From 1985aefc0e502048f92b91beef87c0dfbe669fed Mon Sep 17 00:00:00 2001 From: Matthias Melcher Date: Fri, 7 Mar 2025 16:34:35 +0100 Subject: Restructuring Fluid source files. --- fluid/.gitignore | 2 +- fluid/CMakeLists.txt | 164 +- fluid/CodeEditor.cxx | 316 --- fluid/CodeEditor.h | 105 - fluid/ExternalCodeEditor_UNIX.cxx | 576 ----- fluid/ExternalCodeEditor_UNIX.h | 60 - fluid/ExternalCodeEditor_WIN32.cxx | 632 ----- fluid/ExternalCodeEditor_WIN32.h | 59 - fluid/Fd_Snap_Action.cxx | 1816 -------------- fluid/Fd_Snap_Action.h | 193 -- fluid/Fl_Button_Type.cxx | 226 -- fluid/Fl_Button_Type.h | 46 - fluid/Fl_Function_Type.cxx | 2156 ---------------- fluid/Fl_Function_Type.h | 259 -- fluid/Fl_Grid_Type.cxx | 993 -------- fluid/Fl_Grid_Type.h | 82 - fluid/Fl_Group_Type.cxx | 848 ------- fluid/Fl_Group_Type.h | 242 -- fluid/Fl_Menu_Type.cxx | 922 ------- fluid/Fl_Menu_Type.h | 287 --- fluid/Fl_Type.cxx | 1336 ---------- fluid/Fl_Type.h | 317 --- fluid/Fl_Widget_Type.cxx | 3937 ------------------------------ fluid/Fl_Widget_Type.h | 132 - fluid/Fl_Window_Type.cxx | 1560 ------------ fluid/Fl_Window_Type.h | 157 -- fluid/Fluid_Image.cxx | 412 ---- fluid/Fluid_Image.h | 60 - fluid/StyleParse.cxx | 328 --- fluid/StyleParse.h | 61 - fluid/about_panel.cxx | 2059 ---------------- fluid/about_panel.fl | 76 - fluid/about_panel.h | 32 - fluid/align_widget.cxx | 414 ---- fluid/align_widget.h | 24 - fluid/app/Fd_Snap_Action.cxx | 1816 ++++++++++++++ fluid/app/Fd_Snap_Action.h | 193 ++ fluid/app/Fluid_Image.cxx | 412 ++++ fluid/app/Fluid_Image.h | 60 + fluid/app/align_widget.cxx | 414 ++++ fluid/app/align_widget.h | 24 + fluid/app/fluid.cxx | 2339 ++++++++++++++++++ fluid/app/fluid.h | 208 ++ fluid/app/mergeback.cxx | 493 ++++ fluid/app/mergeback.h | 81 + fluid/app/shell_command.cxx | 1005 ++++++++ fluid/app/shell_command.h | 148 ++ fluid/app/undo.cxx | 263 ++ fluid/app/undo.h | 37 + fluid/autodoc.cxx | 612 ----- fluid/autodoc.h | 59 - fluid/code.cxx | 1107 --------- fluid/code.h | 112 - fluid/codeview_panel.cxx | 550 ----- fluid/codeview_panel.fl | 506 ---- fluid/codeview_panel.h | 58 - fluid/comments.h | 65 - fluid/custom_widgets.cxx | 311 --- fluid/custom_widgets.h | 90 - fluid/documentation/CMakeLists.txt | 2 +- fluid/factory.cxx | 1718 ------------- fluid/factory.h | 34 - fluid/file.cxx | 983 -------- fluid/file.h | 94 - fluid/fluid.cxx | 2340 ------------------ fluid/fluid.h | 204 -- fluid/fluid_filename.cxx | 220 -- fluid/fluid_filename.h | 60 - fluid/function_panel.cxx | 1559 ------------ fluid/function_panel.fl | 1044 -------- fluid/function_panel.h | 116 - fluid/io/code.cxx | 1107 +++++++++ fluid/io/code.h | 112 + fluid/io/file.cxx | 983 ++++++++ fluid/io/file.h | 94 + fluid/main.cxx | 23 + fluid/main.h | 22 + fluid/mergeback.cxx | 493 ---- fluid/mergeback.h | 81 - fluid/nodes/Fl_Button_Type.cxx | 226 ++ fluid/nodes/Fl_Button_Type.h | 46 + fluid/nodes/Fl_Function_Type.cxx | 2156 ++++++++++++++++ fluid/nodes/Fl_Function_Type.h | 259 ++ fluid/nodes/Fl_Grid_Type.cxx | 993 ++++++++ fluid/nodes/Fl_Grid_Type.h | 82 + fluid/nodes/Fl_Group_Type.cxx | 848 +++++++ fluid/nodes/Fl_Group_Type.h | 242 ++ fluid/nodes/Fl_Menu_Type.cxx | 922 +++++++ fluid/nodes/Fl_Menu_Type.h | 287 +++ fluid/nodes/Fl_Type.cxx | 1336 ++++++++++ fluid/nodes/Fl_Type.h | 317 +++ fluid/nodes/Fl_Widget_Type.cxx | 3937 ++++++++++++++++++++++++++++++ fluid/nodes/Fl_Widget_Type.h | 132 + fluid/nodes/Fl_Window_Type.cxx | 1560 ++++++++++++ fluid/nodes/Fl_Window_Type.h | 157 ++ fluid/nodes/factory.cxx | 1718 +++++++++++++ fluid/nodes/factory.h | 34 + fluid/panels/about_panel.cxx | 2059 ++++++++++++++++ fluid/panels/about_panel.fl | 76 + fluid/panels/about_panel.h | 32 + fluid/panels/codeview_panel.cxx | 550 +++++ fluid/panels/codeview_panel.fl | 506 ++++ fluid/panels/codeview_panel.h | 58 + fluid/panels/function_panel.cxx | 1559 ++++++++++++ fluid/panels/function_panel.fl | 1043 ++++++++ fluid/panels/function_panel.h | 116 + fluid/panels/print_panel.cxx | 586 +++++ fluid/panels/print_panel.fl | 358 +++ fluid/panels/print_panel.h | 56 + fluid/panels/settings_panel.cxx | 3551 +++++++++++++++++++++++++++ fluid/panels/settings_panel.fl | 1883 ++++++++++++++ fluid/panels/settings_panel.h | 143 ++ fluid/panels/template_panel.cxx | 340 +++ fluid/panels/template_panel.fl | 297 +++ fluid/panels/template_panel.h | 41 + fluid/panels/widget_panel.cxx | 2497 +++++++++++++++++++ fluid/panels/widget_panel.fl | 1872 ++++++++++++++ fluid/panels/widget_panel.h | 225 ++ fluid/pixmaps.cxx | 226 -- fluid/pixmaps.h | 32 - fluid/print_panel.cxx | 586 ----- fluid/print_panel.fl | 358 --- fluid/print_panel.h | 56 - fluid/rsrcs/comments.h | 65 + fluid/rsrcs/pixmaps.cxx | 226 ++ fluid/rsrcs/pixmaps.h | 32 + fluid/settings_panel.cxx | 3551 --------------------------- fluid/settings_panel.fl | 1883 -------------- fluid/settings_panel.h | 143 -- fluid/shell_command.cxx | 1005 -------- fluid/shell_command.h | 148 -- fluid/template_panel.cxx | 340 --- fluid/template_panel.fl | 298 --- fluid/template_panel.h | 41 - fluid/templates/FLTK_License.fl | 2 +- fluid/tools/ExternalCodeEditor_UNIX.cxx | 576 +++++ fluid/tools/ExternalCodeEditor_UNIX.h | 60 + fluid/tools/ExternalCodeEditor_WIN32.cxx | 632 +++++ fluid/tools/ExternalCodeEditor_WIN32.h | 59 + fluid/tools/autodoc.cxx | 613 +++++ fluid/tools/autodoc.h | 59 + fluid/tools/fluid_filename.cxx | 219 ++ fluid/tools/fluid_filename.h | 59 + fluid/undo.cxx | 263 -- fluid/undo.h | 37 - fluid/widget_browser.cxx | 669 ----- fluid/widget_browser.h | 84 - fluid/widget_panel.cxx | 2497 ------------------- fluid/widget_panel.fl | 1872 -------------- fluid/widget_panel.h | 225 -- fluid/widgets/CodeEditor.cxx | 316 +++ fluid/widgets/CodeEditor.h | 105 + fluid/widgets/StyleParse.cxx | 328 +++ fluid/widgets/StyleParse.h | 61 + fluid/widgets/custom_widgets.cxx | 311 +++ fluid/widgets/custom_widgets.h | 90 + fluid/widgets/widget_browser.cxx | 669 +++++ fluid/widgets/widget_browser.h | 84 + 158 files changed, 47590 insertions(+), 47531 deletions(-) delete mode 100644 fluid/CodeEditor.cxx delete mode 100644 fluid/CodeEditor.h delete mode 100644 fluid/ExternalCodeEditor_UNIX.cxx delete mode 100644 fluid/ExternalCodeEditor_UNIX.h delete mode 100644 fluid/ExternalCodeEditor_WIN32.cxx delete mode 100644 fluid/ExternalCodeEditor_WIN32.h delete mode 100644 fluid/Fd_Snap_Action.cxx delete mode 100644 fluid/Fd_Snap_Action.h delete mode 100644 fluid/Fl_Button_Type.cxx delete mode 100644 fluid/Fl_Button_Type.h delete mode 100644 fluid/Fl_Function_Type.cxx delete mode 100644 fluid/Fl_Function_Type.h delete mode 100644 fluid/Fl_Grid_Type.cxx delete mode 100644 fluid/Fl_Grid_Type.h delete mode 100644 fluid/Fl_Group_Type.cxx delete mode 100644 fluid/Fl_Group_Type.h delete mode 100644 fluid/Fl_Menu_Type.cxx delete mode 100644 fluid/Fl_Menu_Type.h delete mode 100644 fluid/Fl_Type.cxx delete mode 100644 fluid/Fl_Type.h delete mode 100644 fluid/Fl_Widget_Type.cxx delete mode 100644 fluid/Fl_Widget_Type.h delete mode 100644 fluid/Fl_Window_Type.cxx delete mode 100644 fluid/Fl_Window_Type.h delete mode 100644 fluid/Fluid_Image.cxx delete mode 100644 fluid/Fluid_Image.h delete mode 100644 fluid/StyleParse.cxx delete mode 100644 fluid/StyleParse.h delete mode 100644 fluid/about_panel.cxx delete mode 100644 fluid/about_panel.fl delete mode 100644 fluid/about_panel.h delete mode 100644 fluid/align_widget.cxx delete mode 100644 fluid/align_widget.h create mode 100644 fluid/app/Fd_Snap_Action.cxx create mode 100644 fluid/app/Fd_Snap_Action.h create mode 100644 fluid/app/Fluid_Image.cxx create mode 100644 fluid/app/Fluid_Image.h create mode 100644 fluid/app/align_widget.cxx create mode 100644 fluid/app/align_widget.h create mode 100644 fluid/app/fluid.cxx create mode 100644 fluid/app/fluid.h create mode 100644 fluid/app/mergeback.cxx create mode 100644 fluid/app/mergeback.h create mode 100644 fluid/app/shell_command.cxx create mode 100644 fluid/app/shell_command.h create mode 100644 fluid/app/undo.cxx create mode 100644 fluid/app/undo.h delete mode 100644 fluid/autodoc.cxx delete mode 100644 fluid/autodoc.h delete mode 100644 fluid/code.cxx delete mode 100644 fluid/code.h delete mode 100644 fluid/codeview_panel.cxx delete mode 100644 fluid/codeview_panel.fl delete mode 100644 fluid/codeview_panel.h delete mode 100644 fluid/comments.h delete mode 100644 fluid/custom_widgets.cxx delete mode 100644 fluid/custom_widgets.h delete mode 100644 fluid/factory.cxx delete mode 100644 fluid/factory.h delete mode 100644 fluid/file.cxx delete mode 100644 fluid/file.h delete mode 100644 fluid/fluid.cxx delete mode 100644 fluid/fluid.h delete mode 100644 fluid/fluid_filename.cxx delete mode 100644 fluid/fluid_filename.h delete mode 100644 fluid/function_panel.cxx delete mode 100644 fluid/function_panel.fl delete mode 100644 fluid/function_panel.h create mode 100644 fluid/io/code.cxx create mode 100644 fluid/io/code.h create mode 100644 fluid/io/file.cxx create mode 100644 fluid/io/file.h create mode 100644 fluid/main.cxx create mode 100644 fluid/main.h delete mode 100644 fluid/mergeback.cxx delete mode 100644 fluid/mergeback.h create mode 100644 fluid/nodes/Fl_Button_Type.cxx create mode 100644 fluid/nodes/Fl_Button_Type.h create mode 100644 fluid/nodes/Fl_Function_Type.cxx create mode 100644 fluid/nodes/Fl_Function_Type.h create mode 100644 fluid/nodes/Fl_Grid_Type.cxx create mode 100644 fluid/nodes/Fl_Grid_Type.h create mode 100644 fluid/nodes/Fl_Group_Type.cxx create mode 100644 fluid/nodes/Fl_Group_Type.h create mode 100644 fluid/nodes/Fl_Menu_Type.cxx create mode 100644 fluid/nodes/Fl_Menu_Type.h create mode 100644 fluid/nodes/Fl_Type.cxx create mode 100644 fluid/nodes/Fl_Type.h create mode 100644 fluid/nodes/Fl_Widget_Type.cxx create mode 100644 fluid/nodes/Fl_Widget_Type.h create mode 100644 fluid/nodes/Fl_Window_Type.cxx create mode 100644 fluid/nodes/Fl_Window_Type.h create mode 100644 fluid/nodes/factory.cxx create mode 100644 fluid/nodes/factory.h create mode 100644 fluid/panels/about_panel.cxx create mode 100644 fluid/panels/about_panel.fl create mode 100644 fluid/panels/about_panel.h create mode 100644 fluid/panels/codeview_panel.cxx create mode 100644 fluid/panels/codeview_panel.fl create mode 100644 fluid/panels/codeview_panel.h create mode 100644 fluid/panels/function_panel.cxx create mode 100644 fluid/panels/function_panel.fl create mode 100644 fluid/panels/function_panel.h create mode 100644 fluid/panels/print_panel.cxx create mode 100644 fluid/panels/print_panel.fl create mode 100644 fluid/panels/print_panel.h create mode 100644 fluid/panels/settings_panel.cxx create mode 100644 fluid/panels/settings_panel.fl create mode 100644 fluid/panels/settings_panel.h create mode 100644 fluid/panels/template_panel.cxx create mode 100644 fluid/panels/template_panel.fl create mode 100644 fluid/panels/template_panel.h create mode 100644 fluid/panels/widget_panel.cxx create mode 100644 fluid/panels/widget_panel.fl create mode 100644 fluid/panels/widget_panel.h delete mode 100644 fluid/pixmaps.cxx delete mode 100644 fluid/pixmaps.h delete mode 100644 fluid/print_panel.cxx delete mode 100644 fluid/print_panel.fl delete mode 100644 fluid/print_panel.h create mode 100644 fluid/rsrcs/comments.h create mode 100644 fluid/rsrcs/pixmaps.cxx create mode 100644 fluid/rsrcs/pixmaps.h delete mode 100644 fluid/settings_panel.cxx delete mode 100644 fluid/settings_panel.fl delete mode 100644 fluid/settings_panel.h delete mode 100644 fluid/shell_command.cxx delete mode 100644 fluid/shell_command.h delete mode 100644 fluid/template_panel.cxx delete mode 100644 fluid/template_panel.fl delete mode 100644 fluid/template_panel.h create mode 100644 fluid/tools/ExternalCodeEditor_UNIX.cxx create mode 100644 fluid/tools/ExternalCodeEditor_UNIX.h create mode 100644 fluid/tools/ExternalCodeEditor_WIN32.cxx create mode 100644 fluid/tools/ExternalCodeEditor_WIN32.h create mode 100644 fluid/tools/autodoc.cxx create mode 100644 fluid/tools/autodoc.h create mode 100644 fluid/tools/fluid_filename.cxx create mode 100644 fluid/tools/fluid_filename.h delete mode 100644 fluid/undo.cxx delete mode 100644 fluid/undo.h delete mode 100644 fluid/widget_browser.cxx delete mode 100644 fluid/widget_browser.h delete mode 100644 fluid/widget_panel.cxx delete mode 100644 fluid/widget_panel.fl delete mode 100644 fluid/widget_panel.h create mode 100644 fluid/widgets/CodeEditor.cxx create mode 100644 fluid/widgets/CodeEditor.h create mode 100644 fluid/widgets/StyleParse.cxx create mode 100644 fluid/widgets/StyleParse.h create mode 100644 fluid/widgets/custom_widgets.cxx create mode 100644 fluid/widgets/custom_widgets.h create mode 100644 fluid/widgets/widget_browser.cxx create mode 100644 fluid/widgets/widget_browser.h diff --git a/fluid/.gitignore b/fluid/.gitignore index f1c3b079f..023bc907c 100644 --- a/fluid/.gitignore +++ b/fluid/.gitignore @@ -6,7 +6,7 @@ fluid fluid-shared TAGS fluid.app -pixmaps/*.bck +../pixmaps/*.bck # local documentation generation diff --git a/fluid/CMakeLists.txt b/fluid/CMakeLists.txt index b9065616b..c0a398d5f 100644 --- a/fluid/CMakeLists.txt +++ b/fluid/CMakeLists.txt @@ -1,7 +1,7 @@ # # CMakeLists.txt to build fluid for the FLTK project using CMake (www.cmake.org) # -# Copyright 1998-2024 by Bill Spitzak and others. +# 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 @@ -18,96 +18,108 @@ set(TARGETS fluid) # Source files for 'fluid-lib' = all source files except the main files -# (fluid.cxx and fluid.h) -# Note: macOS (Xcode) needs at least one source file (fluid.cxx) to link the main +# (main.cxx and main.h) +# Note: macOS (Xcode) needs at least one source file (main.cxx) to link the main # program fluid properly 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 + app/align_widget.cxx + app/Fd_Snap_Action.cxx + app/fluid.cxx + app/Fluid_Image.cxx + app/mergeback.cxx + app/shell_command.cxx + app/undo.cxx + io/code.cxx + io/file.cxx + nodes/factory.cxx + nodes/Fl_Button_Type.cxx + nodes/Fl_Function_Type.cxx + nodes/Fl_Grid_Type.cxx + nodes/Fl_Group_Type.cxx + nodes/Fl_Menu_Type.cxx + nodes/Fl_Type.cxx + nodes/Fl_Widget_Type.cxx + nodes/Fl_Window_Type.cxx + panels/about_panel.cxx + panels/codeview_panel.cxx + panels/function_panel.cxx + panels/settings_panel.cxx + panels/template_panel.cxx + panels/widget_panel.cxx + rsrcs/pixmaps.cxx + tools/autodoc.cxx + tools/fluid_filename.cxx + widgets/CodeEditor.cxx + widgets/custom_widgets.cxx + widgets/StyleParse.cxx + widgets/widget_browser.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 + app/align_widget.h + app/Fd_Snap_Action.h + app/fluid.h + app/Fluid_Image.h + app/mergeback.h + app/shell_command.h + app/undo.h + io/code.h + io/file.h + nodes/factory.h + nodes/Fl_Button_Type.h + nodes/Fl_Function_Type.h + nodes/Fl_Grid_Type.h + nodes/Fl_Group_Type.h + nodes/Fl_Menu_Type.h + nodes/Fl_Type.h + nodes/Fl_Widget_Type.h + nodes/Fl_Window_Type.h + panels/about_panel.h + panels/codeview_panel.h + panels/function_panel.h + panels/settings_panel.h + panels/template_panel.h + panels/widget_panel.h + rsrcs/comments.h + rsrcs/pixmaps.h + tools/autodoc.h + tools/fluid_filename.h + widgets/CodeEditor.h + widgets/custom_widgets.h + widgets/StyleParse.h + widgets/widget_browser.h ) # Add ExternalCodeEditor: platform specific files if(WIN32) - list(APPEND CPPFILES ExternalCodeEditor_WIN32.cxx) - list(APPEND HEADERFILES ExternalCodeEditor_WIN32.h) + list(APPEND CPPFILES tools/ExternalCodeEditor_WIN32.cxx) + list(APPEND HEADERFILES tools/ExternalCodeEditor_WIN32.h) else() - list(APPEND CPPFILES ExternalCodeEditor_UNIX.cxx) - list(APPEND HEADERFILES ExternalCodeEditor_UNIX.h) + list(APPEND CPPFILES tools/ExternalCodeEditor_UNIX.cxx) + list(APPEND HEADERFILES tools/ExternalCodeEditor_UNIX.h) endif(WIN32) -source_group("Header Files" FILES ${HEADERFILES}) +source_group( + TREE + ${CMAKE_CURRENT_SOURCE_DIR} + FILES + ${CPPFILES} + ${HEADERFILES} + main.cxx + main.h + CMakeLists.txt +) # 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 PRIVATE .) target_link_libraries(fluid-lib PUBLIC fltk::images) # Build targets @@ -117,8 +129,8 @@ if(APPLE AND NOT FLTK_BACKEND_X11) # macOS set(ICON_NAME fluid.icns) - set(ICON_PATH "${CMAKE_CURRENT_SOURCE_DIR}/icons/${ICON_NAME}") - add_executable(fluid MACOSX_BUNDLE fluid.cxx fluid.h ${ICON_PATH}) + set(ICON_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../icons/${ICON_NAME}") + add_executable(fluid MACOSX_BUNDLE main.cxx main.h ${ICON_PATH}) # create macOS bundle wrapper script @@ -135,10 +147,11 @@ if(APPLE AND NOT FLTK_BACKEND_X11) else() # Option 'WIN32' builds a Windows GUI program, ignored on other platforms - add_executable(fluid WIN32 fluid.cxx fluid.h) + add_executable(fluid WIN32 main.cxx main.h) endif() +target_include_directories(fluid PRIVATE .) target_link_libraries(fluid PRIVATE fluid-lib) # Build the console app on Windows @@ -146,7 +159,8 @@ target_link_libraries(fluid PRIVATE fluid-lib) if(WIN32) list(APPEND TARGETS fluid-cmd) - add_executable(fluid-cmd fluid.cxx fluid.h) + add_executable(fluid-cmd main.cxx main.h) + target_include_directories(fluid-cmd PRIVATE .) target_link_libraries(fluid-cmd PRIVATE fluid-lib) set(FLTK_FLUID_EXECUTABLE fltk::fluid-cmd) else() @@ -207,8 +221,8 @@ if(UNIX) # Install desktop icons foreach(icon 32 48 64 128) - install(FILES icons/fluid-${icon}.png - DESTINATION ${FLTK_DATADIR}/icons/hicolor/${icon}x${icon}/apps + install(FILES ../icons/fluid-${icon}.png + DESTINATION ${FLTK_DATADIR}/../icons/hicolor/${icon}x${icon}/apps RENAME fluid.png ) endforeach() diff --git a/fluid/CodeEditor.cxx b/fluid/CodeEditor.cxx deleted file mode 100644 index 2fffcd8bc..000000000 --- a/fluid/CodeEditor.cxx +++ /dev/null @@ -1,316 +0,0 @@ -// -// 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); -} - - diff --git a/fluid/CodeEditor.h b/fluid/CodeEditor.h deleted file mode 100644 index 9cfa50abe..000000000 --- a/fluid/CodeEditor.h +++ /dev/null @@ -1,105 +0,0 @@ -// -// 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 diff --git a/fluid/ExternalCodeEditor_UNIX.cxx b/fluid/ExternalCodeEditor_UNIX.cxx deleted file mode 100644 index 4f0bea3f9..000000000 --- a/fluid/ExternalCodeEditor_UNIX.cxx +++ /dev/null @@ -1,576 +0,0 @@ -// -// 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); - } - } -} diff --git a/fluid/ExternalCodeEditor_UNIX.h b/fluid/ExternalCodeEditor_UNIX.h deleted file mode 100644 index 9d49cf617..000000000 --- a/fluid/ExternalCodeEditor_UNIX.h +++ /dev/null @@ -1,60 +0,0 @@ -// -// 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 - -#include "fluid.h" - -#include /* errno */ -#include /* strerror() */ -#include /* stat().. */ -#include -#include - -// ---- 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_; - std::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 */ diff --git a/fluid/ExternalCodeEditor_WIN32.cxx b/fluid/ExternalCodeEditor_WIN32.cxx deleted file mode 100644 index bb7d5791a..000000000 --- a/fluid/ExternalCodeEditor_WIN32.cxx +++ /dev/null @@ -1,632 +0,0 @@ -// -// 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; -} diff --git a/fluid/ExternalCodeEditor_WIN32.h b/fluid/ExternalCodeEditor_WIN32.h deleted file mode 100644 index de4c2c4a7..000000000 --- a/fluid/ExternalCodeEditor_WIN32.h +++ /dev/null @@ -1,59 +0,0 @@ -// -// 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 */ diff --git a/fluid/Fd_Snap_Action.cxx b/fluid/Fd_Snap_Action.cxx deleted file mode 100644 index 1e9fee1a3..000000000 --- a/fluid/Fd_Snap_Action.cxx +++ /dev/null @@ -1,1816 +0,0 @@ -// -// 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 "file.h" - -#include -#include -#include -#include -#include -#include - -// 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() { - std::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; iwrite_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; iwrite_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, "{")) { - std::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(std::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; ichildren(); 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); - } - } - } -} diff --git a/fluid/Fd_Snap_Action.h b/fluid/Fd_Snap_Action.h deleted file mode 100644 index a7485c770..000000000 --- a/fluid/Fd_Snap_Action.h +++ /dev/null @@ -1,193 +0,0 @@ -// -// 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 - -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_; - std::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(std::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 std::string &filename); - int save(const std::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 diff --git a/fluid/Fl_Button_Type.cxx b/fluid/Fl_Button_Type.cxx deleted file mode 100644 index ee12c731a..000000000 --- a/fluid/Fl_Button_Type.cxx +++ /dev/null @@ -1,226 +0,0 @@ -// -// 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; - diff --git a/fluid/Fl_Button_Type.h b/fluid/Fl_Button_Type.h deleted file mode 100644 index 3eb4a3d1d..000000000 --- a/fluid/Fl_Button_Type.h +++ /dev/null @@ -1,46 +0,0 @@ -// -// 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 diff --git a/fluid/Fl_Function_Type.cxx b/fluid/Fl_Function_Type.cxx deleted file mode 100644 index 935cd6405..000000000 --- a/fluid/Fl_Function_Type.cxx +++ /dev/null @@ -1,2156 +0,0 @@ -// -// 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; -} diff --git a/fluid/Fl_Function_Type.h b/fluid/Fl_Function_Type.h deleted file mode 100644 index 91a0e521a..000000000 --- a/fluid/Fl_Function_Type.h +++ /dev/null @@ -1,259 +0,0 @@ -// -// 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 diff --git a/fluid/Fl_Grid_Type.cxx b/fluid/Fl_Grid_Type.cxx deleted file mode 100644 index 45110a880..000000000 --- a/fluid/Fl_Grid_Type.cxx +++ /dev/null @@ -1,993 +0,0 @@ -// -// 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); - } - } - } -} - diff --git a/fluid/Fl_Grid_Type.h b/fluid/Fl_Grid_Type.h deleted file mode 100644 index 2098cf783..000000000 --- a/fluid/Fl_Grid_Type.h +++ /dev/null @@ -1,82 +0,0 @@ -// -// 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 diff --git a/fluid/Fl_Group_Type.cxx b/fluid/Fl_Group_Type.cxx deleted file mode 100644 index d3ec98fce..000000000 --- a/fluid/Fl_Group_Type.cxx +++ /dev/null @@ -1,848 +0,0 @@ -// -// 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(); -} - diff --git a/fluid/Fl_Group_Type.h b/fluid/Fl_Group_Type.h deleted file mode 100644 index 1f7bc2747..000000000 --- a/fluid/Fl_Group_Type.h +++ /dev/null @@ -1,242 +0,0 @@ -// -// 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 diff --git a/fluid/Fl_Menu_Type.cxx b/fluid/Fl_Menu_Type.cxx deleted file mode 100644 index 35670766b..000000000 --- a/fluid/Fl_Menu_Type.cxx +++ /dev/null @@ -1,922 +0,0 @@ -// -// 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); - } -} diff --git a/fluid/Fl_Menu_Type.h b/fluid/Fl_Menu_Type.h deleted file mode 100644 index 41bddced6..000000000 --- a/fluid/Fl_Menu_Type.h +++ /dev/null @@ -1,287 +0,0 @@ -// -// 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 diff --git a/fluid/Fl_Type.cxx b/fluid/Fl_Type.cxx deleted file mode 100644 index 444047cd8..000000000 --- a/fluid/Fl_Type.cxx +++ /dev/null @@ -1,1336 +0,0 @@ -// -// 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 -#include -#include -#include "../src/flstring.h" - -#include -#include - -// ---- 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; -} - -/// \} - diff --git a/fluid/Fl_Type.h b/fluid/Fl_Type.h deleted file mode 100644 index 50f4b34b1..000000000 --- a/fluid/Fl_Type.h +++ /dev/null @@ -1,317 +0,0 @@ -// -// 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 diff --git a/fluid/Fl_Widget_Type.cxx b/fluid/Fl_Widget_Type.cxx deleted file mode 100644 index b92ef53cc..000000000 --- a/fluid/Fl_Widget_Type.cxx +++ /dev/null @@ -1,3937 +0,0 @@ -// -// 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(); -} - diff --git a/fluid/Fl_Widget_Type.h b/fluid/Fl_Widget_Type.h deleted file mode 100644 index 40470c544..000000000 --- a/fluid/Fl_Widget_Type.h +++ /dev/null @@ -1,132 +0,0 @@ -// -// 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 diff --git a/fluid/Fl_Window_Type.cxx b/fluid/Fl_Window_Type.cxx deleted file mode 100644 index de58fb762..000000000 --- a/fluid/Fl_Window_Type.cxx +++ /dev/null @@ -1,1560 +0,0 @@ -// -// 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(); -} diff --git a/fluid/Fl_Window_Type.h b/fluid/Fl_Window_Type.h deleted file mode 100644 index 3b9a03e62..000000000 --- a/fluid/Fl_Window_Type.h +++ /dev/null @@ -1,157 +0,0 @@ -// -// 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 diff --git a/fluid/Fluid_Image.cxx b/fluid/Fluid_Image.cxx deleted file mode 100644 index c57d54c85..000000000 --- a/fluid/Fluid_Image.cxx +++ /dev/null @@ -1,412 +0,0 @@ -// -// 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; -} diff --git a/fluid/Fluid_Image.h b/fluid/Fluid_Image.h deleted file mode 100644 index 73387ffd4..000000000 --- a/fluid/Fluid_Image.h +++ /dev/null @@ -1,60 +0,0 @@ -// -// 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 diff --git a/fluid/StyleParse.cxx b/fluid/StyleParse.cxx deleted file mode 100644 index b8b8ff4f0..000000000 --- a/fluid/StyleParse.cxx +++ /dev/null @@ -1,328 +0,0 @@ -// -// 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(); -} diff --git a/fluid/StyleParse.h b/fluid/StyleParse.h deleted file mode 100644 index 2fcc4f4db..000000000 --- a/fluid/StyleParse.h +++ /dev/null @@ -1,61 +0,0 @@ -// -// 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 diff --git a/fluid/about_panel.cxx b/fluid/about_panel.cxx deleted file mode 100644 index b28347ae5..000000000 --- a/fluid/about_panel.cxx +++ /dev/null @@ -1,2059 +0,0 @@ -// -// 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.0500 - -#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}; diff --git a/fluid/about_panel.fl b/fluid/about_panel.fl deleted file mode 100644 index 6ef5bdbd0..000000000 --- a/fluid/about_panel.fl +++ /dev/null @@ -1,76 +0,0 @@ -# data file for the Fltk User Interface Designer (fluid) -version 1.0500 -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} -} diff --git a/fluid/about_panel.h b/fluid/about_panel.h deleted file mode 100644 index 0130a1e44..000000000 --- a/fluid/about_panel.h +++ /dev/null @@ -1,32 +0,0 @@ -// -// 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.0500 - -#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 diff --git a/fluid/align_widget.cxx b/fluid/align_widget.cxx deleted file mode 100644 index a1018e2ca..000000000 --- a/fluid/align_widget.cxx +++ /dev/null @@ -1,414 +0,0 @@ -// -// 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); -} diff --git a/fluid/align_widget.h b/fluid/align_widget.h deleted file mode 100644 index f04372215..000000000 --- a/fluid/align_widget.h +++ /dev/null @@ -1,24 +0,0 @@ -// -// 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 diff --git a/fluid/app/Fd_Snap_Action.cxx b/fluid/app/Fd_Snap_Action.cxx new file mode 100644 index 000000000..c093af1ff --- /dev/null +++ b/fluid/app/Fd_Snap_Action.cxx @@ -0,0 +1,1816 @@ +// +// 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 "app/Fd_Snap_Action.h" + +#include "io/file.h" +#include "nodes/Fl_Group_Type.h" +#include "panels/settings_panel.h" + +#include +#include +#include +#include +#include +#include + +// 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() { + std::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; iwrite_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; iwrite_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, "{")) { + std::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(std::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; ichildren(); 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); + } + } + } +} diff --git a/fluid/app/Fd_Snap_Action.h b/fluid/app/Fd_Snap_Action.h new file mode 100644 index 000000000..50b520319 --- /dev/null +++ b/fluid/app/Fd_Snap_Action.h @@ -0,0 +1,193 @@ +// +// 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 "app/fluid.h" +#include "nodes/Fl_Window_Type.h" + +#include + +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_; + std::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(std::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 std::string &filename); + int save(const std::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 diff --git a/fluid/app/Fluid_Image.cxx b/fluid/app/Fluid_Image.cxx new file mode 100644 index 000000000..d25f17023 --- /dev/null +++ b/fluid/app/Fluid_Image.cxx @@ -0,0 +1,412 @@ +// +// 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 "app/Fluid_Image.h" + +#include "app/fluid.h" +#include "io/file.h" +#include "io/code.h" +#include "nodes/Fl_Group_Type.h" +#include "nodes/Fl_Window_Type.h" +#include "tools/fluid_filename.h" + +#include +#include +#include +#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; +} diff --git a/fluid/app/Fluid_Image.h b/fluid/app/Fluid_Image.h new file mode 100644 index 000000000..e3b5faaac --- /dev/null +++ b/fluid/app/Fluid_Image.h @@ -0,0 +1,60 @@ +// +// 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 "io/code.h" + +#include + +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 diff --git a/fluid/app/align_widget.cxx b/fluid/app/align_widget.cxx new file mode 100644 index 000000000..a9badf9e4 --- /dev/null +++ b/fluid/app/align_widget.cxx @@ -0,0 +1,414 @@ +// +// 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 "app/align_widget.h" + +#include "app/fluid.h" +#include "app/undo.h" +#include "nodes/Fl_Group_Type.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); +} diff --git a/fluid/app/align_widget.h b/fluid/app/align_widget.h new file mode 100644 index 000000000..f04372215 --- /dev/null +++ b/fluid/app/align_widget.h @@ -0,0 +1,24 @@ +// +// 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 diff --git a/fluid/app/fluid.cxx b/fluid/app/fluid.cxx new file mode 100644 index 000000000..e9d473fb2 --- /dev/null +++ b/fluid/app/fluid.cxx @@ -0,0 +1,2339 @@ +// +// FLUID main entry 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 "app/fluid.h" + +#include "app/mergeback.h" +#include "app/undo.h" +#include "io/file.h" +#include "io/code.h" +#include "nodes/Fl_Type.h" +#include "nodes/Fl_Function_Type.h" +#include "nodes/Fl_Group_Type.h" +#include "nodes/Fl_Window_Type.h" +#include "nodes/factory.h" +#include "panels/settings_panel.h" +#include "panels/function_panel.h" +#include "panels/codeview_panel.h" +#include "panels/template_panel.h" +#include "panels/about_panel.h" +#include "rsrcs/pixmaps.h" +#include "app/shell_command.h" +#include "tools/autodoc.h" +#include "widgets/widget_browser.h" + +#include +#ifdef __APPLE__ +#include // for fl_open_callback +#endif +#include +#include +#include +#include +#include +#include +#include // setlocale().. +#include "../src/flstring.h" + +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 +} + +/// \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 std::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 +std::string g_code_filename_arg; + +/// command line arguments that overrides the generate header file extension or name +std::string g_header_filename_arg; + +/// current directory path at application launch +std::string g_launch_path; + +/// if set, generate images for automatic documentation in this directory +std::string g_autodoc_path; + +/// path to store temporary files during app run +/// \see tmpdir_create_called +std::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 = ""; + i18n_gnu_conditional = ""; + i18n_gnu_function = "gettext"; + i18n_gnu_static_function = "gettext_noop"; + + i18n_pos_include = ""; + 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 std::string end_with_slash(const std::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\\AppData\Local\Temp + fl_snprintf(buf, sizeof(buf)-1, "fluid-%d/", (long)GetCurrentProcessId()); + std::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; + } + std::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()); + std::string name = buf; + std::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 = std::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 = std::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; id_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 std::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 + std::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)) { + std::string basename = fl_filename_name(std::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 + */ +std::string open_project_filechooser(const std::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) { + std::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 std::string(); + return std::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 std::string &filename_arg) { + bool is_a_merge = (Fl_Type::first != NULL); + std::string title = is_a_merge ? "Merge Project File" : "Open Project File"; + + // ask for a filename if none was given + std::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 std::string &filename_arg) { + // verify user intention + if (confirm_project_clear() == false) + return false; + + // ask for a filename if none was given + std::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(std::string(c)); +} +#endif // __APPLE__ + +/** + Get the absolute path of the project file, for example `/Users/matt/dev/`. + \return the path ending in '/' + */ +std::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 + */ +std::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 '/' + */ +std::string Fluid_Project::codefile_path() const { + std::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 + */ +std::string Fluid_Project::codefile_name() const { + std::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 '/' + */ +std::string Fluid_Project::headerfile_path() const { + std::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 + */ +std::string Fluid_Project::headerfile_name() const { + std::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 '/' + */ +std::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 + */ +std::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 + */ +std::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; + std::string code_filename = g_project.codefile_path() + g_project.codefile_name(); + std::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()); + std::string code_filename_rel = fl_filename_relative(code_filename); + std::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; + } + + std::string proj_filename = g_project.projectfile_path() + g_project.projectfile_name(); + std::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; ivalue()) { + 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 + ( + "\n" + "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... + std::string basename = fl_filename_name(std::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(std::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... + std::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])); + std::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) { + std::string basename; + if (!filename) basename = "Untitled.fl"; + else basename = fl_filename_name(std::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 fluid_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); +} + +/// \} + diff --git a/fluid/app/fluid.h b/fluid/app/fluid.h new file mode 100644 index 000000000..d02ae79cc --- /dev/null +++ b/fluid/app/fluid.h @@ -0,0 +1,208 @@ +// +// FLUID main entry 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 +// + +#ifndef _FLUID_FLUID_H +#define _FLUID_FLUID_H + +#include "tools/fluid_filename.h" + +#include +#include + +#include + +#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 std::string g_code_filename_arg; +extern std::string g_header_filename_arg; +extern std::string g_launch_path; + +extern std::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(); + + std::string projectfile_path() const; + std::string projectfile_name() const; + std::string codefile_path() const; + std::string codefile_name() const; + std::string headerfile_path() const; + std::string headerfile_name() const; + std::string stringsfile_path() const; + std::string stringsfile_name() const; + std::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. + std::string i18n_gnu_include; + // Optional name of a macro for conditional i18n compilation. + std::string i18n_gnu_conditional; + /// For the gettext/intl.h options, this is the function that translates text + /// at runtime. This is usually "gettext" or "_". + std::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_". + std::string i18n_gnu_static_function; + + /// Include file for Posix i18n, write a #include statement into the source + /// file. This is usually `` for Posix catgets. + std::string i18n_pos_include; + // Optional name of a macro for conditional i18n compilation. + std::string i18n_pos_conditional; + /// Name of the nl_catd database + std::string i18n_pos_file; + /// Message set ID for the catalog. + std::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. + std::string header_file_name; + /// Hold the default extension for source code files, or the entire filename if set via command line. + std::string code_file_name; +}; + +extern Fluid_Project g_project; + +// ---- public functions + +extern int fluid_main(int argc,char **argv); + +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 std::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 + diff --git a/fluid/app/mergeback.cxx b/fluid/app/mergeback.cxx new file mode 100644 index 000000000..f914f6e1e --- /dev/null +++ b/fluid/app/mergeback.cxx @@ -0,0 +1,493 @@ +// +// 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 "app/mergeback.h" + +#include "app/fluid.h" +#include "app/undo.h" +#include "io/code.h" +#include "nodes/Fl_Function_Type.h" +#include "nodes/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 std::string &s, const std::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 + */ +std::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); + std::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 std::string &code_filename, const std::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; + } + std::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()) { + std::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)) { + std::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()) { + std::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)) { + std::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 std::string &s, int task). + */ +int Fd_Mergeback::merge_back(const std::string &s, const std::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 + diff --git a/fluid/app/mergeback.h b/fluid/app/mergeback.h new file mode 100644 index 000000000..f828e9669 --- /dev/null +++ b/fluid/app/mergeback.h @@ -0,0 +1,81 @@ +// +// 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 +#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 std::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); + std::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 std::string &s, const std::string &p, int task); + int ask_user_to_merge(const std::string &s, const std::string &p); + int analyse(); + int apply(); +}; + +extern int merge_back(const std::string &s, const std::string &p, int task); + + +#endif // _FLUID_MERGEBACK_H + +#endif diff --git a/fluid/app/shell_command.cxx b/fluid/app/shell_command.cxx new file mode 100644 index 000000000..df71a00f5 --- /dev/null +++ b/fluid/app/shell_command.cxx @@ -0,0 +1,1005 @@ +// +// 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 std::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, std::string &value, const std::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 std::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(std::string &cmd, const std::string ¯o, const std::string &content) { + for (int i=0;;) { + i = (int)cmd.find(macro, i); + if (i==(int)std::string::npos) break; + cmd.replace(i, macro.size(), content); + } +} + +static void expand_macros(std::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@") != std::string::npos) { +// find_fltk_config(); +// expand_macro(cmd, "@FLTK_CONFIG@", fltk_config_cmd.c_str()); +// } + if (cmd.find("@TMPDIR@") != std::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 std::string &cmd, int flags) { + if (cmd.empty()) { + fl_alert("No shell command entered!"); + return; + } + + if (!prepare_shell_command(flags)) return; + + std::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 std::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 std::string &in_name, + const std::string &in_label, + Fl_Shortcut in_shortcut, + Fd_Tool_Store in_storage, + int in_condition, + const std::string &in_condition_data, + const std::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; + diff --git a/fluid/app/shell_command.h b/fluid/app/shell_command.h new file mode 100644 index 000000000..b45e2f8cc --- /dev/null +++ b/fluid/app/shell_command.h @@ -0,0 +1,148 @@ +// +// 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 "app/fluid.h" + +#include + +#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, std::string &value, const std::string &defaultValue); +char preferences_set(Fl_Preferences &prefs, const char *key, const std::string &value); + +void show_terminal_window(); +void run_shell_command(const std::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 std::string &in_name); + Fd_Shell_Command(const std::string &in_name, + const std::string &in_label, + Fl_Shortcut in_shortcut, + Fd_Tool_Store in_storage, + int in_condition, + const std::string &in_condition_data, + const std::string &in_command, + int in_flags); + std::string name; + std::string label; + Fl_Shortcut shortcut; + Fd_Tool_Store storage; + int condition; // always, hide, windows only, linux only, mac only, user, machine + std::string condition_data; // user name, machine name + std::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 std::string &filename); +// int save(const std::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 diff --git a/fluid/app/undo.cxx b/fluid/app/undo.cxx new file mode 100644 index 000000000..eb5001468 --- /dev/null +++ b/fluid/app/undo.cxx @@ -0,0 +1,263 @@ +// +// FLUID undo 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 "app/undo.h" + +#include "app/fluid.h" +#include "io/file.h" +#include "nodes/Fl_Type.h" +#include "nodes/Fl_Widget_Type.h" +#include "widgets/widget_browser.h" + +#include +#include +#include +#include +#include +#include "tools/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++; +} diff --git a/fluid/app/undo.h b/fluid/app/undo.h new file mode 100644 index 000000000..e8ffab891 --- /dev/null +++ b/fluid/app/undo.h @@ -0,0 +1,37 @@ +// +// FLUID undo definitions 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 +// + +#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 diff --git a/fluid/autodoc.cxx b/fluid/autodoc.cxx deleted file mode 100644 index a6c7f2fc5..000000000 --- a/fluid/autodoc.cxx +++ /dev/null @@ -1,612 +0,0 @@ -// -// 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 std::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 diff --git a/fluid/autodoc.h b/fluid/autodoc.h deleted file mode 100644 index 51f9739ea..000000000 --- a/fluid/autodoc.h +++ /dev/null @@ -1,59 +0,0 @@ -// -// 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 -#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 std::string &target_dir); - -#endif - diff --git a/fluid/code.cxx b/fluid/code.cxx deleted file mode 100644 index 3c789abd3..000000000 --- a/fluid/code.cxx +++ /dev/null @@ -1,1107 +0,0 @@ -// -// 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 std::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) { - std::string proj_filename = g_project.projectfile_path() + g_project.projectfile_name(); - int i, n = (int)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()); - } - } - std::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); -} - -/// \} - diff --git a/fluid/code.h b/fluid/code.h deleted file mode 100644 index 758e7bf45..000000000 --- a/fluid/code.h +++ /dev/null @@ -1,112 +0,0 @@ -// -// 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 - -#include -#include -#include - -class Fl_Type; -struct Fd_Identifier_Tree; -struct Fd_Text_Tree; -struct Fd_Pointer_Tree; - -int is_id(char c); -int write_strings(const std::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 diff --git a/fluid/codeview_panel.cxx b/fluid/codeview_panel.cxx deleted file mode 100644 index 78674a7d8..000000000 --- a/fluid/codeview_panel.cxx +++ /dev/null @@ -1,550 +0,0 @@ -// -// 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.0500 - -#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()) { - std::string code_file_name_bak = g_project.code_file_name; - g_project.code_file_name = cv_source_filename; - std::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; -} - -// diff --git a/fluid/codeview_panel.fl b/fluid/codeview_panel.fl deleted file mode 100644 index 5417ad9c7..000000000 --- a/fluid/codeview_panel.fl +++ /dev/null @@ -1,506 +0,0 @@ -# data file for the Fltk User Interface Designer (fluid) -version 1.0500 -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()) { - std::string code_file_name_bak = g_project.code_file_name; - g_project.code_file_name = cv_source_filename; - std::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 -} diff --git a/fluid/codeview_panel.h b/fluid/codeview_panel.h deleted file mode 100644 index 34efd22af..000000000 --- a/fluid/codeview_panel.h +++ /dev/null @@ -1,58 +0,0 @@ -// -// 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.0500 - -#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 - -// diff --git a/fluid/comments.h b/fluid/comments.h deleted file mode 100644 index 85f3376b8..000000000 --- a/fluid/comments.h +++ /dev/null @@ -1,65 +0,0 @@ - -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 .\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 .\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" - }; diff --git a/fluid/custom_widgets.cxx b/fluid/custom_widgets.cxx deleted file mode 100644 index b50169f3a..000000000 --- a/fluid/custom_widgets.cxx +++ /dev/null @@ -1,311 +0,0 @@ -// -// 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); -} diff --git a/fluid/custom_widgets.h b/fluid/custom_widgets.h deleted file mode 100644 index 875496b8e..000000000 --- a/fluid/custom_widgets.h +++ /dev/null @@ -1,90 +0,0 @@ -// -// 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 diff --git a/fluid/documentation/CMakeLists.txt b/fluid/documentation/CMakeLists.txt index fccdeac97..b613acee5 100644 --- a/fluid/documentation/CMakeLists.txt +++ b/fluid/documentation/CMakeLists.txt @@ -1,7 +1,7 @@ # # CMakeLists.txt to build docs for the FLTK project using CMake (www.cmake.org) # -# Copyright 1998-2024 by Bill Spitzak and others. +# 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 diff --git a/fluid/factory.cxx b/fluid/factory.cxx deleted file mode 100644 index a96a1ec45..000000000 --- a/fluid/factory.cxx +++ /dev/null @@ -1,1718 +0,0 @@ -// -// 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; -} diff --git a/fluid/factory.h b/fluid/factory.h deleted file mode 100644 index 7f3ca6dfa..000000000 --- a/fluid/factory.h +++ /dev/null @@ -1,34 +0,0 @@ -// -// 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 diff --git a/fluid/file.cxx b/fluid/file.cxx deleted file mode 100644 index 9f5b78c39..000000000 --- a/fluid/file.cxx +++ /dev/null @@ -1,983 +0,0 @@ -// -// 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 -#include -#include -#include -#include "../src/flstring.h" - -#include -#include -#include - -/// \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(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()) { // - ((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; -} - -/// \} diff --git a/fluid/file.h b/fluid/file.h deleted file mode 100644 index 4000c2b02..000000000 --- a/fluid/file.h +++ /dev/null @@ -1,94 +0,0 @@ -// -// 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 diff --git a/fluid/fluid.cxx b/fluid/fluid.cxx deleted file mode 100644 index e6520b6c0..000000000 --- a/fluid/fluid.cxx +++ /dev/null @@ -1,2340 +0,0 @@ -// -// 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 -#ifdef __APPLE__ -#include // for fl_open_callback -#endif -#include -#include -#include -#include -#include -#include -#include // setlocale().. -#include "../src/flstring.h" - -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 -} - -/// \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 std::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 -std::string g_code_filename_arg; - -/// command line arguments that overrides the generate header file extension or name -std::string g_header_filename_arg; - -/// current directory path at application launch -std::string g_launch_path; - -/// if set, generate images for automatic documentation in this directory -std::string g_autodoc_path; - -/// path to store temporary files during app run -/// \see tmpdir_create_called -std::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 = ""; - i18n_gnu_conditional = ""; - i18n_gnu_function = "gettext"; - i18n_gnu_static_function = "gettext_noop"; - - i18n_pos_include = ""; - 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 std::string end_with_slash(const std::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\\AppData\Local\Temp - fl_snprintf(buf, sizeof(buf)-1, "fluid-%d/", (long)GetCurrentProcessId()); - std::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; - } - std::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()); - std::string name = buf; - std::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 = std::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 = std::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; id_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 std::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 - std::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)) { - std::string basename = fl_filename_name(std::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 - */ -std::string open_project_filechooser(const std::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) { - std::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 std::string(); - return std::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 std::string &filename_arg) { - bool is_a_merge = (Fl_Type::first != NULL); - std::string title = is_a_merge ? "Merge Project File" : "Open Project File"; - - // ask for a filename if none was given - std::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 std::string &filename_arg) { - // verify user intention - if (confirm_project_clear() == false) - return false; - - // ask for a filename if none was given - std::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(std::string(c)); -} -#endif // __APPLE__ - -/** - Get the absolute path of the project file, for example `/Users/matt/dev/`. - \return the path ending in '/' - */ -std::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 - */ -std::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 '/' - */ -std::string Fluid_Project::codefile_path() const { - std::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 - */ -std::string Fluid_Project::codefile_name() const { - std::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 '/' - */ -std::string Fluid_Project::headerfile_path() const { - std::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 - */ -std::string Fluid_Project::headerfile_name() const { - std::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 '/' - */ -std::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 - */ -std::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 - */ -std::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; - std::string code_filename = g_project.codefile_path() + g_project.codefile_name(); - std::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()); - std::string code_filename_rel = fl_filename_relative(code_filename); - std::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; - } - - std::string proj_filename = g_project.projectfile_path() + g_project.projectfile_name(); - std::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; ivalue()) { - 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 - ( - "\n" - "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... - std::string basename = fl_filename_name(std::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(std::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... - std::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])); - std::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) { - std::string basename; - if (!filename) basename = "Untitled.fl"; - else basename = fl_filename_name(std::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); -} - -/// \} - diff --git a/fluid/fluid.h b/fluid/fluid.h deleted file mode 100644 index 140231936..000000000 --- a/fluid/fluid.h +++ /dev/null @@ -1,204 +0,0 @@ -// -// 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 - -#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 std::string g_code_filename_arg; -extern std::string g_header_filename_arg; -extern std::string g_launch_path; - -extern std::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(); - - std::string projectfile_path() const; - std::string projectfile_name() const; - std::string codefile_path() const; - std::string codefile_name() const; - std::string headerfile_path() const; - std::string headerfile_name() const; - std::string stringsfile_path() const; - std::string stringsfile_name() const; - std::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. - std::string i18n_gnu_include; - // Optional name of a macro for conditional i18n compilation. - std::string i18n_gnu_conditional; - /// For the gettext/intl.h options, this is the function that translates text - /// at runtime. This is usually "gettext" or "_". - std::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_". - std::string i18n_gnu_static_function; - - /// Include file for Posix i18n, write a #include statement into the source - /// file. This is usually `` for Posix catgets. - std::string i18n_pos_include; - // Optional name of a macro for conditional i18n compilation. - std::string i18n_pos_conditional; - /// Name of the nl_catd database - std::string i18n_pos_file; - /// Message set ID for the catalog. - std::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. - std::string header_file_name; - /// Hold the default extension for source code files, or the entire filename if set via command line. - std::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 std::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 diff --git a/fluid/fluid_filename.cxx b/fluid/fluid_filename.cxx deleted file mode 100644 index 9bb3b1f73..000000000 --- a/fluid/fluid_filename.cxx +++ /dev/null @@ -1,220 +0,0 @@ -// -// 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 std::string and also - includes the main header file . - - \note This file contains some filename functions using std::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 -#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) - */ -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); -} - -/** - 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 - */ -std::string fl_filename_shortened(const std::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 std::string tilde = "~/"; - static std::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(), (int)home.size()); - } - std::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, (int)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; - } -} diff --git a/fluid/fluid_filename.h b/fluid/fluid_filename.h deleted file mode 100644 index 5fa23c82e..000000000 --- a/fluid/fluid_filename.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * 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 std::string and also - includes the main header file . - - \note This file contains some filename functions using std::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) - -#include - -std::string fl_filename_shortened(const std::string &filename, int maxchars); -std::string fl_filename_name(const std::string &filename); -std::string fl_filename_path(const std::string &filename); -std::string fl_filename_ext(const std::string &filename); -std::string fl_filename_setext(const std::string &filename, const std::string &new_extension); -std::string fl_filename_expand(const std::string &from); -std::string fl_filename_absolute(const std::string &from); -std::string fl_filename_absolute(const std::string &from, const std::string &base); -std::string fl_filename_relative(const std::string &from); -std::string fl_filename_relative(const std::string &from, const std::string &base); -std::string fl_getcwd(); - -# endif - -/** @} */ - -#endif /* FLUID_FILENAME_H */ diff --git a/fluid/function_panel.cxx b/fluid/function_panel.cxx deleted file mode 100644 index 489341c5b..000000000 --- a/fluid/function_panel.cxx +++ /dev/null @@ -1,1559 +0,0 @@ -// -// 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.0500 - -#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; -} - -// diff --git a/fluid/function_panel.fl b/fluid/function_panel.fl deleted file mode 100644 index 7c77af009..000000000 --- a/fluid/function_panel.fl +++ /dev/null @@ -1,1044 +0,0 @@ -# data file for the Fltk User Interface Designer (fluid) -version 1.0500 -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 -} diff --git a/fluid/function_panel.h b/fluid/function_panel.h deleted file mode 100644 index d41a9d355..000000000 --- a/fluid/function_panel.h +++ /dev/null @@ -1,116 +0,0 @@ -// -// 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.0500 - -#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 - -// diff --git a/fluid/io/code.cxx b/fluid/io/code.cxx new file mode 100644 index 000000000..b77cad147 --- /dev/null +++ b/fluid/io/code.cxx @@ -0,0 +1,1107 @@ +// +// Code output 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 "io/code.h" + +#include "app/fluid.h" +#include "app/undo.h" +#include "io/file.h" +#include "nodes/Fl_Group_Type.h" +#include "nodes/Fl_Window_Type.h" +#include "nodes/Fl_Function_Type.h" +#include "tools/fluid_filename.h" + +#include +#include +#include +#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 std::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) { + std::string proj_filename = g_project.projectfile_path() + g_project.projectfile_name(); + int i, n = (int)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()); + } + } + std::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); +} + +/// \} + diff --git a/fluid/io/code.h b/fluid/io/code.h new file mode 100644 index 000000000..758e7bf45 --- /dev/null +++ b/fluid/io/code.h @@ -0,0 +1,112 @@ +// +// 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 + +#include +#include +#include + +class Fl_Type; +struct Fd_Identifier_Tree; +struct Fd_Text_Tree; +struct Fd_Pointer_Tree; + +int is_id(char c); +int write_strings(const std::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 diff --git a/fluid/io/file.cxx b/fluid/io/file.cxx new file mode 100644 index 000000000..b697325dc --- /dev/null +++ b/fluid/io/file.cxx @@ -0,0 +1,983 @@ +// +// 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 "io/file.h" + +#include "app/fluid.h" +#include "app/shell_command.h" +#include "app/undo.h" +#include "io/code.h" +#include "nodes/factory.h" +#include "nodes/Fl_Function_Type.h" +#include "nodes/Fl_Widget_Type.h" +#include "nodes/Fl_Grid_Type.h" +#include "nodes/Fl_Window_Type.h" +#include "panels/settings_panel.h" +#include "widgets/widget_browser.h" + +#include +#include +#include +#include +#include "../src/flstring.h" + +#include +#include +#include + +/// \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(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()) { // + ((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; +} + +/// \} diff --git a/fluid/io/file.h b/fluid/io/file.h new file mode 100644 index 000000000..470cc1a7b --- /dev/null +++ b/fluid/io/file.h @@ -0,0 +1,94 @@ +// +// 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 "nodes/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 diff --git a/fluid/main.cxx b/fluid/main.cxx new file mode 100644 index 000000000..d05732d2b --- /dev/null +++ b/fluid/main.cxx @@ -0,0 +1,23 @@ +// +// FLUID main entry 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 "main.h" +#include "app/fluid.h" + +int main(int argc,char **argv) { + return fluid_main(argc, argv); +} + diff --git a/fluid/main.h b/fluid/main.h new file mode 100644 index 000000000..a6286962a --- /dev/null +++ b/fluid/main.h @@ -0,0 +1,22 @@ +// +// FLUID main entry 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 +// + +#ifndef _FLUID_MAIN_H +#define _FLUID_MAIN_H + +extern int main(int argc,char **argv); + +#endif // _FLUID_MAIN_H diff --git a/fluid/mergeback.cxx b/fluid/mergeback.cxx deleted file mode 100644 index a0b87534c..000000000 --- a/fluid/mergeback.cxx +++ /dev/null @@ -1,493 +0,0 @@ -// -// 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 std::string &s, const std::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 - */ -std::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); - std::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 std::string &code_filename, const std::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; - } - std::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()) { - std::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)) { - std::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()) { - std::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)) { - std::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 std::string &s, int task). - */ -int Fd_Mergeback::merge_back(const std::string &s, const std::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 - diff --git a/fluid/mergeback.h b/fluid/mergeback.h deleted file mode 100644 index f828e9669..000000000 --- a/fluid/mergeback.h +++ /dev/null @@ -1,81 +0,0 @@ -// -// 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 -#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 std::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); - std::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 std::string &s, const std::string &p, int task); - int ask_user_to_merge(const std::string &s, const std::string &p); - int analyse(); - int apply(); -}; - -extern int merge_back(const std::string &s, const std::string &p, int task); - - -#endif // _FLUID_MERGEBACK_H - -#endif diff --git a/fluid/nodes/Fl_Button_Type.cxx b/fluid/nodes/Fl_Button_Type.cxx new file mode 100644 index 000000000..18620b477 --- /dev/null +++ b/fluid/nodes/Fl_Button_Type.cxx @@ -0,0 +1,226 @@ +// +// 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 "nodes/Fl_Button_Type.h" + +#include "app/Fd_Snap_Action.h" +#include "io/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; + diff --git a/fluid/nodes/Fl_Button_Type.h b/fluid/nodes/Fl_Button_Type.h new file mode 100644 index 000000000..d513c1398 --- /dev/null +++ b/fluid/nodes/Fl_Button_Type.h @@ -0,0 +1,46 @@ +// +// 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 "nodes/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 diff --git a/fluid/nodes/Fl_Function_Type.cxx b/fluid/nodes/Fl_Function_Type.cxx new file mode 100644 index 000000000..1f0a4fea5 --- /dev/null +++ b/fluid/nodes/Fl_Function_Type.cxx @@ -0,0 +1,2156 @@ +// +// 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 "nodes/Fl_Function_Type.h" + +#include "app/fluid.h" +#include "app/mergeback.h" +#include "app/undo.h" +#include "io/file.h" +#include "io/code.h" +#include "nodes/Fl_Window_Type.h" +#include "nodes/Fl_Group_Type.h" +#include "panels/function_panel.h" +#include "rsrcs/comments.h" +#include "widgets/widget_browser.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; +} diff --git a/fluid/nodes/Fl_Function_Type.h b/fluid/nodes/Fl_Function_Type.h new file mode 100644 index 000000000..536a511c0 --- /dev/null +++ b/fluid/nodes/Fl_Function_Type.h @@ -0,0 +1,259 @@ +// +// 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 "nodes/Fl_Type.h" + +#include "app/Fluid_Image.h" +#ifdef _WIN32 +#include "tools/ExternalCodeEditor_WIN32.h" +#else +#include "tools/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 diff --git a/fluid/nodes/Fl_Grid_Type.cxx b/fluid/nodes/Fl_Grid_Type.cxx new file mode 100644 index 000000000..2ae05a0ce --- /dev/null +++ b/fluid/nodes/Fl_Grid_Type.cxx @@ -0,0 +1,993 @@ +// +// 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 "nodes/Fl_Grid_Type.h" + +#include "app/fluid.h" +#include "app/Fd_Snap_Action.h" +#include "app/undo.h" +#include "io/file.h" +#include "io/code.h" +#include "widgets/widget_browser.h" +#include "widgets/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); + } + } + } +} + diff --git a/fluid/nodes/Fl_Grid_Type.h b/fluid/nodes/Fl_Grid_Type.h new file mode 100644 index 000000000..1093a38f3 --- /dev/null +++ b/fluid/nodes/Fl_Grid_Type.h @@ -0,0 +1,82 @@ +// +// 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 "nodes/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 diff --git a/fluid/nodes/Fl_Group_Type.cxx b/fluid/nodes/Fl_Group_Type.cxx new file mode 100644 index 000000000..a7ab20473 --- /dev/null +++ b/fluid/nodes/Fl_Group_Type.cxx @@ -0,0 +1,848 @@ +// +// 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 "nodes/Fl_Group_Type.h" + +#include "app/fluid.h" +#include "app/undo.h" +#include "app/Fd_Snap_Action.h" +#include "io/file.h" +#include "io/code.h" +#include "widgets/widget_browser.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(); +} + diff --git a/fluid/nodes/Fl_Group_Type.h b/fluid/nodes/Fl_Group_Type.h new file mode 100644 index 000000000..88645a08e --- /dev/null +++ b/fluid/nodes/Fl_Group_Type.h @@ -0,0 +1,242 @@ +// +// 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 "nodes/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 diff --git a/fluid/nodes/Fl_Menu_Type.cxx b/fluid/nodes/Fl_Menu_Type.cxx new file mode 100644 index 000000000..684d765f8 --- /dev/null +++ b/fluid/nodes/Fl_Menu_Type.cxx @@ -0,0 +1,922 @@ +// +// 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 "nodes/Fl_Menu_Type.h" + +#include "app/fluid.h" +#include "app/Fluid_Image.h" +#include "app/mergeback.h" +#include "app/undo.h" +#include "io/file.h" +#include "io/code.h" +#include "nodes/Fl_Window_Type.h" +#include "widgets/custom_widgets.h" +#include "widgets/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); + } +} diff --git a/fluid/nodes/Fl_Menu_Type.h b/fluid/nodes/Fl_Menu_Type.h new file mode 100644 index 000000000..b4ad90081 --- /dev/null +++ b/fluid/nodes/Fl_Menu_Type.h @@ -0,0 +1,287 @@ +// +// 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 "nodes/Fl_Button_Type.h" + +#include "app/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 diff --git a/fluid/nodes/Fl_Type.cxx b/fluid/nodes/Fl_Type.cxx new file mode 100644 index 000000000..56a15175e --- /dev/null +++ b/fluid/nodes/Fl_Type.cxx @@ -0,0 +1,1336 @@ +// +// 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 "nodes/Fl_Type.h" + +#include "app/fluid.h" +#include "app/Fd_Snap_Action.h" +#include "app/shell_command.h" +#include "app/undo.h" +#include "io/file.h" +#include "io/code.h" +#include "nodes/Fl_Function_Type.h" +#include "nodes/Fl_Widget_Type.h" +#include "nodes/Fl_Window_Type.h" +#include "nodes/Fl_Group_Type.h" +#include "rsrcs/pixmaps.h" +#include "widgets/widget_browser.h" + +#include +#include +#include +#include "../src/flstring.h" + +#include +#include + +// ---- 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; +} + +/// \} + diff --git a/fluid/nodes/Fl_Type.h b/fluid/nodes/Fl_Type.h new file mode 100644 index 000000000..478059c13 --- /dev/null +++ b/fluid/nodes/Fl_Type.h @@ -0,0 +1,317 @@ +// +// Widget type header file 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 +// + +#ifndef _FLUID_FL_TYPE_H +#define _FLUID_FL_TYPE_H + +#include "io/code.h" + +#include +#include + +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 diff --git a/fluid/nodes/Fl_Widget_Type.cxx b/fluid/nodes/Fl_Widget_Type.cxx new file mode 100644 index 000000000..27e309cbe --- /dev/null +++ b/fluid/nodes/Fl_Widget_Type.cxx @@ -0,0 +1,3937 @@ +// +// Widget type 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 +// + +#include "nodes/Fl_Widget_Type.h" + +#include "app/fluid.h" +#include "app/Fluid_Image.h" +#include "app/mergeback.h" +#include "app/undo.h" +#include "io/file.h" +#include "io/code.h" +#include "nodes/Fl_Window_Type.h" +#include "nodes/Fl_Group_Type.h" +#include "nodes/Fl_Menu_Type.h" +#include "nodes/Fl_Function_Type.h" +#include "panels/settings_panel.h" +#include "panels/widget_panel.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(); +} + diff --git a/fluid/nodes/Fl_Widget_Type.h b/fluid/nodes/Fl_Widget_Type.h new file mode 100644 index 000000000..76bea3404 --- /dev/null +++ b/fluid/nodes/Fl_Widget_Type.h @@ -0,0 +1,132 @@ +// +// 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 "nodes/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 diff --git a/fluid/nodes/Fl_Window_Type.cxx b/fluid/nodes/Fl_Window_Type.cxx new file mode 100644 index 000000000..c26191b72 --- /dev/null +++ b/fluid/nodes/Fl_Window_Type.cxx @@ -0,0 +1,1560 @@ +// +// 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-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 "nodes/Fl_Window_Type.h" + +#include "app/Fd_Snap_Action.h" +#include "app/fluid.h" +#include "app/undo.h" +#include "io/file.h" +#include "io/code.h" +#include "nodes/factory.h" +#include "nodes/Fl_Group_Type.h" +#include "nodes/Fl_Grid_Type.h" +#include "panels/settings_panel.h" +#include "panels/widget_panel.h" +#include "widgets/widget_browser.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(); +} diff --git a/fluid/nodes/Fl_Window_Type.h b/fluid/nodes/Fl_Window_Type.h new file mode 100644 index 000000000..a0695f2a1 --- /dev/null +++ b/fluid/nodes/Fl_Window_Type.h @@ -0,0 +1,157 @@ +// +// 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 "nodes/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 diff --git a/fluid/nodes/factory.cxx b/fluid/nodes/factory.cxx new file mode 100644 index 000000000..ad5d388e1 --- /dev/null +++ b/fluid/nodes/factory.cxx @@ -0,0 +1,1718 @@ +// +// 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-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 "nodes/factory.h" + +#include "app/Fd_Snap_Action.h" +#include "app/fluid.h" +#include "app/undo.h" +#include "nodes/Fl_Group_Type.h" +#include "nodes/Fl_Grid_Type.h" +#include "nodes/Fl_Menu_Type.h" +#include "rsrcs/pixmaps.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; +} diff --git a/fluid/nodes/factory.h b/fluid/nodes/factory.h new file mode 100644 index 000000000..f1968b167 --- /dev/null +++ b/fluid/nodes/factory.h @@ -0,0 +1,34 @@ +// +// 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 "nodes/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 diff --git a/fluid/panels/about_panel.cxx b/fluid/panels/about_panel.cxx new file mode 100644 index 000000000..ab36ddc10 --- /dev/null +++ b/fluid/panels/about_panel.cxx @@ -0,0 +1,2059 @@ +// +// 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.0500 + +#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}; diff --git a/fluid/panels/about_panel.fl b/fluid/panels/about_panel.fl new file mode 100644 index 000000000..3b5d54b72 --- /dev/null +++ b/fluid/panels/about_panel.fl @@ -0,0 +1,76 @@ +# data file for the Fltk User Interface Designer (fluid) +version 1.0500 +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} +} diff --git a/fluid/panels/about_panel.h b/fluid/panels/about_panel.h new file mode 100644 index 000000000..0130a1e44 --- /dev/null +++ b/fluid/panels/about_panel.h @@ -0,0 +1,32 @@ +// +// 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.0500 + +#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 diff --git a/fluid/panels/codeview_panel.cxx b/fluid/panels/codeview_panel.cxx new file mode 100644 index 000000000..33fb92ebd --- /dev/null +++ b/fluid/panels/codeview_panel.cxx @@ -0,0 +1,550 @@ +// +// 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.0500 + +#include "codeview_panel.h" +#include "app/fluid.h" +#include "io/file.h" +#include +#include +#include "../src/flstring.h" +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()) { + std::string code_file_name_bak = g_project.code_file_name; + g_project.code_file_name = cv_source_filename; + std::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; +} + +// diff --git a/fluid/panels/codeview_panel.fl b/fluid/panels/codeview_panel.fl new file mode 100644 index 000000000..54f0d790f --- /dev/null +++ b/fluid/panels/codeview_panel.fl @@ -0,0 +1,506 @@ +# data file for the Fltk User Interface Designer (fluid) +version 1.0500 +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 "app/fluid.h"} {private local +} + +decl {\#include "io/file.h"} {private local +} + +decl {\#include } {private local +} + +decl {\#include } {private local +} + +decl {\#include "../src/flstring.h"} {selected 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()) { + std::string code_file_name_bak = g_project.code_file_name; + g_project.code_file_name = cv_source_filename; + std::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 "widgets/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 "widgets/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 +} diff --git a/fluid/panels/codeview_panel.h b/fluid/panels/codeview_panel.h new file mode 100644 index 000000000..6dbbde1b4 --- /dev/null +++ b/fluid/panels/codeview_panel.h @@ -0,0 +1,58 @@ +// +// 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.0500 + +#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 "widgets/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 + +// diff --git a/fluid/panels/function_panel.cxx b/fluid/panels/function_panel.cxx new file mode 100644 index 000000000..2f8f72817 --- /dev/null +++ b/fluid/panels/function_panel.cxx @@ -0,0 +1,1559 @@ +// +// 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.0500 + +#include "function_panel.h" +#include "app/fluid.h" +#include "app/undo.h" +#include "nodes/Fl_Type.h" +#include "nodes/factory.h" +#include "rsrcs/pixmaps.h" +#include "widgets/custom_widgets.h" +#include "widgets/widget_browser.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; +} + +// diff --git a/fluid/panels/function_panel.fl b/fluid/panels/function_panel.fl new file mode 100644 index 000000000..5ad6325fc --- /dev/null +++ b/fluid/panels/function_panel.fl @@ -0,0 +1,1043 @@ +# data file for the Fltk User Interface Designer (fluid) +version 1.0500 +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 "app/fluid.h"} {private local +} + +decl {\#include "app/undo.h"} {selected private local +} + +decl {\#include "nodes/Fl_Type.h"} {private local +} + +decl {\#include "nodes/factory.h"} {private local +} + +decl {\#include "rsrcs/pixmaps.h"} {private local +} + +decl {\#include "widgets/custom_widgets.h"} {private global +} + +decl {\#include "widgets/widget_browser.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 "widgets/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 "widgets/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);} {} +} + +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 +} diff --git a/fluid/panels/function_panel.h b/fluid/panels/function_panel.h new file mode 100644 index 000000000..9dffa5c04 --- /dev/null +++ b/fluid/panels/function_panel.h @@ -0,0 +1,116 @@ +// +// 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.0500 + +#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 "widgets/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 + +// diff --git a/fluid/panels/print_panel.cxx b/fluid/panels/print_panel.cxx new file mode 100644 index 000000000..f585efee5 --- /dev/null +++ b/fluid/panels/print_panel.cxx @@ -0,0 +1,586 @@ +// +// 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.0500 + +#include "print_panel.h" +#include "app/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(); +} diff --git a/fluid/panels/print_panel.fl b/fluid/panels/print_panel.fl new file mode 100644 index 000000000..ae1899c3e --- /dev/null +++ b/fluid/panels/print_panel.fl @@ -0,0 +1,358 @@ +# data file for the Fltk User Interface Designer (fluid) +version 1.0500 +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 "app/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();} {} +} diff --git a/fluid/panels/print_panel.h b/fluid/panels/print_panel.h new file mode 100644 index 000000000..fed8fd3c0 --- /dev/null +++ b/fluid/panels/print_panel.h @@ -0,0 +1,56 @@ +// +// 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.0500 + +#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 diff --git a/fluid/panels/settings_panel.cxx b/fluid/panels/settings_panel.cxx new file mode 100644 index 000000000..a0e2092a8 --- /dev/null +++ b/fluid/panels/settings_panel.cxx @@ -0,0 +1,3551 @@ +// +// 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.0500 + +#include "settings_panel.h" +#include "app/undo.h" +#include +#include +#include +#include "../src/flstring.h" +#include +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; + + std::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 + + std::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"); + std::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]; diff --git a/fluid/panels/settings_panel.fl b/fluid/panels/settings_panel.fl new file mode 100644 index 000000000..a53e96b4b --- /dev/null +++ b/fluid/panels/settings_panel.fl @@ -0,0 +1,1883 @@ +# data file for the Fltk User Interface Designer (fluid) +version 1.0500 +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 "app/fluid.h"} {public global +} + +decl {\#include "app/undo.h"} {private global +} + +decl {\#include "app/Fd_Snap_Action.h"} {public global +} + +decl {\#include "app/shell_command.h"} {public global +} + +decl {\#include "tools/fluid_filename.h"} {public local +} + +decl {\#include "widgets/widget_browser.h"} {public global +} + +decl {\#include } {public local +} + +decl {\#include } {public local +} + +decl {\#include } {public local +} + +decl {\#include } {public local +} + +decl {\#include } {private global +} + +decl {\#include } {private global +} + +decl {\#include } {private global +} + +decl {\#include "../src/flstring.h"} {selected private global +} + +decl {\#include } {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 + 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; + +std::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 + +std::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"); + std::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 +} diff --git a/fluid/panels/settings_panel.h b/fluid/panels/settings_panel.h new file mode 100644 index 000000000..918e69c8a --- /dev/null +++ b/fluid/panels/settings_panel.h @@ -0,0 +1,143 @@ +// +// 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.0500 + +#ifndef settings_panel_h +#define settings_panel_h +#include +#include "app/fluid.h" +#include "app/Fd_Snap_Action.h" +#include "app/shell_command.h" +#include "tools/fluid_filename.h" +#include "widgets/widget_browser.h" +#include +#include +#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 diff --git a/fluid/panels/template_panel.cxx b/fluid/panels/template_panel.cxx new file mode 100644 index 000000000..ec4a5e29a --- /dev/null +++ b/fluid/panels/template_panel.cxx @@ -0,0 +1,340 @@ +// +// 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.0500 + +#include "template_panel.h" +#include "app/fluid.h" +#include "tools/fluid_filename.h" +#include +#include +#include +#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); +} diff --git a/fluid/panels/template_panel.fl b/fluid/panels/template_panel.fl new file mode 100644 index 000000000..cbbb5c7ff --- /dev/null +++ b/fluid/panels/template_panel.fl @@ -0,0 +1,297 @@ +# data file for the Fltk User Interface Designer (fluid) +version 1.0500 +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 "app/fluid.h"} {private local +} + +decl {\#include "tools/fluid_filename.h"} {selected private local +} + +decl {\#include } {private local +} + +decl {\#include } {private local +} + +decl {\#include } {private local +} + +decl {\#include "../src/flstring.h"} {private local +} + +decl {\#include } {private local +} + +decl {\#include } {private local +} + +decl {\#include } {private local +} + +decl {\#include } {private local +} + +declblock {\#if defined(_WIN32) && !defined(__CYGWIN__)} {after {\#endif // _WIN32 && !__CYGWIN__} +} { + decl {\#include } {private local + } + decl {\#else} {private local + } + decl {\#include } {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();} {} +} + +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);} {} +} diff --git a/fluid/panels/template_panel.h b/fluid/panels/template_panel.h new file mode 100644 index 000000000..172e4c7de --- /dev/null +++ b/fluid/panels/template_panel.h @@ -0,0 +1,41 @@ +// +// 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.0500 + +#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 diff --git a/fluid/panels/widget_panel.cxx b/fluid/panels/widget_panel.cxx new file mode 100644 index 000000000..cd3779851 --- /dev/null +++ b/fluid/panels/widget_panel.cxx @@ -0,0 +1,2497 @@ +// +// 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.0500 + +#include "widget_panel.h" +#include "app/undo.h" +#include "nodes/Fl_Widget_Type.h" +#include "nodes/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; +} diff --git a/fluid/panels/widget_panel.fl b/fluid/panels/widget_panel.fl new file mode 100644 index 000000000..57ae30273 --- /dev/null +++ b/fluid/panels/widget_panel.fl @@ -0,0 +1,1872 @@ +# data file for the Fltk User Interface Designer (fluid) +version 1.0500 +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 "app/undo.h"} {private global +} + +decl {\#include "nodes/Fl_Widget_Type.h"} {private global +} + +decl {\#include "nodes/Fl_Grid_Type.h"} {private global +} + +decl {\#include "widgets/custom_widgets.h"} {selected public global +} + +decl {\#include } {private 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_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 + 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 } + 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 "widgets/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 + } + } + } +} diff --git a/fluid/panels/widget_panel.h b/fluid/panels/widget_panel.h new file mode 100644 index 000000000..de827464e --- /dev/null +++ b/fluid/panels/widget_panel.h @@ -0,0 +1,225 @@ +// +// 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.0500 + +#ifndef widget_panel_h +#define widget_panel_h +#include +#include "widgets/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 "widgets/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 diff --git a/fluid/pixmaps.cxx b/fluid/pixmaps.cxx deleted file mode 100644 index 3d9e9d769..000000000 --- a/fluid/pixmaps.cxx +++ /dev/null @@ -1,226 +0,0 @@ -// -// 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); -} - diff --git a/fluid/pixmaps.h b/fluid/pixmaps.h deleted file mode 100644 index 628bcd199..000000000 --- a/fluid/pixmaps.h +++ /dev/null @@ -1,32 +0,0 @@ -// -// 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 diff --git a/fluid/print_panel.cxx b/fluid/print_panel.cxx deleted file mode 100644 index bf1dca655..000000000 --- a/fluid/print_panel.cxx +++ /dev/null @@ -1,586 +0,0 @@ -// -// 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.0500 - -#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(); -} diff --git a/fluid/print_panel.fl b/fluid/print_panel.fl deleted file mode 100644 index 382eece2b..000000000 --- a/fluid/print_panel.fl +++ /dev/null @@ -1,358 +0,0 @@ -# data file for the Fltk User Interface Designer (fluid) -version 1.0500 -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();} {} -} diff --git a/fluid/print_panel.h b/fluid/print_panel.h deleted file mode 100644 index fed8fd3c0..000000000 --- a/fluid/print_panel.h +++ /dev/null @@ -1,56 +0,0 @@ -// -// 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.0500 - -#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 diff --git a/fluid/rsrcs/comments.h b/fluid/rsrcs/comments.h new file mode 100644 index 000000000..85f3376b8 --- /dev/null +++ b/fluid/rsrcs/comments.h @@ -0,0 +1,65 @@ + +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 .\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 .\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" + }; diff --git a/fluid/rsrcs/pixmaps.cxx b/fluid/rsrcs/pixmaps.cxx new file mode 100644 index 000000000..dbcebe043 --- /dev/null +++ b/fluid/rsrcs/pixmaps.cxx @@ -0,0 +1,226 @@ +// +// 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 "rsrcs/pixmaps.h" + +#include "nodes/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); +} + diff --git a/fluid/rsrcs/pixmaps.h b/fluid/rsrcs/pixmaps.h new file mode 100644 index 000000000..628bcd199 --- /dev/null +++ b/fluid/rsrcs/pixmaps.h @@ -0,0 +1,32 @@ +// +// 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 diff --git a/fluid/settings_panel.cxx b/fluid/settings_panel.cxx deleted file mode 100644 index 291f5d24a..000000000 --- a/fluid/settings_panel.cxx +++ /dev/null @@ -1,3551 +0,0 @@ -// -// 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.0500 - -#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; - - std::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 - - std::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"); - std::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]; diff --git a/fluid/settings_panel.fl b/fluid/settings_panel.fl deleted file mode 100644 index 540ca48df..000000000 --- a/fluid/settings_panel.fl +++ /dev/null @@ -1,1883 +0,0 @@ -# data file for the Fltk User Interface Designer (fluid) -version 1.0500 -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; - -std::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 - -std::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"); - std::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 -} diff --git a/fluid/settings_panel.h b/fluid/settings_panel.h deleted file mode 100644 index a582f69e6..000000000 --- a/fluid/settings_panel.h +++ /dev/null @@ -1,143 +0,0 @@ -// -// 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.0500 - -#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 diff --git a/fluid/shell_command.cxx b/fluid/shell_command.cxx deleted file mode 100644 index e961fc24c..000000000 --- a/fluid/shell_command.cxx +++ /dev/null @@ -1,1005 +0,0 @@ -// -// 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 std::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, std::string &value, const std::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 std::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(std::string &cmd, const std::string ¯o, const std::string &content) { - for (int i=0;;) { - i = (int)cmd.find(macro, i); - if (i==(int)std::string::npos) break; - cmd.replace(i, macro.size(), content); - } -} - -static void expand_macros(std::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@") != std::string::npos) { -// find_fltk_config(); -// expand_macro(cmd, "@FLTK_CONFIG@", fltk_config_cmd.c_str()); -// } - if (cmd.find("@TMPDIR@") != std::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 std::string &cmd, int flags) { - if (cmd.empty()) { - fl_alert("No shell command entered!"); - return; - } - - if (!prepare_shell_command(flags)) return; - - std::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 std::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 std::string &in_name, - const std::string &in_label, - Fl_Shortcut in_shortcut, - Fd_Tool_Store in_storage, - int in_condition, - const std::string &in_condition_data, - const std::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; - diff --git a/fluid/shell_command.h b/fluid/shell_command.h deleted file mode 100644 index e5f8e3e87..000000000 --- a/fluid/shell_command.h +++ /dev/null @@ -1,148 +0,0 @@ -// -// 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 - -#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, std::string &value, const std::string &defaultValue); -char preferences_set(Fl_Preferences &prefs, const char *key, const std::string &value); - -void show_terminal_window(); -void run_shell_command(const std::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 std::string &in_name); - Fd_Shell_Command(const std::string &in_name, - const std::string &in_label, - Fl_Shortcut in_shortcut, - Fd_Tool_Store in_storage, - int in_condition, - const std::string &in_condition_data, - const std::string &in_command, - int in_flags); - std::string name; - std::string label; - Fl_Shortcut shortcut; - Fd_Tool_Store storage; - int condition; // always, hide, windows only, linux only, mac only, user, machine - std::string condition_data; // user name, machine name - std::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 std::string &filename); -// int save(const std::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 diff --git a/fluid/template_panel.cxx b/fluid/template_panel.cxx deleted file mode 100644 index 7bc8943c0..000000000 --- a/fluid/template_panel.cxx +++ /dev/null @@ -1,340 +0,0 @@ -// -// 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.0500 - -#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); -} diff --git a/fluid/template_panel.fl b/fluid/template_panel.fl deleted file mode 100644 index f4e4f8bb2..000000000 --- a/fluid/template_panel.fl +++ /dev/null @@ -1,298 +0,0 @@ -# data file for the Fltk User Interface Designer (fluid) -version 1.0500 -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 } {private local -} - -decl {\#include } {private local -} - -decl {\#include } {private local -} - -decl {\#include "fluid_filename.h"} {private local -} - -decl {\#include "../src/flstring.h"} {private local -} - -decl {\#include } {private local -} - -decl {\#include } {private local -} - -decl {\#include } {private local -} - -decl {\#include } {private local -} - -declblock {\#if defined(_WIN32) && !defined(__CYGWIN__)} {after {\#endif // _WIN32 && !__CYGWIN__} -} { - decl {\#include } {private local - } - decl {\#else} {private local - } - decl {\#include } {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);} {} -} diff --git a/fluid/template_panel.h b/fluid/template_panel.h deleted file mode 100644 index 172e4c7de..000000000 --- a/fluid/template_panel.h +++ /dev/null @@ -1,41 +0,0 @@ -// -// 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.0500 - -#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 diff --git a/fluid/templates/FLTK_License.fl b/fluid/templates/FLTK_License.fl index 7530bb5fb..95bd151f8 100644 --- a/fluid/templates/FLTK_License.fl +++ b/fluid/templates/FLTK_License.fl @@ -5,7 +5,7 @@ code_name {.cxx} comment {// // @INSTANCE@ for the Fast Light Tool Kit (FLTK). // -// Copyright 1998-2024 by Bill Spitzak and others. +// 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 diff --git a/fluid/tools/ExternalCodeEditor_UNIX.cxx b/fluid/tools/ExternalCodeEditor_UNIX.cxx new file mode 100644 index 000000000..09d7e6178 --- /dev/null +++ b/fluid/tools/ExternalCodeEditor_UNIX.cxx @@ -0,0 +1,576 @@ +// +// External code editor management class for Unix +// +// Note: This entire file Unix only + +#include "ExternalCodeEditor_UNIX.h" + +#include "app/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); + } + } +} diff --git a/fluid/tools/ExternalCodeEditor_UNIX.h b/fluid/tools/ExternalCodeEditor_UNIX.h new file mode 100644 index 000000000..644f22afa --- /dev/null +++ b/fluid/tools/ExternalCodeEditor_UNIX.h @@ -0,0 +1,60 @@ +// +// 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 "app/fluid.h" + +#include + +#include /* errno */ +#include /* strerror() */ +#include /* stat().. */ +#include +#include + +// ---- 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_; + std::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 */ diff --git a/fluid/tools/ExternalCodeEditor_WIN32.cxx b/fluid/tools/ExternalCodeEditor_WIN32.cxx new file mode 100644 index 000000000..c58f22a30 --- /dev/null +++ b/fluid/tools/ExternalCodeEditor_WIN32.cxx @@ -0,0 +1,632 @@ +// +// 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 "tools/ExternalCodeEditor_WIN32.h" +#include "app/fluid.h" + +#include // Fl_Timeout_Handler.. +#include // fl_alert() +#include // fl_utf8fromwc() +#include // fl_strdup() + +#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; +} diff --git a/fluid/tools/ExternalCodeEditor_WIN32.h b/fluid/tools/ExternalCodeEditor_WIN32.h new file mode 100644 index 000000000..de4c2c4a7 --- /dev/null +++ b/fluid/tools/ExternalCodeEditor_WIN32.h @@ -0,0 +1,59 @@ +// +// 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 */ diff --git a/fluid/tools/autodoc.cxx b/fluid/tools/autodoc.cxx new file mode 100644 index 000000000..59f9a7b27 --- /dev/null +++ b/fluid/tools/autodoc.cxx @@ -0,0 +1,613 @@ +// +// Self-generate snapshots of user interface for FLUID documentation. +// +// Copyright 2024-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 +// + +#ifndef NDEBUG + +#include "tools/autodoc.h" + +#include "app/fluid.h" +#include "nodes/factory.h" +#include "nodes/Fl_Widget_Type.h" +#include "nodes/Fl_Window_Type.h" +#include "panels/widget_panel.h" +#include "panels/function_panel.h" +#include "panels/settings_panel.h" +#include "panels/codeview_panel.h" +#include "widgets/widget_browser.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 std::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 diff --git a/fluid/tools/autodoc.h b/fluid/tools/autodoc.h new file mode 100644 index 000000000..33b0bd6fc --- /dev/null +++ b/fluid/tools/autodoc.h @@ -0,0 +1,59 @@ +// +// Widget snapshot header-only file for the Fast Light Tool Kit (FLTK). +// +// Copyright 2023-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 autodoc.h + \brief tools to take snapshots of UI elements for documentation purposes + */ + +#ifndef fl_screenshot_H +#define fl_screenshot_H + +#include +#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 std::string &target_dir); + +#endif + diff --git a/fluid/tools/fluid_filename.cxx b/fluid/tools/fluid_filename.cxx new file mode 100644 index 000000000..cd9dadfa6 --- /dev/null +++ b/fluid/tools/fluid_filename.cxx @@ -0,0 +1,219 @@ +// +// 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 std::string and also + includes the main header file . + + \note This file contains some filename functions using std::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 "../src/flstring.h" + +#include +#include + +/** + 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); +} + +/** + 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 + */ +std::string fl_filename_shortened(const std::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 std::string tilde = "~/"; + static std::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(), (int)home.size()); + } + std::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, (int)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; + } +} diff --git a/fluid/tools/fluid_filename.h b/fluid/tools/fluid_filename.h new file mode 100644 index 000000000..1486e61ab --- /dev/null +++ b/fluid/tools/fluid_filename.h @@ -0,0 +1,59 @@ +/* + * 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 std::string and also + includes the main header file . + + \note This file contains some filename functions using std::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) + +#include + +std::string fl_filename_shortened(const std::string &filename, int maxchars); +std::string fl_filename_name(const std::string &filename); +std::string fl_filename_path(const std::string &filename); +std::string fl_filename_ext(const std::string &filename); +std::string fl_filename_setext(const std::string &filename, const std::string &new_extension); +std::string fl_filename_expand(const std::string &from); +std::string fl_filename_absolute(const std::string &from); +std::string fl_filename_absolute(const std::string &from, const std::string &base); +std::string fl_filename_relative(const std::string &from); +std::string fl_filename_relative(const std::string &from, const std::string &base); +std::string fl_getcwd(); + +# endif + +/** @} */ + +#endif /* FLUID_FILENAME_H */ diff --git a/fluid/undo.cxx b/fluid/undo.cxx deleted file mode 100644 index 49aea2d98..000000000 --- a/fluid/undo.cxx +++ /dev/null @@ -1,263 +0,0 @@ -// -// 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++; -} diff --git a/fluid/undo.h b/fluid/undo.h deleted file mode 100644 index 20572351d..000000000 --- a/fluid/undo.h +++ /dev/null @@ -1,37 +0,0 @@ -// -// 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 diff --git a/fluid/widget_browser.cxx b/fluid/widget_browser.cxx deleted file mode 100644 index c54231263..000000000 --- a/fluid/widget_browser.cxx +++ /dev/null @@ -1,669 +0,0 @@ -// -// 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); -} diff --git a/fluid/widget_browser.h b/fluid/widget_browser.h deleted file mode 100644 index 86c60777c..000000000 --- a/fluid/widget_browser.h +++ /dev/null @@ -1,84 +0,0 @@ -// -// 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 diff --git a/fluid/widget_panel.cxx b/fluid/widget_panel.cxx deleted file mode 100644 index ec61c1083..000000000 --- a/fluid/widget_panel.cxx +++ /dev/null @@ -1,2497 +0,0 @@ -// -// 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.0500 - -#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; -} diff --git a/fluid/widget_panel.fl b/fluid/widget_panel.fl deleted file mode 100644 index 470248e7d..000000000 --- a/fluid/widget_panel.fl +++ /dev/null @@ -1,1872 +0,0 @@ -# data file for the Fltk User Interface Designer (fluid) -version 1.0500 -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 } {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_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 } - 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 - } - } - } -} diff --git a/fluid/widget_panel.h b/fluid/widget_panel.h deleted file mode 100644 index 38e70cc71..000000000 --- a/fluid/widget_panel.h +++ /dev/null @@ -1,225 +0,0 @@ -// -// 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.0500 - -#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 diff --git a/fluid/widgets/CodeEditor.cxx b/fluid/widgets/CodeEditor.cxx new file mode 100644 index 000000000..ca114b577 --- /dev/null +++ b/fluid/widgets/CodeEditor.cxx @@ -0,0 +1,316 @@ +// +// Code editor widget for the Fast Light Tool Kit (FLTK). +// Syntax highlighting rewritten by erco@seriss.com 09/15/20. +// +// 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 necessary headers... +// + +#include "widgets/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); +} + + diff --git a/fluid/widgets/CodeEditor.h b/fluid/widgets/CodeEditor.h new file mode 100644 index 000000000..cc720d618 --- /dev/null +++ b/fluid/widgets/CodeEditor.h @@ -0,0 +1,105 @@ +// +// Code editor widget for the Fast Light Tool Kit (FLTK). +// Syntax highlighting rewritten by erco@seriss.com 09/15/20. +// +// 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 +// + +#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 diff --git a/fluid/widgets/StyleParse.cxx b/fluid/widgets/StyleParse.cxx new file mode 100644 index 000000000..b8b8ff4f0 --- /dev/null +++ b/fluid/widgets/StyleParse.cxx @@ -0,0 +1,328 @@ +// +// 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(); +} diff --git a/fluid/widgets/StyleParse.h b/fluid/widgets/StyleParse.h new file mode 100644 index 000000000..2fcc4f4db --- /dev/null +++ b/fluid/widgets/StyleParse.h @@ -0,0 +1,61 @@ +// +// 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 diff --git a/fluid/widgets/custom_widgets.cxx b/fluid/widgets/custom_widgets.cxx new file mode 100644 index 000000000..25a630783 --- /dev/null +++ b/fluid/widgets/custom_widgets.cxx @@ -0,0 +1,311 @@ +// +// 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 "widgets/custom_widgets.h" + +#include "app/fluid.h" +#include "nodes/Fl_Window_Type.h" +#include "nodes/factory.h" +#include "panels/widget_panel.h" +#include "widgets/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); +} diff --git a/fluid/widgets/custom_widgets.h b/fluid/widgets/custom_widgets.h new file mode 100644 index 000000000..875496b8e --- /dev/null +++ b/fluid/widgets/custom_widgets.h @@ -0,0 +1,90 @@ +// +// 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 diff --git a/fluid/widgets/widget_browser.cxx b/fluid/widgets/widget_browser.cxx new file mode 100644 index 000000000..9f7c8ff6c --- /dev/null +++ b/fluid/widgets/widget_browser.cxx @@ -0,0 +1,669 @@ +// +// Widget Browser 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 +// + +#include "widgets/widget_browser.h" + +#include "app/fluid.h" +#include "nodes/Fl_Widget_Type.h" +#include "rsrcs/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); +} diff --git a/fluid/widgets/widget_browser.h b/fluid/widgets/widget_browser.h new file mode 100644 index 000000000..86c60777c --- /dev/null +++ b/fluid/widgets/widget_browser.h @@ -0,0 +1,84 @@ +// +// 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 -- cgit v1.2.3