diff options
author | Aaron M. Ucko <ucko@debian.org> | 2015-07-07 01:32:55 -0400 |
---|---|---|
committer | Aaron M. Ucko <ucko@debian.org> | 2015-07-07 01:40:11 -0400 |
commit | 574b357ee8bd5c44a1511a5a29f60b2d659b263f (patch) | |
tree | e7f69d70ef4c9414325db8cca0b4e7b56ee7c81a /src | |
parent | 51a046516db7c8e194cc232e4fb18ecb3ffa65dc (diff) | |
parent | a3d0ced57399c9fd8075377b7310d545f968e524 (diff) |
Merge tag 'upstream/1.3.3' (Closes: #791346.)
Upstream version 1.3.3
Diffstat (limited to 'src')
125 files changed, 13003 insertions, 8603 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0c0865a..d53ab80 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,4 +1,3 @@ -include_regular_expression("[.][cxx|c|h]$") set(CPPFILES Fl.cxx @@ -15,9 +14,11 @@ set(CPPFILES Fl_Choice.cxx Fl_Clock.cxx Fl_Color_Chooser.cxx + Fl_Copy_Surface.cxx Fl_Counter.cxx Fl_Device.cxx Fl_Dial.cxx + Fl_Help_Dialog_Dox.cxx Fl_Double_Window.cxx Fl_File_Browser.cxx Fl_File_Chooser.cxx @@ -27,13 +28,13 @@ set(CPPFILES Fl_Group.cxx Fl_Help_View.cxx Fl_Image.cxx + Fl_Image_Surface.cxx Fl_Input.cxx Fl_Input_.cxx Fl_Light_Button.cxx Fl_Menu.cxx Fl_Menu_.cxx Fl_Menu_Bar.cxx - Fl_Sys_Menu_Bar.cxx Fl_Menu_Button.cxx Fl_Menu_Window.cxx Fl_Menu_add.cxx @@ -45,6 +46,7 @@ set(CPPFILES Fl_Paged_Device.cxx Fl_Pixmap.cxx Fl_Positioner.cxx + Fl_PostScript.cxx Fl_Printer.cxx Fl_Preferences.cxx Fl_Progress.cxx @@ -79,6 +81,7 @@ set(CPPFILES Fl_Window_fullscreen.cxx Fl_Window_hotspot.cxx Fl_Window_iconize.cxx + Fl_Window_shape.cxx Fl_Wizard.cxx Fl_XBM_Image.cxx Fl_XPM_Image.cxx @@ -116,6 +119,7 @@ set(CPPFILES fl_engraved_label.cxx fl_file_dir.cxx fl_font.cxx + fl_gleam.cxx fl_gtk.cxx fl_labeltype.cxx fl_line_style.cxx @@ -195,32 +199,22 @@ set(CFILES add_definitions(-DFL_LIBRARY) if(APPLE) - set(MMFILES - Fl_cocoa.mm - Fl_Quartz_Printer.mm - Fl_Native_File_Chooser_MAC.mm - ) + set(MMFILES + Fl_cocoa.mm + Fl_Quartz_Printer.mm + Fl_Native_File_Chooser_MAC.mm + Fl_Sys_Menu_Bar.mm + ) else() set(MMFILES ) endif(APPLE) ####################################################################### -add_library(fltk STATIC ${CPPFILES} ${MMFILES} ${CFILES} fl_call_main.c) -set_target_properties(fltk PROPERTIES CLEAN_DIRECT_OUTPUT 1) -if(MSVC) - if(OPTION_LARGE_FILE) - set_target_properties(fltk PROPERTIES LINK_FLAGS /LARGEADDRESSAWARE) - endif() - set_target_properties(fltk - PROPERTIES - OUTPUT_NAME fltk - DEBUG_OUTPUT_NAME fltkd - ) -endif(MSVC) +FL_ADD_LIBRARY(fltk STATIC "${CPPFILES};${MMFILES};${CFILES};fl_call_main.c") if(USE_THREADS) - target_link_libraries(fltk ${CMAKE_THREAD_LIBS_INIT}) + target_link_libraries(fltk ${CMAKE_THREAD_LIBS_INIT} ${LIB_dl}) endif(USE_THREADS) if(USE_X11) @@ -239,73 +233,52 @@ if(HAVE_XINERAMA) target_link_libraries(fltk ${X11_Xinerama_LIB}) endif(HAVE_XINERAMA) +if(HAVE_XFIXES) + target_link_libraries(fltk ${X11_Xfixes_LIB}) +endif(HAVE_XFIXES) + +if(HAVE_XCURSOR) + target_link_libraries(fltk ${X11_Xcursor_LIB}) +endif(HAVE_XCURSOR) + if(USE_XFT) target_link_libraries(fltk ${X11_Xft_LIB}) + if(LIB_fontconfig) + target_link_libraries(fltk ${LIB_fontconfig}) + endif(LIB_fontconfig) endif(USE_XFT) -if(LIB_fontconfig) - target_link_libraries(fltk ${LIB_fontconfig}) -endif(LIB_fontconfig) - ####################################################################### -add_library(fltk_forms STATIC ${FLCPPFILES}) +FL_ADD_LIBRARY(fltk_forms STATIC "${FLCPPFILES}") target_link_libraries(fltk_forms fltk) -set_target_properties(fltk_forms - PROPERTIES CLEAN_DIRECT_OUTPUT 1 -) -if(MSVC) - if(OPTION_LARGE_FILE) - set_target_properties(fltk_forms PROPERTIES LINK_FLAGS /LARGEADDRESSAWARE) - endif() - set_target_properties(fltk_forms - PROPERTIES - OUTPUT_NAME fltkforms - DEBUG_OUTPUT_NAME fltkformsd - ) -endif(MSVC) ####################################################################### -add_library(fltk_images STATIC ${IMGCPPFILES}) +FL_ADD_LIBRARY(fltk_images STATIC "${IMGCPPFILES}") target_link_libraries(fltk_images fltk ${FLTK_PNG_LIBRARIES} ${FLTK_JPEG_LIBRARIES} ${FLTK_ZLIB_LIBRARIES}) -set_target_properties(fltk_images PROPERTIES CLEAN_DIRECT_OUTPUT 1) -if(MSVC) - if(OPTION_LARGE_FILE) - set_target_properties(fltk_images PROPERTIES LINK_FLAGS /LARGEADDRESSAWARE) - endif() - set_target_properties(fltk_images - PROPERTIES - OUTPUT_NAME fltkimages - DEBUG_OUTPUT_NAME fltkimagesd - ) -endif(MSVC) -####################################################################### -install(TARGETS fltk fltk_forms fltk_images - EXPORT fltk-install - DESTINATION ${PREFIX_LIB} -) +if(OPTION_USE_SYSTEM_LIBJPEG) + target_link_libraries(fltk_images ${FLTK_JPEG_LIBRARIES}) +else() + target_link_libraries(fltk_images fltk_jpeg) +endif(OPTION_USE_SYSTEM_LIBJPEG) + +if(OPTION_USE_SYSTEM_ZLIB) + target_link_libraries(fltk_images ${FLTK_ZLIB_LIBRARIES}) +else() + target_link_libraries(fltk_images fltk_z) +endif(OPTION_USE_SYSTEM_ZLIB) + +if(OPTION_USE_SYSTEM_LIBPNG) + target_link_libraries(fltk_images ${FLTK_PNG_LIBRARIES}) +else() + target_link_libraries(fltk_images fltk_png) +endif(OPTION_USE_SYSTEM_LIBPNG) ####################################################################### if(OPENGL_FOUND) - add_library(fltk_gl STATIC ${GLCPPFILES}) + FL_ADD_LIBRARY(fltk_gl STATIC "${GLCPPFILES}") target_link_libraries(fltk_gl fltk ${OPENGL_LIBRARIES}) - set_target_properties(fltk_gl PROPERTIES CLEAN_DIRECT_OUTPUT 1) - if(MSVC) - if(OPTION_LARGE_FILE) - set_target_properties(fltk_gl PROPERTIES LINK_FLAGS /LARGEADDRESSAWARE) - endif() - set_target_properties(fltk_gl - PROPERTIES - OUTPUT_NAME fltkgl - DEBUG_OUTPUT_NAME fltkgld - ) - endif(MSVC) - - install(TARGETS fltk_gl - EXPORT fltk-install - DESTINATION ${PREFIX_LIB} - ) endif(OPENGL_FOUND) ####################################################################### @@ -313,28 +286,10 @@ endif(OPENGL_FOUND) if(OPTION_BUILD_SHARED_LIBS) ####################################################################### -add_library(fltk_SHARED SHARED ${CPPFILES} ${MMFILES} ${CFILES}) -set_target_properties(fltk_SHARED - PROPERTIES CLEAN_DIRECT_OUTPUT 1 - VERSION ${FLTK_VERSION_MAJOR}.${FLTK_VERSION_MINOR} - SOVERSION ${FLTK_VERSION_PATCH} -) -if(MSVC) - set_target_properties(fltk_SHARED - PROPERTIES - OUTPUT_NAME fltkdll - DEBUG_OUTPUT_NAME fltkdlld - COMPILE_DEFINITIONS "FL_DLL;FL_LIBRARY" - ) - if(OPTION_LARGE_FILE) - set_target_properties(fltk_SHARED PROPERTIES LINK_FLAGS /LARGEADDRESSAWARE) - endif(OPTION_LARGE_FILE) -else() - set_target_properties(fltk_SHARED PROPERTIES OUTPUT_NAME fltk) -endif(MSVC) +FL_ADD_LIBRARY(fltk SHARED "${CPPFILES};${MMFILES};${CFILES}") if(USE_THREADS) - target_link_libraries(fltk_SHARED ${CMAKE_THREAD_LIBS_INIT}) + target_link_libraries(fltk_SHARED ${CMAKE_THREAD_LIBS_INIT} ${LIB_dl}) endif(USE_THREADS) if(USE_X11) @@ -346,7 +301,7 @@ if(WIN32) endif(WIN32) if(FLTK_HAVE_CAIRO) - target_link_libraries(fltk_SHARED fltk_cairo ${PKG_CAIRO_LIBRARIES}) + target_link_libraries(fltk_SHARED fltk_cairo_SHARED ${PKG_CAIRO_LIBRARIES}) ENDif(FLTK_HAVE_CAIRO) if(HAVE_XINERAMA) @@ -355,99 +310,51 @@ endif(HAVE_XINERAMA) if(USE_XFT) target_link_libraries(fltk_SHARED ${X11_Xft_LIB}) + if(LIB_fontconfig) + target_link_libraries(fltk_SHARED ${LIB_fontconfig}) + endif(LIB_fontconfig) endif(USE_XFT) -if(LIB_fontconfig) - target_link_libraries(fltk_SHARED ${LIB_fontconfig}) -endif(LIB_fontconfig) - ####################################################################### -add_library(fltk_forms_SHARED SHARED ${FLCPPFILES}) -target_link_libraries(fltk_forms_SHARED fltk) -set_target_properties(fltk_forms_SHARED - PROPERTIES CLEAN_DIRECT_OUTPUT 1 - VERSION ${FLTK_VERSION_MAJOR}.${FLTK_VERSION_MINOR} - SOVERSION ${FLTK_VERSION_PATCH} -) -if(MSVC) - set_target_properties(fltk_forms_SHARED - PROPERTIES - OUTPUT_NAME fltkformsdll - DEBUG_OUTPUT_NAME fltkformsdlld - COMPILE_DEFINITIONS "FL_DLL;FL_LIBRARY" - ) - if(OPTION_LARGE_FILE) - set_target_properties(fltk_forms_SHARED PROPERTIES LINK_FLAGS /LARGEADDRESSAWARE) - endif(OPTION_LARGE_FILE) -else() - set_target_properties(fltk_forms_SHARED PROPERTIES OUTPUT_NAME fltk_forms) -endif(MSVC) +FL_ADD_LIBRARY(fltk_forms SHARED "${FLCPPFILES}") +target_link_libraries(fltk_forms_SHARED fltk_SHARED) if(USE_THREADS) - target_link_libraries(fltk_SHARED ${CMAKE_THREAD_LIBS_INIT}) + target_link_libraries(fltk_forms_SHARED ${CMAKE_THREAD_LIBS_INIT} ${LIB_dl}) endif(USE_THREADS) if(USE_X11) - target_link_libraries(fltk_SHARED ${X11_LIBRARIES}) + target_link_libraries(fltk_forms_SHARED ${X11_LIBRARIES}) endif(USE_X11) ####################################################################### -add_library(fltk_images_SHARED SHARED ${IMGCPPFILES}) -target_link_libraries(fltk_images_SHARED fltk - ${FLTK_PNG_LIBRARIES} ${FLTK_JPEG_LIBRARIES} ${FLTK_ZLIB_LIBRARIES} -) -set_target_properties(fltk_images_SHARED - PROPERTIES CLEAN_DIRECT_OUTPUT 1 - VERSION ${FLTK_VERSION_MAJOR}.${FLTK_VERSION_MINOR} - SOVERSION ${FLTK_VERSION_PATCH} -) -if(MSVC) - set_target_properties(fltk_images_SHARED - PROPERTIES - OUTPUT_NAME fltkimagesdll - DEBUG_OUTPUT_NAME fltkimagesdlld - COMPILE_DEFINITIONS "FL_DLL;FL_LIBRARY" - ) - if(OPTION_LARGE_FILE) - set_target_properties(fltk_images_SHARED PROPERTIES LINK_FLAGS /LARGEADDRESSAWARE) - endif(OPTION_LARGE_FILE) +FL_ADD_LIBRARY(fltk_images SHARED "${IMGCPPFILES}") +target_link_libraries(fltk_images_SHARED fltk_SHARED) + +if(OPTION_USE_SYSTEM_LIBJPEG) + target_link_libraries(fltk_images_SHARED ${FLTK_JPEG_LIBRARIES}) else() - set_target_properties(fltk_images_SHARED PROPERTIES OUTPUT_NAME fltk_images) -endif(MSVC) + target_link_libraries(fltk_images_SHARED fltk_jpeg_SHARED) +endif(OPTION_USE_SYSTEM_LIBJPEG) -####################################################################### -install(TARGETS fltk_SHARED fltk_forms_SHARED fltk_images_SHARED - EXPORT fltk-install - DESTINATION ${PREFIX_LIB} -) +if(OPTION_USE_SYSTEM_ZLIB) + target_link_libraries(fltk_images_SHARED ${FLTK_ZLIB_LIBRARIES}) +else() + target_link_libraries(fltk_images_SHARED fltk_z_SHARED) +endif(OPTION_USE_SYSTEM_ZLIB) + +if(OPTION_USE_SYSTEM_LIBPNG) + target_link_libraries(fltk_images_SHARED ${FLTK_PNG_LIBRARIES}) +else() + target_link_libraries(fltk_images_SHARED fltk_png_SHARED) +endif(OPTION_USE_SYSTEM_LIBPNG) ####################################################################### if(OPENGL_FOUND) - add_library(fltk_gl_SHARED SHARED ${GLCPPFILES}) - target_link_libraries(fltk_gl_SHARED fltk ${OPENGL_LIBRARIES}) - set_target_properties(fltk_gl_SHARED - PROPERTIES CLEAN_DIRECT_OUTPUT 1 - VERSION ${FLTK_VERSION_MAJOR}.${FLTK_VERSION_MINOR} - SOVERSION ${FLTK_VERSION_PATCH} - ) - if(MSVC) - set_target_properties(fltk_gl_SHARED - PROPERTIES - OUTPUT_NAME fltkgldll - DEBUG_OUTPUT_NAME fltkgldlld - COMPILE_DEFINITIONS "FL_DLL;FL_LIBRARY" - ) - if(OPTION_LARGE_FILE) - set_target_properties(fltk_gl_SHARED PROPERTIES LINK_FLAGS /LARGEADDRESSAWARE) - endif(OPTION_LARGE_FILE) - else() - set_target_properties(fltk_gl_SHARED PROPERTIES OUTPUT_NAME fltk_gl) - endif(MSVC) - - install(TARGETS fltk_gl_SHARED - EXPORT fltk-install - DESTINATION ${PREFIX_LIB} - ) + FL_ADD_LIBRARY(fltk_gl SHARED "${GLCPPFILES}") + target_link_libraries(fltk_gl_SHARED fltk_SHARED ${OPENGL_LIBRARIES}) endif(OPENGL_FOUND) +####################################################################### endif(OPTION_BUILD_SHARED_LIBS) +####################################################################### @@ -1,5 +1,5 @@ // -// "$Id: Fl.cxx 9666 2012-08-16 20:59:36Z matt $" +// "$Id: Fl.cxx 10364 2014-10-08 12:47:20Z ossman $" // // Main event handling code for the Fast Light Tool Kit (FLTK). // @@ -67,20 +67,20 @@ void fl_cleanup_pens(void); void fl_release_dc(HWND,HDC); void fl_cleanup_dc_list(void); #elif defined(__APPLE__) -extern double fl_mac_flush_and_wait(double time_to_wait, char in_idle); +extern double fl_mac_flush_and_wait(double time_to_wait); #endif // WIN32 // // Globals... // #if defined(__APPLE__) || defined(FL_DOXYGEN) -const char *Fl_Mac_App_Menu::about = "About "; +const char *Fl_Mac_App_Menu::about = "About %@"; const char *Fl_Mac_App_Menu::print = "Print Front Window"; const char *Fl_Mac_App_Menu::services = "Services"; -const char *Fl_Mac_App_Menu::hide = "Hide "; +const char *Fl_Mac_App_Menu::hide = "Hide %@"; const char *Fl_Mac_App_Menu::hide_others = "Hide Others"; const char *Fl_Mac_App_Menu::show = "Show All"; -const char *Fl_Mac_App_Menu::quit = "Quit "; +const char *Fl_Mac_App_Menu::quit = "Quit %@"; #endif // __APPLE__ #ifndef FL_DOXYGEN Fl_Widget *Fl::belowmouse_, @@ -104,6 +104,8 @@ int Fl::damage_, char *Fl::e_text = (char *)""; int Fl::e_length; +const char* Fl::e_clipboard_type = ""; +void * Fl::e_clipboard_data = NULL; Fl_Event_Dispatch Fl::e_dispatch = 0; @@ -111,13 +113,16 @@ unsigned char Fl::options_[] = { 0, 0 }; unsigned char Fl::options_read_ = 0; -Fl_Window *fl_xfocus; // which window X thinks has focus +Fl_Window *fl_xfocus = NULL; // which window X thinks has focus Fl_Window *fl_xmousewin;// which window X thinks has FL_ENTER Fl_Window *Fl::grab_; // most recent Fl::grab() Fl_Window *Fl::modal_; // topmost modal() window #endif // FL_DOXYGEN +char const * const Fl::clipboard_plain_text = "text/plain"; +char const * const Fl::clipboard_image = "image"; + // // 'Fl::version()' - Return the API version number... // @@ -220,7 +225,7 @@ int Fl::event_inside(const Fl_Widget *o) /*const*/ { #elif defined(__APPLE__) -// implementation in Fl_mac.cxx +// implementation in Fl_cocoa.mm (was Fl_mac.cxx) #else @@ -430,11 +435,75 @@ static void run_checks() } } -#ifndef WIN32 +#if !defined(WIN32) && !defined(__APPLE__) static char in_idle; #endif //////////////////////////////////////////////////////////////// +// Clipboard notifications + +struct Clipboard_Notify { + Fl_Clipboard_Notify_Handler handler; + void *data; + struct Clipboard_Notify *next; +}; + +static struct Clipboard_Notify *clip_notify_list = NULL; + +extern void fl_clipboard_notify_change(); // in Fl_<platform>.cxx + +void Fl::add_clipboard_notify(Fl_Clipboard_Notify_Handler h, void *data) { + struct Clipboard_Notify *node; + + remove_clipboard_notify(h); + + node = new Clipboard_Notify; + + node->handler = h; + node->data = data; + node->next = clip_notify_list; + + clip_notify_list = node; + + fl_clipboard_notify_change(); +} + +void Fl::remove_clipboard_notify(Fl_Clipboard_Notify_Handler h) { + struct Clipboard_Notify *node, **prev; + + node = clip_notify_list; + prev = &clip_notify_list; + while (node != NULL) { + if (node->handler == h) { + *prev = node->next; + delete node; + + fl_clipboard_notify_change(); + + return; + } + + prev = &node->next; + node = node->next; + } +} + +bool fl_clipboard_notify_empty(void) { + return clip_notify_list == NULL; +} + +void fl_trigger_clipboard_notify(int source) { + struct Clipboard_Notify *node, *next; + + node = clip_notify_list; + while (node != NULL) { + next = node->next; + node->handler(source, node->data); + node = next; + } +} + +//////////////////////////////////////////////////////////////// // wait/run/check/ready: void (*Fl::idle)(); // see Fl::add_idle.cxx for the add/remove functions @@ -456,16 +525,7 @@ double Fl::wait(double time_to_wait) { #elif defined(__APPLE__) run_checks(); - if (idle) { - if (!in_idle) { - in_idle = 1; - idle(); - in_idle = 0; - } - // the idle function may turn off idle, we can then wait: - if (idle) time_to_wait = 0.0; - } - return fl_mac_flush_and_wait(time_to_wait, in_idle); + return fl_mac_flush_and_wait(time_to_wait); #else @@ -530,45 +590,6 @@ int Fl::run() { return 0; } -#ifdef WIN32 - -// Function to initialize COM/OLE for usage. This must be done only once. -// We define a flag to register whether we called it: -static char oleInitialized = 0; - -// This calls the Windows function OleInitialize() exactly once. -void fl_OleInitialize() { - if (!oleInitialized) { - OleInitialize(0L); - oleInitialized = 1; - } -} - -// This calls the Windows function OleUninitialize() only, if -// OleInitialize has been called before. -void fl_OleUninitialize() { - if (oleInitialized) { - OleUninitialize(); - oleInitialized = 0; - } -} - -class Fl_Win32_At_Exit { -public: - Fl_Win32_At_Exit() { } - ~Fl_Win32_At_Exit() { - fl_free_fonts(); // do some WIN32 cleanup - fl_cleanup_pens(); - fl_OleUninitialize(); - fl_brush_action(1); - fl_cleanup_dc_list(); - } -}; -static Fl_Win32_At_Exit win32_at_exit; -#endif - - - /** Waits until "something happens" and then returns. Call this repeatedly to "run" your program. You can also check what happened @@ -828,6 +849,83 @@ static int send_handlers(int e) { return 0; } + +//////////////////////////////////////////////////////////////// +// System event handlers: + + +struct system_handler_link { + Fl_System_Handler handle; + void *data; + system_handler_link *next; +}; + + +static system_handler_link *sys_handlers = 0; + + +/** + \brief Install a function to intercept system events. + + FLTK calls each of these functions as soon as a new system event is + received. The processing will stop at the first function to return + non-zero. If all functions return zero then the event is passed on + for normal handling by FLTK. + + Each function will be called with a pointer to the system event as + the first argument and \p data as the second argument. The system + event pointer will always be void *, but will point to different + objects depending on the platform: + - X11: XEvent + - Windows: MSG + - OS X: NSEvent + + \param ha The event handler function to register + \param data User data to include on each call + + \see Fl::remove_system_handler(Fl_System_Handler) +*/ +void Fl::add_system_handler(Fl_System_Handler ha, void *data) { + system_handler_link *l = new system_handler_link; + l->handle = ha; + l->data = data; + l->next = sys_handlers; + sys_handlers = l; +} + + +/** + Removes a previously added system event handler. + + \param ha The event handler function to remove + + \see Fl::add_system_handler(Fl_System_Handler) +*/ +void Fl::remove_system_handler(Fl_System_Handler ha) { + system_handler_link *l, *p; + + // Search for the handler in the list... + for (l = sys_handlers, p = 0; l && l->handle != ha; p = l, l = l->next); + + if (l) { + // Found it, so remove it from the list... + if (p) p->next = l->next; + else sys_handlers = l->next; + + // And free the record... + delete l; + } +} + +int fl_send_system_handlers(void *e) { + for (const system_handler_link *hl = sys_handlers; hl; hl = hl->next) { + if (hl->handle(e, hl->data)) + return 1; + } + return 0; +} + + //////////////////////////////////////////////////////////////// Fl_Widget* fl_oldfocus; // kludge for Fl_Group... @@ -862,10 +960,18 @@ void Fl::focus(Fl_Widget *o) { if (fl_xfocus != win) { Fl_X *x = Fl_X::i(win); if (x) x->set_key_window(); - } + } +#elif defined(USE_X11) + if (fl_xfocus != win) { + Fl_X *x = Fl_X::i(win); + if (!Fl_X::ewmh_supported()) + win->show(); // Old WMs, XMapRaised + else if (x) // New WMs use the NETWM attribute: + Fl_X::activate_window(x->xid); + } #endif fl_xfocus = win; - } + } } // take focus from the old focused window fl_oldfocus = 0; @@ -1357,11 +1463,38 @@ int Fl::handle_(int e, Fl_Window* window) //////////////////////////////////////////////////////////////// // hide() destroys the X window, it does not do unmap! -#if !defined(WIN32) && USE_XFT +#if defined(WIN32) +extern void fl_clipboard_notify_retarget(HWND wnd); +extern void fl_update_clipboard(void); +#elif USE_XFT extern void fl_destroy_xft_draw(Window); #endif void Fl_Window::hide() { +#ifdef WIN32 + // STR#3079: if there remains a window and a non-modal window, and the window is deleted, + // the app remains running without any apparent window. + // Bug mechanism: hiding an owner window unmaps the owned (non-modal) window(s) + // but does not delete it(them) in FLTK. + // Fix for it: + // when hiding a window, build list of windows it owns, and do hide/show on them. + int count = 0; + Fl_Window *win, **doit = NULL; + for (win = Fl::first_window(); win && i; win = Fl::next_window(win)) { + if (win->non_modal() && GetWindow(fl_xid(win), GW_OWNER) == i->xid) { + count++; + } + } + if (count) { + doit = new Fl_Window*[count]; + count = 0; + for (win = Fl::first_window(); win && i; win = Fl::next_window(win)) { + if (win->non_modal() && GetWindow(fl_xid(win), GW_OWNER) == i->xid) { + doit[count++] = win; + } + } + } +#endif clear_visible(); if (!shown()) return; @@ -1402,16 +1535,14 @@ void Fl_Window::hide() { handle(FL_HIDE); #if defined(WIN32) + // make sure any custom icons get freed + icons(NULL, 0); // this little trick keeps the current clipboard alive, even if we are about // to destroy the window that owns the selection. - if (GetClipboardOwner()==ip->xid) { - Fl_Window *w1 = Fl::first_window(); - if (w1 && OpenClipboard(fl_xid(w1))) { - EmptyClipboard(); - SetClipboardData(CF_TEXT, NULL); - CloseClipboard(); - } - } + if (GetClipboardOwner()==ip->xid) + fl_update_clipboard(); + // Make sure we unlink this window from the clipboard chain + fl_clipboard_notify_retarget(ip->xid); // Send a message to myself so that I'll get out of the event loop... PostMessage(ip->xid, WM_APP, 0, 0); if (ip->private_dc) fl_release_dc(ip->xid, ip->private_dc); @@ -1445,6 +1576,12 @@ void Fl_Window::hide() { ShowWindow(p, SW_SHOWNA); } XDestroyWindow(fl_display, ip->xid); + // end of fix for STR#3079 + for (int ii = 0; ii < count; ii++) { + doit[ii]->hide(); + doit[ii]->show(); + } + if (count) delete[] doit; #elif defined(__APPLE_QUARTZ__) ip->destroy(); #else @@ -1459,12 +1596,6 @@ void Fl_Window::hide() { delete ip; } -Fl_Window::~Fl_Window() { - hide(); - if (xclass_) { - free(xclass_); - } -} // FL_SHOW and FL_HIDE are called whenever the visibility of this widget // or any parent changes. We must correctly map/unmap the system's window. @@ -1551,12 +1682,23 @@ void Fl::selection(Fl_Widget &owner, const char* text, int len) { /** Backward compatibility only. This calls Fl::paste(receiver, 0); - \see Fl::paste(Fl_Widget &receiver, int clipboard) + \see Fl::paste(Fl_Widget &receiver, int clipboard, const char* type) */ void Fl::paste(Fl_Widget &receiver) { Fl::paste(receiver, 0); } +#if FLTK_ABI_VERSION >= 10303 +#elif !defined(FL_DOXYGEN) +void Fl::paste(Fl_Widget &receiver, int source) +{ + Fl::paste(receiver, source, Fl::clipboard_plain_text); +} + +void Fl::copy(const char* stuff, int len, int destination) { + Fl::copy(stuff, len, destination, Fl::clipboard_plain_text); +} +#endif //////////////////////////////////////////////////////////////// #include <FL/fl_draw.H> @@ -1696,6 +1838,7 @@ void Fl_Widget::damage(uchar fl, int X, int Y, int W, int H) { Fl::damage(FL_DAMAGE_CHILD); } void Fl_Window::flush() { + if (!shown()) return; make_current(); //if (damage() == FL_DAMAGE_EXPOSE && can_boxcheat(box())) fl_boxcheat = this; fl_clip_region(i->region); i->region = 0; @@ -1931,6 +2074,14 @@ void Fl::clear_widget_pointer(Fl_Widget const *w) There should be an application that manages options system wide, per user, and per application. + Example: + \code + if ( Fl::option(Fl::OPTION_ARROW_FOCUS) ) + { ..on.. } + else + { ..off.. } + \endcode + \note As of FLTK 1.3.0, options can be managed within fluid, using the menu <i>Edit/Global FLTK Settings</i>. @@ -1960,6 +2111,8 @@ bool Fl::option(Fl_Option opt) options_[OPTION_DND_TEXT] = tmp; opt_prefs.get("ShowTooltips", tmp, 1); // default: on options_[OPTION_SHOW_TOOLTIPS] = tmp; + opt_prefs.get("FNFCUsesGTK", tmp, 1); // default: on + options_[OPTION_FNFC_USES_GTK] = tmp; } { // next, check the user preferences // override system options only, if the option is set ( >= 0 ) @@ -1977,6 +2130,8 @@ bool Fl::option(Fl_Option opt) if (tmp >= 0) options_[OPTION_DND_TEXT] = tmp; opt_prefs.get("ShowTooltips", tmp, -1); if (tmp >= 0) options_[OPTION_SHOW_TOOLTIPS] = tmp; + opt_prefs.get("FNFCUsesGTK", tmp, -1); + if (tmp >= 0) options_[OPTION_FNFC_USES_GTK] = tmp; } { // now, if the developer has registered this app, we could as for per-application preferences } @@ -1992,6 +2147,12 @@ bool Fl::option(Fl_Option opt) This function does not change any system or user settings. + Example: + \code + Fl::option(Fl::OPTION_ARROW_FOCUS, true); // on + Fl::option(Fl::OPTION_ARROW_FOCUS, false); // off + \endcode + \param opt which option \param val set to true or false \see enum Fl::Fl_Option @@ -2030,5 +2191,5 @@ Fl_Widget_Tracker::~Fl_Widget_Tracker() // -// End of "$Id: Fl.cxx 9666 2012-08-16 20:59:36Z matt $". +// End of "$Id: Fl.cxx 10364 2014-10-08 12:47:20Z ossman $". // diff --git a/src/Fl_Bitmap.cxx b/src/Fl_Bitmap.cxx index 01fb41a..67a2905 100644 --- a/src/Fl_Bitmap.cxx +++ b/src/Fl_Bitmap.cxx @@ -1,5 +1,5 @@ // -// "$Id: Fl_Bitmap.cxx 9293 2012-03-18 18:48:29Z manolo $" +// "$Id: Fl_Bitmap.cxx 10132 2014-04-28 09:17:12Z manolo $" // // Bitmap drawing routines for the Fast Light Tool Kit (FLTK). // @@ -243,35 +243,39 @@ void Fl_Bitmap::draw(int XP, int YP, int WP, int HP, int cx, int cy) { fl_graphics_driver->draw(this, XP, YP, WP, HP, cx, cy); } -static int start(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int w, int h, int &cx, int &cy, +int Fl_Bitmap::start(int XP, int YP, int WP, int HP, int &cx, int &cy, int &X, int &Y, int &W, int &H) { + if (!array) { + draw_empty(XP, YP); + return 1; + } // account for current clip region (faster on Irix): fl_clip_box(XP,YP,WP,HP,X,Y,W,H); cx += X-XP; cy += Y-YP; // clip the box down to the size of image, quit if empty: if (cx < 0) {W += cx; X -= cx; cx = 0;} - if (cx+W > w) W = w-cx; + if (cx+W > w()) W = w()-cx; if (W <= 0) return 1; if (cy < 0) {H += cy; Y -= cy; cy = 0;} - if (cy+H > h) H = h-cy; + if (cy+H > h()) H = h()-cy; if (H <= 0) return 1; +#if defined(WIN32) + if (!id_) id_ = fl_create_bitmap(w(), h(), array); +#else + if (!id_) id_ = fl_create_bitmask(w(), h(), array); +#endif return 0; } #ifdef __APPLE__ void Fl_Quartz_Graphics_Driver::draw(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int cx, int cy) { int X, Y, W, H; - if (!bm->array) { - bm->draw_empty(XP, YP); + if (bm->start(XP, YP, WP, HP, cx, cy, X, Y, W, H)) { return; } - if (start(bm, XP, YP, WP, HP, bm->w(), bm->h(), cx, cy, X, Y, W, H)) { - return; - } - if (!bm->id_) bm->id_ = fl_create_bitmask(bm->w(), bm->h(), bm->array); if (bm->id_ && fl_gc) { - CGRect rect = { { X, Y }, { W, H } }; + CGRect rect = { { (CGFloat)X, (CGFloat)Y }, { (CGFloat)W, (CGFloat)H } }; Fl_X::q_begin_image(rect, cx, cy, bm->w(), bm->h()); CGContextDrawImage(fl_gc, rect, (CGImageRef)bm->id_); Fl_X::q_end_image(); @@ -281,60 +285,62 @@ void Fl_Quartz_Graphics_Driver::draw(Fl_Bitmap *bm, int XP, int YP, int WP, int #elif defined(WIN32) void Fl_GDI_Graphics_Driver::draw(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int cx, int cy) { int X, Y, W, H; - if (!bm->array) { - bm->draw_empty(XP, YP); + if (bm->start(XP, YP, WP, HP, cx, cy, X, Y, W, H)) { return; } - if (start(bm, XP, YP, WP, HP, bm->w(), bm->h(), cx, cy, X, Y, W, H)) { + + HDC tempdc = CreateCompatibleDC(fl_gc); + int save = SaveDC(tempdc); + SelectObject(tempdc, (HGDIOBJ)bm->id_); + SelectObject(fl_gc, fl_brush()); + // secret bitblt code found in old MSWindows reference manual: + BitBlt(fl_gc, X, Y, W, H, tempdc, cx, cy, 0xE20746L); + RestoreDC(tempdc, save); + DeleteDC(tempdc); +} + +void Fl_GDI_Printer_Graphics_Driver::draw(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int cx, int cy) { + int X, Y, W, H; + typedef BOOL (WINAPI* fl_transp_func) (HDC,int,int,int,int,HDC,int,int,int,int,UINT); + static fl_transp_func fl_TransparentBlt = NULL; + static HMODULE hMod = NULL; + if (!hMod) { + hMod = LoadLibrary("MSIMG32.DLL"); + if (hMod) fl_TransparentBlt = (fl_transp_func)GetProcAddress(hMod, "TransparentBlt"); + } + if (!fl_TransparentBlt) { + Fl_GDI_Graphics_Driver::draw(bm, XP, YP, WP, HP, cx, cy); + return; + } + if (bm->start(XP, YP, WP, HP, cx, cy, X, Y, W, H)) { return; } - if (!bm->id_) bm->id_ = fl_create_bitmap(bm->w(), bm->h(), bm->array); - typedef BOOL (WINAPI* fl_transp_func) (HDC,int,int,int,int,HDC,int,int,int,int,UINT); - static fl_transp_func fl_TransparentBlt; HDC tempdc; int save; - BOOL use_print_algo = false; - if (Fl_Surface_Device::surface() != Fl_Display_Device::display_device()) { - static HMODULE hMod = NULL; - if (!hMod) { - hMod = LoadLibrary("MSIMG32.DLL"); - if (hMod) fl_TransparentBlt = (fl_transp_func)GetProcAddress(hMod, "TransparentBlt"); - } - if (fl_TransparentBlt) use_print_algo = true; - } - if (use_print_algo) { // algorithm for bitmap output to Fl_GDI_Printer - Fl_Color save_c = fl_color(); // save bitmap's desired color - uchar r, g, b; - Fl::get_color(save_c, r, g, b); - r = 255-r; - g = 255-g; - b = 255-b; - Fl_Color background = fl_rgb_color(r, g, b); // a color very different from the bitmap's - Fl_Offscreen tmp_id = fl_create_offscreen(W, H); - fl_begin_offscreen(tmp_id); - fl_color(background); - fl_rectf(0,0,W,H); // use this color as offscreen background - fl_color(save_c); // back to bitmap's color - tempdc = CreateCompatibleDC(fl_gc); - save = SaveDC(tempdc); - SelectObject(tempdc, (HGDIOBJ)bm->id_); - SelectObject(fl_gc, fl_brush()); // use bitmap's desired color - BitBlt(fl_gc, 0, 0, W, H, tempdc, 0, 0, 0xE20746L); // draw bitmap to offscreen - fl_end_offscreen(); // offscreen data is in tmp_id - SelectObject(tempdc, (HGDIOBJ)tmp_id); // use offscreen data - // draw it to printer context with background color as transparent - fl_TransparentBlt(fl_gc, X,Y,W,H, tempdc, cx, cy, bm->w(), bm->h(), RGB(r, g, b) ); - fl_delete_offscreen(tmp_id); - } - else { // algorithm for bitmap output to display - tempdc = CreateCompatibleDC(fl_gc); - save = SaveDC(tempdc); - SelectObject(tempdc, (HGDIOBJ)bm->id_); - SelectObject(fl_gc, fl_brush()); - // secret bitblt code found in old MSWindows reference manual: - BitBlt(fl_gc, X, Y, W, H, tempdc, cx, cy, 0xE20746L); - } + // algorithm for bitmap output to Fl_GDI_Printer + Fl_Color save_c = fl_color(); // save bitmap's desired color + uchar r, g, b; + Fl::get_color(save_c, r, g, b); + r = 255-r; + g = 255-g; + b = 255-b; + Fl_Color background = fl_rgb_color(r, g, b); // a color very different from the bitmap's + Fl_Offscreen tmp_id = fl_create_offscreen(W, H); + fl_begin_offscreen(tmp_id); + fl_color(background); + fl_rectf(0,0,W,H); // use this color as offscreen background + fl_color(save_c); // back to bitmap's color + tempdc = CreateCompatibleDC(fl_gc); + save = SaveDC(tempdc); + SelectObject(tempdc, (HGDIOBJ)bm->id_); + SelectObject(fl_gc, fl_brush()); // use bitmap's desired color + BitBlt(fl_gc, 0, 0, W, H, tempdc, 0, 0, 0xE20746L); // draw bitmap to offscreen + fl_end_offscreen(); // offscreen data is in tmp_id + SelectObject(tempdc, (HGDIOBJ)tmp_id); // use offscreen data + // draw it to printer context with background color as transparent + fl_TransparentBlt(fl_gc, X,Y,W,H, tempdc, cx, cy, bm->w(), bm->h(), RGB(r, g, b) ); + fl_delete_offscreen(tmp_id); RestoreDC(tempdc, save); DeleteDC(tempdc); } @@ -342,14 +348,9 @@ void Fl_GDI_Graphics_Driver::draw(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, #else // Xlib void Fl_Xlib_Graphics_Driver::draw(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int cx, int cy) { int X, Y, W, H; - if (!bm->array) { - bm->draw_empty(XP, YP); - return; - } - if (start(bm, XP, YP, WP, HP, bm->w(), bm->h(), cx, cy, X, Y, W, H)) { + if (bm->start(XP, YP, WP, HP, cx, cy, X, Y, W, H)) { return; } - if (!bm->id_) bm->id_ = fl_create_bitmask(bm->w(), bm->h(), bm->array); XSetStipple(fl_display, fl_gc, bm->id_); int ox = X-cx; if (ox < 0) ox += bm->w(); @@ -469,5 +470,5 @@ Fl_Image *Fl_Bitmap::copy(int W, int H) { // -// End of "$Id: Fl_Bitmap.cxx 9293 2012-03-18 18:48:29Z manolo $". +// End of "$Id: Fl_Bitmap.cxx 10132 2014-04-28 09:17:12Z manolo $". // diff --git a/src/Fl_Button.cxx b/src/Fl_Button.cxx index e75621b..145c80d 100644 --- a/src/Fl_Button.cxx +++ b/src/Fl_Button.cxx @@ -1,12 +1,12 @@ // -// "$Id: Fl_Button.cxx 9637 2012-07-24 04:37:22Z matt $" +// "$Id: Fl_Button.cxx 10386 2014-10-19 20:17:17Z AlbrechtS $" // // Button widget for the Fast Light Tool Kit (FLTK). // -// Copyright 1998-2010 by Bill Spitzak and others. +// Copyright 1998-2014 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in -// the file "COPYING" which should have been included with this file. If this +// the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // http://www.fltk.org/COPYING.php @@ -89,12 +89,12 @@ int Fl_Button::handle(int event) { return 1; case FL_PUSH: if (Fl::visible_focus() && handle(FL_FOCUS)) Fl::focus(this); + /* FALLTHROUGH */ case FL_DRAG: if (Fl::event_inside(this)) { if (type() == FL_RADIO_BUTTON) newval = 1; else newval = !oldval; - } else - { + } else { clear_changed(); newval = oldval; } @@ -126,10 +126,10 @@ int Fl_Button::handle(int event) { return 1; case FL_SHORTCUT: if (!(shortcut() ? - Fl::test_shortcut(shortcut()) : test_shortcut())) return 0; + Fl::test_shortcut(shortcut()) : test_shortcut())) return 0; if (Fl::visible_focus() && handle(FL_FOCUS)) Fl::focus(this); goto triggered_by_keyboard; - case FL_FOCUS : /* FALLTHROUGH */ + case FL_FOCUS : case FL_UNFOCUS : if (Fl::visible_focus()) { if (box() == FL_NO_BOX) { @@ -142,6 +142,7 @@ int Fl_Button::handle(int event) { } else redraw(); return 1; } else return 0; + /* NOTREACHED */ case FL_KEYBOARD : if (Fl::focus() == this && Fl::event_key() == ' ' && !(Fl::event_state() & (FL_SHIFT | FL_CTRL | FL_ALT | FL_META))) { @@ -174,7 +175,7 @@ void Fl_Button::simulate_key_action() Fl::remove_timeout(key_release_timeout, key_release_tracker); key_release_timeout(key_release_tracker); } - value(1); + value(1); redraw(); key_release_tracker = new Fl_Widget_Tracker(this); Fl::add_timeout(0.15, key_release_timeout, key_release_tracker); @@ -185,7 +186,7 @@ void Fl_Button::key_release_timeout(void *d) Fl_Widget_Tracker *wt = (Fl_Widget_Tracker*)d; if (!wt) return; - if (wt==key_release_tracker) + if (wt==key_release_tracker) key_release_tracker = 0L; Fl_Button *btn = (Fl_Button*)wt->widget(); if (btn) { @@ -196,7 +197,16 @@ void Fl_Button::key_release_timeout(void *d) } /** - The constructor creates the button using the given position, size and label. + The constructor creates the button using the given position, size, and label. + + The default box type is box(FL_UP_BOX). + + You can control how the button is drawn when ON by setting down_box(). + The default is FL_NO_BOX (0) which will select an appropriate box type + using the normal (OFF) box type by using fl_down(box()). + + Derived classes may handle this differently. + \param[in] X, Y, W, H position and size of the widget \param[in] L widget label, default is no label */ @@ -209,20 +219,34 @@ Fl_Button::Fl_Button(int X, int Y, int W, int H, const char *L) set_flag(SHORTCUT_LABEL); } +/** + The constructor creates the button using the given position, size, and label. + + The Button type() is set to FL_RADIO_BUTTON. + \param[in] X, Y, W, H position and size of the widget + \param[in] L widget label, default is no label + */ Fl_Radio_Button::Fl_Radio_Button(int X,int Y,int W,int H,const char *L) : Fl_Button(X, Y, W, H, L) { type(FL_RADIO_BUTTON); } +/** + The constructor creates the button using the given position, size, and label. + + The Button type() is set to FL_TOGGLE_BUTTON. -Fl_Toggle_Button::Fl_Toggle_Button(int X,int Y,int W,int H,const char *l) -: Fl_Button(X,Y,W,H,l) + \param[in] X, Y, W, H position and size of the widget + \param[in] L widget label, default is no label + */ +Fl_Toggle_Button::Fl_Toggle_Button(int X,int Y,int W,int H,const char *L) +: Fl_Button(X,Y,W,H,L) { type(FL_TOGGLE_BUTTON); } // -// End of "$Id: Fl_Button.cxx 9637 2012-07-24 04:37:22Z matt $". +// End of "$Id: Fl_Button.cxx 10386 2014-10-19 20:17:17Z AlbrechtS $". // diff --git a/src/Fl_Check_Button.cxx b/src/Fl_Check_Button.cxx index 2da2e99..e42cac1 100644 --- a/src/Fl_Check_Button.cxx +++ b/src/Fl_Check_Button.cxx @@ -1,12 +1,12 @@ // -// "$Id: Fl_Check_Button.cxx 8864 2011-07-19 04:49:30Z greg.ercolano $" +// "$Id: Fl_Check_Button.cxx 10386 2014-10-19 20:17:17Z AlbrechtS $" // // Check button widget for the Fast Light Tool Kit (FLTK). // -// Copyright 1998-2010 by Bill Spitzak and others. +// Copyright 1998-2014 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in -// the file "COPYING" which should have been included with this file. If this +// the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // http://www.fltk.org/COPYING.php @@ -19,14 +19,32 @@ #include <FL/Fl.H> #include <FL/Fl_Check_Button.H> -// TODO Correct incorrect Fl_Check_Button comments. -// A subclass of Fl_Button that always draws as a diamond box. This -// diamond is smaller than the widget size and can be surchecked by -// another box type, for compatibility with Forms. +/** + \class Fl_Check_Button + \brief A button with a "checkmark" to show its status. + + \image html Fl_Check_Button.png + \image latex Fl_Check_Button.png "Fl_Check_Button" width=4cm + + Buttons generate callbacks when they are clicked by the user. You control + exactly when and how by changing the values for type() and when(). + + The Fl_Check_Button subclass displays its "ON" state by showing a "checkmark" + rather than drawing itself pushed in. + */ /** - Creates a new Fl_Check_Button widget using the given position, size and - label string. + Creates a new Fl_Check_Button widget using the given position, size, and label string. + + The default box type is FL_NO_BOX, which draws the label w/o a box + right of the checkmark. + + The selection_color() sets the color of the checkmark. + Default is FL_FOREGROUND_COLOR (usually black). + + You can use down_box() to change the box type of the checkmark. + Default is FL_DOWN_BOX. + \param[in] X, Y, W, H position and size of the widget \param[in] L widget label, default is no label */ diff --git a/src/Fl_Color_Chooser.cxx b/src/Fl_Color_Chooser.cxx index bfcc682..4b4ce1d 100644 --- a/src/Fl_Color_Chooser.cxx +++ b/src/Fl_Color_Chooser.cxx @@ -1,5 +1,5 @@ // -// "$Id: Fl_Color_Chooser.cxx 9673 2012-08-18 10:47:48Z AlbrechtS $" +// "$Id: Fl_Color_Chooser.cxx 10234 2014-08-21 12:18:32Z cand $" // // Color chooser for the Fast Light Tool Kit (FLTK). // @@ -91,7 +91,7 @@ enum { M_HEX, /**< mode() of Fl_Color_Chooser showing hex values */ M_HSV /**< mode() of Fl_Color_Chooser showing HSV values */ }; -static Fl_Menu_Item mode_menu[] = { +static const Fl_Menu_Item mode_menu[] = { {"rgb"}, {"byte"}, {"hex"}, @@ -619,5 +619,5 @@ int fl_color_chooser(const char* name, uchar& r, uchar& g, uchar& b, int cmode) /** @} */ // -// End of "$Id: Fl_Color_Chooser.cxx 9673 2012-08-18 10:47:48Z AlbrechtS $". +// End of "$Id: Fl_Color_Chooser.cxx 10234 2014-08-21 12:18:32Z cand $". // diff --git a/src/Fl_Copy_Surface.cxx b/src/Fl_Copy_Surface.cxx new file mode 100644 index 0000000..ecb8ebc --- /dev/null +++ b/src/Fl_Copy_Surface.cxx @@ -0,0 +1,399 @@ +// +// "$Id: Fl_Copy_Surface.cxx 10209 2014-06-26 16:14:42Z manolo $" +// +// Copy-to-clipboard code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2014 by Bill Spitzak and others. +// +// This library is free software. Distribution and use rights are outlined in +// the file "COPYING" which should have been included with this file. If this +// file is missing or damaged, see the license at: +// +// http://www.fltk.org/COPYING.php +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <FL/Fl_Copy_Surface.H> +#include <FL/Fl.H> + + +#if defined(__APPLE__) +#include <ApplicationServices/ApplicationServices.h> +#if defined(__ppc__) +#include <QuickTime/QuickTimeComponents.h> +#endif // __ppc__ + +Fl_Quartz_Surface_::Fl_Quartz_Surface_(int w, int h) : Fl_System_Printer(), width(w), height(h) { +} + +int Fl_Quartz_Surface_::printable_rect(int *w, int *h) { + *w = width; + *h = height; + return 0; +} + +const char *Fl_Quartz_Surface_::class_id = "Fl_Quartz_Surface_"; + +#elif defined(WIN32) + +Fl_GDI_Surface_::Fl_GDI_Surface_() : Fl_Paged_Device() { + driver(new Fl_GDI_Graphics_Driver); + depth = 0; +} + +Fl_GDI_Surface_::~Fl_GDI_Surface_() { + delete driver(); +} + +void Fl_GDI_Surface_::translate(int x, int y) { + GetWindowOrgEx(fl_gc, origins+depth); + SetWindowOrgEx(fl_gc, origins[depth].x - x, origins[depth].y - y, NULL); + if (depth < sizeof(origins)/sizeof(POINT)) depth++; + else Fl::warning("Fl_GDI_Surface_: translate stack overflow!"); +} + +void Fl_GDI_Surface_::untranslate() { + if (depth > 0) depth--; + SetWindowOrgEx(fl_gc, origins[depth].x, origins[depth].y, NULL); +} + +const char *Fl_GDI_Surface_::class_id = "Fl_GDI_Surface_"; + +#endif + + +const char *Fl_Copy_Surface::class_id = "Fl_Copy_Surface"; + +/** Constructor. + \param w and \param h are the width and height of the clipboard surface + in pixels where drawing will occur. + */ +Fl_Copy_Surface::Fl_Copy_Surface(int w, int h) : Fl_Surface_Device(NULL) +{ + width = w; + height = h; +#ifdef __APPLE__ + helper = new Fl_Quartz_Surface_(width, height); + driver(helper->driver()); + prepare_copy_pdf_and_tiff(w, h); + oldgc = fl_gc; +#elif defined(WIN32) + helper = new Fl_GDI_Surface_(); + driver(helper->driver()); + oldgc = fl_gc; + // exact computation of factor from screen units to EnhMetaFile units (0.01 mm) + HDC hdc = GetDC(NULL); + int hmm = GetDeviceCaps(hdc, HORZSIZE); + int hdots = GetDeviceCaps(hdc, HORZRES); + int vmm = GetDeviceCaps(hdc, VERTSIZE); + int vdots = GetDeviceCaps(hdc, VERTRES); + ReleaseDC(NULL, hdc); + float factorw = (100. * hmm) / hdots; + float factorh = (100. * vmm) / vdots + 0.5; + + RECT rect; rect.left = 0; rect.top = 0; rect.right = w * factorw; rect.bottom = h * factorh; + gc = CreateEnhMetaFile (NULL, NULL, &rect, NULL); + if (gc != NULL) { + SetTextAlign(gc, TA_BASELINE|TA_LEFT); + SetBkMode(gc, TRANSPARENT); + } +#else // Xlib + helper = new Fl_Xlib_Surface_(); + driver(helper->driver()); + Fl::first_window()->make_current(); + oldwindow = fl_xid(Fl::first_window()); + xid = fl_create_offscreen(w,h); + Fl_Surface_Device *present_surface = Fl_Surface_Device::surface(); + set_current(); + fl_color(FL_WHITE); + fl_rectf(0, 0, w, h); + present_surface->set_current(); +#endif +} + +/** Destructor. + */ +Fl_Copy_Surface::~Fl_Copy_Surface() +{ +#ifdef __APPLE__ + complete_copy_pdf_and_tiff(); + fl_gc = oldgc; + delete (Fl_Quartz_Surface_*)helper; +#elif defined(WIN32) + if(oldgc == fl_gc) oldgc = NULL; + HENHMETAFILE hmf = CloseEnhMetaFile (gc); + if ( hmf != NULL ) { + if ( OpenClipboard (NULL) ){ + EmptyClipboard (); + SetClipboardData (CF_ENHMETAFILE, hmf); + CloseClipboard (); + } + DeleteEnhMetaFile(hmf); + } + DeleteDC(gc); + fl_gc = oldgc; + delete (Fl_GDI_Surface_*)helper; +#else // Xlib + fl_pop_clip(); + unsigned char *data = fl_read_image(NULL,0,0,width,height,0); + fl_window = oldwindow; + _ss->set_current(); + Fl::copy_image(data,width,height,1); + delete[] data; + fl_delete_offscreen(xid); + delete (Fl_Xlib_Surface_*)helper; +#endif +} + +/** Copies a widget in the clipboard + + \param widget any FLTK widget (e.g., standard, custom, window, GL view) to copy + \param delta_x and \param delta_y give + the position in the clipboard of the top-left corner of the widget + */ +void Fl_Copy_Surface::draw(Fl_Widget* widget, int delta_x, int delta_y) +{ + helper->print_widget(widget, delta_x, delta_y); +} + +void Fl_Copy_Surface::set_current() +{ +#if defined(__APPLE__) || defined(WIN32) + fl_gc = gc; + fl_window = (Window)1; + Fl_Surface_Device::set_current(); +#else + fl_window=xid; + _ss = Fl_Surface_Device::surface(); + Fl_Surface_Device::set_current(); + fl_push_no_clip(); +#endif +} + + +#if defined(__APPLE__) + +size_t Fl_Copy_Surface::MyPutBytes(void* info, const void* buffer, size_t count) + { + CFDataAppendBytes ((CFMutableDataRef) info, (const UInt8 *)buffer, count); + return count; +} + +void Fl_Copy_Surface::init_PDF_context(int w, int h) +{ + CGRect bounds = CGRectMake(0, 0, w, h ); + pdfdata = CFDataCreateMutable(NULL, 0); + CGDataConsumerRef myconsumer; +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1040 + if(CGDataConsumerCreateWithCFData != NULL) { + myconsumer = CGDataConsumerCreateWithCFData(pdfdata); // 10.4 + } + else +#endif + { + static CGDataConsumerCallbacks callbacks = { Fl_Copy_Surface::MyPutBytes, NULL }; + myconsumer = CGDataConsumerCreate ((void*) pdfdata, &callbacks); + } + gc = CGPDFContextCreate (myconsumer, &bounds, NULL); + CGDataConsumerRelease (myconsumer); +} + +void Fl_Copy_Surface::prepare_copy_pdf_and_tiff(int w, int h) +{ + init_PDF_context(w, h); + if (gc == NULL) return; + CGRect bounds = CGRectMake(0, 0, w, h ); + CGContextBeginPage (gc, &bounds); + CGContextTranslateCTM(gc, 0, h); + CGContextScaleCTM(gc, 1.0f, -1.0f); + CGContextSaveGState(gc); +} + + +void Fl_Copy_Surface::complete_copy_pdf_and_tiff() +{ + CGContextRestoreGState(gc); + CGContextEndPage(gc); + CGContextRelease(gc); + PasteboardRef clipboard = NULL; + PasteboardCreate(kPasteboardClipboard, &clipboard); + PasteboardClear(clipboard); // first, copy PDF to clipboard + PasteboardPutItemFlavor (clipboard, (PasteboardItemID)1, + CFSTR("com.adobe.pdf"), // kUTTypePDF + pdfdata, kPasteboardFlavorNoFlags); + //second, transform this PDF to a bitmap image and put it as tiff in clipboard + CGDataProviderRef prov; +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1040 + if(fl_mac_os_version >= 100400) + prov = CGDataProviderCreateWithCFData(pdfdata); // 10.4 + else +#endif + prov = CGDataProviderCreateWithData(NULL, CFDataGetBytePtr(pdfdata), CFDataGetLength(pdfdata), NULL); + CGPDFDocumentRef pdfdoc = CGPDFDocumentCreateWithProvider(prov); + CGPDFPageRef pdfpage = CGPDFDocumentGetPage(pdfdoc, 1); + CGDataProviderRelease(prov); + CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB(); + void *mem = ( fl_mac_os_version >= 100600 ? NULL : malloc(width * height * 4) ); + gc = CGBitmapContextCreate(mem, width, height, 8, width * 4, space, kCGImageAlphaNoneSkipLast); + CFRelease(space); + if (gc == NULL) { if (mem) free(mem); return; } + CGRect rect = CGRectMake(0, 0, width, height); + CGContextSetRGBFillColor(gc, 1,1,1,1);//need to clear background + CGContextFillRect(gc, rect); +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 + CGContextDrawPDFPage(gc, pdfpage); // requires 10.3 +#endif + CGPDFDocumentRelease(pdfdoc); + CFRelease(pdfdata); + PasteboardPutItemFlavor(clipboard, (PasteboardItemID)1, CFSTR("public.tiff"), + Fl_X::CGBitmapContextToTIFF(gc), kPasteboardFlavorNoFlags); + CFRelease(clipboard); + CGContextRelease(gc); + if (mem) free(mem); +} + +#endif // __APPLE__ + +#if !(defined(__APPLE__) || defined(WIN32) || defined(FL_DOXYGEN)) +/* graphics driver that translates all graphics coordinates before calling Xlib */ +class Fl_translated_Xlib_Graphics_Driver_ : public Fl_Xlib_Graphics_Driver { + int offset_x, offset_y; // translation between user and graphical coordinates: graphical = user + offset + unsigned depth; // depth of translation stack + int stack_x[20], stack_y[20]; // translation stack allowing cumulative translations +public: + static const char *class_id; + const char *class_name() {return class_id;}; + Fl_translated_Xlib_Graphics_Driver_() { + offset_x = 0; offset_y = 0; + depth = 0; + } + virtual ~Fl_translated_Xlib_Graphics_Driver_() {}; + void translate_all(int dx, int dy) { // reversibly adds dx,dy to the offset between user and graphical coordinates + stack_x[depth] = offset_x; + stack_y[depth] = offset_y; + offset_x = stack_x[depth] + dx; + offset_y = stack_y[depth] + dy; + push_matrix(); + translate(dx, dy); + if (depth < sizeof(stack_x)/sizeof(int)) depth++; + else Fl::warning("%s: translate stack overflow!", class_id); + } + void untranslate_all() { // undoes previous translate_all() + if (depth > 0) depth--; + offset_x = stack_x[depth]; + offset_y = stack_y[depth]; + pop_matrix(); + } + void rect(int x, int y, int w, int h) { Fl_Xlib_Graphics_Driver::rect(x+offset_x, y+offset_y, w, h); } + void rectf(int x, int y, int w, int h) { Fl_Xlib_Graphics_Driver::rectf(x+offset_x, y+offset_y, w, h); } + void xyline(int x, int y, int x1) { Fl_Xlib_Graphics_Driver::xyline(x+offset_x, y+offset_y, x1+offset_x); } + void xyline(int x, int y, int x1, int y2) { Fl_Xlib_Graphics_Driver::xyline(x+offset_x, y+offset_y, x1+offset_x, y2+offset_y); } + void xyline(int x, int y, int x1, int y2, int x3) { Fl_Xlib_Graphics_Driver::xyline(x+offset_x, y+offset_y, x1+offset_x, y2+offset_y, x3+offset_x); } + void yxline(int x, int y, int y1) { Fl_Xlib_Graphics_Driver::yxline(x+offset_x, y+offset_y, y1+offset_y); } + void yxline(int x, int y, int y1, int x2) { Fl_Xlib_Graphics_Driver::yxline(x+offset_x, y+offset_y, y1+offset_y, x2+offset_x); } + void yxline(int x, int y, int y1, int x2, int y3) { Fl_Xlib_Graphics_Driver::yxline(x+offset_x, y+offset_y, y1+offset_y, x2+offset_x, y3+offset_y); } + void line(int x, int y, int x1, int y1) { Fl_Xlib_Graphics_Driver::line(x+offset_x, y+offset_y, x1+offset_x, y1+offset_y); } + void line(int x, int y, int x1, int y1, int x2, int y2) { Fl_Xlib_Graphics_Driver::line(x+offset_x, y+offset_y, x1+offset_x, y1+offset_y, x2+offset_x, y2+offset_y); } + void draw(const char* str, int n, int x, int y) { + Fl_Xlib_Graphics_Driver::draw(str, n, x+offset_x, y+offset_y); + } + void draw(int angle, const char *str, int n, int x, int y) { + Fl_Xlib_Graphics_Driver::draw(angle, str, n, x+offset_x, y+offset_y); + } + void rtl_draw(const char* str, int n, int x, int y) { + Fl_Xlib_Graphics_Driver::rtl_draw(str, n, x+offset_x, y+offset_y); + } + void draw(Fl_Pixmap *pxm, int XP, int YP, int WP, int HP, int cx, int cy) { + XP += offset_x; YP += offset_y; + translate_all(-offset_x, -offset_y); + Fl_Xlib_Graphics_Driver::draw(pxm, XP, YP, WP,HP,cx,cy); + untranslate_all(); + } + void draw(Fl_Bitmap *bm, int XP, int YP, int WP, int HP, int cx, int cy) { + XP += offset_x; YP += offset_y; + translate_all(-offset_x, -offset_y); + Fl_Xlib_Graphics_Driver::draw(bm, XP, YP, WP,HP,cx,cy); + untranslate_all(); + } + void draw(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy) { + XP += offset_x; YP += offset_y; + translate_all(-offset_x, -offset_y); + Fl_Xlib_Graphics_Driver::draw(img, XP, YP, WP,HP,cx,cy); + untranslate_all(); + } + void draw_image(const uchar* buf, int X,int Y,int W,int H, int D=3, int L=0) { + X += offset_x; Y += offset_y; + translate_all(-offset_x, -offset_y); + Fl_Xlib_Graphics_Driver::draw_image(buf, X, Y, W,H,D,L); + untranslate_all(); + } + void draw_image(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=3) { + X += offset_x; Y += offset_y; + translate_all(-offset_x, -offset_y); + Fl_Xlib_Graphics_Driver::draw_image(cb, data, X, Y, W,H,D); + untranslate_all(); + } + void draw_image_mono(const uchar* buf, int X,int Y,int W,int H, int D=1, int L=0) { + X += offset_x; Y += offset_y; + translate_all(-offset_x, -offset_y); + Fl_Xlib_Graphics_Driver::draw_image_mono(buf, X, Y, W,H,D,L); + untranslate_all(); + } + void draw_image_mono(Fl_Draw_Image_Cb cb, void* data, int X,int Y,int W,int H, int D=1) { + X += offset_x; Y += offset_y; + translate_all(-offset_x, -offset_y); + Fl_Xlib_Graphics_Driver::draw_image_mono(cb, data, X, Y, W,H,D); + untranslate_all(); + } + void copy_offscreen(int x, int y, int w, int h, Fl_Offscreen pixmap, int srcx, int srcy) { + Fl_Xlib_Graphics_Driver::copy_offscreen(x+offset_x, y+offset_y, w, h,pixmap,srcx,srcy); + } + void push_clip(int x, int y, int w, int h) { + Fl_Xlib_Graphics_Driver::push_clip(x+offset_x, y+offset_y, w, h); + } + int not_clipped(int x, int y, int w, int h) { return Fl_Xlib_Graphics_Driver::not_clipped(x + offset_x, y + offset_y, w, h); }; + int clip_box(int x, int y, int w, int h, int& X, int& Y, int& W, int& H) { + int retval = Fl_Xlib_Graphics_Driver::clip_box(x + offset_x, y + offset_y, w,h,X,Y,W,H); + X -= offset_x; + Y -= offset_y; + return retval; + } + void pie(int x, int y, int w, int h, double a1, double a2) { Fl_Xlib_Graphics_Driver::pie(x+offset_x,y+offset_y,w,h,a1,a2); } + void arc(int x, int y, int w, int h, double a1, double a2) { Fl_Xlib_Graphics_Driver::arc(x+offset_x,y+offset_y,w,h,a1,a2); } + void polygon(int x0, int y0, int x1, int y1, int x2, int y2) { Fl_Xlib_Graphics_Driver::polygon(x0+offset_x,y0+offset_y,x1+offset_x,y1+offset_y,x2+offset_x,y2+offset_y);} + void polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) { + Fl_Xlib_Graphics_Driver::polygon(x0+offset_x,y0+offset_y,x1+offset_x,y1+offset_y,x2+offset_x,y2+offset_y,x3+offset_x,y3+offset_y); + } + void loop(int x0, int y0, int x1, int y1, int x2, int y2) {Fl_Xlib_Graphics_Driver::loop(x0+offset_x,y0+offset_y,x1+offset_x,y1+offset_y,x2+offset_x,y2+offset_y);} + void loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3) { + Fl_Xlib_Graphics_Driver::loop(x0+offset_x,y0+offset_y,x1+offset_x,y1+offset_y,x2+offset_x,y2+offset_y,x3+offset_x,y3+offset_y); + } + void point(int x, int y) { Fl_Xlib_Graphics_Driver::point(x+offset_x, y+offset_y); } +}; + +const char *Fl_translated_Xlib_Graphics_Driver_::class_id = "Fl_translated_Xlib_Graphics_Driver_"; + +void Fl_Xlib_Surface_::translate(int x, int y) { + ((Fl_translated_Xlib_Graphics_Driver_*)driver())->translate_all(x, y); +} +void Fl_Xlib_Surface_::untranslate() { + ((Fl_translated_Xlib_Graphics_Driver_*)driver())->untranslate_all(); +} + +Fl_Xlib_Surface_::Fl_Xlib_Surface_() : Fl_Paged_Device() { + driver(new Fl_translated_Xlib_Graphics_Driver_()); +} +Fl_Xlib_Surface_::~Fl_Xlib_Surface_() { + delete driver(); +} + +const char *Fl_Xlib_Surface_::class_id = "Fl_Xlib_Surface_"; + +#endif + +// +// End of "$Id: Fl_Copy_Surface.cxx 10209 2014-06-26 16:14:42Z manolo $". +// diff --git a/src/Fl_Double_Window.cxx b/src/Fl_Double_Window.cxx index e31643d..6fbfa24 100644 --- a/src/Fl_Double_Window.cxx +++ b/src/Fl_Double_Window.cxx @@ -1,5 +1,5 @@ // -// "$Id: Fl_Double_Window.cxx 9719 2012-11-13 14:45:42Z manolo $" +// "$Id: Fl_Double_Window.cxx 10335 2014-09-23 10:48:36Z manolo $" // // Double-buffered window code for the Fast Light Tool Kit (FLTK). // @@ -214,12 +214,10 @@ void Fl_GDI_Graphics_Driver::copy_offscreen_with_alpha(int x,int y,int w,int h,H HDC new_gc = CreateCompatibleDC(fl_gc); int save = SaveDC(new_gc); SelectObject(new_gc, bitmap); - fl_can_do_alpha_blending(); // make sure this is called BOOL alpha_ok = 0; // first try to alpha blend - // if to printer, always try alpha_blend - if ( Fl_Surface_Device::surface() != Fl_Display_Device::display_device() || fl_can_do_alpha_blending() ) { - if (fl_alpha_blend) alpha_ok = fl_alpha_blend(fl_gc, x, y, w, h, new_gc, srcx, srcy, w, h, blendfunc); + if ( fl_can_do_alpha_blending() ) { + alpha_ok = fl_alpha_blend(fl_gc, x, y, w, h, new_gc, srcx, srcy, w, h, blendfunc); } // if that failed (it shouldn't), still copy the bitmap over, but now alpha is 1 if (!alpha_ok) { @@ -229,7 +227,6 @@ void Fl_GDI_Graphics_Driver::copy_offscreen_with_alpha(int x,int y,int w,int h,H DeleteDC(new_gc); } -extern void fl_restore_clip(); #elif defined(__APPLE_QUARTZ__) || defined(FL_DOXYGEN) @@ -349,7 +346,6 @@ void fl_end_offscreen() { /** @} */ -extern void fl_restore_clip(); #else # error unsupported platform @@ -369,6 +365,7 @@ void Fl_Double_Window::flush() {flush(0);} and leaving the clip region set to the entire window. */ void Fl_Double_Window::flush(int eraseoverlay) { + if (!shown()) return; make_current(); // make sure fl_gc is non-zero Fl_X *myi = Fl_X::i(this); if (!myi) return; // window not yet created @@ -514,5 +511,5 @@ Fl_Overlay_Window::Fl_Overlay_Window(int X, int Y, int W, int H, const char *l) // -// End of "$Id: Fl_Double_Window.cxx 9719 2012-11-13 14:45:42Z manolo $". +// End of "$Id: Fl_Double_Window.cxx 10335 2014-09-23 10:48:36Z manolo $". // diff --git a/src/Fl_File_Browser.cxx b/src/Fl_File_Browser.cxx index f6d4d65..d7f3d2a 100644 --- a/src/Fl_File_Browser.cxx +++ b/src/Fl_File_Browser.cxx @@ -1,5 +1,5 @@ // -// "$Id: Fl_File_Browser.cxx 9325 2012-04-05 05:12:30Z fabien $" +// "$Id: Fl_File_Browser.cxx 10145 2014-05-04 13:46:09Z manolo $" // // Fl_File_Browser routines. // @@ -62,6 +62,33 @@ # include <sys/mount.h> #endif // __APPLE__ +#if defined(_AIX) +extern "C" { +# include <sys/types.h> +# include <sys/vmount.h> +# include <sys/mntctl.h> + // Older AIX versions don't expose this prototype + int + mntctl(int, int, char *); +} +#endif // _AIX + +#if defined(__NetBSD__) +extern "C" { +# include <sys/param.h> // For '__NetBSD_Version__' definition +# if defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 300000000) +# include <sys/types.h> +# include <sys/statvfs.h> +# if defined(HAVE_PTHREAD) && defined(HAVE_PTHREAD_H) +# include <pthread.h> +# endif // HAVE_PTHREAD && HAVE_PTHREAD_H +# ifdef HAVE_PTHREAD + static pthread_mutex_t getvfsstat_mutex = PTHREAD_MUTEX_INITIALIZER; +# endif // HAVE_PTHREAD/ +# endif // __NetBSD_Version__ +} +#endif // __NetBSD__ + // // FL_BLINE definition from "Fl_Browser.cxx"... // @@ -349,7 +376,7 @@ Fl_File_Browser::item_draw(void *p, // I - List item data if (columns) { // Try clipping inside this column... - for (i = 0; i < column && columns[i]; i ++); + for (i = 0; i < column && columns[i]; i ++) { ; } if (columns[i]) cW = columns[i]; @@ -522,6 +549,77 @@ Fl_File_Browser::load(const char *directory,// I - Directory to load // Free the memory used for the file system info array... delete[] fs; } +#elif defined(_AIX) + // AIX don't write the mounted filesystems to a file like '/etc/mnttab'. + // But reading the list of mounted filesystems from the kernel is possible: + // http://publib.boulder.ibm.com/infocenter/pseries/v5r3/topic/com.ibm.aix.basetechref/doc/basetrf1/mntctl.htm + int res = -1, len; + char *list = NULL, *name; + struct vmount *vp; + + // We always have the root filesystem + add("/", icon); + // Get the required buffer size for the vmount structures + res = mntctl(MCTL_QUERY, sizeof(len), (char *) &len); + if (!res) { + // Allocate buffer ... + list = (char *) malloc((size_t) len); + if (NULL == list) { + res = -1; + } else { + // ... and read vmount structures from kernel + res = mntctl(MCTL_QUERY, len, list); + if (0 >= res) { + res = -1; + } else { + for (i = 0, vp = (struct vmount *) list; i < res; ++i) { + name = (char *) vp + vp->vmt_data[VMT_STUB].vmt_off; + strlcpy(filename, name, sizeof(filename)); + // Skip the already added root filesystem + if (strcmp("/", filename) != 0) { + strlcat(filename, "/", sizeof(filename)); + add(filename, icon); + } + vp = (struct vmount *) ((char *) vp + vp->vmt_length); + } + } + } + } + // Note: Executing 'free(NULL)' is allowed and simply do nothing + free((void *) list); +#elif defined(__NetBSD__) && defined(__NetBSD_Version__) \ + && (__NetBSD_Version__ >= 300000000) + // NetBSD don't write the mounted filesystems to a file like '/etc/mnttab'. + // Since NetBSD 3.0 the system call getvfsstat(2) has replaced getfsstat(2) + // that is used by getmntinfo(3): + // http://www.daemon-systems.org/man/getmntinfo.3.html + int res = -1; + struct statvfs *list; + + // We always have the root filesystem + add("/", icon); +# ifdef HAVE_PTHREAD + // Lock mutex for thread safety + if (!pthread_mutex_lock(&getvfsstat_mutex)) { +# endif // HAVE_PTHREAD + // Get list of statvfs structures + res = getmntinfo(&list, ST_WAIT); + if(0 < res) { + for (i = 0; i < res; ++i) { + strlcpy(filename, list[i].f_mntonname, sizeof(filename)); + // Skip the already added root filesystem + if (strcmp("/", filename) != 0) { + strlcat(filename, "/", sizeof(filename)); + add(filename, icon); + } + } + } else { + res = -1; + } +# ifdef HAVE_PTHREAD + pthread_mutex_unlock(&getvfsstat_mutex); + } +# endif // HAVE_PTHREAD #else // // UNIX code uses /etc/fstab or similar... @@ -550,7 +648,10 @@ Fl_File_Browser::load(const char *directory,// I - Directory to load if (sscanf(line, "%*s%4095s", filename) != 1) continue; - strlcat(filename, "/", sizeof(filename)); + // Add a trailing slash (except for the root filesystem) + if (strcmp("/", filename) != 0) { + strlcat(filename, "/", sizeof(filename)); + } // printf("Fl_File_Browser::load() - adding \"%s\" to list...\n", filename); add(filename, icon); @@ -558,8 +659,13 @@ Fl_File_Browser::load(const char *directory,// I - Directory to load } fclose(mtab); + } else { + // Every Unix has a root filesystem '/'. + // This last stage fallback ensures that the user don't get an empty + // window after requesting filesystem list. + add("/", icon); } -#endif // WIN32 || __EMX__ +#endif // WIN32 || __EMX__ || __APPLE__ || _AIX || ... } else { @@ -630,5 +736,5 @@ Fl_File_Browser::filter(const char *pattern) // I - Pattern string // -// End of "$Id: Fl_File_Browser.cxx 9325 2012-04-05 05:12:30Z fabien $". +// End of "$Id: Fl_File_Browser.cxx 10145 2014-05-04 13:46:09Z manolo $". // diff --git a/src/Fl_File_Chooser.cxx b/src/Fl_File_Chooser.cxx index 62ee256..935127e 100644 --- a/src/Fl_File_Chooser.cxx +++ b/src/Fl_File_Chooser.cxx @@ -1,9 +1,9 @@ // -// "$Id: Fl_File_Chooser.cxx 8864 2011-07-19 04:49:30Z greg.ercolano $" +// "$Id: Fl_File_Chooser.cxx 10358 2014-10-05 11:56:06Z AlbrechtS $" // // Fl_File_Chooser dialog for the Fast Light Tool Kit (FLTK). // -// Copyright 1998-2011 by Bill Spitzak and others. +// Copyright 1998-2014 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this @@ -15,8 +15,15 @@ // // http://www.fltk.org/str.php // +// ======================================================================== +// DO NOT EDIT FL/Fl_File_Chooser.H and src/Fl_File_Chooser.cxx !!! +// ======================================================================== +// Please use fluid to change src/Fl_File_Chooser.fl interactively +// and then use fluid to "write code" or edit and use fluid -c . +// ======================================================================== +// -// generated by Fast Light User Interface Designer (fluid) version 1.0300 +// generated by Fast Light User Interface Designer (fluid) version 1.0303 #include "../FL/Fl_File_Chooser.H" #include <FL/fl_draw.H> @@ -53,7 +60,7 @@ void Fl_File_Chooser::cb_newButton(Fl_Button* o, void* v) { } #include <FL/Fl_Bitmap.H> -static unsigned char idata_new[] = +static const unsigned char idata_new[] = {0,0,120,0,132,0,2,1,1,254,1,128,49,128,49,128,253,128,253,128,49,128,49, 128,1,128,1,128,255,255,0,0}; static Fl_Bitmap image_new(idata_new, 16, 16); @@ -221,7 +228,7 @@ Fl_File_Chooser::Fl_File_Chooser(const char *d, const char *p, int t, const char fileName->callback((Fl_Callback*)cb_fileName); fileName->when(FL_WHEN_ENTER_KEY); Fl_Group::current()->resizable(fileName); - fileName->when(FL_WHEN_CHANGED | FL_WHEN_ENTER_KEY); + fileName->when(FL_WHEN_CHANGED | FL_WHEN_ENTER_KEY_ALWAYS); } // Fl_File_Input* fileName { Fl_Box* o = new Fl_Box(10, 310, 105, 25, "Filename:"); o->labelfont(1); @@ -462,5 +469,5 @@ Fl_Widget* Fl_File_Chooser::add_extra(Fl_Widget* gr) { } // -// End of "$Id: Fl_File_Chooser.cxx 8864 2011-07-19 04:49:30Z greg.ercolano $". +// End of "$Id: Fl_File_Chooser.cxx 10358 2014-10-05 11:56:06Z AlbrechtS $". // diff --git a/src/Fl_File_Chooser.fl b/src/Fl_File_Chooser.fl index d13d23e..b2a528b 100644 --- a/src/Fl_File_Chooser.fl +++ b/src/Fl_File_Chooser.fl @@ -1,13 +1,13 @@ # data file for the Fltk User Interface Designer (fluid) -version 1.0300 +version 1.0303 header_name {../FL/Fl_File_Chooser.H} code_name {.cxx} comment {// -// "$Id: Fl_File_Chooser.fl 8864 2011-07-19 04:49:30Z greg.ercolano $" +// "$Id: Fl_File_Chooser.fl 10357 2014-10-05 11:28:29Z AlbrechtS $" // // Fl_File_Chooser dialog for the Fast Light Tool Kit (FLTK). // -// Copyright 1998-2011 by Bill Spitzak and others. +// Copyright 1998-2014 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this @@ -19,31 +19,55 @@ comment {// // // http://www.fltk.org/str.php // +// ======================================================================== +// DO NOT EDIT FL/Fl_File_Chooser.H and src/Fl_File_Chooser.cxx !!! +// ======================================================================== +// Please use fluid to change src/Fl_File_Chooser.fl interactively +// and then use fluid to "write code" or edit and use fluid -c . +// ======================================================================== +// } {in_source in_header } -decl {\#include <FL/fl_draw.H>} {} +decl {\#include <FL/fl_draw.H>} {private local +} class FL_EXPORT Fl_File_Chooser {open } { - decl {enum { SINGLE = 0, MULTI = 1, CREATE = 2, DIRECTORY = 4 };} {public - } - decl {static Fl_Preferences prefs_;} {} - decl {void (*callback_)(Fl_File_Chooser*, void *);} {} - decl {void *data_;} {} - decl {char directory_[FL_PATH_MAX];} {} - decl {char pattern_[FL_PATH_MAX];} {} - decl {char preview_text_[2048];} {} - decl {int type_;} {} - decl {void favoritesButtonCB();} {} - decl {void favoritesCB(Fl_Widget *w);} {} - decl {void fileListCB();} {} - decl {void fileNameCB();} {} - decl {void newdir();} {} - decl {static void previewCB(Fl_File_Chooser *fc);} {} - decl {void showChoiceCB();} {} - decl {void update_favorites();} {} - decl {void update_preview();} {} + decl {enum { SINGLE = 0, MULTI = 1, CREATE = 2, DIRECTORY = 4 };} {public local + } + decl {static Fl_Preferences prefs_;} {private local + } + decl {void (*callback_)(Fl_File_Chooser*, void *);} {private local + } + decl {void *data_;} {private local + } + decl {char directory_[FL_PATH_MAX];} {private local + } + decl {char pattern_[FL_PATH_MAX];} {private local + } + decl {char preview_text_[2048];} {private local + } + decl {int type_;} {private local + } + decl {void favoritesButtonCB();} {private local + } + decl {void favoritesCB(Fl_Widget *w);} {private local + } + decl {void fileListCB();} {private local + } + decl {void fileNameCB();} {private local + } + decl {void newdir();} {private local + } + decl {static void previewCB(Fl_File_Chooser *fc);} {private local + } + decl {void showChoiceCB();} {private local + } + decl {void update_favorites();} {private local + } + decl {void update_preview();} {private local + } Function {Fl_File_Chooser(const char *d, const char *p, int t, const char *title)} {} { code {Fl_Group *prev_current = Fl_Group::current();} {} Fl_Window window { @@ -119,7 +143,7 @@ window->hide();} open Fl_File_Input fileName { callback {fileNameCB();} private xywh {115 300 365 35} labelfont 1 when 8 resizable - code0 {fileName->when(FL_WHEN_CHANGED | FL_WHEN_ENTER_KEY);} + code0 {fileName->when(FL_WHEN_CHANGED | FL_WHEN_ENTER_KEY_ALWAYS);} } Fl_Box {} { label {Filename:} @@ -238,15 +262,15 @@ data_ = d;} {} } { code {return (fileList->color());} {} } - decl {int count();} {public + decl {int count();} {public local } - decl {void directory(const char *d);} {public + decl {void directory(const char *d);} {public local } Function {directory()} {return_type {char *} } { code {return directory_;} {} } - decl {void filter(const char *p);} {public + decl {void filter(const char *p);} {public local } Function {filter()} {return_type {const char *} } { @@ -294,19 +318,19 @@ okButton->parent()->init_sizes();} {} } { code {return (okButton->label());} {} } - decl {void preview(int e);} {public + decl {void preview(int e);} {public local } - decl {int preview() const { return previewButton->value(); }} {public + decl {int preview() const { return previewButton->value(); }} {public local } - decl {void showHidden(int e);} {private + decl {void showHidden(int e);} {private local } - decl {void remove_hidden_files();} {private + decl {void remove_hidden_files();} {private local } - decl {void rescan();} {public + decl {void rescan();} {public local } - decl {void rescan_keep_filename();} {public + decl {void rescan_keep_filename();} {public local } - decl {void show();} {public + decl {void show();} {public local } Function {shown()} {return_type int } { @@ -364,61 +388,62 @@ else } { code {data_ = d;} {} } - decl {const char *value(int f = 1);} {public + decl {const char *value(int f = 1);} {public local } - decl {void value(const char *filename);} {public + decl {void value(const char *filename);} {public local } Function {visible()} {return_type int } { code {return window->visible();} {} } decl {static const char *add_favorites_label;} { - comment {[standard text may be customized at run-time]} public + comment {[standard text may be customized at run-time]} public local } decl {static const char *all_files_label;} { - comment {[standard text may be customized at run-time]} public + comment {[standard text may be customized at run-time]} public local } decl {static const char *custom_filter_label;} { - comment {[standard text may be customized at run-time]} public + comment {[standard text may be customized at run-time]} public local } decl {static const char *existing_file_label;} { - comment {[standard text may be customized at run-time]} public + comment {[standard text may be customized at run-time]} public local } decl {static const char *favorites_label;} { - comment {[standard text may be customized at run-time]} public + comment {[standard text may be customized at run-time]} public local } decl {static const char *filename_label;} { - comment {[standard text may be customized at run-time]} public + comment {[standard text may be customized at run-time]} public local } decl {static const char *filesystems_label;} { - comment {[standard text may be customized at run-time]} public + comment {[standard text may be customized at run-time]} public local } decl {static const char *manage_favorites_label;} { - comment {[standard text may be customized at run-time]} public + comment {[standard text may be customized at run-time]} public local } decl {static const char *new_directory_label;} { - comment {[standard text may be customized at run-time]} public + comment {[standard text may be customized at run-time]} public local } decl {static const char *new_directory_tooltip;} { - comment {[standard text may be customized at run-time]} public + comment {[standard text may be customized at run-time]} public local } decl {static const char *preview_label;} { - comment {[standard text may be customized at run-time]} public + comment {[standard text may be customized at run-time]} public local } decl {static const char *save_label;} { - comment {[standard text may be customized at run-time]} public + comment {[standard text may be customized at run-time]} public local } decl {static const char *show_label;} { - comment {[standard text may be customized at run-time]} public + comment {[standard text may be customized at run-time]} public local } decl {static const char *hidden_label;} { - comment {[standard text may be customized at run-time]} public + comment {[standard text may be customized at run-time]} public local } decl {static Fl_File_Sort_F *sort;} { comment {the sort function that is used when loading -the contents of a directory.} public +the contents of a directory.} public local + } + decl {Fl_Widget* ext_group;} {private local } - decl {Fl_Widget* ext_group;} {} Function {add_extra(Fl_Widget* gr)} {open return_type {Fl_Widget*} } { code {Fl_Widget* ret=ext_group;} {} @@ -451,20 +476,20 @@ window->resizable(svres);} {} } } -decl {FL_EXPORT char *fl_dir_chooser(const char *message,const char *fname,int relative=0);} {public +decl {FL_EXPORT char *fl_dir_chooser(const char *message,const char *fname,int relative=0);} {public local } -decl {FL_EXPORT char *fl_file_chooser(const char *message,const char *pat,const char *fname,int relative=0);} {public +decl {FL_EXPORT char *fl_file_chooser(const char *message,const char *pat,const char *fname,int relative=0);} {public local } -decl {FL_EXPORT void fl_file_chooser_callback(void (*cb)(const char*));} {public +decl {FL_EXPORT void fl_file_chooser_callback(void (*cb)(const char*));} {public local } -decl {FL_EXPORT void fl_file_chooser_ok_label(const char*l);} {public +decl {FL_EXPORT void fl_file_chooser_ok_label(const char*l);} {public local } comment { // -// End of "$Id: Fl_File_Chooser.fl 8864 2011-07-19 04:49:30Z greg.ercolano $". +// End of "$Id: Fl_File_Chooser.fl 10357 2014-10-05 11:28:29Z AlbrechtS $". //} {in_source in_header } diff --git a/src/Fl_File_Chooser2.cxx b/src/Fl_File_Chooser2.cxx index 72378d9..a1a0b9e 100644 --- a/src/Fl_File_Chooser2.cxx +++ b/src/Fl_File_Chooser2.cxx @@ -1,5 +1,5 @@ // -// "$Id: Fl_File_Chooser2.cxx 9704 2012-10-19 11:23:51Z manolo $" +// "$Id: Fl_File_Chooser2.cxx 10004 2013-10-21 04:58:43Z greg.ercolano $" // // More Fl_File_Chooser routines. // @@ -1423,6 +1423,15 @@ Fl_File_Chooser::update_preview() previewBox->labelsize(size); previewBox->labelfont(FL_COURIER); } + } else if (image && ( (image->w() <= 0) || + (image->h() <= 0) || + (image->d() <= 0) )) { + // Image has errors? Show big 'X' + previewBox->label("X"); + previewBox->align(FL_ALIGN_CLIP); + previewBox->labelsize(70); + previewBox->labelfont(FL_HELVETICA); + previewBox->redraw(); } else if (image) { pbw = previewBox->w() - 20; pbh = previewBox->h() - 20; @@ -1696,5 +1705,5 @@ unquote_pathname(char *dst, // O - Destination string // -// End of "$Id: Fl_File_Chooser2.cxx 9704 2012-10-19 11:23:51Z manolo $". +// End of "$Id: Fl_File_Chooser2.cxx 10004 2013-10-21 04:58:43Z greg.ercolano $". // diff --git a/src/Fl_File_Icon2.cxx b/src/Fl_File_Icon2.cxx index 1e31b13..89d7958 100644 --- a/src/Fl_File_Icon2.cxx +++ b/src/Fl_File_Icon2.cxx @@ -1,5 +1,5 @@ // -// "$Id: Fl_File_Icon2.cxx 8864 2011-07-19 04:49:30Z greg.ercolano $" +// "$Id: Fl_File_Icon2.cxx 10140 2014-05-01 15:55:03Z manolo $" // // Fl_File_Icon system icon routines. // @@ -570,9 +570,14 @@ int Fl_File_Icon::load_image(const char *ifile) // I - File to read from img->release(); #ifdef DEBUG - printf("Icon File \"%s\":\n", xpm); +{ + int i; + printf("Icon File \"%s\":\n", ifile); for (i = 0; i < num_data_; i ++) + { printf(" %d,\n", data_[i]); + } +} #endif // DEBUG return 0; @@ -582,7 +587,7 @@ int Fl_File_Icon::load_image(const char *ifile) // I - File to read from /** Loads all system-defined icons. This call is useful when using the FileChooser widget and should be used when the application starts: - + \code Fl_File_Icon::load_system_icons(); \endcode @@ -616,7 +621,7 @@ Fl_File_Icon::load_system_icons(void) { VERTEX, 7000, 5000, END, LINE, VERTEX, 3000, 4000, VERTEX, 7000, 4000, END, LINE, VERTEX, 3000, 3000, VERTEX, 7000, 3000, END, LINE, VERTEX, 3000, 2000, - VERTEX, 7000, 2000, END, + VERTEX, 7000, 2000, END, END }; static short image[] = { // Image file icon @@ -1009,5 +1014,5 @@ get_kde_val(char *str, // -// End of "$Id: Fl_File_Icon2.cxx 8864 2011-07-19 04:49:30Z greg.ercolano $". +// End of "$Id: Fl_File_Icon2.cxx 10140 2014-05-01 15:55:03Z manolo $". // diff --git a/src/Fl_Font.H b/src/Fl_Font.H index 3c6ddc8..6eb6743 100644 --- a/src/Fl_Font.H +++ b/src/Fl_Font.H @@ -1,5 +1,5 @@ // -// "$Id: Fl_Font.H 8864 2011-07-19 04:49:30Z greg.ercolano $" +// "$Id: Fl_Font.H 10248 2014-08-23 08:41:58Z cand $" // // Font definitions for the Fast Light Tool Kit (FLTK). // @@ -29,7 +29,7 @@ # if USE_XFT typedef struct _XftFont XftFont; # elif !defined(WIN32) && !defined(__APPLE__) -# include <FL/Xutf8.h> +# include "Xutf8.h" # endif // USE_XFT /** @@ -60,7 +60,6 @@ public: # endif ATSUStyle style; short ascent, descent, q_width; - char *q_name; # elif USE_XFT XftFont* font; //const char* encoding; @@ -105,5 +104,5 @@ FL_EXPORT char *fl_find_fontsize(char *name); #endif // -// End of "$Id: Fl_Font.H 8864 2011-07-19 04:49:30Z greg.ercolano $". +// End of "$Id: Fl_Font.H 10248 2014-08-23 08:41:58Z cand $". // diff --git a/src/Fl_GDI_Printer.cxx b/src/Fl_GDI_Printer.cxx index e07e5ec..ad1988b 100644 --- a/src/Fl_GDI_Printer.cxx +++ b/src/Fl_GDI_Printer.cxx @@ -1,5 +1,5 @@ // -// "$Id: Fl_GDI_Printer.cxx 9325 2012-04-05 05:12:30Z fabien $" +// "$Id: Fl_GDI_Printer.cxx 10391 2014-10-23 11:33:43Z AlbrechtS $" // // Support for WIN32 printing for the Fast Light Tool Kit (FLTK). // @@ -132,8 +132,11 @@ void Fl_System_Printer::absolute_printable_rect(int *x, int *y, int *w, int *h) { POINT physPageSize; POINT pixelsPerInch; + XFORM transform; if (hPr == NULL) return; + GetWorldTransform(fl_gc, &transform); + ModifyWorldTransform(fl_gc, NULL, MWT_IDENTITY); SetWindowOrgEx(fl_gc, 0, 0, NULL); physPageSize.x = GetDeviceCaps(hPr, HORZRES); @@ -152,11 +155,12 @@ void Fl_System_Printer::absolute_printable_rect(int *x, int *y, int *w, int *h) *x = left_margin; *y = top_margin; origin(x_offset, y_offset); + SetWorldTransform(fl_gc, &transform); } void Fl_System_Printer::margins(int *left, int *top, int *right, int *bottom) { - int x, y, w, h; + int x = 0, y = 0, w = 0, h = 0; absolute_printable_rect(&x, &y, &w, &h); if (left) *left = x; if (top) *top = y; @@ -273,5 +277,5 @@ void Fl_System_Printer::untranslate (void) #endif // WIN32 // -// End of "$Id: Fl_GDI_Printer.cxx 9325 2012-04-05 05:12:30Z fabien $". +// End of "$Id: Fl_GDI_Printer.cxx 10391 2014-10-23 11:33:43Z AlbrechtS $". // diff --git a/src/Fl_Gl_Device_Plugin.cxx b/src/Fl_Gl_Device_Plugin.cxx index 53d2e1b..313cd8e 100644 --- a/src/Fl_Gl_Device_Plugin.cxx +++ b/src/Fl_Gl_Device_Plugin.cxx @@ -1,5 +1,5 @@ // -// "$Id: Fl_Gl_Device_Plugin.cxx 8864 2011-07-19 04:49:30Z greg.ercolano $" +// "$Id: Fl_Gl_Device_Plugin.cxx 10051 2014-01-10 16:50:55Z manolo $" // // implementation of class Fl_Gl_Device_Plugin for the Fast Light Tool Kit (FLTK). // @@ -34,33 +34,12 @@ static void imgProviderReleaseData (void *info, const void *data, size_t size) static void print_gl_window(Fl_Gl_Window *glw, int x, int y, int height) { -#ifdef WIN32 - HDC save_gc = fl_gc; - const int bytesperpixel = 3; -#elif defined(__APPLE__) - CGContextRef save_gc = fl_gc; +#if defined(__APPLE__) const int bytesperpixel = 4; #else - _XGC *save_gc = fl_gc; const int bytesperpixel = 3; #endif - Fl_Surface_Device *save_surface = Fl_Surface_Device::surface(); - fl_gc = NULL; - Fl_Display_Device::display_device()->set_current(); -#ifdef WIN32 - Fl::check(); - Fl_Window *win = (Fl_Window*)glw; - while( win->window() ) win = win->window(); - win->redraw(); - Fl::check(); - glw->make_current(); -#else - glw->make_current(); - glw->redraw(); - glFlush(); - Fl::check(); - glFinish(); -#endif + glw->flush(); // forces a GL redraw necessary for the glpuzzle demo // Read OpenGL context pixels directly. // For extra safety, save & restore OpenGL states that are changed glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT); @@ -73,17 +52,13 @@ static void print_gl_window(Fl_Gl_Window *glw, int x, int y, int height) mByteWidth = (mByteWidth + 3) & ~3; // Align to 4 bytes uchar *baseAddress = (uchar*)malloc(mByteWidth * glw->h()); glReadPixels(0, 0, glw->w(), glw->h(), -#ifdef WIN32 - GL_RGB, GL_UNSIGNED_BYTE, -#elif defined(__APPLE__) +#if defined(__APPLE__) GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, -#else // FIXME Linux/Unix +#else GL_RGB, GL_UNSIGNED_BYTE, #endif baseAddress); glPopClientAttrib(); - save_surface->set_current(); - fl_gc = save_gc; #if defined(__APPLE__) // kCGBitmapByteOrder32Host and CGBitmapInfo are supposed to arrive with 10.4 // but some 10.4 don't have kCGBitmapByteOrder32Host, so we play a little #define game @@ -143,5 +118,5 @@ static Fl_Gl_Device_Plugin Gl_Device_Plugin; FL_EXPORT int fl_gl_load_plugin = 0; // -// End of "$Id: Fl_Gl_Device_Plugin.cxx 8864 2011-07-19 04:49:30Z greg.ercolano $". +// End of "$Id: Fl_Gl_Device_Plugin.cxx 10051 2014-01-10 16:50:55Z manolo $". // diff --git a/src/Fl_Gl_Window.cxx b/src/Fl_Gl_Window.cxx index 36f3ddf..257085c 100644 --- a/src/Fl_Gl_Window.cxx +++ b/src/Fl_Gl_Window.cxx @@ -1,5 +1,5 @@ // -// "$Id: Fl_Gl_Window.cxx 9264 2012-03-05 08:46:30Z manolo $" +// "$Id: Fl_Gl_Window.cxx 10214 2014-06-30 10:30:58Z ossman $" // // OpenGL window code for the Fast Light Tool Kit (FLTK). // @@ -24,8 +24,6 @@ extern int fl_gl_load_plugin; extern void gl_texture_reset(); #endif -static int temp = fl_gl_load_plugin; - #include <FL/Fl.H> #include <FL/x.H> #ifdef __APPLE__ @@ -183,8 +181,10 @@ void Fl_Gl_Window::make_current() { GLint xywh[4]; if (window()) { - xywh[0] = x(); - xywh[1] = window()->h() - y() - h(); + int xoff,yoff; + const Fl_Window *win = top_window_offset(xoff, yoff); // STR #2944 [2] + xywh[0] = xoff; + xywh[1] = win->h() - yoff - h(); } else { xywh[0] = 0; xywh[1] = 0; @@ -249,10 +249,34 @@ void Fl_Gl_Window::swap_buffers() { # endif #elif defined(__APPLE_QUARTZ__) if(overlay != NULL) { - //aglSwapBuffers does not work well with overlays under cocoa - glReadBuffer(GL_BACK); - glDrawBuffer(GL_FRONT); - glCopyPixels(0,0,w(),h(),GL_COLOR); + // STR# 2944 [1] + // Save matrixmode/proj/modelview/rasterpos before doing overlay. + // + int wo=w(), ho=h(); + GLint matrixmode; + GLfloat pos[4]; + glGetIntegerv(GL_MATRIX_MODE, &matrixmode); + glGetFloatv(GL_CURRENT_RASTER_POSITION, pos); // save original glRasterPos + glMatrixMode(GL_PROJECTION); // save proj/model matrices + glPushMatrix(); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + glScalef(2.0f/wo, 2.0f/ho, 1.0f); + glTranslatef(-wo/2.0f, -ho/2.0f, 0.0f); // set transform so 0,0 is bottom/left of Gl_Window + glRasterPos2i(0,0); // set glRasterPos to bottom left corner + { + // Emulate overlay by doing copypixels + glReadBuffer(GL_BACK); + glDrawBuffer(GL_FRONT); + glCopyPixels(0, 0, wo, ho, GL_COLOR); // copy GL_BACK to GL_FRONT + } + glPopMatrix(); // GL_MODELVIEW // restore model/proj matrices + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(matrixmode); + glRasterPos3f(pos[0], pos[1], pos[2]); // restore original glRasterPos } else aglSwapBuffers((AGLContext)context_); @@ -268,6 +292,7 @@ int fl_overlay_depth = 0; void Fl_Gl_Window::flush() { + if (!shown()) return; uchar save_valid = valid_f_ & 1; #if HAVE_GL_OVERLAY && defined(WIN32) uchar save_valid_f = valid_f_; @@ -288,16 +313,9 @@ void Fl_Gl_Window::flush() { #if HAVE_GL_OVERLAY && defined(WIN32) - bool fixcursor = false; // for fixing the SGI 320 bug - // Draw into hardware overlay planes if they are damaged: if (overlay && overlay != this && (damage()&(FL_DAMAGE_OVERLAY|FL_DAMAGE_EXPOSE) || !save_valid)) { - // SGI 320 messes up overlay with user-defined cursors: - if (Fl_X::i(this)->cursor && Fl_X::i(this)->cursor != fl_default_cursor) { - fixcursor = true; // make it restore cursor later - SetCursor(0); - } fl_set_gl_context(this, (GLContext)overlay); if (fl_overlay_depth) wglRealizeLayerPalette(Fl_X::i(this)->private_dc, 1, TRUE); @@ -310,7 +328,6 @@ void Fl_Gl_Window::flush() { wglSwapLayerBuffers(Fl_X::i(this)->private_dc, WGL_SWAP_OVERLAY1); // if only the overlay was damaged we are done, leave main layer alone: if (damage() == FL_DAMAGE_OVERLAY) { - if (fixcursor) SetCursor(Fl_X::i(this)->cursor); return; } } @@ -406,9 +423,6 @@ void Fl_Gl_Window::flush() { } -#if HAVE_GL_OVERLAY && defined(WIN32) - if (fixcursor) SetCursor(Fl_X::i(this)->cursor); -#endif valid(1); context_valid(1); } @@ -549,6 +563,11 @@ int Fl_Gl_Window::handle(int event) return Fl_Window::handle(event); } +// don't remove me! this serves only to force linking of Fl_Gl_Device_Plugin.o +int Fl_Gl_Window::gl_plugin_linkage() { + return fl_gl_load_plugin; +} + // -// End of "$Id: Fl_Gl_Window.cxx 9264 2012-03-05 08:46:30Z manolo $". +// End of "$Id: Fl_Gl_Window.cxx 10214 2014-06-30 10:30:58Z ossman $". // diff --git a/src/Fl_Group.cxx b/src/Fl_Group.cxx index 6584be7..3f9f8fc 100644 --- a/src/Fl_Group.cxx +++ b/src/Fl_Group.cxx @@ -1,5 +1,5 @@ // -// "$Id: Fl_Group.cxx 9637 2012-07-24 04:37:22Z matt $" +// "$Id: Fl_Group.cxx 10261 2014-08-29 12:10:11Z cand $" // // Group widget for the Fast Light Tool Kit (FLTK). // @@ -122,8 +122,10 @@ static int send(Fl_Widget* o, int event) { } // translate the current keystroke into up/down/left/right for navigation: -#define ctrl(x) (x^0x40) static int navkey() { + // The app may want these for hotkeys, check key state + if (Fl::event_state(FL_CTRL | FL_ALT | FL_META)) return 0; + switch (Fl::event_key()) { case 0: // not an FL_KEYBOARD/FL_SHORTCUT event break; @@ -875,5 +877,5 @@ Fl_Spinner::Fl_Spinner(int X, int Y, int W, int H, const char *L) // -// End of "$Id: Fl_Group.cxx 9637 2012-07-24 04:37:22Z matt $". +// End of "$Id: Fl_Group.cxx 10261 2014-08-29 12:10:11Z cand $". // diff --git a/src/Fl_Help_Dialog.cxx b/src/Fl_Help_Dialog.cxx index ae8a36b..b608cbe 100644 --- a/src/Fl_Help_Dialog.cxx +++ b/src/Fl_Help_Dialog.cxx @@ -1,9 +1,9 @@ // -// "$Id: Fl_Help_Dialog.cxx 8864 2011-07-19 04:49:30Z greg.ercolano $" +// "$Id: Fl_Help_Dialog.cxx 10357 2014-10-05 11:28:29Z AlbrechtS $" // // Fl_Help_Dialog dialog for the Fast Light Tool Kit (FLTK). // -// Copyright 1998-2010 by Bill Spitzak and others. +// Copyright 1998-2014 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this @@ -15,8 +15,15 @@ // // http://www.fltk.org/str.php // +// ======================================================================== +// DO NOT EDIT FL/Fl_Help_Dialog.H and src/Fl_Help_Dialog.cxx !!! +// ======================================================================== +// Please use fluid to change src/Fl_Help_Dialog.fl interactively +// and then use fluid to "write code" or edit and use fluid -c . +// ======================================================================== +// -// generated by Fast Light User Interface Designer (fluid) version 1.0108 +// generated by Fast Light User Interface Designer (fluid) version 1.0303 #include "../FL/Fl_Help_Dialog.H" #include "flstring.h" @@ -192,13 +199,13 @@ Fl_Help_Dialog::Fl_Help_Dialog() { window_->end(); } // Fl_Double_Window* window_ back_->deactivate(); -forward_->deactivate(); - -index_ = -1; -max_ = 0; -find_pos_ = 0; - -fl_register_images(); + forward_->deactivate(); + + index_ = -1; + max_ = 0; + find_pos_ = 0; + + fl_register_images(); } Fl_Help_Dialog::~Fl_Help_Dialog() { @@ -215,8 +222,8 @@ void Fl_Help_Dialog::hide() { void Fl_Help_Dialog::load(const char *f) { view_->set_changed(); -view_->load(f); -window_->label(view_->title()); + view_->load(f); + window_->label(view_->title()); } void Fl_Help_Dialog::position(int xx, int yy) { @@ -237,16 +244,16 @@ void Fl_Help_Dialog::show(int argc, char **argv) { void Fl_Help_Dialog::textsize(Fl_Fontsize s) { view_->textsize(s); - -if (s <= 8) - smaller_->deactivate(); -else - smaller_->activate(); - -if (s >= 18) - larger_->deactivate(); -else - larger_->activate(); + + if (s <= 8) + smaller_->deactivate(); + else + smaller_->activate(); + + if (s >= 18) + larger_->deactivate(); + else + larger_->activate(); } Fl_Fontsize Fl_Help_Dialog::textsize() { @@ -263,8 +270,8 @@ void Fl_Help_Dialog::topline(int n) { void Fl_Help_Dialog::value(const char *f) { view_->set_changed(); -view_->value(f); -window_->label(view_->title()); + view_->value(f); + window_->label(view_->title()); } const char * Fl_Help_Dialog::value() const { @@ -288,5 +295,5 @@ int Fl_Help_Dialog::y() { } // -// End of "$Id: Fl_Help_Dialog.cxx 8864 2011-07-19 04:49:30Z greg.ercolano $". +// End of "$Id: Fl_Help_Dialog.cxx 10357 2014-10-05 11:28:29Z AlbrechtS $". // diff --git a/src/Fl_Help_Dialog.fl b/src/Fl_Help_Dialog.fl index 30e731b..42dc5d2 100644 --- a/src/Fl_Help_Dialog.fl +++ b/src/Fl_Help_Dialog.fl @@ -1,13 +1,13 @@ # data file for the Fltk User Interface Designer (fluid) -version 1.0108 +version 1.0303 header_name {../FL/Fl_Help_Dialog.H} code_name {.cxx} comment {// -// "$Id: Fl_Help_Dialog.fl 8864 2011-07-19 04:49:30Z greg.ercolano $" +// "$Id: Fl_Help_Dialog.fl 10357 2014-10-05 11:28:29Z AlbrechtS $" // // Fl_Help_Dialog dialog for the Fast Light Tool Kit (FLTK). // -// Copyright 1998-2010 by Bill Spitzak and others. +// Copyright 1998-2014 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this @@ -19,20 +19,34 @@ comment {// // // http://www.fltk.org/str.php // +// ======================================================================== +// DO NOT EDIT FL/Fl_Help_Dialog.H and src/Fl_Help_Dialog.cxx !!! +// ======================================================================== +// Please use fluid to change src/Fl_Help_Dialog.fl interactively +// and then use fluid to "write code" or edit and use fluid -c . +// ======================================================================== +// } {in_source in_header } -decl {\#include "flstring.h"} {} +decl {\#include "flstring.h"} {private local +} -decl {\#include <FL/fl_ask.H>} {} +decl {\#include <FL/fl_ask.H>} {private local +} class FL_EXPORT Fl_Help_Dialog {open } { - decl {int index_;} {} - decl {int max_;} {} - decl {int line_[100];} {} - decl {char file_[100][256];} {} - decl {int find_pos_;} {} + decl {int index_;} {private local + } + decl {int max_;} {private local + } + decl {int line_[100]; // FIXME: we must remove those static numbers} {private local + } + decl {char file_[100][FL_PATH_MAX]; // FIXME: we must remove those static numbers} {private local + } + decl {int find_pos_;} {private local + } Function {Fl_Help_Dialog()} {open } { Fl_Window window_ { @@ -251,6 +265,6 @@ window_->label(view_->title());} {} comment { // -// End of "$Id: Fl_Help_Dialog.fl 8864 2011-07-19 04:49:30Z greg.ercolano $". +// End of "$Id: Fl_Help_Dialog.fl 10357 2014-10-05 11:28:29Z AlbrechtS $". //} {in_source in_header } diff --git a/src/Fl_Help_View.cxx b/src/Fl_Help_View.cxx index 46d8090..f2e3fe0 100644 --- a/src/Fl_Help_View.cxx +++ b/src/Fl_Help_View.cxx @@ -1,5 +1,5 @@ // -// "$Id: Fl_Help_View.cxx 9325 2012-04-05 05:12:30Z fabien $" +// "$Id: Fl_Help_View.cxx 10234 2014-08-21 12:18:32Z cand $" // // Fl_Help_View widget routines. // @@ -97,7 +97,7 @@ static char initial_load = 0; // Broken image... // -static const char *broken_xpm[] = +static const char * const broken_xpm[] = { "16 24 4 1", "@ c #000000", @@ -3362,7 +3362,7 @@ Fl_Help_View::value(const char *val) // I - Text to view static int // O - Code or -1 on error quote_char(const char *p) { // I - Quoted string int i; // Looping var - static struct { + static const struct { const char *name; int namelen; int code; @@ -3505,5 +3505,5 @@ hscrollbar_callback(Fl_Widget *s, void *) // -// End of "$Id: Fl_Help_View.cxx 9325 2012-04-05 05:12:30Z fabien $". +// End of "$Id: Fl_Help_View.cxx 10234 2014-08-21 12:18:32Z cand $". // diff --git a/src/Fl_Image.cxx b/src/Fl_Image.cxx index 69c972b..da0bccf 100644 --- a/src/Fl_Image.cxx +++ b/src/Fl_Image.cxx @@ -1,9 +1,9 @@ // -// "$Id: Fl_Image.cxx 9709 2012-11-09 16:02:08Z manolo $" +// "$Id: Fl_Image.cxx 10377 2014-10-14 11:53:51Z AlbrechtS $" // // Image drawing code for the Fast Light Tool Kit (FLTK). // -// Copyright 1998-2012 by Bill Spitzak and others. +// Copyright 1998-2014 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this @@ -34,6 +34,8 @@ void fl_restore_clip(); // from fl_rect.cxx // Base image class... // +Fl_RGB_Scaling Fl_Image::RGB_scaling_ = FL_RGB_SCALING_NEAREST; + /** The destructor is a virtual method that frees all memory used by the image. @@ -159,13 +161,40 @@ Fl_Image::measure(const Fl_Label *lo, // I - Label lh = img->h(); } +/** Sets the RGB image scaling method used for copy(int, int). + Applies to all RGB images, defaults to FL_RGB_SCALING_NEAREST. +*/ +void Fl_Image::RGB_scaling(Fl_RGB_Scaling method) { + RGB_scaling_ = method; +} + +/** Returns the currently used RGB image scaling method. */ +Fl_RGB_Scaling Fl_Image::RGB_scaling() { + return RGB_scaling_; +} + // // RGB image class... // size_t Fl_RGB_Image::max_size_ = ~((size_t)0); -/** The destructor free all memory and server resources that are used by the image. */ +int fl_convert_pixmap(const char*const* cdata, uchar* out, Fl_Color bg); + +/** The constructor creates a new RGBA image from the specified Fl_Pixmap. + + The RGBA image is built fully opaque except for the transparent area + of the pixmap that is assigned the \par bg color with full transparency */ +Fl_RGB_Image::Fl_RGB_Image(const Fl_Pixmap *pxm, Fl_Color bg): + Fl_Image(pxm->w(), pxm->h(), 4), id_(0), mask_(0) +{ + array = new uchar[w() * h() * d()]; + alloc_array = 1; + fl_convert_pixmap(pxm->data(), (uchar*)array, bg); + data((const char **)&array, 1); +} + +/** The destructor frees all memory and server resources that are used by the image. */ Fl_RGB_Image::~Fl_RGB_Image() { uncache(); if (alloc_array) delete[] (uchar *)array; @@ -245,25 +274,89 @@ Fl_Image *Fl_RGB_Image::copy(int W, int H) { new_image = new Fl_RGB_Image(new_array, W, H, d()); new_image->alloc_array = 1; - // Scale the image using a nearest-neighbor algorithm... - for (dy = H, sy = 0, yerr = H, new_ptr = new_array; dy > 0; dy --) { - for (dx = W, xerr = W, old_ptr = array + sy * line_d; dx > 0; dx --) { - for (c = 0; c < d(); c ++) *new_ptr++ = old_ptr[c]; + if (Fl_Image::RGB_scaling() == FL_RGB_SCALING_NEAREST) { + // Scale the image using a nearest-neighbor algorithm... + for (dy = H, sy = 0, yerr = H, new_ptr = new_array; dy > 0; dy --) { + for (dx = W, xerr = W, old_ptr = array + sy * line_d; dx > 0; dx --) { + for (c = 0; c < d(); c ++) *new_ptr++ = old_ptr[c]; + + old_ptr += xstep; + xerr -= xmod; - old_ptr += xstep; - xerr -= xmod; + if (xerr <= 0) { + xerr += W; + old_ptr += d(); + } + } - if (xerr <= 0) { - xerr += W; - old_ptr += d(); + sy += ystep; + yerr -= ymod; + if (yerr <= 0) { + yerr += H; + sy ++; } } + } else { + // Bilinear scaling (FL_RGB_SCALING_BILINEAR) + const float xscale = (w() - 1) / (float) W; + const float yscale = (h() - 1) / (float) H; + for (dy = 0; dy < H; dy++) { + float oldy = dy * yscale; + if (oldy >= h()) + oldy = h() - 1; + const float yfract = oldy - (unsigned) oldy; + + for (dx = 0; dx < W; dx++) { + new_ptr = new_array + dy * W * d() + dx * d(); + + float oldx = dx * xscale; + if (oldx >= w()) + oldx = w() - 1; + const float xfract = oldx - (unsigned) oldx; + + const unsigned leftx = oldx; + const unsigned lefty = oldy; + const unsigned rightx = oldx + 1 >= w() ? oldx : oldx + 1; + const unsigned righty = oldy; + const unsigned dleftx = oldx; + const unsigned dlefty = oldy + 1 >= h() ? oldy : oldy + 1; + const unsigned drightx = rightx; + const unsigned drighty = dlefty; + + uchar left[4], right[4], downleft[4], downright[4]; + memcpy(left, array + lefty * line_d + leftx * d(), d()); + memcpy(right, array + righty * line_d + rightx * d(), d()); + memcpy(downleft, array + dlefty * line_d + dleftx * d(), d()); + memcpy(downright, array + drighty * line_d + drightx * d(), d()); + + int i; + if (d() == 4) { + for (i = 0; i < 3; i++) { + left[i] *= left[3] / 255.0f; + right[i] *= right[3] / 255.0f; + downleft[i] *= downleft[3] / 255.0f; + downright[i] *= downright[3] / 255.0f; + } + } + + const float leftf = 1 - xfract; + const float rightf = xfract; + const float upf = 1 - yfract; + const float downf = yfract; + + for (i = 0; i < d(); i++) { + new_ptr[i] = (left[i] * leftf + + right[i] * rightf) * upf + + (downleft[i] * leftf + + downright[i] * rightf) * downf; + } - sy += ystep; - yerr -= ymod; - if (yerr <= 0) { - yerr += H; - sy ++; + if (d() == 4 && new_ptr[3]) { + for (i = 0; i < 3; i++) { + new_ptr[i] /= new_ptr[3] / 255.0f; + } + } + } } } @@ -453,6 +546,10 @@ static void imgProviderReleaseData (void *info, const void *data, size_t size) delete[] (unsigned char *)data; } +#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5 +typedef void (*CGDataProviderReleaseDataCallback)(void *info, const void *data, size_t size); +#endif + void Fl_Quartz_Graphics_Driver::draw(Fl_RGB_Image *img, int XP, int YP, int WP, int HP, int cx, int cy) { int X, Y, W, H; // Don't draw an empty image... @@ -595,7 +692,6 @@ void Fl_RGB_Image::label(Fl_Menu_Item* m) { m->label(_FL_IMAGE_LABEL, (const char*)this); } - // -// End of "$Id: Fl_Image.cxx 9709 2012-11-09 16:02:08Z manolo $". +// End of "$Id: Fl_Image.cxx 10377 2014-10-14 11:53:51Z AlbrechtS $". // diff --git a/src/Fl_Image_Surface.cxx b/src/Fl_Image_Surface.cxx new file mode 100644 index 0000000..b69b477 --- /dev/null +++ b/src/Fl_Image_Surface.cxx @@ -0,0 +1,157 @@ +// +// "$Id: Fl_Image_Surface.cxx 10200 2014-06-18 01:22:16Z manolo $" +// +// Draw-to-image code for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2014 by Bill Spitzak and others. +// +// This library is free software. Distribution and use rights are outlined in +// the file "COPYING" which should have been included with this file. If this +// file is missing or damaged, see the license at: +// +// http://www.fltk.org/COPYING.php +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +#include <FL/Fl_Image_Surface.H> +#include <FL/Fl_Printer.H> +#include <FL/Fl.H> + + +const char *Fl_Image_Surface::class_id = "Fl_Image_Surface"; + +/** The constructor. + \param w and \param h give the size in pixels of the resulting image. + */ +Fl_Image_Surface::Fl_Image_Surface(int w, int h) : Fl_Surface_Device(NULL) { + width = w; + height = h; +#if !(defined(__APPLE__) || defined(WIN32)) + gc = 0; + if (!fl_display) { // allows use of this class before any window is shown + fl_open_display(); + gc = XCreateGC(fl_display, RootWindow(fl_display, fl_screen), 0, 0); + fl_gc = gc; + } +#endif + offscreen = fl_create_offscreen(w, h); +#ifdef __APPLE__ + helper = new Fl_Quartz_Flipped_Surface_(width, height); + driver(helper->driver()); +#elif defined(WIN32) + helper = new Fl_GDI_Surface_(); + driver(helper->driver()); +#else + helper = new Fl_Xlib_Surface_(); + driver(helper->driver()); +#endif +} + +/** The destructor. + */ +Fl_Image_Surface::~Fl_Image_Surface() { + fl_delete_offscreen(offscreen); +#ifdef __APPLE__ + delete (Fl_Quartz_Flipped_Surface_*)helper; +#elif defined(WIN32) + delete (Fl_GDI_Surface_*)helper; +#else + if (gc) { XFreeGC(fl_display, gc); fl_gc = 0; } + delete (Fl_Xlib_Surface_*)helper; +#endif +} + +/** Returns an image made of all drawings sent to the Fl_Image_Surface object. + The returned object contains its own copy of the RGB data. + */ +Fl_RGB_Image* Fl_Image_Surface::image() +{ + unsigned char *data; +#ifdef __APPLE__ + CGContextFlush(offscreen); + data = fl_read_image(NULL, 0, 0, width, height, 0); + fl_end_offscreen(); +#elif defined(WIN32) + fl_pop_clip(); + data = fl_read_image(NULL, 0, 0, width, height, 0); + RestoreDC(fl_gc, _savedc); + DeleteDC(fl_gc); + _ss->set_current(); + fl_window=_sw; + fl_gc = _sgc; +#else + fl_pop_clip(); + data = fl_read_image(NULL, 0, 0, width, height, 0); + fl_window = pre_window; + previous->set_current(); +#endif + Fl_RGB_Image *image = new Fl_RGB_Image(data, width, height); + image->alloc_array = 1; + return image; +} + +/** Draws a widget in the image surface + + \param widget any FLTK widget (e.g., standard, custom, window, GL view) to draw in the image + \param delta_x and \param delta_y give + the position in the image of the top-left corner of the widget + */ +void Fl_Image_Surface::draw(Fl_Widget *widget, int delta_x, int delta_y) +{ + helper->print_widget(widget, delta_x, delta_y); +} + + +void Fl_Image_Surface::set_current() +{ +#if defined(__APPLE__) + fl_begin_offscreen(offscreen); + fl_pop_clip(); + Fl_Surface_Device::set_current(); + fl_push_no_clip(); +#elif defined(WIN32) + _sgc=fl_gc; + _sw=fl_window; + _ss = Fl_Surface_Device::surface(); + Fl_Surface_Device::set_current(); + fl_gc = fl_makeDC(offscreen); + _savedc = SaveDC(fl_gc); + fl_window=(HWND)offscreen; + fl_push_no_clip(); +#else + pre_window = fl_window; + fl_window = offscreen; + previous = Fl_Surface_Device::surface(); + Fl_Surface_Device::set_current(); + fl_push_no_clip(); +#endif +} + +#if defined(__APPLE__) + +Fl_Quartz_Flipped_Surface_::Fl_Quartz_Flipped_Surface_(int w, int h) : Fl_Quartz_Surface_(w, h) { +} + +void Fl_Quartz_Flipped_Surface_::translate(int x, int y) { + CGContextRestoreGState(fl_gc); + CGContextSaveGState(fl_gc); + CGContextTranslateCTM(fl_gc, x, -y); + CGContextSaveGState(fl_gc); + CGContextTranslateCTM(fl_gc, 0, height); + CGContextScaleCTM(fl_gc, 1.0f, -1.0f); +} + +void Fl_Quartz_Flipped_Surface_::untranslate() { + CGContextRestoreGState(fl_gc); +} + +const char *Fl_Quartz_Flipped_Surface_::class_id = "Fl_Quartz_Flipped_Surface_"; + +#endif // __APPLE__ + +// +// End of "$Id: Fl_Image_Surface.cxx 10200 2014-06-18 01:22:16Z manolo $". +// diff --git a/src/Fl_Input.cxx b/src/Fl_Input.cxx index f1e8e1c..623e87f 100644 --- a/src/Fl_Input.cxx +++ b/src/Fl_Input.cxx @@ -1,5 +1,5 @@ // -// "$Id: Fl_Input.cxx 9637 2012-07-24 04:37:22Z matt $" +// "$Id: Fl_Input.cxx 10031 2013-12-13 16:28:38Z manolo $" // // Input widget for the Fast Light Tool Kit (FLTK). // @@ -358,6 +358,11 @@ int Fl_Input::handle_key() { else replace(position(), del ? position()-del : mark(), Fl::event_text(), Fl::event_length()); } +#ifdef __APPLE__ + if (Fl::compose_state) { + this->mark( this->position() - Fl::compose_state ); + } +#endif return 1; } @@ -583,8 +588,16 @@ int Fl_Input::handle_key() { int Fl_Input::handle(int event) { static int dnd_save_position, dnd_save_mark, drag_start = -1, newpos; - static Fl_Widget *dnd_save_focus; + static Fl_Widget *dnd_save_focus = NULL; switch (event) { +#ifdef __APPLE__ + case FL_UNFOCUS: + if (Fl::compose_state) { + this->mark( this->position() ); + Fl::reset_marked_text(); + } + break; +#endif case FL_FOCUS: switch (Fl::event_key()) { case FL_Right: @@ -617,7 +630,8 @@ int Fl_Input::handle(int event) { && !Fl::event_state(FL_SHIFT) // no shift? && !tab_nav() // with tab navigation disabled? && input_type() == FL_MULTILINE_INPUT // with a multiline input? - && (mark()==0 && position()==size())) { // while entire field selected? + && size() > 0 // non-empty field? + && ((mark()==0 && position()==size()) || (position()==0 && mark()==size()))) {// while entire field selected? // Set cursor to the end of the selection... if (mark() > position()) position(mark()); @@ -662,6 +676,7 @@ int Fl_Input::handle(int event) { // save the position because sometimes we don't get DND_ENTER: dnd_save_position = position(); dnd_save_mark = mark(); + dnd_save_focus = this; // drag the data: copy(0); Fl::dnd(); return 1; @@ -693,10 +708,10 @@ int Fl_Input::handle(int event) { case FL_DND_ENTER: Fl::belowmouse(this); // send the leave events first - dnd_save_position = position(); - dnd_save_mark = mark(); - dnd_save_focus = Fl::focus(); if (dnd_save_focus != this) { + dnd_save_position = position(); + dnd_save_mark = mark(); + dnd_save_focus = Fl::focus(); Fl::focus(this); handle(FL_FOCUS); } @@ -722,16 +737,33 @@ int Fl_Input::handle(int event) { #if DND_OUT_XXXX if (!focused()) #endif - if (dnd_save_focus != this) { + if (dnd_save_focus && dnd_save_focus != this) { Fl::focus(dnd_save_focus); handle(FL_UNFOCUS); } #if !(defined(__APPLE__) || defined(WIN32)) Fl::first_window()->cursor(FL_CURSOR_MOVE); #endif + dnd_save_focus = NULL; return 1; case FL_DND_RELEASE: + if (dnd_save_focus == this) { // if the dragged text comes from the same widget + // remove the selected text + int old_position = position(); + if (dnd_save_mark > dnd_save_position) { + int tmp = dnd_save_mark; + dnd_save_mark = dnd_save_position; + dnd_save_position = tmp; + } + replace(dnd_save_mark, dnd_save_position, NULL, 0); + if (old_position > dnd_save_position) position(old_position - (dnd_save_position - dnd_save_mark)); + else position(old_position); + } + else if(dnd_save_focus) { + dnd_save_focus->handle(FL_UNFOCUS); + } + dnd_save_focus = NULL; take_focus(); return 1; @@ -766,12 +798,14 @@ Fl_Float_Input::Fl_Float_Input(int X,int Y,int W,int H,const char *l) : Fl_Input(X,Y,W,H,l) { type(FL_FLOAT_INPUT); + clear_flag(MAC_USE_ACCENTS_MENU); } Fl_Int_Input::Fl_Int_Input(int X,int Y,int W,int H,const char *l) : Fl_Input(X,Y,W,H,l) { type(FL_INT_INPUT); + clear_flag(MAC_USE_ACCENTS_MENU); } @@ -796,9 +830,19 @@ Fl_Multiline_Output::Fl_Multiline_Output(int X,int Y,int W,int H,const char *l) Fl_Secret_Input::Fl_Secret_Input(int X,int Y,int W,int H,const char *l) : Fl_Input(X,Y,W,H,l) { type(FL_SECRET_INPUT); + clear_flag(MAC_USE_ACCENTS_MENU); } +int Fl_Secret_Input::handle(int event) { + int retval = Fl_Input::handle(event); +#ifdef __APPLE__ + if (event == FL_KEYBOARD && Fl::compose_state) { + this->mark( this->position() ); // don't underline marked text + } +#endif + return retval; +} // -// End of "$Id: Fl_Input.cxx 9637 2012-07-24 04:37:22Z matt $". +// End of "$Id: Fl_Input.cxx 10031 2013-12-13 16:28:38Z manolo $". // diff --git a/src/Fl_Input_.cxx b/src/Fl_Input_.cxx index ff29d2a..08b4222 100644 --- a/src/Fl_Input_.cxx +++ b/src/Fl_Input_.cxx @@ -1,5 +1,5 @@ // -// "$Id: Fl_Input_.cxx 9326 2012-04-05 14:30:19Z AlbrechtS $" +// "$Id: Fl_Input_.cxx 10402 2014-10-28 15:33:17Z cand $" // // Common input widget routines for the Fast Light Tool Kit (FLTK). // @@ -339,10 +339,25 @@ void Fl_Input_::drawtext(int X, int Y, int W, int H) { int offset2; if (pp <= e) x2 = xpos + (float)expandpos(p, pp, buf, &offset2); else offset2 = (int) strlen(buf); +#ifdef __APPLE__ // Mac OS: underline marked ( = selected + Fl::compose_state != 0) text + if (Fl::compose_state) { + fl_color(textcolor()); + } + else +#endif + { fl_color(selection_color()); fl_rectf((int)(x1+0.5), Y+ypos, (int)(x2-x1+0.5), height); fl_color(fl_contrast(textcolor(), selection_color())); + } fl_draw(buf+offset1, offset2-offset1, x1, (float)(Y+ypos+desc)); +#ifdef __APPLE__ // Mac OS: underline marked ( = selected + Fl::compose_state != 0) text + if (Fl::compose_state) { + fl_color( fl_color_average(textcolor(), color(), 0.6) ); + float width = fl_width(buf+offset1, offset2-offset1); + fl_line(x1, Y+ypos+height-1, x1+width, Y+ypos+height-1); + } +#endif if (pp < e) { fl_color(tc); fl_draw(buf+offset2, (int) strlen(buf+offset2), x2, (float)(Y+ypos+desc)); @@ -357,7 +372,11 @@ void Fl_Input_::drawtext(int X, int Y, int W, int H) { CONTINUE2: // draw the cursor: - if (Fl::focus() == this && selstart == selend && + if (Fl::focus() == this && ( +#ifdef __APPLE__ + Fl::compose_state || +#endif + selstart == selend) && position() >= p-value() && position() <= e-value()) { fl_color(cursor_color()); // cursor position may need to be recomputed (see STR #2486) @@ -369,6 +388,9 @@ void Fl_Input_::drawtext(int X, int Y, int W, int H) { } else { fl_rectf((int)(xpos+curx+0.5), Y+ypos, 2, height); } +#ifdef __APPLE__ + Fl::insertion_point_location(xpos+curx, Y+ypos+height, height); +#endif } CONTINUE: @@ -397,25 +419,27 @@ void Fl_Input_::drawtext(int X, int Y, int W, int H) { /** \internal Simple function that determines if a character could be part of a word. - \todo This function is not ucs4-aware. + \todo This function is not UTF-8-aware. */ static int isword(char c) { - return (c&128 || isalnum(c) || strchr("#%&-/@\\_~", c)); + return (c&128 || isalnum(c) || strchr("#%-@_~", c)); } /** Finds the end of a word. - This call calculates the end of a word based on the given - index \p i. Calling this function repeatedly will move - forwards to the end of the text. - + Returns the index after the last byte of a word. + If the index is already at the end of a word, it will find the + end of the following word, so if you call it repeatedly you will + move forwards to the end of the text. + + Note that this is inconsistent with line_end(). + \param [in] i starting index for the search \return end of the word */ int Fl_Input_::word_end(int i) const { if (input_type() == FL_SECRET_INPUT) return size(); - //while (i < size() && !isword(index(i))) i++; while (i < size() && !isword(index(i))) i++; while (i < size() && isword(index(i))) i++; return i; @@ -424,17 +448,18 @@ int Fl_Input_::word_end(int i) const { /** Finds the start of a word. - This call calculates the start of a word based on the given - index \p i. Calling this function repeatedly will move - backwards to the beginning of the text. - + Returns the index of the first byte of a word. + If the index is already at the beginning of a word, it will find the + beginning of the previous word, so if you call it repeatedly you will + move backwards to the beginning of the text. + + Note that this is inconsistent with line_start(). + \param [in] i starting index for the search - \return start of the word + \return start of the word, or previous word */ int Fl_Input_::word_start(int i) const { if (input_type() == FL_SECRET_INPUT) return 0; -// if (i >= size() || !isword(index(i))) -// while (i > 0 && !isword(index(i-1))) i--; while (i > 0 && !isword(index(i-1))) i--; while (i > 0 && isword(index(i-1))) i--; return i; @@ -496,6 +521,20 @@ int Fl_Input_::line_start(int i) const { } else return j; } +static int strict_word_start(const char *s, int i, int itype) { + if (itype == FL_SECRET_INPUT) return 0; + while (i > 0 && !isspace(s[i-1])) + i--; + return i; +} + +static int strict_word_end(const char *s, int len, int i, int itype) { + if (itype == FL_SECRET_INPUT) return len; + while (i < len && !isspace(s[i])) + i++; + return i; +} + /** Handles mouse clicks and mouse moves. \todo Add comment and parameters @@ -549,16 +588,16 @@ void Fl_Input_::handle_mouse(int X, int Y, int /*W*/, int /*H*/, int drag) { newpos = line_end(newpos); newmark = line_start(newmark); } else { - newpos = word_end(newpos); - newmark = word_start(newmark); + newpos = strict_word_end(value(), size(), newpos, input_type()); + newmark = strict_word_start(value(), newmark, input_type()); } } else { if (Fl::event_clicks() > 1) { newpos = line_start(newpos); newmark = line_end(newmark); } else { - newpos = word_start(newpos); - newmark = word_end(newmark); + newpos = strict_word_start(value(), newpos, input_type()); + newmark = strict_word_end(value(), size(), newmark, input_type()); } } // if the multiple click does not increase the selection, revert @@ -1100,6 +1139,7 @@ Fl_Input_::Fl_Input_(int X, int Y, int W, int H, const char* l) maximum_size_ = 32767; shortcut_ = 0; set_flag(SHORTCUT_LABEL); + set_flag(MAC_USE_ACCENTS_MENU); tab_nav(1); } @@ -1298,5 +1338,5 @@ unsigned int Fl_Input_::index(int i) const } // -// End of "$Id: Fl_Input_.cxx 9326 2012-04-05 14:30:19Z AlbrechtS $". +// End of "$Id: Fl_Input_.cxx 10402 2014-10-28 15:33:17Z cand $". // diff --git a/src/Fl_JPEG_Image.cxx b/src/Fl_JPEG_Image.cxx index e62768f..179ade6 100644 --- a/src/Fl_JPEG_Image.cxx +++ b/src/Fl_JPEG_Image.cxx @@ -1,5 +1,5 @@ // -// "$Id: Fl_JPEG_Image.cxx 9709 2012-11-09 16:02:08Z manolo $" +// "$Id: Fl_JPEG_Image.cxx 9980 2013-09-21 16:41:23Z greg.ercolano $" // // Fl_JPEG_Image routines. // @@ -212,35 +212,39 @@ typedef struct { typedef my_source_mgr *my_src_ptr; -void init_source (j_decompress_ptr cinfo) { - my_src_ptr src = (my_src_ptr)cinfo->src; - src->s = src->data; -} +extern "C" { -boolean fill_input_buffer(j_decompress_ptr cinfo) { - my_src_ptr src = (my_src_ptr)cinfo->src; - size_t nbytes = 4096; - src->pub.next_input_byte = src->s; - src->pub.bytes_in_buffer = nbytes; - src->s += nbytes; - return TRUE; -} + static void init_source(j_decompress_ptr cinfo) { + my_src_ptr src = (my_src_ptr)cinfo->src; + src->s = src->data; + } -void term_source(j_decompress_ptr cinfo) -{ -} + static boolean fill_input_buffer(j_decompress_ptr cinfo) { + my_src_ptr src = (my_src_ptr)cinfo->src; + size_t nbytes = 4096; + src->pub.next_input_byte = src->s; + src->pub.bytes_in_buffer = nbytes; + src->s += nbytes; + return TRUE; + } + + static void term_source(j_decompress_ptr cinfo) + { + } -void skip_input_data(j_decompress_ptr cinfo, long num_bytes) { - my_src_ptr src = (my_src_ptr)cinfo->src; - if (num_bytes > 0) { - while (num_bytes > (long)src->pub.bytes_in_buffer) { - num_bytes -= (long)src->pub.bytes_in_buffer; - fill_input_buffer(cinfo); + static void skip_input_data(j_decompress_ptr cinfo, long num_bytes) { + my_src_ptr src = (my_src_ptr)cinfo->src; + if (num_bytes > 0) { + while (num_bytes > (long)src->pub.bytes_in_buffer) { + num_bytes -= (long)src->pub.bytes_in_buffer; + fill_input_buffer(cinfo); + } + src->pub.next_input_byte += (size_t) num_bytes; + src->pub.bytes_in_buffer -= (size_t) num_bytes; } - src->pub.next_input_byte += (size_t) num_bytes; - src->pub.bytes_in_buffer -= (size_t) num_bytes; } -} + +} // extern "C" static void jpeg_mem_src(j_decompress_ptr cinfo, const unsigned char *data) { @@ -373,5 +377,5 @@ Fl_JPEG_Image::Fl_JPEG_Image(const char *name, const unsigned char *data) } // -// End of "$Id: Fl_JPEG_Image.cxx 9709 2012-11-09 16:02:08Z manolo $". +// End of "$Id: Fl_JPEG_Image.cxx 9980 2013-09-21 16:41:23Z greg.ercolano $". // diff --git a/src/Fl_Menu.cxx b/src/Fl_Menu.cxx index 4e07383..20c9eed 100644 --- a/src/Fl_Menu.cxx +++ b/src/Fl_Menu.cxx @@ -1,5 +1,5 @@ // -// "$Id: Fl_Menu.cxx 9738 2012-12-07 16:29:49Z AlbrechtS $" +// "$Id: Fl_Menu.cxx 10211 2014-06-28 12:29:51Z manolo $" // // Menu code for the Fast Light Tool Kit (FLTK). // @@ -353,7 +353,11 @@ menuwindow::menuwindow(const Fl_Menu_Item* m, int X, int Y, int Wp, int Hp, if (Wp > W) W = Wp; if (Wtitle > W) W = Wtitle; - if (X < scr_x) X = scr_x; if (X > scr_x+scr_w-W) X = right_edge-W; + if (X < scr_x) X = scr_x; + // this change improves popup submenu positioning at right screen edge, + // but it makes right_edge argument useless + //if (X > scr_x+scr_w-W) X = right_edge-W; + if (X > scr_x+scr_w-W) X = scr_x+scr_w-W; x(X); w(W); h((numitems ? itemheight*numitems-LEADING : 0)+2*BW+3); if (selected >= 0) { @@ -916,10 +920,12 @@ const Fl_Menu_Item* Fl_Menu_Item::pulldown( if (n->selected>=0) { int dy = n->y()-nY; int dx = n->x()-nX; + int waX, waY, waW, waH; + Fl::screen_work_area(waX, waY, waW, waH, X, Y); for (int menu = 0; menu <= pp.menu_number; menu++) { menuwindow* tt = pp.p[menu]; - int nx = tt->x()+dx; if (nx < 0) {nx = 0; dx = -tt->x();} - int ny = tt->y()+dy; if (ny < 0) {ny = 0; dy = -tt->y();} + int nx = tt->x()+dx; if (nx < waX) {nx = waX; dx = -tt->x() + waX;} + int ny = tt->y()+dy; if (ny < waY) {ny = waY; dy = -tt->y() + waY;} tt->position(nx, ny); } setitem(pp.nummenus-1, n->selected); @@ -1046,5 +1052,5 @@ const Fl_Menu_Item* Fl_Menu_Item::test_shortcut() const { } // -// End of "$Id: Fl_Menu.cxx 9738 2012-12-07 16:29:49Z AlbrechtS $". +// End of "$Id: Fl_Menu.cxx 10211 2014-06-28 12:29:51Z manolo $". // diff --git a/src/Fl_Menu_Window.cxx b/src/Fl_Menu_Window.cxx index f49d74d..6380572 100644 --- a/src/Fl_Menu_Window.cxx +++ b/src/Fl_Menu_Window.cxx @@ -1,5 +1,5 @@ // -// "$Id: Fl_Menu_Window.cxx 9637 2012-07-24 04:37:22Z matt $" +// "$Id: Fl_Menu_Window.cxx 10095 2014-02-07 00:09:52Z AlbrechtS $" // // Menu window code for the Fast Light Tool Kit (FLTK). // @@ -54,6 +54,7 @@ void Fl_Menu_Window::show() { } void Fl_Menu_Window::flush() { + if (!shown()) return; #if HAVE_OVERLAY if (!fl_overlay_visual || !overlay()) {Fl_Single_Window::flush(); return;} Fl_X *myi = Fl_X::i(this); @@ -111,5 +112,5 @@ Fl_Menu_Window::Fl_Menu_Window(int X, int Y, int W, int H, const char *l) // -// End of "$Id: Fl_Menu_Window.cxx 9637 2012-07-24 04:37:22Z matt $". +// End of "$Id: Fl_Menu_Window.cxx 10095 2014-02-07 00:09:52Z AlbrechtS $". // diff --git a/src/Fl_Native_File_Chooser_FLTK.cxx b/src/Fl_Native_File_Chooser_FLTK.cxx index e3160b5..bedd7c7 100644 --- a/src/Fl_Native_File_Chooser_FLTK.cxx +++ b/src/Fl_Native_File_Chooser_FLTK.cxx @@ -1,10 +1,9 @@ -// "$Id: Fl_Native_File_Chooser_FLTK.cxx 9547 2012-05-25 14:46:02Z manolo $" +// "$Id: Fl_Native_File_Chooser_FLTK.cxx 10349 2014-10-01 17:24:55Z manolo $" // -// FLTK native OS file chooser widget +// FLTK native file chooser widget wrapper for GTK's GtkFileChooserDialog // -// Copyright 1998-2010 by Bill Spitzak and others. -// Copyright 2004 Greg Ercolano. -// API changes + filter improvements by Nathan Vander Wilt 2005 +// Copyright 1998-2014 by Bill Spitzak and others. +// Copyright 2012 IMM // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this @@ -17,6 +16,7 @@ // http://www.fltk.org/str.php // +#include <config.h> #include <FL/Fl_Native_File_Chooser.H> #include <FL/Fl_File_Icon.H> #define FLTK_CHOOSER_SINGLE Fl_File_Chooser::SINGLE @@ -25,24 +25,20 @@ #define FLTK_CHOOSER_CREATE Fl_File_Chooser::CREATE #include "Fl_Native_File_Chooser_common.cxx" +#include "Fl_Native_File_Chooser_GTK.cxx" + #include <sys/stat.h> #include <string.h> +int Fl_Native_File_Chooser::have_looked_for_GTK_libs = 0; + /** - The constructor. Internally allocates the native widgets. - Optional \p val presets the type of browser this will be, - which can also be changed with type(). -*/ + The constructor. Internally allocates the native widgets. + Optional \p val presets the type of browser this will be, + which can also be changed with type(). + */ Fl_Native_File_Chooser::Fl_Native_File_Chooser(int val) { - //// CANT USE THIS -- MESSES UP LINKING/CREATES DEPENDENCY ON fltk_images. - //// Have app call this from main() instead. - //// - //// static int init = 0; // 'first time' initialize flag - //// if ( init == 0 ) { - //// // Initialize when instanced for first time - //// Fl_File_Icon::load_system_icons(); - //// init = 1; - //// } +#if FLTK_ABI_VERSION <= 10302 _btype = val; _options = NO_OPTIONS; _filter = NULL; @@ -52,17 +48,203 @@ Fl_Native_File_Chooser::Fl_Native_File_Chooser(int val) { _prevvalue = NULL; _directory = NULL; _errmsg = NULL; - _file_chooser = new Fl_File_Chooser(NULL, NULL, 0, NULL); - type(val); // do this after _file_chooser created - _nfilters = 0; -} +#endif // FLTK_ABI_VERSION + if (have_looked_for_GTK_libs == 0) { + // First Time here, try to find the GTK libs if they are installed +#if HAVE_DLSYM && HAVE_DLFCN_H + if (Fl::option(Fl::OPTION_FNFC_USES_GTK)) { + Fl_GTK_File_Chooser::probe_for_GTK_libs(); + } +#endif + have_looked_for_GTK_libs = -1; + } + // if we found all the GTK functions we need, we will use the GtkFileChooserDialog + if (Fl_GTK_File_Chooser::did_find_GTK_libs) _gtk_file_chooser = new Fl_GTK_File_Chooser(val); + else _x11_file_chooser = new Fl_FLTK_File_Chooser(val); +} /** - Destructor. - Deallocates any resources allocated to this widget. -*/ + Destructor. + Deallocates any resources allocated to this widget. + */ Fl_Native_File_Chooser::~Fl_Native_File_Chooser() { + delete _x11_file_chooser; +} + +/** + Sets the current Fl_Native_File_Chooser::Type of browser. + */ +void Fl_Native_File_Chooser::type(int t) { return _x11_file_chooser->type(t); } +/** + Gets the current Fl_Native_File_Chooser::Type of browser. + */ +int Fl_Native_File_Chooser::type() const { return _x11_file_chooser->type(); } +/** + Sets the platform specific chooser options to \p val. + \p val is expected to be one or more Fl_Native_File_Chooser::Option flags ORed together. + Some platforms have OS-specific functions that can be enabled/disabled via this method. + <P> + \code + Flag Description Win Mac Other + -------------- ----------------------------------------------- ------- ------- ------- + NEW_FOLDER Shows the 'New Folder' button. Ignored Used Used + PREVIEW Enables the 'Preview' mode by default. Ignored Ignored Used + SAVEAS_CONFIRM Confirm dialog if BROWSE_SAVE_FILE file exists. Used Used Used + USE_FILTER_EXT Chooser filter pilots the output file extension. Ignored Used Ignored +\endcode + */ +void Fl_Native_File_Chooser::options(int o) { _x11_file_chooser->options(o); } +/** + Gets the platform specific Fl_Native_File_Chooser::Option flags. + */ +int Fl_Native_File_Chooser::options() const { return _x11_file_chooser->options(); } + +/** + Returns the number of filenames (or directory names) the user selected. + <P> + \b Example: + \code + if ( fnfc->show() == 0 ) { + // Print all filenames user selected + for (int n=0; n<fnfc->count(); n++ ) { + printf("%d) '%s'\n", n, fnfc->filename(n)); + } + } + \endcode + */ +int Fl_Native_File_Chooser::count() const { return _x11_file_chooser->count(); } +/** + Return the filename the user chose. + Use this if only expecting a single filename. + If more than one filename is expected, use filename(int) instead. + Return value may be "" if no filename was chosen (eg. user cancelled). + */ +const char *Fl_Native_File_Chooser::filename() const { return _x11_file_chooser->filename(); } +/** + Return one of the filenames the user selected. + Use count() to determine how many filenames the user selected. + <P> + \b Example: + \code + if ( fnfc->show() == 0 ) { + // Print all filenames user selected + for (int n=0; n<fnfc->count(); n++ ) { + printf("%d) '%s'\n", n, fnfc->filename(n)); + } + } + \endcode + */ +const char *Fl_Native_File_Chooser::filename(int i) const { return _x11_file_chooser->filename(i); } +/** + Preset the directory the browser will show when opened. + If \p val is NULL, or no directory is specified, the chooser will attempt + to use the last non-cancelled folder. + */ +void Fl_Native_File_Chooser::directory(const char *val) { _x11_file_chooser->directory(val); } +/** + Returns the current preset directory() value. + */ +const char *Fl_Native_File_Chooser::directory() const { return _x11_file_chooser->directory(); } +/** + Set the title of the file chooser's dialog window. + Can be NULL if no title desired. + The default title varies according to the platform, so you are advised to set the title explicitly. + */ +void Fl_Native_File_Chooser::title(const char *t) { _x11_file_chooser->title(t); } +/** + Get the title of the file chooser's dialog window. + Return value may be NULL if no title was set. + */ +const char* Fl_Native_File_Chooser::title() const { return _x11_file_chooser->title(); } +/** + Returns the filter string last set. + Can be NULL if no filter was set. + */ +const char *Fl_Native_File_Chooser::filter() const { return _x11_file_chooser->filter(); } +/** + Sets the filename filters used for browsing. + The default is NULL, which browses all files. + <P> + The filter string can be any of: + <P> + - A single wildcard (eg. "*.txt") + - Multiple wildcards (eg. "*.{cxx,h,H}") + - A descriptive name followed by a "\t" and a wildcard (eg. "Text Files\t*.txt") + - A list of separate wildcards with a "\n" between each (eg. "*.{cxx,H}\n*.txt") + - A list of descriptive names and wildcards (eg. "C++ Files\t*.{cxx,H}\nTxt Files\t*.txt") + <P> + The format of each filter is a wildcard, or an optional user description + followed by '\\t' and the wildcard. + <P> + On most platforms, each filter is available to the user via a pulldown menu + in the file chooser. The 'All Files' option is always available to the user. + */ +void Fl_Native_File_Chooser::filter(const char *f) { _x11_file_chooser->filter(f); } +/** + Gets how many filters were available, not including "All Files" + */ +int Fl_Native_File_Chooser::filters() const { return _x11_file_chooser->filters(); } +/** + Sets which filter will be initially selected. + + The first filter is indexed as 0. + If filter_value()==filters(), then "All Files" was chosen. + If filter_value() > filters(), then a custom filter was set. + */ +void Fl_Native_File_Chooser::filter_value(int i) { _x11_file_chooser->filter_value(i); } +/** + Returns which filter value was last selected by the user. + This is only valid if the chooser returns success. + */ +int Fl_Native_File_Chooser::filter_value() const { return _x11_file_chooser->filter_value(); } +/** + Sets the default filename for the chooser. + Use directory() to set the default directory. + Mainly used to preset the filename for save dialogs, + and on most platforms can be used for opening files as well. + */ +void Fl_Native_File_Chooser::preset_file(const char* f) { _x11_file_chooser->preset_file(f); } +/** + Get the preset filename. + */ +const char* Fl_Native_File_Chooser::preset_file() const { return _x11_file_chooser->preset_file(); } +/** + Returns a system dependent error message for the last method that failed. + This message should at least be flagged to the user in a dialog box, or to some kind of error log. + Contents will be valid only for methods that document errmsg() will have info on failures. + */ +const char *Fl_Native_File_Chooser::errmsg() const { return _x11_file_chooser->errmsg(); } +/** + Post the chooser's dialog. Blocks until dialog has been completed or cancelled. + \returns + - 0 -- user picked a file + - 1 -- user cancelled + - -1 -- failed; errmsg() has reason + */ +int Fl_Native_File_Chooser::show() { return _x11_file_chooser->show(); } + + +Fl_FLTK_File_Chooser::Fl_FLTK_File_Chooser(int val) { + _btype = 0; + _options = 0; + _filter = NULL; + _filtvalue = 0; + _parsedfilt = NULL; + _preset_file = NULL; + _prevvalue = NULL; + _directory = NULL; + _errmsg = NULL; + _file_chooser= NULL; + if (val >= 0) { + _file_chooser = new Fl_File_Chooser(NULL, NULL, 0, NULL); + type(val); // do this after _file_chooser created + } + _nfilters = 0; +} + +Fl_FLTK_File_Chooser::~Fl_FLTK_File_Chooser() { delete _file_chooser; + _file_chooser = NULL; _filter = strfree(_filter); _parsedfilt = strfree(_parsedfilt); _preset_file = strfree(_preset_file); @@ -71,285 +253,169 @@ Fl_Native_File_Chooser::~Fl_Native_File_Chooser() { _errmsg = strfree(_errmsg); } + // PRIVATE: SET ERROR MESSAGE -void Fl_Native_File_Chooser::errmsg(const char *msg) { +void Fl_FLTK_File_Chooser::errmsg(const char *msg) { _errmsg = strfree(_errmsg); _errmsg = strnew(msg); } // PRIVATE: translate Native types to Fl_File_Chooser types -int Fl_Native_File_Chooser::type_fl_file(int val) { +int Fl_FLTK_File_Chooser::type_fl_file(int val) { switch (val) { - case BROWSE_FILE: - return(FLTK_CHOOSER_SINGLE); - case BROWSE_DIRECTORY: - return(FLTK_CHOOSER_SINGLE | FLTK_CHOOSER_DIRECTORY); - case BROWSE_MULTI_FILE: - return(FLTK_CHOOSER_MULTI); - case BROWSE_MULTI_DIRECTORY: - return(FLTK_CHOOSER_DIRECTORY | FLTK_CHOOSER_MULTI); - case BROWSE_SAVE_FILE: - return(FLTK_CHOOSER_SINGLE | FLTK_CHOOSER_CREATE); - case BROWSE_SAVE_DIRECTORY: - return(FLTK_CHOOSER_DIRECTORY | FLTK_CHOOSER_MULTI | FLTK_CHOOSER_CREATE); + case Fl_Native_File_Chooser::BROWSE_FILE: + return(Fl_File_Chooser::SINGLE); + case Fl_Native_File_Chooser::BROWSE_DIRECTORY: + return(Fl_File_Chooser::SINGLE | Fl_File_Chooser::DIRECTORY); + case Fl_Native_File_Chooser::BROWSE_MULTI_FILE: + return(Fl_File_Chooser::MULTI); + case Fl_Native_File_Chooser::BROWSE_MULTI_DIRECTORY: + return(Fl_File_Chooser::DIRECTORY | Fl_File_Chooser::MULTI); + case Fl_Native_File_Chooser::BROWSE_SAVE_FILE: + return(Fl_File_Chooser::SINGLE | Fl_File_Chooser::CREATE); + case Fl_Native_File_Chooser::BROWSE_SAVE_DIRECTORY: + return(Fl_File_Chooser::DIRECTORY | Fl_File_Chooser::MULTI | Fl_File_Chooser::CREATE); default: - return(FLTK_CHOOSER_SINGLE); + return(Fl_File_Chooser::SINGLE); } } -/** - Sets the current Fl_Native_File_Chooser::Type of browser. - */ -void Fl_Native_File_Chooser::type(int val) { +void Fl_FLTK_File_Chooser::type(int val) { _btype = val; _file_chooser->type(type_fl_file(val)); } -/** - Gets the current Fl_Native_File_Chooser::Type of browser. - */ -int Fl_Native_File_Chooser::type() const { +int Fl_FLTK_File_Chooser::type() const { return(_btype); } -/** - Sets the platform specific chooser options to \p val. - \p val is expected to be one or more Fl_Native_File_Chooser::Option flags ORed together. - Some platforms have OS-specific functions that can be enabled/disabled via this method. - <P> - \code - Flag Description Win Mac Other - -------------- ----------------------------------------------- ------- ------- ------- - NEW_FOLDER Shows the 'New Folder' button. Ignored Used Used - PREVIEW Enables the 'Preview' mode by default. Ignored Ignored Used - SAVEAS_CONFIRM Confirm dialog if BROWSE_SAVE_FILE file exists. Used Used Used - \endcode -*/ -void Fl_Native_File_Chooser::options(int val) { +void Fl_FLTK_File_Chooser::options(int val) { _options = val; } -/** - Gets the platform specific Fl_Native_File_Chooser::Option flags. -*/ -int Fl_Native_File_Chooser::options() const { +int Fl_FLTK_File_Chooser::options() const { return(_options); } -/** - Post the chooser's dialog. Blocks until dialog has been completed or cancelled. - \returns - - 0 -- user picked a file - - 1 -- user cancelled - - -1 -- failed; errmsg() has reason -*/ -int Fl_Native_File_Chooser::show() { - // FILTER - if ( _parsedfilt ) { - _file_chooser->filter(_parsedfilt); - } +int Fl_FLTK_File_Chooser::show() { - // FILTER VALUE - // Set this /after/ setting the filter - // - _file_chooser->filter_value(_filtvalue); + // FILTER + if ( _parsedfilt ) { + _file_chooser->filter(_parsedfilt); + } - // DIRECTORY - if ( _directory && _directory[0] ) { - _file_chooser->directory(_directory); - } else { - _file_chooser->directory(_prevvalue); - } + // FILTER VALUE + // Set this /after/ setting the filter + // + _file_chooser->filter_value(_filtvalue); - // PRESET FILE - if ( _preset_file ) { - _file_chooser->value(_preset_file); - } + // DIRECTORY + if ( _directory && _directory[0] ) { + _file_chooser->directory(_directory); + } else { + _file_chooser->directory(_prevvalue); + } - // OPTIONS: PREVIEW - _file_chooser->preview( (options() & PREVIEW) ? 1 : 0); + // PRESET FILE + if ( _preset_file ) { + _file_chooser->value(_preset_file); + } - // OPTIONS: NEW FOLDER - if ( options() & NEW_FOLDER ) - _file_chooser->type(_file_chooser->type() | FLTK_CHOOSER_CREATE); // on + // OPTIONS: PREVIEW + _file_chooser->preview( (options() & Fl_Native_File_Chooser::PREVIEW) ? 1 : 0); - // SHOW - _file_chooser->show(); + // OPTIONS: NEW FOLDER + if ( options() & Fl_Native_File_Chooser::NEW_FOLDER ) + _file_chooser->type(_file_chooser->type() | Fl_File_Chooser::CREATE); // on + + // SHOW + _file_chooser->show(); - // BLOCK WHILE BROWSER SHOWN - while ( _file_chooser->shown() ) { - Fl::wait(); - } + // BLOCK WHILE BROWSER SHOWN + while ( _file_chooser->shown() ) { + Fl::wait(); + } - if ( _file_chooser->value() && _file_chooser->value()[0] ) { - _prevvalue = strfree(_prevvalue); - _prevvalue = strnew(_file_chooser->value()); - _filtvalue = _file_chooser->filter_value(); // update filter value - - // HANDLE SHOWING 'SaveAs' CONFIRM - if ( options() & SAVEAS_CONFIRM && type() == BROWSE_SAVE_FILE ) { - struct stat buf; - if ( stat(_file_chooser->value(), &buf) != -1 ) { - if ( buf.st_mode & S_IFREG ) { // Regular file + exists? - if ( exist_dialog() == 0 ) { - return(1); - } - } + if ( _file_chooser->value() && _file_chooser->value()[0] ) { + _prevvalue = strfree(_prevvalue); + _prevvalue = strnew(_file_chooser->value()); + _filtvalue = _file_chooser->filter_value(); // update filter value + + // HANDLE SHOWING 'SaveAs' CONFIRM + if ( options() & Fl_Native_File_Chooser::SAVEAS_CONFIRM && type() == Fl_Native_File_Chooser::BROWSE_SAVE_FILE ) { + struct stat buf; + if ( stat(_file_chooser->value(), &buf) != -1 ) { + if ( buf.st_mode & S_IFREG ) { // Regular file + exists? + if ( exist_dialog() == 0 ) { + return(1); + } + } + } } } - } - if ( _file_chooser->count() ) return(0); - else return(1); + if ( _file_chooser->count() ) return(0); + else return(1); } -/** - Returns a system dependent error message for the last method that failed. - This message should at least be flagged to the user in a dialog box, or to some kind of error log. - Contents will be valid only for methods that document errmsg() will have info on failures. - */ -const char *Fl_Native_File_Chooser::errmsg() const { +const char *Fl_FLTK_File_Chooser::errmsg() const { return(_errmsg ? _errmsg : "No error"); } -/** - Return the filename the user choose. - Use this if only expecting a single filename. - If more than one filename is expected, use filename(int) instead. - Return value may be "" if no filename was chosen (eg. user cancelled). - */ -const char* Fl_Native_File_Chooser::filename() const { - if ( _file_chooser->count() > 0 ) return(_file_chooser->value()); +const char* Fl_FLTK_File_Chooser::filename() const { + if ( _file_chooser->count() > 0 ) { + return(_file_chooser->value()); + } return(""); } -/** - Return one of the filenames the user selected. - Use count() to determine how many filenames the user selected. - <P> - \b Example: - \code - if ( fnfc->show() == 0 ) { - // Print all filenames user selected - for (int n=0; n<fnfc->count(); n++ ) { - printf("%d) '%s'\n", n, fnfc->filename(n)); - } - } - \endcode - */ -const char* Fl_Native_File_Chooser::filename(int i) const { - if ( i < _file_chooser->count() ) - return(_file_chooser->value(i+1)); // convert fltk 1 based to our 0 based +const char* Fl_FLTK_File_Chooser::filename(int i) const { + if ( i < _file_chooser->count() ) + return(_file_chooser->value(i+1)); // convert fltk 1 based to our 0 based return(""); } -/** - Set the title of the file chooser's dialog window. - Can be NULL if no title desired. - The default title varies according to the platform, so you are advised to set the title explicitly. -*/ -void Fl_Native_File_Chooser::title(const char *val) { +void Fl_FLTK_File_Chooser::title(const char *val) { _file_chooser->label(val); } -/** - Get the title of the file chooser's dialog window. - Return value may be NULL if no title was set. -*/ -const char *Fl_Native_File_Chooser::title() const { - return(_file_chooser->label()); +const char *Fl_FLTK_File_Chooser::title() const { + return(_file_chooser->label()); } -/** - Sets the filename filters used for browsing. - The default is NULL, which browses all files. - <P> - The filter string can be any of: - <P> - - A single wildcard (eg. "*.txt") - - Multiple wildcards (eg. "*.{cxx,h,H}") - - A descriptive name followed by a "\t" and a wildcard (eg. "Text Files\t*.txt") - - A list of separate wildcards with a "\n" between each (eg. "*.{cxx,H}\n*.txt") - - A list of descriptive names and wildcards (eg. "C++ Files\t*.{cxx,H}\nTxt Files\t*.txt") - <P> - The format of each filter is a wildcard, or an optional user description - followed by '\\t' and the wildcard. - <P> - On most platforms, each filter is available to the user via a pulldown menu - in the file chooser. The 'All Files' option is always available to the user. -*/ -void Fl_Native_File_Chooser::filter(const char *val) { +void Fl_FLTK_File_Chooser::filter(const char *val) { _filter = strfree(_filter); _filter = strnew(val); parse_filter(); } -/** - Returns the filter string last set. - Can be NULL if no filter was set. - */ -const char *Fl_Native_File_Chooser::filter() const { +const char *Fl_FLTK_File_Chooser::filter() const { return(_filter); } -/** -Gets how many filters were available, not including "All Files" -*/ -int Fl_Native_File_Chooser::filters() const { +int Fl_FLTK_File_Chooser::filters() const { return(_nfilters); } -/** - Sets which filter will be initially selected. - - The first filter is indexed as 0. - If filter_value()==filters(), then "All Files" was chosen. - If filter_value() > filters(), then a custom filter was set. - */ -void Fl_Native_File_Chooser::filter_value(int val) { +void Fl_FLTK_File_Chooser::filter_value(int val) { _filtvalue = val; } -/** - Returns which filter value was last selected by the user. - This is only valid if the chooser returns success. - */ -int Fl_Native_File_Chooser::filter_value() const { - return(_filtvalue); +int Fl_FLTK_File_Chooser::filter_value() const { + return _filtvalue; } -/** - Returns the number of filenames (or directory names) the user selected. - <P> - \b Example: - \code - if ( fnfc->show() == 0 ) { - // Print all filenames user selected - for (int n=0; n<fnfc->count(); n++ ) { - printf("%d) '%s'\n", n, fnfc->filename(n)); - } - } - \endcode -*/ -int Fl_Native_File_Chooser::count() const { - return(_file_chooser->count()); +int Fl_FLTK_File_Chooser::count() const { + return _file_chooser->count(); } -/** - Preset the directory the browser will show when opened. - If \p val is NULL, or no directory is specified, the chooser will attempt - to use the last non-cancelled folder. -*/ -void Fl_Native_File_Chooser::directory(const char *val) { +void Fl_FLTK_File_Chooser::directory(const char *val) { _directory = strfree(_directory); _directory = strnew(val); } -/** - Returns the current preset directory() value. -*/ -const char *Fl_Native_File_Chooser::directory() const { - return(_directory); +const char *Fl_FLTK_File_Chooser::directory() const { + return _directory; } // PRIVATE: Convert our filter format to fltk's chooser format @@ -362,7 +428,7 @@ const char *Fl_Native_File_Chooser::directory() const { // Returns a modified version of the filter that the caller is responsible // for freeing with strfree(). // -void Fl_Native_File_Chooser::parse_filter() { +void Fl_FLTK_File_Chooser::parse_filter() { _parsedfilt = strfree(_parsedfilt); // clear previous parsed filter (if any) _nfilters = 0; char *in = _filter; @@ -425,29 +491,19 @@ void Fl_Native_File_Chooser::parse_filter() { //NOTREACHED } -/** - Sets the default filename for the chooser. - Use directory() to set the default directory. - Mainly used to preset the filename for save dialogs, - and on most platforms can be used for opening files as well. - */ -void Fl_Native_File_Chooser::preset_file(const char* val) { +void Fl_FLTK_File_Chooser::preset_file(const char* val) { _preset_file = strfree(_preset_file); _preset_file = strnew(val); } -/** - Get the preset filename. - */ -const char* Fl_Native_File_Chooser::preset_file() const { - return(_preset_file); +const char* Fl_FLTK_File_Chooser::preset_file() const { + return _preset_file; } - -int Fl_Native_File_Chooser::exist_dialog() { - return(fl_choice("%s", fl_cancel, fl_ok, NULL, file_exists_message)); +int Fl_FLTK_File_Chooser::exist_dialog() { + return fl_choice("%s", fl_cancel, fl_ok, NULL, Fl_Native_File_Chooser::file_exists_message); } // -// End of "$Id: Fl_Native_File_Chooser_FLTK.cxx 9547 2012-05-25 14:46:02Z manolo $". +// End of "$Id: Fl_Native_File_Chooser_FLTK.cxx 10349 2014-10-01 17:24:55Z manolo $". // diff --git a/src/Fl_Native_File_Chooser_GTK.cxx b/src/Fl_Native_File_Chooser_GTK.cxx new file mode 100644 index 0000000..1b47511 --- /dev/null +++ b/src/Fl_Native_File_Chooser_GTK.cxx @@ -0,0 +1,732 @@ +// "$Id$" +// +// FLTK native file chooser widget wrapper for GTK's GtkFileChooserDialog +// +// Copyright 1998-2014 by Bill Spitzak and others. +// Copyright 2012 IMM +// +// This library is free software. Distribution and use rights are outlined in +// the file "COPYING" which should have been included with this file. If this +// file is missing or damaged, see the license at: +// +// http://www.fltk.org/COPYING.php +// +// Please report all bugs and problems to: +// +// http://www.fltk.org/str.php +// + +#include <FL/x.H> +#if HAVE_DLSYM && HAVE_DLFCN_H +#include <dlfcn.h> // for dlopen et al +#endif +#include <locale.h> // for setlocale + +/* --------------------- Type definitions from GLIB and GTK --------------------- */ +/* all of this is from the public gnome API, so unlikely to change */ +#ifndef FALSE +#define FALSE (0) +#endif +#ifndef TRUE +#define TRUE (!FALSE) +#endif +typedef void* gpointer; +typedef int gint; +typedef unsigned int guint; +typedef unsigned long gulong; +typedef gint gboolean; +typedef char gchar; +typedef struct _GSList GSList; +struct _GSList +{ + gpointer data; + GSList *next; +}; +#define g_slist_next(slist) ((slist) ? (((GSList *)(slist))->next) : NULL) +typedef struct _GtkWidget GtkWidget; +typedef struct _GtkFileChooser GtkFileChooser; +typedef struct _GtkDialog GtkDialog; +typedef struct _GtkWindow GtkWindow; +typedef struct _GdkDrawable GdkWindow; +typedef struct _GtkFileFilter GtkFileFilter; +typedef struct _GtkToggleButton GtkToggleButton; +typedef enum { + GTK_FILE_FILTER_FILENAME = 1 << 0, + GTK_FILE_FILTER_URI = 1 << 1, + GTK_FILE_FILTER_DISPLAY_NAME = 1 << 2, + GTK_FILE_FILTER_MIME_TYPE = 1 << 3 +} GtkFileFilterFlags; +struct _GtkFileFilterInfo +{ + GtkFileFilterFlags contains; + + const gchar *filename; + const gchar *uri; + const gchar *display_name; + const gchar *mime_type; +}; +typedef struct _GtkFileFilterInfo GtkFileFilterInfo; +typedef gboolean (*GtkFileFilterFunc) (const GtkFileFilterInfo *filter_info, gpointer data); +typedef void (*GDestroyNotify)(gpointer data); +typedef enum +{ + GTK_FILE_CHOOSER_ACTION_OPEN, + GTK_FILE_CHOOSER_ACTION_SAVE, + GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, + GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER +} GtkFileChooserAction; +#define GTK_STOCK_CANCEL "gtk-cancel" +#define GTK_STOCK_SAVE "gtk-save" +#define GTK_STOCK_OPEN "gtk-open" +const int GTK_RESPONSE_NONE = -1; +const int GTK_RESPONSE_ACCEPT = -3; +const int GTK_RESPONSE_DELETE_EVENT = -4; +const int GTK_RESPONSE_CANCEL = -6; +typedef void (*GCallback)(void); +#define G_CALLBACK(f) ((GCallback) (f)) +typedef int GConnectFlags; +typedef struct _GClosure GClosure; +typedef void (*GClosureNotify)(gpointer data, GClosure *closure); + +/* --------------------- End of Type definitions from GLIB and GTK --------------------- */ + +int Fl_GTK_File_Chooser::did_find_GTK_libs = 0; + +/* These are the GTK/GLib methods we want to load, but not call by name...! */ + +// void g_free (gpointer mem); +typedef void (*XX_g_free)(gpointer); +static XX_g_free fl_g_free = NULL; + +// gpointer g_slist_nth_data (GSList *list, guint n); +typedef gpointer (*XX_g_slist_nth_data) (GSList *, guint); +static XX_g_slist_nth_data fl_g_slist_nth_data = NULL; + +// guint g_slist_length (GSList *list); +typedef guint (*XX_g_slist_length) (GSList *); +static XX_g_slist_length fl_g_slist_length = NULL; + +// void g_slist_free (GSList *list); +typedef void (*XX_g_slist_free) (GSList *); +static XX_g_slist_free fl_g_slist_free = NULL; + +// gboolean gtk_init_check (int *argc, char ***argv); +typedef gboolean (*XX_gtk_init_check)(int *, char ***); +static XX_gtk_init_check fl_gtk_init_check = NULL; + +// void gtk_widget_destroy (GtkWidget *widget); +typedef void (*XX_gtk_widget_destroy) (GtkWidget *); +static XX_gtk_widget_destroy fl_gtk_widget_destroy = NULL; + +// void gtk_file_chooser_set_select_multiple(GtkFileChooser *chooser, gboolean select_multiple); +typedef void (*XX_gtk_file_chooser_set_select_multiple)(GtkFileChooser *, gboolean); +static XX_gtk_file_chooser_set_select_multiple fl_gtk_file_chooser_set_select_multiple = NULL; + +// void gtk_file_chooser_set_do_overwrite_confirmation(GtkFileChooser *chooser, gboolean do_overwrite_confirmation); +typedef void (*XX_gtk_file_chooser_set_do_overwrite_confirmation)(GtkFileChooser *, gboolean); +static XX_gtk_file_chooser_set_do_overwrite_confirmation fl_gtk_file_chooser_set_do_overwrite_confirmation = NULL; + +// void gtk_file_chooser_set_current_name (GtkFileChooser *chooser, const gchar *name); +typedef void (*XX_gtk_file_chooser_set_current_name)(GtkFileChooser *, const gchar *); +static XX_gtk_file_chooser_set_current_name fl_gtk_file_chooser_set_current_name = NULL; + +// void gtk_file_chooser_set_current_folder (GtkFileChooser *chooser, const gchar *name); +typedef void (*XX_gtk_file_chooser_set_current_folder)(GtkFileChooser *, const gchar *); +static XX_gtk_file_chooser_set_current_folder fl_gtk_file_chooser_set_current_folder = NULL; + +// void gtk_file_chooser_set_create_folders (GtkFileChooser *chooser, gboolean create_folders); +typedef void (*XX_gtk_file_chooser_set_create_folders) (GtkFileChooser *, gboolean); +static XX_gtk_file_chooser_set_create_folders fl_gtk_file_chooser_set_create_folders = NULL; + +// gboolean gtk_file_chooser_get_select_multiple(GtkFileChooser *chooser); +typedef gboolean (*XX_gtk_file_chooser_get_select_multiple)(GtkFileChooser *); +static XX_gtk_file_chooser_get_select_multiple fl_gtk_file_chooser_get_select_multiple = NULL; + +// void gtk_widget_hide(GtkWidget *widget); +typedef void (*XX_gtk_widget_hide)(GtkWidget *); +static XX_gtk_widget_hide fl_gtk_widget_hide = NULL; + +// gchar * gtk_file_chooser_get_filename(GtkFileChooser *chooser); +typedef gchar* (*XX_gtk_file_chooser_get_filename)(GtkFileChooser *); +static XX_gtk_file_chooser_get_filename fl_gtk_file_chooser_get_filename = NULL; + +// GSList * gtk_file_chooser_get_filenames(GtkFileChooser *chooser); +typedef GSList* (*XX_gtk_file_chooser_get_filenames)(GtkFileChooser *chooser); +static XX_gtk_file_chooser_get_filenames fl_gtk_file_chooser_get_filenames = NULL; + +// gboolean gtk_main_iteration(void); +typedef gboolean (*XX_gtk_main_iteration)(void); +static XX_gtk_main_iteration fl_gtk_main_iteration = NULL; + +// gboolean gtk_events_pending(void); +typedef gboolean (*XX_gtk_events_pending)(void); +static XX_gtk_events_pending fl_gtk_events_pending = NULL; + +// GtkWidget * gtk_file_chooser_dialog_new(const gchar *title, GtkWindow *parent, GtkFileChooserAction action, const gchar *first_button_text, ...); +typedef GtkWidget* (*XX_gtk_file_chooser_dialog_new)(const gchar *, GtkWindow *, GtkFileChooserAction, const gchar *, ...); +static XX_gtk_file_chooser_dialog_new fl_gtk_file_chooser_dialog_new = NULL; + +// void gtk_file_chooser_add_filter(GtkFileChooser*, GtkFileFilter*); +typedef void (*XX_gtk_file_chooser_add_filter)(GtkFileChooser*, GtkFileFilter*); +static XX_gtk_file_chooser_add_filter fl_gtk_file_chooser_add_filter = NULL; + +// GtkFileFilter* gtk_file_chooser_get_filter(GtkFileChooser*); +typedef GtkFileFilter* (*XX_gtk_file_chooser_get_filter)(GtkFileChooser*); +static XX_gtk_file_chooser_get_filter fl_gtk_file_chooser_get_filter = NULL; + +// void gtk_file_chooser_set_filter(GtkFileChooser*, GtkFileFilter*); +typedef void (*XX_gtk_file_chooser_set_filter)(GtkFileChooser*, GtkFileFilter*); +static XX_gtk_file_chooser_set_filter fl_gtk_file_chooser_set_filter = NULL; + +// GtkFileFilter * gtk_file_filter_new(); +typedef GtkFileFilter* (*XX_gtk_file_filter_new)(void); +static XX_gtk_file_filter_new fl_gtk_file_filter_new = NULL; + +// void gtk_file_filter_add_pattern(GtkFileFilter*, const gchar*); +typedef void (*XX_gtk_file_filter_add_pattern)(GtkFileFilter*, const gchar*); +static XX_gtk_file_filter_add_pattern fl_gtk_file_filter_add_pattern = NULL; + +// void gtk_file_filter_add_custom(GtkFileFilter *filter, GtkFileFilterFlags needed, +// GtkFileFilterFunc func, gpointer data, GDestroyNotify notify); +typedef void (*XX_gtk_file_filter_add_custom)(GtkFileFilter *filter, GtkFileFilterFlags needed, + GtkFileFilterFunc func, gpointer data, + GDestroyNotify notify); +static XX_gtk_file_filter_add_custom fl_gtk_file_filter_add_custom = NULL; + +// void gtk_file_filter_set_name(GtkFileFilter*, const gchar*); +typedef void (*XX_gtk_file_filter_set_name)(GtkFileFilter*, const gchar*); +static XX_gtk_file_filter_set_name fl_gtk_file_filter_set_name = NULL; + +// const gchar* gtk_file_filter_get_name(GtkFileFilter*); +typedef const gchar* (*XX_gtk_file_filter_get_name)(GtkFileFilter*); +static XX_gtk_file_filter_get_name fl_gtk_file_filter_get_name = NULL; + +// void gtk_file_chooser_set_extra_widget(GtkFileChooser *, GtkWidget *); +typedef void (*XX_gtk_file_chooser_set_extra_widget)(GtkFileChooser *, GtkWidget *); +static XX_gtk_file_chooser_set_extra_widget fl_gtk_file_chooser_set_extra_widget = NULL; + +// void gtk_widget_show_now(GtkWidget *); +typedef void (*XX_gtk_widget_show_now)(GtkWidget *); +static XX_gtk_widget_show_now fl_gtk_widget_show_now = NULL; + +// GdkWindow* gtk_widget_get_window(GtkWidget *); +typedef GdkWindow* (*XX_gtk_widget_get_window)(GtkWidget *); +static XX_gtk_widget_get_window fl_gtk_widget_get_window = NULL; + +// Window gdk_x11_drawable_get_xid(GdkWindow *); +typedef Window (*XX_gdk_x11_drawable_get_xid)(GdkWindow *); +static XX_gdk_x11_drawable_get_xid fl_gdk_x11_drawable_get_xid = NULL; + +// GtkWidget *gtk_check_button_new_with_label(const gchar *); +typedef GtkWidget* (*XX_gtk_check_button_new_with_label)(const gchar *); +static XX_gtk_check_button_new_with_label fl_gtk_check_button_new_with_label = NULL; + +// gulong g_signal_connect_data(gpointer, const gchar *, GCallback, gpointer, GClosureNotify, GConnectFlags); +typedef gulong (*XX_g_signal_connect_data)(gpointer, const gchar *, GCallback, gpointer, GClosureNotify, GConnectFlags); +static XX_g_signal_connect_data fl_g_signal_connect_data = NULL; + +// gboolean gtk_toggle_button_get_active(GtkToggleButton *); +typedef gboolean (*XX_gtk_toggle_button_get_active)(GtkToggleButton*); +static XX_gtk_toggle_button_get_active fl_gtk_toggle_button_get_active = NULL; + +// void gtk_file_chooser_set_show_hidden(GtkFileChooser *, gboolean); +typedef void (*XX_gtk_file_chooser_set_show_hidden)(GtkFileChooser *, gboolean); +static XX_gtk_file_chooser_set_show_hidden fl_gtk_file_chooser_set_show_hidden = NULL; + +// gboolean gtk_file_chooser_get_show_hidden(GtkFileChooser *); +typedef gboolean (*XX_gtk_file_chooser_get_show_hidden)(GtkFileChooser *); +static XX_gtk_file_chooser_get_show_hidden fl_gtk_file_chooser_get_show_hidden = NULL; + +// void gtk_toggle_button_set_active(GtkToggleButton *, gboolean); +typedef void (*XX_gtk_toggle_button_set_active)(GtkToggleButton *, gboolean); +static XX_gtk_toggle_button_set_active fl_gtk_toggle_button_set_active = NULL; + + +Fl_GTK_File_Chooser::Fl_GTK_File_Chooser(int val) : Fl_FLTK_File_Chooser(-1) +{ + gtkw_ptr = NULL; // used to hold a GtkWidget* + gtkw_slist = NULL; // will hold the returned file names in a multi-selection... + gtkw_count = 0; // How many items were selected? + gtkw_filename = NULL; // holds the last name we read back in a single file selection... + gtkw_title = NULL; // dialog title + _btype = val; + previous_filter = NULL; +} + +Fl_GTK_File_Chooser::~Fl_GTK_File_Chooser() +{ + // Should free up resources taken for... + if(gtkw_ptr) { + fl_gtk_widget_destroy (gtkw_ptr); + gtkw_ptr = NULL; + } + if(gtkw_filename) { + fl_g_free(gtkw_filename); + gtkw_filename = NULL; + } + if(gtkw_slist) { + GSList *iter = (GSList *)gtkw_slist; + while(iter) { + if(iter->data) fl_g_free(iter->data); + iter = g_slist_next(iter); + } + fl_g_slist_free((GSList *)gtkw_slist); + gtkw_slist = NULL; + } + gtkw_count = 0; // assume we have no files selected now + gtkw_title = strfree(gtkw_title); +} + +void Fl_GTK_File_Chooser::type(int val) { + _btype = val; +} + +int Fl_GTK_File_Chooser::count() const { + return gtkw_count; +} + +const char *Fl_GTK_File_Chooser::filename() const +{ + if(gtkw_ptr) { + if(fl_gtk_file_chooser_get_select_multiple((GtkFileChooser *)gtkw_ptr) == FALSE) { + return gtkw_filename; + } + else { + GSList *iter = (GSList *)gtkw_slist; + char *nm = (char *)iter->data; + return nm; + } + } + return(""); +} + +const char *Fl_GTK_File_Chooser::filename(int i) const +{ + if(fl_gtk_file_chooser_get_select_multiple((GtkFileChooser *)gtkw_ptr) == FALSE) { + return gtkw_filename; + } + else { + if ((unsigned)i < gtkw_count) { + GSList *iter = (GSList *)gtkw_slist; + char *nm = (char *)fl_g_slist_nth_data(iter, i); + return nm; + } + } + return(""); +} + +void Fl_GTK_File_Chooser::title(const char *val) +{ + strfree(gtkw_title); + gtkw_title = strnew(val); +} + +const char* Fl_GTK_File_Chooser::title() const +{ + return gtkw_title; +} + +/* changes the extension of the outfile in the chooser according to newly selected filter */ +void Fl_GTK_File_Chooser::changed_output_type(const char *filter) +{ + if ( !(options()&Fl_Native_File_Chooser::USE_FILTER_EXT) ) return; + if (strchr(filter, '(') || strchr(filter, '{') || strchr(filter+1, '*') || strncmp(filter, "*.", 2)) return; + const char *p = fl_gtk_file_chooser_get_filename((GtkFileChooser*)gtkw_ptr); + if (!p) return; + p = fl_filename_name(p); + const char *q = strrchr(p, '.'); + if (!q) q = p + strlen(p); + char *r = new char[strlen(p) + strlen(filter)]; + strcpy(r, p); + strcpy(r + (q - p), filter + 1); + fl_gtk_file_chooser_set_current_name((GtkFileChooser*)gtkw_ptr, r); + delete[] r; +} + +/* Filters files before display in chooser. + Also used to detect when the filter just changed */ +gboolean Fl_GTK_File_Chooser::custom_gtk_filter_function(const GtkFileFilterInfo *info, Fl_GTK_File_Chooser::pair* p) +{ + if (p->running->previous_filter != p->filter) { + p->running->changed_output_type(p->filter); + p->running->previous_filter = p->filter; + } + return (gboolean)fl_filename_match(info->filename, p->filter); +} + +void Fl_GTK_File_Chooser::free_pair(Fl_GTK_File_Chooser::pair *p) +{ + delete p; +} + +static void hidden_files_cb(GtkToggleButton *togglebutton, gpointer user_data) +{ + gboolean state = fl_gtk_toggle_button_get_active(togglebutton); + fl_gtk_file_chooser_set_show_hidden((GtkFileChooser*)user_data, state); +} + +int Fl_GTK_File_Chooser::show() +{ + // The point here is that after running a GTK dialog, the calling program's current locale is modified. + // To avoid that, we memorize the calling program's current locale, and the locale as modified + // by GTK after the first dialog use. We restore the calling program's current locale + // before returning, and we set the locale as modified by GTK before subsequent GTK dialog uses. + static bool first = true; + char *p; + char *before = NULL; + static char *gtk_wants = NULL; + // record in before the calling program's current locale + p = setlocale(LC_ALL, NULL); + if (p) before = strdup(p); + if (gtk_wants) { // set the locale as GTK 'wants it' + setlocale(LC_ALL, gtk_wants); + } + int retval = fl_gtk_chooser_wrapper(); // may change the locale + if (first) { + first = false; + // record in gtk_wants the locale as modified by the GTK dialog + p = setlocale(LC_ALL, NULL); + if (p) gtk_wants = strdup(p); + } + if (before) { + setlocale(LC_ALL, before); // restore calling program's current locale + free(before); + } + return retval; +} + +static char *extract_dir_from_path(const char *path) +{ + static char *dir = NULL; + if (fl_filename_isdir(path)) { + return (char*)path; + } + if (*path != '/') return NULL; + if (dir) free(dir); + dir = strdup(path); + do { + char *p = strrchr(dir, '/'); + if (p == dir) p++; + *p = 0; + } + while (!fl_filename_isdir(dir)); + return dir; +} + +static void run_response_handler(GtkDialog *dialog, gint response_id, gpointer data) +{ + gint *ri = (gint *)data; + *ri = response_id; +} + + +int Fl_GTK_File_Chooser::fl_gtk_chooser_wrapper() +{ + int result = 1; + static int have_gtk_init = 0; + char *p; + + if(!have_gtk_init) { + have_gtk_init = -1; + int ac = 0; + fl_gtk_init_check(&ac, NULL); + } + + if(gtkw_ptr) { // discard the previous dialog widget + fl_gtk_widget_destroy (gtkw_ptr); + gtkw_ptr = NULL; + } + + // set the dialog action type + GtkFileChooserAction gtw_action_type; + switch (_btype) { + case Fl_Native_File_Chooser::BROWSE_DIRECTORY: + case Fl_Native_File_Chooser::BROWSE_MULTI_DIRECTORY: + gtw_action_type = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER; + break; + + case Fl_Native_File_Chooser::BROWSE_SAVE_FILE: + gtw_action_type = GTK_FILE_CHOOSER_ACTION_SAVE; + break; + + case Fl_Native_File_Chooser::BROWSE_SAVE_DIRECTORY: + gtw_action_type = GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER; + break; + + case Fl_Native_File_Chooser::BROWSE_MULTI_FILE: + case Fl_Native_File_Chooser::BROWSE_FILE: + default: + gtw_action_type = GTK_FILE_CHOOSER_ACTION_OPEN; + break; + } + // create a new dialog + gtkw_ptr = fl_gtk_file_chooser_dialog_new (gtkw_title, + NULL, /* parent_window */ + gtw_action_type, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + gtw_action_type == GTK_FILE_CHOOSER_ACTION_SAVE || gtw_action_type == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER ? + GTK_STOCK_SAVE : GTK_STOCK_OPEN, + GTK_RESPONSE_ACCEPT, + NULL); + // did we create a valid dialog widget? + if(!gtkw_ptr) { + // fail + return -1; + } + + // set the dialog properties + switch (_btype) { + case Fl_Native_File_Chooser::BROWSE_MULTI_DIRECTORY: + case Fl_Native_File_Chooser::BROWSE_MULTI_FILE: + fl_gtk_file_chooser_set_select_multiple((GtkFileChooser *)gtkw_ptr, TRUE); + break; + + case Fl_Native_File_Chooser::BROWSE_SAVE_FILE: + if (_preset_file)fl_gtk_file_chooser_set_current_name ((GtkFileChooser *)gtkw_ptr, fl_filename_name(_preset_file)); + /* FALLTHROUGH */ + case Fl_Native_File_Chooser::BROWSE_SAVE_DIRECTORY: + fl_gtk_file_chooser_set_create_folders((GtkFileChooser *)gtkw_ptr, TRUE); + fl_gtk_file_chooser_set_do_overwrite_confirmation ((GtkFileChooser *)gtkw_ptr, (_options & Fl_Native_File_Chooser::SAVEAS_CONFIRM)?TRUE:FALSE); + break; + + case Fl_Native_File_Chooser::BROWSE_DIRECTORY: + case Fl_Native_File_Chooser::BROWSE_FILE: + default: + break; + } + + if (_directory && _directory[0]) { + p = extract_dir_from_path(_directory); + if (p) fl_gtk_file_chooser_set_current_folder((GtkFileChooser *)gtkw_ptr, p); + } + else if (_preset_file) { + p = extract_dir_from_path(_preset_file); + if (p) fl_gtk_file_chooser_set_current_folder((GtkFileChooser *)gtkw_ptr, p); + } + + GtkFileFilter **filter_tab = NULL; + if (_parsedfilt) { + filter_tab = new GtkFileFilter*[_nfilters]; + char *filter = strdup(_parsedfilt); + p = strtok(filter, "\t"); + int count = 0; + while (p) { + filter_tab[count] = fl_gtk_file_filter_new(); + fl_gtk_file_filter_set_name(filter_tab[count], p); + p = strchr(p, '(') + 1; + char *q = strchr(p, ')'); *q = 0; + fl_gtk_file_filter_add_custom(filter_tab[count], + GTK_FILE_FILTER_FILENAME, + (GtkFileFilterFunc)Fl_GTK_File_Chooser::custom_gtk_filter_function, + new Fl_GTK_File_Chooser::pair(this, p), + (GDestroyNotify)Fl_GTK_File_Chooser::free_pair); + fl_gtk_file_chooser_add_filter((GtkFileChooser *)gtkw_ptr, filter_tab[count]); + p = strtok(NULL, "\t"); + count++; + } + free(filter); + fl_gtk_file_chooser_set_filter((GtkFileChooser *)gtkw_ptr, filter_tab[_filtvalue < _nfilters?_filtvalue:0]); + previous_filter = NULL; + if (gtw_action_type == GTK_FILE_CHOOSER_ACTION_OPEN) { + GtkFileFilter* gfilter = fl_gtk_file_filter_new(); + fl_gtk_file_filter_set_name(gfilter, Fl_File_Chooser::all_files_label); + fl_gtk_file_filter_add_pattern(gfilter, "*"); + fl_gtk_file_chooser_add_filter((GtkFileChooser *)gtkw_ptr, gfilter); + } + } + + GtkWidget *toggle = fl_gtk_check_button_new_with_label(Fl_File_Chooser::hidden_label); + fl_gtk_file_chooser_set_extra_widget((GtkFileChooser *)gtkw_ptr, toggle); + fl_g_signal_connect_data(toggle, "toggled", G_CALLBACK(hidden_files_cb), gtkw_ptr, NULL, (GConnectFlags) 0); + Fl_Window* firstw = Fl::first_window(); + fl_gtk_widget_show_now(gtkw_ptr); // map the GTK window on screen + if (firstw) { + GdkWindow* gdkw = fl_gtk_widget_get_window(gtkw_ptr); + Window xw = fl_gdk_x11_drawable_get_xid(gdkw); // get the X11 ref of the GTK window + XSetTransientForHint(fl_display, xw, fl_xid(firstw)); // set the GTK window transient for the last FLTK win + } + gboolean state = fl_gtk_file_chooser_get_show_hidden((GtkFileChooser *)gtkw_ptr); + fl_gtk_toggle_button_set_active((GtkToggleButton *)toggle, state); + + gint response_id = GTK_RESPONSE_NONE; + fl_g_signal_connect_data(gtkw_ptr, "response", G_CALLBACK(run_response_handler), &response_id, NULL, (GConnectFlags) 0); + while (response_id == GTK_RESPONSE_NONE) { // loop that shows the GTK dialog window + fl_gtk_main_iteration(); // one iteration of the GTK event loop + while (XEventsQueued(fl_display, QueuedAfterReading)) { // emulate modal dialog + XEvent xevent; + XNextEvent(fl_display, &xevent); + Window xid = xevent.xany.window; + if (xevent.type == ConfigureNotify) xid = xevent.xmaprequest.window; + if (!fl_find(xid)) continue; // skip events to non-FLTK windows + // process Expose and ConfigureNotify events + if ( xevent.type == Expose || xevent.type == ConfigureNotify ) fl_handle(xevent); + } + Fl::flush(); // do the drawings needed after Expose events + } + + if (response_id == GTK_RESPONSE_ACCEPT) { + if (_parsedfilt) { + GtkFileFilter *gfilter = fl_gtk_file_chooser_get_filter((GtkFileChooser *)gtkw_ptr); + for (_filtvalue = 0; _filtvalue < _nfilters; _filtvalue++) { + if (filter_tab[_filtvalue] == gfilter) break; + } + } + + // discard any filenames or lists from previous calls + if(gtkw_filename) { + fl_g_free(gtkw_filename); + gtkw_filename = NULL; + } + if(gtkw_slist) { + GSList *iter = (GSList *)gtkw_slist; + while(iter) { + if(iter->data) fl_g_free(iter->data); + iter = g_slist_next(iter); + } + fl_g_slist_free((GSList *)gtkw_slist); + gtkw_slist = NULL; + } + gtkw_count = 0; // assume we have no files selected now + + if(fl_gtk_file_chooser_get_select_multiple((GtkFileChooser *)gtkw_ptr) == FALSE) { + gtkw_filename = fl_gtk_file_chooser_get_filename ((GtkFileChooser *)gtkw_ptr); + if (gtkw_filename) { + gtkw_count = 1; + result = 0; + //printf("single: %s\n", gtkw_filename); + } + } + else { + gtkw_slist = fl_gtk_file_chooser_get_filenames((GtkFileChooser *)gtkw_ptr); + gtkw_count = fl_g_slist_length((GSList *)gtkw_slist); + if(gtkw_count) result = 0; + + // puts("multiple"); + // GSList *iter = (GSList *)gtkw_slist; + // printf ("Selected %d files\n", gtkw_count); + // while(iter) { + // char *nm = (char *)iter->data; + // printf("%s\n", nm); + // iter = g_slist_next(iter); + // } + } + } + delete[] filter_tab; + if ( response_id == GTK_RESPONSE_DELETE_EVENT) gtkw_ptr = NULL; + else fl_gtk_widget_hide (gtkw_ptr); + + // I think this is analogus to doing an Fl::check() - we need this here to make sure + // the GtkFileChooserDialog is removed from the display correctly + while (fl_gtk_events_pending ()) fl_gtk_main_iteration (); + + return result; +} // fl_gtk_chooser_wrapper + +#if HAVE_DLSYM && HAVE_DLFCN_H +// macro to help with the symbol loading boilerplate... +# define GET_SYM(SSS, LLL) \ +dlerror(); /* Clear any existing error */ \ +fl_##SSS = (XX_##SSS)dlsym(LLL, #SSS); \ +if ((pc_dl_error = dlerror()) != NULL) { \ +fprintf(stderr, "%s\n", pc_dl_error); \ +did_find_GTK_libs = 0; \ +return; } + +static void* fl_dlopen(const char *filename1, const char *filename2) +{ + void *ptr = dlopen(filename1, RTLD_LAZY | RTLD_GLOBAL); + if (!ptr) ptr = dlopen(filename2, RTLD_LAZY | RTLD_GLOBAL); + return ptr; +} +#endif + +/* + * Use dlopen to see if we can load the gtk dynamic libraries that + * will allow us to create a GtkFileChooserDialog() on the fly, + * without linking to the GTK libs at compile time. + */ +void Fl_GTK_File_Chooser::probe_for_GTK_libs(void) { +#if HAVE_DLSYM && HAVE_DLFCN_H + void *ptr_glib = NULL; + void *ptr_gtk = NULL; + +# ifdef __APPLE_CC__ // allows testing on Darwin + X11 + ptr_glib = dlopen("/sw/lib/libglib-2.0.dylib", RTLD_LAZY | RTLD_GLOBAL); +# else + ptr_glib = fl_dlopen("libglib-2.0.so", "libglib-2.0.so.0"); +# endif + // Try first with GTK2 +# ifdef __APPLE_CC__ // allows testing on Darwin + X11 + ptr_gtk = dlopen("/sw/lib/libgtk-x11-2.0.dylib", RTLD_LAZY | RTLD_GLOBAL); +#else + ptr_gtk = fl_dlopen("libgtk-x11-2.0.so", "libgtk-x11-2.0.so.0"); +#endif + if (ptr_gtk && ptr_glib) { +#ifdef DEBUG + puts("selected GTK-2\n"); +#endif + } + else {// Try then with GTK3 + ptr_gtk = fl_dlopen("libgtk-3.so", "libgtk-3.so.0"); +#ifdef DEBUG + if (ptr_gtk && ptr_glib) { + puts("selected GTK-3\n"); + } +#endif + } + + if((!ptr_glib) || (!ptr_gtk)) { +#ifdef DEBUG + puts("Failure to load libglib or libgtk"); +#endif + did_find_GTK_libs = 0; + return; + } + + char *pc_dl_error; // used to report errors by the GET_SYM macro... + // items we need from GLib + GET_SYM(g_free, ptr_glib); + GET_SYM(g_slist_nth_data, ptr_glib); + GET_SYM(g_slist_length, ptr_glib); + GET_SYM(g_slist_free, ptr_glib); + // items we need from GTK + GET_SYM(gtk_init_check, ptr_gtk); + GET_SYM(gtk_widget_destroy, ptr_gtk); + GET_SYM(gtk_file_chooser_set_select_multiple, ptr_gtk); + GET_SYM(gtk_file_chooser_set_do_overwrite_confirmation, ptr_gtk); + GET_SYM(gtk_file_chooser_set_current_name, ptr_gtk); + GET_SYM(gtk_file_chooser_set_current_folder, ptr_gtk); + GET_SYM(gtk_file_chooser_set_create_folders, ptr_gtk); + GET_SYM(gtk_file_chooser_get_select_multiple, ptr_gtk); + GET_SYM(gtk_widget_hide, ptr_gtk); + GET_SYM(gtk_file_chooser_get_filename, ptr_gtk); + GET_SYM(gtk_file_chooser_get_filenames, ptr_gtk); + GET_SYM(gtk_main_iteration, ptr_gtk); + GET_SYM(gtk_events_pending, ptr_gtk); + GET_SYM(gtk_file_chooser_dialog_new, ptr_gtk); + GET_SYM(gtk_file_chooser_add_filter, ptr_gtk); + GET_SYM(gtk_file_chooser_get_filter, ptr_gtk); + GET_SYM(gtk_file_chooser_set_filter, ptr_gtk); + GET_SYM(gtk_file_filter_new, ptr_gtk); + GET_SYM(gtk_file_filter_add_pattern, ptr_gtk); + GET_SYM(gtk_file_filter_add_custom, ptr_gtk); + GET_SYM(gtk_file_filter_set_name, ptr_gtk); + GET_SYM(gtk_file_filter_get_name, ptr_gtk); + GET_SYM(gtk_file_chooser_set_extra_widget, ptr_gtk); + GET_SYM(gtk_widget_show_now, ptr_gtk); + GET_SYM(gtk_widget_get_window, ptr_gtk); + GET_SYM(gdk_x11_drawable_get_xid, ptr_gtk); + GET_SYM(gtk_check_button_new_with_label, ptr_gtk); + GET_SYM(g_signal_connect_data, ptr_gtk); + GET_SYM(gtk_toggle_button_get_active, ptr_gtk); + GET_SYM(gtk_file_chooser_set_show_hidden, ptr_gtk); + GET_SYM(gtk_file_chooser_get_show_hidden, ptr_gtk); + GET_SYM(gtk_toggle_button_set_active, ptr_gtk); + + did_find_GTK_libs = 1; +#endif +} // probe_for_GTK_libs + +// +// End of "$Id$". +// diff --git a/src/Fl_Native_File_Chooser_MAC.mm b/src/Fl_Native_File_Chooser_MAC.mm index 6fc9c82..518ae02 100644 --- a/src/Fl_Native_File_Chooser_MAC.mm +++ b/src/Fl_Native_File_Chooser_MAC.mm @@ -1,4 +1,4 @@ -// "$Id: Fl_Native_File_Chooser_MAC.mm 9685 2012-09-27 12:49:39Z manolo $" +// "$Id: Fl_Native_File_Chooser_MAC.mm 10317 2014-09-16 17:34:29Z manolo $" // // FLTK native OS file chooser widget // @@ -344,8 +344,7 @@ int Fl_Native_File_Chooser::filters() const { int Fl_Native_File_Chooser::get_saveas_basename(void) { char *q = strdup( [[[(NSSavePanel*)_panel URL] path] UTF8String] ); - id delegate = [(NSSavePanel*)_panel delegate]; - if (delegate != nil) { + if ( !(_options & SAVEAS_CONFIRM) ) { const char *d = [[[[(NSSavePanel*)_panel URL] path] stringByDeletingLastPathComponent] UTF8String]; int l = strlen(d) + 1; if (strcmp(d, "/") == 0) l = 1; @@ -412,6 +411,7 @@ static char *prepareMacFilter(int count, const char *filter, char **patterns) { } - (FLopenDelegate*)setPopup:(NSPopUpButton*)popup filter_pattern:(char**)pattern; - (BOOL)panel:(id)sender shouldShowFilename:(NSString *)filename; +- (BOOL)panel:(id)sender shouldEnableURL:(NSURL *)url; @end @implementation FLopenDelegate - (FLopenDelegate*)setPopup:(NSPopUpButton*)popup filter_pattern:(char**)pattern @@ -423,11 +423,16 @@ static char *prepareMacFilter(int count, const char *filter, char **patterns) { - (BOOL)panel:(id)sender shouldShowFilename:(NSString *)filename { if ( [nspopup indexOfSelectedItem] == [nspopup numberOfItems] - 1) return YES; - const char *pathname = [filename fileSystemRepresentation]; - if ( fl_filename_isdir(pathname) ) return YES; - if ( fl_filename_match(pathname, filter_pattern[ [nspopup indexOfSelectedItem] ]) ) return YES; + BOOL isdir = NO; + [[NSFileManager defaultManager] fileExistsAtPath:filename isDirectory:&isdir]; + if (isdir) return YES; + if ( fl_filename_match([filename fileSystemRepresentation], filter_pattern[ [nspopup indexOfSelectedItem] ]) ) return YES; return NO; } +- (BOOL)panel:(id)sender shouldEnableURL:(NSURL *)url +{ + return [self panel:sender shouldShowFilename:[url path]]; +} @end @interface FLsaveDelegate : NSObject @@ -435,17 +440,53 @@ static char *prepareMacFilter(int count, const char *filter, char **patterns) { <NSOpenSavePanelDelegate> #endif { + NSSavePanel *dialog; + BOOL saveas_confirm; } - (NSString *)panel:(id)sender userEnteredFilename:(NSString *)filename confirmed:(BOOL)okFlag; +- (void)changedPopup:(id)sender; +- (void)panel:(NSSavePanel*)p; +- (void)option:(BOOL)o; @end @implementation FLsaveDelegate - (NSString *)panel:(id)sender userEnteredFilename:(NSString *)filename confirmed:(BOOL)okFlag { - if (! okFlag) return filename; + if ( !okFlag || saveas_confirm ) return filename; // User has clicked save, and no overwrite confirmation should occur. // To get the latter, we need to change the name we return (hence the prefix): return [@ UNLIKELYPREFIX stringByAppendingString:filename]; } +- (void)changedPopup:(id)sender +// runs when the save panel popup menu changes output file type +// correspondingly changes the extension of the output file name +{ + if (fl_mac_os_version < 100600) return; // because of setNameFieldStringValue and nameFieldStringValue + char *s = strdup([[(NSPopUpButton*)sender titleOfSelectedItem] UTF8String]); + if (!s) return; + char *p = strchr(s, '('); + if (!p) p = s; + p = strchr(p, '.'); + if (!p) {free(s); return;} + p++; + while (*p == ' ') p++; + if (!p || *p == '{') {free(s); return;} + char *q = p+1; + while (*q != ' ' && *q != ')' && *q != 0) q++; + *q = 0; + NSString *ns = [NSString stringWithFormat:@"%@.%@", + [[dialog performSelector:@selector(nameFieldStringValue)] stringByDeletingPathExtension], + [NSString stringWithUTF8String:p]]; + free(s); + [dialog performSelector:@selector(setNameFieldStringValue:) withObject:ns]; +} +- (void)panel:(NSSavePanel*)p +{ + dialog = p; +} +- (void) option:(BOOL)o +{ + saveas_confirm = o; +} @end static NSPopUpButton *createPopupAccessory(NSSavePanel *panel, const char *filter, const char *title, int rank) @@ -501,8 +542,8 @@ int Fl_Native_File_Chooser::runmodal() } if (_directory && !dir) dir = [[NSString alloc] initWithUTF8String:_directory]; if (fl_mac_os_version >= 100600) { - if (dir) [(NSSavePanel*)_panel setDirectoryURL:[NSURL fileURLWithPath:dir]]; - if (fname) [(NSSavePanel*)_panel setNameFieldStringValue:fname]; + if (dir) [(NSSavePanel*)_panel performSelector:@selector(setDirectoryURL:) withObject:[NSURL fileURLWithPath:dir]]; + if (fname) [(NSSavePanel*)_panel performSelector:@selector(setNameFieldStringValue:) withObject:fname]; retval = [(NSSavePanel*)_panel runModal]; } else { @@ -541,7 +582,6 @@ int Fl_Native_File_Chooser::post() { _panel = [NSSavePanel savePanel]; break; } - int retval; NSString *nstitle = [NSString stringWithUTF8String: (_title ? _title : "No Title")]; [(NSSavePanel*)_panel setTitle:nstitle]; switch (_btype) { @@ -561,8 +601,9 @@ int Fl_Native_File_Chooser::post() { // SHOW THE DIALOG NSWindow *key = [NSApp keyWindow]; - if ( [(NSSavePanel*)_panel isKindOfClass:[NSOpenPanel class]] ) { - NSPopUpButton *popup = nil; + BOOL is_open_panel = [(NSSavePanel*)_panel isKindOfClass:[NSOpenPanel class]]; + NSPopUpButton *popup = nil; + if ( is_open_panel ) { if (_filt_total) { char *t = prepareMacFilter(_filt_total, _filter, _filt_patt); popup = createPopupAccessory((NSSavePanel*)_panel, t, Fl_File_Chooser::show_label, 0); @@ -571,47 +612,44 @@ int Fl_Native_File_Chooser::post() { [popup addItemWithTitle:[[NSString alloc] initWithUTF8String:Fl_File_Chooser::all_files_label]]; [popup setAction:@selector(validateVisibleColumns)]; [popup setTarget:(NSObject*)_panel]; - static FLopenDelegate *openDelegate = nil; - if (openDelegate == nil) { - // not to be ever freed - openDelegate = [[FLopenDelegate alloc] init]; - } + FLopenDelegate *openDelegate = [[[FLopenDelegate alloc] init] autorelease]; [openDelegate setPopup:popup filter_pattern:_filt_patt]; [(NSOpenPanel*)_panel setDelegate:openDelegate]; } - retval = runmodal(); - if (_filt_total) { - _filt_value = [popup indexOfSelectedItem]; - } - if ( retval == NSOKButton ) { - clear_pathnames(); - NSArray *array = [(NSOpenPanel*)_panel URLs]; - _tpathnames = [array count]; - _pathnames = new char*[_tpathnames]; - for(int i = 0; i < _tpathnames; i++) { - _pathnames[i] = strnew([[(NSURL*)[array objectAtIndex:i] path] UTF8String]); - } - } } else { - NSPopUpButton *popup = nil; + FLsaveDelegate *saveDelegate = [[[FLsaveDelegate alloc] init] autorelease]; [(NSSavePanel*)_panel setAllowsOtherFileTypes:YES]; - if ( !(_options & SAVEAS_CONFIRM) ) { - static FLsaveDelegate *saveDelegate = nil; - if (saveDelegate == nil)saveDelegate = [[FLsaveDelegate alloc] init]; // not to be ever freed - [(NSSavePanel*)_panel setDelegate:saveDelegate]; - } + [(NSSavePanel*)_panel setDelegate:saveDelegate]; + [saveDelegate option:(_options & SAVEAS_CONFIRM)]; if (_filt_total) { if (_filt_value >= _filt_total) _filt_value = _filt_total - 1; char *t = prepareMacFilter(_filt_total, _filter, _filt_patt); popup = createPopupAccessory((NSSavePanel*)_panel, t, [[(NSSavePanel*)_panel nameFieldLabel] UTF8String], _filt_value); delete[] t; + if (_options & USE_FILTER_EXT) { + [popup setAction:@selector(changedPopup:)]; + [popup setTarget:saveDelegate]; + [saveDelegate panel:(NSSavePanel*)_panel]; + } + [(NSSavePanel*)_panel setCanSelectHiddenExtension:YES]; } - retval = runmodal(); - if (_filt_total) { - _filt_value = [popup indexOfSelectedItem]; + } + int retval = runmodal(); + if (_filt_total) { + _filt_value = [popup indexOfSelectedItem]; + } + if ( retval == NSOKButton ) { + if (is_open_panel) { + clear_pathnames(); + NSArray *array = [(NSOpenPanel*)_panel URLs]; + _tpathnames = [array count]; + _pathnames = new char*[_tpathnames]; + for(int i = 0; i < _tpathnames; i++) { + _pathnames[i] = strnew([[(NSURL*)[array objectAtIndex:i] path] UTF8String]); + } } - if ( retval == NSOKButton ) get_saveas_basename(); + else get_saveas_basename(); } [key makeKeyWindow]; [localPool release]; @@ -621,5 +659,5 @@ int Fl_Native_File_Chooser::post() { #endif // __APPLE__ // -// End of "$Id: Fl_Native_File_Chooser_MAC.mm 9685 2012-09-27 12:49:39Z manolo $". +// End of "$Id: Fl_Native_File_Chooser_MAC.mm 10317 2014-09-16 17:34:29Z manolo $". // diff --git a/src/Fl_Native_File_Chooser_WIN32.cxx b/src/Fl_Native_File_Chooser_WIN32.cxx index 0c8e0a9..094ea9f 100644 --- a/src/Fl_Native_File_Chooser_WIN32.cxx +++ b/src/Fl_Native_File_Chooser_WIN32.cxx @@ -1,4 +1,4 @@ -// "$Id: Fl_Native_File_Chooser_WIN32.cxx 9629 2012-06-26 07:03:46Z greg.ercolano $" +// "$Id: Fl_Native_File_Chooser_WIN32.cxx 10312 2014-09-15 09:35:05Z ossman $" // // FLTK native OS file chooser widget // @@ -34,14 +34,12 @@ LPCWSTR utf8towchar(const char *in); //MG char *wchartoutf8(LPCWSTR in); //MG #include <FL/Fl_Native_File_Chooser.H> +#include <FL/x.H> #define LCURLY_CHR '{' #define RCURLY_CHR '}' #define LBRACKET_CHR '[' #define RBRACKET_CHR ']' -#define MAXFILTERS 80 - -void fl_OleInitialize(); // in Fl.cxx (Windows only) // STATIC: PRINT WINDOWS 'DOUBLE NULL' STRING (DEBUG) #ifdef DEBUG @@ -54,7 +52,7 @@ static void dnullprint(char *wp) { return; } else if ( wp[t] == '\0' ) { printf("\\0"); - } else { + } else { printf("%c",wp[t]); } } @@ -96,7 +94,7 @@ static void dnullcat(char*&wp, const char *string, int n = -1 ) { // Make copy of wp into larger buffer char *tmp = new char[wplen + inlen + 4]; memcpy(tmp, wp, wplen+2); // copy of wp plus doublenull - delete [] wp; // delete old wp + delete[] wp; // delete old wp wp = tmp; // use new copy //DEBUG printf("DEBUG: dnullcat COPY: <"); dnullprint(wp); printf("> (wplen=%d)\n", wplen); } @@ -191,7 +189,7 @@ void Fl_Native_File_Chooser::clear_pathnames() { while ( --_tpathnames >= 0 ) { _pathnames[_tpathnames] = strfree(_pathnames[_tpathnames]); } - delete [] _pathnames; + delete[] _pathnames; _pathnames = NULL; } _tpathnames = 0; @@ -214,9 +212,9 @@ void Fl_Native_File_Chooser::add_pathname(const char *s) { } else { // Grow array by 1 char **tmp = new char*[_tpathnames+1]; // create new buffer - memcpy((void*)tmp, (void*)_pathnames, + memcpy((void*)tmp, (void*)_pathnames, sizeof(char*)*_tpathnames); // copy old - delete [] _pathnames; // delete old + delete[] _pathnames; // delete old _pathnames = tmp; // use new ++_tpathnames; } @@ -237,11 +235,11 @@ void Fl_Native_File_Chooser::FreePIDL(LPITEMIDLIST pidl) { void Fl_Native_File_Chooser::ClearOFN() { // Free any previously allocated lpstrFile before zeroing out _ofn if ( _ofn.lpstrFile ) { - delete [] _ofn.lpstrFile; + delete[] _ofn.lpstrFile; _ofn.lpstrFile = NULL; } if ( _ofn.lpstrInitialDir ) { - delete [] (TCHAR*) _ofn.lpstrInitialDir; //msvc6 compilation fix + delete[] (TCHAR*) _ofn.lpstrInitialDir; //msvc6 compilation fix _ofn.lpstrInitialDir = NULL; } _ofn.lpstrFilter = NULL; // (deleted elsewhere) @@ -364,7 +362,7 @@ int Fl_Native_File_Chooser::showfile() { char *oldcwd = 0; DWORD oldcwdsz = GetCurrentDirectory(0,0); if ( oldcwdsz > 0 ) { - oldcwd = (char*)malloc(oldcwdsz); + oldcwd = (char*)malloc(oldcwdsz); if (GetCurrentDirectory(oldcwdsz, oldcwd) == 0 ) { free(oldcwd); oldcwd = 0; } @@ -376,30 +374,25 @@ int Fl_Native_File_Chooser::showfile() { } else { err = GetOpenFileNameW(&_ofn); } + // GET EXTENDED ERROR + int exterr = CommDlgExtendedError(); + // XXX: RESTORE CWD + if ( oldcwd ) { + SetCurrentDirectory(oldcwd); + free(oldcwd); oldcwd = 0; + } + // ERROR OR CANCEL? if ( err == 0 ) { - // EXTENDED ERROR CHECK - int err = CommDlgExtendedError(); - // CANCEL? - if ( err == 0 ) return(1); // user hit 'cancel' - // AN ERROR OCCURRED + if ( exterr == 0 ) return(1); // user hit cancel + // Otherwise, an error occurred.. char msg[80]; sprintf(msg, "CommDlgExtendedError() code=%d", err); errmsg(msg); - // XXX: RESTORE CWD - if ( oldcwd ) { - SetCurrentDirectory(oldcwd); - free(oldcwd); oldcwd = 0; - } return(-1); } - // XXX: RESTORE CWD - if ( oldcwd ) { - SetCurrentDirectory(oldcwd); - free(oldcwd); oldcwd = 0; - } // PREPARE PATHNAMES FOR RETURN switch ( _btype ) { - case BROWSE_FILE: + case BROWSE_FILE: case BROWSE_SAVE_FILE: set_single_pathname(wchartoutf8(_ofn.lpstrFile)); // Win2Unix(_pathnames[_tpathnames-1]); @@ -412,8 +405,8 @@ int Fl_Native_File_Chooser::showfile() { // WALK STRING SEARCHING FOR 'DOUBLE-NULL' // eg. "/dir/name\0foo1\0foo2\0foo3\0\0" // - char pathname[FNFC_MAX_PATH]; - for ( const WCHAR *s = dirname + dirlen + 1; + char pathname[FNFC_MAX_PATH]; + for ( const WCHAR *s = dirname + dirlen + 1; *s; s+= (wcslen(s)+1)) { strcpy(pathname, wchartoutf8(dirname)); strcat(pathname, "\\"); @@ -427,7 +420,7 @@ int Fl_Native_File_Chooser::showfile() { // not to grok forward slashes, passing back as a 'filename'..! // if ( _tpathnames == 0 ) { - add_pathname(wchartoutf8(dirname)); + add_pathname(wchartoutf8(dirname)); // Win2Unix(_pathnames[_tpathnames-1]); } break; @@ -447,7 +440,7 @@ int Fl_Native_File_Chooser::showfile() { int CALLBACK Fl_Native_File_Chooser::Dir_CB(HWND win, UINT msg, LPARAM param, LPARAM data) { switch (msg) { case BFFM_INITIALIZED: - if (data) ::SendMessage(win, BFFM_SETSELECTION, TRUE, data); + if (data) ::SendMessageW(win, BFFM_SETSELECTIONW, TRUE, data); break; case BFFM_SELCHANGED: TCHAR path[FNFC_MAX_PATH]; @@ -459,7 +452,7 @@ int CALLBACK Fl_Native_File_Chooser::Dir_CB(HWND win, UINT msg, LPARAM param, LP } break; case BFFM_VALIDATEFAILED: - // we could pop up an annoying message here. + // we could pop up an annoying message here. // also needs set ulFlags |= BIF_VALIDATE break; default: @@ -471,13 +464,22 @@ int CALLBACK Fl_Native_File_Chooser::Dir_CB(HWND win, UINT msg, LPARAM param, LP // SHOW DIRECTORY BROWSER int Fl_Native_File_Chooser::showdir() { // initialize OLE only once - fl_OleInitialize(); // init needed by BIF_USENEWUI + fl_open_display(); // init needed by BIF_USENEWUI ClearBINF(); clear_pathnames(); // PARENT WINDOW _binf.hwndOwner = GetForegroundWindow(); // DIALOG TITLE - _binf.lpszTitle = _title ? _title : NULL; + //_binf.lpszTitle = _title ? _title : NULL; + if (_title) { + static WCHAR wtitle[256]; + wcsncpy(wtitle, utf8towchar(_title), 256); + wtitle[255] = 0; + _binf.lpszTitle = wtitle; + } else { + _binf.lpszTitle = NULL; + } + // FLAGS _binf.ulFlags = 0; // initialize @@ -510,19 +512,22 @@ int Fl_Native_File_Chooser::showdir() { #endif // BUFFER - char displayname[FNFC_MAX_PATH]; + //char displayname[FNFC_MAX_PATH]; + WCHAR displayname[FNFC_MAX_PATH]; _binf.pszDisplayName = displayname; + // PRESET DIR - char presetname[FNFC_MAX_PATH]; + WCHAR presetname[FNFC_MAX_PATH]; if ( _directory ) { - strcpy(presetname, _directory); // Unix2Win(presetname); + wcsncpy(presetname, utf8towchar(_directory), FNFC_MAX_PATH); + presetname[FNFC_MAX_PATH-1] = 0; _binf.lParam = (LPARAM)presetname; } else _binf.lParam = 0; _binf.lpfn = Dir_CB; // OPEN BROWSER - LPITEMIDLIST pidl = SHBrowseForFolder(&_binf); + LPITEMIDLIST pidl = SHBrowseForFolderW(&_binf); // CANCEL? if ( pidl == NULL ) return(1); @@ -530,13 +535,14 @@ int Fl_Native_File_Chooser::showdir() { // TBD: expand NetHood shortcuts from this PIDL?? // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/reference/functions/shbrowseforfolder.asp - TCHAR path[FNFC_MAX_PATH]; - if ( SHGetPathFromIDList(pidl, path) ) { + WCHAR path[FNFC_MAX_PATH]; + if ( SHGetPathFromIDListW(pidl, path) ) { // Win2Unix(path); - add_pathname(path); + //add_pathname(path); + add_pathname(wchartoutf8(path)); } FreePIDL(pidl); - if ( !strlen(path) ) return(1); // don't return empty pathnames + if ( !wcslen(path) ) return(1); // don't return empty pathnames return(0); } @@ -546,8 +552,8 @@ int Fl_Native_File_Chooser::showdir() { // -1 - failed; errmsg() has reason // int Fl_Native_File_Chooser::show() { - if ( _btype == BROWSE_DIRECTORY || - _btype == BROWSE_MULTI_DIRECTORY || + if ( _btype == BROWSE_DIRECTORY || + _btype == BROWSE_MULTI_DIRECTORY || _btype == BROWSE_SAVE_DIRECTORY ) { return(showdir()); } else { @@ -620,7 +626,7 @@ void Fl_Native_File_Chooser::filter(const char *val) { add_filter("All Files", "*.*"); // always include 'all files' option #ifdef DEBUG - nullprint(_parsedfilt); + dnullprint(_parsedfilt); #endif /*DEBUG*/ } @@ -657,7 +663,55 @@ void Fl_Native_File_Chooser::add_filter(const char *name_in, // name of filter ( //DEBUG printf("DEBUG: ADD FILTER name=<%s> winfilter=<%s>\n", name, winfilter); } +// RETURN HOW MANY DIFFERENT FILTERS WERE SPECIFIED +// In: "foo.[CH]" or "foo.{C,H}" +// Out: 2 +// +static int count_filters(const char *filter) { + int count = 0; + char mode = 0; + const char *in = filter; + while (*in) { + switch(*in) { + case '\\': // escape next character + ++in; if ( *in == 0 ) continue; // skip escape. EOL? done + ++in; // skip escaped char + continue; + case LCURLY_CHR: // start "{aaa,bbb}" + mode = *in; // set mode, parse over curly + ++count; // at least +1 wildcard + break; + case RCURLY_CHR: // end "{aaa,bbb}" + if ( mode == LCURLY_CHR ) // disable curly mode (if on) + mode = 0; + break; + case LBRACKET_CHR: // start "[xyz]" + mode = *in; // set mode, parse over bracket + break; + case RBRACKET_CHR: // end "[xyz]" + if ( mode == LBRACKET_CHR ) // disable bracket mode (if on) + mode = 0; + break; + default: // any other char + switch (mode) { // handle {} or [] modes + case LCURLY_CHR: // handle "{aaa,bbb}" + if (*in==',' || *in=='|') // ',' and '|' adds filters + ++count; + break; + case LBRACKET_CHR: // handle "[xyz]" + ++count; // all chars in []'s add new filter + break; + } + break; + } + ++in; // parse past char + } + return count > 0 ? count : 1; // return at least 1 +} + // CONVERT FLTK STYLE PATTERN MATCHES TO WINDOWS 'DOUBLENULL' PATTERN +// Returns with the parsed double-null result in '_parsedfilt'. +// // Handles: // IN OUT // ----------- ----------------------------- @@ -685,16 +739,22 @@ void Fl_Native_File_Chooser::parse_filter(const char *in) { if ( ! in ) return; int has_name = strchr(in, '\t') ? 1 : 0; + char mode = has_name ? 'n' : 'w'; // parse mode: n=name, w=wildcard - char mode = has_name ? 'n' : 'w'; // parse mode: n=name, w=wildcard - int nwildcards = 0; - char wildcards[MAXFILTERS][1024]; // parsed wildcards (can be several) - char wildprefix[512] = ""; - char name[512] = ""; + // whatever input string is, our output won't be much longer in length.. + // use double length just for safety. + size_t slen = strlen(in); + char *wildprefix = new char[slen*2]; wildprefix[0] = 0; + char *comp = new char[slen*2]; comp[0] = 0; + char *name = new char[slen*2]; name[0] = 0; // Init + int nwildcards = 0; + int maxfilters = count_filters(in) + 1; // count wildcard seps + char **wildcards = new char*[maxfilters]; // parsed wildcards (can be several) int t; - for ( t=0; t<MAXFILTERS; t++ ) { + for ( t=0; t<maxfilters; t++ ) { + wildcards[t] = new char[slen]; wildcards[t][0] = '\0'; } @@ -739,7 +799,7 @@ void Fl_Native_File_Chooser::parse_filter(const char *in) { strcpy(wildcards[nwildcards++], wildprefix); } // Append wildcards in Microsoft's "*.one;*.two" format - char comp[4096] = ""; + comp[0] = 0; for ( t=0; t<nwildcards; t++ ) { if ( t != 0 ) strcat(comp, ";"); strcat(comp, wildcards[t]); @@ -750,14 +810,22 @@ void Fl_Native_File_Chooser::parse_filter(const char *in) { } } // RESET - for ( t=0; t<MAXFILTERS; t++ ) { + for ( t=0; t<maxfilters; t++ ) { wildcards[t][0] = '\0'; } nwildcards = 0; wildprefix[0] = name[0] = '\0'; mode = strchr(in,'\t') ? 'n' : 'w'; // DONE? - if ( *in == '\0' ) return; // done + if ( *in == '\0' ) { // done + // Free everything + delete[] wildprefix; + delete[] comp; + delete[] name; + for ( t=0; t<maxfilters; t++ ) delete[] wildcards[t]; + delete[] wildcards; + return; + } continue; // not done yet, more filters } @@ -781,7 +849,7 @@ void Fl_Native_File_Chooser::parse_filter(const char *in) { default: regchar: // handle regular char switch ( mode ) { - case LBRACKET_CHR: + case LBRACKET_CHR: // create new wildcard ++nwildcards; // copy in prefix @@ -868,5 +936,5 @@ LPCWSTR utf8towchar(const char *in) #endif /*!FL_DOXYGEN*/ // -// End of "$Id: Fl_Native_File_Chooser_WIN32.cxx 9629 2012-06-26 07:03:46Z greg.ercolano $". +// End of "$Id: Fl_Native_File_Chooser_WIN32.cxx 10312 2014-09-15 09:35:05Z ossman $". // diff --git a/src/Fl_Native_File_Chooser_common.cxx b/src/Fl_Native_File_Chooser_common.cxx index 5e8aa98..70e2ca4 100644 --- a/src/Fl_Native_File_Chooser_common.cxx +++ b/src/Fl_Native_File_Chooser_common.cxx @@ -1,4 +1,4 @@ -// "$Id: Fl_Native_File_Chooser_common.cxx 8864 2011-07-19 04:49:30Z greg.ercolano $" +// "$Id: Fl_Native_File_Chooser_common.cxx 10064 2014-01-16 16:10:19Z manolo $" // // FLTK native OS file chooser widget // @@ -71,6 +71,7 @@ static void chrcat(char *s, char c) { strcat(s, tmp); } + // -// End of "$Id: Fl_Native_File_Chooser_common.cxx 8864 2011-07-19 04:49:30Z greg.ercolano $". +// End of "$Id: Fl_Native_File_Chooser_common.cxx 10064 2014-01-16 16:10:19Z manolo $". // diff --git a/src/Fl_PNG_Image.cxx b/src/Fl_PNG_Image.cxx index 30ea565..67eb3df 100644 --- a/src/Fl_PNG_Image.cxx +++ b/src/Fl_PNG_Image.cxx @@ -1,5 +1,5 @@ // -// "$Id: Fl_PNG_Image.cxx 9713 2012-11-10 09:01:16Z manolo $" +// "$Id: Fl_PNG_Image.cxx 9980 2013-09-21 16:41:23Z greg.ercolano $" // // Fl_PNG_Image routines. // @@ -51,20 +51,22 @@ typedef struct { const unsigned char *last; } fl_png_memory; -static void png_read_data_from_mem( png_structp png_ptr, //pointer to our data - png_bytep data, // where to copy the image data for libpng computing - png_size_t length) // length of data to copy -{ - fl_png_memory *png_mem_data = (fl_png_memory*)png_get_io_ptr(png_ptr); // get the pointer to our struct - if (png_mem_data->current + length > png_mem_data->last) { - png_error(png_mem_data->pp, "Invalid attempt to read row data"); - return; +extern "C" { + static void png_read_data_from_mem( png_structp png_ptr, //pointer to our data + png_bytep data, // where to copy the image data for libpng computing + png_size_t length) // length of data to copy + { + fl_png_memory *png_mem_data = (fl_png_memory*)png_get_io_ptr(png_ptr); // get the pointer to our struct + if (png_mem_data->current + length > png_mem_data->last) { + png_error(png_mem_data->pp, "Invalid attempt to read row data"); + return; + } + /* copy data from image buffer */ + memcpy (data, png_mem_data->current, length); + /* advance in the memory data */ + png_mem_data->current += length; } - /* copy data from image buffer */ - memcpy (data, png_mem_data->current, length); - /* advance in the memory data */ - png_mem_data->current += length; -} +} // extern "C" #endif // HAVE_LIBPNG && HAVE_LIBZ @@ -221,5 +223,5 @@ void Fl_PNG_Image::load_png_(const char *name_png, const unsigned char *buffer_p // -// End of "$Id: Fl_PNG_Image.cxx 9713 2012-11-10 09:01:16Z manolo $". +// End of "$Id: Fl_PNG_Image.cxx 9980 2013-09-21 16:41:23Z greg.ercolano $". // diff --git a/src/Fl_Paged_Device.cxx b/src/Fl_Paged_Device.cxx index a5f4b94..8cd4cc7 100644 --- a/src/Fl_Paged_Device.cxx +++ b/src/Fl_Paged_Device.cxx @@ -1,5 +1,5 @@ // -// "$Id: Fl_Paged_Device.cxx 8864 2011-07-19 04:49:30Z greg.ercolano $" +// "$Id: Fl_Paged_Device.cxx 10116 2014-03-05 12:55:34Z manolo $" // // implementation of Fl_Paged_Device class for the Fast Light Tool Kit (FLTK). // @@ -42,6 +42,7 @@ void Fl_Paged_Device::print_widget(Fl_Widget* widget, int delta_x, int delta_y) int old_x, old_y, new_x, new_y, is_window; if ( ! widget->visible() ) return; is_window = (widget->as_window() != NULL); + uchar old_damage = widget->damage(); widget->damage(FL_DAMAGE_ALL); // set origin to the desired top-left position of the widget origin(&old_x, &old_y); @@ -54,29 +55,34 @@ void Fl_Paged_Device::print_widget(Fl_Widget* widget, int delta_x, int delta_y) if (new_x != old_x || new_y != old_y) { translate(new_x - old_x, new_y - old_y ); } - // if widget is a window, clip all drawings to the window area - if (is_window) fl_push_clip(0, 0, widget->w(), widget->h() ); + // if widget is a main window, clip all drawings to the window area + if (is_window && !widget->window()) fl_push_clip(0, 0, widget->w(), widget->h() ); // we do some trickery to recognize OpenGL windows and draw them via a plugin int drawn_by_plugin = 0; if (widget->as_gl_window()) { Fl_Plugin_Manager pm("fltk:device"); Fl_Device_Plugin *pi = (Fl_Device_Plugin*)pm.plugin("opengl.device.fltk.org"); if (pi) { - int width, height; + int height = 0; +#ifdef __APPLE__ + int width; this->printable_rect(&width, &height); +#endif drawn_by_plugin = pi->print(widget, 0, 0, height); } } if (!drawn_by_plugin) { widget->draw(); } - if (is_window) fl_pop_clip(); + if (is_window && !widget->window()) fl_pop_clip(); // find subwindows of widget and print them traverse(widget); // reset origin to where it was if (new_x != old_x || new_y != old_y) { untranslate(); } + if ((old_damage & FL_DAMAGE_CHILD) == 0) widget->clear_damage(old_damage); + else widget->damage(FL_DAMAGE_ALL); } @@ -284,5 +290,5 @@ const Fl_Paged_Device::page_format Fl_Paged_Device::page_formats[NO_PAGE_FORMATS }; // -// End of "$Id: Fl_Paged_Device.cxx 8864 2011-07-19 04:49:30Z greg.ercolano $". +// End of "$Id: Fl_Paged_Device.cxx 10116 2014-03-05 12:55:34Z manolo $". // diff --git a/src/Fl_PostScript.cxx b/src/Fl_PostScript.cxx index b7b72e6..bff175e 100644 --- a/src/Fl_PostScript.cxx +++ b/src/Fl_PostScript.cxx @@ -1,5 +1,5 @@ // -// "$Id: Fl_PostScript.cxx 9630 2012-06-28 08:38:14Z manolo $" +// "$Id: Fl_PostScript.cxx 10308 2014-09-13 17:51:20Z manolo $" // // PostScript device support for the Fast Light Tool Kit (FLTK). // @@ -16,6 +16,7 @@ // http://www.fltk.org/str.php // +#include <FL/Fl_Printer.H> #include <config.h> #include <FL/Fl.H> #include <FL/fl_ask.H> @@ -23,6 +24,7 @@ #include <stdio.h> #include <FL/Fl_PostScript.H> #include <FL/Fl_Native_File_Chooser.H> +#include <stdarg.h> #if defined(USE_X11) #include "Fl_Font.H" #if USE_XFT @@ -94,7 +96,7 @@ int Fl_PostScript_File_Device::start_job (int pagecount, enum Fl_Paged_Device::P // Show native chooser if ( fnfc.show() ) return 1; Fl_PostScript_Graphics_Driver *ps = driver(); - ps->output = fopen(fnfc.filename(), "w"); + ps->output = fl_fopen(fnfc.filename(), "w"); if(ps->output == NULL) return 2; ps->ps_filename_ = strdup(fnfc.filename()); ps->start_postscript(pagecount, format, layout); @@ -102,9 +104,11 @@ int Fl_PostScript_File_Device::start_job (int pagecount, enum Fl_Paged_Device::P return 0; } -static int dont_close(FILE *f) -{ - return 0; +extern "C" { + static int dont_close(FILE *f) + { + return 0; + } } /** @@ -129,6 +133,12 @@ int Fl_PostScript_File_Device::start_job (FILE *ps_output, int pagecount, return 0; } +/** Don't use with this class. */ +int Fl_PostScript_File_Device::start_job(int pagecount, int* from, int* to) +{ + return 1; +} + /** @brief The destructor. */ @@ -137,6 +147,24 @@ Fl_PostScript_File_Device::~Fl_PostScript_File_Device() { if (ps) delete ps; } +/** Shields output PostScript data from modifications of the current locale. + It typically avoids PostScript errors caused if the current locale uses comma instead of dot + as "decimal point". + \param format directives controlling output PostScript data + \return value returned by vfprintf() call + */ +int Fl_PostScript_Graphics_Driver::clocale_printf(const char *format, ...) +{ + char *saved_locale = setlocale(LC_NUMERIC, NULL); + setlocale(LC_NUMERIC, "C"); + va_list args; + va_start(args, format); + int retval = vfprintf(output, format, args); + va_end(args); + setlocale(LC_NUMERIC, saved_locale); + return retval; +} + #ifndef FL_DOXYGEN #if ! (defined(__APPLE__) || defined(WIN32) ) @@ -652,7 +680,7 @@ void Fl_PostScript_Graphics_Driver::page(double pw, double ph, int media) { fprintf(output, "save\n"); fprintf(output, "GS\n"); - fprintf(output, "%g %g TR\n", (double)0 /*lm_*/ , ph_ /* - tm_*/); + clocale_printf( "%g %g TR\n", (double)0 /*lm_*/ , ph_ /* - tm_*/); fprintf(output, "1 -1 SC\n"); line_style(0); fprintf(output, "GS\n"); @@ -701,7 +729,7 @@ void Fl_PostScript_Graphics_Driver::rect(int x, int y, int w, int h) { } void Fl_PostScript_Graphics_Driver::rectf(int x, int y, int w, int h) { - fprintf(output, "%g %g %i %i FR\n", x-0.5, y-0.5, w, h); + clocale_printf( "%g %g %i %i FR\n", x-0.5, y-0.5, w, h); } void Fl_PostScript_Graphics_Driver::line(int x1, int y1, int x2, int y2) { @@ -831,7 +859,7 @@ void Fl_PostScript_Graphics_Driver::point(int x, int y){ rectf(x,y,1,1); } -static int dashes_flat[5][7]={ +static const int dashes_flat[5][7]={ {-1,0,0,0,0,0,0}, {3,1,-1,0,0,0,0}, {1,1,-1,0,0,0,0}, @@ -841,7 +869,7 @@ static int dashes_flat[5][7]={ //yeah, hack... -static double dashes_cap[5][7]={ +static const double dashes_cap[5][7]={ {-1,0,0,0,0,0,0}, {2,2,-1,0,0,0,0}, {0.01,1.99,-1,0,0,0,0}, @@ -890,16 +918,15 @@ void Fl_PostScript_Graphics_Driver::line_style(int style, int width, char* dashe dashes++; } }else{ - int * ds; if(style & 0x200){ // round and square caps, dash length need to be adjusted - double *dt = dashes_cap[style & 0xff]; + const double *dt = dashes_cap[style & 0xff]; while (*dt >= 0){ - fprintf(output, "%g ",width * (*dt)); - dt++; + clocale_printf("%g ",width * (*dt)); + dt++; } }else{ - ds = dashes_flat[style & 0xff]; + const int *ds = dashes_flat[style & 0xff]; while (*ds >= 0){ fprintf(output, "%i ",width * (*ds)); ds++; @@ -954,7 +981,7 @@ void Fl_PostScript_Graphics_Driver::font(int f, int s) { } #endif // USE_XFT #endif // USE_X11 - fprintf(output,"%.1f FS\n", ps_size); + clocale_printf("%.1f FS\n", ps_size); } } @@ -962,6 +989,10 @@ double Fl_PostScript_Graphics_Driver::width(const char *s, int n) { return Fl_Display_Device::display_device()->driver()->width(s, n); } +double Fl_PostScript_Graphics_Driver::width(unsigned u) { + return Fl_Display_Device::display_device()->driver()->width(u); +} + int Fl_PostScript_Graphics_Driver::height() { return Fl_Display_Device::display_device()->driver()->height(); } @@ -985,13 +1016,13 @@ void Fl_PostScript_Graphics_Driver::color(unsigned char r, unsigned char g, unsi cr_ = r; cg_ = g; cb_ = b; if (r == g && g == b) { double gray = r/255.0; - fprintf(output, "%g GL\n", gray); + clocale_printf("%g GL\n", gray); } else { double fr, fg, fb; fr = r/255.0; fg = g/255.0; fb = b/255.0; - fprintf(output, "%g %g %g SRGB\n", fr , fg , fb); + clocale_printf("%g %g %g SRGB\n", fr , fg , fb); } } @@ -1035,7 +1066,7 @@ static uchar *calc_mask(uchar *img, int w, int h, Fl_Color bg) // write to PostScript a bitmap image of a UTF8 string static void transformed_draw_extra(const char* str, int n, double x, double y, int w, - FILE *output, Fl_Graphics_Driver *driver, bool rtl) { + FILE *output, Fl_PostScript_Graphics_Driver *driver, bool rtl) { // scale for bitmask computation #if defined(USE_X11) && !USE_XFT float scale = 1; // don't scale because we can't expect to have scalable fonts @@ -1043,11 +1074,11 @@ static void transformed_draw_extra(const char* str, int n, double x, double y, i float scale = 2; #endif Fl_Fontsize old_size = driver->size(); - Fl_Font fontnum = driver->font(); + Fl_Font fontnum = driver->Fl_Graphics_Driver::font(); int w_scaled = (int)(w * (scale + 0.5)); int h = (int)(driver->height() * scale); // create an offscreen image of the string - Fl_Color text_color = driver->color(); + Fl_Color text_color = driver->Fl_Graphics_Driver::color(); Fl_Color bg_color = fl_contrast(FL_WHITE, text_color); Fl_Offscreen off = fl_create_offscreen(w_scaled, (int)(h+3*scale) ); fl_begin_offscreen(off); @@ -1075,7 +1106,7 @@ static void transformed_draw_extra(const char* str, int n, double x, double y, i delete[] img; // write the string image to PostScript as a scaled bitmask scale = w2 / float(w); - fprintf(output, "%g %g %g %g %d %d MI\n", x, y - h*0.77/scale, w2/scale, h/scale, w2, h); + driver->clocale_printf("%g %g %g %g %d %d MI\n", x, y - h*0.77/scale, w2/scale, h/scale, w2, h); uchar *di; int wmask = (w2+7)/8; for (int j = h - 1; j >= 0; j--){ @@ -1151,7 +1182,7 @@ void Fl_PostScript_Graphics_Driver::transformed_draw(const char* str, int n, dou } fprintf(output, "%4.4X", utf); } - fprintf(output, "> %g %g show_pos_width\n", x, y); + clocale_printf("> %g %g show_pos_width\n", x, y); } void Fl_PostScript_Graphics_Driver::rtl_draw(const char* str, int n, int x, int y) { @@ -1160,11 +1191,11 @@ void Fl_PostScript_Graphics_Driver::rtl_draw(const char* str, int n, int x, int } void Fl_PostScript_Graphics_Driver::concat(){ - fprintf(output,"[%g %g %g %g %g %g] CT\n", fl_matrix->a , fl_matrix->b , fl_matrix->c , fl_matrix->d , fl_matrix->x , fl_matrix->y); + clocale_printf("[%g %g %g %g %g %g] CT\n", fl_matrix->a , fl_matrix->b , fl_matrix->c , fl_matrix->d , fl_matrix->x , fl_matrix->y); } void Fl_PostScript_Graphics_Driver::reconcat(){ - fprintf(output, "[%g %g %g %g %g %g] RCT\n" , fl_matrix->a , fl_matrix->b , fl_matrix->c , fl_matrix->d , fl_matrix->x , fl_matrix->y); + clocale_printf("[%g %g %g %g %g %g] RCT\n" , fl_matrix->a , fl_matrix->b , fl_matrix->c , fl_matrix->d , fl_matrix->x , fl_matrix->y); } ///////////////// transformed (double) drawings //////////////////////////////// @@ -1205,26 +1236,26 @@ void Fl_PostScript_Graphics_Driver::begin_polygon(){ void Fl_PostScript_Graphics_Driver::vertex(double x, double y){ if(shape_==POINTS){ - fprintf(output,"%g %g MT\n", x , y); + clocale_printf("%g %g MT\n", x , y); gap_=1; return; } if(gap_){ - fprintf(output,"%g %g MT\n", x , y); + clocale_printf("%g %g MT\n", x , y); gap_=0; }else - fprintf(output, "%g %g LT\n", x , y); + clocale_printf("%g %g LT\n", x , y); } void Fl_PostScript_Graphics_Driver::curve(double x, double y, double x1, double y1, double x2, double y2, double x3, double y3){ if(shape_==NONE) return; if(gap_) - fprintf(output,"%g %g MT\n", x , y); + clocale_printf("%g %g MT\n", x , y); else - fprintf(output, "%g %g LT\n", x , y); + clocale_printf("%g %g LT\n", x , y); gap_=0; - fprintf(output, "%g %g %g %g %g %g curveto \n", x1 , y1 , x2 , y2 , x3 , y3); + clocale_printf("%g %g %g %g %g %g curveto \n", x1 , y1 , x2 , y2 , x3 , y3); } @@ -1233,13 +1264,13 @@ void Fl_PostScript_Graphics_Driver::circle(double x, double y, double r){ fprintf(output, "GS\n"); concat(); // fprintf(output, "BP\n"); - fprintf(output,"%g %g %g 0 360 arc\n", x , y , r); + clocale_printf("%g %g %g 0 360 arc\n", x , y , r); reconcat(); // fprintf(output, "ELP\n"); fprintf(output, "GR\n"); }else - fprintf(output, "%g %g %g 0 360 arc\n", x , y , r); + clocale_printf("%g %g %g 0 360 arc\n", x , y , r); } @@ -1247,22 +1278,23 @@ void Fl_PostScript_Graphics_Driver::arc(double x, double y, double r, double sta if(shape_==NONE) return; gap_=0; if(start>a) - fprintf(output, "%g %g %g %g %g arc\n", x , y , r , -start, -a); + clocale_printf("%g %g %g %g %g arc\n", x , y , r , -start, -a); else - fprintf(output, "%g %g %g %g %g arcn\n", x , y , r , -start, -a); + clocale_printf("%g %g %g %g %g arcn\n", x , y , r , -start, -a); } void Fl_PostScript_Graphics_Driver::arc(int x, int y, int w, int h, double a1, double a2) { + if (w <= 1 || h <= 1) return; fprintf(output, "GS\n"); //fprintf(output, "BP\n"); begin_line(); - fprintf(output, "%g %g TR\n", x + w/2.0 -0.5 , y + h/2.0 - 0.5); - fprintf(output, "%g %g SC\n", (w-1)/2.0 , (h-1)/2.0 ); + clocale_printf("%g %g TR\n", x + w/2.0 -0.5 , y + h/2.0 - 0.5); + clocale_printf("%g %g SC\n", (w-1)/2.0 , (h-1)/2.0 ); arc(0,0,1,a2,a1); // fprintf(output, "0 0 1 %g %g arc\n" , -a1 , -a2); - fprintf(output, "%g %g SC\n", 2.0/(w-1) , 2.0/(h-1) ); - fprintf(output, "%g %g TR\n", -x - w/2.0 +0.5 , -y - h/2.0 +0.5); + clocale_printf("%g %g SC\n", 2.0/(w-1) , 2.0/(h-1) ); + clocale_printf("%g %g TR\n", -x - w/2.0 +0.5 , -y - h/2.0 +0.5); end_line(); // fprintf(output, "%g setlinewidth\n", 2/sqrt(w*h)); @@ -1275,8 +1307,8 @@ void Fl_PostScript_Graphics_Driver::arc(int x, int y, int w, int h, double a1, d void Fl_PostScript_Graphics_Driver::pie(int x, int y, int w, int h, double a1, double a2) { fprintf(output, "GS\n"); begin_polygon(); - fprintf(output, "%g %g TR\n", x + w/2.0 -0.5 , y + h/2.0 - 0.5); - fprintf(output, "%g %g SC\n", (w-1)/2.0 , (h-1)/2.0 ); + clocale_printf("%g %g TR\n", x + w/2.0 -0.5 , y + h/2.0 - 0.5); + clocale_printf("%g %g SC\n", (w-1)/2.0 , (h-1)/2.0 ); vertex(0,0); arc(0.0,0.0, 1, a2, a1); end_polygon(); @@ -1318,10 +1350,10 @@ void Fl_PostScript_Graphics_Driver::end_polygon(){ void Fl_PostScript_Graphics_Driver::transformed_vertex(double x, double y){ reconcat(); if(gap_){ - fprintf(output, "%g %g MT\n", x , y); + clocale_printf("%g %g MT\n", x , y); gap_=0; }else - fprintf(output, "%g %g LT\n", x , y); + clocale_printf("%g %g LT\n", x , y); concat(); } @@ -1335,7 +1367,7 @@ void Fl_PostScript_Graphics_Driver::push_clip(int x, int y, int w, int h) { fprintf(output, "CR\nCS\n"); if(lang_level_<3) recover(); - fprintf(output, "%g %g %i %i CL\n", clip_->x-0.5 , clip_->y-0.5 , clip_->w , clip_->h); + clocale_printf("%g %g %i %i CL\n", clip_->x-0.5 , clip_->y-0.5 , clip_->w , clip_->h); } @@ -1356,7 +1388,7 @@ void Fl_PostScript_Graphics_Driver::pop_clip() { delete c; fprintf(output, "CR\nCS\n"); if(clip_ && clip_->w >0) - fprintf(output, "%g %g %i %i CL\n", clip_->x - 0.5, clip_->y - 0.5, clip_->w , clip_->h); + clocale_printf("%g %g %i %i CL\n", clip_->x - 0.5, clip_->y - 0.5, clip_->w , clip_->h); // uh, -0.5 is to match screen clipping, for floats there should be something beter if(lang_level_<3) recover(); @@ -1407,7 +1439,6 @@ int Fl_PostScript_Graphics_Driver::not_clipped(int x, int y, int w, int h){ return 0; } - void Fl_PostScript_File_Device::margins(int *left, int *top, int *right, int *bottom) // to implement { Fl_PostScript_Graphics_Driver *ps = driver(); @@ -1436,7 +1467,7 @@ void Fl_PostScript_File_Device::origin(int x, int y) x_offset = x; y_offset = y; Fl_PostScript_Graphics_Driver *ps = driver(); - fprintf(ps->output, "GR GR GS %d %d TR %f %f SC %d %d TR %f rotate GS\n", + ps->clocale_printf("GR GR GS %d %d TR %f %f SC %d %d TR %f rotate GS\n", ps->left_margin, ps->top_margin, ps->scale_x, ps->scale_y, x, y, ps->angle); } @@ -1446,7 +1477,7 @@ void Fl_PostScript_File_Device::scale (float s_x, float s_y) Fl_PostScript_Graphics_Driver *ps = driver(); ps->scale_x = s_x; ps->scale_y = s_y; - fprintf(ps->output, "GR GR GS %d %d TR %f %f SC %f rotate GS\n", + ps->clocale_printf("GR GR GS %d %d TR %f %f SC %f rotate GS\n", ps->left_margin, ps->top_margin, ps->scale_x, ps->scale_y, ps->angle); } @@ -1454,7 +1485,7 @@ void Fl_PostScript_File_Device::rotate (float rot_angle) { Fl_PostScript_Graphics_Driver *ps = driver(); ps->angle = - rot_angle; - fprintf(ps->output, "GR GR GS %d %d TR %f %f SC %d %d TR %f rotate GS\n", + ps->clocale_printf("GR GR GS %d %d TR %f %f SC %d %d TR %f rotate GS\n", ps->left_margin, ps->top_margin, ps->scale_x, ps->scale_y, x_offset, y_offset, ps->angle); } @@ -1577,7 +1608,7 @@ int Fl_PostScript_Printer::start_job(int pages, int *firstpage, int *lastpage) { if (to < from) to = from; if (firstpage) *firstpage = from; if (lastpage) *lastpage = to; - pages = to - from + 1; + if (pages > 0) pages = to - from + 1; } if (print_output_mode[0]->value()) layout = Fl_Paged_Device::PORTRAIT; @@ -1617,5 +1648,5 @@ int Fl_PostScript_Printer::start_job(int pages, int *firstpage, int *lastpage) { #endif // FL_DOXYGEN // -// End of "$Id: Fl_PostScript.cxx 9630 2012-06-28 08:38:14Z manolo $". +// End of "$Id: Fl_PostScript.cxx 10308 2014-09-13 17:51:20Z manolo $". // diff --git a/src/Fl_Preferences.cxx b/src/Fl_Preferences.cxx index ada52a6..3cf501b 100644 --- a/src/Fl_Preferences.cxx +++ b/src/Fl_Preferences.cxx @@ -1,5 +1,5 @@ // -// "$Id: Fl_Preferences.cxx 9334 2012-04-09 12:36:23Z AlbrechtS $" +// "$Id: Fl_Preferences.cxx 10378 2014-10-14 12:10:18Z ianmacarthur $" // // Preferences methods for the Fast Light Tool Kit (FLTK). // @@ -40,10 +40,14 @@ #elif defined (__APPLE__) # include <ApplicationServices/ApplicationServices.h> # include <unistd.h> +# include <config.h> # include <dlfcn.h> #else # include <unistd.h> -# include <dlfcn.h> +# include <config.h> +# if HAVE_DLFCN_H +# include <dlfcn.h> +# endif #endif #ifdef WIN32 @@ -1212,7 +1216,7 @@ int Fl_Preferences::RootNode::write() { // get the path to the preferences directory char Fl_Preferences::RootNode::getPath( char *path, int pathlen ) { if (!filename_) // RUNTIME preferences - return -1; + return 1; // return 1 (not -1) to be consistent with fl_make_path() strlcpy( path, filename_, pathlen); char *s; @@ -1766,7 +1770,10 @@ int Fl_Plugin_Manager::load(const char *filename) { #if defined(WIN32) && !defined(__CYGWIN__) HMODULE dl = LoadLibrary(filename); #else - void * dl = dlopen(filename, RTLD_LAZY); + void * dl = NULL; +# if HAVE_DLSYM + dl = dlopen(filename, RTLD_LAZY); +# endif #endif // There is no way of unloading a plugin! return (dl!=0) ? 0 : -1; @@ -1790,5 +1797,5 @@ int Fl_Plugin_Manager::loadAll(const char *filepath, const char *pattern) { } // -// End of "$Id: Fl_Preferences.cxx 9334 2012-04-09 12:36:23Z AlbrechtS $". +// End of "$Id: Fl_Preferences.cxx 10378 2014-10-14 12:10:18Z ianmacarthur $". // diff --git a/src/Fl_Printer.cxx b/src/Fl_Printer.cxx index a953c9c..3518d23 100644 --- a/src/Fl_Printer.cxx +++ b/src/Fl_Printer.cxx @@ -1,5 +1,5 @@ // -// "$Id: Fl_Printer.cxx 8864 2011-07-19 04:49:30Z greg.ercolano $" +// "$Id: Fl_Printer.cxx 10291 2014-09-08 16:03:52Z manolo $" // // Encompasses platform-specific printing-support code and // PostScript output code for the Fast Light Tool Kit (FLTK). @@ -19,14 +19,10 @@ #include <FL/Fl_Printer.H> -#ifdef __APPLE__ -//#include "Fl_Quartz_Printer.mm" -#elif defined(WIN32) +#if defined(WIN32) #include "Fl_GDI_Printer.cxx" #endif -#include "Fl_PostScript.cxx" - // print dialog customization strings /** [this text may be customized at run-time] */ const char *Fl_Printer::dialog_title = "Print"; @@ -189,5 +185,5 @@ Fl_Printer::~Fl_Printer(void) // -// End of "$Id: Fl_Printer.cxx 8864 2011-07-19 04:49:30Z greg.ercolano $". +// End of "$Id: Fl_Printer.cxx 10291 2014-09-08 16:03:52Z manolo $". // diff --git a/src/Fl_Quartz_Printer.mm b/src/Fl_Quartz_Printer.mm index 71646f5..a7cf38e 100644 --- a/src/Fl_Quartz_Printer.mm +++ b/src/Fl_Quartz_Printer.mm @@ -1,9 +1,9 @@ // -// "$Id: Fl_Quartz_Printer.mm 9276 2012-03-12 09:39:17Z manolo $" +// "$Id: Fl_Quartz_Printer.mm 10393 2014-10-26 15:23:03Z manolo $" // // Mac OS X-specific printing support (objective-c++) for the Fast Light Tool Kit (FLTK). // -// Copyright 2010-2012 by Bill Spitzak and others. +// Copyright 2010-2014 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this @@ -24,6 +24,21 @@ #include <FL/fl_draw.H> #import <Cocoa/Cocoa.h> +typedef OSStatus (*PMSessionSetDocumentFormatGeneration_type)( + PMPrintSession printSession, + CFStringRef docFormat, + CFArrayRef graphicsContextTypes, + CFTypeRef options); +typedef OSStatus (*PMSessionBeginDocumentNoDialog_type)( + PMPrintSession printSession, + PMPrintSettings printSettings, + PMPageFormat pageFormat); +typedef OSStatus +(*PMSessionGetGraphicsContext_type)( + PMPrintSession printSession, + CFStringRef graphicsContextType, + void ** graphicsContext); + extern void fl_quartz_restore_line_style_(); Fl_System_Printer::Fl_System_Printer(void) @@ -69,9 +84,9 @@ int Fl_System_Printer::start_job (int pagecount, int *frompage, int *topage) if(topage && *topage > pagecount) *topage = pagecount; status = PMSessionBeginCGDocumentNoDialog(printSession, printSettings, pageFormat);//from 10.4 } - else { + else #endif - + { #if !__LP64__ Boolean accepted; status = PMCreateSession(&printSession); @@ -112,14 +127,16 @@ int Fl_System_Printer::start_job (int pagecount, int *frompage, int *topage) CFStringRef mystring[1]; mystring[0] = kPMGraphicsContextCoreGraphics; CFArrayRef array = CFArrayCreate(NULL, (const void **)mystring, 1, &kCFTypeArrayCallBacks); + PMSessionSetDocumentFormatGeneration_type PMSessionSetDocumentFormatGeneration = + (PMSessionSetDocumentFormatGeneration_type)Fl_X::get_carbon_function("PMSessionSetDocumentFormatGeneration"); status = PMSessionSetDocumentFormatGeneration(printSession, kPMDocumentFormatDefault, array, NULL); CFRelease(array); + PMSessionBeginDocumentNoDialog_type PMSessionBeginDocumentNoDialog = + (PMSessionBeginDocumentNoDialog_type)Fl_X::get_carbon_function("PMSessionBeginDocumentNoDialog"); status = PMSessionBeginDocumentNoDialog(printSession, printSettings, pageFormat); #endif //__LP64__ - -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 } -#endif + if (status != noErr) return 1; y_offset = x_offset = 0; this->set_current(); @@ -224,14 +241,15 @@ int Fl_System_Printer::start_page (void) if ( PMSessionGetCGGraphicsContext != NULL ) { status = PMSessionGetCGGraphicsContext(printSession, &fl_gc); } - else { + else #endif -#if ! __LP64__ - status = PMSessionGetGraphicsContext(printSession,NULL,(void **)&fl_gc); + { +#if ! __LP64_ + PMSessionGetGraphicsContext_type PMSessionGetGraphicsContext = + (PMSessionGetGraphicsContext_type)Fl_X::get_carbon_function("PMSessionGetGraphicsContext"); + status = PMSessionGetGraphicsContext(printSession, NULL, (void **)&fl_gc); #endif -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 } -#endif PMRect pmRect; float win_scale_x, win_scale_y; @@ -284,14 +302,41 @@ void Fl_System_Printer::end_job (void) fl_alert ("PM Session error %d", (int)status); } PMSessionEndDocumentNoDialog(printSession); +#if !__LP64__ + if (fl_mac_os_version < 100500) { + PMRelease(printSettings); + PMRelease(pageFormat); + PMRelease(printSession); + } +#endif Fl_Display_Device::display_device()->set_current(); fl_gc = 0; Fl_Window *w = Fl::first_window(); if (w) w->show(); } +// version that prints at high res if using a retina display +void Fl_System_Printer::print_window_part(Fl_Window *win, int x, int y, int w, int h, int delta_x, int delta_y) +{ + Fl_Surface_Device *current = Fl_Surface_Device::surface(); + Fl_Display_Device::display_device()->set_current(); + Fl_Window *save_front = Fl::first_window(); + win->show(); + fl_gc = NULL; + Fl::check(); + win->make_current(); + CGImageRef img = Fl_X::CGImage_from_window_rect(win, x, y, w, h); + if (save_front != win) save_front->show(); + current->set_current(); + CGRect rect = { { delta_x, delta_y }, { w, h } }; + Fl_X::q_begin_image(rect, 0, 0, w, h); + CGContextDrawImage(fl_gc, rect, img); + Fl_X::q_end_image(); + CFRelease(img); +} + #endif // __APPLE__ // -// End of "$Id: Fl_Quartz_Printer.mm 9276 2012-03-12 09:39:17Z manolo $". +// End of "$Id: Fl_Quartz_Printer.mm 10393 2014-10-26 15:23:03Z manolo $". // diff --git a/src/Fl_Round_Button.cxx b/src/Fl_Round_Button.cxx index c2edc4e..c2f24ce 100644 --- a/src/Fl_Round_Button.cxx +++ b/src/Fl_Round_Button.cxx @@ -1,12 +1,12 @@ // -// "$Id: Fl_Round_Button.cxx 9637 2012-07-24 04:37:22Z matt $" +// "$Id: Fl_Round_Button.cxx 10386 2014-10-19 20:17:17Z AlbrechtS $" // // Round button for the Fast Light Tool Kit (FLTK). // -// Copyright 1998-2010 by Bill Spitzak and others. +// Copyright 1998-2014 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in -// the file "COPYING" which should have been included with this file. If this +// the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // http://www.fltk.org/COPYING.php @@ -25,24 +25,49 @@ #include <FL/Fl_Radio_Round_Button.H> /** - Creates a new Fl_Round_Button widget using the given - position, size, and label string. + Creates a new Fl_Round_Button widget using the given position, size, and label string. + + \image html Fl_Round_Button.png + \image latex Fl_Round_Button.png " Fl_Round_Button" width=4cm + + The Fl_Round_Button subclass displays the "ON" state by + turning on a light, rather than drawing pushed in. + + The default box type is FL_NO_BOX, which draws the label w/o a box + right of the checkmark. + + The shape of the "light" is set with down_box() and its default + value is FL_ROUND_DOWN_BOX. + + The color of the light when on is controlled with selection_color(), + which defaults to FL_FOREGROUND_COLOR (usually black). + + \param[in] X, Y, W, H position and size of the widget + \param[in] L widget label, default is no label */ -Fl_Round_Button::Fl_Round_Button(int X,int Y,int W,int H, const char *l) -: Fl_Light_Button(X,Y,W,H,l) { +Fl_Round_Button::Fl_Round_Button(int X,int Y,int W,int H, const char *L) +: Fl_Light_Button(X,Y,W,H,L) { box(FL_NO_BOX); down_box(FL_ROUND_DOWN_BOX); selection_color(FL_FOREGROUND_COLOR); } +/** + Creates a new Fl_Radio_Button widget using the given position, size, and label string. + + The button type() is set to FL_RADIO_BUTTON. + + \param[in] X, Y, W, H position and size of the widget + \param[in] L widget label, default is no label +*/ Fl_Radio_Round_Button::Fl_Radio_Round_Button(int X,int Y,int W,int H,const char *L) -: Fl_Round_Button(X,Y,W,H,L) +: Fl_Round_Button(X,Y,W,H,L) { type(FL_RADIO_BUTTON); } // -// End of "$Id: Fl_Round_Button.cxx 9637 2012-07-24 04:37:22Z matt $". +// End of "$Id: Fl_Round_Button.cxx 10386 2014-10-19 20:17:17Z AlbrechtS $". // diff --git a/src/Fl_Scroll.cxx b/src/Fl_Scroll.cxx index a93cde1..9317a11 100644 --- a/src/Fl_Scroll.cxx +++ b/src/Fl_Scroll.cxx @@ -1,5 +1,5 @@ // -// "$Id: Fl_Scroll.cxx 8864 2011-07-19 04:49:30Z greg.ercolano $" +// "$Id: Fl_Scroll.cxx 10221 2014-07-16 18:51:56Z greg.ercolano $" // // Scroll widget for the Fast Light Tool Kit (FLTK). // @@ -100,60 +100,61 @@ void Fl_Scroll::draw_clip(void* v,int X, int Y, int W, int H) { void Fl_Scroll::recalc_scrollbars(ScrollInfo &si) { // inner box of widget (excluding scrollbars) - si.innerbox_x = x()+Fl::box_dx(box()); - si.innerbox_y = y()+Fl::box_dy(box()); - si.innerbox_w = w()-Fl::box_dw(box()); - si.innerbox_h = h()-Fl::box_dh(box()); + si.innerbox.x = x()+Fl::box_dx(box()); + si.innerbox.y = y()+Fl::box_dy(box()); + si.innerbox.w = w()-Fl::box_dw(box()); + si.innerbox.h = h()-Fl::box_dh(box()); // accumulate a bounding box for all the children - si.child_l = si.innerbox_x; - si.child_r = si.innerbox_x; - si.child_b = si.innerbox_y; - si.child_t = si.innerbox_y; + si.child.l = si.innerbox.x; + si.child.r = si.innerbox.x; + si.child.b = si.innerbox.y; + si.child.t = si.innerbox.y; int first = 1; Fl_Widget*const* a = array(); - for (int i=children()-2; i--;) { + for (int i=children(); i--;) { Fl_Widget* o = *a++; + if ( o==&scrollbar || o==&hscrollbar ) continue; if ( first ) { first = 0; - si.child_l = o->x(); - si.child_r = o->x()+o->w(); - si.child_b = o->y()+o->h(); - si.child_t = o->y(); + si.child.l = o->x(); + si.child.r = o->x()+o->w(); + si.child.b = o->y()+o->h(); + si.child.t = o->y(); } else { - if (o->x() < si.child_l) si.child_l = o->x(); - if (o->y() < si.child_t) si.child_t = o->y(); - if (o->x()+o->w() > si.child_r) si.child_r = o->x()+o->w(); - if (o->y()+o->h() > si.child_b) si.child_b = o->y()+o->h(); + if (o->x() < si.child.l) si.child.l = o->x(); + if (o->y() < si.child.t) si.child.t = o->y(); + if (o->x()+o->w() > si.child.r) si.child.r = o->x()+o->w(); + if (o->y()+o->h() > si.child.b) si.child.b = o->y()+o->h(); } } // Turn the scrollbars on and off as necessary. // See if children would fit if we had no scrollbars... { - int X = si.innerbox_x; - int Y = si.innerbox_y; - int W = si.innerbox_w; - int H = si.innerbox_h; + int X = si.innerbox.x; + int Y = si.innerbox.y; + int W = si.innerbox.w; + int H = si.innerbox.h; si.scrollsize = scrollbar_size_ ? scrollbar_size_ : Fl::scrollbar_size(); si.vneeded = 0; si.hneeded = 0; if (type() & VERTICAL) { - if ((type() & ALWAYS_ON) || si.child_t < Y || si.child_b > Y+H) { + if ((type() & ALWAYS_ON) || si.child.t < Y || si.child.b > Y+H) { si.vneeded = 1; W -= si.scrollsize; if (scrollbar.align() & FL_ALIGN_LEFT) X += si.scrollsize; } } if (type() & HORIZONTAL) { - if ((type() & ALWAYS_ON) || si.child_l < X || si.child_r > X+W) { + if ((type() & ALWAYS_ON) || si.child.l < X || si.child.r > X+W) { si.hneeded = 1; H -= si.scrollsize; if (scrollbar.align() & FL_ALIGN_TOP) Y += si.scrollsize; // recheck vertical since we added a horizontal scrollbar if (!si.vneeded && (type() & VERTICAL)) { - if ((type() & ALWAYS_ON) || si.child_t < Y || si.child_b > Y+H) { + if ((type() & ALWAYS_ON) || si.child.t < Y || si.child.b > Y+H) { si.vneeded = 1; W -= si.scrollsize; if (scrollbar.align() & FL_ALIGN_LEFT) X += si.scrollsize; @@ -161,51 +162,51 @@ void Fl_Scroll::recalc_scrollbars(ScrollInfo &si) { } } } - si.innerchild_x = X; - si.innerchild_y = Y; - si.innerchild_w = W; - si.innerchild_h = H; + si.innerchild.x = X; + si.innerchild.y = Y; + si.innerchild.w = W; + si.innerchild.h = H; } // calculate hor scrollbar position - si.hscroll_x = si.innerchild_x; - si.hscroll_y = (scrollbar.align() & FL_ALIGN_TOP) - ? si.innerbox_y - : si.innerbox_y + si.innerbox_h - si.scrollsize; - si.hscroll_w = si.innerchild_w; - si.hscroll_h = si.scrollsize; + si.hscroll.x = si.innerchild.x; + si.hscroll.y = (scrollbar.align() & FL_ALIGN_TOP) + ? si.innerbox.y + : si.innerbox.y + si.innerbox.h - si.scrollsize; + si.hscroll.w = si.innerchild.w; + si.hscroll.h = si.scrollsize; // calculate ver scrollbar position - si.vscroll_x = (scrollbar.align() & FL_ALIGN_LEFT) - ? si.innerbox_x - : si.innerbox_x + si.innerbox_w - si.scrollsize; - si.vscroll_y = si.innerchild_y; - si.vscroll_w = si.scrollsize; - si.vscroll_h = si.innerchild_h; + si.vscroll.x = (scrollbar.align() & FL_ALIGN_LEFT) + ? si.innerbox.x + : si.innerbox.x + si.innerbox.w - si.scrollsize; + si.vscroll.y = si.innerchild.y; + si.vscroll.w = si.scrollsize; + si.vscroll.h = si.innerchild.h; // calculate h/v scrollbar values (pos/size/first/total) - si.hpos = si.innerchild_x - si.child_l; - si.hsize = si.innerchild_w; - si.hfirst = 0; - si.htotal = si.child_r - si.child_l; - if ( si.hpos < 0 ) { si.htotal += (-si.hpos); si.hfirst = si.hpos; } - - si.vpos = si.innerchild_y - si.child_t; - si.vsize = si.innerchild_h; - si.vfirst = 0; - si.vtotal = si.child_b - si.child_t; - if ( si.vpos < 0 ) { si.vtotal += (-si.vpos); si.vfirst = si.vpos; } + si.hscroll.pos = si.innerchild.x - si.child.l; + si.hscroll.size = si.innerchild.w; + si.hscroll.first = 0; + si.hscroll.total = si.child.r - si.child.l; + if ( si.hscroll.pos < 0 ) { si.hscroll.total += (-si.hscroll.pos); si.hscroll.first = si.hscroll.pos; } + + si.vscroll.pos = si.innerchild.y - si.child.t; + si.vscroll.size = si.innerchild.h; + si.vscroll.first = 0; + si.vscroll.total = si.child.b - si.child.t; + if ( si.vscroll.pos < 0 ) { si.vscroll.total += (-si.vscroll.pos); si.vscroll.first = si.vscroll.pos; } // printf("DEBUG --- ScrollInfo ---\n"); // printf("DEBUG scrollsize: %d\n", si.scrollsize); // printf("DEBUG hneeded, vneeded: %d %d\n", si.hneeded, si.vneeded); -// printf("DEBUG innerbox xywh: %d %d %d %d\n", si.innerbox_x, si.innerbox_y, si.innerbox_w, si.innerbox_h); -// printf("DEBUG innerchild xywh: %d %d %d %d\n", si.innerchild_x, si.innerchild_y, si.innerchild_w, si.innerchild_h); -// printf("DEBUG child lrbt: %d %d %d %d\n", si.child_l, si.child_r, si.child_b, si.child_t); -// printf("DEBUG hscroll xywh: %d %d %d %d\n", si.hscroll_x, si.hscroll_y, si.hscroll_w, si.hscroll_h); -// printf("DEBUG vscroll xywh: %d %d %d %d\n", si.vscroll_x, si.vscroll_y, si.vscroll_w, si.vscroll_h); -// printf("DEBUG horz scroll vals: %d %d %d %d\n", si.hpos, si.hsize, si.hfirst, si.htotal); -// printf("DEBUG vert scroll vals: %d %d %d %d\n", si.vpos, si.vsize, si.vfirst, si.vtotal); +// printf("DEBUG innerbox.x, si.innerbox.y, si.innerbox.w,si.innerbox.h); +// printf("DEBUG innerchild.xywh: %d %d %d %d\n", si.innerchild.x, si.innerchild.y, si.innerchild.w, si.innerchild.h); +// printf("DEBUG child lrbt: %d %d %d %d\n", si.child.l, si.child.r, si.child.b, si.child.t); +// printf("DEBUG hscroll xywh: %d %d %d %d\n", si.hscroll.x, si.hscroll.y, si.hscroll.w, si.hscroll.h); +// printf("DEBUG vscroll xywh: %d %d %d %d\n", si.vscroll.x, si.vscroll.y, si.vscroll.w, si.vscroll.h); +// printf("DEBUG horz scroll vals: %d %d %d %d\n", si.hscroll.pos, si.hscroll.size, si.hscroll.first, si.hscroll.total); +// printf("DEBUG vert scroll vals: %d %d %d %d\n", si.vscroll.pos, si.vscroll.size, si.vscroll.first, si.vscroll.total); // printf("DEBUG \n"); } @@ -286,7 +287,7 @@ void Fl_Scroll::draw() { } else if (!si.vneeded && scrollbar.visible()) { scrollbar.clear_visible(); - draw_clip(this, si.vscroll_x, si.vscroll_y, si.vscroll_w, si.vscroll_h); + draw_clip(this, si.vscroll.x, si.vscroll.y, si.vscroll.w, si.vscroll.h); d = FL_DAMAGE_ALL; } if (si.hneeded && !hscrollbar.visible()) { @@ -295,7 +296,7 @@ void Fl_Scroll::draw() { } else if (!si.hneeded && hscrollbar.visible()) { hscrollbar.clear_visible(); - draw_clip(this, si.hscroll_x, si.hscroll_y, si.hscroll_w, si.hscroll_h); + draw_clip(this, si.hscroll.x, si.hscroll.y, si.hscroll.w, si.hscroll.h); d = FL_DAMAGE_ALL; } else if ( hscrollbar.h() != si.scrollsize || scrollbar.w() != si.scrollsize ) { @@ -303,13 +304,13 @@ void Fl_Scroll::draw() { d = FL_DAMAGE_ALL; } - scrollbar.resize(si.vscroll_x, si.vscroll_y, si.vscroll_w, si.vscroll_h); - oldy = yposition_ = si.vpos; // si.innerchild_y - si.child_t; - scrollbar.value(si.vpos, si.vsize, si.vfirst, si.vtotal); + scrollbar.resize(si.vscroll.x, si.vscroll.y, si.vscroll.w, si.vscroll.h); + oldy = yposition_ = si.vscroll.pos; // si.innerchild.y - si.child.t; + scrollbar.value(si.vscroll.pos, si.vscroll.size, si.vscroll.first, si.vscroll.total); - hscrollbar.resize(si.hscroll_x, si.hscroll_y, si.hscroll_w, si.hscroll_h); - oldx = xposition_ = si.hpos; // si.innerchild_x - si.child_l; - hscrollbar.value(si.hpos, si.hsize, si.hfirst, si.htotal); + hscrollbar.resize(si.hscroll.x, si.hscroll.y, si.hscroll.w, si.hscroll.h); + oldx = xposition_ = si.hscroll.pos; // si.innerchild.x - si.child.l; + hscrollbar.value(si.hscroll.pos, si.hscroll.size, si.hscroll.first, si.hscroll.total); } // draw the scrollbars: @@ -383,7 +384,7 @@ void Fl_Scroll::scrollbar_cb(Fl_Widget* o, void*) { whole tree to be deleted at once, without having to keep a pointer to all the children in the user code. A kludge has been done so the Fl_Scroll and all of its children can be automatic (local) - variables, but you must declare the Fl_Scroll<I>first</I>, so + variables, but you must declare the Fl_Scroll <I>first</I>, so that it is destroyed last. */ Fl_Scroll::Fl_Scroll(int X,int Y,int W,int H,const char* L) @@ -407,5 +408,5 @@ int Fl_Scroll::handle(int event) { } // -// End of "$Id: Fl_Scroll.cxx 8864 2011-07-19 04:49:30Z greg.ercolano $". +// End of "$Id: Fl_Scroll.cxx 10221 2014-07-16 18:51:56Z greg.ercolano $". // diff --git a/src/Fl_Sys_Menu_Bar.cxx b/src/Fl_Sys_Menu_Bar.cxx deleted file mode 100644 index 698d562..0000000 --- a/src/Fl_Sys_Menu_Bar.cxx +++ /dev/null @@ -1,289 +0,0 @@ -// -// "$Id: Fl_Sys_Menu_Bar.cxx 9637 2012-07-24 04:37:22Z matt $" -// -// MacOS system menu bar widget for the Fast Light Tool Kit (FLTK). -// -// Copyright 1998-2010 by Bill Spitzak and others. -// -// This library is free software. Distribution and use rights are outlined in -// the file "COPYING" which should have been included with this file. If this -// file is missing or damaged, see the license at: -// -// http://www.fltk.org/COPYING.php -// -// Please report all bugs and problems on the following page: -// -// http://www.fltk.org/str.php -// - -/** - * This code is a quick hack! It was written as a proof of concept. - * It has been tested on the "menubar" sample program and provides - * basic functionality. - * - * To use the System Menu Bar, simply replace the main Fl_Menu_Bar - * in an application with Fl_Sys_Menu_Bar. - * - * FLTK features not supported by the Mac System menu - * - * - no invisible menu items - * - no symbolic labels - * - embossed labels will be underlined instead - * - no font sizes - * - Shortcut Characters should be English alphanumeric only, no modifiers yet - * - no disable main menus - * - changes to menubar in run-time don't update! - * (disable, etc. - toggle and radio button do!) - * - * No care was taken to clean up the menu bar after destruction! - * ::menu(bar) should only be called once! - * Many other calls of the parent class don't work. - * Changing the menu items has no effect on the menu bar. - * Starting with OS X 10.5, FLTK applications must be created as - * a bundle for the System Menu Bar (and maybe other features) to work! - */ - -#if defined(__APPLE__) || defined(FL_DOXYGEN) - -#include <FL/x.H> -#include <FL/Fl.H> -#include <FL/Fl_Sys_Menu_Bar.H> - -#include "flstring.h" -#include <stdio.h> -#include <ctype.h> -#include <stdarg.h> - -#define MenuHandle void * - -typedef const Fl_Menu_Item *pFl_Menu_Item; - - -/* - * Set a shortcut for an Apple menu item using the FLTK shortcut descriptor. - */ -static void setMenuShortcut( MenuHandle mh, int miCnt, const Fl_Menu_Item *m ) -{ - if ( !m->shortcut_ ) - return; - if ( m->flags & FL_SUBMENU ) - return; - if ( m->flags & FL_SUBMENU_POINTER ) - return; - char key = m->shortcut_ & 0xff; - if ( !isalnum( key ) ) - return; - - void *menuItem = Fl_Sys_Menu_Bar::doMenuOrItemOperation(Fl_Sys_Menu_Bar::itemAtIndex, mh, miCnt); - Fl_Sys_Menu_Bar::doMenuOrItemOperation(Fl_Sys_Menu_Bar::setKeyEquivalent, menuItem, m->shortcut_ & 0xff ); - Fl_Sys_Menu_Bar::doMenuOrItemOperation(Fl_Sys_Menu_Bar::setKeyEquivalentModifierMask, menuItem, m->shortcut_ ); -} - - -/* - * Set the Toggle and Radio flag based on FLTK flags - */ -static void setMenuFlags( MenuHandle mh, int miCnt, const Fl_Menu_Item *m ) -{ - if ( m->flags & FL_MENU_TOGGLE ) - { - void *menuItem = Fl_Sys_Menu_Bar::doMenuOrItemOperation(Fl_Sys_Menu_Bar::itemAtIndex, mh, miCnt); - Fl_Sys_Menu_Bar::doMenuOrItemOperation(Fl_Sys_Menu_Bar::setState, menuItem, m->flags & FL_MENU_VALUE ); - } - else if ( m->flags & FL_MENU_RADIO ) { - void *menuItem = Fl_Sys_Menu_Bar::doMenuOrItemOperation(Fl_Sys_Menu_Bar::itemAtIndex, mh, miCnt); - Fl_Sys_Menu_Bar::doMenuOrItemOperation(Fl_Sys_Menu_Bar::setState, menuItem, m->flags & FL_MENU_VALUE ); - } -} - - -/* - * create a sub menu for a specific menu handle - */ -static void createSubMenu( void * mh, pFl_Menu_Item &mm, const Fl_Menu_Item *mitem) -{ - void *submenu; - int miCnt, flags; - - void *menuItem; - submenu = Fl_Sys_Menu_Bar::doMenuOrItemOperation(Fl_Sys_Menu_Bar::initWithTitle, mitem->text); - int cnt; - Fl_Sys_Menu_Bar::doMenuOrItemOperation(Fl_Sys_Menu_Bar::numberOfItems, mh, &cnt); - cnt--; - menuItem = Fl_Sys_Menu_Bar::doMenuOrItemOperation(Fl_Sys_Menu_Bar::itemAtIndex, mh, cnt); - Fl_Sys_Menu_Bar::doMenuOrItemOperation(Fl_Sys_Menu_Bar::setSubmenu, menuItem, submenu); - - while ( mm->text ) - { - char visible = mm->visible() ? 1 : 0; - Fl_Sys_Menu_Bar::doMenuOrItemOperation(Fl_Sys_Menu_Bar::addNewItem, submenu, mm, &miCnt); - setMenuFlags( submenu, miCnt, mm ); - setMenuShortcut( submenu, miCnt, mm ); - if ( mm->flags & FL_MENU_INACTIVE || mitem->flags & FL_MENU_INACTIVE) { - void *item = Fl_Sys_Menu_Bar::doMenuOrItemOperation(Fl_Sys_Menu_Bar::itemAtIndex, submenu, miCnt); - Fl_Sys_Menu_Bar::doMenuOrItemOperation(Fl_Sys_Menu_Bar::setEnabled, item, 0); - } - flags = mm->flags; - if ( mm->flags & FL_SUBMENU ) - { - mm++; - createSubMenu( submenu, mm, mm - 1 ); - } - else if ( mm->flags & FL_SUBMENU_POINTER ) - { - const Fl_Menu_Item *smm = (Fl_Menu_Item*)mm->user_data_; - createSubMenu( submenu, smm, mm ); - } - if ( flags & FL_MENU_DIVIDER ) { - Fl_Sys_Menu_Bar::doMenuOrItemOperation(Fl_Sys_Menu_Bar::addSeparatorItem, submenu); - } - if ( !visible ) { - Fl_Sys_Menu_Bar::doMenuOrItemOperation(Fl_Sys_Menu_Bar::removeItem, submenu, miCnt); - } - mm++; - } -} - - -/* - * convert a complete Fl_Menu_Item array into a series of menus in the top menu bar - * ALL PREVIOUS SYSTEM MENUS, EXCEPT THE APPLICATION MENU, ARE REPLACED BY THE NEW DATA - */ -static void convertToMenuBar(const Fl_Menu_Item *mm) -{ - int rank; - int count;//first, delete all existing system menus - Fl_Sys_Menu_Bar::doMenuOrItemOperation(Fl_Sys_Menu_Bar::numberOfItems, fl_system_menu, &count); - for(int i = count - 1; i > 0; i--) { - Fl_Sys_Menu_Bar::doMenuOrItemOperation(Fl_Sys_Menu_Bar::removeItem, fl_system_menu, i); - } - //now convert FLTK stuff into MacOS menus - for (;;) - { - if ( !mm || !mm->text ) - break; - char visible = mm->visible() ? 1 : 0; - Fl_Sys_Menu_Bar::doMenuOrItemOperation(Fl_Sys_Menu_Bar::addNewItem, fl_system_menu, mm, &rank); - - if ( mm->flags & FL_SUBMENU ) { - mm++; - createSubMenu( fl_system_menu, mm, mm - 1); - } - else if ( mm->flags & FL_SUBMENU_POINTER ) { - const Fl_Menu_Item *smm = (Fl_Menu_Item*)mm->user_data_; - createSubMenu( fl_system_menu, smm, mm); - } - if ( !visible ) { - Fl_Sys_Menu_Bar::doMenuOrItemOperation(Fl_Sys_Menu_Bar::removeItem, fl_system_menu, rank); - } - mm++; - } -} - - -/** - * @brief create a system menu bar using the given list of menu structs - * - * \author Matthias Melcher - * - * @param m list of Fl_Menu_Item - */ -void Fl_Sys_Menu_Bar::menu(const Fl_Menu_Item *m) -{ - fl_open_display(); - Fl_Menu_Bar::menu( m ); - convertToMenuBar(m); -} - - -/** - * @brief add to the system menu bar a new menu item - * - * add to the system menu bar a new menu item, with a title string, shortcut int, - * callback, argument to the callback, and flags. - * - * @see Fl_Menu_::add(const char* label, int shortcut, Fl_Callback *cb, void *user_data, int flags) - */ -int Fl_Sys_Menu_Bar::add(const char* label, int shortcut, Fl_Callback *cb, void *user_data, int flags) -{ - fl_open_display(); - int rank = Fl_Menu_::add(label, shortcut, cb, user_data, flags); - convertToMenuBar(Fl_Menu_::menu()); - return rank; -} - -/** - * @brief insert in the system menu bar a new menu item - * - * insert in the system menu bar a new menu item, with a title string, shortcut int, - * callback, argument to the callback, and flags. - * - * @see Fl_Menu_::insert(int index, const char* label, int shortcut, Fl_Callback *cb, void *user_data, int flags) - */ -int Fl_Sys_Menu_Bar::insert(int index, const char* label, int shortcut, Fl_Callback *cb, void *user_data, int flags) -{ - fl_open_display(); - int rank = Fl_Menu_::insert(index, label, shortcut, cb, user_data, flags); - convertToMenuBar(Fl_Menu_::menu()); - return rank; -} - -void Fl_Sys_Menu_Bar::clear() -{ - Fl_Menu_::clear(); - convertToMenuBar(NULL); -} - -int Fl_Sys_Menu_Bar::clear_submenu(int index) -{ - int retval = Fl_Menu_::clear_submenu(index); - if (retval != -1) convertToMenuBar(Fl_Menu_::menu()); - return retval; -} - -/** - * @brief remove an item from the system menu bar - * - * @param rank the rank of the item to remove - */ -void Fl_Sys_Menu_Bar::remove(int rank) -{ - Fl_Menu_::remove(rank); - convertToMenuBar(Fl_Menu_::menu()); -} - - -/** - * @brief rename an item from the system menu bar - * - * @param rank the rank of the item to rename - * @param name the new item name as a UTF8 string - */ -void Fl_Sys_Menu_Bar::replace(int rank, const char *name) -{ - Fl_Menu_::replace(rank, name); - convertToMenuBar(Fl_Menu_::menu()); -} - - -/* - * Draw the menu bar. - * Nothing here because the OS does this for us. - */ -void Fl_Sys_Menu_Bar::draw() { -} - - -Fl_Sys_Menu_Bar::Fl_Sys_Menu_Bar(int x,int y,int w,int h,const char *l) -: Fl_Menu_Bar(x,y,w,h,l) -{ - deactivate(); // don't let the old area take events - fl_sys_menu_bar = this; -} - - -#endif /* __APPLE__ */ - -// -// End of "$Id: Fl_Sys_Menu_Bar.cxx 9637 2012-07-24 04:37:22Z matt $". -// diff --git a/src/Fl_Sys_Menu_Bar.mm b/src/Fl_Sys_Menu_Bar.mm new file mode 100644 index 0000000..0b62fa5 --- /dev/null +++ b/src/Fl_Sys_Menu_Bar.mm @@ -0,0 +1,508 @@ +// +// "$Id: Fl_Sys_Menu_Bar.mm 10106 2014-02-19 16:02:56Z manolo $" +// +// MacOS system menu bar widget for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2013 by Bill Spitzak and others. +// +// This library is free software. Distribution and use rights are outlined in +// the file "COPYING" which should have been included with this file. If this +// file is missing or damaged, see the license at: +// +// http://www.fltk.org/COPYING.php +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// + +/* + * This code has been tested on the "menubar" sample program and provides + * basic functionality. + * + * To use the System Menu Bar, simply replace the main Fl_Menu_Bar + * in an application with Fl_Sys_Menu_Bar. + * + * FLTK features not supported by the Mac System menu + * + * - no symbolic labels + * - no embossed labels + * - no font sizes + * + * Many other calls of the parent class don't work. + */ + +#if defined(__APPLE__) || defined(FL_DOXYGEN) +#include <FL/Fl_Menu_Item.H> +#include <FL/Fl_Sys_Menu_Bar.H> +#include <FL/x.H> +#include <FL/Fl.H> + +#import <Cocoa/Cocoa.h> + +#ifndef NSINTEGER_DEFINED // appears with 10.5 in NSObjCRuntime.h +#if defined(__LP64__) && __LP64__ +typedef long NSInteger; +typedef unsigned long NSUInteger; +#else +typedef long NSInteger; +typedef unsigned int NSUInteger; +#endif +#endif + +#include "flstring.h" +#include <stdio.h> +#include <ctype.h> +#include <stdarg.h> + +typedef const Fl_Menu_Item *pFl_Menu_Item; + +Fl_Sys_Menu_Bar *fl_sys_menu_bar = 0; + +static char *remove_ampersand(const char *s); +extern void (*fl_lock_function)(); +extern void (*fl_unlock_function)(); + +/* Each MacOS system menu item contains a pointer to a record of type sys_menu_item defined below. + The purpose of these records is to associate each MacOS system menu item with a relevant Fl_Menu_Item. + If use_rank is YES, the "rank" field is used, and fl_sys_menu_bar->menu() + rank is the address + of the relevant Fl_Menu_Item; + Otherwise, the "item" field points to the relevant Fl_Menu_Item. + This allows the MacOS system menu to use the same Fl_Menu_Item's as those used by FLTK menus, + the address of which can be relocated by the FLTK menu logic. + The "item" field is used for non-relocatable Fl_Menu_Item's associated to FL_SUBMENU_POINTER. + Sending the getFlItem message to a MacOS system menu item (of class FLMenuItem) returns the address + of the relevant Fl_Menu_Item. +*/ +typedef struct { + union { + int rank; + const Fl_Menu_Item *item; + }; + BOOL use_rank; +} sys_menu_item; + + +@interface FLMenuItem : NSMenuItem { +} +- (void) doCallback:(id)unused; +- (void) directCallback:(id)unused; +- (const Fl_Menu_Item*) getFlItem; +- (void) setKeyEquivalentModifierMask:(int)value; +- (void) setFltkShortcut:(int)key; ++ (int) addNewItem:(const Fl_Menu_Item*)mitem menu:(NSMenu*)menu; +@end + +@implementation FLMenuItem +- (const Fl_Menu_Item*) getFlItem +// returns the Fl_Menu_Item corresponding to this system menu item +{ + sys_menu_item *smi = (sys_menu_item*)[(NSData*)[self representedObject] bytes]; + if (smi->use_rank) return fl_sys_menu_bar->menu() + smi->rank; + return smi->item; +} +- (void) doCallback:(id)unused +{ + fl_lock_function(); + const Fl_Menu_Item *item = [self getFlItem]; + fl_sys_menu_bar->picked(item); + if ( item->flags & FL_MENU_TOGGLE ) { // update the menu toggle symbol + [self setState:(item->value() ? NSOnState : NSOffState)]; + } + else if ( item->flags & FL_MENU_RADIO ) { // update the menu radio symbols + NSMenu* menu = [self menu]; + NSInteger flRank = [menu indexOfItem:self]; + NSInteger last = [menu numberOfItems] - 1; + int from = flRank; + while(from > 0) { + if ([[menu itemAtIndex:from-1] isSeparatorItem]) break; + item = [(FLMenuItem*)[menu itemAtIndex:from-1] getFlItem]; + if ( !(item->flags & FL_MENU_RADIO) ) break; + from--; + } + int to = flRank; + while (to < last) { + if ([[menu itemAtIndex:to+1] isSeparatorItem]) break; + item = [(FLMenuItem*)[menu itemAtIndex:to+1] getFlItem]; + if (!(item->flags & FL_MENU_RADIO)) break; + to++; + } + for(int i = from; i <= to; i++) { + NSMenuItem *nsitem = [menu itemAtIndex:i]; + [nsitem setState:(nsitem != self ? NSOffState : NSOnState)]; + } + } + fl_unlock_function(); +} +- (void) directCallback:(id)unused +{ + fl_lock_function(); + Fl_Menu_Item *item = (Fl_Menu_Item *)[(NSData*)[self representedObject] bytes]; + if ( item && item->callback() ) item->do_callback(NULL); + fl_unlock_function(); +} +- (void) setKeyEquivalentModifierMask:(int)value +{ + NSUInteger macMod = 0; + if ( value & FL_META ) macMod = NSCommandKeyMask; + if ( value & FL_SHIFT || isupper(value) ) macMod |= NSShiftKeyMask; + if ( value & FL_ALT ) macMod |= NSAlternateKeyMask; + if ( value & FL_CTRL ) macMod |= NSControlKeyMask; + [super setKeyEquivalentModifierMask:macMod]; +} +- (void) setFltkShortcut:(int)key +{ + // Separate key and modifier + int mod = key; + mod &= ~FL_KEY_MASK; // modifier(s) + key &= FL_KEY_MASK; // key + unichar mac_key = (unichar)key; + if ( (key >= (FL_F+1)) && (key <= FL_F_Last) ) { // Handle function keys + int fkey_num = (key - FL_F); // 1,2.. + mac_key = NSF1FunctionKey + fkey_num - 1; + } + [self setKeyEquivalent:[NSString stringWithCharacters:&mac_key length:1]]; + [self setKeyEquivalentModifierMask:mod]; +} ++ (int) addNewItem:(const Fl_Menu_Item*)mitem menu:(NSMenu*)menu +{ + char *name = remove_ampersand(mitem->label()); + CFStringRef cfname = CFStringCreateWithCString(NULL, name, kCFStringEncodingUTF8); + free(name); + FLMenuItem *item = [[FLMenuItem alloc] initWithTitle:(NSString*)cfname + action:@selector(doCallback:) + keyEquivalent:@""]; + sys_menu_item smi; + smi.rank = fl_sys_menu_bar->find_index(mitem); // ≥ 0 if mitem is in the menu items of fl_sys_menu_bar, -1 if not + smi.use_rank = (smi.rank >= 0); + if (!smi.use_rank) smi.item = mitem; + NSData *pointer = [NSData dataWithBytes:&smi length:sizeof(smi)]; + [item setRepresentedObject:pointer]; + [menu addItem:item]; + CFRelease(cfname); + [item setTarget:item]; + int retval = [menu indexOfItem:item]; + [item release]; + return retval; +} +@end + + +void fl_mac_set_about( Fl_Callback *cb, void *user_data, int shortcut) +{ + fl_open_display(); + Fl_Menu_Item aboutItem; + memset(&aboutItem, 0, sizeof(Fl_Menu_Item)); + aboutItem.callback(cb); + aboutItem.user_data(user_data); + aboutItem.shortcut(shortcut); + NSMenu *appleMenu = [[[NSApp mainMenu] itemAtIndex:0] submenu]; + CFStringRef cfname = CFStringCreateCopy(NULL, (CFStringRef)[[appleMenu itemAtIndex:0] title]); + [appleMenu removeItemAtIndex:0]; + FLMenuItem *item = [[[FLMenuItem alloc] initWithTitle:(NSString*)cfname + action:@selector(directCallback:) + keyEquivalent:@""] autorelease]; + if (aboutItem.shortcut()) + [item setFltkShortcut:aboutItem.shortcut()]; + NSData *pointer = [NSData dataWithBytes:&aboutItem length:sizeof(Fl_Menu_Item)]; + [item setRepresentedObject:pointer]; + [appleMenu insertItem:item atIndex:0]; + CFRelease(cfname); + [item setTarget:item]; +} + +/* + * Set a shortcut for an Apple menu item using the FLTK shortcut descriptor. + */ +static void setMenuShortcut( NSMenu* mh, int miCnt, const Fl_Menu_Item *m ) +{ + if ( !m->shortcut_ ) + return; + if ( m->flags & FL_SUBMENU ) + return; + if ( m->flags & FL_SUBMENU_POINTER ) + return; + FLMenuItem* menuItem = (FLMenuItem*)[mh itemAtIndex:miCnt]; + [menuItem setFltkShortcut:(m->shortcut_)]; +} + + +/* + * Set the Toggle and Radio flag based on FLTK flags + */ +static void setMenuFlags( NSMenu* mh, int miCnt, const Fl_Menu_Item *m ) +{ + if ( m->flags & FL_MENU_TOGGLE ) + { + NSMenuItem *menuItem = [mh itemAtIndex:miCnt]; + [menuItem setState:(m->flags & FL_MENU_VALUE ? NSOnState : NSOffState)]; + } + else if ( m->flags & FL_MENU_RADIO ) { + NSMenuItem *menuItem = [mh itemAtIndex:miCnt]; + [menuItem setState:(m->flags & FL_MENU_VALUE ? NSOnState : NSOffState)]; + } +} + +static char *remove_ampersand(const char *s) +{ + char *ret = strdup(s); + const char *p = s; + char *q = ret; + while(*p != 0) { + if (p[0]=='&') { + if (p[1]=='&') { + *q++ = '&'; p+=2; + } else { + p++; + } + } else { + *q++ = *p++; + } + } + *q = 0; + return ret; +} + + +/* + * create a sub menu for a specific menu handle + */ +static void createSubMenu( NSMenu *mh, pFl_Menu_Item &mm, const Fl_Menu_Item *mitem) +{ + NSMenu *submenu; + int miCnt, flags; + + NSMenuItem *menuItem; + char *ts = remove_ampersand(mitem->text); + CFStringRef title = CFStringCreateWithCString(NULL, ts, kCFStringEncodingUTF8); + free(ts); + submenu = [[NSMenu alloc] initWithTitle:(NSString*)title]; + CFRelease(title); + [submenu setAutoenablesItems:NO]; + + int cnt; + cnt = [mh numberOfItems]; + cnt--; + menuItem = [mh itemAtIndex:cnt]; + [menuItem setSubmenu:submenu]; + [submenu release]; + + while ( mm->text ) + { + if (!mm->visible() ) { // skip invisible items and submenus + mm = mm->next(0); + continue; + } + miCnt = [FLMenuItem addNewItem:mm menu:submenu]; + setMenuFlags( submenu, miCnt, mm ); + setMenuShortcut( submenu, miCnt, mm ); + if ( mm->flags & FL_MENU_INACTIVE || mitem->flags & FL_MENU_INACTIVE) { + NSMenuItem *item = [submenu itemAtIndex:miCnt]; + [item setEnabled:NO]; + } + flags = mm->flags; + if ( mm->flags & FL_SUBMENU ) + { + mm++; + createSubMenu( submenu, mm, mm - 1 ); + } + else if ( mm->flags & FL_SUBMENU_POINTER ) + { + const Fl_Menu_Item *smm = (Fl_Menu_Item*)mm->user_data_; + createSubMenu( submenu, smm, mm); + } + if ( flags & FL_MENU_DIVIDER ) { + [submenu addItem:[NSMenuItem separatorItem]]; + } + mm++; + } +} + + +/* + * convert a complete Fl_Menu_Item array into a series of menus in the top menu bar + * ALL PREVIOUS SYSTEM MENUS, EXCEPT THE APPLICATION MENU, ARE REPLACED BY THE NEW DATA + */ +static void convertToMenuBar(const Fl_Menu_Item *mm) +{ + NSMenu *fl_system_menu = [NSApp mainMenu]; + int rank; + int count;//first, delete all existing system menus + count = [fl_system_menu numberOfItems]; + for(int i = count - 1; i > 0; i--) { + [fl_system_menu removeItem:[fl_system_menu itemAtIndex:i]]; + } + //now convert FLTK stuff into MacOS menus + for (;;) + { + if ( !mm || !mm->text ) + break; + if (!mm->visible() ) { // skip invisible menus + mm = mm->next(0); + continue; + } + rank = [FLMenuItem addNewItem:mm menu:fl_system_menu]; + + if ( mm->flags & FL_SUBMENU ) { + mm++; + createSubMenu(fl_system_menu, mm, mm - 1); + } + else if ( mm->flags & FL_SUBMENU_POINTER ) { + const Fl_Menu_Item *smm = (Fl_Menu_Item*)mm->user_data_; + createSubMenu(fl_system_menu, smm, mm); + } + mm++; + } +} + + +/** + * @brief create a system menu bar using the given list of menu structs + * + * \author Matthias Melcher + * + * @param m list of Fl_Menu_Item + */ +void Fl_Sys_Menu_Bar::menu(const Fl_Menu_Item *m) +{ + fl_open_display(); + Fl_Menu_Bar::menu( m ); + convertToMenuBar(m); +} + + +/** + * @brief add to the system menu bar a new menu item + * + * add to the system menu bar a new menu item, with a title string, shortcut int, + * callback, argument to the callback, and flags. + * + * @see Fl_Menu_::add(const char* label, int shortcut, Fl_Callback *cb, void *user_data, int flags) + */ +int Fl_Sys_Menu_Bar::add(const char* label, int shortcut, Fl_Callback *cb, void *user_data, int flags) +{ + fl_open_display(); + int rank = Fl_Menu_::add(label, shortcut, cb, user_data, flags); + update(); + return rank; +} + +/** + * Forms-compatible procedure to add items to the system menu bar +* + * @see Fl_Menu_::add(const char* str) + */ +int Fl_Sys_Menu_Bar::add(const char* str) +{ + fl_open_display(); + int rank = Fl_Menu_::add(str); + update(); + return rank; +} + +/** + * @brief insert in the system menu bar a new menu item + * + * insert in the system menu bar a new menu item, with a title string, shortcut int, + * callback, argument to the callback, and flags. + * + * @see Fl_Menu_::insert(int index, const char* label, int shortcut, Fl_Callback *cb, void *user_data, int flags) + */ +int Fl_Sys_Menu_Bar::insert(int index, const char* label, int shortcut, Fl_Callback *cb, void *user_data, int flags) +{ + fl_open_display(); + int rank = Fl_Menu_::insert(index, label, shortcut, cb, user_data, flags); + update(); + return rank; +} + +void Fl_Sys_Menu_Bar::clear() +{ + Fl_Menu_::clear(); + convertToMenuBar(NULL); +} + +int Fl_Sys_Menu_Bar::clear_submenu(int index) +{ + int retval = Fl_Menu_::clear_submenu(index); + if (retval != -1) update(); + return retval; +} + +/** + * @brief remove an item from the system menu bar + * + * @param rank the rank of the item to remove + */ +void Fl_Sys_Menu_Bar::remove(int rank) +{ + Fl_Menu_::remove(rank); + update(); +} + + +/** + * @brief rename an item from the system menu bar + * + * @param rank the rank of the item to rename + * @param name the new item name as a UTF8 string + */ +void Fl_Sys_Menu_Bar::replace(int rank, const char *name) +{ + Fl_Menu_::replace(rank, name); + update(); +} + +/** Updates the system menu after any change to its items. + */ +void Fl_Sys_Menu_Bar::update() +{ + convertToMenuBar(Fl_Menu_::menu()); +} + +/* + * Draw the menu bar. + * Nothing here because the OS does this for us. + */ +void Fl_Sys_Menu_Bar::draw() { +} + +static int process_sys_menu_shortcuts(int event) +{ + if (event != FL_SHORTCUT || !fl_sys_menu_bar || Fl::modal()) return 0; + // is the last event the shortcut of an item of the fl_sys_menu_bar menu ? + const Fl_Menu_Item *item = fl_sys_menu_bar->menu()->test_shortcut(); + if (!item) return 0; + if (item->visible()) // have the system menu process the shortcut, highlighting the corresponding menu + [[NSApp mainMenu] performKeyEquivalent:[NSApp currentEvent]]; + else // have FLTK process the shortcut associated to an invisible Fl_Menu_Item + fl_sys_menu_bar->picked(item); + return 1; +} + + +/** + The constructor. + On Mac OS X, all arguments are unused. On other platforms they are used as by Fl_Menu_Bar::Fl_Menu_Bar(). + */ +Fl_Sys_Menu_Bar::Fl_Sys_Menu_Bar(int x,int y,int w,int h,const char *l) +: Fl_Menu_Bar(x,y,w,h,l) +{ + deactivate(); // don't let the old area take events + fl_sys_menu_bar = this; + Fl::add_handler(process_sys_menu_shortcuts); +} + +/** The destructor */ +Fl_Sys_Menu_Bar::~Fl_Sys_Menu_Bar() +{ + fl_sys_menu_bar = 0; + clear(); + Fl::remove_handler(process_sys_menu_shortcuts); +} + +#endif /* __APPLE__ */ + +// +// End of "$Id: Fl_Sys_Menu_Bar.mm 10106 2014-02-19 16:02:56Z manolo $". +// diff --git a/src/Fl_Table.cxx b/src/Fl_Table.cxx index 98b67bd..7e42b2e 100644 --- a/src/Fl_Table.cxx +++ b/src/Fl_Table.cxx @@ -1,5 +1,5 @@ // -// "$Id: Fl_Table.cxx 9706 2012-11-06 20:46:14Z matt $" +// "$Id: Fl_Table.cxx 10225 2014-08-03 16:40:58Z greg.ercolano $" // // Fl_Table -- A table widget // @@ -131,6 +131,9 @@ Fl_Table::Fl_Table(int X, int Y, int W, int H, const char *l) : Fl_Group(X,Y,W,H #if FLTK_ABI_VERSION >= 10301 _scrollbar_size = 0; #endif +#if FLTK_ABI_VERSION >= 10303 + flags_ = 0; // TABCELLNAV off +#endif box(FL_THIN_DOWN_FRAME); vscrollbar = new Fl_Scrollbar(x()+w()-Fl::scrollbar_size(), y(), @@ -196,7 +199,7 @@ void Fl_Table::col_width(int col, int width) // Add column widths, even if none yet int now_size = (int)_colwidths.size(); if ( col >= now_size ) { - _colwidths.size(col); + _colwidths.size(col+1); while (now_size < col) { _colwidths[now_size++] = width; } @@ -674,7 +677,7 @@ void Fl_Table::damage_zone(int r1, int c1, int r2, int c2, int r3, int c3) { redraw_range(R1, R2, C1, C2); } -int Fl_Table::move_cursor(int R, int C) { +int Fl_Table::move_cursor(int R, int C, int shiftselect) { if (select_row == -1) R++; if (select_col == -1) C++; R += select_row; @@ -687,7 +690,7 @@ int Fl_Table::move_cursor(int R, int C) { damage_zone(current_row, current_col, select_row, select_col, R, C); select_row = R; select_col = C; - if (!Fl::event_state(FL_SHIFT)) { + if (!shiftselect || !Fl::event_state(FL_SHIFT)) { current_row = R; current_col = C; } @@ -696,7 +699,11 @@ int Fl_Table::move_cursor(int R, int C) { return 1; } -// #define DEBUG 1 +int Fl_Table::move_cursor(int R, int C) { + return move_cursor(R,C,1); +} + +//#define DEBUG 1 #ifdef DEBUG #include <FL/names.h> #define PRINTEVENT \ @@ -729,7 +736,9 @@ int Fl_Table::handle(int event) { int _event_x = Fl::event_x(); int _event_y = Fl::event_y(); int _event_key = Fl::event_key(); +#if FLTK_ABI_VERSION >= 10303 int _event_state = Fl::event_state(); +#endif Fl_Widget *_focus = Fl::focus(); switch ( event ) { case FL_PUSH: @@ -746,8 +755,11 @@ int Fl_Table::handle(int event) { current_col = select_col = C; _selecting = CONTEXT_CELL; } else { - current_row = select_row = -1; - current_col = select_col = -1; + // Clear selection if not resizing row/col + if ( !resizeflag ) { + current_row = select_row = -1; + current_col = select_col = -1; + } } } // A click on table with user's callback defined? @@ -796,6 +808,7 @@ int Fl_Table::handle(int event) { ret = 1; } else { // Not resizing? Select the column + if ( Fl::focus() != this && contains(Fl::focus()) ) return 0; // STR #3018 - item 1 current_col = select_col = C; current_row = 0; select_row = rows() - 1; @@ -822,6 +835,7 @@ int Fl_Table::handle(int event) { ret = 1; } else { // Not resizing? Select the row + if ( Fl::focus() != this && contains(Fl::focus()) ) return 0; // STR #3018 - item 1 current_row = select_row = R; current_col = 0; select_col = cols() - 1; @@ -887,6 +901,8 @@ int Fl_Table::handle(int event) { if (_event_button == 1 && _selecting == CONTEXT_CELL && context == CONTEXT_CELL) { + // Dragging a cell selection? + if ( _event_clicks ) break; // STR #3018 - item 2 if (select_row != R || select_col != C) { damage_zone(current_row, current_col, select_row, select_col, R, C); } @@ -1020,12 +1036,17 @@ int Fl_Table::handle(int event) { ret = move_cursor(1, 0); break; case FL_Tab: +#if FLTK_ABI_VERSION >= 10303 + if ( !tab_cell_nav() ) break; // not navigating cells? let fltk handle it (STR#2862) if ( _event_state & FL_SHIFT ) { - ret = move_cursor(0, -1); // shift-tab -> left + ret = move_cursor(0, -1, 0); // shift-tab -> left } else { - ret = move_cursor(0, 1); // tab -> right + ret = move_cursor(0, 1, 0); // tab -> right } break; +#else + break; // without tab_cell_nav(), Fl_Table should default to navigating widgets, not cells +#endif } if (ret && Fl::focus() != this) { do_callback(CONTEXT_TABLE, -1, -1); @@ -1293,5 +1314,5 @@ void Fl_Table::draw() { } // -// End of "$Id: Fl_Table.cxx 9706 2012-11-06 20:46:14Z matt $". +// End of "$Id: Fl_Table.cxx 10225 2014-08-03 16:40:58Z greg.ercolano $". // diff --git a/src/Fl_Tabs.cxx b/src/Fl_Tabs.cxx index 8302afb..75d4458 100644 --- a/src/Fl_Tabs.cxx +++ b/src/Fl_Tabs.cxx @@ -1,5 +1,5 @@ // -// "$Id: Fl_Tabs.cxx 8864 2011-07-19 04:49:30Z greg.ercolano $" +// "$Id: Fl_Tabs.cxx 10122 2014-03-24 18:24:59Z greg.ercolano $" // // Tab widget for the Fast Light Tool Kit (FLTK). // @@ -114,8 +114,13 @@ int Fl_Tabs::tab_height() { else return (H <= 0) ? 0 : H; } -// This is used for event handling (clicks) and by fluid to pick tabs. -// Returns 0, if children() = 0, or if the event is outside of the tabs area. +/** + Return the widget of the tab the user clicked on at \p event_x / \p event_y. + This is used for event handling (clicks) and by fluid to pick tabs. + + \returns The child widget of the tab the user clicked on, or<br> + 0 if there are no children or if the event is outside of the tabs area. +*/ Fl_Widget *Fl_Tabs::which(int event_x, int event_y) { if (children() == 0) return 0; int H = tab_height(); @@ -173,7 +178,11 @@ int Fl_Tabs::handle(int event) { Fl::focus(this); redraw_tabs(); } - if (o && value(o)) { + if (o && // Released on a tab and.. + (value(o) || // tab changed value or.. + (when()&(FL_WHEN_NOT_CHANGED)) // ..no change but WHEN_NOT_CHANGED set, + ) // handles FL_WHEN_RELEASE_ALWAYS too. + ) { Fl_Widget_Tracker wp(o); set_changed(); do_callback(); @@ -257,6 +266,17 @@ int Fl_Tabs::handle(int event) { } } +/** + This is called by the tab widget's handle() method to set the + tab group widget the user last FL_PUSH'ed on. Set back to zero + on FL_RELEASE. + + As of this writing, the value is mainly used by draw_tab() + to determine whether or not to draw a 'down' box for the tab + when it's clicked, and to turn it off if the user drags off it. + + \see push(). +*/ int Fl_Tabs::push(Fl_Widget *o) { if (push_ == o) return 0; if ( (push_ && !push_->visible()) || (o && !o->visible()) ) @@ -288,6 +308,8 @@ Fl_Widget* Fl_Tabs::value() { Sets the widget to become the current visible widget/tab. Setting the value hides all other children, and makes this one visible, if it is really a child. + \returns 1 if there was a change (new value different from previous),<BR> + 0 if there was no change (new value already set) */ int Fl_Tabs::value(Fl_Widget *newvalue) { Fl_Widget*const* a = array(); @@ -518,5 +540,5 @@ void Fl_Tabs::clear_tab_positions() { } // -// End of "$Id: Fl_Tabs.cxx 8864 2011-07-19 04:49:30Z greg.ercolano $". +// End of "$Id: Fl_Tabs.cxx 10122 2014-03-24 18:24:59Z greg.ercolano $". // diff --git a/src/Fl_Text_Buffer.cxx b/src/Fl_Text_Buffer.cxx index e7c9e99..d4350d8 100644 --- a/src/Fl_Text_Buffer.cxx +++ b/src/Fl_Text_Buffer.cxx @@ -1,5 +1,5 @@ // -// "$Id: Fl_Text_Buffer.cxx 9366 2012-04-21 15:05:00Z fabien $" +// "$Id: Fl_Text_Buffer.cxx 10083 2014-01-25 23:47:44Z AlbrechtS $" // // Copyright 2001-2010 by Bill Spitzak and others. // Original code Copyright Mark Edel. Permission to distribute under @@ -139,9 +139,9 @@ Fl_Text_Buffer::~Fl_Text_Buffer() delete[]mModifyProcs; delete[]mCbArgs; } - if (mNPredeleteProcs != 0) { - delete[]mPredeleteProcs; - delete[]mPredeleteCbArgs; + if (mNPredeleteProcs > 0) { + delete[] mPredeleteProcs; + delete[] mPredeleteCbArgs; } } @@ -735,9 +735,9 @@ void Fl_Text_Buffer::add_predelete_callback(Fl_Text_Predelete_Cb bufPreDeleteCB, newPreDeleteProcs[i + 1] = mPredeleteProcs[i]; newCBArgs[i + 1] = mPredeleteCbArgs[i]; } - if (!mNPredeleteProcs != 0) { - delete[]mPredeleteProcs; - delete[]mPredeleteCbArgs; + if (mNPredeleteProcs > 0) { + delete[] mPredeleteProcs; + delete[] mPredeleteCbArgs; } newPreDeleteProcs[0] = bufPreDeleteCB; newCBArgs[0] = cbArg; @@ -767,19 +767,16 @@ void Fl_Text_Buffer::remove_predelete_callback(Fl_Text_Predelete_Cb bufPreDelete return; } - /* Allocate new lists for remaining callback procs and args (if - any are left) */ + /* Allocate new lists for remaining callback procs and args (if any are left) */ mNPredeleteProcs--; if (mNPredeleteProcs == 0) { - mNPredeleteProcs = 0; delete[]mPredeleteProcs; mPredeleteProcs = NULL; delete[]mPredeleteCbArgs; mPredeleteCbArgs = NULL; return; } - Fl_Text_Predelete_Cb *newPreDeleteProcs = - new Fl_Text_Predelete_Cb[mNPredeleteProcs]; + Fl_Text_Predelete_Cb *newPreDeleteProcs = new Fl_Text_Predelete_Cb[mNPredeleteProcs]; void **newCBArgs = new void *[mNPredeleteProcs]; /* copy out the remaining members and free the old lists */ @@ -791,8 +788,8 @@ void Fl_Text_Buffer::remove_predelete_callback(Fl_Text_Predelete_Cb bufPreDelete newPreDeleteProcs[i] = mPredeleteProcs[i + 1]; newCBArgs[i] = mPredeleteCbArgs[i + 1]; } - delete[]mPredeleteProcs; - delete[]mPredeleteCbArgs; + delete[] mPredeleteProcs; + delete[] mPredeleteCbArgs; mPredeleteProcs = newPreDeleteProcs; mPredeleteCbArgs = newCBArgs; } @@ -1805,5 +1802,5 @@ int Fl_Text_Buffer::utf8_align(int pos) const } // -// End of "$Id: Fl_Text_Buffer.cxx 9366 2012-04-21 15:05:00Z fabien $". +// End of "$Id: Fl_Text_Buffer.cxx 10083 2014-01-25 23:47:44Z AlbrechtS $". // diff --git a/src/Fl_Text_Display.cxx b/src/Fl_Text_Display.cxx index d418df7..0255fe8 100644 --- a/src/Fl_Text_Display.cxx +++ b/src/Fl_Text_Display.cxx @@ -1,12 +1,12 @@ // -// "$Id: Fl_Text_Display.cxx 9362 2012-04-21 03:02:25Z fabien $" +// "$Id: Fl_Text_Display.cxx 10416 2014-10-30 12:35:36Z AlbrechtS $" // -// Copyright 2001-2010 by Bill Spitzak and others. +// Copyright 2001-2014 by Bill Spitzak and others. // Original code Copyright Mark Edel. Permission to distribute under // the LGPL for the FLTK library granted by Mark Edel. // // This library is free software. Distribution and use rights are outlined in -// the file "COPYING" which should have been included with this file. If this +// the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // http://www.fltk.org/COPYING.php @@ -17,7 +17,7 @@ // // TODO: rendering of the "optional hyphen" -// TODO: make line numbering work again +// TODO: font background color control via style buffer #include <stdio.h> #include <stdlib.h> @@ -25,6 +25,7 @@ #include "flstring.h" #include <limits.h> #include <ctype.h> +#include <string.h> // strdup() #include <FL/Fl.H> #include <FL/Fl_Text_Buffer.H> #include <FL/Fl_Text_Display.H> @@ -152,6 +153,14 @@ Fl_Text_Display::Fl_Text_Display(int X, int Y, int W, int H, const char* l) mContinuousWrap = 0; mWrapMarginPix = 0; mSuppressResync = mNLinesDeleted = mModifyingTabDistance = 0; +#if FLTK_ABI_VERSION >= 10303 + linenumber_font_ = FL_HELVETICA; + linenumber_size_ = FL_NORMAL_SIZE; + linenumber_fgcolor_ = FL_INACTIVE_COLOR; + linenumber_bgcolor_ = 53; // ~90% gray + linenumber_align_ = FL_ALIGN_RIGHT; + linenumber_format_ = strdup("%d"); +#endif } @@ -172,9 +181,189 @@ Fl_Text_Display::~Fl_Text_Display() { mBuffer->remove_predelete_callback(buffer_predelete_cb, this); } if (mLineStarts) delete[] mLineStarts; +#if FLTK_ABI_VERSION >= 10303 + if (linenumber_format_) { + free((void*)linenumber_format_); + linenumber_format_ = 0; + } +#endif +} + + +/** + Set width of screen area for line numbers. + Use to also enable/disable line numbers. + A value of 0 disables line numbering, values >0 enables them. + \param width The new width of the area for line numbers to appear, in pixels. + 0 disables line numbers (default) +*/ +void Fl_Text_Display::linenumber_width(int width) { + if (width < 0) return; + mLineNumWidth = width; + resize(x(), y(), w(), h()); // triggers code to recalculate line#s +} + +/** + Return the screen area width provided for line numbers. +*/ +int Fl_Text_Display::linenumber_width() const { + return mLineNumWidth; +} + +/** + Set the font used for line numbers (if enabled). + \version 1.3.3 ABI feature (ignored in 1.3.x unless FLTK_ABI_VERSION is 10303 or higher) +*/ +void Fl_Text_Display::linenumber_font(Fl_Font val) { +#if FLTK_ABI_VERSION >= 10303 + linenumber_font_ = val; +#else + // do nothing +#endif +} + +/** + Return the font used for line numbers (if enabled). +*/ +Fl_Font Fl_Text_Display::linenumber_font() const { +#if FLTK_ABI_VERSION >= 10303 + return linenumber_font_; +#else + return FL_HELVETICA; +#endif +} + +/** + Set the font size used for line numbers (if enabled). + \version 1.3.3 ABI feature (ignored in 1.3.x unless FLTK_ABI_VERSION is 10303 or higher) +*/ +void Fl_Text_Display::linenumber_size(Fl_Fontsize val) { +#if FLTK_ABI_VERSION >= 10303 + linenumber_size_ = val; +#else + // do nothing +#endif +} + +/** + Return the font size used for line numbers (if enabled). +*/ +Fl_Fontsize Fl_Text_Display::linenumber_size() const { +#if FLTK_ABI_VERSION >= 10303 + return linenumber_size_; +#else + return FL_NORMAL_SIZE; +#endif +} + +/** + Set the foreground color used for line numbers (if enabled). + \version 1.3.3 ABI feature (ignored in 1.3.x unless FLTK_ABI_VERSION is 10303 or higher) +*/ +void Fl_Text_Display::linenumber_fgcolor(Fl_Color val) { +#if FLTK_ABI_VERSION >= 10303 + linenumber_fgcolor_ = val; +#else + // do nothing +#endif +} + +/** + Return the foreground color used for line numbers (if enabled). +*/ +Fl_Color Fl_Text_Display::linenumber_fgcolor() const { +#if FLTK_ABI_VERSION >= 10303 + return linenumber_fgcolor_; +#else + return FL_INACTIVE_COLOR; +#endif } +/** + Set the background color used for line numbers (if enabled). + \version 1.3.3 ABI feature (ignored in 1.3.x unless FLTK_ABI_VERSION is 10303 or higher) +*/ +void Fl_Text_Display::linenumber_bgcolor(Fl_Color val) { +#if FLTK_ABI_VERSION >= 10303 + linenumber_bgcolor_ = val; +#else + // do nothing +#endif +} +/** + Returns the background color used for line numbers (if enabled). +*/ +Fl_Color Fl_Text_Display::linenumber_bgcolor() const { +#if FLTK_ABI_VERSION >= 10303 + return linenumber_bgcolor_; +#else + return 53; // hard coded ~90% gray +#endif +} + +/** + Set alignment for line numbers (if enabled). + Valid values are FL_ALIGN_LEFT, FL_ALIGN_CENTER or FL_ALIGN_RIGHT. + \version 1.3.3 ABI feature (ignored in 1.3.x unless FLTK_ABI_VERSION is 10303 or higher) +*/ +void Fl_Text_Display::linenumber_align(Fl_Align val) { +#if FLTK_ABI_VERSION >= 10303 + linenumber_align_ = val; +#else + // do nothing +#endif +} + +/** + Returns the alignment used for line numbers (if enabled). +*/ +Fl_Align Fl_Text_Display::linenumber_align() const { +#if FLTK_ABI_VERSION >= 10303 + return linenumber_align_; +#else + return FL_ALIGN_RIGHT; +#endif +} + +/** + Sets the printf() style format string used for line numbers. + Default is "%d" for normal unpadded decimal integers. + + An internal copy of \p val is allocated and managed; + it is automatically freed whenever a new value is assigned, + or when the widget is destroyed. + + The value of \p val must \a not be NULL. + + Example values: + + - "%d" -- For normal line numbers without padding (Default) + - "%03d" -- For 000 padding + - "%x" -- For hexadecimal line numbers + - "%o" -- For octal line numbers + + \version 1.3.3 ABI feature (ignored in 1.3.x unless FLTK_ABI_VERSION is 10303 or higher) +*/ +void Fl_Text_Display::linenumber_format(const char* val) { +#if FLTK_ABI_VERSION >= 10303 + if ( linenumber_format_ ) free((void*)linenumber_format_); + linenumber_format_ = val ? strdup(val) : 0; +#else + // do nothing +#endif +} + +/** + Returns the line number printf() format string. +*/ +const char* Fl_Text_Display::linenumber_format() const { +#if FLTK_ABI_VERSION >= 10303 + return linenumber_format_; +#else + return "%d"; +#endif +} /** Attach a text buffer to display, replacing the current buffer (if any) @@ -406,6 +595,12 @@ void Fl_Text_Display::resize(int X, int Y, int W, int H) { } } + // add linenum width to the text area - LZA / STR#2621 + if (mLineNumWidth > 0) { + text_area.x += mLineNumWidth; + text_area.w -= mLineNumWidth; + } + // user request to change viewport if (mTopLineNumHint != mTopLineNum || mHorizOffsetHint != mHorizOffset) scroll_(mTopLineNumHint, mHorizOffsetHint); @@ -465,10 +660,6 @@ void Fl_Text_Display::draw_text( int left, int top, int width, int height ) { for ( line = firstLine; line <= lastLine; line++ ) draw_vline( line, left, left + width, 0, INT_MAX ); - /* draw the line numbers if exposed area includes them */ - if (mLineNumWidth != 0 && left <= mLineNumLeft + mLineNumWidth) - draw_line_numbers(false); - fl_pop_clip(); } @@ -700,7 +891,7 @@ void Fl_Text_Display::wrap_mode(int wrap, int wrapMargin) { mNBufferLines = 0; mFirstChar = 0; mTopLineNum = 1; - mAbsTopLineNum = 0; + mAbsTopLineNum = 1; // changed from 0 to 1 -- LZA / STR#2621 } resize(x(), y(), w(), h()); @@ -1514,8 +1705,10 @@ void Fl_Text_Display::buffer_modified_cb( int pos, int nInserted, int nDeleted, // CET - FIXME if ( origCursorPos >= startDispPos && // ( origCursorPos <= endDispPos || endDispPos == buf->length() ) ) } - - if (linesInserted > 1) textD->draw_line_numbers(false); + if (linesInserted > 1) { + // textD->draw_line_numbers(false); // can't do this b/c not called from virtual draw(); + textD->damage(::FL_DAMAGE_EXPOSE); + } } else { endDispPos = buf->next_char(textD->mLastChar); // CET - FIXME if ( origCursorPos >= pos ) @@ -1524,7 +1717,11 @@ void Fl_Text_Display::buffer_modified_cb( int pos, int nInserted, int nDeleted, have changed. If only one line is altered, line numbers cannot be affected (the insertion or removal of a line break always results in at least two lines being redrawn). */ - textD->draw_line_numbers(false); + + // Call draw_line_numbers() here to ensure line# is drawn + // when hitting enter for new line -- LZA / STR #2621 + //textD->draw_line_numbers(true); // no, can't call this here, not in draw() context -- ERCO / STR#2621 + //textD->damage(::FL_DAMAGE_EXPOSE); } IS_UTF8_ALIGNED2(buf, startDispPos) IS_UTF8_ALIGNED2(buf, endDispPos) @@ -1543,6 +1740,7 @@ void Fl_Text_Display::buffer_modified_cb( int pos, int nInserted, int nDeleted, } +/* Line Numbering Methods */ /** \brief Line numbering stuff, currently unused. @@ -1940,7 +2138,13 @@ void Fl_Text_Display::draw_string(int style, fsize = styleRec->size; if (style & PRIMARY_MASK) { - if (Fl::focus() == (Fl_Widget*)this) background = selection_color(); + if (Fl::focus() == (Fl_Widget*)this) { +#ifdef __APPLE__ + if (Fl::compose_state) background = color();// Mac OS: underline marked text + else +#endif + background = selection_color(); + } else background = fl_color_average(color(), selection_color(), 0.4f); } else if (style & HIGHLIGHT_MASK) { if (Fl::focus() == (Fl_Widget*)this) background = fl_color_average(color(), selection_color(), 0.5f); @@ -1972,6 +2176,12 @@ void Fl_Text_Display::draw_string(int style, fl_push_clip(X, Y, toX - X, mMaxsize); #endif fl_draw( string, nChars, X, Y + mMaxsize - fl_descent()); +#ifdef __APPLE__ // Mac OS: underline marked (= selected + Fl::compose_state != 0) text + if (Fl::compose_state && (style & PRIMARY_MASK)) { + fl_color( fl_color_average(foreground, background, 0.6) ); + fl_line(X, Y + mMaxsize - 1, X + fl_width(string, nChars), Y + mMaxsize - 1); + } +#endif #if !(defined(__APPLE__) || defined(WIN32)) && USE_XFT fl_pop_clip(); #endif @@ -2055,6 +2265,9 @@ void Fl_Text_Display::draw_cursor( int X, int Y ) { if ( X < text_area.x - 1 || X > text_area.x + text_area.w ) return; +#ifdef __APPLE__ + Fl::insertion_point_location(X, bot, fontHeight); +#endif /* For cursors other than the block, make them around 2/3 of a character width, rounded to an even number of pixels so that X will draw an odd number centered on the stem at x. */ @@ -2630,63 +2843,71 @@ void Fl_Text_Display::h_scrollbar_cb(Fl_Scrollbar* b, Fl_Text_Display* textD) { /** \brief Refresh the line number area. - - If clearAll is False, writes only over the character cell areas. Setting - clearAll to True will clear out any stray marks outside of the character cell - area, which might have been left from before a resize or font change. - - This function is not used. + \param clearAll -- (currently unused) If False, only draws the line number text, + does not clear the area behind it. If True, clears the area + and redraws the text. Use False to avoid a 'flash' for + single buffered windows. */ + +// This draw_line_numbers() method based on patch from +// http://www.mail-archive.com/fltk-dev@easysw.com/msg06376.html +// altered to support line numbers right alignment. -LZA / STR #2621 +// void Fl_Text_Display::draw_line_numbers(bool /*clearAll*/) { -#if 0 - int y, line, visLine, nCols, lineStart; - char lineNumString[12]; - int lineHeight = mMaxsize ? mMaxsize : textsize_; - int charWidth = TMPFONTWIDTH; //mFontStruct->max_bounds.width; - - /* Don't draw if mLineNumWidth == 0 (line numbers are hidden), or widget is - not yet realized */ - if (mLineNumWidth == 0 || visible_r()) + int Y, line, visLine, lineStart; + char lineNumString[16]; + int lineHeight = mMaxsize; + + // Don't draw if lineNumWidth == 0 (line numbers are hidden), + // or widget is not yet realized + if (mLineNumWidth <= 0 || !visible_r()) return; - /* GC is allocated on demand, since not everyone will use line numbering */ - if (textD->lineNumGC == NULL) { - XGCValues values; - values.foreground = textD->lineNumFGPixel; - values.background = textD->bgPixel; - values.font = textD->fontStruct->fid; - textD->lineNumGC = XtGetGC(textD->w, - GCFont| GCForeground | GCBackground, &values); - } - - /* Erase the previous contents of the line number area, if requested */ - if (clearAll) - XClearArea(XtDisplay(textD->w), XtWindow(textD->w), textD->lineNumLeft, - textD->top, textD->lineNumWidth, textD->height, False); - - /* Draw the line numbers, aligned to the text */ - nCols = min(11, textD->lineNumWidth / charWidth); - y = textD->top; - line = getAbsTopLineNum(textD); - for (visLine=0; visLine < textD->nVisibleLines; visLine++) { - lineStart = textD->lineStarts[visLine]; - if (lineStart != -1 && (lineStart==0 || - BufGetCharacter(textD->buffer, lineStart-1)=='\n')) { - sprintf(lineNumString, "%*d", nCols, line); - XDrawImageString(XtDisplay(textD->w), XtWindow(textD->w), - textD->lineNumGC, textD->lineNumLeft, y + textD->ascent, - lineNumString, strlen(lineNumString)); - line++; - } else { - XClearArea(XtDisplay(textD->w), XtWindow(textD->w), - textD->lineNumLeft, y, textD->lineNumWidth, - textD->ascent + textD->descent, False); - if (visLine == 0) - line++; + // Make sure we reset clipping range for line number's GC; + // it may be shared (e.g. if line numbers and text have same color) + // and therefore clipping ranges may be invalid. + int xoff = Fl::box_dx(box()); + int hscroll_h = mHScrollBar->visible() ? mHScrollBar->h() : 0; + fl_push_clip(x() + xoff, + y() + Fl::box_dy(box()), + mLineNumWidth - xoff, + h() - Fl::box_dh(box()) - hscroll_h); + { + // Set background color for line number area -- LZA / STR# 2621 + // Erase background + fl_color(linenumber_bgcolor()); + fl_rectf(x(), y(), mLineNumWidth, h()); + + // Draw separator line + //fl_color(180,180,180); + //fl_line(x()+mLineNumWidth-1, y(), x()+mLineNumWidth-1, y()+h()); + + // Draw line number text + fl_font(linenumber_font(), linenumber_size()); + + Y = y(); + line = get_absolute_top_line_number(); + + // set font color for line numbers + fl_color(linenumber_fgcolor()); + for (visLine=0; visLine < mNVisibleLines; visLine++) { + lineStart = mLineStarts[visLine]; + if (lineStart != -1 && (lineStart==0 || buffer()->char_at(lineStart-1)=='\n')) { + sprintf(lineNumString, linenumber_format(), line); + int xx = x() + xoff + 3, + yy = Y + 3, + ww = mLineNumWidth - xoff - (3*2), + hh = lineHeight; + fl_draw(lineNumString, xx, yy, ww, hh, linenumber_align(), 0, 0); + //DEBUG fl_rect(xx, yy, ww, hh); + line++; + } else { + if (visLine == 0) line++; + } + Y += lineHeight; } - y += lineHeight; - } -#endif + } + fl_pop_clip(); } static int max( int i1, int i2 ) { @@ -3042,12 +3263,13 @@ void Fl_Text_Display::measure_deleted_lines(int pos, int nDeleted) { and the styleBufOffset argument must indicate the starting position of the copy, to take into account the correct style information. - \param buf - \param startPos - \param maxPos - \param maxLines - \param startPosIsLineStart - \param styleBufOffset + \param[in] buf The text buffer to operate on + \param[in] startPos Starting index position into the buffer + \param[in] maxPos Maximum index position into the buffer we'll reach + \param[in] maxLines Maximum number of lines we'll reach + \param[in] startPosIsLineStart Flag indicating if startPos is start of line. + (If set, prevents our having to find the line start) + \param[in] styleBufOffset Offset index position into style buffer. \param[out] retPos Position where counting ended. When counting lines, the position returned is the start of the line "maxLines" lines @@ -3147,9 +3369,13 @@ void Fl_Text_Display::wrapped_line_counter(Fl_Text_Buffer *buf, int startPos, if (b<lineStart) b = lineStart; if (!foundBreak) { /* no whitespace, just break at margin */ newLineStart = max(p, buf->next_char(lineStart)); - const char *s = buf->address(b); colNum++; - width = measure_proportional_character(s, 0, p+styleBufOffset); + if (b >= buf->length()) { // STR #2730 + width = 0; + } else { + const char *s = buf->address(b); + width = measure_proportional_character(s, 0, p+styleBufOffset); + } } if (p >= maxPos) { *retPos = maxPos; @@ -3401,8 +3627,7 @@ void Fl_Text_Display::draw(void) { fl_rectf(mVScrollBar->x(), mHScrollBar->y(), mVScrollBar->w(), mHScrollBar->h(), FL_GRAY); - - // blank the previous cursor protrusions + //draw_line_numbers(true); // commented out STR# 2621 / LZA } else if (damage() & (FL_DAMAGE_SCROLL | FL_DAMAGE_EXPOSE)) { // printf("blanking previous cursor extrusions at Y: %d\n", mCursorOldY); @@ -3456,8 +3681,14 @@ void Fl_Text_Display::draw(void) { } // draw the text cursor + int start, end; + int has_selection = buffer()->selection_position(&start, &end); if (damage() & (FL_DAMAGE_ALL | FL_DAMAGE_SCROLL | FL_DAMAGE_EXPOSE) - && !buffer()->primary_selection()->selected() && + && ( +#ifdef __APPLE__ + Fl::compose_state || +#endif + !has_selection || mCursorPos < start || mCursorPos > end) && mCursorOn && Fl::focus() == (Fl_Widget*)this ) { fl_push_clip(text_area.x-LEFT_MARGIN, text_area.y, @@ -3473,6 +3704,11 @@ void Fl_Text_Display::draw(void) { //printf("drew cursor at pos: %d (%d,%d)\n", mCursorPos, X, Y); fl_pop_clip(); } + + // Important to do this at end of this method, otherwise line numbers + // will not scroll with the text edit area + draw_line_numbers(true); + fl_pop_clip(); } @@ -3797,5 +4033,5 @@ double Fl_Text_Display::col_to_x(double col) const // -// End of "$Id: Fl_Text_Display.cxx 9362 2012-04-21 03:02:25Z fabien $". +// End of "$Id: Fl_Text_Display.cxx 10416 2014-10-30 12:35:36Z AlbrechtS $". // diff --git a/src/Fl_Text_Editor.cxx b/src/Fl_Text_Editor.cxx index 0ec6544..721b31a 100644 --- a/src/Fl_Text_Editor.cxx +++ b/src/Fl_Text_Editor.cxx @@ -1,5 +1,5 @@ // -// "$Id: Fl_Text_Editor.cxx 9325 2012-04-05 05:12:30Z fabien $" +// "$Id: Fl_Text_Editor.cxx 10031 2013-12-13 16:28:38Z manolo $" // // Copyright 2001-2010 by Bill Spitzak and others. // Original code Copyright Mark Edel. Permission to distribute under @@ -73,6 +73,7 @@ Fl_Text_Editor::Fl_Text_Editor(int X, int Y, int W, int H, const char* l) mCursorOn = 1; insert_mode_ = 1; key_bindings = 0; + set_flag(MAC_USE_ACCENTS_MENU); // handle the default key bindings add_default_key_bindings(&key_bindings); @@ -514,8 +515,9 @@ int Fl_Text_Editor::handle_key() { int del = 0; if (Fl::compose(del)) { if (del) { - int dp = insert_position(), di = del; - while (di--) dp = buffer()->prev_char_clipped(dp); + // del is a number of bytes + int dp = insert_position() - del; + if ( dp < 0 ) dp = 0; buffer()->select(dp, insert_position()); } kill_selection(this); @@ -523,6 +525,12 @@ int Fl_Text_Editor::handle_key() { if (insert_mode()) insert(Fl::event_text()); else overstrike(Fl::event_text()); } +#ifdef __APPLE__ + if (Fl::compose_state) { + int pos = this->insert_position(); + this->buffer()->select(pos - Fl::compose_state, pos); + } +#endif show_insert_position(); set_changed(); if (when()&FL_WHEN_CHANGED) do_callback(); @@ -560,6 +568,13 @@ int Fl_Text_Editor::handle(int event) { case FL_UNFOCUS: show_cursor(mCursorOn); // redraws the cursor +#ifdef __APPLE__ + if (buffer()->selected() && Fl::compose_state) { + int pos = insert_position(); + buffer()->select(pos, pos); + Fl::reset_marked_text(); + } +#endif if (buffer()->selected()) redraw(); // Redraw selections... case FL_HIDE: if (when() & FL_WHEN_RELEASE) maybe_do_callback(); @@ -631,7 +646,7 @@ int Fl_Text_Editor::handle(int event) { insert_position(dndCursorPos); return 1; case FL_DND_RELEASE: // keep insertion cursor and wait for the FL_PASTE event - buffer()->unselect(); // FL_PASTE must not destroy current selection! + if (!dragging) buffer()->unselect(); // FL_PASTE must not destroy current selection if drag comes from outside return 1; } @@ -639,5 +654,5 @@ int Fl_Text_Editor::handle(int event) { } // -// End of "$Id: Fl_Text_Editor.cxx 9325 2012-04-05 05:12:30Z fabien $". +// End of "$Id: Fl_Text_Editor.cxx 10031 2013-12-13 16:28:38Z manolo $". // diff --git a/src/Fl_Tile.cxx b/src/Fl_Tile.cxx index e800110..dfe215f 100644 --- a/src/Fl_Tile.cxx +++ b/src/Fl_Tile.cxx @@ -1,12 +1,12 @@ // -// "$Id: Fl_Tile.cxx 9637 2012-07-24 04:37:22Z matt $" +// "$Id: Fl_Tile.cxx 10385 2014-10-19 14:17:47Z AlbrechtS $" // // Tile widget for the Fast Light Tool Kit (FLTK). // -// Copyright 1998-2010 by Bill Spitzak and others. +// Copyright 1998-2014 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in -// the file "COPYING" which should have been included with this file. If this +// the file "COPYING" which should have been included with this file. If this // file is missing or damaged, see the license at: // // http://www.fltk.org/COPYING.php @@ -16,23 +16,81 @@ // http://www.fltk.org/str.php // +/** + \class Fl_Tile -// Group of 2 or 4 "tiles" that can be resized by dragging border -// The size of the first child determines where the resize border is. -// The resizebox is used to limit where the border can be dragged to. + The Fl_Tile class lets you resize its children by dragging + the border between them. + + \image html Fl_Tile.png + \image latex Fl_Tile.png "Fl_Tile" width=5cm + + For the tiling to work correctly, the children of an Fl_Tile must + cover the entire area of the widget, but not overlap. + This means that all children must touch each other at their edges, + and no gaps can be left inside the Fl_Tile. + + Fl_Tile does not normally draw any graphics of its own. + The "borders" which can be seen in the snapshot above are actually + part of the children. Their boxtypes have been set to FL_DOWN_BOX + creating the impression of "ridges" where the boxes touch. What + you see are actually two adjacent FL_DOWN_BOX's drawn next to each + other. All neighboring widgets share the same edge - the widget's + thick borders make it appear as though the widgets aren't actually + touching, but they are. If the edges of adjacent widgets do not + touch, then it will be impossible to drag the corresponding edges. + + Fl_Tile allows objects to be resized to zero dimensions. + To prevent this you can use the resizable() to limit where + corners can be dragged to. For more information see note below. + + Even though objects can be resized to zero sizes, they must initially + have non-zero sizes so the Fl_Tile can figure out their layout. + If desired, call position() after creating the children but before + displaying the window to set the borders where you want. + + <b>Note on resizable(Fl_Widget &w):</b> + The "resizable" child widget (which should be invisible) limits where + the borders can be dragged to. All dragging will be limited inside the + resizable widget's borders. If you don't set it, it will be possible + to drag the borders right to the edges of the Fl_Tile widget, and thus + resize objects on the edges to zero width or height. When the entire + Fl_Tile widget is resized, the resizable() widget will keep its border + distance to all borders the same (this is normal resize behavior), so + that you can effectively set a border width that will never change. + + <b>Note:</b> + You can still resize widgets \b inside the resizable() to zero width and/or + height, i.e. box \b 2b above to zero width and box \b 3a to zero height. + + \see void Fl_Group::resizable(Fl_Widget &w) + + Example for resizable with 20 pixel border distance: + \code + int dx = 20, dy = dx; + Fl_Tile tile(50,50,300,300); + // ... create widgets inside tile (see test/tile.cxx) ... + // create resizable() box + Fl_Box r(tile.x()+dx,tile.y()+dy,tile.w()-2*dx,tile.h()-2*dy); + tile.resizable(r); + tile.end(); + \endcode + + See also the complete example program in test/tile.cxx. +*/ #include <FL/Fl.H> #include <FL/Fl_Tile.H> #include <FL/Fl_Window.H> #include <stdlib.h> -// Drag the edges that were initially at oldx,oldy to newx,newy: -// pass zero as oldx or oldy to disable drag in that direction: -/** - Drag the intersection at from_x,from_y to to_x,to_y. +/** + Drags the intersection at (\p oldx,\p oldy) to (\p newx,\p newy). This redraws all the necessary children. + + Pass zero as \p oldx or \p oldy to disable drag in that direction. */ -void Fl_Tile::position(int oix, int oiy, int newx, int newy) { +void Fl_Tile::position(int oldx, int oldy, int newx, int newy) { Fl_Widget*const* a = array(); int *p = sizes(); p += 8; // skip group & resizable's saved size @@ -41,28 +99,43 @@ void Fl_Tile::position(int oix, int oiy, int newx, int newy) { if (o == resizable()) continue; int X = o->x(); int R = X+o->w(); - if (oix) { + if (oldx) { int t = p[0]; - if (t == oix || (t>oix && X<newx) || (t<oix && X>newx) ) X = newx; + if (t == oldx || (t>oldx && X<newx) || (t<oldx && X>newx) ) X = newx; t = p[1]; - if (t == oix || (t>oix && R<newx) || (t<oix && R>newx) ) R = newx; + if (t == oldx || (t>oldx && R<newx) || (t<oldx && R>newx) ) R = newx; } int Y = o->y(); int B = Y+o->h(); - if (oiy) { + if (oldy) { int t = p[2]; - if (t == oiy || (t>oiy && Y<newy) || (t<oiy && Y>newy) ) Y = newy; + if (t == oldy || (t>oldy && Y<newy) || (t<oldy && Y>newy) ) Y = newy; t = p[3]; - if (t == oiy || (t>oiy && B<newy) || (t<oiy && B>newy) ) B = newy; + if (t == oldy || (t>oldy && B<newy) || (t<oldy && B>newy) ) B = newy; } o->damage_resize(X,Y,R-X,B-Y); } } -// move the lower-right corner (sort of): +/** + Resizes the Fl_Tile widget and its children. + + Fl_Tile implements its own resize() method. It does not use + Fl_Group::resize() to resize itself and its children. + + Enlarging works by just moving the lower-right corner and resizing + the bottom and right border widgets accordingly. + + Shrinking the Fl_Tile works in the opposite way by shrinking + the bottom and right border widgets, unless they are reduced to zero + width or height, resp. or to their minimal sizes defined by the + resizable() widget. In this case other widgets will be shrunk as well. + + See the Fl_Tile class documentation about how the resizable() works. +*/ + void Fl_Tile::resize(int X,int Y,int W,int H) { - //Fl_Group::resize(X, Y, W, H); - //return; + // remember how much to move the child widgets: int dx = X-x(); int dy = Y-y(); @@ -71,11 +144,13 @@ void Fl_Tile::resize(int X,int Y,int W,int H) { int *p = sizes(); // resize this (skip the Fl_Group resize): Fl_Widget::resize(X,Y,W,H); - // find bottom-right of resiable: - int OR = p[5]; - int NR = X+W-(p[1]-OR); - int OB = p[7]; - int NB = Y+H-(p[3]-OB); + + // find bottom-right corner of resizable: + int OR = p[5]; // old right border + int NR = X+W-(p[1]-OR); // new right border + int OB = p[7]; // old bottom border + int NB = Y+H-(p[3]-OB); // new bottom border + // move everything to be on correct side of new resizable: Fl_Widget*const* a = array(); p += 8; @@ -90,7 +165,7 @@ void Fl_Tile::resize(int X,int Y,int W,int H) { if (*p++ >= OB) yy += dh; else if (yy > NB) yy = NB; if (*p++ >= OB) B += dh; else if (B > NB) B = NB; o->resize(xx,yy,R-xx,B-yy); - // do *not* call o->redraw() here! If you do, and the tile is inside a + // do *not* call o->redraw() here! If you do, and the tile is inside a // scroll, it'll set the damage areas wrong for all children! } } @@ -200,13 +275,26 @@ int Fl_Tile::handle(int event) { return Fl_Group::handle(event); } +/** + Creates a new Fl_Tile widget using the given position, size, + and label string. The default boxtype is FL_NO_BOX. + + The destructor <I>also deletes all the children</I>. This allows a + whole tree to be deleted at once, without having to keep a pointer to + all the children in the user code. A kludge has been done so the + Fl_Tile and all of its children can be automatic (local) + variables, but you must declare the Fl_Tile <I>first</I>, so + that it is destroyed last. + + \see class Fl_Group +*/ -Fl_Tile::Fl_Tile(int X,int Y,int W,int H,const char*l) -: Fl_Group(X,Y,W,H,l) +Fl_Tile::Fl_Tile(int X,int Y,int W,int H,const char*l) +: Fl_Group(X,Y,W,H,l) { } // -// End of "$Id: Fl_Tile.cxx 9637 2012-07-24 04:37:22Z matt $". +// End of "$Id: Fl_Tile.cxx 10385 2014-10-19 14:17:47Z AlbrechtS $". // diff --git a/src/Fl_Tiled_Image.cxx b/src/Fl_Tiled_Image.cxx index d708742..2f459ea 100644 --- a/src/Fl_Tiled_Image.cxx +++ b/src/Fl_Tiled_Image.cxx @@ -1,5 +1,5 @@ // -// "$Id: Fl_Tiled_Image.cxx 8864 2011-07-19 04:49:30Z greg.ercolano $" +// "$Id: Fl_Tiled_Image.cxx 10218 2014-07-10 12:28:00Z manolo $" // // Tiled image code for the Fast Light Tool Kit (FLTK). // @@ -19,6 +19,7 @@ #include <FL/Fl.H> #include <FL/Fl_Tiled_Image.H> +#include <FL/Fl_Window.H> #include <FL/fl_draw.H> /** @@ -31,9 +32,10 @@ Fl_Tiled_Image::Fl_Tiled_Image(Fl_Image *i, // I - Image to tile Fl_Image(W,H,0) { image_ = i; alloc_image_ = 0; - - if (W == 0) w(Fl::w()); - if (H == 0) h(Fl::h()); + // giving to the tiled image the screen size may fail with multiscreen configurations + // so we leave it with w = h = 0 (STR #3106) + /* if (W == 0) w(Fl::w()); + if (H == 0) h(Fl::h());*/ } /** The destructor frees all memory and server resources that are used by @@ -99,8 +101,11 @@ Fl_Tiled_Image::draw(int X, // I - Starting X position int cx, // I - "Source" X position int cy) { // I - "Source" Y position if (!image_->w() || !image_->h()) return; - if (W == 0) W = Fl::w(); - if (H == 0) H = Fl::h(); + if (W == 0 && H == 0 && Fl_Window::current()) { // W and H null means the image is potentially as large as the current window + W = Fl_Window::current()->w(); + H = Fl_Window::current()->h(); + X = Y = 0; + } fl_push_clip(X, Y, W, H); @@ -122,5 +127,5 @@ Fl_Tiled_Image::draw(int X, // I - Starting X position // -// End of "$Id: Fl_Tiled_Image.cxx 8864 2011-07-19 04:49:30Z greg.ercolano $". +// End of "$Id: Fl_Tiled_Image.cxx 10218 2014-07-10 12:28:00Z manolo $". // diff --git a/src/Fl_Tree.cxx b/src/Fl_Tree.cxx index f0c6f72..1a513d1 100644 --- a/src/Fl_Tree.cxx +++ b/src/Fl_Tree.cxx @@ -1,5 +1,5 @@ // -// "$Id: Fl_Tree.cxx 9706 2012-11-06 20:46:14Z matt $" +// "$Id: Fl_Tree.cxx 10275 2014-09-05 12:04:28Z cand $" // #include <stdio.h> @@ -27,60 +27,44 @@ // http://www.fltk.org/str.php // -// INTERNAL: scroller callback +// INTERNAL: scroller callback (hor+vert scroll) static void scroll_cb(Fl_Widget*,void *data) { ((Fl_Tree*)data)->redraw(); } -// INTERNAL: Parse elements from path into an array of null terminated strings -// Handles escape characters. -// Path="/aa/bb" -// Return: arr[0]="aa", arr[1]="bb", arr[2]=0 +// INTERNAL: Parse elements from 'path' into an array of null terminated strings +// Handles escape characters, ignores multiple /'s. +// Path="/aa/bb", returns arr[0]="aa", arr[1]="bb", arr[2]=0. // Caller must call free_path(arr). // static char **parse_path(const char *path) { - while ( *path == '/' ) path++; // skip leading '/' - // First pass: identify, null terminate, and count separators - int seps = 1; // separator count (1: first item) - int arrsize = 1; // array size (1: first item) - char *save = strdup(path); // make copy we can modify - char *sin = save, *sout = save; - while ( *sin ) { - if ( *sin == '\\' ) { // handle escape character - *sout++ = *++sin; - if ( *sin ) ++sin; - } else if ( *sin == '/' ) { // handle submenu - *sout++ = 0; - sin++; - seps++; - arrsize++; - } else { // all other chars - *sout++ = *sin++; - } - } - *sout = 0; - arrsize++; // (room for terminating NULL) - // Second pass: create array, save nonblank elements - char **arr = (char**)malloc(sizeof(char*) * arrsize); - int t = 0; - sin = save; - while ( seps-- > 0 ) { - if ( *sin ) { arr[t++] = sin; } // skips empty fields, e.g. '//' - sin += (strlen(sin) + 1); + size_t len = strlen(path); + char *cp = new char[(len+1)], *word = cp, *s = cp; // freed below or in free_path() + char **ap = new char*[(len+1)], **arr = ap; // overallocates arr[] + while (1) { + if (*path =='/' || *path == 0) { // handle path sep or eos + if (word != s) { *s++ = 0; *arr++= word; word = s; } + if ( !*path++) break; else continue; // eos? done, else cont + } else if ( *path == '\\' ) { // handle escape + if ( *(++path) ) { *s++ = *path++; } else continue; + } else { *s++ = *path++; } // handle normal char } - arr[t] = 0; - return(arr); + *arr = 0; + if ( arr == ap ) delete[] cp; // empty arr[]? delete since free_path() can't + return ap; } -// INTERNAL: Free the array returned by parse_path() +// INTERNAL: Free an array 'arr' returned by parse_path() static void free_path(char **arr) { if ( arr ) { - if ( arr[0] ) { free((void*)arr[0]); } - free((void*)arr); + if ( arr[0] ) { delete[] arr[0]; } // deletes cp in parse_path + delete[] arr; // deletes ptr array } } -// INTERNAL: Recursively descend tree hierarchy, accumulating total child count +// INTERNAL: Recursively descend 'item's tree hierarchy +// accumulating total child 'count' +// static int find_total_children(Fl_Tree_Item *item, int count=0) { count++; for ( int t=0; t<item->children(); t++ ) { @@ -91,7 +75,11 @@ static int find_total_children(Fl_Tree_Item *item, int count=0) { /// Constructor. Fl_Tree::Fl_Tree(int X, int Y, int W, int H, const char *L) : Fl_Group(X,Y,W,H,L) { +#if FLTK_ABI_VERSION >= 10303 + _root = new Fl_Tree_Item(this); +#else _root = new Fl_Tree_Item(_prefs); +#endif _root->parent(0); // we are root of tree _root->label("ROOT"); _item_focus = 0; @@ -109,11 +97,25 @@ Fl_Tree::Fl_Tree(int X, int Y, int W, int H, const char *L) : Fl_Group(X,Y,W,H,L box(FL_DOWN_BOX); color(FL_BACKGROUND2_COLOR, FL_SELECTION_COLOR); when(FL_WHEN_CHANGED); - _vscroll = new Fl_Scrollbar(0,0,0,0); // will be resized by draw() + int scrollsize = _scrollbar_size ? _scrollbar_size : Fl::scrollbar_size(); + _vscroll = new Fl_Scrollbar(X+W-scrollsize,Y,scrollsize,H); _vscroll->hide(); _vscroll->type(FL_VERTICAL); _vscroll->step(1); _vscroll->callback(scroll_cb, (void*)this); +#if FLTK_ABI_VERSION >= 10303 + _hscroll = new Fl_Scrollbar(X,Y+H-scrollsize,W,scrollsize); + _hscroll->hide(); + _hscroll->type(FL_HORIZONTAL); + _hscroll->step(1); + _hscroll->callback(scroll_cb, (void*)this); + _tox = _tix = X + Fl::box_dx(box()); + _toy = _tiy = Y + Fl::box_dy(box()); + _tow = _tiw = W - Fl::box_dw(box()); + _toh = _tih = H - Fl::box_dh(box()); + _tree_w = -1; + _tree_h = -1; +#endif end(); } @@ -122,26 +124,137 @@ Fl_Tree::~Fl_Tree() { if ( _root ) { delete _root; _root = 0; } } -/// Extend a selection between 'from' and 'to'. -/// Used by SHIFT-click to extend a selection between two items inclusive. +/// Extend the selection between and including \p 'from' and \p 'to' +/// depending on direction \p 'dir', \p 'val', and \p 'visible'. /// -void Fl_Tree::extend_selection(Fl_Tree_Item *from, Fl_Tree_Item *to) { - char on = 0; +/// Efficient: does not walk entire tree; starts with \p 'from' and stops +/// at \p 'to' while moving in direction \p 'dir'. Dir must be specified though. +#if FLTK_ABI_VERSION >= 10303 +/// +/// If dir cannot be known in advance, such as during SHIFT-click operations, +/// the method extend_selection(Fl_Tree_Item*,Fl_Tree_Item*,int,bool) +/// should be used. +#endif +/// +/// Handles calling redraw() if anything changed. +/// +/// \param[in] from Starting item +/// \param[in] to Ending item +/// \param[in] dir Direction to extend selection (FL_Up or FL_Down) +/// \param[in] val 0=deselect, 1=select, 2=toggle +/// \param[in] visible true=affect only open(), visible items,<br> +/// false=affect open or closed items (default) +/// \returns The number of items whose selection states were changed, if any. +/// \version 1.3.3 +/// +int Fl_Tree::extend_selection_dir(Fl_Tree_Item *from, Fl_Tree_Item *to, + int dir, int val, bool visible ) { + int changed = 0; + for (Fl_Tree_Item *item=from; item; item = next_item(item, dir, visible) ) { + switch (val) { + case 0: + if ( deselect(item, when()) ) ++changed; + break; + case 1: + if ( select(item, when()) ) ++changed; + break; + case 2: + select_toggle(item, when()); + ++changed; // toggle always involves a change + break; + } + if ( item==to ) break; + } + return(changed); +} + +/// Extend a selection between \p 'from' and \p 'to' depending on \p 'visible'. +/// +/// Similar to the more efficient +/// extend_selection_dir(Fl_Tree_Item*,Fl_Tree_Item*,int dir,int val,bool vis) +/// method, but direction (up or down) doesn't need to be known.<br> +/// We're less efficient because we search the tree for to/from, then operate +/// on items in between. The more efficient method avoids the "search", +/// but necessitates a direction to be specified to find \p 'to'.<br> +/// Used by SHIFT-click to extend a selection between two items inclusive.<br> +/// Handles calling redraw() if anything changed. +/// +/// \param[in] from Starting item +/// \param[in] to Ending item +/// \param[in] val Select or deselect items (0=deselect, 1=select, 2=toggle) +/// \param[in] visible true=affect only open(), visible items,<br> +/// false=affect open or closed items (default) +/// \returns The number of items whose selection states were changed, if any. +#if FLTK_ABI_VERSION >= 10303 +/// \version 1.3.3 ABI feature +int Fl_Tree::extend_selection(Fl_Tree_Item *from, Fl_Tree_Item *to, + int val, bool visible) { +#else +/// \notes Made public in 1.3.3 ABI +// Adding overload if not at least one overload breaks ABI, so avoid +// by making a private function until ABI can change.. +int Fl_Tree::extend_selection__(Fl_Tree_Item *from, Fl_Tree_Item *to, + int val, bool visible) { +#endif + int changed = 0; if ( from == to ) { - from->select(); - return; + if ( visible && !from->is_visible() ) return(0); // do nothing + switch (val) { + case 0: + if ( deselect(from, when()) ) ++changed; + break; + case 1: + if ( select(from, when()) ) ++changed; + break; + case 2: + select_toggle(from, when()); + ++changed; // always changed + break; + } + return(changed); } - for ( Fl_Tree_Item *item = first(); item; item = next(item) ) { - if ( (item == from) || (item == to) ) { - item->select(); // inclusive - on ^= 1; - } else if ( on ) { - item->select(); + char on = 0; + for ( Fl_Tree_Item *item = first(); item; item = item->next_visible(_prefs) ) { + if ( visible && !item->is_visible() ) continue; + if ( on || (item == from) || (item == to) ) { + switch (val) { + case 0: + if ( deselect(item, when()) ) ++changed; + break; + case 1: + if ( select(item, when()) ) ++changed; + break; + case 2: + select_toggle(item, when()); + ++changed; // toggle always involves a change + break; + } + if ( (item == from) || (item == to) ) { + on ^= 1; + if ( !on ) break; // done + } } } + return(changed); } +#if FLTK_ABI_VERSION >= 10303 +// not needed, above overload handles this +#else +/// Extend a selection between \p 'from' and \p 'to'. +/// Extends selection for items and all children, visible ('open') or not. +/// Walks entire tree from top to bottom looking for \p 'from' and \p 'to'. +/// \version 1.3.0 +/// +void Fl_Tree::extend_selection(Fl_Tree_Item *from, Fl_Tree_Item *to) { + const int val = 1; // 0=clr, 1=set, 2=toggle + const bool visible = false; // true=only 'open' items, false='open' or 'closed' + extend_selection__(from, to, val, visible); // use private method until we can release it +} +#endif + /// Standard FLTK event handler for this widget. +/// \todo add Fl_Widget_Tracker (see Fl_Browser_.cxx::handle()) int Fl_Tree::handle(int e) { if (e == FL_NO_EVENT) return(0); // XXX: optimize to prevent slow resizes on large trees! int ret = 0; @@ -157,6 +270,7 @@ int Fl_Tree::handle(int e) { // Developer note: Fl_Browser_::handle() used for reference here.. // #include <FL/names.h> // for event debugging // fprintf(stderr, "DEBUG: %s (%d)\n", fl_eventnames[e], e); + if (e == FL_ENTER || e == FL_LEAVE) return(1); switch (e) { case FL_FOCUS: { @@ -164,10 +278,10 @@ int Fl_Tree::handle(int e) { // If a nav key was used to give us focus, and we've got no saved // focus widget, determine which item gets focus depending on nav key. // - if ( ! _item_focus ) { // no focus established yet? - switch (Fl::event_key()) { // determine if focus was navigated.. - case FL_Tab: { // received focus via TAB? - int updown = is_shift ? FL_Up : FL_Down; // SHIFT-TAB similar to Up, TAB similar to Down + if ( ! _item_focus ) { // no focus established yet? + switch (Fl::event_key()) { // determine if focus was navigated.. + case FL_Tab: { // received focus via TAB? + int updown = is_shift ? FL_Up : FL_Down; // SHIFT-TAB similar to Up, TAB similar to Down set_item_focus(next_visible_item(0, updown)); break; } @@ -196,7 +310,7 @@ int Fl_Tree::handle(int e) { if ( (Fl::focus() == this) && // tree has focus? _prefs.selectmode() > FL_TREE_SELECT_NONE ) { // select mode that supports kb events? if ( !_item_focus ) { // no current focus item? - set_item_focus(first_visible()); // use first vis item + set_item_focus(first_visible_item()); // use first vis item if ( Fl::event_key() == FL_Up || // Up or down? Fl::event_key() == FL_Down ) // ..if so, already did 'motion' return(1); // ..so just return. @@ -214,6 +328,7 @@ int Fl_Tree::handle(int e) { case FL_TREE_SELECT_NONE: break; // ignore, let group have shot at event case FL_TREE_SELECT_SINGLE: + case FL_TREE_SELECT_SINGLE_DRAGGABLE: if ( is_ctrl ) { // CTRL-SPACE: (single mode) toggle if ( ! _item_focus->is_selected() ) { select_only(_item_focus, when()); @@ -239,14 +354,10 @@ int Fl_Tree::handle(int e) { case FL_Left: { // LEFT: close children (if any) if ( _item_focus ) { if ( ekey == FL_Right && _item_focus->is_close() ) { - // Open closed item - open(_item_focus); - redraw(); + open(_item_focus); // open closed item ret = 1; } else if ( ekey == FL_Left && _item_focus->is_open() ) { - // Close open item - close(_item_focus); - redraw(); + close(_item_focus); // close open item ret = 1; } return(1); @@ -279,11 +390,12 @@ int Fl_Tree::handle(int e) { switch ( _prefs.selectmode() ) { case FL_TREE_SELECT_NONE: case FL_TREE_SELECT_SINGLE: + case FL_TREE_SELECT_SINGLE_DRAGGABLE: break; case FL_TREE_SELECT_MULTI: // Do a 'select all' select_all(); - _lastselect = first_visible(); + _lastselect = first_visible_item(); take_focus(); return(1); } @@ -306,44 +418,54 @@ int Fl_Tree::handle(int e) { // fprintf(stderr, "Fl_Tree::handle(): Event was %s (%d)\n", fl_eventnames[e], e); // DEBUGGING if ( ! _root ) return(ret); + static int last_my = 0; switch ( e ) { case FL_PUSH: { // clicked on tree - if (Fl::visible_focus() && handle(FL_FOCUS)) { - Fl::focus(this); - } - // Not extending a selection? zero lastselect + last_my = Fl::event_y(); // save for dragging direction.. + if (Fl::visible_focus() && handle(FL_FOCUS)) Fl::focus(this); +#if FLTK_ABI_VERSION >= 10303 + Fl_Tree_Item *item = _root->find_clicked(_prefs, 0); +#else Fl_Tree_Item *item = _root->find_clicked(_prefs); +#endif if ( !item ) { // clicked, but not on an item? + _lastselect = 0; switch ( _prefs.selectmode() ) { case FL_TREE_SELECT_NONE: break; case FL_TREE_SELECT_SINGLE: + case FL_TREE_SELECT_SINGLE_DRAGGABLE: case FL_TREE_SELECT_MULTI: deselect_all(); break; } break; } - set_item_focus(item); // becomes new focus widget - redraw(); - ret |= 1; // handled + set_item_focus(item); // becomes new focus widget, calls redraw() if needed + ret |= 1; // handled if ( Fl::event_button() == FL_LEFT_MOUSE ) { if ( item->event_on_collapse_icon(_prefs) ) { // collapse icon clicked? - open_toggle(item); + open_toggle(item); // toggle open (handles redraw) } else if ( item->event_on_label(_prefs) && // label clicked? - (!item->widget() || !Fl::event_inside(item->widget())) && // not inside widget - (!_vscroll->visible() || !Fl::event_inside(_vscroll)) ) { // not on scroller + (!item->widget() || !Fl::event_inside(item->widget())) ) { // not inside widget switch ( _prefs.selectmode() ) { case FL_TREE_SELECT_NONE: break; case FL_TREE_SELECT_SINGLE: - select_only(item, when()); + case FL_TREE_SELECT_SINGLE_DRAGGABLE: + select_only(item, when()); // select only this item (handles redraw) _lastselect = item; break; case FL_TREE_SELECT_MULTI: { if ( is_shift ) { // SHIFT+PUSH? if ( _lastselect ) { - extend_selection(_lastselect, item); + int val = is_ctrl ? 2 : 1; + bool visible = true; +#if FLTK_ABI_VERSION >= 10303 + extend_selection(_lastselect, item, val, visible); +#else + extend_selection__(_lastselect, item, val, visible); +#endif } else { select(item); // add to selection } @@ -361,61 +483,363 @@ int Fl_Tree::handle(int e) { break; } case FL_DRAG: { - // do the scrolling first: + // Do scrolling first.. + + // Detect up/down dragging int my = Fl::event_y(); - if ( my < y() ) { // above top? - int p = vposition()-(y()-my); - if ( p < 0 ) p = 0; - vposition(p); - } else if ( my > (y()+h()) ) { // below bottom? - int p = vposition()+(my-y()-h()); - if ( p > (int)_vscroll->maximum() ) p = (int)_vscroll->maximum(); - vposition(p); + int dir = (my>last_my) ? FL_Down : FL_Up; + last_my = my; + + // Handle autoscrolling + if ( my < y() ) { // Above top? + dir = FL_Up; // ..going up + int p = vposition()-(y()-my); // ..position above us + if ( p < 0 ) p = 0; // ..don't go above 0 + vposition(p); // ..scroll to new position + } else if ( my > (y()+h()) ) { // Below bottom? + dir = FL_Down; // ..going down + int p = vposition()+(my-y()-h()); // ..position below us + if ( p > (int)_vscroll->maximum() ) // ..don't go below bottom + p = (int)_vscroll->maximum(); + vposition(p); // ..scroll to new position } + + // Now handle the event.. + // During drag, only interested in left-mouse operations. + // if ( Fl::event_button() != FL_LEFT_MOUSE ) break; - Fl_Tree_Item *item = _root->find_clicked(_prefs); - if ( ! item ) break; - set_item_focus(item); // becomes new focus widget - redraw(); - ret |= 1; - // Item's label clicked? - if ( item->event_on_label(_prefs) && - (!item->widget() || !Fl::event_inside(item->widget())) && - (!_vscroll->visible() || !Fl::event_inside(_vscroll)) ) { - // Handle selection behavior - switch ( _prefs.selectmode() ) { - case FL_TREE_SELECT_NONE: - break; // no selection changes - case FL_TREE_SELECT_SINGLE: - select_only(item, when()); - _lastselect = item; - break; - case FL_TREE_SELECT_MULTI: - if ( is_ctrl ) { // CTRL-DRAG: toggle? - if ( _lastselect != item ) { // not already toggled from last microdrag? - select_toggle(item, when()); // toggle selection - } - } else { - select(item); // select this - } - _lastselect = item; - break; +#if FLTK_ABI_VERSION >= 10303 + Fl_Tree_Item *item = _root->find_clicked(_prefs, 1); // item we're on, vertically +#else + Fl_Tree_Item *item = _root->find_clicked(_prefs); // item we're on, vertically +#endif + if ( !item ) break; // not near item? ignore drag event + ret |= 1; // acknowledge event + if (_prefs.selectmode() != FL_TREE_SELECT_SINGLE_DRAGGABLE) + set_item_focus(item); // becomes new focus item + if (item==_lastselect) break; // same item as before? avoid reselect + + // Handle selection behavior + switch ( _prefs.selectmode() ) { + case FL_TREE_SELECT_NONE: + break; // no selection changes + case FL_TREE_SELECT_SINGLE: { + select_only(item, when()); // select only this item (handles redraw) + break; + } + case FL_TREE_SELECT_SINGLE_DRAGGABLE: { + item = _lastselect; // Keep the source intact + redraw(); + break; + } + case FL_TREE_SELECT_MULTI: { + Fl_Tree_Item *from = next_visible_item(_lastselect, dir); // avoid reselecting item + Fl_Tree_Item *to = item; + int val = is_ctrl ? 2 : 1; // toggle_select() or just select()? + bool visible = true; + extend_selection_dir(from, to, dir, val, visible); + break; } } + _lastselect = item; // save current item for later break; } + case FL_RELEASE: + if (_prefs.selectmode() == FL_TREE_SELECT_SINGLE_DRAGGABLE && + Fl::event_button() == FL_LEFT_MOUSE) { +#if FLTK_ABI_VERSION >= 10303 + Fl_Tree_Item *item = _root->find_clicked(_prefs, 1); // item we're on, vertically +#else + Fl_Tree_Item *item = _root->find_clicked(_prefs); // item we're on, vertically +#endif + + if (item && _lastselect && item != _lastselect && + Fl::event_x() >= item->label_x()) { + //printf("Would drag '%s' to '%s'\n", _lastselect->label(), item->label()); + // Are we dropping above or below the target item? + const int h = Fl::event_y() - item->y(); + const int mid = item->h() / 2; + const bool before = h < mid; + //printf("Dropping %s it\n", before ? "before" : "after"); + + // Do nothing if it would be a no-op + if ((before && prev(item) != _lastselect) || + (!before && next(item) != _lastselect)) { + Fl_Tree_Item *parent = item->parent(); + + if (parent) { + int pos = parent->find_child(item); + if (!before) + pos++; + + // Special case: trying to drop right before a folder + if (item->children() && item->is_open() && !before) { + parent = item; + pos = 0; + } + + // If we're moving inside the same parent, use the below/above methods + if (_lastselect->parent() == parent) { + if (before) { + _lastselect->move_above(item); + } else { + _lastselect->move_below(item); + } + } else { + _lastselect->move_into(parent, pos); + } + + redraw(); + do_callback_for_item(_lastselect, FL_TREE_REASON_DRAGGED); + } + } + } + redraw(); + } // End single-drag check + ret |= 1; + break; } return(ret); } +#if FLTK_ABI_VERSION >= 10303 +// nothing +#else +// Redraw timeout callback +// (Only need this hack for old ABI 10302 and older) +// static void redraw_soon(void *data) { ((Fl_Tree*)data)->redraw(); Fl::remove_timeout(redraw_soon, data); } +#endif + +#if FLTK_ABI_VERSION >= 10303 +/// Recalculate widget dimensions and scrollbar visibility, +/// normally managed automatically. +/// +/// Low overhead way to update the tree widget's outer/inner dimensions +/// and re-determine scrollbar visibility based on these changes without +/// recalculating the entire size of the tree data. +/// +/// Assumes that either the tree's size in _tree_w/_tree_h are correct +/// so that scrollbar visibility can be calculated easily, or are both +/// zero indicating scrollbar visibility can't be calculated yet. +/// +/// This method is called when the widget is resize()ed or if the +/// scrollbar's sizes are changed (affects tree widget's inner dimensions +/// tix/y/w/h), and also used by calc_tree(). +/// \version 1.3.3 ABI feature +/// +void Fl_Tree::calc_dimensions() { + // Calc tree outer xywh + // Area of the tree widget /outside/ scrollbars + // + _tox = x() + Fl::box_dx(box()); + _toy = y() + Fl::box_dy(box()); + _tow = w() - Fl::box_dw(box()); + _toh = h() - Fl::box_dh(box()); + + // Scrollbar visiblity + positions + // Calc this ONLY if tree_h and tree_w have been calculated. + // Zero values for these indicate calc in progress, but not done yet. + // + if ( _tree_h >= 0 && _tree_w >= 0 ) { + int scrollsize = _scrollbar_size ? _scrollbar_size : Fl::scrollbar_size(); + int vshow = _tree_h > _toh ? 1 : 0; + int hshow = _tree_w > _tow ? 1 : 0; + // See if one scroller's appearance affects the other's visibility + if ( hshow && !vshow && (_tree_h > (_toh-scrollsize)) ) vshow = 1; + if ( vshow && !hshow && (_tree_w > (_tow-scrollsize)) ) hshow = 1; + // vertical scrollbar visibility + if ( vshow ) { + _vscroll->show(); + _vscroll->resize(_tox+_tow-scrollsize, _toy, + scrollsize, h()-Fl::box_dh(box()) - (hshow ? scrollsize : 0)); + } else { + _vscroll->hide(); + _vscroll->value(0); + } + // horizontal scrollbar visibility + if ( hshow ) { + _hscroll->show(); + _hscroll->resize(_tox, _toy+_toh-scrollsize, + _tow - (vshow ? scrollsize : 0), scrollsize); + } else { + _hscroll->hide(); + _hscroll->value(0); + } + + // Calculate inner dimensions + // The area the tree occupies inside the scrollbars and margins + // + _tix = _tox; + _tiy = _toy; + _tiw = _tow - (_vscroll->visible() ? _vscroll->w() : 0); + _tih = _toh - (_hscroll->visible() ? _hscroll->h() : 0); + + // Scrollbar tab sizes + _vscroll->slider_size(float(_tih) / float(_tree_h)); + _vscroll->range(0.0, _tree_h - _tih); + + _hscroll->slider_size(float(_tiw) / float(_tree_w)); + _hscroll->range(0.0, _tree_w - _tiw); + } else { + // Best we can do without knowing tree_h/tree_w + _tix = _tox; + _tiy = _toy; + _tiw = _tow; + _tih = _toh; + } +} + +/// Recalculuates the tree's sizes and scrollbar visibility, +/// normally managed automatically. +/// +/// On return: +/// +/// - _tree_w will be the overall pixel width of the entire viewable tree +/// - _tree_h will be the overall pixel height "" +/// - scrollbar visibility and pan sizes are updated +/// - internal _tix/_tiy/_tiw/_tih dimensions are updated +/// +/// _tree_w/_tree_h include the tree's margins (e.g. marginleft()), +/// whether items are open or closed, label contents and font sizes, etc. +/// +/// The tree hierarchy's size is managed separately from the widget's +/// size as an optimization; this way resize() on the widget doesn't +/// involve recalculating the tree's hierarchy needlessly, as widget +/// size has no bearing on the tree hierarchy. +/// +/// The tree hierarchy's size only changes when items are added/removed, +/// open/closed, label contents or font sizes changed, margins changed, etc. +/// +/// This calculation involves walking the *entire* tree from top to bottom, +/// a potentially a slow calculation if the tree has many items (potentially +/// hundreds of thousands), and should therefore be called sparingly. +/// +/// For this reason, recalc_tree() is used as a way to /schedule/ +/// calculation when changes affect the tree hierarchy's size. +/// +/// Apps may want to call this method directly if the app makes changes +/// to the tree's geometry, then immediately needs to work with the tree's +/// new dimensions before an actual redraw (and recalc) occurs. (This +/// use by an app should only rarely be needed) +/// +void Fl_Tree::calc_tree() { + // Set tree width and height to zero, and recalc just _tox/_toy/_tow/_toh for now. + _tree_w = _tree_h = -1; + calc_dimensions(); + if ( !_root ) return; + // Walk the tree to determine its width and height. + // We need this to compute scrollbars.. + // By the end, 'Y' will be the lowest point on the tree + // + int X = _tix + _prefs.marginleft() + _hscroll->value(); + int Y = _tiy + _prefs.margintop() - _vscroll->value(); + int W = _tiw; + // Adjust root's X/W if connectors off + if (_prefs.connectorstyle() == FL_TREE_CONNECTOR_NONE) { + X -= _prefs.openicon()->w(); + W += _prefs.openicon()->w(); + } + int xmax = 0, render = 0, ytop = Y; + fl_font(_prefs.labelfont(), _prefs.labelsize()); + _root->draw(X, Y, W, 0, xmax, 1, render); // descend into tree without drawing (render=0) + // Save computed tree width and height + _tree_w = _prefs.marginleft() + xmax - X; // include margin in tree's width + _tree_h = _prefs.margintop() + Y - ytop; // include margin in tree's height + // Calc tree dims again; now that tree_w/tree_h are known, scrollbars are calculated. + calc_dimensions(); +} +#endif + +void Fl_Tree::resize(int X,int Y,int W, int H) { + fix_scrollbar_order(); + Fl_Group::resize(X,Y,W,H); +#if FLTK_ABI_VERSION >= 10303 + calc_dimensions(); +#endif + init_sizes(); +} + +#if FLTK_ABI_VERSION >= 10303 +/// Standard FLTK draw() method, handles drawing the tree widget. +void Fl_Tree::draw() { + fix_scrollbar_order(); + // Has tree recalc been scheduled? If so, do it + if ( _tree_w == -1 ) calc_tree(); + else calc_dimensions(); + // Let group draw box+label but *NOT* children. + // We handle drawing children ourselves by calling each item's draw() + { + // Draw group's bg + label + if ( damage() & ~FL_DAMAGE_CHILD) { // redraw entire widget? + Fl_Group::draw_box(); + Fl_Group::draw_label(); + } + if ( ! _root ) return; + // These values are changed during drawing + // By end, 'Y' will be the lowest point on the tree + int X = _tix + _prefs.marginleft() - _hscroll->value(); + int Y = _tiy + _prefs.margintop() - _vscroll->value(); + int W = _tiw - X + _tix; + // Adjust root's X/W if connectors off + if (_prefs.connectorstyle() == FL_TREE_CONNECTOR_NONE) { + X -= _prefs.openicon()->w(); + W += _prefs.openicon()->w(); + } + // Draw entire tree, starting with root + fl_push_clip(_tix,_tiy,_tiw,_tih); + { + int xmax = 0; + fl_font(_prefs.labelfont(), _prefs.labelsize()); + _root->draw(X, Y, W, // descend into tree here to draw it + (Fl::focus()==this)?_item_focus:0, // show focus item ONLY if Fl_Tree has focus + xmax, 1, 1); + } + fl_pop_clip(); + } + // Draw scrollbars last + draw_child(*_vscroll); + draw_child(*_hscroll); + // That little tile between the scrollbars + if ( _vscroll->visible() && _hscroll->visible() ) { + fl_color(_vscroll->color()); + fl_rectf(_hscroll->x()+_hscroll->w(), + _vscroll->y()+_vscroll->h(), + _vscroll->w(), + _hscroll->h()); + } + + // Draw dragging line + if (_prefs.selectmode() == FL_TREE_SELECT_SINGLE_DRAGGABLE && + Fl::pushed() == this) { + + Fl_Tree_Item *item = _root->find_clicked(_prefs, 1); // item we're on, vertically + if (item && item != _item_focus) { + // Are we dropping above or before the target item? + const int h = Fl::event_y() - item->y(); + const int mid = item->h() / 2; + const bool before = h < mid; + + fl_color(FL_BLACK); + int tgt; + if (before) { + tgt = item->y(); + } else { + tgt = item->y() + item->h(); + } + fl_line(item->x(), tgt, item->x() + item->w(), tgt); + } + } +} +#else /// Standard FLTK draw() method, handles drawing the tree widget. void Fl_Tree::draw() { int ytoofar = draw_tree(); + // See if we're scrolled below bottom of tree // This can happen if someone just closed a large item. // If so, change scroller as needed. @@ -435,8 +859,32 @@ void Fl_Tree::draw() { } Fl::add_timeout(.10, redraw_soon, (void*)this); // use timer to trigger redraw; we can't } + + // Draw dragging line + if (_prefs.selectmode() == FL_TREE_SELECT_SINGLE_DRAGGABLE && + Fl::pushed() == this) { + + Fl_Tree_Item *item = _root->find_clicked(_prefs); // item we're on, vertically + if (item && item != _item_focus) { + // Are we dropping above or before the target item? + const int h = Fl::event_y() - item->y(); + const int mid = item->h() / 2; + const bool before = h < mid; + + fl_color(FL_BLACK); + + int tgt; + if (before) { + tgt = item->y(); + } else { + tgt = item->y() + item->h(); + } + fl_line(item->x(), tgt, item->x() + item->w(), tgt); + } + } } +// This method is undocumented, and has been removed in ABI 1.3.3 int Fl_Tree::draw_tree() { int ret = 0; fix_scrollbar_order(); @@ -465,7 +913,6 @@ int Fl_Tree::draw_tree() { W += _prefs.openicon()->w(); } int Ysave = Y; - fl_push_clip(cx,cy,cw,ch); { fl_font(_prefs.labelfont(), _prefs.labelsize()); @@ -509,16 +956,19 @@ int Fl_Tree::draw_tree() { draw_child(*_vscroll); // draw scroll last return(ret); } +#endif /// Print the tree as 'ascii art' to stdout. /// Used mainly for debugging. +/// \todo should be const +/// \version 1.3.0 /// void Fl_Tree::show_self() { if ( ! _root ) return; _root->show_self(); } -/// Set the label for the root item. +/// Set the label for the root item to \p 'new_label'. /// /// Makes an internally managed copy of 'new_label'. /// @@ -532,63 +982,132 @@ Fl_Tree_Item* Fl_Tree::root() { return(_root); } -/// Adds a new item, given a 'menu style' path, eg: "/Parent/Child/item". +/// Sets the root item to \p 'newitem'. +/// +/// If a root item already exists, clear() is first to clear it +/// before replacing it with newitem. +/// +#if FLTK_ABI_VERSION >= 10303 +/// Use this to install a custom item (derived from Fl_Tree_Item) as the root +/// of the tree. This allows the derived class to implement custom drawing +/// by overriding Fl_Tree_Item::draw_item_content(). +/// +#endif +/// \version 1.3.3 +/// +void Fl_Tree::root(Fl_Tree_Item *newitem) { + if ( _root ) clear(); + _root = newitem; +} + +/// Adds a new item, given a menu style \p 'path'. /// Any parent nodes that don't already exist are created automatically. /// Adds the item based on the value of sortorder(). +/// If \p 'item' is NULL, a new item is created. /// /// To specify items or submenus that contain slashes ('/' or '\') /// use an escape character to protect them, e.g. -/// /// \code /// tree->add("/Holidays/Photos/12\\/25\\2010"); // Adds item "12/25/2010" /// tree->add("/Pathnames/c:\\\\Program Files\\\\MyApp"); // Adds item "c:\Program Files\MyApp" /// \endcode -/// -/// \returns the child item created, or 0 on error. -/// -Fl_Tree_Item* Fl_Tree::add(const char *path) { - if ( ! _root ) { // Create root if none +/// \param[in] path The path to the item, e.g. "Flintsone/Fred". +/// \param[in] item The new item to be added. +/// If NULL, a new item is created with +/// a name that is the last element in \p 'path'. +/// \returns The new item added, or 0 on error. +/// \version 1.3.3 +/// +Fl_Tree_Item* Fl_Tree::add(const char *path, Fl_Tree_Item *item) { + // Tree has no root? make one + if ( ! _root ) { +#if FLTK_ABI_VERSION >= 10303 + _root = new Fl_Tree_Item(this); +#else _root = new Fl_Tree_Item(_prefs); +#endif _root->parent(0); _root->label("ROOT"); - } + } + // Find parent item via path char **arr = parse_path(path); - Fl_Tree_Item *item = _root->add(_prefs, arr); + item = _root->add(_prefs, arr, item); free_path(arr); return(item); } -/// Add a new child to a specific item in the tree. +#if FLTK_ABI_VERSION >= 10303 +// do nothing here: add(path,item) where item defaults to 0 takes its place +#else +/// Adds a new item given a menu style \p 'path'. +/// Same as calling add(path, NULL); +/// \param[in] path The path to the item to be created, e.g. "Flintsone/Fred". +/// \returns The new item added, or 0 on error. +/// \see add(const char*,Fl_Tree_Item*) +/// \version 1.3.0 release +/// +Fl_Tree_Item* Fl_Tree::add(const char *path) { + return add(path, 0); +} +#endif + +/// Add a new child item labeled \p 'name' to the specified \p 'parent_item'. /// -/// \param[in] item The existing item to add new child to. Must not be NULL. +/// \param[in] parent_item The parent item the new child item will be added to. +/// Must not be NULL. /// \param[in] name The label for the new item -/// \returns the item that was added. +/// \returns The new item added. +/// \version 1.3.0 release /// -Fl_Tree_Item* Fl_Tree::add(Fl_Tree_Item *item, const char *name) { - return(item->add(_prefs, name)); +Fl_Tree_Item* Fl_Tree::add(Fl_Tree_Item *parent_item, const char *name) { + return(parent_item->add(_prefs, name)); } -/// Inserts a new item above the specified Fl_Tree_Item, with the label set to 'name'. +/// Inserts a new item \p 'name' above the specified Fl_Tree_Item \p 'above'. +/// Example: +/// \code +/// tree->add("Aaa/000"); // "000" is index 0 in Aaa's children +/// tree->add("Aaa/111"); // "111" is index 1 in Aaa's children +/// tree->add("Aaa/222"); // "222" is index 2 in Aaa's children +/// .. +/// // How to use insert_above() to insert a new item above Aaa/222 +/// Fl_Tree_Item *item = tree->find_item("Aaa/222"); // get item Aaa/222 +/// if (item) tree->insert_above(item, "New item"); // insert new item above it +/// \endcode +/// /// \param[in] above -- the item above which to insert the new item. Must not be NULL. /// \param[in] name -- the name of the new item -/// \returns the item that was added, or 0 if 'above' could not be found. +/// \returns The new item added, or 0 if 'above' could not be found. +/// \see insert() /// Fl_Tree_Item* Fl_Tree::insert_above(Fl_Tree_Item *above, const char *name) { return(above->insert_above(_prefs, name)); } -/// Insert a new item into a tree-item's children at a specified position. +/// Insert a new item \p 'name' into \p 'item's children at position \p 'pos'. +/// +/// Example: +/// \code +/// tree->add("Aaa/000"); // "000" is index 0 in Aaa's children +/// tree->add("Aaa/111"); // "111" is index 1 in Aaa's children +/// tree->add("Aaa/222"); // "222" is index 2 in Aaa's children +/// .. +/// // How to use insert() to insert a new item between Aaa/111 + Aaa/222 +/// Fl_Tree_Item *item = tree->find_item("Aaa"); // get parent item Aaa +/// if (item) tree->insert(item, "New item", 2); // insert as a child of Aaa at index #2 +/// \endcode /// /// \param[in] item The existing item to insert new child into. Must not be NULL. /// \param[in] name The label for the new item /// \param[in] pos The position of the new item in the child list -/// \returns the item that was added. +/// \returns The new item added. +/// \see insert_above() /// Fl_Tree_Item* Fl_Tree::insert(Fl_Tree_Item *item, const char *name, int pos) { return(item->insert(_prefs, name, pos)); } -/// Remove the specified \p item from the tree. +/// Remove the specified \p 'item' from the tree. /// \p item may not be NULL. /// If it has children, all those are removed too. /// If item being removed has focus, no item will have focus. @@ -607,7 +1126,7 @@ int Fl_Tree::remove(Fl_Tree_Item *item) { return(0); } -/// Clear all children from the tree. +/// Clear the entire tree's children, including the root. /// The tree will be left completely empty. /// void Fl_Tree::clear() { @@ -615,7 +1134,8 @@ void Fl_Tree::clear() { _root->clear_children(); delete _root; _root = 0; } -/// Clear all the children of a particular node in the tree specified by \p item. + +/// Clear all the children for \p 'item'. /// Item may not be NULL. /// void Fl_Tree::clear_children(Fl_Tree_Item *item) { @@ -625,7 +1145,7 @@ void Fl_Tree::clear_children(Fl_Tree_Item *item) { } } -/// Find the item, given a menu style path, eg: "/Parent/Child/item". +/// Find the item, given a menu style path, e.g. "/Parent/Child/item". /// There is both a const and non-const version of this method. /// Const version allows pure const methods to use this method /// to do lookups without causing compiler errors. @@ -639,19 +1159,9 @@ void Fl_Tree::clear_children(Fl_Tree_Item *item) { /// \endcode /// /// \param[in] path -- the tree item's pathname to be found (e.g. "Flintstones/Fred") -/// \returns the item, or NULL if not found. -/// +/// \returns The item, or NULL if not found. /// \see item_pathname() /// -Fl_Tree_Item *Fl_Tree::find_item(const char *path) { - if ( ! _root ) return(NULL); - char **arr = parse_path(path); - Fl_Tree_Item *item = _root->find_item(arr); - free_path(arr); - return(item); -} - -/// A const version of Fl_Tree::find_item(const char *path) const Fl_Tree_Item *Fl_Tree::find_item(const char *path) const { if ( ! _root ) return(NULL); char **arr = parse_path(path); @@ -660,6 +1170,13 @@ const Fl_Tree_Item *Fl_Tree::find_item(const char *path) const { return(item); } +/// Non-const version of Fl_Tree::find_item(const char *path) const +Fl_Tree_Item *Fl_Tree::find_item(const char *path) { + // "Effective C++, 3rd Ed", p.23. Sola fide, Amen. + return(const_cast<Fl_Tree_Item*>( + static_cast<const Fl_Tree&>(*this).find_item(path))); +} + // Handle safe 'reverse string concatenation'. // In the following we build the pathname from right-to-left, // since we start at the child and work our way up to the root. @@ -669,13 +1186,15 @@ const Fl_Tree_Item *Fl_Tree::find_item(const char *path) const { *s-- = c; \ } -/// Find the pathname for the specified \p item. -/// If \p item is NULL, root() is used. -/// The tree's root will be included in the pathname of showroot() is on. +/// Return \p 'pathname' of size \p 'pathnamelen' for the specified \p 'item'. +/// +/// If \p 'item' is NULL, root() is used.<br> +/// The tree's root will be included in the pathname of showroot() is on.<br> /// Menu items or submenus that contain slashes ('/' or '\') in their names /// will be escaped with a backslash. This is symmetrical with the add() /// function which uses the same escape pattern to set names. -/// \param[in] pathname The string to use to return the pathname +/// +/// \param[out] pathname The string to use to return the pathname /// \param[in] pathnamelen The maximum length of the string (including NULL). Must not be zero. /// \param[in] item The item whose pathname is to be returned. /// \returns @@ -712,88 +1231,137 @@ int Fl_Tree::item_pathname(char *pathname, int pathnamelen, const Fl_Tree_Item * return(0); } -/// Find the item that was clicked. +#if FLTK_ABI_VERSION >= 10303 +/// Find the item that was last clicked on. /// You should use callback_item() instead, which is fast, /// and is meant to be used within a callback to determine the item clicked. /// /// This method walks the entire tree looking for the first item that is -/// under the mouse (ie. at Fl::event_x()/Fl:event_y(). +/// under the mouse. (The value of the \p 'yonly' flag affects whether +/// both x and y events are checked, or just y) /// /// Use this method /only/ if you've subclassed Fl_Tree, and are receiving /// events before Fl_Tree has been able to process and update callback_item(). /// -/// \returns the item clicked, or 0 if no item was under the current event. +/// \param[in] yonly -- 0: check both event's X and Y values. +/// -- 1: only check event's Y value, don't care about X. +/// \returns The item clicked, or NULL if no item was under the current event. +/// \version 1.3.0 +/// \version 1.3.3 ABI feature: added yonly parameter +/// +const Fl_Tree_Item* Fl_Tree::find_clicked(int yonly) const { + if ( ! _root ) return(NULL); + return(_root->find_clicked(_prefs, yonly)); +} + +/// Non-const version of Fl_Tree::find_clicked(int yonly) const. +Fl_Tree_Item *Fl_Tree::find_clicked(int yonly) { + // "Effective C++, 3rd Ed", p.23. Sola fide, Amen. + return(const_cast<Fl_Tree_Item*>( + static_cast<const Fl_Tree&>(*this).find_clicked(yonly))); +} +#else +/// Find the item that was last clicked on. +/// You should use callback_item() instead, which is fast, +/// and is meant to be used within a callback to determine the item clicked. +/// +/// This method walks the entire tree looking for the first item that is +/// under the mouse, i.e. at Fl::event_x() / Fl::event_y(). +/// +/// Use this method /only/ if you've subclassed Fl_Tree, and are receiving +/// events before Fl_Tree has been able to process and update callback_item(). +/// +/// \returns The item clicked, or NULL if no item was under the current event. +/// \version 1.3.0 /// const Fl_Tree_Item* Fl_Tree::find_clicked() const { if ( ! _root ) return(NULL); return(_root->find_clicked(_prefs)); } +/// Non-const version of Fl_Tree::find_clicked() const. +/// \version 1.3.0 +Fl_Tree_Item *Fl_Tree::find_clicked() { + // "Effective C++, 3rd Ed", p.23. Sola fide, Amen. + return(const_cast<Fl_Tree_Item*>( + static_cast<const Fl_Tree&>(*this).find_clicked())); +} +#endif + /// Set the item that was last clicked. /// Should only be used by subclasses needing to change this value. /// Normally Fl_Tree manages this value. /// -/// Deprecated: use callback_item() instead. +/// \deprecated in 1.3.3 ABI -- use callback_item() instead. /// -void Fl_Tree::item_clicked(Fl_Tree_Item* val) { - _callback_item = val; +void Fl_Tree::item_clicked(Fl_Tree_Item* item) { + _callback_item = item; } /// Return the item that was last clicked. /// /// Valid only from within the callback(). /// -/// Deprecated: use callback_item() instead. -/// -/// \returns the item clicked, or 0 if none. +/// \returns The item clicked, or 0 if none. /// 0 may also be used to indicate several items were clicked/changed. +/// \deprecated in 1.3.3 ABI -- use callback_item() instead. /// Fl_Tree_Item* Fl_Tree::item_clicked() { return(_callback_item); } -/// Returns next visible item above (dir==Fl_Up) or below (dir==Fl_Down) the specified \p item. -/// If \p item is 0, returns first() if \p dir is Fl_Up, or last() if \p dir is FL_Down. +/// Returns next open(), visible item above (\p dir==FL_Up) +/// or below (\p dir==FL_Down) the specified \p 'item', or 0 if no more items. +/// +/// If \p 'item' is 0, returns first() if \p 'dir' is FL_Up, +/// or last() if \p dir is FL_Down. +/// +/// \code +/// // Walk down the tree (forwards) +/// for ( Fl_Tree_Item *i=tree->first_visible_item(); i; i=tree->next_visible_item(i, FL_Down) ) +/// printf("Item: %s\n", i->label()); /// +/// // Walk up the tree (backwards) +/// for ( Fl_Tree_Item *i=tree->last_visible_item(); i; i=tree->next_visible_item(i, FL_Up) ) +/// printf("Item: %s\n", i->label()); +/// \endcode /// \param[in] item The item above/below which we'll find the next visible item -/// \param[in] dir The direction to search. Can be FL_Up or FL_Down. +/// \param[in] dir The direction to search. Can be FL_Up or FL_Down. /// \returns The item found, or 0 if there's no visible items above/below the specified \p item. +/// \version 1.3.3 /// Fl_Tree_Item *Fl_Tree::next_visible_item(Fl_Tree_Item *item, int dir) { - if ( ! item ) { // no start item? - item = ( dir == FL_Up ) ? last_visible() : // wrap to bottom - first_visible(); // wrap to top - if ( ! item ) return(0); - if ( item->visible_r() ) return(item); // return first/last visible item - } - switch ( dir ) { - case FL_Up: return(item->prev_displayed(_prefs)); - case FL_Down: return(item->next_displayed(_prefs)); - default: return(item->next_displayed(_prefs)); - } + return next_item(item, dir, true); } -/// Returns the first item in the tree. +/// Returns the first item in the tree, or 0 if none. /// -/// Use this to walk the tree in the forward direction, eg: +/// Use this to walk the tree in the forward direction, e.g. /// \code -/// for ( Fl_Tree_Item *item = tree->first(); item; item = tree->next(item) ) { +/// for ( Fl_Tree_Item *item = tree->first(); item; item = tree->next(item) ) /// printf("Item: %s\n", item->label()); -/// } /// \endcode /// -/// \returns first item in tree, or 0 if none (tree empty). -/// \see first(),next(),last(),prev() +/// \returns First item in tree, or 0 if none (tree empty). +/// \see first(), next(), last(), prev() /// Fl_Tree_Item* Fl_Tree::first() { - return(_root); // first item always root + return(_root); // first item always root } -/// Returns the first visible item in the tree. -/// \returns first visible item in tree, or 0 if none. -/// \see first_visible(), last_visible() +/// Returns the first open(), visible item in the tree, or 0 if none. +/// \deprecated in 1.3.3 ABI -- use first_visible_item() instead. /// Fl_Tree_Item* Fl_Tree::first_visible() { + return(first_visible_item()); +} + +/// Returns the first open(), visible item in the tree, or 0 if none. +/// \returns First visible item in tree, or 0 if none. +/// \see first_visible_item(), last_visible_item(), next_visible_item() +/// \version 1.3.3 +/// +Fl_Tree_Item* Fl_Tree::first_visible_item() { Fl_Tree_Item *i = showroot() ? first() : next(first()); while ( i ) { if ( i->visible() ) return(i); @@ -802,39 +1370,36 @@ Fl_Tree_Item* Fl_Tree::first_visible() { return(0); } -/// Return the next item after \p item, or 0 if no more items. +/// Return the next item after \p 'item', or 0 if no more items. /// /// Use this code to walk the entire tree: /// \code -/// for ( Fl_Tree_Item *item = tree->first(); item; item = tree->next(item) ) { -/// printf("Item: %s\n", item->label()); -/// } +/// for ( Fl_Tree_Item *i = tree->first(); i; i = tree->next(i) ) +/// printf("Item: %s\n", i->label()); /// \endcode /// /// \param[in] item The item to use to find the next item. If NULL, returns 0. /// \returns Next item in tree, or 0 if at last item. /// -/// \see first(),next(),last(),prev() +/// \see first(), next(), last(), prev() /// Fl_Tree_Item *Fl_Tree::next(Fl_Tree_Item *item) { if ( ! item ) return(0); return(item->next()); } -/// Return the previous item before \p item, or 0 if no more items. -/// -/// This can be used to walk the tree in reverse, eg: +/// Return the previous item before \p 'item', or 0 if no more items. /// +/// This can be used to walk the tree in reverse, e.g. /// \code -/// for ( Fl_Tree_Item *item = tree->first(); item; item = tree->prev(item) ) { +/// for ( Fl_Tree_Item *item = tree->first(); item; item = tree->prev(item) ) /// printf("Item: %s\n", item->label()); -/// } /// \endcode /// /// \param[in] item The item to use to find the previous item. If NULL, returns 0. /// \returns Previous item in tree, or 0 if at first item. /// -/// \see first(),next(),last(),prev() +/// \see first(), next(), last(), prev() /// Fl_Tree_Item *Fl_Tree::prev(Fl_Tree_Item *item) { if ( ! item ) return(0); @@ -843,17 +1408,15 @@ Fl_Tree_Item *Fl_Tree::prev(Fl_Tree_Item *item) { /// Returns the last item in the tree. /// -/// This can be used to walk the tree in reverse, eg: +/// This can be used to walk the tree in reverse, e.g. /// /// \code -/// for ( Fl_Tree_Item *item = tree->last(); item; item = tree->prev() ) { +/// for ( Fl_Tree_Item *item = tree->last(); item; item = tree->prev() ) /// printf("Item: %s\n", item->label()); -/// } /// \endcode /// -/// \returns last item in the tree, or 0 if none (tree empty). -/// -/// \see first(),next(),last(),prev() +/// \returns Last item in the tree, or 0 if none (tree empty). +/// \see first(), next(), last(), prev() /// Fl_Tree_Item* Fl_Tree::last() { if ( ! _root ) return(0); @@ -864,12 +1427,19 @@ Fl_Tree_Item* Fl_Tree::last() { return(item); } -/// Returns the last visible item in the tree. -/// \returns last visible item in the tree, or 0 if none. -/// -/// \see first_visible(), last_visible() +/// Returns the last open(), visible item in the tree. +/// \deprecated in 1.3.3 -- use last_visible_item() instead. /// Fl_Tree_Item* Fl_Tree::last_visible() { + return(last_visible_item()); +} + +/// Returns the last open(), visible item in the tree. +/// \returns Last visible item in the tree, or 0 if none. +/// \see first_visible_item(), last_visible_item(), next_visible_item() +/// \version 1.3.3 +/// +Fl_Tree_Item* Fl_Tree::last_visible_item() { Fl_Tree_Item *item = last(); while ( item ) { if ( item->visible() ) { @@ -886,48 +1456,216 @@ Fl_Tree_Item* Fl_Tree::last_visible() { /// Returns the first selected item in the tree. /// -/// Use this to walk the tree looking for all the selected items, eg: +/// Use this to walk the tree from top to bottom +/// looking for all the selected items, e.g. /// /// \code -/// for ( Fl_Tree_Item *item = tree->first_selected_item(); item; item = tree->next_selected_item(item) ) { -/// printf("Item: %s\n", item->label()); -/// } +/// // Walk tree forward, from top to bottom +/// for ( Fl_Tree_Item *i=tree->first_selected_item(); i; i=tree->next_selected_item(i) ) +/// printf("Selected item: %s\n", i->label()); /// \endcode /// -/// \returns The next selected item, or 0 if there are no more selected items. +/// \returns The first selected item, or 0 if none. +/// \see first_selected_item(), last_selected_item(), next_selected_item() /// Fl_Tree_Item *Fl_Tree::first_selected_item() { return(next_selected_item(0)); } -/// Returns the next selected item after \p item. +#if FLTK_ABI_VERSION >= 10303 +// nothing +#else +/// Returns the next selected item after \p 'item'. /// If \p item is 0, search starts at the first item (root). /// -/// Use this to walk the tree looking for all the selected items, eg: +/// This is a convenience method; equivalent to next_selected_item(item, FL_Down); +/// +/// Use this to walk the tree forward (downward) looking for all the selected items, e.g. /// \code -/// for ( Fl_Tree_Item *item = tree->first_selected_item(); item; item = tree->next_selected_item(item) ) { -/// printf("Item: %s\n", item->label()); -/// } +/// for ( Fl_Tree_Item *i = tree->first_selected_item(); i; i = tree->next_selected_item(i) ) +/// printf("Selected item: %s\n", i->label()); /// \endcode /// /// \param[in] item The item to use to find the next selected item. If NULL, first() is used. /// \returns The next selected item, or 0 if there are no more selected items. +/// \see first_selected_item(), last_selected_item(), next_selected_item() /// Fl_Tree_Item *Fl_Tree::next_selected_item(Fl_Tree_Item *item) { - if ( ! item ) { - if ( ! (item = first()) ) return(0); - if ( item->is_selected() ) return(item); + return(next_selected_item(item, FL_Down)); +} +#endif + +/// Returns the last selected item in the tree. +/// +/// Use this to walk the tree in reverse from bottom to top +/// looking for all the selected items, e.g. +/// +/// \code +/// // Walk tree in reverse, from bottom to top +/// for ( Fl_Tree_Item *i=tree->last_selected_item(); i; i=tree->next_selected_item(i, FL_Up) ) +/// printf("Selected item: %s\n", i->label()); +/// \endcode +/// +/// \returns The last selected item, or 0 if none. +/// \see first_selected_item(), last_selected_item(), next_selected_item() +/// \version 1.3.3 +/// +Fl_Tree_Item *Fl_Tree::last_selected_item() { + return(next_selected_item(0, FL_Up)); +} + +/// Returns next item after \p 'item' in direction \p 'dir' +/// depending on \p 'visible'. +/// +/// Next item will be above (if dir==FL_Up) or below (if dir==FL_Down). +/// If \p 'visible' is true, only items whose parents are open() will be returned. +/// If \p 'visible' is false, even items whose parents are close()ed will be returned. +/// +/// If \p item is 0, the return value will be the result of this truth table: +/// <PRE> +/// visible=true visible=false +/// ------------------- ------------- +/// dir=Fl_Up: last_visible_item() last() +/// dir=Fl_Down: first_visible_item() first() +/// </PRE> +/// +/// \par Example use: +/// \code +/// // Walk down the tree showing open(), visible items +/// for ( Fl_Tree_Item *i=tree->first_visible_item(); i; i=tree->next_item(i, FL_Down, true) ) +/// printf("Item: %s\n", i->label()); +/// +/// // Walk up the tree showing open(), visible items +/// for ( Fl_Tree_Item *i=tree->last_visible_item(); i; i=tree->next_item(i, FL_Up, true) ) +/// printf("Item: %s\n", i->label()); +/// +/// // Walk down the tree showing all items (open or closed) +/// for ( Fl_Tree_Item *i=tree->first(); i; i=tree->next_item(i, FL_Down, false) ) +/// printf("Item: %s\n", i->label()); +/// +/// // Walk up the tree showing all items (open or closed) +/// for ( Fl_Tree_Item *i=tree->last(); i; i=tree->next_item(i, FL_Up, false) ) +/// printf("Item: %s\n", i->label()); +/// \endcode +/// +/// \param[in] item The item to use to find the next item. If NULL, returns 0. +/// \param[in] dir Can be FL_Up or FL_Down (default=FL_Down or 'next') +/// \param[in] visible true=return only open(), visible items,<br> +/// false=return open or closed items (default) +/// \returns Next item in tree in the direction and visibility specified, +/// or 0 if no more items of specified visibility in that direction. +/// \see first(), last(), next(),<BR> +/// first_visible_item(), last_visible_item(), next_visible_item(),<BR> +/// first_selected_item(), last_selected_item(), next_selected_item() +/// \version 1.3.3 +/// +Fl_Tree_Item *Fl_Tree::next_item(Fl_Tree_Item *item, int dir, bool visible) { + if ( ! item ) { // no start item? + if ( visible ) { + item = ( dir == FL_Up ) ? last_visible_item() : // wrap to bottom + first_visible_item(); // wrap to top + } else { + item = ( dir == FL_Up ) ? last() : // wrap to bottom + first(); // wrap to top + } + if ( ! item ) return(0); + if ( item->visible_r() ) return(item); // return first/last visible item + } + switch (dir) { + case FL_Up: + if ( visible ) return(item->prev_visible(_prefs)); + else return(item->prev()); + case FL_Down: + if ( visible ) return(item->next_visible(_prefs)); + else return(item->next()); + } + return(0); // unknown dir +} + +/// Returns the next selected item above or below \p 'item', depending on \p 'dir'. +/// If \p 'item' is 0, search starts at either first() or last(), depending on \p 'dir': +/// first() if \p 'dir' is FL_Down (default), last() if \p 'dir' is FL_Up. +/// +/// Use this to walk the tree looking for all the selected items, e.g. +/// \code +/// // Walk down the tree (forwards) +/// for ( Fl_Tree_Item *i=tree->first_selected_item(); i; i=tree->next_selected_item(i, FL_Down) ) +/// printf("Item: %s\n", i->label()); +/// +/// // Walk up the tree (backwards) +/// for ( Fl_Tree_Item *i=tree->last_selected_item(); i; i=tree->next_selected_item(i, FL_Up) ) +/// printf("Item: %s\n", i->label()); +/// \endcode +/// +/// \param[in] item The item above or below which we'll find the next selected item. +/// If NULL, first() is used if FL_Down, last() if FL_Up. +/// (default=NULL) +/// \param[in] dir The direction to go. +/// FL_Up for moving up the tree, +/// FL_Down for down the tree (default) +/// \returns The next selected item, or 0 if there are no more selected items. +/// \see first_selected_item(), last_selected_item(), next_selected_item() +/// \version 1.3.3 +/// +Fl_Tree_Item *Fl_Tree::next_selected_item(Fl_Tree_Item *item, int dir) { + switch (dir) { + case FL_Down: + if ( ! item ) { + if ( ! (item = first()) ) return(0); + if ( item->is_selected() ) return(item); + } + while ( (item = item->next()) ) + if ( item->is_selected() ) + return(item); + return(0); + case FL_Up: + if ( ! item ) { + if ( ! (item = last()) ) return(0); + if ( item->is_selected() ) return(item); + } + while ( (item = item->prev()) ) + if ( item->is_selected() ) + return(item); + return(0); } - while ( (item = item->next()) ) - if ( item->is_selected() ) - return(item); return(0); } -/// Open the specified 'item'. -/// This causes the item's children (if any) to be shown. -/// Handles redrawing if anything was actually changed. -/// Invokes the callback depending on the value of optional parameter \p docallback. +#if FLTK_ABI_VERSION >= 10303 /* reason for this: Fl_Tree_Item_Array::manage_item_destroy() */ +/// Returns the currently selected items as an array of \p 'ret_items'. +/// +/// Example: +/// \code +/// // Get selected items as an array +/// Fl_Tree_Item_Array items; +/// tree->get_selected_items(items); +/// // Manipulate the returned array +/// for ( int t=0; t<items.total(); t++ ) { +/// Fl_Tree_Item &item = items[t]; +/// ..do stuff with each selected item.. +/// } +/// \endcode +/// +/// \param[out] ret_items The returned array of selected items. +/// \returns The number of items in the returned array. +/// \see first_selected_item(), next_selected_item() +/// \version 1.3.3 ABI feature +/// +int Fl_Tree::get_selected_items(Fl_Tree_Item_Array &ret_items) { + ret_items.clear(); + for ( Fl_Tree_Item *i=first_selected_item(); i; i=next_selected_item(i) ) { + ret_items.add(i); + } + return ret_items.total(); +} +#endif + +/// Open the specified \p 'item'. +/// +/// This causes the item's children (if any) to be shown.<br> +/// Invokes the callback depending on the value of optional +/// parameter \p 'docallback'.<br> +/// Handles calling redraw() if anything changed. /// /// The callback can use callback_item() and callback_reason() respectively to determine /// the item changed and the reason the callback was called. @@ -935,7 +1673,7 @@ Fl_Tree_Item *Fl_Tree::next_selected_item(Fl_Tree_Item *item) { /// \param[in] item -- the item to be opened. Must not be NULL. /// \param[in] docallback -- A flag that determines if the callback() is invoked or not: /// - 0 - callback() is not invoked -/// - 1 - callback() is invoked if item changed, +/// - 1 - callback() is invoked if item changed, (default) /// callback_reason() will be FL_TREE_REASON_OPENED /// \returns /// - 1 -- item was opened @@ -945,7 +1683,7 @@ Fl_Tree_Item *Fl_Tree::next_selected_item(Fl_Tree_Item *item) { /// int Fl_Tree::open(Fl_Tree_Item *item, int docallback) { if ( item->is_open() ) return(0); - item->open(); + item->open(); // handles recalc_tree() redraw(); if ( docallback ) { do_callback_for_item(item, FL_TREE_REASON_OPENED); @@ -953,10 +1691,12 @@ int Fl_Tree::open(Fl_Tree_Item *item, int docallback) { return(1); } -/// Opens the item specified by \p path (eg: "Parent/child/item"). -/// This causes the item's children (if any) to be shown. -/// Handles redrawing if anything was actually changed. -/// Invokes the callback depending on the value of optional parameter \p docallback. +/// Opens the item specified by \p 'path'. +/// +/// This causes the item's children (if any) to be shown.<br> +/// Invokes the callback depending on the value of optional +/// parameter \p 'docallback'.<br> +/// Handles calling redraw() if anything changed. /// /// Items or submenus that themselves contain slashes ('/' or '\') /// should be escaped, e.g. open("Holidays/12\\/25\//2010"). @@ -967,24 +1707,25 @@ int Fl_Tree::open(Fl_Tree_Item *item, int docallback) { /// \param[in] path -- the tree item's pathname (e.g. "Flintstones/Fred") /// \param[in] docallback -- A flag that determines if the callback() is invoked or not: /// - 0 - callback() is not invoked -/// - 1 - callback() is invoked if item changed, +/// - 1 - callback() is invoked if item changed (default), /// callback_reason() will be FL_TREE_REASON_OPENED /// \returns /// - 1 -- OK: item opened /// - 0 -- OK: item was already open, no change /// - -1 -- ERROR: item was not found -/// /// \see open(), close(), is_open(), is_close(), callback_item(), callback_reason() /// int Fl_Tree::open(const char *path, int docallback) { Fl_Tree_Item *item = find_item(path); if ( ! item ) return(-1); - return(open(item, docallback)); + return(open(item, docallback)); // handles recalc_tree() } -/// Toggle the open state of \p item. -/// Handles redrawing if anything was actually changed. -/// Invokes the callback depending on the value of optional parameter \p docallback. +/// Toggle the open state of \p 'item'. +/// +/// Invokes the callback depending on the value of optional +/// parameter \p 'docallback'.<br> +/// Handles calling redraw() if anything changed. /// /// The callback can use callback_item() and callback_reason() respectively to determine /// the item changed and the reason the callback was called. @@ -992,22 +1733,24 @@ int Fl_Tree::open(const char *path, int docallback) { /// \param[in] item -- the item whose open state is to be toggled. Must not be NULL. /// \param[in] docallback -- A flag that determines if the callback() is invoked or not: /// - 0 - callback() is not invoked -/// - 1 - callback() is invoked, callback_reason() will be either +/// - 1 - callback() is invoked (default), callback_reason() will be either /// FL_TREE_REASON_OPENED or FL_TREE_REASON_CLOSED /// /// \see open(), close(), is_open(), is_close(), callback_item(), callback_reason() /// void Fl_Tree::open_toggle(Fl_Tree_Item *item, int docallback) { if ( item->is_open() ) { - close(item, docallback); + close(item, docallback); // handles recalc_tree() } else { - open(item, docallback); + open(item, docallback); // handles recalc_tree() } } -/// Closes the specified \p item. -/// Handles redrawing if anything was actually changed. -/// Invokes the callback depending on the value of optional parameter \p docallback. +/// Closes the specified \p 'item'. +/// +/// Invokes the callback depending on the value of optional +/// parameter \p 'docallback'.<br> +/// Handles calling redraw() if anything changed. /// /// The callback can use callback_item() and callback_reason() respectively to determine /// the item changed and the reason the callback was called. @@ -1015,17 +1758,16 @@ void Fl_Tree::open_toggle(Fl_Tree_Item *item, int docallback) { /// \param[in] item -- the item to be closed. Must not be NULL. /// \param[in] docallback -- A flag that determines if the callback() is invoked or not: /// - 0 - callback() is not invoked -/// - 1 - callback() is invoked if item changed, +/// - 1 - callback() is invoked if item changed (default), /// callback_reason() will be FL_TREE_REASON_CLOSED /// \returns /// - 1 -- item was closed /// - 0 -- item was already closed, no change -/// /// \see open(), close(), is_open(), is_close(), callback_item(), callback_reason() /// int Fl_Tree::close(Fl_Tree_Item *item, int docallback) { if ( item->is_close() ) return(0); - item->close(); + item->close(); // handles recalc_tree() redraw(); if ( docallback ) { do_callback_for_item(item, FL_TREE_REASON_CLOSED); @@ -1033,9 +1775,11 @@ int Fl_Tree::close(Fl_Tree_Item *item, int docallback) { return(1); } -/// Closes the item specified by \p path, eg: "Parent/child/item". -/// Handles redrawing if anything was actually changed. -/// Invokes the callback depending on the value of optional parameter \p docallback. +/// Closes the item specified by \p 'path'. +/// +/// Invokes the callback depending on the value of optional +/// parameter \p 'docallback'.<br> +/// Handles calling redraw() if anything changed. /// /// Items or submenus that themselves contain slashes ('/' or '\') /// should be escaped, e.g. close("Holidays/12\\/25\//2010"). @@ -1046,22 +1790,21 @@ int Fl_Tree::close(Fl_Tree_Item *item, int docallback) { /// \param[in] path -- the tree item's pathname (e.g. "Flintstones/Fred") /// \param[in] docallback -- A flag that determines if the callback() is invoked or not: /// - 0 - callback() is not invoked -/// - 1 - callback() is invoked if item changed, +/// - 1 - callback() is invoked if item changed (default), /// callback_reason() will be FL_TREE_REASON_CLOSED /// \returns /// - 1 -- OK: item closed /// - 0 -- OK: item was already closed, no change /// - -1 -- ERROR: item was not found -/// /// \see open(), close(), is_open(), is_close(), callback_item(), callback_reason() /// int Fl_Tree::close(const char *path, int docallback) { Fl_Tree_Item *item = find_item(path); if ( ! item ) return(-1); - return(close(item, docallback)); + return(close(item, docallback)); // handles recalc_tree() } -/// See if \p item is open. +/// See if \p 'item' is open. /// /// Items that are 'open' are themselves not necessarily visible; /// one of the item's parents might be closed. @@ -1075,7 +1818,7 @@ int Fl_Tree::is_open(Fl_Tree_Item *item) const { return(item->is_open()?1:0); } -/// See if item specified by \p path (eg: "Parent/child/item") is open. +/// See if item specified by \p 'path' is open. /// /// Items or submenus that themselves contain slashes ('/' or '\') /// should be escaped, e.g. is_open("Holidays/12\\/25\//2010"). @@ -1088,6 +1831,7 @@ int Fl_Tree::is_open(Fl_Tree_Item *item) const { /// - 1 - OK: item is open /// - 0 - OK: item is closed /// - -1 - ERROR: item was not found +/// \see Fl_Tree_Item::visible_r() /// int Fl_Tree::is_open(const char *path) const { const Fl_Tree_Item *item = find_item(path); @@ -1095,7 +1839,7 @@ int Fl_Tree::is_open(const char *path) const { return(item->is_open()?1:0); } -/// See if the specified \p item is closed. +/// See if the specified \p 'item' is closed. /// /// \param[in] item -- the item to be tested. Must not be NULL. /// \returns @@ -1106,7 +1850,7 @@ int Fl_Tree::is_close(Fl_Tree_Item *item) const { return(item->is_close()); } -/// See if item specified by \p path (eg: "Parent/child/item") is closed. +/// See if item specified by \p 'path' is closed. /// /// Items or submenus that themselves contain slashes ('/' or '\') /// should be escaped, e.g. is_close("Holidays/12\\/25\//2010"). @@ -1123,9 +1867,10 @@ int Fl_Tree::is_close(const char *path) const { return(item->is_close()?1:0); } -/// Select the specified \p item. Use 'deselect()' to de-select it. -/// Handles redrawing if anything was actually changed. -/// Invokes the callback depending on the value of optional parameter \p docallback. +/// Select the specified \p 'item'. Use 'deselect()' to de-select it. +/// +/// Invokes the callback depending on the value of optional parameter \p docallback.<br> +/// Handles calling redraw() if anything changed. /// /// The callback can use callback_item() and callback_reason() respectively to determine /// the item changed and the reason the callback was called. @@ -1161,9 +1906,11 @@ int Fl_Tree::select(Fl_Tree_Item *item, int docallback) { return(0); } -/// Select the item specified by \p path (eg: "Parent/child/item"). -/// Handles redrawing if anything was actually changed. -/// Invokes the callback depending on the value of optional parameter \p docallback. +/// Select the item specified by \p 'path'. +/// +/// Invokes the callback depending on the value of optional +/// parameter \p 'docallback'.<br> +/// Handles calling redraw() if anything changed. /// /// Items or submenus that themselves contain slashes ('/' or '\') /// should be escaped, e.g. select("Holidays/12\\/25\//2010"). @@ -1174,7 +1921,7 @@ int Fl_Tree::select(Fl_Tree_Item *item, int docallback) { /// \param[in] path -- the tree item's pathname (e.g. "Flintstones/Fred") /// \param[in] docallback -- A flag that determines if the callback() is invoked or not: /// - 0 - the callback() is not invoked -/// - 1 - the callback() is invoked if item changed state, +/// - 1 - the callback() is invoked if item changed state (default), /// callback_reason() will be FL_TREE_REASON_SELECTED /// \returns /// - 1 : OK: item's state was changed @@ -1187,9 +1934,11 @@ int Fl_Tree::select(const char *path, int docallback) { return(select(item, docallback)); } -/// Toggle the select state of the specified \p item. -/// Handles redrawing if anything was actually changed. -/// Invokes the callback depending on the value of optional parameter \p docallback. +/// Toggle the select state of the specified \p 'item'. +/// +/// Invokes the callback depending on the value of optional +/// parameter \p 'docallback'.<br> +/// Handles calling redraw() if anything changed. /// /// The callback can use callback_item() and callback_reason() respectively to determine /// the item changed and the reason the callback was called. @@ -1197,7 +1946,7 @@ int Fl_Tree::select(const char *path, int docallback) { /// \param[in] item -- the item to be selected. Must not be NULL. /// \param[in] docallback -- A flag that determines if the callback() is invoked or not: /// - 0 - the callback() is not invoked -/// - 1 - the callback() is invoked, callback_reason() will be +/// - 1 - the callback() is invoked (default), callback_reason() will be /// either FL_TREE_REASON_SELECTED or FL_TREE_REASON_DESELECTED /// void Fl_Tree::select_toggle(Fl_Tree_Item *item, int docallback) { @@ -1211,8 +1960,10 @@ void Fl_Tree::select_toggle(Fl_Tree_Item *item, int docallback) { } /// De-select the specified \p item. -/// Handles redrawing if anything was actually changed. -/// Invokes the callback depending on the value of optional parameter \p docallback. +/// +/// Invokes the callback depending on the value of optional +/// parameter \p 'docallback'.<br> +/// Handles calling redraw() if anything changed. /// /// The callback can use callback_item() and callback_reason() respectively to determine /// the item changed and the reason the callback was called. @@ -1220,7 +1971,7 @@ void Fl_Tree::select_toggle(Fl_Tree_Item *item, int docallback) { /// \param[in] item -- the item to be selected. Must not be NULL. /// \param[in] docallback -- A flag that determines if the callback() is invoked or not: /// - 0 - the callback() is not invoked -/// - 1 - the callback() is invoked if item changed state, +/// - 1 - the callback() is invoked if item changed state (default), /// callback_reason() will be FL_TREE_REASON_DESELECTED /// \returns /// - 0 - item was already deselected, no change was made @@ -1239,9 +1990,11 @@ int Fl_Tree::deselect(Fl_Tree_Item *item, int docallback) { return(0); } -/// Deselect an item specified by \p path (eg: "Parent/child/item"). -/// Handles redrawing if anything was actually changed. -/// Invokes the callback depending on the value of optional parameter \p docallback. +/// Deselect an item specified by \p 'path'. +/// +/// Invokes the callback depending on the value of optional +/// parameter \p 'docallback'.<br> +/// Handles calling redraw() if anything changed. /// /// Items or submenus that themselves contain slashes ('/' or '\') /// should be escaped, e.g. deselect("Holidays/12\\/25\//2010"). @@ -1252,7 +2005,7 @@ int Fl_Tree::deselect(Fl_Tree_Item *item, int docallback) { /// \param[in] path -- the tree item's pathname (e.g. "Flintstones/Fred") /// \param[in] docallback -- A flag that determines if the callback() is invoked or not: /// - 0 - the callback() is not invoked -/// - 1 - the callback() is invoked if item changed state, +/// - 1 - the callback() is invoked if item changed state (default), /// callback_reason() will be FL_TREE_REASON_DESELECTED /// \returns /// - 1 - OK: item's state was changed @@ -1265,10 +2018,12 @@ int Fl_Tree::deselect(const char *path, int docallback) { return(deselect(item, docallback)); } -/// Deselect \p item and all its children. -/// If item is NULL, first() is used. -/// Handles calling redraw() if anything was changed. -/// Invokes the callback depending on the value of optional parameter \p docallback. +/// Deselect \p 'item' and all its children. +/// +/// If item is NULL, first() is used.<br> +/// Invokes the callback depending on the value of optional +/// parameter \p 'docallback'.<br> +/// Handles calling redraw() if anything changed. /// /// The callback can use callback_item() and callback_reason() respectively to determine /// the item changed and the reason the callback was called. @@ -1277,10 +2032,9 @@ int Fl_Tree::deselect(const char *path, int docallback) { /// If NULL, first() is used. /// \param[in] docallback -- A flag that determines if the callback() is invoked or not: /// - 0 - the callback() is not invoked -/// - 1 - the callback() is invoked for each item that changed state, +/// - 1 - the callback() is invoked for each item that changed state (default), /// callback_reason() will be FL_TREE_REASON_DESELECTED -/// -/// \returns count of how many items were actually changed to the deselected state. +/// \returns Count of how many items were actually changed to the deselected state. /// int Fl_Tree::deselect_all(Fl_Tree_Item *item, int docallback) { item = item ? item : first(); // NULL? use first() @@ -1297,10 +2051,12 @@ int Fl_Tree::deselect_all(Fl_Tree_Item *item, int docallback) { return(count); } -/// Select only the specified \p item, deselecting all others that might be selected. -/// If item is 0, first() is used. -/// Handles calling redraw() if anything was changed. -/// Invokes the callback depending on the value of optional parameter \p docallback. +/// Select only the specified \p 'item', deselecting all others that might be selected. +/// +/// If item is 0, first() is used.<br> +/// Invokes the callback depending on the value of optional +/// parameter \p 'docallback'.<br> +/// Handles calling redraw() if anything changed. /// /// The callback can use callback_item() and callback_reason() respectively to determine /// the item changed and the reason the callback was called. @@ -1308,45 +2064,51 @@ int Fl_Tree::deselect_all(Fl_Tree_Item *item, int docallback) { /// \param[in] selitem The item to be selected. If NULL, first() is used. /// \param[in] docallback -- A flag that determines if the callback() is invoked or not: /// - 0 - the callback() is not invoked -/// - 1 - the callback() is invoked for each item that changed state, +/// - 1 - the callback() is invoked for each item that changed state (default), /// callback_reason() will be either FL_TREE_REASON_SELECTED or /// FL_TREE_REASON_DESELECTED -/// \returns the number of items whose selection states were changed, if any. +/// \returns The number of items whose selection states were changed, if any. /// int Fl_Tree::select_only(Fl_Tree_Item *selitem, int docallback) { selitem = selitem ? selitem : first(); // NULL? use first() if ( ! selitem ) return(0); int changed = 0; + // Deselect everything first. + // Prevents callbacks from seeing more than one item selected. + // for ( Fl_Tree_Item *item = first(); item; item = item->next() ) { - if ( item == selitem ) { -#if FLTK_ABI_VERSION >= 10301 - // NEW - if ( item->is_selected() ) { // already selected? - if ( item_reselect_mode() == FL_TREE_SELECTABLE_ALWAYS ) { - select(item, docallback); // handles callback with reason==reselect - } - continue; // leave 'changed' unmodified (nothing changed) - } -#else - // OLD - if ( item->is_selected() ) continue; // don't count if already selected -#endif - select(item, docallback); + if ( item == selitem ) continue; // don't do anything to selitem yet.. + if ( item->is_selected() ) { + deselect(item, docallback); ++changed; - } else { - if ( item->is_selected() ) { - deselect(item, docallback); - ++changed; - } } } +#if FLTK_ABI_VERSION >= 10301 + // Should we 'reselect' item if already selected? + if ( selitem->is_selected() && (item_reselect_mode()==FL_TREE_SELECTABLE_ALWAYS) ) { + // Selection unchanged, so no ++change + select(selitem, docallback); // do callback with reason=reselect + } else if ( !selitem->is_selected() ) { + // Item was not already selected, select and indicate changed + select(selitem, docallback); + ++changed; + } +#else + if ( !selitem->is_selected() ) { + // All items deselected, now select the one we want + select(selitem, docallback); + ++changed; + } +#endif return(changed); } -/// Select \p item and all its children. -/// If item is NULL, first() is used. -/// Handles calling redraw() if anything was changed. -/// Invokes the callback depending on the value of optional parameter \p docallback. +/// Select \p 'item' and all its children. +/// +/// If item is NULL, first() is used.<br> +/// Invokes the callback depending on the value of optional +/// parameter \p 'docallback'.<br> +/// Handles calling redraw() if anything changed. /// /// The callback can use callback_item() and callback_reason() respectively to determine /// the item changed and the reason the callback was called. @@ -1355,9 +2117,9 @@ int Fl_Tree::select_only(Fl_Tree_Item *selitem, int docallback) { /// If NULL, first() is used. /// \param[in] docallback -- A flag that determines if the callback() is invoked or not: /// - 0 - the callback() is not invoked -/// - 1 - the callback() is invoked for each item that changed state, +/// - 1 - the callback() is invoked for each item that changed state (default), /// callback_reason() will be FL_TREE_REASON_SELECTED -/// \returns count of how many items were actually changed to the selected state. +/// \returns Count of how many items were actually changed to the selected state. /// int Fl_Tree::select_all(Fl_Tree_Item *item, int docallback) { item = item ? item : first(); // NULL? use first() @@ -1380,6 +2142,7 @@ Fl_Tree_Item* Fl_Tree::get_item_focus() const { } /// Set the item that currently should have keyboard focus. +/// /// Handles calling redraw() to update the focus box (if it is visible). /// /// \param[in] item The item that should take focus. If NULL, none will have focus. @@ -1391,7 +2154,7 @@ void Fl_Tree::set_item_focus(Fl_Tree_Item *item) { } } -/// See if the specified \p item is selected. +/// See if the specified \p 'item' is selected. /// /// \param[in] item -- the item to be tested. Must not be NULL. /// @@ -1403,7 +2166,7 @@ int Fl_Tree::is_selected(Fl_Tree_Item *item) const { return(item->is_selected()?1:0); } -/// See if item specified by \p path (eg: "Parent/child/item") is selected. +/// See if item specified by \p 'path' is selected. /// /// Items or submenus that themselves contain slashes ('/' or '\') /// should be escaped, e.g. is_selected("Holidays/12\\/25\//2010"). @@ -1493,6 +2256,7 @@ int Fl_Tree::marginleft() const { void Fl_Tree::marginleft(int val) { _prefs.marginleft(val); redraw(); + recalc_tree(); } /// Get the amount of white space (in pixels) that should appear @@ -1508,6 +2272,7 @@ int Fl_Tree::margintop() const { void Fl_Tree::margintop(int val) { _prefs.margintop(val); redraw(); + recalc_tree(); } #if FLTK_ABI_VERSION >= 10301 @@ -1524,6 +2289,7 @@ int Fl_Tree::marginbottom() const { void Fl_Tree::marginbottom(int val) { _prefs.marginbottom(val); redraw(); + recalc_tree(); } #endif /*FLTK_ABI_VERSION*/ @@ -1540,6 +2306,7 @@ int Fl_Tree::linespacing() const { void Fl_Tree::linespacing(int val) { _prefs.linespacing(val); redraw(); + recalc_tree(); } /// Get the amount of white space (in pixels) that should appear @@ -1555,40 +2322,50 @@ int Fl_Tree::openchild_marginbottom() const { void Fl_Tree::openchild_marginbottom(int val) { _prefs.openchild_marginbottom(val); redraw(); + recalc_tree(); } + /// Get the amount of white space (in pixels) that should appear /// to the left of the usericon. int Fl_Tree::usericonmarginleft() const { return(_prefs.usericonmarginleft()); } + /// Set the amount of white space (in pixels) that should appear /// to the left of the usericon. void Fl_Tree::usericonmarginleft(int val) { _prefs.usericonmarginleft(val); redraw(); + recalc_tree(); } + /// Get the amount of white space (in pixels) that should appear /// to the left of the label text. int Fl_Tree::labelmarginleft() const { return(_prefs.labelmarginleft()); } + /// Set the amount of white space (in pixels) that should appear /// to the left of the label text. void Fl_Tree::labelmarginleft(int val) { _prefs.labelmarginleft(val); redraw(); + recalc_tree(); } + #if FLTK_ABI_VERSION >= 10301 /// Get the amount of white space (in pixels) that should appear /// to the left of the child fltk widget (if any). int Fl_Tree::widgetmarginleft() const { return(_prefs.widgetmarginleft()); } + /// Set the amount of white space (in pixels) that should appear /// to the left of the child fltk widget (if any). void Fl_Tree::widgetmarginleft(int val) { _prefs.widgetmarginleft(val); redraw(); + recalc_tree(); } #endif /*FLTK_ABI_VERSION*/ @@ -1605,6 +2382,7 @@ int Fl_Tree::connectorwidth() const { void Fl_Tree::connectorwidth(int val) { _prefs.connectorwidth(val); redraw(); + recalc_tree(); } /// Returns the Fl_Image being used as the default user icon for all @@ -1627,6 +2405,7 @@ Fl_Image* Fl_Tree::usericon() const { void Fl_Tree::usericon(Fl_Image *val) { _prefs.usericon(val); redraw(); + recalc_tree(); } /// Returns the icon to be used as the 'open' icon. @@ -1645,6 +2424,7 @@ Fl_Image* Fl_Tree::openicon() const { void Fl_Tree::openicon(Fl_Image *val) { _prefs.openicon(val); redraw(); + recalc_tree(); } /// Returns the icon to be used as the 'close' icon. @@ -1663,6 +2443,7 @@ Fl_Image* Fl_Tree::closeicon() const { void Fl_Tree::closeicon(Fl_Image *val) { _prefs.closeicon(val); redraw(); + recalc_tree(); } /// Returns 1 if the collapse icon is enabled, 0 if not. @@ -1681,6 +2462,7 @@ int Fl_Tree::showcollapse() const { void Fl_Tree::showcollapse(int val) { _prefs.showcollapse(val); redraw(); + recalc_tree(); } /// Returns 1 if the root item is to be shown, or 0 if not. @@ -1695,6 +2477,7 @@ int Fl_Tree::showroot() const { void Fl_Tree::showroot(int val) { _prefs.showroot(val); redraw(); + recalc_tree(); } /// Returns the line drawing style for inter-connecting items. @@ -1703,13 +2486,15 @@ Fl_Tree_Connector Fl_Tree::connectorstyle() const { } /// Sets the line drawing style for inter-connecting items. +/// See ::Fl_Tree_Connector for possible values. +/// void Fl_Tree::connectorstyle(Fl_Tree_Connector val) { _prefs.connectorstyle(val); redraw(); } /// Set the default sort order used when items are added to the tree. -/// See Fl_Tree_Sort for possible values. +/// See ::Fl_Tree_Sort for possible values. /// Fl_Tree_Sort Fl_Tree::sortorder() const { return(_prefs.sortorder()); @@ -1722,7 +2507,7 @@ void Fl_Tree::sortorder(Fl_Tree_Sort val) { } /// Sets the style of box used to draw selected items. -/// This is an fltk Fl_Boxtype. +/// This is an fltk ::Fl_Boxtype. /// The default is influenced by FLTK's current Fl::scheme() /// Fl_Boxtype Fl_Tree::selectbox() const { @@ -1730,7 +2515,7 @@ Fl_Boxtype Fl_Tree::selectbox() const { } /// Gets the style of box used to draw selected items. -/// This is an fltk Fl_Boxtype. +/// This is an fltk ::Fl_Boxtype. /// The default is influenced by FLTK's current Fl::scheme() /// void Fl_Tree::selectbox(Fl_Boxtype val) { @@ -1744,44 +2529,64 @@ Fl_Tree_Select Fl_Tree::selectmode() const { } /// Sets the tree's selection mode. +/// See ::Fl_Tree_Select for possible values. +/// void Fl_Tree::selectmode(Fl_Tree_Select val) { _prefs.selectmode(val); } #if FLTK_ABI_VERSION >= 10301 -/// Returns the current item re/selection mode +/// Returns the current item re/selection mode. +/// \version 1.3.1 ABI feature +/// Fl_Tree_Item_Reselect_Mode Fl_Tree::item_reselect_mode() const { return(_prefs.item_reselect_mode()); } /// Sets the item re/selection mode +/// See ::Fl_Tree_Item_Reselect_Mode for possible values. +/// \version 1.3.1 ABI feature +/// void Fl_Tree::item_reselect_mode(Fl_Tree_Item_Reselect_Mode mode) { _prefs.item_reselect_mode(mode); } /// Get the 'item draw mode' used for the tree +/// \version 1.3.1 ABI feature +/// Fl_Tree_Item_Draw_Mode Fl_Tree::item_draw_mode() const { return(_prefs.item_draw_mode()); } -/// Set the 'item draw mode' used for the tree to \p val. -/// This affects how items in the tree are drawn, -/// such as when a widget() is defined. -/// See Fl_Tree_Item_Draw_Mode for possible values. +/// Set the 'item draw mode' used for the tree to \p 'mode'. +/// +/// This affects how items in the tree are drawn, +/// such as when a widget() is defined. +/// See ::Fl_Tree_Item_Draw_Mode for possible values. +/// \version 1.3.1 ABI feature /// -void Fl_Tree::item_draw_mode(Fl_Tree_Item_Draw_Mode val) { - _prefs.item_draw_mode(val); +void Fl_Tree::item_draw_mode(Fl_Tree_Item_Draw_Mode mode) { + _prefs.item_draw_mode(mode); } -void Fl_Tree::item_draw_mode(int val) { - _prefs.item_draw_mode(Fl_Tree_Item_Draw_Mode(val)); + +/// Set the 'item draw mode' used for the tree to integer \p 'mode'. +/// +/// This affects how items in the tree are drawn, +/// such as when a widget() is defined. +/// See ::Fl_Tree_Item_Draw_Mode for possible values. +/// \version 1.3.1 ABI feature +/// +void Fl_Tree::item_draw_mode(int mode) { + _prefs.item_draw_mode(Fl_Tree_Item_Draw_Mode(mode)); } -#endif /*FLTK_ABI_VERSION*/ +#endif -/// See if \p item is currently displayed on-screen (visible within the widget). +/// See if \p 'item' is currently displayed on-screen (visible within the widget). +/// /// This can be used to detect if the item is scrolled off-screen. /// Checks to see if the item's vertical position is within the top and bottom -/// edges of the display window. This does NOT take into account the hide()/show() -/// or open()/close() status of the item. +/// edges of the display window. This does NOT take into account the hide() / show() +/// or open() / close() status of the item. /// /// \param[in] item The item to be checked. If NULL, first() is used. /// \returns 1 if displayed, 0 if scrolled off screen or no items are in tree. @@ -1792,8 +2597,8 @@ int Fl_Tree::displayed(Fl_Tree_Item *item) { return( (item->y() >= y()) && (item->y() <= (y()+h()-item->h())) ? 1 : 0); } -/// Adjust the vertical scroll bar so that \p item is visible -/// \p yoff pixels from the top of the Fl_Tree widget's display. +/// Adjust the vertical scroll bar so that \p 'item' is visible +/// \p 'yoff' pixels from the top of the Fl_Tree widget's display. /// /// For instance, yoff=0 will position the item at the top. /// @@ -1816,7 +2621,7 @@ void Fl_Tree::show_item(Fl_Tree_Item *item, int yoff) { redraw(); } -/// Adjust the vertical scroll bar to show \p item at the top +/// Adjust the vertical scroll bar to show \p 'item' at the top /// of the display IF it is currently off-screen (e.g. show_item_top()). /// If it is already on-screen, no change is made. /// @@ -1831,7 +2636,7 @@ void Fl_Tree::show_item(Fl_Tree_Item *item) { show_item_top(item); } -/// Adjust the vertical scrollbar so that \p item is at the top of the display. +/// Adjust the vertical scrollbar so that \p 'item' is at the top of the display. /// /// \param[in] item The item to be shown. If NULL, first() is used. /// @@ -1840,25 +2645,33 @@ void Fl_Tree::show_item_top(Fl_Tree_Item *item) { if (item) show_item(item, 0); } -/// Adjust the vertical scrollbar so that \p item is in the middle of the display. +/// Adjust the vertical scrollbar so that \p 'item' is in the middle of the display. /// /// \param[in] item The item to be shown. If NULL, first() is used. /// void Fl_Tree::show_item_middle(Fl_Tree_Item *item) { item = item ? item : first(); +#if FLTK_ABI_VERSION >= 10303 + if (item) show_item(item, (_tih/2)-(item->h()/2)); +#else if (item) show_item(item, (h()/2)-(item->h()/2)); +#endif } -/// Adjust the vertical scrollbar so that \p item is at the bottom of the display. +/// Adjust the vertical scrollbar so that \p 'item' is at the bottom of the display. /// /// \param[in] item The item to be shown. If NULL, first() is used. /// void Fl_Tree::show_item_bottom(Fl_Tree_Item *item) { item = item ? item : first(); +#if FLTK_ABI_VERSION >= 10303 + if (item) show_item(item, _tih-item->h()); +#else if (item) show_item(item, h()-item->h()); +#endif } -/// Displays \p item, scrolling the tree as necessary. +/// Displays \p 'item', scrolling the tree as necessary. /// \param[in] item The item to be displayed. If NULL, first() is used. /// void Fl_Tree::display(Fl_Tree_Item *item) { @@ -1868,19 +2681,17 @@ void Fl_Tree::display(Fl_Tree_Item *item) { /// Returns the vertical scroll position as a pixel offset. /// The position returned is how many pixels of the tree are scrolled off the top edge -/// of the screen. Example: A position of '3' indicates the top 3 pixels of -/// the tree are scrolled off the top edge of the screen. +/// of the screen. /// \see vposition(), hposition() /// int Fl_Tree::vposition() const { return((int)_vscroll->value()); } -/// Sets the vertical scroll offset to position \p pos. -/// The position is how many pixels of the tree are scrolled off the top edge -/// of the screen. Example: A position of '3' scrolls the top three pixels of -/// the tree off the top edge of the screen. -/// \param[in] pos The vertical position (in pixels) to scroll the browser to. +/// Sets the vertical scroll offset to position \p 'pos'. +/// The position is how many pixels of the tree are scrolled off the top edge +/// of the screen. +/// \param[in] pos The vertical position (in pixels) to scroll the browser to. /// void Fl_Tree::vposition(int pos) { if (pos < 0) pos = 0; @@ -1890,7 +2701,37 @@ void Fl_Tree::vposition(int pos) { redraw(); } -/// See if widget \p w is one of the Fl_Tree widget's scrollbars. +/// Returns the horizontal scroll position as a pixel offset. +/// The position returned is how many pixels of the tree are scrolled off the left edge +/// of the screen. +/// \see vposition(), hposition() +/// \note Must be using FLTK ABI 1.3.3 or higher for this to be effective. +/// +int Fl_Tree::hposition() const { +#if FLTK_ABI_VERSION >= 10303 + return((int)_hscroll->value()); +#else + return(0); +#endif +} + +/// Sets the horizontal scroll offset to position \p 'pos'. +/// The position is how many pixels of the tree are scrolled off the left edge +/// of the screen. +/// \param[in] pos The vertical position (in pixels) to scroll the browser to. +/// \note Must be using FLTK ABI 1.3.3 or higher for this to be effective. +/// +void Fl_Tree::hposition(int pos) { +#if FLTK_ABI_VERSION >= 10303 + if (pos < 0) pos = 0; + if (pos > _hscroll->maximum()) pos = (int)_hscroll->maximum(); + if (pos == _hscroll->value()) return; + _hscroll->value(pos); + redraw(); +#endif +} + +/// See if widget \p 'w' is one of the Fl_Tree widget's scrollbars. /// Use this to skip over the scrollbars when walking the child() array. Example: /// \code /// for ( int i=0; i<tree->children(); i++ ) { // walk children @@ -1901,12 +2742,18 @@ void Fl_Tree::vposition(int pos) { /// \endcode /// \param[in] w Widget to test /// \returns 1 if \p w is a scrollbar, 0 if not. +/// \todo should be const /// int Fl_Tree::is_scrollbar(Fl_Widget *w) { - return( ( w == _vscroll ) ? 1 : 0 ); +#if FLTK_ABI_VERSION >= 10303 + return( (w==_vscroll || w==_hscroll) ? 1 : 0 ); +#else + return( (w==_vscroll) ? 1 : 0 ); +#endif } -/// Gets the current size of the scrollbars' troughs, in pixels. +/// Gets the default size of scrollbars' troughs for this widget +/// in pixels. /// /// If this value is zero (default), this widget will use the global /// Fl::scrollbar_size() value as the scrollbar's width. @@ -1918,16 +2765,17 @@ int Fl_Tree::scrollbar_size() const { return(_scrollbar_size); } -/// Sets the pixel size of the scrollbars' troughs to the \p size, in pixels. +/// Sets the pixel size of the scrollbars' troughs to \p 'size' +/// for this widget, in pixels. /// /// Normally you should not need this method, and should use the global /// Fl::scrollbar_size(int) instead to manage the size of ALL /// your widgets' scrollbars. This ensures your application -/// has a consistent UI, is the default behavior, and is normally -/// what you want. +/// has a consistent UI, and is the default behavior. Normally +/// this is what you want. /// -/// Only use THIS method if you really need to override the global -/// scrollbar size. The need for this should be rare. +/// Only use this method if you really need to override just THIS +/// instance of the widget's scrollbar size. (This need should be rare.) /// /// Setting \p size to the special value of 0 causes the widget to /// track the global Fl::scrollbar_size(), which is the default. @@ -1942,15 +2790,37 @@ void Fl_Tree::scrollbar_size(int size) { if ( _vscroll->w() != scrollsize ) { _vscroll->resize(x()+w()-scrollsize, h(), scrollsize, _vscroll->h()); } +#if FLTK_ABI_VERSION >= 10303 + if ( _hscroll->h() != scrollsize ) { + _hscroll->resize(x(), y()+h()-scrollsize, _hscroll->w(), scrollsize); + } + // Changing scrollbar size affects _tiw/_tih + may affect scrollbar visibility + calc_dimensions(); +#endif } /// See if the vertical scrollbar is currently visible. /// \returns 1 if scrollbar visible, 0 if not. +/// int Fl_Tree::is_vscroll_visible() const { return(_vscroll->visible() ? 1 : 0); } -/// Do the callback for the item, setting the item and reason +/// See if the horizontal scrollbar is currently visible. +/// \returns 1 if scrollbar visible, 0 if not. +/// \note Must be using FLTK ABI 1.3.3 or higher for this to be effective. +/// +int Fl_Tree::is_hscroll_visible() const { +#if FLTK_ABI_VERSION >= 10303 + return(_hscroll->visible() ? 1 : 0); +#else + return 0; +#endif +} + +/// Do the callback for the specified \p 'item' using \p 'reason', +/// setting the callback_item() and callback_reason(). +/// void Fl_Tree::do_callback_for_item(Fl_Tree_Item* item, Fl_Tree_Reason reason) { callback_reason(reason); callback_item(item); @@ -1958,7 +2828,7 @@ void Fl_Tree::do_callback_for_item(Fl_Tree_Item* item, Fl_Tree_Reason reason) { } /// Sets the item that was changed for this callback. -/// Used internally to pass the item that invoked the callback. +/// Used internally to pass the item that invoked the callback. /// void Fl_Tree::callback_item(Fl_Tree_Item* item) { _callback_item = item; @@ -2007,8 +2877,7 @@ Fl_Tree_Reason Fl_Tree::callback_reason() const { * directly loaded into the tree view for inspection. * \param[in] prefs the Fl_Preferences database */ -void Fl_Tree::load(Fl_Preferences &prefs) -{ +void Fl_Tree::load(Fl_Preferences &prefs) { int i, j, n, pn = (int) strlen(prefs.path()); char *p; const char *path = prefs.path(); @@ -2056,13 +2925,30 @@ void Fl_Tree::fix_scrollbar_order() { Fl_Widget** a = (Fl_Widget**)array(); if (a[children()-1] != _vscroll) { int i,j; +#if FLTK_ABI_VERSION >= 10303 + for (i = j = 0; j < children(); j++) { + if (a[j] != _vscroll && a[j] != _hscroll ) a[i++] = a[j]; + } + a[i++] = _hscroll; + a[i++] = _vscroll; +#else for (i = j = 0; j < children(); j++) { if (a[j] != _vscroll) a[i++] = a[j]; } a[i++] = _vscroll; +#endif } } +/// Schedule tree to recalc the entire tree size. +/// \note Must be using FLTK ABI 1.3.3 or higher for this to be effective. +/// +void Fl_Tree::recalc_tree() { +#if FLTK_ABI_VERSION >= 10303 + _tree_w = _tree_h = -1; +#endif +} + // -// End of "$Id: Fl_Tree.cxx 9706 2012-11-06 20:46:14Z matt $". +// End of "$Id: Fl_Tree.cxx 10275 2014-09-05 12:04:28Z cand $". // diff --git a/src/Fl_Tree_Item.cxx b/src/Fl_Tree_Item.cxx index 81cb47b..d08494e 100644 --- a/src/Fl_Tree_Item.cxx +++ b/src/Fl_Tree_Item.cxx @@ -1,5 +1,5 @@ // -// "$Id: Fl_Tree_Item.cxx 9706 2012-11-06 20:46:14Z matt $" +// "$Id: Fl_Tree_Item.cxx 10272 2014-09-05 02:59:00Z greg.ercolano $" // #include <stdio.h> @@ -35,9 +35,22 @@ static int event_inside(const int xywh[4]) { } /// Constructor. -/// Makes a new instance of Fl_Tree_Item using defaults from 'prefs'. +/// Makes a new instance of Fl_Tree_Item using defaults from \p 'prefs'. +#if FLTK_ABI_VERSION >= 10303 +/// \deprecated in 1.3.3 ABI -- you must use Fl_Tree_Item(Fl_Tree*) for proper horizontal scrollbar behavior. +#endif /// Fl_Tree_Item::Fl_Tree_Item(const Fl_Tree_Prefs &prefs) { + _Init(prefs, 0); +} + +// Initialize the tree item +// Used by constructors +// +void Fl_Tree_Item::_Init(const Fl_Tree_Prefs &prefs, Fl_Tree *tree) { +#if FLTK_ABI_VERSION >= 10303 + _tree = tree; +#endif _label = 0; _labelfont = prefs.labelfont(); _labelsize = prefs.labelsize(); @@ -67,12 +80,29 @@ Fl_Tree_Item::Fl_Tree_Item(const Fl_Tree_Prefs &prefs) { _usericon = 0; _userdata = 0; _parent = 0; +#if FLTK_ABI_VERSION >= 10303 + _children.manage_item_destroy(1); // let array's dtor manage destroying Fl_Tree_Items +#endif #if FLTK_ABI_VERSION >= 10301 _prev_sibling = 0; _next_sibling = 0; #endif /*FLTK_ABI_VERSION*/ } +#if FLTK_ABI_VERSION >= 10303 +/// Constructor. +/// Makes a new instance of Fl_Tree_Item for \p 'tree'. +/// +/// This must be used instead of the older, deprecated Fl_Tree_Item(Fl_Tree_Prefs) +/// constructor for proper horizontal scrollbar calculation. +/// +/// \version 1.3.3 ABI feature +/// +Fl_Tree_Item::Fl_Tree_Item(Fl_Tree *tree) { + _Init(tree->_prefs, tree); +} +#endif + // DTOR Fl_Tree_Item::~Fl_Tree_Item() { if ( _label ) { @@ -86,6 +116,9 @@ Fl_Tree_Item::~Fl_Tree_Item() { /// Copy constructor. Fl_Tree_Item::Fl_Tree_Item(const Fl_Tree_Item *o) { +#if FLTK_ABI_VERSION >= 10303 + _tree = o->_tree; +#endif _label = o->label() ? strdup(o->label()) : 0; _labelfont = o->labelfont(); _labelsize = o->labelsize(); @@ -125,31 +158,34 @@ Fl_Tree_Item::Fl_Tree_Item(const Fl_Tree_Item *o) { /// Used mainly for debugging. /// void Fl_Tree_Item::show_self(const char *indent) const { - if ( label() ) { + const char *thelabel = label() ? label() : "(NULL)"; #if FLTK_ABI_VERSION >= 10301 - printf("%s-%s (%d children, this=%p, parent=%p, prev=%p, next=%p, depth=%d)\n", - indent,label(),children(),(void*)this, (void*)_parent, - _prev_sibling, _next_sibling, depth()); + printf("%s-%s (%d children, this=%p, parent=%p, prev=%p, next=%p, depth=%d)\n", + indent,thelabel,children(),(void*)this, (void*)_parent, + _prev_sibling, _next_sibling, depth()); #else /*FLTK_ABI_VERSION*/ - printf("%s-%s (%d children, this=%p, parent=%p depth=%d)\n", - indent,label(),children(),(void*)this, (void*)_parent, depth()); + printf("%s-%s (%d children, this=%p, parent=%p depth=%d)\n", + indent,thelabel,children(),(void*)this, (void*)_parent, depth()); #endif /*FLTK_ABI_VERSION*/ - } if ( children() ) { - char *i2 = (char*)malloc(strlen(indent) + 2); + char *i2 = new char [strlen(indent)+2]; strcpy(i2, indent); strcat(i2, " |"); for ( int t=0; t<children(); t++ ) { child(t)->show_self(i2); } + delete[] i2; } fflush(stdout); } -/// Set the label. Makes a copy of the name. +/// Set the label to \p 'name'. +/// Makes and manages an internal copy of \p 'name'. +/// void Fl_Tree_Item::label(const char *name) { if ( _label ) { free((void*)_label); _label = 0; } _label = name ? strdup(name) : 0; + recalc_tree(); // may change label geometry } /// Return the label. @@ -157,7 +193,7 @@ const char *Fl_Tree_Item::label() const { return(_label); } -/// Return child item for the specified 'index'. +/// Return const child item for the specified 'index'. const Fl_Tree_Item *Fl_Tree_Item::child(int index) const { return(_children[index]); } @@ -165,51 +201,55 @@ const Fl_Tree_Item *Fl_Tree_Item::child(int index) const { /// Clear all the children for this item. void Fl_Tree_Item::clear_children() { _children.clear(); + recalc_tree(); // may change tree geometry } -/// Return the index of the immediate child of this item that has the label 'name'. +/// Return the index of the immediate child of this item +/// that has the label \p 'name'. /// /// \returns index of found item, or -1 if not found. +/// \version 1.3.0 release /// int Fl_Tree_Item::find_child(const char *name) { if ( name ) { - for ( int t=0; t<children(); t++ ) { - if ( child(t)->label() ) { - if ( strcmp(child(t)->label(), name) == 0 ) { + for ( int t=0; t<children(); t++ ) + if ( child(t)->label() ) + if ( strcmp(child(t)->label(), name) == 0 ) return(t); - } - } - } } return(-1); } -/// Find child item by descending array of names. Does not include self in search. -/// Only Fl_Tree should need this method. +/// Return the /immediate/ child of current item +/// that has the label \p 'name'. /// -/// \returns item, or 0 if not found +/// \returns const found item, or 0 if not found. +/// \version 1.3.3 /// -const Fl_Tree_Item *Fl_Tree_Item::find_child_item(char **arr) const { - for ( int t=0; t<children(); t++ ) { - if ( child(t)->label() ) { - if ( strcmp(child(t)->label(), *arr) == 0 ) { // match? - if ( *(arr+1) ) { // more in arr? descend - return(_children[t]->find_item(arr+1)); - } else { // end of arr? done - return(_children[t]); - } - } - } - } +const Fl_Tree_Item* Fl_Tree_Item::find_child_item(const char *name) const { + if ( name ) + for ( int t=0; t<children(); t++ ) + if ( child(t)->label() ) + if ( strcmp(child(t)->label(), name) == 0 ) + return(child(t)); return(0); } -/// Find child item by descending array of names. Does not include self in search. -/// Only Fl_Tree should need this method. Use Fl_Tree::find_item() instead. +/// Non-const version of Fl_Tree_Item::find_child_item(const char *name) const. +Fl_Tree_Item* Fl_Tree_Item::find_child_item(const char *name) { + // "Effective C++, 3rd Ed", p.23. Sola fide, Amen. + return(const_cast<Fl_Tree_Item*>( + static_cast<const Fl_Tree_Item &>(*this).find_child_item(name))); +} + +/// Find child item by descending array \p 'arr' of names. +/// Does not include self in search. +/// Only Fl_Tree should need this method. /// /// \returns item, or 0 if not found +/// \version 1.3.0 release /// -Fl_Tree_Item *Fl_Tree_Item::find_child_item(char **arr) { +const Fl_Tree_Item *Fl_Tree_Item::find_child_item(char **arr) const { for ( int t=0; t<children(); t++ ) { if ( child(t)->label() ) { if ( strcmp(child(t)->label(), *arr) == 0 ) { // match? @@ -224,16 +264,24 @@ Fl_Tree_Item *Fl_Tree_Item::find_child_item(char **arr) { return(0); } -/// Find item by descending array of \p names. Includes self in search. +/// Non-const version of Fl_Tree_Item::find_child_item(char **arr) const. +Fl_Tree_Item *Fl_Tree_Item::find_child_item(char **arr) { + // "Effective C++, 3rd Ed", p.23. Sola fide, Amen. + return(const_cast<Fl_Tree_Item*>( + static_cast<const Fl_Tree_Item &>(*this).find_child_item(arr))); +} + +/// Find item by descending array of \p 'names'. +/// Includes self in search. /// Only Fl_Tree should need this method. Use Fl_Tree::find_item() instead. /// -/// \returns item, or 0 if not found +/// \returns const item, or 0 if not found /// const Fl_Tree_Item *Fl_Tree_Item::find_item(char **names) const { + if ( ! *names ) return(0); if ( label() && strcmp(label(), *names) == 0 ) { // match self? - if ( *(names+1) == 0 ) { // end of names, - return(this); // found ourself. - } + ++names; // skip self + if ( *names == 0 ) return(this); // end of names, found ourself } if ( children() ) { // check children.. return(find_child_item(names)); @@ -241,44 +289,56 @@ const Fl_Tree_Item *Fl_Tree_Item::find_item(char **names) const { return(0); } -/// Find item by descending array of \p names. Includes self in search. -/// Only Fl_Tree should need this method. -/// -/// \returns item, or 0 if not found -/// +/// Non-const version of Fl_Tree_Item::find_item(char **names) const. Fl_Tree_Item *Fl_Tree_Item::find_item(char **names) { - if ( label() && strcmp(label(), *names) == 0 ) { // match self? - if ( *(names+1) == 0 ) { // end of names, - return(this); // found ourself. - } - } - if ( children() ) { // check children.. - return(find_child_item(names)); - } - return(0); + // "Effective C++, 3rd Ed", p.23. Sola fide, Amen. + return(const_cast<Fl_Tree_Item*>( + static_cast<const Fl_Tree_Item &>(*this).find_item(names))); } -/// Find the index number for the specified 'item' +/// Find the index number for the specified \p 'item' /// in the current item's list of children. /// /// \returns the index, or -1 if not found. /// int Fl_Tree_Item::find_child(Fl_Tree_Item *item) { - for ( int t=0; t<children(); t++ ) { - if ( item == child(t) ) { + for ( int t=0; t<children(); t++ ) + if ( item == child(t) ) return(t); - } - } return(-1); } -/// Add a new child to this item with the name 'new_label', with defaults from 'prefs'. +/// Add a new child to this item with the name \p 'new_label' +/// and defaults from \p 'prefs'. /// An internally managed copy is made of the label string. /// Adds the item based on the value of prefs.sortorder(). +/// \returns the item added +/// \version 1.3.0 release /// -Fl_Tree_Item *Fl_Tree_Item::add(const Fl_Tree_Prefs &prefs, const char *new_label) { - Fl_Tree_Item *item = new Fl_Tree_Item(prefs); - item->label(new_label); +Fl_Tree_Item *Fl_Tree_Item::add(const Fl_Tree_Prefs &prefs, + const char *new_label) { + return(add(prefs, new_label, (Fl_Tree_Item*)0)); +} + +/// Add \p 'item' as immediate child with \p 'new_label' +/// and defaults from \p 'prefs'. +/// If \p 'item' is NULL, a new item is created. +/// An internally managed copy is made of the label string. +/// Adds the item based on the value of prefs.sortorder(). +/// \returns the item added +/// \version 1.3.3 +/// +Fl_Tree_Item *Fl_Tree_Item::add(const Fl_Tree_Prefs &prefs, + const char *new_label, + Fl_Tree_Item *item) { +#if FLTK_ABI_VERSION >= 10303 + if ( !item ) + { item = new Fl_Tree_Item(_tree); item->label(new_label); } +#else + if ( !item ) + { item = new Fl_Tree_Item(prefs); item->label(new_label); } +#endif + recalc_tree(); // may change tree geometry item->_parent = this; switch ( prefs.sortorder() ) { case FL_TREE_SORT_NONE: { @@ -311,38 +371,73 @@ Fl_Tree_Item *Fl_Tree_Item::add(const Fl_Tree_Prefs &prefs, const char *new_labe return(item); } -/// Descend into the path specified by \p arr, and add a new child there. +/// Descend into the path specified by \p 'arr', and add a new child there. /// Should be used only by Fl_Tree's internals. /// Adds the item based on the value of prefs.sortorder(). /// \returns the item added. +/// \version 1.3.0 release /// Fl_Tree_Item *Fl_Tree_Item::add(const Fl_Tree_Prefs &prefs, char **arr) { - int t = (*arr && *(arr+1)) ? find_child(*arr) : -1; - Fl_Tree_Item *item = 0; - if ( t == -1 ) { - item = (Fl_Tree_Item*)add(prefs, *arr); - } else { - item = (Fl_Tree_Item*)child(t); - } - if ( *(arr+1) ) { // descend? - return(item->add(prefs, arr+1)); - } else { - return(item); // end? done + return add(prefs, arr, 0); +} + +/// Descend into path specified by \p 'arr' and add \p 'newitem' there. +/// Should be used only by Fl_Tree's internals. +/// If item is NULL, a new item is created. +/// Adds the item based on the value of prefs.sortorder(). +/// \returns the item added. +/// \version 1.3.3 ABI feature +/// +Fl_Tree_Item *Fl_Tree_Item::add(const Fl_Tree_Prefs &prefs, + char **arr, + Fl_Tree_Item *newitem) { + if ( !*arr ) return 0; + // See if we can find an existing child with name requested. + Fl_Tree_Item *child = find_child_item(*arr); + if ( child ) { // Child found? + if ( *(arr+1) == 0 ) { // ..and at end of path? + if ( !newitem ) { // ..and no item specified? + return 0; // ..error: child exists already + } else { + // Child found, end of path, item specified + return child->add(prefs, newitem->label(), newitem); + } + } + // Child found: more path elements to go or item specified? + // Descend into child to handle add.. + return child->add(prefs, arr+1, newitem); // recurse } + // No child found, see if we reached end of path. + // If so, add as an immediate child, done + if ( *(arr+1) == 0 ) // end of path? + return add(prefs, *arr, newitem); // add as immediate child + + // No child found, but more to path? + // If so, create new child to handle add() + Fl_Tree_Item *newchild; + return (newchild=add(prefs, *arr)) // create new immediate child + ? newchild->add(prefs,arr+1,newitem) // it worked? recurse to add + : 0; // failed? error } -/// Insert a new item into current item's children at a specified position. +/// Insert a new item named \p 'new_label' into current item's +/// children at a specified position \p 'pos'. /// \returns the new item inserted. /// Fl_Tree_Item *Fl_Tree_Item::insert(const Fl_Tree_Prefs &prefs, const char *new_label, int pos) { +#if FLTK_ABI_VERSION >= 10303 + Fl_Tree_Item *item = new Fl_Tree_Item(_tree); +#else Fl_Tree_Item *item = new Fl_Tree_Item(prefs); +#endif item->label(new_label); item->_parent = this; _children.insert(pos, item); + recalc_tree(); // may change tree geometry return(item); } -/// Insert a new item above this item. +/// Insert a new item named \p 'new_label' above this item. /// \returns the new item inserted, or 0 if an error occurred. /// Fl_Tree_Item *Fl_Tree_Item::insert_above(const Fl_Tree_Prefs &prefs, const char *new_label) { @@ -358,28 +453,231 @@ Fl_Tree_Item *Fl_Tree_Item::insert_above(const Fl_Tree_Prefs &prefs, const char return(0); } -/// Remove child by item. -/// \returns 0 if removed, -1 if item not an immediate child. +/// Deparent child at index position \p 'pos'. +/// This creates an "orphaned" item that is still allocated, +/// but has no parent or siblings. Normally the caller would +/// want to immediately reparent the orphan elsewhere. +/// +/// A successfully orphaned item will have its parent() +/// and prev_sibling()/next_sibling() set to NULL. +/// +/// \returns +/// - pointer to orphaned item on success +/// - NULL on error (could not deparent the item) +/// +Fl_Tree_Item* Fl_Tree_Item::deparent(int pos) { + Fl_Tree_Item *orphan = _children[pos]; + if ( _children.deparent(pos) < 0 ) return NULL; + return orphan; +} + +/// Reparent specified item as a child of ourself at position \p 'pos'. +/// Typically 'newchild' was recently orphaned with deparent(). +/// +/// \returns +/// - 0: on success +/// - -1: on error (e.g. if \p 'pos' out of range) +/// +int Fl_Tree_Item::reparent(Fl_Tree_Item *newchild, int pos) { + int ret; + if ( (ret = _children.reparent(newchild, this, pos)) < 0 ) return ret; + newchild->parent(this); // take custody + return 0; +} + +/// Move the item 'to' to sibling position of 'from'. +/// +/// \returns +/// - 0: Success +/// - -1: range error (e.g. if \p 'to' or \p 'from' out of range). +/// - (Other return values reserved for future use) +/// +int Fl_Tree_Item::move(int to, int from) { + return _children.move(to, from); +} + +/// Move the current item above/below/into the specified 'item', +/// where \p 'op' determines the type of move: +/// +/// - 0: move above \p 'item' (\p 'pos' ignored) +/// - 1: move below \p 'item' (\p 'pos' ignored) +/// - 2: move into \p 'item' as a child (at optional position \p 'pos') +/// +/// \returns 0 on success. a negative number on error: +/// - -1: one of the items has no parent +/// - -2: item's index could not be determined +/// - -3: bad 'op' +/// - -4: index range error +/// - -5: could not deparent +/// - -6: could not reparent at \p 'pos' +/// - (Other return values reserved for future use.) +/// +int Fl_Tree_Item::move(Fl_Tree_Item *item, int op, int pos) { + Fl_Tree_Item *from_parent, *to_parent; + int from, to; + switch (op) { + case 0: // "above" + from_parent = this->parent(); + to_parent = item->parent(); + from = from_parent->find_child(this); + to = to_parent->find_child(item); + break; + case 1: // "below" + from_parent = this->parent(); + to_parent = item->parent(); + from = from_parent->find_child(this); + to = to_parent->find_child(item); + break; + case 2: // "into" + from_parent = this->parent(); + to_parent = item; + from = from_parent->find_child(this); + to = pos; + break; + default: + return -3; + } + if ( !from_parent || !to_parent ) return -1; + if ( from < 0 || to < 0 ) return -2; + if ( from_parent == to_parent ) { // same parent? + switch (op) { // 'to' offsets due to scroll + case 0: if ( from < to && to > 0 ) --to; break; + case 1: if ( from > to && to < to_parent->children() ) ++to; break; + } + if ( from_parent->move(to, from) < 0 ) // simple move among siblings + return -4; + } else { // different parent? + if ( to > to_parent->children() ) // try to prevent a reparent() error + return -4; + if ( from_parent->deparent(from) < 0 ) // deparent self from current parent + return -5; + if ( to_parent->reparent(this, to) < 0 ) { // reparent self to new parent at position 'to' + to_parent->reparent(this, 0); // failed? shouldn't happen, reparent at 0 + return -6; + } + } + return 0; +} + +/// Move the current item above the specified 'item'. +/// This is the equivalent of calling move(item,0,0). +/// +/// \returns 0 on success.<br> +/// On error returns a negative value; +/// see move(Fl_Tree_Item*,int,int) for possible error codes. +/// +int Fl_Tree_Item::move_above(Fl_Tree_Item *item) { + return move(item, 0, 0); +} + +/// Move the current item below the specified 'item'. +/// This is the equivalent of calling move(item,1,0). +/// +/// \returns 0 on success.<br> +/// On error returns a negative value; +/// see move(Fl_Tree_Item*,int,int) for possible error codes. +/// +int Fl_Tree_Item::move_below(Fl_Tree_Item *item) { + return move(item, 1, 0); +} + +/// Parent the current item as a child of the specified \p 'item'. +/// This is the equivalent of calling move(item,2,pos). +/// +/// \returns 0 on success.<br> +/// On error returns a negative value; +/// see move(Fl_Tree_Item*,int,int) for possible error codes. +/// +int Fl_Tree_Item::move_into(Fl_Tree_Item *item, int pos) { + return move(item, 2, pos); +} + +#if FLTK_ABI_VERSION >= 10303 +/// Return the parent tree's prefs. +/// \returns a reference to the parent tree's Fl_Tree_Prefs +/// \version 1.3.3 ABI feature +/// +const Fl_Tree_Prefs& Fl_Tree_Item::prefs() const { + return(_tree->_prefs); +} + +/// Replace the current item with a new item. +/// +/// The current item is destroyed if successful. +/// No checks are made to see if an item with the same name exists. +/// +/// This method can be used to, for example, install 'custom' items +/// into the tree derived from Fl_Tree_Item; see draw_item_content(). +/// +/// \param[in] newitem The new item to replace the current item +/// \returns newitem on success, NULL if could not be replaced. +/// \see Fl_Tree_Item::draw_item_content(), Fl_Tree::root(Fl_Tree_Item*) +/// \version 1.3.3 ABI feature +/// +Fl_Tree_Item *Fl_Tree_Item::replace(Fl_Tree_Item *newitem) { + Fl_Tree_Item *p = parent(); + if ( !p ) { // no parent? then we're the tree's root.. + _tree->root(newitem); // ..tell tree to replace root + return newitem; + } + // has parent? ask parent to replace us + return p->replace_child(this, newitem); +} + +/// Replace existing child \p 'olditem' with \p 'newitem'. +/// +/// The \p 'olditem' is destroyed if successful. +/// Can be used to put custom items (derived from Fl_Tree_Item) into the tree. +/// No checks are made to see if an item with the same name exists. +/// +/// \param[in] olditem The item to be found and replaced +/// \param[in] newitem The new item to take the place of \p 'olditem' +/// \returns newitem on success and \p 'olditem' is destroyed. +/// NULL on error if \p 'olditem' was not found +/// as an immediate child. +/// \see replace(), Fl_Tree_Item::draw() +/// \version 1.3.3 ABI feature +/// +Fl_Tree_Item *Fl_Tree_Item::replace_child(Fl_Tree_Item *olditem, + Fl_Tree_Item *newitem) { + int pos = find_child(olditem); // find our index for olditem + if ( pos == -1 ) return(NULL); + newitem->_parent = this; + // replace in array (handles stitching neighboring items) + _children.replace(pos, newitem); + recalc_tree(); // newitem may have changed tree geometry + return newitem; +} +#endif + +/// Remove \p 'item' from the current item's children. +/// \returns 0 if removed, -1 if item not an immediate child. /// int Fl_Tree_Item::remove_child(Fl_Tree_Item *item) { for ( int t=0; t<children(); t++ ) { if ( child(t) == item ) { item->clear_children(); _children.remove(t); + recalc_tree(); // may change tree geometry return(0); } } return(-1); } -/// Remove immediate child (and its children) by its label 'name'. +/// Remove immediate child (and its children) by its label \p 'name'. +/// If more than one item matches \p 'name', only the first +/// matching item is removed. +/// \param[in] name The label name of the immediate child to remove /// \returns 0 if removed, -1 if not found. +/// \version 1.3.3 /// int Fl_Tree_Item::remove_child(const char *name) { for ( int t=0; t<children(); t++ ) { if ( child(t)->label() ) { if ( strcmp(child(t)->label(), name) == 0 ) { _children.remove(t); + recalc_tree(); // may change tree geometry return(0); } } @@ -387,30 +685,27 @@ int Fl_Tree_Item::remove_child(const char *name) { return(-1); } -/// Swap two of our children, given two child index values. -/// Use this eg. for sorting. -/// -/// This method is FAST, and does not involve lookups. -/// +/// Swap two of our children, given two child index values \p 'ax' and \p 'bx'. +/// Use e.g. for sorting.<br> +/// This method is FAST, and does not involve lookups.<br> /// No range checking is done on either index value. -/// -/// \returns -/// - 0 : OK -/// - -1 : failed: 'a' or 'b' is not our immediate child +/// \param[in] ax,bx the index of the items to swap /// void Fl_Tree_Item::swap_children(int ax, int bx) { _children.swap(ax, bx); } -/// Swap two of our children, given item pointers. -/// Use this eg. for sorting. +/// Swap two of our immediate children, given item pointers. +/// Use e.g. for sorting. /// -/// This method is SLOW because it involves linear lookups. +/// This method is SLOW because it involves linear lookups.<br> /// For speed, use swap_children(int,int) instead. /// +/// \param[in] a,b The item ptrs of the two items to swap. +/// Both must be immediate children of the current item. /// \returns /// - 0 : OK -/// - -1 : failed: 'a' or 'b' is not our immediate child +/// - -1 : failed: item \p 'a' or \p 'b' is not our child. /// int Fl_Tree_Item::swap_children(Fl_Tree_Item *a, Fl_Tree_Item *b) { int ax = -1, bx = -1; @@ -424,6 +719,11 @@ int Fl_Tree_Item::swap_children(Fl_Tree_Item *a, Fl_Tree_Item *b) { } /// Internal: Horizontal connector line based on preference settings. +/// \param[in] x1 The left hand X position of the horizontal connector +/// \param[in] x2 The right hand X position of the horizontal connector +/// \param[in] y The vertical position of the horizontal connector +/// \param[in] prefs The Fl_Tree prefs +/// void Fl_Tree_Item::draw_horizontal_connector(int x1, int x2, int y, const Fl_Tree_Prefs &prefs) { fl_color(prefs.connectorcolor()); switch ( prefs.connectorstyle() ) { @@ -445,6 +745,11 @@ void Fl_Tree_Item::draw_horizontal_connector(int x1, int x2, int y, const Fl_Tre } /// Internal: Vertical connector line based on preference settings. +/// \param[in] x The x position of the vertical connector +/// \param[in] y1 The top of the vertical connector +/// \param[in] y2 The bottom of the vertical connector +/// \param[in] prefs The Fl_Tree prefs +/// void Fl_Tree_Item::draw_vertical_connector(int x, int y1, int y2, const Fl_Tree_Prefs &prefs) { fl_color(prefs.connectorcolor()); switch ( prefs.connectorstyle() ) { @@ -467,45 +772,55 @@ void Fl_Tree_Item::draw_vertical_connector(int x, int y1, int y2, const Fl_Tree_ } } +#if FLTK_ABI_VERSION >= 10303 /// Find the item that the last event was over. +/// If \p 'yonly' is 1, only check event's y value, don't care about x. +/// \param[in] prefs The parent tree's Fl_Tree_Prefs +/// \param[in] yonly -- 0: check both event's X and Y values. +/// -- 1: only check event's Y value, don't care about X. +/// \returns pointer to clicked item, or NULL if none found +/// \version 1.3.3 ABI feature /// -/// Returns the item if it is visible, and mouse is over it. -/// Works even if widget deactivated. -/// Use event_on_collapse_icon() to determine if collapse button was pressed. -/// -/// \returns const visible item under the event if found, or 0 if none. -/// -const Fl_Tree_Item *Fl_Tree_Item::find_clicked(const Fl_Tree_Prefs &prefs) const { +const Fl_Tree_Item *Fl_Tree_Item::find_clicked(const Fl_Tree_Prefs &prefs, int yonly) const { if ( ! is_visible() ) return(0); if ( is_root() && !prefs.showroot() ) { // skip event check if we're root but root not being shown } else { // See if event is over us - if ( event_inside(_xywh) ) { // event within this item? - return(this); // found + if ( yonly ) { + if ( Fl::event_y() >= _xywh[1] && + Fl::event_y() <= (_xywh[1]+_xywh[3]) ) { + return(this); + } + } else { + if ( event_inside(_xywh) ) { // event within this item? + return(this); // found + } } } if ( is_open() ) { // open? check children of this item for ( int t=0; t<children(); t++ ) { const Fl_Tree_Item *item; - if ( ( item = _children[t]->find_clicked(prefs) ) != NULL) { // check child and its descendents - return(item); // found? - } + if ( (item = _children[t]->find_clicked(prefs, yonly)) != NULL) // recurse into child for descendents + return(item); // found? } } return(0); } -/// Non-const version of the above. +/// Non-const version of Fl_Tree_Item::find_clicked(const Fl_Tree_Prefs&,int) const +Fl_Tree_Item *Fl_Tree_Item::find_clicked(const Fl_Tree_Prefs &prefs, int yonly) { + // "Effective C++, 3rd Ed", p.23. Sola fide, Amen. + return(const_cast<Fl_Tree_Item*>( + static_cast<const Fl_Tree_Item &>(*this).find_clicked(prefs, yonly))); +} +#else /// Find the item that the last event was over. +/// \param[in] prefs The parent tree's Fl_Tree_Prefs +/// \returns pointer to clicked item, or NULL if none found +/// \version 1.3.0 /// -/// Returns the item if it is visible, and mouse is over it. -/// Works even if widget deactivated. -/// Use event_on_collapse_icon() to determine if collapse button was pressed. -/// -/// \returns the visible item under the event if found, or 0 if none. -/// -Fl_Tree_Item *Fl_Tree_Item::find_clicked(const Fl_Tree_Prefs &prefs) { +const Fl_Tree_Item *Fl_Tree_Item::find_clicked(const Fl_Tree_Prefs &prefs) const { if ( ! is_visible() ) return(0); if ( is_root() && !prefs.showroot() ) { // skip event check if we're root but root not being shown @@ -517,16 +832,23 @@ Fl_Tree_Item *Fl_Tree_Item::find_clicked(const Fl_Tree_Prefs &prefs) { } if ( is_open() ) { // open? check children of this item for ( int t=0; t<children(); t++ ) { - Fl_Tree_Item *item; - if ( ( item = _children[t]->find_clicked(prefs) ) != NULL ) { // check child and its descendents - return(item); // found? - } + const Fl_Tree_Item *item; + if ( (item = _children[t]->find_clicked(prefs)) != NULL) // recurse into child for descendents + return(item); // found? } } return(0); } -static void draw_item_focus(Fl_Boxtype B, Fl_Color C, int X, int Y, int W, int H) { +/// Non-const version of Fl_Tree_Item::find_clicked(const Fl_Tree_Prefs&) const. +Fl_Tree_Item *Fl_Tree_Item::find_clicked(const Fl_Tree_Prefs &prefs) { + // "Effective C++, 3rd Ed", p.23. Sola fide, Amen. + return(const_cast<Fl_Tree_Item*>( + static_cast<const Fl_Tree_Item &>(*this).find_clicked(prefs))); +} +#endif + +static void draw_item_focus(Fl_Boxtype B, Fl_Color fg, Fl_Color bg, int X, int Y, int W, int H) { if (!Fl::visible_focus()) return; switch (B) { case FL_DOWN_BOX: @@ -538,7 +860,7 @@ static void draw_item_focus(Fl_Boxtype B, Fl_Color C, int X, int Y, int W, int H default: break; } - fl_color(fl_contrast(FL_BLACK, C)); + fl_color(fl_contrast(fg, bg)); #if defined(USE_X11) || defined(__APPLE_QUARTZ__) fl_line_style(FL_DOT); @@ -566,8 +888,14 @@ static void draw_item_focus(Fl_Boxtype B, Fl_Color C, int X, int Y, int W, int H #endif } -/// Return the item's 'visible' height. -/// Doesn't include linespacing(); prevents affecting eg. height of widget(). +/// Return the item's 'visible' height. Takes into account the item's: +/// - visibility (if !is_visible(), returns 0) +/// - labelfont() height: if label() != NULL +/// - widget() height: if widget() != NULL +/// - openicon() height (if not NULL) +/// - usericon() height (if not NULL) +/// Does NOT include Fl_Tree::linespacing(); +/// \returns maximum pixel height /// int Fl_Tree_Item::calc_item_height(const Fl_Tree_Prefs &prefs) const { if ( ! is_visible() ) return(0); @@ -590,7 +918,336 @@ int Fl_Tree_Item::calc_item_height(const Fl_Tree_Prefs &prefs) const { return(H); } +#if FLTK_ABI_VERSION >= 10303 +// These methods held for 1.3.3 ABI: all need 'tree()' back-reference. + +/// Returns the recommended foreground color used for drawing this item. +/// \see draw_item_content() +/// \version 1.3.3 ABI ABI +/// +Fl_Color Fl_Tree_Item::drawfgcolor() const { + return is_selected() ? fl_contrast(_labelfgcolor, tree()->selection_color()) + : is_active() ? _labelfgcolor + : fl_inactive(_labelfgcolor); +} + +/// Returns the recommended background color used for drawing this item. +/// \see draw_item_content() +/// \version 1.3.3 ABI +/// +Fl_Color Fl_Tree_Item::drawbgcolor() const { + const Fl_Color unspecified = 0xffffffff; + return is_selected() ? is_active() ? tree()->selection_color() + : fl_inactive(tree()->selection_color()) + : _labelbgcolor == unspecified ? tree()->color() + : _labelbgcolor; +} + +/// Draw the item content +/// +/// This method can be overridden to implement custom drawing +/// by filling the label_[xywh]() area with content. +/// +/// A minimal example of how to override draw_item_content() +/// and draw just a normal item's background and label ourselves: +/// +/// \code +/// class MyTreeItem : public Fl_Tree_Item { +/// public: +/// MyTreeItem() { } +/// ~MyTreeItem() { } +/// // DRAW OUR CUSTOM CONTENT FOR THE ITEM +/// int draw_item_content(int render) { +/// // Our item's dimensions + text content +/// int X=label_x(), Y=label_y(), W=label_w(), H=label_h(); +/// const char *text = label() ? label() : ""; +/// // Rendering? Do any drawing that's needed +/// if ( render ) { +/// // Draw bg -- a filled rectangle +/// fl_color(drawbgcolor()); fl_rectf(X,Y,W,H); +/// // Draw label +/// fl_font(labelfont(), labelsize()); // use item's label font/size +/// fl_color(drawfgcolor()); // use recommended fg color +/// fl_draw(text, X,Y,W,H, FL_ALIGN_LEFT); // draw the item's label +/// } +/// // Rendered or not, we must calculate content's max X position +/// int lw=0, lh=0; +/// fl_measure(text, lw, lh); // get width of label text +/// return X + lw; // return X + label width +/// } +/// }; +/// \endcode +/// +/// You can draw anything you want inside draw_item_content() +/// using any of the fl_draw.H functions, as long as it's +/// within the label's xywh area. +/// +/// To add instances of your custom item to the tree, you can use: +/// +/// \code +/// // Example #1: using add() +/// MyTreeItem *bart = new MyTreeItem(..); // class derived from Fl_Tree_Item +/// tree->add("/Simpsons/Bart", bart); // Add item as /Simpsons/Bart +/// \endcode +/// +/// ..or you can insert or replace existing items: +/// +/// \code +/// // Example #2: using replace() +/// MyTreeItem *marge = new MyTreeItem(..); // class derived from Fl_Tree_Item +/// item = tree->add("/Simpsons/Marge"); // create item +/// item->replace(mi); // replace it with our own +/// \endcode +/// +/// \param[in] render Whether we should render content (1), or just tally +/// the geometry (0). Fl_Tree may want only to find the widest +/// item in the tree for scrollbar calculations. +/// +/// \returns the right-most X coordinate, or 'xmax' of content we drew, +/// i.e. the "scrollable" content. +/// The tree uses the largest xmax to determine the maximum +/// width of the tree's content (needed for e.g. computing the +/// horizontal scrollbar's size). +/// \version 1.3.3 ABI feature +/// +int Fl_Tree_Item::draw_item_content(int render) { + Fl_Color fg = drawfgcolor(); + Fl_Color bg = drawbgcolor(); + const Fl_Tree_Prefs &prefs = tree()->prefs(); + int xmax = label_x(); + // Background for this item, only if different from tree's bg + if ( render && (bg != tree()->color() || is_selected()) ) { + if ( is_selected() ) { // Selected? Use selectbox() style + fl_draw_box(prefs.selectbox(), + label_x(), label_y(), label_w(), label_h(), bg); + } else { // Not Selected? use plain filled rectangle + fl_color(bg); + fl_rectf(label_x(), label_y(), label_w(), label_h()); + } + if ( widget() ) widget()->damage(FL_DAMAGE_ALL); // if there's a child widget, we just damaged it + } + // Draw label + if ( _label && + ( !widget() || + (prefs.item_draw_mode() & FL_TREE_ITEM_DRAW_LABEL_AND_WIDGET) ) ) { + if ( render ) { + fl_color(fg); + fl_font(_labelfont, _labelsize); + } + int lx = label_x()+(_label ? prefs.labelmarginleft() : 0); + int ly = label_y()+(label_h()/2)+(_labelsize/2)-fl_descent()/2; + int lw=0, lh=0; + fl_measure(_label, lw, lh); // get box around text (including white space) + if ( render ) fl_draw(_label, lx, ly); + xmax = lx + lw; // update max width of drawn item + } + return xmax; +} + +/// Draw this item and its children. +/// +/// \param[in] X Horizontal position for item being drawn +/// \param[in,out] Y Vertical position for item being drawn, +/// returns new position for next item +/// \param[in] W Recommended width for item +/// \param[in] itemfocus The tree's current focus item (if any) +/// \param[in,out] tree_item_xmax The tree's running xmax (right-most edge so far). +/// Mainly used by parent tree when render==0 to +/// calculate tree's max width. +/// \param[in] lastchild Is this item the last child in a subtree? +/// \param[in] render Whether or not to render the item: +/// 0: no rendering, just calculate size w/out drawing. +/// 1: render item as well as size calc +/// +/// \version 1.3.3 ABI feature: modified parameters +/// +void Fl_Tree_Item::draw(int X, int &Y, int W, Fl_Tree_Item *itemfocus, + int &tree_item_xmax, int lastchild, int render) { + Fl_Tree_Prefs &prefs = _tree->_prefs; + if ( !is_visible() ) return; + int tree_top = tree()->_tiy; + int tree_bot = tree_top + tree()->_tih; + int H = calc_item_height(prefs); // height of item + int H2 = H + prefs.linespacing(); // height of item with line spacing + + // Update the xywh of this item + _xywh[0] = X; + _xywh[1] = Y; + _xywh[2] = W; + _xywh[3] = H; + + // Determine collapse icon's xywh + // Note: calculate collapse icon's xywh for possible mouse click detection. + // We don't care about items clipped off the viewport; they won't get mouse events. + // + int item_y_center = Y+(H/2); + _collapse_xywh[2] = prefs.openicon()->w(); + int &icon_w = _collapse_xywh[2]; + _collapse_xywh[0] = X + (icon_w + prefs.connectorwidth())/2 - 3; + int &icon_x = _collapse_xywh[0]; + _collapse_xywh[1] = item_y_center - (prefs.openicon()->h()/2); + int &icon_y = _collapse_xywh[1]; + _collapse_xywh[3] = prefs.openicon()->h(); + + // Horizontal connector values + // Must calculate these even if(clipped) because 'draw children' code (below) + // needs hconn_x_center value. (Otherwise, these calculations could be 'clipped') + // + int hconn_x = X+icon_w/2-1; + int hconn_x2 = hconn_x + prefs.connectorwidth(); + int hconn_x_center = X + icon_w + ((hconn_x2 - (X + icon_w)) / 2); + int cw1 = icon_w+prefs.connectorwidth()/2, cw2 = prefs.connectorwidth(); + int conn_w = cw1>cw2 ? cw1 : cw2; + + // Usericon position + int uicon_x = X+(icon_w/2-1+conn_w) + ( (usericon() || prefs.usericon()) + ? prefs.usericonmarginleft() : 0); + int uicon_w = usericon() ? usericon()->w() + : prefs.usericon() ? prefs.usericon()->w() : 0; + + // Label xywh + _label_xywh[0] = uicon_x + uicon_w + prefs.labelmarginleft(); + _label_xywh[1] = Y; + _label_xywh[2] = tree()->_tix + tree()->_tiw - _label_xywh[0]; + _label_xywh[3] = H; + + // Begin calc of this item's max width.. + // It might not even be visible, so start at zero. + // + int xmax = 0; + + // Recalc widget position + // Do this whether clipped or not, so that when scrolled, + // the widgets move to appropriate 'offscreen' positions + // (so that they don't get mouse events, etc) + // + if ( widget() ) { + int wx = uicon_x + uicon_w + (_label ? prefs.labelmarginleft() : 0); + int wy = label_y(); + int ww = widget()->w(); // use widget's width + int wh = (prefs.item_draw_mode() & FL_TREE_ITEM_HEIGHT_FROM_WIDGET) + ? widget()->h() : H; + if ( _label && + (prefs.item_draw_mode() & FL_TREE_ITEM_DRAW_LABEL_AND_WIDGET) ) { + fl_font(_labelfont, _labelsize); // fldescent() needs this + int lw=0, lh=0; + fl_measure(_label,lw,lh); // get box around text (including white space) + wx += (lw + prefs.widgetmarginleft()); + } + if ( widget()->x() != wx || widget()->y() != wy || + widget()->w() != ww || widget()->h() != wh ) { + widget()->resize(wx,wy,ww,wh); // we'll handle redraw below + } + } + char clipped = ((Y+H) < tree_top) || (Y>tree_bot) ? 1 : 0; + if (!render) clipped = 0; // NOT rendering? Then don't clip, so we calc unclipped items + char drawthis = ( is_root() && prefs.showroot() == 0 ) ? 0 : 1; + if ( !clipped ) { + Fl_Color fg = drawfgcolor(); + Fl_Color bg = drawbgcolor(); + // See if we should draw this item + // If this item is root, and showroot() is disabled, don't draw. + // 'clipped' is an optimization to prevent drawing anything offscreen. + // + if ( drawthis ) { // draw this item at all? + if ( (tree()->damage() & ~FL_DAMAGE_CHILD) || !render ) { // non-child damage? + // Draw connectors + if ( render && prefs.connectorstyle() != FL_TREE_CONNECTOR_NONE ) { + // Horiz connector between center of icon and text + // if this is root, the connector should not dangle in thin air on the left + if (is_root()) draw_horizontal_connector(hconn_x_center, hconn_x2, item_y_center, prefs); + else draw_horizontal_connector(hconn_x, hconn_x2, item_y_center, prefs); + // Small vertical line down to children + if ( has_children() && is_open() ) + draw_vertical_connector(hconn_x_center, item_y_center, Y+H2, prefs); + // Connectors for last child + if ( !is_root() ) { + if ( lastchild ) draw_vertical_connector(hconn_x, Y, item_y_center, prefs); + else draw_vertical_connector(hconn_x, Y, Y+H2, prefs); + } + } + // Draw collapse icon + if ( render && has_children() && prefs.showcollapse() ) { + // Draw icon image + if ( is_open() ) { + prefs.closeicon()->draw(icon_x,icon_y); + } else { + prefs.openicon()->draw(icon_x,icon_y); + } + } + // Draw user icon (if any) + if ( render && usericon() ) { + // Item has user icon? Use it + int uicon_y = item_y_center - (usericon()->h() >> 1); + usericon()->draw(uicon_x,uicon_y); + } else if ( render && prefs.usericon() ) { + // Prefs has user icon? Use it + int uicon_y = item_y_center - (prefs.usericon()->h() >> 1); + prefs.usericon()->draw(uicon_x,uicon_y); + } + // Draw item's content + xmax = draw_item_content(render); + } // end non-child damage + // Draw child FLTK widget? + if ( widget() ) { + if (render) + tree()->draw_child(*widget()); // let group handle drawing child + if ( widget()->label() && render ) + tree()->draw_outside_label(*widget());// label too + xmax = widget()->x() + widget()->w(); // update max width of widget + } + // Draw focus box around item's bg last + if ( render && + this == itemfocus && + Fl::visible_focus() && + Fl::focus() == tree() && + prefs.selectmode() != FL_TREE_SELECT_NONE ) { + draw_item_focus(FL_NO_BOX,fg,bg,label_x()+1,label_y()+1,label_w()-1,label_h()-1); + } + } // end drawthis + } // end clipped + if ( drawthis ) Y += H2; // adjust Y (even if clipped) + // Manage tree_item_xmax + if ( xmax > tree_item_xmax ) + tree_item_xmax = xmax; + // Draw child items (if any) + if ( has_children() && is_open() ) { + int child_x = drawthis ? (hconn_x_center - (icon_w/2) + 1) // offset children to right, + : X; // unless didn't drawthis + int child_w = W - (child_x-X); + int child_y_start = Y; + for ( int t=0; t<children(); t++ ) { + int lastchild = ((t+1)==children()) ? 1 : 0; + _children[t]->draw(child_x, Y, child_w, itemfocus, tree_item_xmax, lastchild, render); + } + if ( has_children() && is_open() ) { + Y += prefs.openchild_marginbottom(); // offset below open child tree + } + if ( ! lastchild ) { + // Special 'clipped' calculation. (intentional variable shadowing) + int clipped = ((child_y_start < tree_top) && (Y < tree_top)) || + ((child_y_start > tree_bot) && (Y > tree_bot)); + if (render && !clipped ) + draw_vertical_connector(hconn_x, child_y_start, Y, prefs); + } + } +} + +#else + /// Draw this item and its children. +/// +/// \param[in] X Horizontal position for item being drawn +/// \param[in,out] Y Vertical position for item being drawn, +/// returns new position for next item +/// \param[in] W Recommended width of item +/// \param[in] tree The parent tree +/// \param[in] itemfocus The tree's current focus item (if any) +/// \param[in] prefs The tree's preferences +/// \param[in] lastchild Is this item the last child in a subtree? +/// +/// \version 1.3.0 release, removed 1.3.3 ABI +/// void Fl_Tree_Item::draw(int X, int &Y, int W, Fl_Widget *tree, Fl_Tree_Item *itemfocus, const Fl_Tree_Prefs &prefs, int lastchild) { @@ -611,9 +1268,12 @@ void Fl_Tree_Item::draw(int X, int &Y, int W, Fl_Widget *tree, // We don't care about items clipped off the viewport; they won't get mouse events. // int item_y_center = Y+(H/2); - int &icon_w = _collapse_xywh[2] = prefs.openicon()->w(); - int &icon_x = _collapse_xywh[0] = X + (icon_w + prefs.connectorwidth())/2 - 3; - int &icon_y = _collapse_xywh[1] = item_y_center - (prefs.openicon()->h()/2); + _collapse_xywh[2] = prefs.openicon()->w(); + int &icon_w = _collapse_xywh[2]; + _collapse_xywh[0] = X + (icon_w + prefs.connectorwidth())/2 - 3; + int &icon_x = _collapse_xywh[0]; + _collapse_xywh[1] = item_y_center - (prefs.openicon()->h()/2); + int &icon_y = _collapse_xywh[1]; _collapse_xywh[3] = prefs.openicon()->h(); // Horizontal connector values @@ -676,13 +1336,14 @@ void Fl_Tree_Item::draw(int X, int &Y, int W, Fl_Widget *tree, char clipped = ((Y+H) < tree_top) || (Y>tree_bot) ? 1 : 0; char drawthis = ( is_root() && prefs.showroot() == 0 ) ? 0 : 1; if ( !clipped ) { + const Fl_Color unspecified = 0xffffffff; Fl_Color fg = is_selected() ? fl_contrast(_labelfgcolor, tree->selection_color()) - : is_active() ? _labelfgcolor + : is_active() ? _labelfgcolor : fl_inactive(_labelfgcolor); Fl_Color bg = is_selected() ? is_active() ? tree->selection_color() : fl_inactive(tree->selection_color()) - : _labelbgcolor == 0xffffffff ? tree->color() // transparent bg? - : _labelbgcolor; + : _labelbgcolor == unspecified ? tree->color() + : _labelbgcolor; // See if we should draw this item // If this item is root, and showroot() is disabled, don't draw. // 'clipped' is an optimization to prevent drawing anything offscreen. @@ -713,8 +1374,7 @@ void Fl_Tree_Item::draw(int X, int &Y, int W, Fl_Widget *tree, prefs.openicon()->draw(icon_x,icon_y); } } - // Background for this item - // Draw bg only if different from tree's bg + // Draw background for the item.. only if different from tree's bg color if ( bg != tree->color() || is_selected() ) { if ( is_selected() ) { // Selected? Use selectbox() style fl_draw_box(prefs.selectbox(),bg_x,bg_y,bg_w,bg_h,bg); @@ -736,13 +1396,13 @@ void Fl_Tree_Item::draw(int X, int &Y, int W, Fl_Widget *tree, } // Draw label #if FLTK_ABI_VERSION >= 10301 - if ( _label && + if ( _label && ( !widget() || (prefs.item_draw_mode() & FL_TREE_ITEM_DRAW_LABEL_AND_WIDGET) ) ) #else /*FLTK_ABI_VERSION*/ - if ( _label && !widget() ) // back compat: don't draw label if widget() present + if ( _label && !widget() ) // back compat: don't draw label if widget() present #endif /*FLTK_ABI_VERSION*/ - { + { fl_color(fg); fl_font(_labelfont, _labelsize); int label_y = Y+(H/2)+(_labelsize/2)-fl_descent()/2; @@ -760,7 +1420,7 @@ void Fl_Tree_Item::draw(int X, int &Y, int W, Fl_Widget *tree, Fl::visible_focus() && Fl::focus() == tree && prefs.selectmode() != FL_TREE_SELECT_NONE ) { - draw_item_focus(FL_NO_BOX,bg,bg_x+1,bg_y+1,bg_w-1,bg_h-1); + draw_item_focus(FL_NO_BOX,fg,bg,bg_x+1,bg_y+1,bg_w-1,bg_h-1); } } // end drawthis } // end clipped @@ -786,8 +1446,9 @@ void Fl_Tree_Item::draw(int X, int &Y, int W, Fl_Widget *tree, } } } +#endif -/// Was the event on the 'collapse' button? +/// Was the event on the 'collapse' button of this item? /// int Fl_Tree_Item::event_on_collapse_icon(const Fl_Tree_Prefs &prefs) const { if ( is_visible() && is_active() && has_children() && prefs.showcollapse() ) { @@ -797,7 +1458,7 @@ int Fl_Tree_Item::event_on_collapse_icon(const Fl_Tree_Prefs &prefs) const { } } -/// Was event on the label()? +/// Was event on the label() of this item? /// int Fl_Tree_Item::event_on_label(const Fl_Tree_Prefs &prefs) const { if ( is_visible() && is_active() ) { @@ -836,6 +1497,7 @@ void Fl_Tree_Item::open() { for ( int t=0; t<_children.total(); t++ ) { _children[t]->show_widgets(); } + recalc_tree(); // may change tree geometry } /// Close this item and all its children. @@ -845,12 +1507,14 @@ void Fl_Tree_Item::close() { for ( int t=0; t<_children.total(); t++ ) { _children[t]->hide_widgets(); } + recalc_tree(); // may change tree geometry } /// Returns how many levels deep this item is in the hierarchy. /// /// For instance; root has a depth of zero, and its immediate children -/// would have a depth of 1, and so on. +/// would have a depth of 1, and so on. Use e.g. for determining the +/// horizontal indent of this item during drawing. /// int Fl_Tree_Item::depth() const { int count = 0; @@ -898,7 +1562,8 @@ Fl_Tree_Item *Fl_Tree_Item::next() { /// This method can be used to walk the tree backwards. /// For an example of how to use this method, see Fl_Tree::last(). /// -/// \returns the previous item in the tree, or 0 if there's no item above this one (hit the root). +/// \returns the previous item in the tree, +/// or 0 if there's no item above this one (hit the root). /// Fl_Tree_Item *Fl_Tree_Item::prev() { #if FLTK_ABI_VERSION >= 10301 @@ -949,7 +1614,7 @@ Fl_Tree_Item *Fl_Tree_Item::prev() { /// Return this item's next sibling. /// /// Moves to the next item below us at the same level (sibling). -/// Use this to move down the tree without moving deeper into the tree, +/// Use this to move down the tree without changing depth(). /// effectively skipping over this item's children/descendents. /// /// \returns item's next sibling, or 0 if none. @@ -972,7 +1637,7 @@ Fl_Tree_Item *Fl_Tree_Item::next_sibling() { /// Return this item's previous sibling. /// /// Moves to the previous item above us at the same level (sibling). -/// Use this to move up the tree without moving deeper into the tree. +/// Use this to move up the tree without changing depth(). /// /// \returns This item's previous sibling, or 0 if none. /// @@ -990,13 +1655,21 @@ Fl_Tree_Item *Fl_Tree_Item::prev_sibling() { #endif /*FLTK_ABI_VERSION*/ } -/// Update our _prev_sibling and _next_sibling pointers to point to neighbors, +/// Update our _prev_sibling and _next_sibling pointers to point to neighbors /// given \p index as being our current position in the parent's item array. -/// Call this whenever items in the array are added/removed/moved/swapped. +/// Call this whenever items in the array are added/removed/moved/swapped/etc. +/// \param[in] index Our index# in the parent.<br> +/// Special case if index=-1: become an orphan; null out all parent/sibling associations. /// void Fl_Tree_Item::update_prev_next(int index) { #if FLTK_ABI_VERSION >= 10301 // NEW + if ( index == -1 ) { // special case: become an orphan + _parent = 0; + _prev_sibling = 0; + _next_sibling = 0; + return; + } int pchildren = parent() ? parent()->children() : 0; int index_prev = index-1; int index_next = index+1; @@ -1015,14 +1688,17 @@ void Fl_Tree_Item::update_prev_next(int index) { #endif /*FLTK_ABI_VERSION*/ } -/// Return the next visible item. (If this item has children and is closed, children are skipped) +/// Return the next open(), visible() item. +/// (If this item has children and is closed, children are skipped) /// /// This method can be used to walk the tree forward, skipping items -/// that are not currently visible to the user. +/// that are not currently open/visible to the user. /// -/// \returns the next visible item below us, or 0 if there's no more items. +/// \returns the next open() visible() item below us, +/// or 0 if there's no more items. +/// \version 1.3.3 /// -Fl_Tree_Item *Fl_Tree_Item::next_displayed(Fl_Tree_Prefs &prefs) { +Fl_Tree_Item *Fl_Tree_Item::next_visible(Fl_Tree_Prefs &prefs) { Fl_Tree_Item *item = this; while ( 1 ) { item = item->next(); @@ -1032,14 +1708,22 @@ Fl_Tree_Item *Fl_Tree_Item::next_displayed(Fl_Tree_Prefs &prefs) { } } -/// Return the previous visible item. (If this item above us has children and is closed, its children are skipped) +/// Same as next_visible(). +/// \deprecated in 1.3.3 for confusing name, use next_visible() instead +Fl_Tree_Item *Fl_Tree_Item::next_displayed(Fl_Tree_Prefs &prefs) { + return next_visible(prefs); +} + +/// Return the previous open(), visible() item. +/// (If this item above us has children and is closed, its children are skipped) /// /// This method can be used to walk the tree backward, -/// skipping items that are not currently visible to the user. +/// skipping items that are not currently open/visible to the user. /// -/// \returns the previous visible item above us, or 0 if there's no more items. +/// \returns the previous open() visible() item above us, +/// or 0 if there's no more items. /// -Fl_Tree_Item *Fl_Tree_Item::prev_displayed(Fl_Tree_Prefs &prefs) { +Fl_Tree_Item *Fl_Tree_Item::prev_visible(Fl_Tree_Prefs &prefs) { Fl_Tree_Item *c = this; while ( c ) { c = c->prev(); // previous item @@ -1059,11 +1743,17 @@ Fl_Tree_Item *Fl_Tree_Item::prev_displayed(Fl_Tree_Prefs &prefs) { return(0); // hit end: no more items } -/// Returns if item and all its parents are visible. -/// Also takes into consideration if any parent is close()ed. +/// Same as prev_visible(). +/// \deprecated in 1.3.3 for confusing name, use prev_visible() +/// +Fl_Tree_Item *Fl_Tree_Item::prev_displayed(Fl_Tree_Prefs &prefs) { + return prev_visible(prefs); +} + +/// See if item and all its parents are open() and visible(). /// \returns -/// 1 -- item and its parents are visible/open() -/// 0 -- item (or parents) invisible or close()ed. +/// 1 -- item and its parents are open() and visible() +/// 0 -- item (or one of its parents) are invisible or close()ed. /// int Fl_Tree_Item::visible_r() const { if ( !visible() ) return(0); @@ -1072,6 +1762,17 @@ int Fl_Tree_Item::visible_r() const { return(1); } +/// Call this when our geometry is changed. (Font size, label contents, etc) +/// Schedules tree to recalculate itself, as changes to us may affect tree +/// widget's scrollbar visibility and tab sizes. +/// \version 1.3.3 ABI +/// +void Fl_Tree_Item::recalc_tree() { +#if FLTK_ABI_VERSION >= 10303 + _tree->recalc_tree(); +#endif +} + // -// End of "$Id: Fl_Tree_Item.cxx 9706 2012-11-06 20:46:14Z matt $". +// End of "$Id: Fl_Tree_Item.cxx 10272 2014-09-05 02:59:00Z greg.ercolano $". // diff --git a/src/Fl_Tree_Item_Array.cxx b/src/Fl_Tree_Item_Array.cxx index aea7e09..63d05af 100644 --- a/src/Fl_Tree_Item_Array.cxx +++ b/src/Fl_Tree_Item_Array.cxx @@ -1,5 +1,5 @@ // -// "$Id: Fl_Tree_Item_Array.cxx 9706 2012-11-06 20:46:14Z matt $" +// "$Id: Fl_Tree_Item_Array.cxx 10272 2014-09-05 02:59:00Z greg.ercolano $" // #include <stdio.h> @@ -36,6 +36,9 @@ Fl_Tree_Item_Array::Fl_Tree_Item_Array(int new_chunksize) { _items = 0; _total = 0; _size = 0; +#if FLTK_ABI_VERSION >= 10303 + _flags = 0; +#endif _chunksize = new_chunksize; } @@ -50,10 +53,24 @@ Fl_Tree_Item_Array::Fl_Tree_Item_Array(const Fl_Tree_Item_Array* o) { _total = 0; _size = o->_size; _chunksize = o->_chunksize; +#if FLTK_ABI_VERSION >= 10303 + _flags = o->_flags; +#endif for ( int t=0; t<o->_total; t++ ) { - _items[t] = new Fl_Tree_Item(o->_items[t]); +#if FLTK_ABI_VERSION >= 10303 + if ( _flags & MANAGE_ITEM ) { + _items[t] = new Fl_Tree_Item(o->_items[t]); // make new copy of item + ++_total; + _items[t]->update_prev_next(t); // update uses _total's current value + } else { + _items[t] = o->_items[t]; // copy ptr only + ++_total; + } +#else + _items[t] = new Fl_Tree_Item(o->_items[t]); // make new copy of item ++_total; - _items[t]->update_prev_next(t); // update uses _total's current value + _items[t]->update_prev_next(t); // update uses _total's current value +#endif } } @@ -65,8 +82,13 @@ Fl_Tree_Item_Array::Fl_Tree_Item_Array(const Fl_Tree_Item_Array* o) { void Fl_Tree_Item_Array::clear() { if ( _items ) { for ( int t=0; t<_total; t++ ) { - delete _items[t]; - _items[t] = 0; +#if FLTK_ABI_VERSION >= 10303 + if ( _flags & MANAGE_ITEM ) +#endif + { + delete _items[t]; + _items[t] = 0; + } } free((void*)_items); _items = 0; } @@ -110,7 +132,12 @@ void Fl_Tree_Item_Array::insert(int pos, Fl_Tree_Item *new_item) { } _items[pos] = new_item; _total++; - _items[pos]->update_prev_next(pos); // adjust item's prev/next and its neighbors +#if FLTK_ABI_VERSION >= 10303 + if ( _flags & MANAGE_ITEM ) +#endif + { + _items[pos]->update_prev_next(pos); // adjust item's prev/next and its neighbors + } } /// Add an item* to the end of the array. @@ -123,24 +150,55 @@ void Fl_Tree_Item_Array::add(Fl_Tree_Item *val) { insert(_total, val); } +/// Replace the item at \p index with \p newitem. +/// +/// Old item at index position will be destroyed, +/// and the new item will take it's place, and stitched into the linked list. +/// +void Fl_Tree_Item_Array::replace(int index, Fl_Tree_Item *newitem) { + if ( _items[index] ) { // delete if non-zero +#if FLTK_ABI_VERSION >= 10303 + if ( _flags & MANAGE_ITEM ) +#endif + // Destroy old item + delete _items[index]; + } + _items[index] = newitem; // install new item +#if FLTK_ABI_VERSION >= 10303 + if ( _flags & MANAGE_ITEM ) +#endif + { + // Restitch into linked list + _items[index]->update_prev_next(index); + } +} + /// Remove the item at \param[in] index from the array. /// /// The item will be delete'd (if non-NULL), so its destructor will be called. /// void Fl_Tree_Item_Array::remove(int index) { if ( _items[index] ) { // delete if non-zero - delete _items[index]; +#if FLTK_ABI_VERSION >= 10303 + if ( _flags & MANAGE_ITEM ) +#endif + delete _items[index]; } _items[index] = 0; _total--; for ( int i=index; i<_total; i++ ) { // reshuffle the array _items[i] = _items[i+1]; } - if ( index < _total ) { // removed item not last? - _items[index]->update_prev_next(index); // update next item's prev/next and neighbors - } else if ( ((index-1) >= 0) && // removed item IS last? - ((index-1) < _total)) { - _items[index-1]->update_prev_next(index-1); // update prev item's prev/next and neighbors +#if FLTK_ABI_VERSION >= 10303 + if ( _flags & MANAGE_ITEM ) +#endif + { + if ( index < _total ) { // removed item not last? + _items[index]->update_prev_next(index); // update next item's prev/next and neighbors + } else if ( ((index-1) >= 0) && // removed item IS last? + ((index-1) < _total)) { + _items[index-1]->update_prev_next(index-1);// update prev item's prev/next and neighbors + } } } @@ -164,12 +222,88 @@ void Fl_Tree_Item_Array::swap(int ax, int bx) { Fl_Tree_Item *asave = _items[ax]; _items[ax] = _items[bx]; _items[bx] = asave; - // Adjust prev/next ptrs - _items[ax]->update_prev_next(ax); - _items[bx]->update_prev_next(bx); +#if FLTK_ABI_VERSION >= 10303 + if ( _flags & MANAGE_ITEM ) +#endif + { + // Adjust prev/next ptrs + _items[ax]->update_prev_next(ax); + _items[bx]->update_prev_next(bx); + } } #endif /* FLTK_ABI_VERSION */ +/// Move item at 'from' to new position 'to' in the array. +/// Due to how the moving an item shuffles the array around, +/// a positional 'move' implies things that may not be obvious: +/// - When 'from' moved lower in tree, appears BELOW item that was at 'to'. +/// - When 'from' moved higher in tree, appears ABOVE item that was at 'to'. +/// +/// \returns 0 on success, -1 on range error (e.g. if \p 'to' or \p 'from' out of range) +/// +int Fl_Tree_Item_Array::move(int to, int from) { + if ( from == to ) return 0; // nop + if ( to<0 || to>=_total || from<0 || from>=_total ) return -1; + Fl_Tree_Item *item = _items[from]; + // Remove item.. + if ( from < to ) + for ( int t=from; t<to && t<(_total+1); t++ ) + _items[t] = _items[t+1]; + else + for ( int t=from; t>to && t>0; t-- ) + _items[t] = _items[t-1]; + // Move to new position + _items[to] = item; + // Update all children + for ( int r=0; r<_total; r++ ) // XXX: excessive to do all children, + _items[r]->update_prev_next(r); // XXX: but avoids weird boundary issues + return 0; +} + +/// Deparent item at \p 'pos' from our list of children. +/// Similar to a remove() without the destruction of the item. +/// This creates an orphaned item (still allocated, has no parent) +/// which soon after is typically reparented elsewhere. +/// +/// \returns 0 on success, -1 on error (e.g. if \p 'pos' out of range) +/// +int Fl_Tree_Item_Array::deparent(int pos) { + if ( pos>=_total || pos<0 ) return -1; + // Save item being deparented, and its two nearest siblings + Fl_Tree_Item *item = _items[pos]; + Fl_Tree_Item *prev = item->prev_sibling(); + Fl_Tree_Item *next = item->next_sibling(); + // Remove from parent's list of children + _total -= 1; + for ( int t=pos; t<_total; t++ ) + _items[t] = _items[t+1]; // delete, no destroy + // Now an orphan: remove association with old parent and siblings + item->update_prev_next(-1); // become an orphan + // Adjust bereaved siblings + if ( prev ) prev->update_prev_next(pos-1); + if ( next ) next->update_prev_next(pos); + return 0; +} + +/// Reparent specified item as a child of ourself. +/// Typically 'newchild' was recently orphaned with deparent(). +/// +/// \returns 0 on success, -1 on error (e.g. if \p 'pos' out of range) +/// +int Fl_Tree_Item_Array::reparent(Fl_Tree_Item *item, Fl_Tree_Item* newparent, int pos) { + if ( pos<0 || pos>_total ) return -1; + // Add item to new parent + enlarge(1); + _total += 1; + for ( int t=_total-1; t>pos; --t ) // shuffle array to make room for new entry + _items[t] = _items[t-1]; + _items[pos] = item; // insert new entry + // Attach to new parent and siblings + _items[pos]->parent(newparent); // reparent (update_prev_next() needs this) + _items[pos]->update_prev_next(pos); // find new siblings + return 0; +} + // -// End of "$Id: Fl_Tree_Item_Array.cxx 9706 2012-11-06 20:46:14Z matt $". +// End of "$Id: Fl_Tree_Item_Array.cxx 10272 2014-09-05 02:59:00Z greg.ercolano $". // diff --git a/src/Fl_Tree_Prefs.cxx b/src/Fl_Tree_Prefs.cxx index 204340e..322caee 100644 --- a/src/Fl_Tree_Prefs.cxx +++ b/src/Fl_Tree_Prefs.cxx @@ -1,5 +1,5 @@ // -// "$Id: Fl_Tree_Prefs.cxx 9706 2012-11-06 20:46:14Z matt $" +// "$Id: Fl_Tree_Prefs.cxx 10233 2014-08-21 12:16:40Z cand $" // #include <FL/Fl.H> @@ -28,7 +28,7 @@ // INTERNAL: BUILT IN OPEN/STOW XPMS // These can be replaced via prefs.openicon()/closeicon() // -static const char *L_open_xpm[] = { +static const char * const L_open_xpm[] = { #ifdef __APPLE__ "11 11 2 1", ". c None", @@ -64,7 +64,7 @@ static const char *L_open_xpm[] = { }; static Fl_Pixmap L_openpixmap(L_open_xpm); -static const char *L_close_xpm[] = { +static const char * const L_close_xpm[] = { #ifdef __APPLE__ "11 11 2 1", ". c None", @@ -156,6 +156,10 @@ Fl_Tree_Prefs::Fl_Tree_Prefs() { _itemreselectmode = FL_TREE_SELECTABLE_ONCE; _itemdrawmode = FL_TREE_ITEM_DRAW_DEFAULT; #endif +#if FLTK_ABI_VERSION >= 10303 + _itemdrawcallback = 0; + _itemdrawuserdata = 0; +#endif // Let fltk's current 'scheme' affect defaults if ( Fl::scheme() ) { if ( strcmp(Fl::scheme(), "gtk+") == 0 ) { @@ -167,5 +171,5 @@ Fl_Tree_Prefs::Fl_Tree_Prefs() { } // -// End of "$Id: Fl_Tree_Prefs.cxx 9706 2012-11-06 20:46:14Z matt $". +// End of "$Id: Fl_Tree_Prefs.cxx 10233 2014-08-21 12:16:40Z cand $". // diff --git a/src/Fl_Window.cxx b/src/Fl_Window.cxx index d7e4794..a0dca45 100644 --- a/src/Fl_Window.cxx +++ b/src/Fl_Window.cxx @@ -1,5 +1,5 @@ // -// "$Id: Fl_Window.cxx 9706 2012-11-06 20:46:14Z matt $" +// "$Id: Fl_Window.cxx 10405 2014-10-29 15:53:52Z manolo $" // // Window widget class for the Fast Light Tool Kit (FLTK). // @@ -23,6 +23,7 @@ #include <config.h> #include <FL/Fl.H> #include <FL/x.H> +#include <FL/Fl_RGB_Image.H> #include <FL/Fl_Window.H> #include <stdlib.h> #include "flstring.h" @@ -45,11 +46,13 @@ void Fl_Window::_Fl_Window() { } i = 0; xclass_ = 0; - icon_ = 0; + icon_ = new icon_data; + memset(icon_, 0, sizeof(*icon_)); iconlabel_ = 0; resizable(0); size_range_set = 0; minw = maxw = minh = maxh = 0; + shape_data_ = NULL; #if FLTK_ABI_VERSION >= 10301 no_fullscreen_x = 0; no_fullscreen_y = 0; @@ -62,8 +65,6 @@ void Fl_Window::_Fl_Window() { Fl_Window::Fl_Window(int X,int Y,int W, int H, const char *l) : Fl_Group(X, Y, W, H, l) { cursor_default = FL_CURSOR_DEFAULT; - cursor_fg = FL_BLACK; - cursor_bg = FL_WHITE; _Fl_Window(); set_flag(FORCE_POSITION); @@ -73,18 +74,72 @@ Fl_Window::Fl_Window(int W, int H, const char *l) // fix common user error of a missing end() with current(0): : Fl_Group((Fl_Group::current(0),0), 0, W, H, l) { cursor_default = FL_CURSOR_DEFAULT; - cursor_fg = FL_BLACK; - cursor_bg = FL_WHITE; _Fl_Window(); clear_visible(); } +Fl_Window::~Fl_Window() { + hide(); + if (xclass_) { + free(xclass_); + } + free_icons(); + delete icon_; + if (shape_data_) { + if (shape_data_->todelete_) delete shape_data_->todelete_; +#if defined(__APPLE__) + if (shape_data_->mask) { + CGImageRelease(shape_data_->mask); + } +#endif + delete shape_data_; + } +} + + +/** Returns a pointer to the nearest parent window up the widget hierarchy. + This will return sub-windows if there are any, or the parent window if there's no sub-windows. + If this widget IS the top-level window, NULL is returned. + \retval NULL if no window is associated with this widget. + \note for an Fl_Window widget, this returns its <I>parent</I> window + (if any), not <I>this</I> window. + \see top_window() +*/ Fl_Window *Fl_Widget::window() const { for (Fl_Widget *o = parent(); o; o = o->parent()) if (o->type() >= FL_WINDOW) return (Fl_Window*)o; return 0; } + +/** Returns a pointer to the top-level window for the widget. + In other words, the 'window manager window' that contains this widget. + This method differs from window() in that it won't return sub-windows (if there are any). + \returns the top-level window, or NULL if no top-level window is associated with this widget. + \see window() +*/ +Fl_Window *Fl_Widget::top_window() const { + const Fl_Widget *w = this; + while (w->parent()) { w = w->parent(); } // walk up the widget hierarchy to top-level item + return const_cast<Fl_Widget*>(w)->as_window(); // return if window, or NULL if not +} + +/** + Finds the x/y offset of the current widget relative to the top-level window. + \param[out] xoff,yoff Returns the x/y offset + \returns the top-level window (or NULL for a widget that's not in any window) +*/ +Fl_Window* Fl_Widget::top_window_offset(int& xoff, int& yoff) const { + xoff = yoff = 0; + const Fl_Widget *w = this; + while (w && w->window()) { + xoff += w->x(); // accumulate offsets + yoff += w->y(); + w = w->window(); // walk up window hierarchy + } + return const_cast<Fl_Widget*>(w)->as_window(); +} + /** Gets the x position of the window on the screen */ int Fl_Window::x_root() const { Fl_Window *p = window(); @@ -98,50 +153,11 @@ int Fl_Window::y_root() const { return y(); } -void Fl_Window::draw() { - - // The following is similar to Fl_Group::draw(), but ... - // - we draw the box with x=0 and y=0 instead of x() and y() - // - we don't draw a label - - if (damage() & ~FL_DAMAGE_CHILD) { // draw the entire thing - draw_box(box(),0,0,w(),h(),color()); // draw box with x/y = 0 - } - draw_children(); - -#ifdef __APPLE_QUARTZ__ - // on OS X, windows have no frame. Before OS X 10.7, to resize a window, we drag the lower right - // corner. This code draws a little ribbed triangle for dragging. - if (fl_mac_os_version < 100700 && fl_gc && !parent() && resizable() && - (!size_range_set || minh!=maxh || minw!=maxw)) { - int dx = Fl::box_dw(box())-Fl::box_dx(box()); - int dy = Fl::box_dh(box())-Fl::box_dy(box()); - if (dx<=0) dx = 1; - if (dy<=0) dy = 1; - int x1 = w()-dx-1, x2 = x1, y1 = h()-dx-1, y2 = y1; - Fl_Color c[4] = { - color(), - fl_color_average(color(), FL_WHITE, 0.7f), - fl_color_average(color(), FL_BLACK, 0.6f), - fl_color_average(color(), FL_BLACK, 0.8f), - }; - int i; - for (i=dx; i<12; i++) { - fl_color(c[i&3]); - fl_line(x1--, y1, x2, y2--); - } - } -#endif - -# if defined(FLTK_USE_CAIRO) - Fl::cairo_make_current(this); // checkout if an update is necessary -# endif -} - void Fl_Window::label(const char *name) { label(name, iconlabel()); // platform dependent } +/** Sets the window titlebar label to a copy of a character string */ void Fl_Window::copy_label(const char *a) { Fl_Widget::copy_label(a); label(label(), iconlabel()); // platform dependent @@ -268,17 +284,175 @@ const char *Fl_Window::xclass() const } } -/** Gets the current icon window target dependent data. */ +/** Sets a single default window icon. + + \param[in] icon default icon for all windows subsequently created + + \see Fl_Window::default_icons(const Fl_RGB_Image *[], int) + \see Fl_Window::icon(const Fl_RGB_Image *) + \see Fl_Window::icons(const Fl_RGB_Image *[], int) + */ +void Fl_Window::default_icon(const Fl_RGB_Image *icon) { + default_icons(&icon, 1); +} + +/** Sets the default window icons. + + The default icons are used for all windows that don't have their + own icons set before show() is called. You can change the default + icons whenever you want, but this only affects windows that are + created (and shown) after this call. + + The given images in \p icons are copied. You can use a local + variable or free the images immediately after this call. + + \param[in] icons default icons for all windows subsequently created + \param[in] count number of images in \p icons. set to 0 to remove + the current default icons + + \see Fl_Window::default_icon(const Fl_RGB_Image *) + \see Fl_Window::icon(const Fl_RGB_Image *) + \see Fl_Window::icons(const Fl_RGB_Image *[], int) + */ +void Fl_Window::default_icons(const Fl_RGB_Image *icons[], int count) { + Fl_X::set_default_icons(icons, count); +} + +/** Sets a single window icon. + + \param[in] icon icon for this window + + \see Fl_Window::default_icon(const Fl_RGB_Image *) + \see Fl_Window::default_icons(const Fl_RGB_Image *[], int) + \see Fl_Window::icons(const Fl_RGB_Image *[], int) + */ +void Fl_Window::icon(const Fl_RGB_Image *icon) { + icons(&icon, 1); +} + +/** Sets the window icons. + + The given images in \p icons are copied. You can use a local + variable or free the images immediately after this call. + + \param[in] icons icons for this window + \param[in] count number of images in \p icons. set to 0 to remove + the current icons + + \see Fl_Window::default_icon(const Fl_RGB_Image *) + \see Fl_Window::default_icons(const Fl_RGB_Image *[], int) + \see Fl_Window::icon(const Fl_RGB_Image *) + */ +void Fl_Window::icons(const Fl_RGB_Image *icons[], int count) { + free_icons(); + + if (count > 0) { + icon_->icons = new Fl_RGB_Image*[count]; + icon_->count = count; + // FIXME: Fl_RGB_Image lacks const modifiers on methods + for (int i = 0;i < count;i++) + icon_->icons[i] = (Fl_RGB_Image*)((Fl_RGB_Image*)icons[i])->copy(); + } + + if (i) + i->set_icons(); +} + +/** Gets the current icon window target dependent data. + \deprecated in 1.3.3 + */ const void *Fl_Window::icon() const { - return icon_; + return icon_->legacy_icon; } -/** Sets the current icon window target dependent data. */ +/** Sets the current icon window target dependent data. + \deprecated in 1.3.3 + */ void Fl_Window::icon(const void * ic) { - icon_ = ic; + free_icons(); + icon_->legacy_icon = ic; +} + +/** Deletes all icons previously attached to the window. + \see Fl_Window::icons(const Fl_RGB_Image *icons[], int count) + */ +void Fl_Window::free_icons() { + int i; + + icon_->legacy_icon = 0L; + + if (icon_->icons) { + for (i = 0;i < icon_->count;i++) + delete icon_->icons[i]; + delete [] icon_->icons; + icon_->icons = 0L; + } + + icon_->count = 0; + +#ifdef WIN32 + if (icon_->big_icon) + DestroyIcon(icon_->big_icon); + if (icon_->small_icon) + DestroyIcon(icon_->small_icon); + + icon_->big_icon = NULL; + icon_->small_icon = NULL; +#endif } +/** + Waits for the window to be fully displayed after calling show(). + + Fl_Window::show() is not guaranteed to show and draw the window on + all platforms immediately. Instead this is done in the background; + particularly on X11 this will take a few messages (client server + roundtrips) to display the window. + + Usually this small delay doesn't matter, but in some cases you may + want to have the window instantiated and displayed synchronously. + + Currently (as of FLTK 1.3.3) this method only has an effect on X11. + On Windows and Mac OS X show() is always synchronous. If you want to + write portable code and need this synchronous show() feature, add + win->wait_for_expose() on all platforms, FLTK will just do the + right thing. + + This method can be used for displaying splash screens before + calling Fl::run() or for having exact control over which window + has focus after calling show(). + + If the window is not shown(), this method does nothing. + + \see virtual void Fl_Window::show() + + Example code for displaying a window before calling Fl::run() + + \code + Fl_Double_Window win = new Fl_Double_Window(...); + + // do more window initialization here ... + + win->show(); // show window + win->wait_for_expose(); // wait, until displayed + Fl::flush(); // make sure everything gets drawn + + // do more initialization work that needs some time here ... + + Fl::run(); // start FLTK event loop + \endcode + + Note that the window will not be responsive until the event loop + is started with Fl::run(). +*/ + +void Fl_Window::wait_for_expose() { + if (!shown()) return; + while (!i || i->wait_for_expose) { + Fl::wait(); + } +} // -// End of "$Id: Fl_Window.cxx 9706 2012-11-06 20:46:14Z matt $". +// End of "$Id: Fl_Window.cxx 10405 2014-10-29 15:53:52Z manolo $". // diff --git a/src/Fl_Window_fullscreen.cxx b/src/Fl_Window_fullscreen.cxx index a7044eb..2808f29 100644 --- a/src/Fl_Window_fullscreen.cxx +++ b/src/Fl_Window_fullscreen.cxx @@ -1,5 +1,5 @@ // -// "$Id: Fl_Window_fullscreen.cxx 9706 2012-11-06 20:46:14Z matt $" +// "$Id: Fl_Window_fullscreen.cxx 10189 2014-06-11 09:10:53Z ossman $" // // Fullscreen window support for the Fast Light Tool Kit (FLTK). // @@ -36,6 +36,10 @@ int Fl_Window::no_fullscreen_x = 0; int Fl_Window::no_fullscreen_y = 0; int Fl_Window::no_fullscreen_w = 0; int Fl_Window::no_fullscreen_h = 0; +int Fl_Window::fullscreen_screen_top = -1; +int Fl_Window::fullscreen_screen_bottom = -1; +int Fl_Window::fullscreen_screen_left = -1; +int Fl_Window::fullscreen_screen_right = -1; #endif void Fl_Window::border(int b) { @@ -95,7 +99,24 @@ void Fl_Window::fullscreen_off() { fullscreen_off(no_fullscreen_x, no_fullscreen_y, no_fullscreen_w, no_fullscreen_h); } +void Fl_Window::fullscreen_screens(int top, int bottom, int left, int right) { + if ((top < 0) || (bottom < 0) || (left < 0) || (right < 0)) { + fullscreen_screen_top = -1; + fullscreen_screen_bottom = -1; + fullscreen_screen_left = -1; + fullscreen_screen_right = -1; + } else { + fullscreen_screen_top = top; + fullscreen_screen_bottom = bottom; + fullscreen_screen_left = left; + fullscreen_screen_right = right; + } + + if (shown() && fullscreen_active()) + fullscreen_x(); +} + // -// End of "$Id: Fl_Window_fullscreen.cxx 9706 2012-11-06 20:46:14Z matt $". +// End of "$Id: Fl_Window_fullscreen.cxx 10189 2014-06-11 09:10:53Z ossman $". // diff --git a/src/Fl_Window_shape.cxx b/src/Fl_Window_shape.cxx new file mode 100644 index 0000000..3204944 --- /dev/null +++ b/src/Fl_Window_shape.cxx @@ -0,0 +1,407 @@ +// +// "$Id: Fl_Window_shape.cxx 10348 2014-10-01 16:37:13Z manolo $" +// +// implementation of Fl_Window::shape(Fl_Image*) for the Fast Light Tool Kit (FLTK). +// +// Copyright 2010-2014 by Bill Spitzak and others. +// +// This library is free software. Distribution and use rights are outlined in +// the file "COPYING" which should have been included with this file. If this +// file is missing or damaged, see the license at: +// +// http://www.fltk.org/COPYING.php +// +// Please report all bugs and problems to: +// +// http://www.fltk.org/str.php +// + +#include <FL/Fl.H> +#include <FL/fl_draw.H> +#include <FL/x.H> +#include <FL/Fl_Window.H> +#include <FL/Fl_Bitmap.H> +#include <FL/Fl_Pixmap.H> +#include <string.h> + +#ifdef WIN32 +# include <malloc.h> // needed for VisualC2010 +#elif !defined(__APPLE__) +#include <config.h> +#if HAVE_DLFCN_H +#include <dlfcn.h> +#endif +#define ShapeBounding 0 +#define ShapeSet 0 +#endif + + +#if defined(__APPLE__) + +static void MyProviderReleaseData (void *info, const void *data, size_t size) { + delete[] (uchar*)data; +} + +// bitwise inversion of all 4-bit quantities +static const unsigned char swapped[16] = {0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15}; + +static inline uchar swap_byte(const uchar b) { + // reverse the order of bits of byte b: 1->8 becomes 8->1 + return (swapped[b & 0xF] << 4) | swapped[b >> 4]; +} + +#elif defined(WIN32) + +static inline BYTE bit(int x) { return (BYTE)(1 << (x%8)); } + +static HRGN bitmap2region(Fl_Bitmap* image) { + HRGN hRgn = 0; + /* Does this need to be dynamically determined, perhaps? */ + const int ALLOC_UNIT = 100; + DWORD maxRects = ALLOC_UNIT; + + RGNDATA* pData = (RGNDATA*)malloc(sizeof(RGNDATAHEADER)+(sizeof(RECT)*maxRects)); + pData->rdh.dwSize = sizeof(RGNDATAHEADER); + pData->rdh.iType = RDH_RECTANGLES; + pData->rdh.nCount = pData->rdh.nRgnSize = 0; + SetRect(&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0); + + const int bytesPerLine = (image->w() + 7)/8; + BYTE* p, *data = (BYTE*)image->array; + for (int y = 0; y < image->h(); y++) { + // each row, left to right + for (int x = 0; x < image->w(); x++) { + int x0 = x; + while (x < image->w()) { + p = data + x / 8; + if (!((*p) & bit(x))) break; // transparent pixel + x++; + } + if (x > x0) { + RECT *pr; + /* Add the pixels (x0, y) to (x, y+1) as a new rectangle + * in the region + */ + if (pData->rdh.nCount >= maxRects) { + maxRects += ALLOC_UNIT; + pData = (RGNDATA*)realloc(pData, sizeof(RGNDATAHEADER) + + (sizeof(RECT)*maxRects)); + } + pr = (RECT*)&pData->Buffer; + SetRect(&pr[pData->rdh.nCount], x0, y, x, y+1); + if (x0 < pData->rdh.rcBound.left) + pData->rdh.rcBound.left = x0; + if (y < pData->rdh.rcBound.top) + pData->rdh.rcBound.top = y; + if (x > pData->rdh.rcBound.right) + pData->rdh.rcBound.right = x; + if (y+1 > pData->rdh.rcBound.bottom) + pData->rdh.rcBound.bottom = y+1; + pData->rdh.nCount++; + /* On Windows98, ExtCreateRegion() may fail if the + * number of rectangles is too large (ie: > + * 4000). Therefore, we have to create the region by + * multiple steps. + */ + if (pData->rdh.nCount == 2000) { + HRGN h = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER) + + (sizeof(RECT)*maxRects), pData); + if (hRgn) { + CombineRgn(hRgn, hRgn, h, RGN_OR); + DeleteObject(h); + } else + hRgn = h; + pData->rdh.nCount = 0; + SetRect(&pData->rdh.rcBound, MAXLONG, MAXLONG, 0, 0); + } + } + } + /* Go to next row */ + data += bytesPerLine; + } + /* Create or extend the region with the remaining rectangles*/ + HRGN h = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER) + + (sizeof(RECT)*maxRects), pData); + if (hRgn) { + CombineRgn(hRgn, hRgn, h, RGN_OR); + DeleteObject(h); + } else hRgn = h; + free(pData); // I've created the region so I can free this now, right? + return hRgn; +} + +#else + +#ifndef FL_DOXYGEN +void Fl_Window::combine_mask() +{ + typedef void (*XShapeCombineMask_type)(Display*, int, int, int, int, Pixmap, int); + static XShapeCombineMask_type XShapeCombineMask_f = NULL; + static int beenhere = 0; + typedef Bool (*XShapeQueryExtension_type)(Display*, int*, int*); + if (!beenhere) { + beenhere = 1; +#if HAVE_DLSYM && HAVE_DLFCN_H + fl_open_display(); + void *handle = dlopen(NULL, RTLD_LAZY); // search symbols in executable + XShapeQueryExtension_type XShapeQueryExtension_f = (XShapeQueryExtension_type)dlsym(handle, "XShapeQueryExtension"); + XShapeCombineMask_f = (XShapeCombineMask_type)dlsym(handle, "XShapeCombineMask"); + // make sure that the X server has the SHAPE extension + int error_base, shapeEventBase; + if ( !( XShapeQueryExtension_f && XShapeCombineMask_f && + XShapeQueryExtension_f(fl_display, &shapeEventBase, &error_base) ) ) XShapeCombineMask_f = NULL; +#endif + } + if (!XShapeCombineMask_f) return; + shape_data_->lw_ = w(); + shape_data_->lh_ = h(); + Fl_Bitmap* temp = (Fl_Bitmap*)shape_data_->shape_->copy(shape_data_->lw_, shape_data_->lh_); + Pixmap pbitmap = XCreateBitmapFromData(fl_display, fl_xid(this), + (const char*)temp->array, + temp->w(), temp->h()); + XShapeCombineMask_f(fl_display, fl_xid(this), ShapeBounding, 0, 0, pbitmap, ShapeSet); + if (pbitmap != None) XFreePixmap(fl_display, pbitmap); + delete temp; +} +#endif // !FL_DOXYGEN + +#endif // __APPLE__ + + +void Fl_Window::shape_bitmap_(Fl_Bitmap* b) { + shape_data_->shape_ = b; +#if defined(__APPLE__) + if (b) { + // complement mask bits and perform bitwise inversion of all bytes and also reverse top and bottom + int bytes_per_row = (b->w() + 7)/8; + uchar *from = new uchar[bytes_per_row * b->h()]; + for (int i = 0; i < b->h(); i++) { + uchar *p = (uchar*)b->array + bytes_per_row * i; + uchar *last = p + bytes_per_row; + uchar *q = from + (b->h() - 1 - i) * bytes_per_row; + while (p < last) { + *q++ = swap_byte(~*p++); + } + } + CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, from, bytes_per_row * b->h(), MyProviderReleaseData); + shape_data_->mask = CGImageMaskCreate(b->w(), b->h(), 1, 1, bytes_per_row, provider, NULL, false); + CFRelease(provider); + } +#endif +} + + +#if defined(__APPLE__) // on the mac, use an 8-bit mask +/* the image can be of any depth + offset gives the byte offset from the pixel start to the byte used to construct the shape + */ +void Fl_Window::shape_alpha_(Fl_RGB_Image* img, int offset) { + int i, d = img->d(), w = img->w(), h = img->h(); + shape_data_->shape_ = img; + if (shape_data_->shape_) { + // reverse top and bottom and convert to gray scale if img->d() == 3 and complement bits + int bytes_per_row = w * d; + uchar *from = new uchar[w * h]; + for ( i = 0; i < h; i++) { + uchar *p = (uchar*)img->array + bytes_per_row * i + offset; + uchar *last = p + bytes_per_row; + uchar *q = from + (h - 1 - i) * w; + while (p < last) { + if (d == 3) { + unsigned u = *p++; + u += *p++; + u += *p++; + *q++ = ~(u/3); + } + else { + *q++ = ~(*p); + p += d; + } + } + } + CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, from, w * h, MyProviderReleaseData); + shape_data_->mask = CGImageMaskCreate(w, h, 8, 8, w, provider, NULL, false); + CFRelease(provider); + } +} + +#else + +/* the img image can be of any depth + offset gives the byte offset from the pixel start to the byte used to construct the shape + */ +void Fl_Window::shape_alpha_(Fl_RGB_Image* img, int offset) { + int i, j, d = img->d(), w = img->w(), h = img->h(), bytesperrow = (w+7)/8; + unsigned u; + uchar byte, onebit; + // build an Fl_Bitmap covering the non-fully transparent/black part of the image + const uchar* bits = new uchar[h*bytesperrow]; // to store the bitmap + const uchar* alpha = img->array + offset; // points to alpha value of rgba pixels + for (i = 0; i < h; i++) { + uchar *p = (uchar*)bits + i * bytesperrow; + byte = 0; + onebit = 1; + for (j = 0; j < w; j++) { + if (d == 3) { + u = *alpha; + u += *(alpha+1); + u += *(alpha+2); + } + else u = *alpha; + if (u > 0) { // if the pixel is not fully transparent/black + byte |= onebit; // turn on the corresponding bit of the bitmap + } + onebit = onebit << 1; // move the single set bit one position to the left + if (onebit == 0 || j == w-1) { + onebit = 1; + *p++ = byte; // store in bitmap one pack of bits + byte = 0; + } + alpha += d; // point to alpha value of next pixel + } + } + Fl_Bitmap* bitmap = new Fl_Bitmap(bits, w, h); + bitmap->alloc_array = 1; + shape_bitmap_(bitmap); + shape_data_->todelete_ = bitmap; +} + +#endif + + +void Fl_Window::shape_pixmap_(Fl_Pixmap* pixmap) { + Fl_RGB_Image* rgba = new Fl_RGB_Image(pixmap); + shape_alpha_(rgba, 3); + delete rgba; +} + +#if FLTK_ABI_VERSION < 10303 && !defined(FL_DOXYGEN) +Fl_Window::shape_data_type* Fl_Window::shape_data_ = NULL; +#endif + +/** Assigns a non-rectangular shape to the window. + This function gives an arbitrary shape (not just a rectangular region) to an Fl_Window. + An Fl_Image of any dimension can be used as mask; it is rescaled to the window's dimension as needed. + + The layout and widgets inside are unaware of the mask shape, and most will act as though the window's + rectangular bounding box is available + to them. It is up to you to make sure they adhere to the bounds of their masking shape. + + The \p img argument can be an Fl_Bitmap, Fl_Pixmap or Fl_RGB_Image: + \li With Fl_Bitmap or Fl_Pixmap, the shaped window covers the image part where bitmap bits equal one, + or where the pixmap is not fully transparent. + \li With an Fl_RGB_Image with an alpha channel (depths 2 or 4), the shaped window covers the image part + that is not fully transparent. + \li With an Fl_RGB_Image of depth 1 (gray-scale) or 3 (RGB), the shaped window covers the non-black image part. + + Platform details: + \li On the unix/linux platform, the SHAPE extension of the X server is required. + This function does control the shape of Fl_Gl_Window instances. + \li On the MSWindows platform, this function does nothing with class Fl_Gl_Window. + \li On the Mac platform, OS version 10.4 or above is required. + An 8-bit shape-mask is used when \p img is an Fl_RGB_Image: + with depths 2 or 4, the image alpha channel becomes the shape mask such that areas with alpha = 0 + are out of the shaped window; + with depths 1 or 3, white and black are in and out of the + shaped window, respectively, and other colors give intermediate masking scores. + This function does nothing with class Fl_Gl_Window. + + The window borders and caption created by the window system are turned off by default. They + can be re-enabled by calling Fl_Window::border(1). + + A usage example is found at example/shapedwindow.cxx. + + \version 1.3.3 (and requires compilation with -DFLTK_ABI_VERSION = 10303) + */ +void Fl_Window::shape(const Fl_Image* img) { +#if FLTK_ABI_VERSION >= 10303 + if (shape_data_) { + if (shape_data_->todelete_) { delete shape_data_->todelete_; } +#if defined(__APPLE__) + if (shape_data_->mask) { CGImageRelease(shape_data_->mask); } +#endif + } + else { + shape_data_ = new shape_data_type; + } + memset(shape_data_, 0, sizeof(shape_data_type)); + border(false); + int d = img->d(); + if (d && img->count() >= 2) shape_pixmap_((Fl_Pixmap*)img); + else if (d == 0) shape_bitmap_((Fl_Bitmap*)img); + else if (d == 2 || d == 4) shape_alpha_((Fl_RGB_Image*)img, d - 1); + else if ((d == 1 || d == 3) && img->count() == 1) shape_alpha_((Fl_RGB_Image*)img, 0); +#endif +} + +void Fl_Window::draw() { + if (shape_data_) { +# if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 + if (shape_data_->mask && (CGContextClipToMask != NULL)) { + CGContextClipToMask(fl_gc, CGRectMake(0,0,w(),h()), shape_data_->mask); // requires Mac OS 10.4 + } + CGContextSaveGState(fl_gc); +#elif defined(WIN32) + if ((shape_data_->lw_ != w() || shape_data_->lh_ != h()) && shape_data_->shape_) { + // size of window has changed since last time + shape_data_->lw_ = w(); + shape_data_->lh_ = h(); + Fl_Bitmap* temp = (Fl_Bitmap*)shape_data_->shape_->copy(shape_data_->lw_, shape_data_->lh_); + HRGN region = bitmap2region(temp); + SetWindowRgn(fl_xid(this), region, TRUE); // the system deletes the region when it's no longer needed + delete temp; + } +#elif !(defined(__APPLE__) || defined(WIN32)) + if (( shape_data_->lw_ != w() || shape_data_->lh_ != h() ) && shape_data_->shape_) { + // size of window has changed since last time + combine_mask(); + } +# endif + } + + // The following is similar to Fl_Group::draw(), but ... + // - we draw the box with x=0 and y=0 instead of x() and y() + // - we don't draw a label + + if (damage() & ~FL_DAMAGE_CHILD) { // draw the entire thing + draw_box(box(),0,0,w(),h(),color()); // draw box with x/y = 0 + } + draw_children(); + +#ifdef __APPLE_QUARTZ__ + // on OS X, windows have no frame. Before OS X 10.7, to resize a window, we drag the lower right + // corner. This code draws a little ribbed triangle for dragging. + if (fl_mac_os_version < 100700 && fl_gc && !parent() && resizable() && + (!size_range_set || minh!=maxh || minw!=maxw)) { + int dx = Fl::box_dw(box())-Fl::box_dx(box()); + int dy = Fl::box_dh(box())-Fl::box_dy(box()); + if (dx<=0) dx = 1; + if (dy<=0) dy = 1; + int x1 = w()-dx-1, x2 = x1, y1 = h()-dx-1, y2 = y1; + Fl_Color c[4] = { + color(), + fl_color_average(color(), FL_WHITE, 0.7f), + fl_color_average(color(), FL_BLACK, 0.6f), + fl_color_average(color(), FL_BLACK, 0.8f), + }; + int i; + for (i=dx; i<12; i++) { + fl_color(c[i&3]); + fl_line(x1--, y1, x2, y2--); + } + } +#endif +# if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 + if (shape_data_) CGContextRestoreGState(fl_gc); +# endif + +# if defined(FLTK_USE_CAIRO) + Fl::cairo_make_current(this); // checkout if an update is necessary +# endif +} + + + +// +// End of "$Id: Fl_Window_shape.cxx 10348 2014-10-01 16:37:13Z manolo $". +// diff --git a/src/Fl_XPM_Image.cxx b/src/Fl_XPM_Image.cxx index f79bfef..580d5fe 100644 --- a/src/Fl_XPM_Image.cxx +++ b/src/Fl_XPM_Image.cxx @@ -1,5 +1,5 @@ // -// "$Id: Fl_XPM_Image.cxx 9325 2012-04-05 05:12:30Z fabien $" +// "$Id: Fl_XPM_Image.cxx 10156 2014-05-22 12:11:17Z manolo $" // // Fl_XPM_Image routines. // @@ -60,6 +60,7 @@ Fl_XPM_Image::Fl_XPM_Image(const char *name) : Fl_Pixmap((char *const*)0) { int malloc_size = INITIALLINES; char buffer[MAXSIZE+20]; int i = 0; + int W,H,ncolors,chars_per_pixel; while (fgets(buffer,MAXSIZE+20,f)) { if (buffer[0] != '\"') continue; char *myp = buffer; @@ -74,7 +75,7 @@ Fl_XPM_Image::Fl_XPM_Image(const char *name) : Fl_Pixmap((char *const*)0) { case 'x': { q++; int n = 0; - for (int x = 0; x < 3; x++) { + for (int x = 0; x < 2; x++) { int xd = hexdigit(*q); if (xd > 15) break; n = (n<<4)+xd; @@ -107,6 +108,15 @@ Fl_XPM_Image::Fl_XPM_Image(const char *name) : Fl_Pixmap((char *const*)0) { new_data = temp_data; malloc_size += INITIALLINES; } + // first line has 4 ints: width, height, ncolors, chars_per_pixel + // followed by color segment: + // if ncolors < 0 this is FLTK (non standard) compressed colormap - all colors coded in single line of 4*ncolors bytes + // otherwise - ncolor lines of at least chars_per_pixel bytes + // followed by pic segment: H lines of at least chars_per_pixel*W bytes + // next line: would have loved to use measure_pixmap, but it doesn't return all the data! + if ((!i) && (sscanf(buffer,"%d%d%d%d", &W, &H, &ncolors, &chars_per_pixel) < 4)) goto bad_data; // first line + else if ((i > (ncolors<0?1:ncolors)) && (myp-buffer-1<W*chars_per_pixel)) goto bad_data; // pic segment + else if (myp-buffer-1<(ncolors<0?-ncolors*4:chars_per_pixel)) goto bad_data; // color segment new_data[i] = new char[myp-buffer+1]; memcpy(new_data[i], buffer,myp-buffer); new_data[i][myp-buffer] = 0; @@ -114,14 +124,21 @@ Fl_XPM_Image::Fl_XPM_Image(const char *name) : Fl_Pixmap((char *const*)0) { } fclose(f); - + f = NULL; + if ((!i) || (i<1+(ncolors<0?1:ncolors)+H)) goto bad_data; data((const char **)new_data, i); alloc_data = 1; measure(); + return; + // dealloc and close as needed when bad data was found +bad_data: + while (i > 0) delete[] new_data[--i]; + delete[] new_data; + if (f) fclose(f); } // -// End of "$Id: Fl_XPM_Image.cxx 9325 2012-04-05 05:12:30Z fabien $". +// End of "$Id: Fl_XPM_Image.cxx 10156 2014-05-22 12:11:17Z manolo $". // diff --git a/src/Fl_arg.cxx b/src/Fl_arg.cxx index 74e525f..99bf6a3 100644 --- a/src/Fl_arg.cxx +++ b/src/Fl_arg.cxx @@ -1,5 +1,5 @@ // -// "$Id: Fl_arg.cxx 9365 2012-04-21 11:13:10Z matt $" +// "$Id: Fl_arg.cxx 10145 2014-05-04 13:46:09Z manolo $" // // Optional argument initialization code for the Fast Light Tool Kit (FLTK). // @@ -435,7 +435,7 @@ without express or implied warranty. static int ReadInteger(char* string, char** NextString) { - register int Result = 0; + int Result = 0; int Sign = 1; if (*string == '+') @@ -458,7 +458,7 @@ int XParseGeometry(const char* string, int* x, int* y, unsigned int* width, unsigned int* height) { int mask = NoValue; - register char *strind; + char *strind; unsigned int tempWidth = 0, tempHeight = 0; int tempX = 0, tempY = 0; char *nextCharacter; @@ -541,5 +541,5 @@ int XParseGeometry(const char* string, int* x, int* y, #endif // ifdef WIN32 // -// End of "$Id: Fl_arg.cxx 9365 2012-04-21 11:13:10Z matt $". +// End of "$Id: Fl_arg.cxx 10145 2014-05-04 13:46:09Z manolo $". // diff --git a/src/Fl_cocoa.mm b/src/Fl_cocoa.mm index a361f29..6f5b8b1 100644 --- a/src/Fl_cocoa.mm +++ b/src/Fl_cocoa.mm @@ -1,9 +1,9 @@ // -// "$Id: Fl_cocoa.mm 9734 2012-11-30 18:20:36Z manolo $" +// "$Id: Fl_cocoa.mm 10427 2014-11-02 21:06:07Z manolo $" // // MacOS-Cocoa specific code for the Fast Light Tool Kit (FLTK). // -// Copyright 1998-2012 by Bill Spitzak and others. +// Copyright 1998-2014 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this @@ -41,7 +41,6 @@ extern "C" { #include <FL/x.H> #include <FL/Fl_Window.H> #include <FL/Fl_Tooltip.H> -#include <FL/Fl_Sys_Menu_Bar.H> #include <FL/Fl_Printer.H> #include <FL/Fl_Input_.H> #include <FL/Fl_Text_Display.H> @@ -51,6 +50,8 @@ extern "C" { #include <unistd.h> #include <stdarg.h> #include <math.h> +#include <limits.h> +#include <dlfcn.h> #import <Cocoa/Cocoa.h> @@ -80,6 +81,7 @@ typedef unsigned int NSUInteger; // external functions extern void fl_fix_focus(); extern unsigned short *fl_compute_macKeyLookUp(); +extern int fl_send_system_handlers(void *e); // forward definition of functions in this file // converting cr lf converter function @@ -88,27 +90,34 @@ static void createAppleMenu(void); static Fl_Region MacRegionMinusRect(Fl_Region r, int x,int y,int w,int h); static void cocoaMouseHandler(NSEvent *theEvent); static int calc_mac_os_version(); +static void clipboard_check(void); +static NSString *calc_utf8_format(void); +static void im_update(void); +static unsigned make_current_counts = 0; // if > 0, then Fl_Window::make_current() can be called only once +static Fl_X *fl_x_to_redraw = NULL; // set by Fl_X::flush() to the Fl_X object of the window to be redrawn -static Fl_Quartz_Graphics_Driver fl_quartz_driver; -static Fl_Display_Device fl_quartz_display(&fl_quartz_driver); -Fl_Display_Device *Fl_Display_Device::_display = &fl_quartz_display; // the platform display +Fl_Display_Device *Fl_Display_Device::_display = new Fl_Display_Device(new Fl_Quartz_Graphics_Driver); // the platform display // public variables CGContextRef fl_gc = 0; -void *fl_system_menu; // this is really a NSMenu* -Fl_Sys_Menu_Bar *fl_sys_menu_bar = 0; -void *fl_default_cursor; // this is really a NSCursor* void *fl_capture = 0; // (NSWindow*) we need this to compensate for a missing(?) mouse capture bool fl_show_iconic; // true if called from iconize() - shows the next created window in collapsed state //int fl_disable_transient_for; // secret method of removing TRANSIENT_FOR Window fl_window; Fl_Window *Fl_Window::current_; int fl_mac_os_version = calc_mac_os_version(); // the version number of the running Mac OS X (e.g., 100604 for 10.6.4) +static SEL inputContextSEL = (fl_mac_os_version >= 100600 ? @selector(inputContext) : @selector(FLinputContext)); +Fl_Fontdesc* fl_fonts = Fl_X::calc_fl_fonts(); +static NSString *utf8_format = calc_utf8_format(); // forward declarations of variables in this file static int got_events = 0; static Fl_Window* resize_from_system; static int main_screen_height; // height of menubar-containing screen used to convert between Cocoa and FLTK global screen coordinates +// through_drawRect = YES means the drawRect: message was sent to the view, +// thus the graphics context was prepared by the system +static BOOL through_drawRect = NO; +static int im_enabled = -1; #if CONSOLIDATE_MOTION static Fl_Window* send_motion; @@ -117,6 +126,29 @@ extern Fl_Window* fl_xmousewin; enum { FLTKTimerEvent = 1, FLTKDataReadyEvent }; +// Carbon functions and definitions + +typedef void *TSMDocumentID; + +extern "C" enum { + kTSMDocumentEnabledInputSourcesPropertyTag = 'enis' // from Carbon/TextServices.h +}; + +// Undocumented voodoo. Taken from Mozilla. +static const int smEnableRomanKybdsOnly = -23; + +typedef TSMDocumentID (*TSMGetActiveDocument_type)(void); +static TSMGetActiveDocument_type TSMGetActiveDocument; +typedef OSStatus (*TSMSetDocumentProperty_type)(TSMDocumentID, OSType, UInt32, void*); +static TSMSetDocumentProperty_type TSMSetDocumentProperty; +typedef OSStatus (*TSMRemoveDocumentProperty_type)(TSMDocumentID, OSType); +static TSMRemoveDocumentProperty_type TSMRemoveDocumentProperty; +typedef CFArrayRef (*TISCreateASCIICapableInputSourceList_type)(void); +static TISCreateASCIICapableInputSourceList_type TISCreateASCIICapableInputSourceList; + +typedef void (*KeyScript_type)(short); +static KeyScript_type KeyScript; + /* fltk-utf8 placekeepers */ void fl_reset_spot() @@ -462,9 +494,7 @@ static void processFLTKEvent(void) { * break the current event loop */ static void breakMacEventLoop() -{ - fl_lock_function(); - +{ NSPoint pt={0,0}; NSEvent *event = [NSEvent otherEventWithType:NSApplicationDefined location:pt modifierFlags:0 @@ -472,7 +502,6 @@ static void breakMacEventLoop() windowNumber:0 context:NULL subtype:FLTKTimerEvent data1:0 data2:0]; [NSApp postEvent:event atStart:NO]; - fl_unlock_function(); } // @@ -520,6 +549,7 @@ static void delete_timer(MacTimeout& t) static void do_timer(CFRunLoopTimerRef timer, void* data) { + fl_lock_function(); current_timer = (MacTimeout*)data; current_timer->pending = 0; (current_timer->callback)(current_timer->data); @@ -528,6 +558,7 @@ static void do_timer(CFRunLoopTimerRef timer, void* data) current_timer = NULL; breakMacEventLoop(); + fl_unlock_function(); } void Fl::add_timeout(double time, Fl_Timeout_Handler cb, void* data) @@ -628,11 +659,35 @@ void Fl::remove_timeout(Fl_Timeout_Handler cb, void* data) contentRect:(NSRect)rect styleMask:(NSUInteger)windowStyle; - (Fl_Window *)getFl_Window; +/* These two functions allow to check if a window contains OpenGL-subwindows. + This is useful only for Mac OS < 10.7 to repair a problem apparent with the "cube" test program: + if the cube window is moved around rapidly (with OS < 10.7), the GL pixels leak away from where they should be. + The repair is performed by [FLWindowDelegate windowDidMove:], only if OS < 10.7. + */ - (BOOL)containsGLsubwindow; -- (void)setContainsGLsubwindow:(BOOL)contains; +- (void)containsGLsubwindow:(BOOL)contains; +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 +- (NSPoint)convertBaseToScreen:(NSPoint)aPoint; +#endif @end @implementation FLWindow +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 +- (NSPoint)convertBaseToScreen:(NSPoint)aPoint +{ + if (fl_mac_os_version >= 100700) { + NSRect r = [self convertRectToScreen:NSMakeRect(aPoint.x, aPoint.y, 0, 0)]; + return r.origin; + } + else { + // replaces return [super convertBaseToScreen:aPoint] that may trigger a compiler warning + typedef NSPoint (*convertIMP)(id, SEL, NSPoint); + convertIMP addr = (convertIMP)[NSWindow instanceMethodForSelector:@selector(convertBaseToScreen:)]; + return addr(self, @selector(convertBaseToScreen:), aPoint); + } +} +#endif + - (FLWindow*)initWithFl_W:(Fl_Window *)flw contentRect:(NSRect)rect styleMask:(NSUInteger)windowStyle @@ -641,6 +696,12 @@ void Fl::remove_timeout(Fl_Timeout_Handler cb, void* data) if (self) { w = flw; containsGLsubwindow = NO; + if (fl_mac_os_version >= 100700) { + // replaces [self setRestorable:NO] that may trigger a compiler warning + typedef void (*setIMP)(id, SEL, BOOL); + setIMP addr = (setIMP)[self methodForSelector:@selector(setRestorable:)]; + addr(self, @selector(setRestorable:), NO); + } } return self; } @@ -652,7 +713,7 @@ void Fl::remove_timeout(Fl_Timeout_Handler cb, void* data) { return containsGLsubwindow; } -- (void)setContainsGLsubwindow:(BOOL)contains +- (void)containsGLsubwindow:(BOOL)contains { containsGLsubwindow = contains; } @@ -666,9 +727,6 @@ void Fl::remove_timeout(Fl_Timeout_Handler cb, void* data) return !(w->tooltip_window() || w->menu_window()); } -// TODO see if we really need a canBecomeMainWindow ... -#if 0 - - (BOOL)canBecomeMainWindow { if (Fl::modal_ && (Fl::modal_ != w)) @@ -677,7 +735,6 @@ void Fl::remove_timeout(Fl_Timeout_Handler cb, void* data) return !(w->tooltip_window() || w->menu_window()); } -#endif @end @@ -726,6 +783,7 @@ static double do_queued_events( double time = 0.0 ) return time; } + /* * This public function handles all events. It wait a maximum of * 'time' seconds for an event. This version returns 1 if events @@ -739,17 +797,132 @@ int fl_wait( double time ) return (got_events); } -double fl_mac_flush_and_wait(double time_to_wait, char in_idle) { +double fl_mac_flush_and_wait(double time_to_wait) { + static int in_idle = 0; NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + if (Fl::idle) { + if (!in_idle) { + in_idle = 1; + Fl::idle(); + in_idle = 0; + } + // the idle function may turn off idle, we can then wait: + if (Fl::idle) time_to_wait = 0.0; + } Fl::flush(); if (Fl::idle && !in_idle) // 'idle' may have been set within flush() time_to_wait = 0.0; double retval = fl_wait(time_to_wait); + if (fl_gc) { + CGContextFlush(fl_gc); + fl_gc = 0; + } [pool release]; return retval; } +static NSInteger max_normal_window_level(void) +{ + Fl_X *x; + NSInteger max_level; + + max_level = 0; + + for (x = Fl_X::first;x;x = x->next) { + NSInteger level; + FLWindow *cw = x->xid; + Fl_Window *win = x->w; + if (!win || !cw || ![cw isVisible]) + continue; + if (win->modal() || win->non_modal()) + continue; + level = [cw level]; + if (level >= max_level) + max_level = level; + } + + return max_level; +} + +// appropriate window level for modal windows +static NSInteger modal_window_level(void) +{ + NSInteger level; + + level = max_normal_window_level(); + if (level < NSModalPanelWindowLevel) + return NSModalPanelWindowLevel; + + // Need some room for non-modal windows + level += 2; + + // We cannot exceed this + if (level > CGShieldingWindowLevel()) + return CGShieldingWindowLevel(); + + return level; +} + +// appropriate window level for non-modal windows +static NSInteger non_modal_window_level(void) +{ + NSInteger level; + + level = max_normal_window_level(); + if (level < NSFloatingWindowLevel) + return NSFloatingWindowLevel; + + level += 1; + + if (level > CGShieldingWindowLevel()) + return CGShieldingWindowLevel(); + + return level; +} + +// makes sure modal and non-modal windows stay on top +static void fixup_window_levels(void) +{ + NSInteger modal_level, non_modal_level; + + Fl_X *x; + FLWindow *prev_modal, *prev_non_modal; + + modal_level = modal_window_level(); + non_modal_level = non_modal_window_level(); + + prev_modal = NULL; + prev_non_modal = NULL; + + for (x = Fl_X::first;x;x = x->next) { + FLWindow *cw = x->xid; + Fl_Window *win = x->w; + if (!win || !cw || ![cw isVisible]) + continue; + if (win->modal()) { + if ([cw level] != modal_level) { + [cw setLevel:modal_level]; + // changing level puts then in front, so make sure the + // stacking isn't messed up + if (prev_modal != NULL) + [cw orderWindow:NSWindowBelow + relativeTo:[prev_modal windowNumber]]; + } + prev_modal = cw; + } else if (win->non_modal()) { + if ([cw level] != non_modal_level) { + [cw setLevel:non_modal_level]; + if (prev_non_modal != NULL) + [cw orderWindow:NSWindowBelow + relativeTo:[prev_non_modal windowNumber]]; + } + prev_non_modal = cw; + } + } +} + + // updates Fl::e_x, Fl::e_y, Fl::e_x_root, and Fl::e_y_root static void update_e_xy_and_e_xy_root(NSWindow *nsw) { @@ -893,97 +1066,35 @@ static void cocoaMouseHandler(NSEvent *theEvent) return; } -@interface FLTextView : NSTextView -// this subclass is needed under OS X <= 10.5 but not under >= 10.6 where the base class is enough +@interface FLTextView : NSTextView // this subclass is only needed under OS X < 10.6 { + BOOL isActive; } +- (void)insertText:(id)aString; +- (void)doCommandBySelector:(SEL)aSelector; +- (void)setActive:(BOOL)a; @end @implementation FLTextView - (void)insertText:(id)aString { - [[[NSApp keyWindow] contentView] insertText:aString]; + if (isActive) [[[NSApp keyWindow] contentView] insertText:aString]; } - (void)doCommandBySelector:(SEL)aSelector { [[[NSApp keyWindow] contentView] doCommandBySelector:aSelector]; } -@end - -/* -Handle cocoa keyboard events -Events during a character composition sequence: - - keydown with deadkey -> [[theEvent characters] length] is 0 - - keyup -> [theEvent characters] contains the deadkey - - keydown with next key -> [theEvent characters] contains the composed character - - keyup -> [theEvent characters] contains the standard character - */ -static void cocoaKeyboardHandler(NSEvent *theEvent) +- (void)setActive:(BOOL)a { - NSUInteger mods; - - // get the modifiers - mods = [theEvent modifierFlags]; - // get the key code - UInt32 keyCode = 0, maskedKeyCode = 0; - unsigned short sym = 0; - keyCode = [theEvent keyCode]; - NSString *s = [theEvent characters]; - if ( (mods & NSShiftKeyMask) && (mods & NSCommandKeyMask) ) { - s = [s uppercaseString]; // US keyboards return lowercase letter in s if cmd-shift-key is hit - } - // extended keyboards can also send sequences on key-up to generate Kanji etc. codes. - // Some observed prefixes are 0x81 to 0x83, followed by an 8 bit keycode. - // In this mode, there seem to be no key-down codes - // printf("%08x %08x %08x\n", keyCode, mods, key); - maskedKeyCode = keyCode & 0x7f; - - if ([theEvent type] == NSKeyUp) { - Fl::e_state &= 0xbfffffff; // clear the deadkey flag - } - - mods_to_e_state( mods ); // process modifier keys - sym = macKeyLookUp[maskedKeyCode]; - if (sym < 0xff00) { // a "simple" key - // find the result of this key without modifier - NSString *sim = [theEvent charactersIgnoringModifiers]; - UniChar one; - CFStringGetCharacters((CFStringRef)sim, CFRangeMake(0, 1), &one); - // charactersIgnoringModifiers doesn't ignore shift, remove it when it's on - if(one >= 'A' && one <= 'Z') one += 32; - if (one > 0 && one <= 0x7f && (sym<'0' || sym>'9') ) sym = one; - } - Fl::e_keysym = Fl::e_original_keysym = sym; - - //NSLog(@"cocoaKeyboardHandler: keycode=%08x keysym=%08x mods=%08x symbol=%@ (%@)", - // keyCode, sym, mods, [theEvent characters], [theEvent charactersIgnoringModifiers]); - - // If there is text associated with this key, it will be filled in later. - Fl::e_length = 0; - Fl::e_text = (char*)""; -} - - -/* - * Open callback function to call... - */ -static void (*open_cb)(const char *) = 0; - -/* - * Install an open documents event handler... - */ -void fl_open_callback(void (*cb)(const char *)) { - fl_open_display(); - open_cb = cb; + isActive = a; } +@end -@interface FLDelegate : NSObject +@interface FLWindowDelegate : NSObject #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 -<NSWindowDelegate, NSApplicationDelegate> +<NSWindowDelegate> #endif -{ - BOOL seen_open_file; -} ++ (FLWindowDelegate*)createOnce; - (void)windowDidMove:(NSNotification *)notif; - (void)windowDidResize:(NSNotification *)notif; - (void)windowDidResignKey:(NSNotification *)notif; @@ -992,18 +1103,18 @@ void fl_open_callback(void (*cb)(const char *)) { - (void)windowDidDeminiaturize:(NSNotification *)notif; - (void)windowDidMiniaturize:(NSNotification *)notif; - (BOOL)windowShouldClose:(id)fl; -- (void)anyWindowWillClose:(NSNotification *)notif; -- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication*)sender; -- (void)applicationDidBecomeActive:(NSNotification *)notify; -- (void)applicationDidChangeScreenParameters:(NSNotification *)aNotification; -- (void)applicationWillResignActive:(NSNotification *)notify; -- (void)applicationWillHide:(NSNotification *)notify; -- (void)applicationWillUnhide:(NSNotification *)notify; - (id)windowWillReturnFieldEditor:(NSWindow *)sender toObject:(id)client; -- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename; -- (void)applicationDidFinishLaunching:(NSNotification *)aNotification; +- (void)anyWindowWillClose:(NSNotification *)notif; @end -@implementation FLDelegate +@implementation FLWindowDelegate ++ (FLWindowDelegate*)createOnce +{ + static FLWindowDelegate* delegate = nil; + if (!delegate) { + delegate = [[FLWindowDelegate alloc] init]; + } + return delegate; +} - (void)windowDidMove:(NSNotification *)notif { fl_lock_function(); @@ -1016,8 +1127,8 @@ void fl_open_callback(void (*cb)(const char *)) { update_e_xy_and_e_xy_root(nsw); resize_from_system = window; window->position((int)pt2.x, (int)(main_screen_height - pt2.y)); - if ([nsw containsGLsubwindow] ) { - [nsw display];// redraw window after moving if it contains OpenGL subwindows + if ([nsw containsGLsubwindow] && fl_mac_os_version < 100700) { + [nsw display];// with OS < 10.7, redraw window after moving if it contains OpenGL subwindows } fl_unlock_function(); } @@ -1045,9 +1156,11 @@ void fl_open_callback(void (*cb)(const char *)) { FLWindow *nsw = (FLWindow*)[notif object]; Fl_Window *window = [nsw getFl_Window]; /* Fullscreen windows obscure all other windows so we need to return - to a "normal" level when the user switches to another window */ - if (window->fullscreen_active()) + to a "normal" level when the user switches to another window */ + if (window->fullscreen_active()) { [nsw setLevel:NSNormalWindowLevel]; + fixup_window_levels(); + } Fl::handle( FL_UNFOCUS, window); fl_unlock_function(); } @@ -1057,8 +1170,10 @@ void fl_open_callback(void (*cb)(const char *)) { FLWindow *nsw = (FLWindow*)[notif object]; Fl_Window *w = [nsw getFl_Window]; /* Restore previous fullscreen level */ - if (w->fullscreen_active()) + if (w->fullscreen_active()) { [nsw setLevel:NSStatusWindowLevel]; + fixup_window_levels(); + } if ( w->border() || (!w->modal() && !w->tooltip_window()) ) Fl::handle( FL_FOCUS, w); fl_unlock_function(); } @@ -1096,6 +1211,18 @@ void fl_open_callback(void (*cb)(const char *)) { // the system doesn't need to send [fl close] because FLTK does it when needed return NO; } +- (id)windowWillReturnFieldEditor:(NSWindow *)sender toObject:(id)client +{ + if (fl_mac_os_version < 100600) { + static FLTextView *view = nil; + if (!view) { + NSRect rect={{0,0},{20,20}}; + view = [[FLTextView alloc] initWithFrame:rect]; + } + return view; + } + return nil; +} - (void)anyWindowWillClose:(NSNotification *)notif { fl_lock_function(); @@ -1105,13 +1232,34 @@ void fl_open_callback(void (*cb)(const char *)) { Fl_Window *w = Fl::first_window(); while (w && (w->parent() || !w->border() || !w->visible())) { w = Fl::next_window(w); - } + } if (w) { [Fl_X::i(w)->xid makeKeyWindow]; } } fl_unlock_function(); } +@end + +@interface FLAppDelegate : NSObject +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 +<NSApplicationDelegate> +#endif +{ + void (*open_cb)(const char*); + TSMDocumentID currentDoc; +} +- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication*)sender; +- (void)applicationDidBecomeActive:(NSNotification *)notify; +- (void)applicationDidChangeScreenParameters:(NSNotification *)aNotification; +- (void)applicationDidUpdate:(NSNotification *)aNotification; +- (void)applicationWillResignActive:(NSNotification *)notify; +- (void)applicationWillHide:(NSNotification *)notify; +- (void)applicationWillUnhide:(NSNotification *)notify; +- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename; +- (void)open_cb:(void (*)(const char*))cb; +@end +@implementation FLAppDelegate - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication*)sender { fl_lock_function(); @@ -1128,44 +1276,25 @@ void fl_open_callback(void (*cb)(const char *)) { fl_unlock_function(); return reply; } -/** - * Cocoa organizes the Z depth of windows on a global priority. FLTK however - * expects the window manager to organize Z level by application. The trickery - * below will change Z order during activation and deactivation. - */ - (void)applicationDidBecomeActive:(NSNotification *)notify { fl_lock_function(); - Fl_X *x; - FLWindow *top = 0, *topModal = 0, *topNonModal = 0; - for (x = Fl_X::first;x;x = x->next) { - FLWindow *cw = x->xid; - Fl_Window *win = x->w; - if (win && cw && [cw isVisible]) { - if (win->modal()) { - [cw setLevel:NSModalPanelWindowLevel]; - if (topModal) - [cw orderWindow:NSWindowBelow relativeTo:[topModal windowNumber]]; - else - topModal = cw; - } else if (win->non_modal()) { - [cw setLevel:NSFloatingWindowLevel]; - if (topNonModal) - [cw orderWindow:NSWindowBelow relativeTo:[topNonModal windowNumber]]; - else - topNonModal = cw; - } else { - if (top) - ; - else - top = cw; - } - } - } + + // update clipboard status + clipboard_check(); + + /** + * Cocoa organizes the Z depth of windows on a global priority. FLTK however + * expects the window manager to organize Z level by application. The trickery + * below will change Z order during activation and deactivation. + */ + fixup_window_levels(); + fl_unlock_function(); } - (void)applicationDidChangeScreenParameters:(NSNotification *)unused { // react to changes in screen numbers and positions + fl_lock_function(); main_screen_height = [[[NSScreen screens] objectAtIndex:0] frame].size.height; Fl::call_screen_init(); // FLTK windows have already been notified they were moved, @@ -1179,6 +1308,24 @@ void fl_open_callback(void (*cb)(const char *)) { } } Fl::handle(FL_SCREEN_CONFIGURATION_CHANGED, NULL); + fl_unlock_function(); +} +- (void)applicationDidUpdate:(NSNotification *)aNotification +{ + if ((fl_mac_os_version >= 100500) && (im_enabled != -1) && + (TSMGetActiveDocument != NULL)) { + TSMDocumentID newDoc; + // It is extremely unclear when Cocoa decides to create/update + // the input context, but debugging reveals that it is done + // by NSApplication:updateWindows. So check if the input context + // has shifted after each such run so that we can update our + // input methods status. + newDoc = TSMGetActiveDocument(); + if (newDoc != currentDoc) { + im_update(); + currentDoc = newDoc; + } + } } - (void)applicationWillResignActive:(NSNotification *)notify { @@ -1243,21 +1390,11 @@ void fl_open_callback(void (*cb)(const char *)) { } fl_unlock_function(); } -- (id)windowWillReturnFieldEditor:(NSWindow *)sender toObject:(id)client -{ - if (fl_mac_os_version < 100600) { - static FLTextView *view = nil; - if (!view) { - NSRect rect={{0,0},{20,20}}; - view = [[FLTextView alloc] initWithFrame:rect]; - } - return view; - } - return nil; -} - (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename { - seen_open_file = YES; + // without the next statement, the opening of the 1st window is delayed by several seconds + // under Mac OS ≥ 10.8 when a file is dragged on the application icon + [[theApplication mainWindow] orderFront:self]; if (open_cb) { fl_lock_function(); (*open_cb)([filename UTF8String]); @@ -1266,17 +1403,26 @@ void fl_open_callback(void (*cb)(const char *)) { } return NO; } -- (void)applicationDidFinishLaunching:(NSNotification *)aNotification +- (void)open_cb:(void (*)(const char*))cb { - // without this, the opening of the 1st window is delayed by several seconds - // under Mac OS 10.8 when a file is dragged on the application icon - if (fl_mac_os_version >= 100800 && seen_open_file) [[NSApp mainWindow] orderFront:self]; + open_cb = cb; } @end +/* + * Install an open documents event handler... + */ +void fl_open_callback(void (*cb)(const char *)) { + fl_open_display(); + [(FLAppDelegate*)[NSApp delegate] open_cb:cb]; +} + @implementation FLApplication + (void)sendEvent:(NSEvent *)theEvent { + if (fl_send_system_handlers(theEvent)) + return; + NSEventType type = [theEvent type]; if (type == NSLeftMouseDown) { fl_lock_function(); @@ -1308,21 +1454,29 @@ void fl_open_callback(void (*cb)(const char *)) { } @end -extern "C" { - OSErr CPSEnableForegroundOperation(ProcessSerialNumber *psn, UInt32 _arg2, - UInt32 _arg3, UInt32 _arg4, UInt32 _arg5); +/* Prototype of undocumented function needed to support Mac OS 10.2 or earlier + extern "C" { + OSErr CPSEnableForegroundOperation(ProcessSerialNumber*, UInt32, UInt32, UInt32, UInt32); } +*/ void fl_open_display() { static char beenHereDoneThat = 0; if ( !beenHereDoneThat ) { beenHereDoneThat = 1; + + TSMGetActiveDocument = (TSMGetActiveDocument_type)Fl_X::get_carbon_function("TSMGetActiveDocument"); + TSMSetDocumentProperty = (TSMSetDocumentProperty_type)Fl_X::get_carbon_function("TSMSetDocumentProperty"); + TSMRemoveDocumentProperty = (TSMRemoveDocumentProperty_type)Fl_X::get_carbon_function("TSMRemoveDocumentProperty"); + TISCreateASCIICapableInputSourceList = (TISCreateASCIICapableInputSourceList_type)Fl_X::get_carbon_function("TISCreateASCIICapableInputSourceList"); + + KeyScript = (KeyScript_type)Fl_X::get_carbon_function("KeyScript"); BOOL need_new_nsapp = (NSApp == nil); if (need_new_nsapp) [NSApplication sharedApplication]; NSAutoreleasePool *localPool; localPool = [[NSAutoreleasePool alloc] init]; // never released - [NSApp setDelegate:[[FLDelegate alloc] init]]; + [(NSApplication*)NSApp setDelegate:[[FLAppDelegate alloc] init]]; if (need_new_nsapp) [NSApp finishLaunching]; // empty the event queue but keep system events for drag&drop of files at launch @@ -1333,44 +1487,48 @@ void fl_open_display() { dequeue:YES]; while (ign_event); - fl_default_cursor = [NSCursor arrowCursor]; - // bring the application into foreground without a 'CARB' resource - Boolean same_psn; - ProcessSerialNumber cur_psn, front_psn; - if ( !GetCurrentProcess( &cur_psn ) && !GetFrontProcess( &front_psn ) && - !SameProcess( &front_psn, &cur_psn, &same_psn ) && !same_psn ) { + bool i_am_in_front; + ProcessSerialNumber cur_psn = { 0, kCurrentProcess }; +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 + if (fl_mac_os_version >= 100600) { + i_am_in_front = [[NSRunningApplication currentApplication] isActive]; + } + else +#endif + { + Boolean same_psn; + ProcessSerialNumber front_psn; + //avoid compilation warnings triggered by GetFrontProcess() and SameProcess() + void* h = dlopen(NULL, RTLD_LAZY); + typedef OSErr (*GetFrontProcess_type)(ProcessSerialNumber*); + GetFrontProcess_type GetFrontProcess_ = (GetFrontProcess_type)dlsym(h, "GetFrontProcess"); + typedef OSErr (*SameProcess_type)(ProcessSerialNumber*, ProcessSerialNumber*, Boolean*); + SameProcess_type SameProcess_ = (SameProcess_type)dlsym(h, "SameProcess"); + i_am_in_front = (!GetFrontProcess_( &front_psn ) && + !SameProcess_( &front_psn, &cur_psn, &same_psn ) && same_psn ); + } + if (!i_am_in_front) { // only transform the application type for unbundled apps NSBundle *bundle = [NSBundle mainBundle]; if (bundle) { - NSString *exe = [[bundle executablePath] stringByStandardizingPath]; - NSString *bpath = [bundle bundlePath]; - NSString *exe_dir = [exe stringByDeletingLastPathComponent]; - if ([bpath isEqualToString:exe] || [bpath isEqualToString:exe_dir]) bundle = nil; - } - - if ( !bundle ) - { - // Earlier versions of this code tried to use weak linking, however it - // appears that this does not work on 10.2. Since 10.3 and higher provide - // both TransformProcessType and CPSEnableForegroundOperation, the following - // conditional code compiled on 10.2 will still work on newer releases... - OSErr err; -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_3 - if (TransformProcessType != NULL) { - err = TransformProcessType(&cur_psn, kProcessTransformToForegroundApplication); - } else -#endif // MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_3 - err = CPSEnableForegroundOperation(&cur_psn, 0x03, 0x3C, 0x2C, 0x1103); - if (err == noErr) { - SetFrontProcess( &cur_psn ); - } + NSString *exe = [[bundle executablePath] stringByStandardizingPath]; + NSString *bpath = [bundle bundlePath]; + NSString *exe_dir = [exe stringByDeletingLastPathComponent]; + if ([bpath isEqualToString:exe] || [bpath isEqualToString:exe_dir]) bundle = nil; + } + + if ( !bundle ) { + TransformProcessType(&cur_psn, kProcessTransformToForegroundApplication); // needs Mac OS 10.3 + /* support of Mac OS 10.2 or earlier used this undocumented call instead + err = CPSEnableForegroundOperation(&cur_psn, 0x03, 0x3C, 0x2C, 0x1103); + */ + [NSApp activateIgnoringOtherApps:YES]; } } if (![NSApp servicesMenu]) createAppleMenu(); - fl_system_menu = [NSApp mainMenu]; main_screen_height = [[[NSScreen screens] objectAtIndex:0] frame].size.height; - [[NSNotificationCenter defaultCenter] addObserver:[NSApp delegate] + [[NSNotificationCenter defaultCenter] addObserver:[FLWindowDelegate createOnce] selector:@selector(anyWindowWillClose:) name:NSWindowWillCloseNotification object:nil]; @@ -1387,6 +1545,66 @@ void fl_open_display() { void fl_close_display() { } +// Force a "Roman" or "ASCII" keyboard, which both the Mozilla and +// Safari people seem to think implies turning off advanced IME stuff +// (see nsTSMManager::SyncKeyScript in Mozilla and enableSecureTextInput +// in Safari/Webcore). Should be good enough for us then... + +static void im_update(void) { + if (fl_mac_os_version >= 100500) { + TSMDocumentID doc; + + if ((TSMGetActiveDocument == NULL) || + (TSMSetDocumentProperty == NULL) || + (TSMRemoveDocumentProperty == NULL) || + (TISCreateASCIICapableInputSourceList == NULL)) + return; + + doc = TSMGetActiveDocument(); + + if (im_enabled) + TSMRemoveDocumentProperty(doc, kTSMDocumentEnabledInputSourcesPropertyTag); + else { + CFArrayRef inputSources; + + inputSources = TISCreateASCIICapableInputSourceList(); + TSMSetDocumentProperty(doc, kTSMDocumentEnabledInputSourcesPropertyTag, + sizeof(CFArrayRef), &inputSources); + CFRelease(inputSources); + } + } else { + if (KeyScript == NULL) + return; + + if (im_enabled) + KeyScript(smKeyEnableKybds); + else + KeyScript(smEnableRomanKybdsOnly); + } +} + +void Fl::enable_im() { + fl_open_display(); + + im_enabled = 1; + + if (fl_mac_os_version >= 100500) + [NSApp updateWindows]; + else + im_update(); +} + +void Fl::disable_im() { + fl_open_display(); + + im_enabled = 0; + + if (fl_mac_os_version >= 100500) + [NSApp updateWindows]; + else + im_update(); +} + // Gets the border sizes and the titlebar size static void get_window_frame_sizes(int &bx, int &by, int &bt) { @@ -1463,15 +1681,6 @@ void Fl::get_mouse(int &x, int &y) /* - * Initialize the given port for redraw and call the window's flush() to actually draw the content - */ -void Fl_X::flush() -{ - w->flush(); - if (fl_gc) CGContextFlush(fl_gc); -} - -/* * Gets called when a window is created, resized, or deminiaturized */ static void handleUpdateEvent( Fl_Window *window ) @@ -1491,7 +1700,10 @@ static void handleUpdateEvent( Fl_Window *window ) cx->region = 0; } cx->w->clear_damage(FL_DAMAGE_ALL); + CGContextRef gc = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; + CGContextSaveGState(gc); // save original context cx->flush(); + CGContextRestoreGState(gc); // restore original context cx->w->clear_damage(); } window->clear_damage(FL_DAMAGE_ALL); @@ -1629,16 +1841,143 @@ static void q_set_window_title(NSWindow *nsw, const char * name, const char *mi } } +/** How FLTK handles Mac OS text input + + Let myview be the instance of the FLView class that has the keyboard focus. FLView is an FLTK-defined NSView subclass + that implements the NSTextInputClient protocol to properly handle text input. It also implements the old NSTextInput + protocol to run with OS <= 10.4. The few NSTextInput protocol methods that differ in signature from the NSTextInputClient + protocol transmit the received message to the corresponding NSTextInputClient method. + + Keyboard input sends keyDown: and performKeyEquivalent: messages to myview. The latter occurs for keys such as + ForwardDelete, arrows and F1, and when the Ctrl or Cmd modifiers are used. Other key presses send keyDown: messages. + The keyDown: method calls [[myview inputContext] handleEvent:theEvent] that triggers system + processing of keyboard events. The performKeyEquivalent: method directly calls Fl::handle(FL_KEYBOARD, focus-window) + when the Ctrl or Cmd modifiers are used. If not, it also calls [[myview inputContext] handleEvent:theEvent]. + The performKeyEquivalent: method returns YES when the keystroke has been handled and NO otherwise, which allows + shortcuts of the system menu to be processed. Three sorts of messages are then sent back by the system to myview: + doCommandBySelector:, setMarkedText: and insertText:. All 3 messages eventually produce Fl::handle(FL_KEYBOARD, win) calls. + The doCommandBySelector: message allows to process events such as new-line, forward and backward delete, arrows, + escape, tab, F1. The message setMarkedText: is sent when marked text, that is, temporary text that gets replaced later + by some other text, is inserted. This happens when a dead key is pressed, and also + when entering complex scripts (e.g., Chinese). Fl_X::next_marked_length gives the byte + length of marked text before the FL_KEYBOARD event is processed. Fl::compose_state gives this length after this processing. + Message insertText: is sent to enter text in the focused widget. If there's marked text, Fl::compose_state is > 0, and this + marked text gets replaced by the inserted text. If there's no marked text, the new text is inserted at the insertion point. + When the character palette is used to enter text, the system sends an insertText: message to myview. + The in_key_event field of the FLView class allows to differentiate keyboard from palette inputs. + + During processing of the handleEvent message, inserted and marked strings are concatenated in a single string + inserted in a single FL_KEYBOARD event after return from handleEvent. The need_handle member variable of FLView allows + to determine when setMarkedText or insertText strings have been sent during handleEvent processing and must trigger + an FL_KEYBOARD event. Concatenating two insertText operations or an insertText followed by a setMarkedText is possible. + In contrast, setMarkedText followed by insertText or by another setMarkedText isn't correct if concatenated in a single + string. Thus, in such case, the setMarkedText and the next operation produce each an FL_KEYBOARD event. + + OS >= 10.7 contains a feature where pressing and holding certain keys opens a menu window that shows a list + of possible accented variants of this key. The selectedRange field of the FLView class and the selectedRange, insertText: + and setMarkedText: methods of the NSTextInputClient protocol are used to support this feature. + The notion of selected text (!= marked text) is monitored by the selectedRange field. + The -(NSRange)[FLView selectedRange] method is used to control whether an FLTK widget opens accented character windows + by returning .location = NSNotFound to disable that, or returning the value of the selectedRange field to enable the feature. + When selectedRange.location >= 0, the value of selectedRange.length is meaningful. 0 means no text is currently selected, + > 0 means this number of characters before the insertion point are selected. The insertText: method does + selectedRange = NSMakeRange(100, 0); to indicate no text is selected. The setMarkedText: method does + selectedRange = NSMakeRange(100, newSelection.length); to indicate that this length of text is selected. + + With OS <= 10.5, the crucial call [[myview inputContext] handleEvent:theEvent] is not possible because neither the + inputContext nor the handleEvent: methods are implemented. This call is re-written: + static SEL inputContextSEL = (fl_mac_os_version >= 100600 ? @selector(inputContext) : @selector(FLinputContext)); + [[myview performSelector:inputContextSEL] handleEvent:theEvent]; + that replaces the 10.6 inputContext message by the FLinputContext message. This message and two FLTK-defined classes, + FLTextInputContext and FLTextView, are used to emulate with OS <= 10.5 what's possible with OS >= 10.6. + Method -(FLTextInputContext*)[FLView FLinputContext] returns an instance of class FLTextInputContext that possesses + a handleEvent: method. FLView's FLinputContext method also calls [[self window] fieldEditor:YES forObject:nil] which + returns the so-called view's "field editor". This editor is an instance of the FLTextView class allocated by the + -(id)[FLWindowDelegate windowWillReturnFieldEditor: toObject:] method. + The -(BOOL)[FLTextInputContext handleEvent:] method emulates the missing 10.6 -(BOOL)[NSTextInputContext handleEvent:] + by sending the interpretKeyEvents: message to the FLTextView object. The system sends back doCommandBySelector: and + insertText: messages to the FLTextView object that are transmitted unchanged to myview to be processed as with OS >= 10.6. + The system also sends setMarkedText: messages directly to myview. + + There is furthermore an oddity of dead key processing with OS <= 10.5. It occurs when a dead key followed by a non-accented + key are pressed. Say, for example, that keys '^' followed by 'p' are pressed on a French or German keyboard. Resulting + messages are: [myview setMarkedText:@"^"], [myview insertText:@"^"], [myview insertText:@"p"], [FLTextView insertText:@"^p"]. + The 2nd '^' replaces the marked 1st one, followed by p^p. The resulting text in the widget is "^p^p" instead of the + desired "^p". To avoid that, the FLTextView object is deactivated by the insertText: message and reactivated after + the handleEvent: message has been processed. + + NSEvent's during a character composition sequence: + - keyDown with deadkey -> [[theEvent characters] length] is 0 + - keyUp -> [theEvent characters] contains the deadkey + - keyDown with next key -> [theEvent characters] contains the composed character + - keyUp -> [theEvent characters] contains the standard character + */ -@interface FLView : NSView <NSTextInput> { - int next_compose_length; - bool in_key_event; +static void cocoaKeyboardHandler(NSEvent *theEvent) +{ + NSUInteger mods; + // get the modifiers + mods = [theEvent modifierFlags]; + // get the key code + UInt32 keyCode = 0, maskedKeyCode = 0; + unsigned short sym = 0; + keyCode = [theEvent keyCode]; + // extended keyboards can also send sequences on key-up to generate Kanji etc. codes. + // Some observed prefixes are 0x81 to 0x83, followed by an 8 bit keycode. + // In this mode, there seem to be no key-down codes + // printf("%08x %08x %08x\n", keyCode, mods, key); + maskedKeyCode = keyCode & 0x7f; + mods_to_e_state( mods ); // process modifier keys + sym = macKeyLookUp[maskedKeyCode]; + if (sym < 0xff00) { // a "simple" key + // find the result of this key without modifier + NSString *sim = [theEvent charactersIgnoringModifiers]; + UniChar one; + CFStringGetCharacters((CFStringRef)sim, CFRangeMake(0, 1), &one); + // charactersIgnoringModifiers doesn't ignore shift, remove it when it's on + if(one >= 'A' && one <= 'Z') one += 32; + if (one > 0 && one <= 0x7f && (sym<'0' || sym>'9') ) sym = one; + } + Fl::e_keysym = Fl::e_original_keysym = sym; + /*NSLog(@"cocoaKeyboardHandler: keycode=%08x keysym=%08x mods=%08x symbol=%@ (%@)", + keyCode, sym, mods, [theEvent characters], [theEvent charactersIgnoringModifiers]);*/ + // If there is text associated with this key, it will be filled in later. + Fl::e_length = 0; + Fl::e_text = (char*)""; +} + +@interface FLTextInputContext : NSObject { // "emulates" NSTextInputContext before OS 10.6 +@public + FLTextView *edit; +} +-(BOOL)handleEvent:(NSEvent*)theEvent; +@end +@implementation FLTextInputContext +-(BOOL)handleEvent:(NSEvent*)theEvent { + [self->edit setActive:YES]; + [self->edit interpretKeyEvents:[NSArray arrayWithObject:theEvent]]; + [self->edit setActive:YES]; + return YES; +} +@end + +@interface FLView : NSView <NSTextInput +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 +, NSTextInputClient +#endif +> { + BOOL in_key_event; // YES means keypress is being processed by handleEvent + BOOL need_handle; // YES means Fl::handle(FL_KEYBOARD,) is needed after handleEvent processing + NSInteger identifier; + NSRange selectedRange; } + (void)prepareEtext:(NSString*)aString; ++ (void)concatEtext:(NSString*)aString; - (id)init; - (void)drawRect:(NSRect)rect; - (BOOL)acceptsFirstResponder; - (BOOL)acceptsFirstMouse:(NSEvent*)theEvent; +- (void)resetCursorRects; - (BOOL)performKeyEquivalent:(NSEvent*)theEvent; - (void)mouseUp:(NSEvent *)theEvent; - (void)rightMouseUp:(NSEvent *)theEvent; @@ -1651,7 +1990,6 @@ static void q_set_window_title(NSWindow *nsw, const char * name, const char *mi - (void)rightMouseDragged:(NSEvent *)theEvent; - (void)otherMouseDragged:(NSEvent *)theEvent; - (void)scrollWheel:(NSEvent *)theEvent; -- (BOOL)handleKeyDown:(NSEvent *)theEvent; - (void)keyDown:(NSEvent *)theEvent; - (void)keyUp:(NSEvent *)theEvent; - (void)flagsChanged:(NSEvent *)theEvent; @@ -1660,24 +1998,36 @@ static void q_set_window_title(NSWindow *nsw, const char * name, const char *mi - (BOOL)performDragOperation:(id <NSDraggingInfo>)sender; - (void)draggingExited:(id < NSDraggingInfo >)sender; - (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal; +- (FLTextInputContext*)FLinputContext; +#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5 +- (void)insertText:(id)aString replacementRange:(NSRange)replacementRange; +- (void)setMarkedText:(id)aString selectedRange:(NSRange)newSelection replacementRange:(NSRange)replacementRange; +- (NSAttributedString *)attributedSubstringForProposedRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange; +- (NSRect)firstRectForCharacterRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange; +- (NSInteger)windowLevel; +#endif @end @implementation FLView - (id)init { + static NSInteger counter = 0; self = [super init]; if (self) { - next_compose_length = -1; - in_key_event = false; + in_key_event = NO; + identifier = ++counter; } return self; } - (void)drawRect:(NSRect)rect { fl_lock_function(); + through_drawRect = YES; FLWindow *cw = (FLWindow*)[self window]; Fl_Window *w = [cw getFl_Window]; - handleUpdateEvent(w); + if (fl_x_to_redraw) fl_x_to_redraw->flush(); + else handleUpdateEvent(w); + through_drawRect = NO; fl_unlock_function(); } @@ -1688,7 +2038,28 @@ static void q_set_window_title(NSWindow *nsw, const char * name, const char *mi - (BOOL)performKeyEquivalent:(NSEvent*)theEvent { //NSLog(@"performKeyEquivalent:"); - return [self handleKeyDown:theEvent]; + fl_lock_function(); + cocoaKeyboardHandler(theEvent); + BOOL handled; + NSUInteger mods = [theEvent modifierFlags]; + if ( (mods & NSControlKeyMask) || (mods & NSCommandKeyMask) ) { + NSString *s = [theEvent characters]; + if ( (mods & NSShiftKeyMask) && (mods & NSCommandKeyMask) ) { + s = [s uppercaseString]; // US keyboards return lowercase letter in s if cmd-shift-key is hit + } + [FLView prepareEtext:s]; + Fl::compose_state = 0; + handled = Fl::handle(FL_KEYBOARD, [(FLWindow*)[theEvent window] getFl_Window]); + } + else { + in_key_event = YES; + need_handle = NO; + handled = [[self performSelector:inputContextSEL] handleEvent:theEvent]; + if (need_handle) handled = Fl::handle(FL_KEYBOARD, [(FLWindow*)[theEvent window] getFl_Window]); + in_key_event = NO; + } + fl_unlock_function(); + return handled; } - (BOOL)acceptsFirstMouse:(NSEvent*)theEvent { @@ -1696,6 +2067,17 @@ static void q_set_window_title(NSWindow *nsw, const char * name, const char *mi Fl_Window *first = Fl::first_window(); return (first == w || !first->modal()); } +- (void)resetCursorRects { + Fl_Window *w = [(FLWindow*)[self window] getFl_Window]; + Fl_X *i = Fl_X::i(w); + if (!i) return; // fix for STR #3128 + // We have to have at least one cursor rect for invalidateCursorRectsForView + // to work, hence the "else" clause. + if (i->cursor) + [self addCursorRect:[self visibleRect] cursor:(NSCursor*)i->cursor]; + else + [self addCursorRect:[self visibleRect] cursor:[NSCursor arrowCursor]]; +} - (void)mouseUp:(NSEvent *)theEvent { cocoaMouseHandler(theEvent); } @@ -1729,57 +2111,21 @@ static void q_set_window_title(NSWindow *nsw, const char * name, const char *mi - (void)scrollWheel:(NSEvent *)theEvent { cocoaMouseWheelHandler(theEvent); } -- (BOOL)handleKeyDown:(NSEvent *)theEvent { - //NSLog(@"handleKeyDown"); +- (void)keyDown:(NSEvent *)theEvent { + //NSLog(@"keyDown:%@",[theEvent characters]); fl_lock_function(); - - Fl_Window *window = (Fl_Window*)[(FLWindow*)[theEvent window] getFl_Window]; + Fl_Window *window = [(FLWindow*)[theEvent window] getFl_Window]; Fl::first_window(window); - - next_compose_length = -1; - // First let's process the raw key press cocoaKeyboardHandler(theEvent); - - int no_text_key = false; - static const int notext[] = { // keys that don't emit text - FL_BackSpace, FL_Print, FL_Scroll_Lock, FL_Pause, - FL_Insert, FL_Home, FL_Page_Up, FL_Delete, FL_End, FL_Page_Down, - FL_Left, FL_Up, FL_Right, FL_Down, - FL_Menu, FL_Num_Lock, FL_Help - }; - static const int count = sizeof(notext)/sizeof(int); - if (Fl::e_keysym > FL_F && Fl::e_keysym <= FL_F_Last) no_text_key = true; - else for (int i=0; i < count; i++) { - if (notext[i] == Fl::e_keysym) { - no_text_key = true; - break; - } - } - if (!no_text_key && !(Fl::e_state & FL_META) ) { - // Don't send cmd-<key> to interpretKeyEvents because it beeps. - // Then we can let the OS have a stab at it and see if it thinks it - // should result in some text - NSText *edit = [[theEvent window] fieldEditor:YES forObject:nil]; - in_key_event = true; - [edit interpretKeyEvents:[NSArray arrayWithObject:theEvent]]; - in_key_event = false; - } - //NSLog(@"to text=%@ l=%d", [NSString stringWithUTF8String:Fl::e_text], Fl::e_length); - int handled = Fl::handle(FL_KEYDOWN, window); - // We have to update this after Fl::handle as it says what to do on the - // _next_ input - if (next_compose_length != -1) - Fl::compose_state = next_compose_length; - + in_key_event = YES; + need_handle = NO; + [[self performSelector:inputContextSEL] handleEvent:theEvent]; + if (need_handle) Fl::handle(FL_KEYBOARD, window); + in_key_event = NO; fl_unlock_function(); - return (handled ? YES : NO); -} -- (void)keyDown:(NSEvent *)theEvent { - //NSLog(@"keyDown: "); - [self handleKeyDown:theEvent]; } - (void)keyUp:(NSEvent *)theEvent { - //NSLog(@"keyUp: "); + //NSLog(@"keyUp:%@",[theEvent characters]); fl_lock_function(); Fl_Window *window = (Fl_Window*)[(FLWindow*)[theEvent window] getFl_Window]; Fl::first_window(window); @@ -1863,8 +2209,8 @@ static void q_set_window_title(NSWindow *nsw, const char * name, const char *mi CFStringGetCString(all, DragData, l + 1, kCFStringEncodingUTF8); CFRelease(all); } - else if ( [[pboard types] containsObject:NSStringPboardType] ) { - NSData *data = [pboard dataForType:NSStringPboardType]; + else if ( [[pboard types] containsObject:utf8_format] ) { + NSData *data = [pboard dataForType:utf8_format]; DragData = (char *)malloc([data length] + 1); [data getBytes:DragData]; DragData[[data length]] = 0; @@ -1902,6 +2248,15 @@ static void q_set_window_title(NSWindow *nsw, const char * name, const char *mi return NSDragOperationGeneric; } +- (FLTextInputContext*)FLinputContext { // used only if OS < 10.6 to replace [NSView inputContext] + static FLTextInputContext *context = NULL; + if (!context) { + context = [[FLTextInputContext alloc] init]; + } + context->edit = (FLTextView*)[[self window] fieldEditor:YES forObject:nil]; + return context; +} + + (void)prepareEtext:(NSString*)aString { // fills Fl::e_text with UTF-8 encoded aString using an adequate memory allocation static char *received_utf8 = NULL; @@ -1923,69 +2278,124 @@ static void q_set_window_title(NSWindow *nsw, const char * name, const char *mi Fl::e_length = l; } -// These functions implement text input. -// Only two-stroke character composition works at this point. -// Needs much elaboration to fully support CJK text input, -// but this is the way to go. ++ (void)concatEtext:(NSString*)aString { + // extends Fl::e_text with aString + NSString *newstring = [[NSString stringWithUTF8String:Fl::e_text] stringByAppendingString:aString]; + [FLView prepareEtext:newstring]; +} + - (void)doCommandBySelector:(SEL)aSelector { + NSString *s = [[NSApp currentEvent] characters]; + //NSLog(@"doCommandBySelector:%s text='%@'",sel_getName(aSelector), s); + s = [s substringFromIndex:[s length] - 1]; + [FLView prepareEtext:s]; // use the last character of the event; necessary for deadkey + Tab + Fl_Window *target = [(FLWindow*)[self window] getFl_Window]; + Fl::handle(FL_KEYBOARD, target); } - (void)insertText:(id)aString { + [self insertText:aString replacementRange:NSMakeRange(NSNotFound, 0)]; +} + +- (void)insertText:(id)aString replacementRange:(NSRange)replacementRange { NSString *received; if ([aString isKindOfClass:[NSAttributedString class]]) { received = [(NSAttributedString*)aString string]; } else { received = (NSString*)aString; } - //NSLog(@"insertText: received=%@",received); - - if (!in_key_event) fl_lock_function(); - [FLView prepareEtext:received]; - // We can get called outside of key events (e.g. from the character - // palette). Transform such actions to FL_PASTE events. - if (!in_key_event) { - Fl_Window *target = [(FLWindow*)[self window] getFl_Window]; - Fl::handle(FL_PASTE, target); - // for some reason, the window does not redraw until the next mouse move or button push - // sending a 'redraw()' or 'awake()' does not solve the issue! - Fl::flush(); - } - if (!in_key_event) fl_unlock_function(); + /*NSLog(@"insertText='%@' l=%d Fl::compose_state=%d range=%d,%d", + received,strlen([received UTF8String]),Fl::compose_state,replacementRange.location,replacementRange.length);*/ + fl_lock_function(); + Fl_Window *target = [(FLWindow*)[self window] getFl_Window]; + while (replacementRange.length--) { // delete replacementRange.length characters before insertion point + int saved_keysym = Fl::e_keysym; + Fl::e_keysym = FL_BackSpace; + Fl::handle(FL_KEYBOARD, target); + Fl::e_keysym = saved_keysym; + } + if (in_key_event && Fl_X::next_marked_length && Fl::e_length) { + // if setMarkedText + insertText is sent during handleEvent, text cannot be concatenated in single FL_KEYBOARD event + Fl::handle(FL_KEYBOARD, target); + Fl::e_length = 0; + } + if (in_key_event && Fl::e_length) [FLView concatEtext:received]; + else [FLView prepareEtext:received]; + Fl_X::next_marked_length = 0; + // We can get called outside of key events (e.g., from the character palette, from CJK text input). + BOOL palette = !(in_key_event || Fl::compose_state); + if (palette) Fl::e_keysym = 0; + // YES if key has text attached + BOOL has_text_key = Fl::e_keysym <= '~' || Fl::e_keysym == FL_Iso_Key || + (Fl::e_keysym >= FL_KP && Fl::e_keysym <= FL_KP_Last && Fl::e_keysym != FL_KP_Enter); + // insertText sent during handleEvent of a key without text cannot be processed in a single FL_KEYBOARD event. + // Occurs with deadkey followed by non-text key + if (!in_key_event || !has_text_key) { + Fl::handle(FL_KEYBOARD, target); + Fl::e_length = 0; + } + else need_handle = YES; + selectedRange = NSMakeRange(100, 0); // 100 is an arbitrary value + // for some reason, with the palette, the window does not redraw until the next mouse move or button push + // sending a 'redraw()' or 'awake()' does not solve the issue! + if (palette) Fl::flush(); + if (fl_mac_os_version < 100600) [(FLTextView*)[[self window] fieldEditor:YES forObject:nil] setActive:NO]; + fl_unlock_function(); } - (void)setMarkedText:(id)aString selectedRange:(NSRange)newSelection { + [self setMarkedText:aString selectedRange:newSelection replacementRange:NSMakeRange(NSNotFound, 0)]; +} + +- (void)setMarkedText:(id)aString selectedRange:(NSRange)newSelection replacementRange:(NSRange)replacementRange { NSString *received; - if (newSelection.location == 0) { - [self unmarkText]; - return; - } if ([aString isKindOfClass:[NSAttributedString class]]) { received = [(NSAttributedString*)aString string]; } else { received = (NSString*)aString; } - //NSLog(@"setMarkedText: %@ %d %d",received,newSelection.location,newSelection.length); - // This code creates the OS X behaviour of seeing dead keys as things - // are being composed. - next_compose_length = newSelection.location; - [FLView prepareEtext:received]; - //NSLog(@"Fl::e_text=%@ Fl::e_length=%d next_compose_length=%d", received, Fl::e_length, next_compose_length); + fl_lock_function(); + /*NSLog(@"setMarkedText:%@ l=%d newSelection=%d,%d Fl::compose_state=%d replacement=%d,%d", + received, strlen([received UTF8String]), newSelection.location, newSelection.length, Fl::compose_state, + replacementRange.location, replacementRange.length);*/ + Fl_Window *target = [(FLWindow*)[self window] getFl_Window]; + while (replacementRange.length--) { // delete replacementRange.length characters before insertion point + Fl::e_keysym = FL_BackSpace; + Fl::compose_state = 0; + Fl_X::next_marked_length = 0; + Fl::handle(FL_KEYBOARD, target); + Fl::e_keysym = 'a'; // pretend a letter key was hit + } + if (in_key_event && Fl_X::next_marked_length && Fl::e_length) { + // if setMarkedText + setMarkedText is sent during handleEvent, text cannot be concatenated in single FL_KEYBOARD event + Fl::handle(FL_KEYBOARD, target); + Fl::e_length = 0; + } + if (in_key_event && Fl::e_length) [FLView concatEtext:received]; + else [FLView prepareEtext:received]; + Fl_X::next_marked_length = strlen([received UTF8String]); + if (!in_key_event) Fl::handle( FL_KEYBOARD, target); + else need_handle = YES; + selectedRange = NSMakeRange(100, newSelection.length); + fl_unlock_function(); } - (void)unmarkText { fl_lock_function(); - Fl::compose_state = 0; + Fl::reset_marked_text(); fl_unlock_function(); //NSLog(@"unmarkText"); } - (NSRange)selectedRange { + Fl_Widget *w = Fl::focus(); + if (w && w->use_accents_menu()) return selectedRange; return NSMakeRange(NSNotFound, 0); } - (NSRange)markedRange { - //NSLog(@"markedRange ?"); - return NSMakeRange(NSNotFound, Fl::compose_state); + //NSLog(@"markedRange=%d %d", Fl::compose_state > 0?0:NSNotFound, Fl::compose_state); + return NSMakeRange(Fl::compose_state > 0?0:NSNotFound, Fl::compose_state); } - (BOOL)hasMarkedText { @@ -1994,6 +2404,9 @@ static void q_set_window_title(NSWindow *nsw, const char * name, const char *mi } - (NSAttributedString *)attributedSubstringFromRange:(NSRange)aRange { + return [self attributedSubstringForProposedRange:aRange actualRange:NULL]; +} +- (NSAttributedString *)attributedSubstringForProposedRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange { //NSLog(@"attributedSubstringFromRange: %d %d",aRange.location,aRange.length); return nil; } @@ -2003,28 +2416,44 @@ static void q_set_window_title(NSWindow *nsw, const char * name, const char *mi } - (NSRect)firstRectForCharacterRange:(NSRange)aRange { + return [self firstRectForCharacterRange:aRange actualRange:NULL]; +} +- (NSRect)firstRectForCharacterRange:(NSRange)aRange actualRange:(NSRangePointer)actualRange { + //NSLog(@"firstRectForCharacterRange %d %d actualRange=%p",aRange.location, aRange.length,actualRange); NSRect glyphRect; fl_lock_function(); Fl_Widget *focus = Fl::focus(); - Fl_Window *wfocus = focus->window(); - while (wfocus->window()) wfocus = wfocus->window(); + Fl_Window *wfocus = [(FLWindow*)[self window] getFl_Window]; + if (!focus) focus = wfocus; glyphRect.size.width = 0; - if (dynamic_cast<Fl_Text_Display*>(focus) != NULL) { - int x, y; - Fl_Text_Display *current = (Fl_Text_Display*)focus; - current->position_to_xy( current->insert_position(), &x, &y ); + int x, y, height; + if (Fl_X::insertion_point_location(&x, &y, &height)) { glyphRect.origin.x = (CGFloat)x; - glyphRect.origin.y = (CGFloat)y + current->textsize(); - glyphRect.size.height = current->textsize(); + glyphRect.origin.y = (CGFloat)y; } else { - glyphRect.origin.x = focus->x(); - glyphRect.origin.y = focus->y() + focus->h(); - glyphRect.size.height = 12; + if (focus->as_window()) { + glyphRect.origin.x = 0; + glyphRect.origin.y = focus->h(); + } + else { + glyphRect.origin.x = focus->x(); + glyphRect.origin.y = focus->y() + focus->h(); + } + height = 12; + } + glyphRect.size.height = height; + Fl_Window *win = focus->as_window(); + if (!win) win = focus->window(); + while (win != NULL && win != wfocus) { + glyphRect.origin.x += win->x(); + glyphRect.origin.y += win->y(); + win = win->window(); } // Convert the rect to screen coordinates glyphRect.origin.y = wfocus->h() - glyphRect.origin.y; - glyphRect.origin = [[self window] convertBaseToScreen:glyphRect.origin]; + glyphRect.origin = [(FLWindow*)[self window] convertBaseToScreen:glyphRect.origin]; + if (actualRange) *actualRange = aRange; fl_unlock_function(); return glyphRect; } @@ -2033,8 +2462,12 @@ static void q_set_window_title(NSWindow *nsw, const char * name, const char *mi return 0; } +- (NSInteger)windowLevel { + return [[self window] level]; +} + - (NSInteger)conversationIdentifier { - return (NSInteger)self; + return identifier; } @end @@ -2057,6 +2490,29 @@ void Fl_Window::fullscreen_off_x(int X, int Y, int W, int H) { } /* + * Initialize the given port for redraw and call the window's flush() to actually draw the content + */ +void Fl_X::flush() +{ + if (through_drawRect || w->as_gl_window()) { + make_current_counts = 1; + w->flush(); + make_current_counts = 0; + Fl_X::q_release_context(); + return; + } + // have Cocoa immediately redraw the window's view + FLView *view = (FLView*)[fl_xid(w) contentView]; + fl_x_to_redraw = this; + [view setNeedsDisplay:YES]; + // will send the drawRect: message to the window's view after having prepared the adequate NSGraphicsContext + [view displayIfNeededIgnoringOpacity]; + fl_x_to_redraw = NULL; +} + +//bool Fl_X::make_shaped = false; + +/* * go ahead, create that (sub)window */ void Fl_X::make(Fl_Window* w) @@ -2069,8 +2525,9 @@ void Fl_X::make(Fl_Window* w) x->other_xid = 0; x->region = 0; x->subRegion = 0; - x->cursor = fl_default_cursor; + x->cursor = NULL; x->gc = 0; // stay 0 for Quickdraw; fill with CGContext for Quartz + w->set_visible(); Fl_Window *win = w->window(); Fl_X *xo = Fl_X::i(win); if (xo) { @@ -2092,7 +2549,7 @@ void Fl_X::make(Fl_Window* w) } if (w->as_gl_window()) { // if creating a sub-GL-window while (win->window()) win = win->window(); - [Fl_X::i(win)->xid setContainsGLsubwindow:YES]; + [Fl_X::i(win)->xid containsGLsubwindow:YES]; } fl_show_iconic = 0; } @@ -2109,7 +2566,7 @@ void Fl_X::make(Fl_Window* w) int hp = w->h(); if (w->size_range_set) { if ( w->minh != w->maxh || w->minw != w->maxw) { - winstyle |= NSResizableWindowMask; + if (w->border()) winstyle |= NSResizableWindowMask; } } else { if (w->resizable()) { @@ -2117,7 +2574,7 @@ void Fl_X::make(Fl_Window* w) int minw = o->w(); if (minw > 100) minw = 100; int minh = o->h(); if (minh > 100) minh = 100; w->size_range(w->w() - o->w() + minw, w->h() - o->h() + minh, 0, 0); - winstyle |= NSResizableWindowMask; + if (w->border()) winstyle |= NSResizableWindowMask; } else { w->size_range(w->w(), w->h(), w->w(), w->h()); } @@ -2127,18 +2584,17 @@ void Fl_X::make(Fl_Window* w) if (!fake_X_wm(w, xwm, ywm, bt, bx, by)) { // menu windows and tooltips if (w->modal()||w->tooltip_window()) { - winstyle = NSBorderlessWindowMask; - winlevel = NSModalPanelWindowLevel; - } else { - winstyle = NSBorderlessWindowMask; + winlevel = modal_window_level(); } - } else if (w->modal()) { + //winstyle = NSBorderlessWindowMask; + } + if (w->modal()) { winstyle &= ~NSMiniaturizableWindowMask; // winstyle &= ~(NSResizableWindowMask | NSMiniaturizableWindowMask); - winlevel = NSModalPanelWindowLevel; + winlevel = modal_window_level(); } else if (w->non_modal()) { - winlevel = NSFloatingWindowLevel; + winlevel = non_modal_window_level(); } if (by+bt) { @@ -2165,16 +2621,39 @@ void Fl_X::make(Fl_Window* w) x->other_xid = 0; // room for doublebuffering image map. On OS X this is only used by overlay windows x->region = 0; x->subRegion = 0; - x->cursor = fl_default_cursor; + x->cursor = NULL; x->xidChildren = 0; x->xidNext = 0; x->gc = 0; NSRect crect; if (w->fullscreen_active()) { - int sx, sy, sw, sh; - Fl::screen_xywh(sx, sy, sw, sh, w->x(), w->y(), w->w(), w->h()); - w->resize(sx, sy, sw, sh); + int top, bottom, left, right; + int sx, sy, sw, sh, X, Y, W, H; + + top = w->fullscreen_screen_top; + bottom = w->fullscreen_screen_bottom; + left = w->fullscreen_screen_left; + right = w->fullscreen_screen_right; + + if ((top < 0) || (bottom < 0) || (left < 0) || (right < 0)) { + top = Fl::screen_num(w->x(), w->y(), w->w(), w->h()); + bottom = top; + left = top; + right = top; + } + + Fl::screen_xywh(sx, sy, sw, sh, top); + Y = sy; + Fl::screen_xywh(sx, sy, sw, sh, bottom); + H = sy + sh - Y; + Fl::screen_xywh(sx, sy, sw, sh, left); + X = sx; + Fl::screen_xywh(sx, sy, sw, sh, right); + W = sx + sw - X; + + w->resize(X, Y, W, H); + winstyle = NSBorderlessWindowMask; winlevel = NSStatusWindowLevel; } @@ -2188,6 +2667,10 @@ void Fl_X::make(Fl_Window* w) [cw setFrameOrigin:crect.origin]; [cw setHasShadow:YES]; [cw setAcceptsMouseMovedEvents:YES]; + if (w->shape_data_) { + [cw setOpaque:NO]; // shaped windows must be non opaque + [cw setBackgroundColor:[NSColor clearColor]]; // and with transparent background color + } x->xid = cw; x->w = w; w->i = x; x->wait_for_expose = 1; @@ -2195,6 +2678,7 @@ void Fl_X::make(Fl_Window* w) Fl_X::first = x; FLView *myview = [[FLView alloc] init]; [cw setContentView:myview]; + [myview release]; [cw setLevel:winlevel]; q_set_window_title(cw, w->label(), w->iconlabel()); @@ -2212,12 +2696,10 @@ void Fl_X::make(Fl_Window* w) [cw setAlphaValue:0.97]; } // Install DnD handlers - [myview registerForDraggedTypes:[NSArray arrayWithObjects: - NSStringPboardType, NSFilenamesPboardType, nil]]; + [myview registerForDraggedTypes:[NSArray arrayWithObjects:utf8_format, NSFilenamesPboardType, nil]]; if ( ! Fl_X::first->next ) { // if this is the first window, we need to bring the application to the front - ProcessSerialNumber psn = { 0, kCurrentProcess }; - SetFrontProcess( &psn ); + [NSApp activateIgnoringOtherApps:YES]; } if (w->size_range_set) w->size_range_(); @@ -2231,7 +2713,7 @@ void Fl_X::make(Fl_Window* w) w->set_visible(); if ( w->border() || (!w->modal() && !w->tooltip_window()) ) Fl::handle(FL_FOCUS, w); Fl::first_window(w); - [cw setDelegate:[NSApp delegate]]; + [cw setDelegate:[FLWindowDelegate createOnce]]; if (fl_show_iconic) { fl_show_iconic = 0; [cw miniaturize:nil]; @@ -2316,7 +2798,7 @@ void Fl_Window::show() { labeltype(FL_NO_LABEL); } Fl_Tooltip::exit(this); - if (!shown() || !i) { + if (!shown()) { Fl_X::make(this); } else { if ( !parent() ) { @@ -2388,9 +2870,34 @@ void Fl_Window::resize(int X,int Y,int W,int H) { /* * make all drawing go into this window (called by subclass flush() impl.) + + This can be called in 3 different instances: + + 1) When a window is created, resized, or deminiaturized. + The system sends the drawRect: message to the window's view after having prepared the current graphics context + to draw to this view. Variable through_drawRect is YES, and fl_x_to_redraw is NULL. Processing of drawRect: calls + handleUpdateEvent() that calls Fl_X::flush() for the window and its subwindows. Fl_X::flush() calls + Fl_Window::flush() that calls Fl_Window::make_current() that only needs to identify the graphics port of the + current graphics context. The window's draw() function is then executed. + + 2) At each round of the FLTK event loop. + Fl::flush() is called, that calls Fl_X::flush() on each window that needs drawing. Fl_X::flush() sets + fl_x_to_redraw to this and sends the displayIfNeededIgnoringOpacity message to the window's view. + This message makes the system prepare the current graphics context adequately for drawing to this view, and + send it the drawRect: message which sets through_drawRect to YES. Processing of the drawRect: message calls + Fl_X::flush() for the window which proceeds as in 1) above. + + 3) An FLTK application can call Fl_Window::make_current() at any time before it draws to a window. + This occurs for instance in the idle callback function of the mandelbrot test program. Variable through_drawRect is NO, + so Fl_Window::make_current() creates a new graphics context adequate for the window. + Subsequent drawing requests go to this window. CAUTION: it's not possible to call Fl::wait(), Fl::check() + nor Fl::ready() while in the draw() function of a widget. Use an idle callback instead. + */ void Fl_Window::make_current() { + if (make_current_counts > 1) return; + if (make_current_counts) make_current_counts++; Fl_X::q_release_context(); fl_window = i->xid; current_ = this; @@ -2404,12 +2911,9 @@ void Fl_Window::make_current() yp += win->y(); win = (Fl_Window*)win->window(); } - - NSView *current_focus = [NSView focusView]; - // sometimes current_focus is set to a non-FLTK view: don't touch that - if ( [current_focus isKindOfClass:[FLView class]] ) [current_focus unlockFocus]; - [[i->xid contentView] lockFocus]; - i->gc = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; + NSGraphicsContext *nsgc = through_drawRect ? [NSGraphicsContext currentContext] : + [NSGraphicsContext graphicsContextWithWindow:fl_window]; + i->gc = (CGContextRef)[nsgc graphicsPort]; fl_gc = i->gc; Fl_Region fl_window_region = XRectangleRegion(0,0,w(),h()); if ( ! this->window() ) { @@ -2477,7 +2981,8 @@ void Fl_X::q_clear_clipping() { void Fl_X::q_release_context(Fl_X *x) { if (x && x->gc!=fl_gc) return; if (!fl_gc) return; - CGContextRestoreGState(fl_gc); // matches the CGContextSaveGState of make_current + CGContextRestoreGState(fl_gc); // KEEP IT: matches the CGContextSaveGState of make_current + CGContextFlush(fl_gc); fl_gc = 0; #if defined(FLTK_USE_CAIRO) if (Fl::cairo_autolink_context()) Fl::cairo_make_current((Fl_Window*) 0); // capture gc changes automatically to update the cairo context adequately @@ -2514,35 +3019,55 @@ static void convert_crlf(char * s, size_t len) } // fltk 1.3 clipboard support constant definitions: -const CFStringRef flavorNames[] = { - CFSTR("public.utf16-plain-text"), - CFSTR("public.utf8-plain-text"), - CFSTR("com.apple.traditional-mac-plain-text") }; -const CFStringEncoding encodings[] = { - kCFStringEncodingUnicode, - kCFStringEncodingUTF8, - kCFStringEncodingMacRoman}; -const size_t handledFlavorsCount = sizeof(encodings)/sizeof(CFStringEncoding); +static NSString *calc_utf8_format(void) +{ +#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6 +#define NSPasteboardTypeString @"public.utf8-plain-text" +#endif + if (fl_mac_os_version >= 100600) return NSPasteboardTypeString; + return NSStringPboardType; +} // clipboard variables definitions : -char *fl_selection_buffer[2]; -int fl_selection_length[2]; +char *fl_selection_buffer[2] = {NULL, NULL}; +int fl_selection_length[2] = {0, 0}; static int fl_selection_buffer_length[2]; -static PasteboardRef myPasteboard = 0; -static void allocatePasteboard() { - if (!myPasteboard) - PasteboardCreate(kPasteboardClipboard, &myPasteboard); +static PasteboardRef allocatePasteboard(void) +{ + PasteboardRef clip; + PasteboardCreate(kPasteboardClipboard, &clip); // requires Mac OS 10.3 + return clip; } +static PasteboardRef myPasteboard = allocatePasteboard(); +extern void fl_trigger_clipboard_notify(int source); + +void fl_clipboard_notify_change() { + // No need to do anything here... +} + +static void clipboard_check(void) +{ + PasteboardSyncFlags flags; + + flags = PasteboardSynchronize(myPasteboard); // requires Mac OS 10.3 + + if (!(flags & kPasteboardModified)) + return; + if (flags & kPasteboardClientIsOwner) + return; + + fl_trigger_clipboard_notify(1); +} /* * create a selection - * owner: widget that created the selection * stuff: pointer to selected data - * size of selected data + * len: size of selected data + * type: always "plain/text" for now */ -void Fl::copy(const char *stuff, int len, int clipboard) { +void Fl::copy(const char *stuff, int len, int clipboard, const char *type) { if (!stuff || len<0) return; if (len+1 > fl_selection_buffer_length[clipboard]) { delete[] fl_selection_buffer[clipboard]; @@ -2553,84 +3078,180 @@ void Fl::copy(const char *stuff, int len, int clipboard) { fl_selection_buffer[clipboard][len] = 0; // needed for direct paste fl_selection_length[clipboard] = len; if (clipboard) { - allocatePasteboard(); - OSStatus err = PasteboardClear(myPasteboard); - if (err!=noErr) return; // clear did not work, maybe not owner of clipboard. - PasteboardSynchronize(myPasteboard); CFDataRef text = CFDataCreate(kCFAllocatorDefault, (UInt8*)fl_selection_buffer[1], len); if (text==NULL) return; // there was a pb creating the object, abort. - err=PasteboardPutItemFlavor(myPasteboard, (PasteboardItemID)1, CFSTR("public.utf8-plain-text"), text, 0); + NSPasteboard *clip = [NSPasteboard generalPasteboard]; + [clip declareTypes:[NSArray arrayWithObject:utf8_format] owner:nil]; + [clip setData:(NSData*)text forType:utf8_format]; CFRelease(text); } } +static int get_plain_text_from_clipboard(char **buffer, int previous_length) +{ + NSInteger length = 0; + NSPasteboard *clip = [NSPasteboard generalPasteboard]; + NSString *found = [clip availableTypeFromArray:[NSArray arrayWithObjects:utf8_format, @"public.utf16-plain-text", @"com.apple.traditional-mac-plain-text", nil]]; + if (found) { + NSData *data = [clip dataForType:found]; + if (data) { + NSInteger len; + char *aux_c = NULL; + if (![found isEqualToString:utf8_format]) { + NSString *auxstring; + auxstring = (NSString *)CFStringCreateWithBytes(NULL, + (const UInt8*)[data bytes], + [data length], + [found isEqualToString:@"public.utf16-plain-text"] ? kCFStringEncodingUnicode : kCFStringEncodingMacRoman, + false); + aux_c = strdup([auxstring UTF8String]); + [auxstring release]; + len = strlen(aux_c) + 1; + } + else len = [data length] + 1; + if ( len >= previous_length ) { + length = len; + delete[] *buffer; + *buffer = new char[len]; + } + if (![found isEqualToString:utf8_format]) { + strcpy(*buffer, aux_c); + free(aux_c); + } + else { + [data getBytes:*buffer]; + } + (*buffer)[len - 1] = 0; + length = len - 1; + convert_crlf(*buffer, len - 1); // turn all \r characters into \n: + Fl::e_clipboard_type = Fl::clipboard_plain_text; + } + } + return length; +} + +static Fl_Image* get_image_from_clipboard() +{ + Fl_RGB_Image *image = NULL; + uchar *imagedata; + NSBitmapImageRep *bitmap; + NSPasteboard *clip = [NSPasteboard generalPasteboard]; + NSArray *present = [clip types]; // types in pasteboard in order of decreasing preference + NSArray *possible = [NSArray arrayWithObjects:@"com.adobe.pdf", @"public.tiff", @"com.apple.pict", nil]; + NSString *found = nil; + NSUInteger rank; + for (rank = 0; rank < [present count]; rank++) { // find first of possible types present in pasteboard + for (NSUInteger i = 0; i < [possible count]; i++) { + if ([[present objectAtIndex:rank] isEqualToString:[possible objectAtIndex:i]]) { + found = [present objectAtIndex:rank]; + goto after_loop; + } + } + } +after_loop: + if (found) { + NSData *data = [clip dataForType:found]; + if (data) { + if ([found isEqualToString:@"public.tiff"]) { + bitmap = [NSBitmapImageRep imageRepWithData:data]; + int bpp = [bitmap bytesPerPlane]; + int bpr = [bitmap bytesPerRow]; + int depth = [bitmap samplesPerPixel], w = bpr/depth, h = bpp/bpr; + imagedata = new uchar[w * h * depth]; + memcpy(imagedata, [bitmap bitmapData], w * h * depth); + image = new Fl_RGB_Image(imagedata, w, h, depth); + image->alloc_array = 1; + } + else if ([found isEqualToString:@"com.adobe.pdf"] || [found isEqualToString:@"com.apple.pict"]) { + NSRect rect; + NSImageRep *vectorial; + NSAffineTransform *dilate = [NSAffineTransform transform]; + if ([found isEqualToString:@"com.adobe.pdf"] ) { + vectorial = [NSPDFImageRep imageRepWithData:data]; + rect = [(NSPDFImageRep*)vectorial bounds]; // in points = 1/72 inch + Fl_Window *win = Fl::first_window(); + int screen_num = win ? Fl::screen_num(win->x(), win->y(), win->w(), win->h()) : 0; + float hr, vr; + Fl::screen_dpi(hr, vr, screen_num); // 1 inch = hr pixels = 72 points -> hr/72 pixel/point + CGFloat scale = hr/72; + [dilate scaleBy:scale]; + rect.size.width *= scale; + rect.size.height *= scale; + rect = NSIntegralRect(rect); + } + else { + vectorial = [NSPICTImageRep imageRepWithData:data]; + rect = [(NSPICTImageRep*)vectorial boundingBox]; // in pixel, no scaling required + } + imagedata = new uchar[(int)(rect.size.width * rect.size.height) * 4]; + memset(imagedata, -1, (int)(rect.size.width * rect.size.height) * 4); + bitmap = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:&imagedata + pixelsWide:rect.size.width + pixelsHigh:rect.size.height + bitsPerSample:8 + samplesPerPixel:3 + hasAlpha:NO + isPlanar:NO + colorSpaceName:NSDeviceRGBColorSpace + bytesPerRow:rect.size.width*4 + bitsPerPixel:32]; + NSDictionary *dict = [NSDictionary dictionaryWithObject:bitmap + forKey:NSGraphicsContextDestinationAttributeName]; + NSGraphicsContext *oldgc = [NSGraphicsContext currentContext]; + [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithAttributes:dict]]; + [dilate concat]; + [vectorial draw]; + [NSGraphicsContext setCurrentContext:oldgc]; + [bitmap release]; + image = new Fl_RGB_Image(imagedata, rect.size.width, rect.size.height, 4); + image->alloc_array = 1; + } + Fl::e_clipboard_type = Fl::clipboard_image; + } + } + return image; +} + // Call this when a "paste" operation happens: -void Fl::paste(Fl_Widget &receiver, int clipboard) { +void Fl::paste(Fl_Widget &receiver, int clipboard, const char *type) { + if (type[0] == 0) type = Fl::clipboard_plain_text; if (clipboard) { - // see if we own the selection, if not go get it: - fl_selection_length[1] = 0; - OSStatus err = noErr; - Boolean found = false; - CFDataRef flavorData = NULL; - CFStringEncoding encoding = 0; - - allocatePasteboard(); - PasteboardSynchronize(myPasteboard); - ItemCount nFlavor = 0, i, j; - err = PasteboardGetItemCount(myPasteboard, &nFlavor); - if (err==noErr) { - for (i=1; i<=nFlavor; i++) { - PasteboardItemID itemID = 0; - CFArrayRef flavorTypeArray = NULL; - found = false; - err = PasteboardGetItemIdentifier(myPasteboard, i, &itemID); - if (err!=noErr) continue; - err = PasteboardCopyItemFlavors(myPasteboard, itemID, &flavorTypeArray); - if (err!=noErr) { - if (flavorTypeArray) {CFRelease(flavorTypeArray); flavorTypeArray = NULL;} - continue; - } - CFIndex flavorCount = CFArrayGetCount(flavorTypeArray); - for (j = 0; j < handledFlavorsCount; j++) { - for (CFIndex flavorIndex=0; flavorIndex<flavorCount; flavorIndex++) { - CFStringRef flavorType = (CFStringRef)CFArrayGetValueAtIndex(flavorTypeArray, flavorIndex); - if (UTTypeConformsTo(flavorType, flavorNames[j])) { - err = PasteboardCopyItemFlavorData( myPasteboard, itemID, flavorNames[j], &flavorData ); - if (err != noErr) continue; - encoding = encodings[j]; - found = true; - break; - } - } - if (found) break; - } - if (flavorTypeArray) {CFRelease(flavorTypeArray); flavorTypeArray = NULL;} - if (found) break; + Fl::e_clipboard_type = ""; + if (strcmp(type, Fl::clipboard_plain_text) == 0) { + fl_selection_length[1] = get_plain_text_from_clipboard( &fl_selection_buffer[1], fl_selection_length[1]); } - if (found) { - CFIndex len = CFDataGetLength(flavorData); - CFStringRef mycfs = CFStringCreateWithBytes(NULL, CFDataGetBytePtr(flavorData), len, encoding, false); - CFRelease(flavorData); - len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(mycfs), kCFStringEncodingUTF8) + 1; - if ( len >= fl_selection_buffer_length[1] ) { - fl_selection_buffer_length[1] = len; - delete[] fl_selection_buffer[1]; - fl_selection_buffer[1] = new char[len]; - } - CFStringGetCString(mycfs, fl_selection_buffer[1], len, kCFStringEncodingUTF8); - CFRelease(mycfs); - len = strlen(fl_selection_buffer[1]); - fl_selection_length[1] = len; - convert_crlf(fl_selection_buffer[1],len); // turn all \r characters into \n: + else if (strcmp(type, Fl::clipboard_image) == 0) { + Fl::e_clipboard_data = get_image_from_clipboard( ); + if (Fl::e_clipboard_data) { + int done = receiver.handle(FL_PASTE); + Fl::e_clipboard_type = ""; + if (done == 0) { + delete (Fl_Image*)Fl::e_clipboard_data; + Fl::e_clipboard_data = NULL; + } } - } + return; + } + else + fl_selection_length[1] = 0; } Fl::e_text = fl_selection_buffer[clipboard]; Fl::e_length = fl_selection_length[clipboard]; - if (!Fl::e_text) Fl::e_text = (char *)""; + if (!Fl::e_length) Fl::e_text = (char *)""; receiver.handle(FL_PASTE); } +int Fl::clipboard_contains(const char *type) { + NSString *found = nil; + if (strcmp(type, Fl::clipboard_plain_text) == 0) { + found = [[NSPasteboard generalPasteboard] availableTypeFromArray:[NSArray arrayWithObjects:utf8_format, @"public.utf16-plain-text", @"com.apple.traditional-mac-plain-text", nil]]; + } + else if (strcmp(type, Fl::clipboard_image) == 0) { + found = [[NSPasteboard generalPasteboard] availableTypeFromArray:[NSArray arrayWithObjects:@"public.tiff", @"com.adobe.pdf", @"com.apple.pict", nil]]; + } + return found != nil; +} + int Fl_X::unlink(Fl_X *start) { if (start) { Fl_X *pc = start; @@ -2674,11 +3295,6 @@ void Fl_X::relink(Fl_Window *w, Fl_Window *wp) { void Fl_X::destroy() { // subwindows share their xid with their parent window, so should not close it if (!subwindow && w && !w->parent() && xid) { - NSView *topview = [xid contentView]; - if ( [NSView focusView] == topview ) { - [topview unlockFocus]; - } - [topview release]; [xid close]; } } @@ -2692,6 +3308,10 @@ void Fl_X::map() { Fl_X::relink(w, w->window() ); w->redraw(); } + if (cursor) { + [(NSCursor*)cursor release]; + cursor = NULL; + } } void Fl_X::unmap() { @@ -2780,84 +3400,152 @@ void Fl_X::collapse() { static NSImage *CGBitmapContextToNSImage(CGContextRef c) // the returned NSImage is autoreleased { + NSImage* image; +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 + if (fl_mac_os_version >= 100600) { + CGImageRef cgimg = CGBitmapContextCreateImage(c); // requires 10.4 + image = [[NSImage alloc] initWithCGImage:cgimg size:NSZeroSize]; // requires 10.6 + CFRelease(cgimg); + } + else +#endif + { + unsigned char *pdata = (unsigned char *)CGBitmapContextGetData(c); + NSBitmapImageRep *imagerep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:&pdata + pixelsWide:CGBitmapContextGetWidth(c) + pixelsHigh:CGBitmapContextGetHeight(c) + bitsPerSample:8 + samplesPerPixel:4 + hasAlpha:YES + isPlanar:NO + colorSpaceName:NSDeviceRGBColorSpace + bytesPerRow:CGBitmapContextGetBytesPerRow(c) + bitsPerPixel:CGBitmapContextGetBitsPerPixel(c)]; + image = [[NSImage alloc] initWithData: [imagerep TIFFRepresentation]]; + [imagerep release]; + } + return [image autorelease]; +} + + +CFDataRef Fl_X::CGBitmapContextToTIFF(CGContextRef c) +{ // the returned value is autoreleased unsigned char *pdata = (unsigned char *)CGBitmapContextGetData(c); NSBitmapImageRep *imagerep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:&pdata - pixelsWide:CGBitmapContextGetWidth(c) - pixelsHigh:CGBitmapContextGetHeight(c) - bitsPerSample:8 - samplesPerPixel:4 - hasAlpha:YES - isPlanar:NO - colorSpaceName:NSDeviceRGBColorSpace - bytesPerRow:CGBitmapContextGetBytesPerRow(c) - bitsPerPixel:CGBitmapContextGetBitsPerPixel(c)]; - NSImage* image = [[NSImage alloc] initWithData: [imagerep TIFFRepresentation]]; + pixelsWide:CGBitmapContextGetWidth(c) + pixelsHigh:CGBitmapContextGetHeight(c) + bitsPerSample:8 + samplesPerPixel:3 + hasAlpha:NO + isPlanar:NO + colorSpaceName:NSDeviceRGBColorSpace + bytesPerRow:CGBitmapContextGetBytesPerRow(c) + bitsPerPixel:CGBitmapContextGetBitsPerPixel(c)]; + NSData* tiff = [imagerep TIFFRepresentation]; [imagerep release]; - return [image autorelease]; + return (CFDataRef)tiff; } -static NSCursor *PrepareCursor(NSCursor *cursor, CGContextRef (*f)() ) +int Fl_X::set_cursor(Fl_Cursor c) { - if (cursor == nil) { - CGContextRef c = f(); - NSImage *image = CGBitmapContextToNSImage(c); - fl_delete_offscreen( (Fl_Offscreen)c ); - NSPoint pt = {[image size].width/2, [image size].height/2}; - cursor = [[NSCursor alloc] initWithImage:image hotSpot:pt]; + if (cursor) { + [(NSCursor*)cursor release]; + cursor = NULL; } - return cursor; -} -void Fl_X::set_cursor(Fl_Cursor c) -{ - NSCursor *icrsr; switch (c) { - case FL_CURSOR_CROSS: icrsr = [NSCursor crosshairCursor]; break; - case FL_CURSOR_WAIT: - static NSCursor *watch = nil; - watch = PrepareCursor(watch, &Fl_X::watch_cursor_image); - icrsr = watch; - break; - case FL_CURSOR_INSERT: icrsr = [NSCursor IBeamCursor]; break; - case FL_CURSOR_N: icrsr = [NSCursor resizeUpCursor]; break; - case FL_CURSOR_S: icrsr = [NSCursor resizeDownCursor]; break; - case FL_CURSOR_NS: icrsr = [NSCursor resizeUpDownCursor]; break; - case FL_CURSOR_HELP: - static NSCursor *help = nil; - help = PrepareCursor(help, &Fl_X::help_cursor_image); - icrsr = help; - break; - case FL_CURSOR_HAND: icrsr = [NSCursor pointingHandCursor]; break; - case FL_CURSOR_MOVE: icrsr = [NSCursor openHandCursor]; break; - case FL_CURSOR_NE: - case FL_CURSOR_SW: - case FL_CURSOR_NESW: - static NSCursor *nesw = nil; - nesw = PrepareCursor(nesw, &Fl_X::nesw_cursor_image); - icrsr = nesw; - break; - case FL_CURSOR_E: icrsr = [NSCursor resizeRightCursor]; break; - case FL_CURSOR_W: icrsr = [NSCursor resizeLeftCursor]; break; - case FL_CURSOR_WE: icrsr = [NSCursor resizeLeftRightCursor]; break; - case FL_CURSOR_SE: - case FL_CURSOR_NW: - case FL_CURSOR_NWSE: - static NSCursor *nwse = nil; - nwse = PrepareCursor(nwse, &Fl_X::nwse_cursor_image); - icrsr = nwse; - break; - case FL_CURSOR_NONE: - static NSCursor *none = nil; - none = PrepareCursor(none, &Fl_X::none_cursor_image); - icrsr = none; - break; - case FL_CURSOR_ARROW: - case FL_CURSOR_DEFAULT: - default: icrsr = [NSCursor arrowCursor]; - break; + case FL_CURSOR_ARROW: cursor = [NSCursor arrowCursor]; break; + case FL_CURSOR_CROSS: cursor = [NSCursor crosshairCursor]; break; + case FL_CURSOR_INSERT: cursor = [NSCursor IBeamCursor]; break; + case FL_CURSOR_HAND: cursor = [NSCursor pointingHandCursor]; break; + case FL_CURSOR_MOVE: cursor = [NSCursor openHandCursor]; break; + case FL_CURSOR_NS: cursor = [NSCursor resizeUpDownCursor]; break; + case FL_CURSOR_WE: cursor = [NSCursor resizeLeftRightCursor]; break; + case FL_CURSOR_N: cursor = [NSCursor resizeUpCursor]; break; + case FL_CURSOR_E: cursor = [NSCursor resizeRightCursor]; break; + case FL_CURSOR_W: cursor = [NSCursor resizeLeftCursor]; break; + case FL_CURSOR_S: cursor = [NSCursor resizeDownCursor]; break; + default: + return 0; } - [icrsr set]; - cursor = icrsr; + + [(NSCursor*)cursor retain]; + + [(NSWindow*)xid invalidateCursorRectsForView:[(NSWindow*)xid contentView]]; + + return 1; +} + +int Fl_X::set_cursor(const Fl_RGB_Image *image, int hotx, int hoty) { + if (cursor) { + [(NSCursor*)cursor release]; + cursor = NULL; + } + + if ((hotx < 0) || (hotx >= image->w())) + return 0; + if ((hoty < 0) || (hoty >= image->h())) + return 0; + + // OS X >= 10.6 can create a NSImage from a CGImage, but we need to + // support older versions, hence this pesky handling. + + NSBitmapImageRep *bitmap = [[NSBitmapImageRep alloc] + initWithBitmapDataPlanes:NULL + pixelsWide:image->w() + pixelsHigh:image->h() + bitsPerSample:8 + samplesPerPixel:image->d() + hasAlpha:!(image->d() & 1) + isPlanar:NO + colorSpaceName:(image->d()<=2) ? NSDeviceWhiteColorSpace : NSDeviceRGBColorSpace + bytesPerRow:(image->w() * image->d()) + bitsPerPixel:(image->d()*8)]; + + // Alpha needs to be premultiplied for this format + + const uchar *i = (const uchar*)*image->data(); + unsigned char *o = [bitmap bitmapData]; + for (int y = 0;y < image->h();y++) { + if (!(image->d() & 1)) { + for (int x = 0;x < image->w();x++) { + unsigned int alpha; + if (image->d() == 4) { + alpha = i[3]; + *o++ = (unsigned char)((unsigned int)*i++ * alpha / 255); + *o++ = (unsigned char)((unsigned int)*i++ * alpha / 255); + } + + alpha = i[1]; + *o++ = (unsigned char)((unsigned int)*i++ * alpha / 255); + *o++ = alpha; + i++; + } + } else { + // No alpha, so we can just copy everything directly. + int len = image->w() * image->d(); + memcpy(o, i, len); + o += len; + i += len; + } + i += image->ld(); + } + + NSImage *nsimage = [[NSImage alloc] + initWithSize:NSMakeSize(image->w(), image->h())]; + + [nsimage addRepresentation:bitmap]; + + cursor = [[NSCursor alloc] + initWithImage:nsimage + hotSpot:NSMakePoint(hotx, hoty)]; + + [(NSWindow*)xid invalidateCursorRectsForView:[(NSWindow*)xid contentView]]; + + [bitmap release]; + [nsimage release]; + + return 1; } @interface FLaboutItemTarget : NSObject @@ -2879,7 +3567,7 @@ void Fl_X::set_cursor(Fl_Cursor c) } //#include <FL/Fl_PostScript.H> - (void)printPanel -{ +{ Fl_Printer printer; //Fl_PostScript_File_Device printer; int w, h, ww, wh; @@ -2920,24 +3608,26 @@ static void createAppleMenu(void) static BOOL donethat = NO; if (donethat) return; donethat = YES; - NSMenu *mainmenu, *services, *appleMenu; + NSMenu *mainmenu, *services = nil, *appleMenu; NSMenuItem *menuItem; NSString *title; - - NSString *nsappname = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"]; + + SEL infodictSEL = (fl_mac_os_version >= 100200 ? @selector(localizedInfoDictionary) : @selector(infoDictionary)); + NSString *nsappname = [[[NSBundle mainBundle] performSelector:infodictSEL] objectForKey:@"CFBundleName"]; if (nsappname == nil) nsappname = [[NSProcessInfo processInfo] processName]; appleMenu = [[NSMenu alloc] initWithTitle:@""]; /* Add menu items */ - title = [[NSString stringWithUTF8String:Fl_Mac_App_Menu::about] stringByAppendingString:nsappname]; + title = [NSString stringWithFormat:NSLocalizedString([NSString stringWithUTF8String:Fl_Mac_App_Menu::about],nil), nsappname]; menuItem = [appleMenu addItemWithTitle:title action:@selector(showPanel) keyEquivalent:@""]; FLaboutItemTarget *about = [[FLaboutItemTarget alloc] init]; [menuItem setTarget:about]; [appleMenu addItem:[NSMenuItem separatorItem]]; // Print front window - if (strlen(Fl_Mac_App_Menu::print) > 0) { + title = NSLocalizedString([NSString stringWithUTF8String:Fl_Mac_App_Menu::print], nil); + if ([title length] > 0) { menuItem = [appleMenu - addItemWithTitle:[NSString stringWithUTF8String:Fl_Mac_App_Menu::print] + addItemWithTitle:title action:@selector(printPanel) keyEquivalent:@""]; [menuItem setTarget:about]; @@ -2945,35 +3635,37 @@ static void createAppleMenu(void) [menuItem setEnabled:YES]; [appleMenu addItem:[NSMenuItem separatorItem]]; } - // Services Menu - services = [[NSMenu alloc] init]; - menuItem = [appleMenu - addItemWithTitle:[NSString stringWithUTF8String:Fl_Mac_App_Menu::services] - action:nil - keyEquivalent:@""]; - [appleMenu setSubmenu:services forItem:menuItem]; - [appleMenu addItem:[NSMenuItem separatorItem]]; - // Hide AppName - title = [[NSString stringWithUTF8String:Fl_Mac_App_Menu::hide] stringByAppendingString:nsappname]; - [appleMenu addItemWithTitle:title - action:@selector(hide:) + if (fl_mac_os_version >= 100400) { // services+hide+quit already in menu in OS 10.3 + // Services Menu + services = [[NSMenu alloc] init]; + menuItem = [appleMenu + addItemWithTitle:NSLocalizedString([NSString stringWithUTF8String:Fl_Mac_App_Menu::services], nil) + action:nil + keyEquivalent:@""]; + [appleMenu setSubmenu:services forItem:menuItem]; + [appleMenu addItem:[NSMenuItem separatorItem]]; + // Hide AppName + title = [NSString stringWithFormat:NSLocalizedString([NSString stringWithUTF8String:Fl_Mac_App_Menu::hide],nil), nsappname]; + [appleMenu addItemWithTitle:title + action:@selector(hide:) + keyEquivalent:@"h"]; + // Hide Others + menuItem = [appleMenu + addItemWithTitle:NSLocalizedString([NSString stringWithUTF8String:Fl_Mac_App_Menu::hide_others] , nil) + action:@selector(hideOtherApplications:) keyEquivalent:@"h"]; - // Hide Others - menuItem = [appleMenu - addItemWithTitle:[NSString stringWithUTF8String:Fl_Mac_App_Menu::hide_others] - action:@selector(hideOtherApplications:) - keyEquivalent:@"h"]; - [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)]; - // Show All - [appleMenu addItemWithTitle:[NSString stringWithUTF8String:Fl_Mac_App_Menu::show] - action:@selector(unhideAllApplications:) keyEquivalent:@""]; - [appleMenu addItem:[NSMenuItem separatorItem]]; - // Quit AppName - title = [[NSString stringWithUTF8String:Fl_Mac_App_Menu::quit] - stringByAppendingString:nsappname]; - [appleMenu addItemWithTitle:title - action:@selector(terminate:) - keyEquivalent:@"q"]; + [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)]; + // Show All + [appleMenu addItemWithTitle:NSLocalizedString([NSString stringWithUTF8String:Fl_Mac_App_Menu::show] , nil) + action:@selector(unhideAllApplications:) keyEquivalent:@""]; + [appleMenu addItem:[NSMenuItem separatorItem]]; + // Quit AppName + title = [NSString stringWithFormat:NSLocalizedString([NSString stringWithUTF8String:Fl_Mac_App_Menu::quit] , nil), + nsappname]; + [appleMenu addItemWithTitle:title + action:@selector(terminate:) + keyEquivalent:@"q"]; + } /* Put menu into the menubar */ menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""]; [menuItem setSubmenu:appleMenu]; @@ -2984,224 +3676,16 @@ static void createAppleMenu(void) // to avoid compiler warning raised by use of undocumented setAppleMenu : [NSApp performSelector:@selector(setAppleMenu:) withObject:appleMenu]; } - [NSApp setServicesMenu:services]; [NSApp setMainMenu:mainmenu]; - [services release]; + if (services) { + [NSApp setServicesMenu:services]; + [services release]; + } [mainmenu release]; [appleMenu release]; [menuItem release]; } -@interface FLMenuItem : NSMenuItem { -} -- (void) doCallback:(id)unused; -- (void) directCallback:(id)unused; -- (const Fl_Menu_Item*) getFlItem; -@end -@implementation FLMenuItem -- (const Fl_Menu_Item*) getFlItem -{ - return *(const Fl_Menu_Item **)[(NSData*)[self representedObject] bytes]; -} -- (void) doCallback:(id)unused -{ - fl_lock_function(); - const Fl_Menu_Item *item = [self getFlItem]; - fl_sys_menu_bar->picked(item); - if ( item->flags & FL_MENU_TOGGLE ) { // update the menu toggle symbol - [self setState:(item->value() ? NSOnState : NSOffState)]; - } - else if ( item->flags & FL_MENU_RADIO ) { // update the menu radio symbols - NSMenu* menu = [self menu]; - NSInteger flRank = [menu indexOfItem:self]; - NSInteger last = [menu numberOfItems] - 1; - int from = flRank; - while(from > 0) { - if ([[menu itemAtIndex:from-1] isSeparatorItem]) break; - item = [(FLMenuItem*)[menu itemAtIndex:from-1] getFlItem]; - if ( !(item->flags & FL_MENU_RADIO) ) break; - from--; - } - int to = flRank; - while (to < last) { - if ([[menu itemAtIndex:to+1] isSeparatorItem]) break; - item = [(FLMenuItem*)[menu itemAtIndex:to+1] getFlItem]; - if (!(item->flags & FL_MENU_RADIO)) break; - to++; - } - for(int i = from; i <= to; i++) { - NSMenuItem *nsitem = [menu itemAtIndex:i]; - [nsitem setState:(nsitem != self ? NSOffState : NSOnState)]; - } - } - fl_unlock_function(); -} -- (void) directCallback:(id)unused -{ - fl_lock_function(); - Fl_Menu_Item *item = (Fl_Menu_Item *)[(NSData*)[self representedObject] bytes]; - if ( item && item->callback() ) item->do_callback(NULL); - fl_unlock_function(); -} -@end - -void fl_mac_set_about( Fl_Callback *cb, void *user_data, int shortcut) -{ - fl_open_display(); - Fl_Menu_Item aboutItem; - memset(&aboutItem, 0, sizeof(Fl_Menu_Item)); - aboutItem.callback(cb); - aboutItem.user_data(user_data); - aboutItem.shortcut(shortcut); - NSMenu *appleMenu = [[[NSApp mainMenu] itemAtIndex:0] submenu]; - CFStringRef cfname = CFStringCreateCopy(NULL, (CFStringRef)[[appleMenu itemAtIndex:0] title]); - [appleMenu removeItemAtIndex:0]; - FLMenuItem *item = [[[FLMenuItem alloc] initWithTitle:(NSString*)cfname - action:@selector(directCallback:) - keyEquivalent:@""] autorelease]; - if (aboutItem.shortcut()) { - Fl_Sys_Menu_Bar::doMenuOrItemOperation(Fl_Sys_Menu_Bar::setKeyEquivalent, item, aboutItem.shortcut() & 0xff); - Fl_Sys_Menu_Bar::doMenuOrItemOperation(Fl_Sys_Menu_Bar::setKeyEquivalentModifierMask, item, aboutItem.shortcut() ); - } - NSData *pointer = [NSData dataWithBytes:&aboutItem length:sizeof(Fl_Menu_Item)]; - [item setRepresentedObject:pointer]; - [appleMenu insertItem:item atIndex:0]; - CFRelease(cfname); - [item setTarget:item]; -} - -static char *remove_ampersand(const char *s) -{ - char *ret = strdup(s); - const char *p = s; - char *q = ret; - while(*p != 0) { - if (p[0]=='&') { - if (p[1]=='&') { - *q++ = '&'; p+=2; - } else { - p++; - } - } else { - *q++ = *p++; - } - } - *q = 0; - return ret; -} - -void *Fl_Sys_Menu_Bar::doMenuOrItemOperation(Fl_Sys_Menu_Bar::menuOrItemOperation operation, ...) -/* these operations apply to menus, submenus, or menu items - */ -{ - NSAutoreleasePool *localPool; - localPool = [[NSAutoreleasePool alloc] init]; - NSMenu *menu; - NSMenuItem *item; - int value; - void *pter; - void *retval = NULL; - va_list ap; - va_start(ap, operation); - - if (operation == Fl_Sys_Menu_Bar::itemAtIndex) { // arguments: NSMenu*, int. Returns the item - menu = va_arg(ap, NSMenu*); - value = va_arg(ap, int); - retval = (void *)[menu itemAtIndex:value]; - } - else if (operation == Fl_Sys_Menu_Bar::setKeyEquivalent) { // arguments: NSMenuItem*, int - item = va_arg(ap, NSMenuItem*); - value = va_arg(ap, int); - char key = value; - NSString *equiv = [[NSString alloc] initWithBytes:&key length:1 encoding:NSASCIIStringEncoding]; - [item setKeyEquivalent:equiv]; - [equiv release]; - } - else if (operation == Fl_Sys_Menu_Bar::setKeyEquivalentModifierMask) { // arguments: NSMenuItem*, int - item = va_arg(ap, NSMenuItem*); - value = va_arg(ap, int); - NSUInteger macMod = 0; - if ( value & FL_META ) macMod = NSCommandKeyMask; - if ( value & FL_SHIFT || isupper(value) ) macMod |= NSShiftKeyMask; - if ( value & FL_ALT ) macMod |= NSAlternateKeyMask; - if ( value & FL_CTRL ) macMod |= NSControlKeyMask; - [item setKeyEquivalentModifierMask:macMod]; - } - else if (operation == Fl_Sys_Menu_Bar::setState) { // arguments: NSMenuItem*, int - item = va_arg(ap, NSMenuItem*); - value = va_arg(ap, int); - [item setState:(value ? NSOnState : NSOffState)]; - } - else if (operation == Fl_Sys_Menu_Bar::initWithTitle) { // arguments: const char*title. Returns the newly created menu - // creates a new (sub)menu - char *ts = remove_ampersand(va_arg(ap, char *)); - CFStringRef title = CFStringCreateWithCString(NULL, ts, kCFStringEncodingUTF8); - free(ts); - NSMenu *menu = [[NSMenu alloc] initWithTitle:(NSString*)title]; - CFRelease(title); - [menu setAutoenablesItems:NO]; - retval = (void *)menu; - } - else if (operation == Fl_Sys_Menu_Bar::numberOfItems) { // arguments: NSMenu *menu, int *pcount - // upon return, *pcount is set to menu's item count - menu = va_arg(ap, NSMenu*); - pter = va_arg(ap, void *); - *(int*)pter = [menu numberOfItems]; - } - else if (operation == Fl_Sys_Menu_Bar::setSubmenu) { // arguments: NSMenuItem *item, NSMenu *menu - // sets 'menu' as submenu attached to 'item' - item = va_arg(ap, NSMenuItem*); - menu = va_arg(ap, NSMenu*); - [item setSubmenu:menu]; - [menu release]; - } - else if (operation == Fl_Sys_Menu_Bar::setEnabled) { // arguments: NSMenuItem*, int - item = va_arg(ap, NSMenuItem*); - value = va_arg(ap, int); - [item setEnabled:(value ? YES : NO)]; - } - else if (operation == Fl_Sys_Menu_Bar::addSeparatorItem) { // arguments: NSMenu* - menu = va_arg(ap, NSMenu*); - [menu addItem:[NSMenuItem separatorItem]]; - } - else if (operation == Fl_Sys_Menu_Bar::setTitle) { // arguments: NSMenuItem*, const char * - item = va_arg(ap, NSMenuItem*); - char *ts = remove_ampersand(va_arg(ap, char *)); - CFStringRef title = CFStringCreateWithCString(NULL, ts, kCFStringEncodingUTF8); - free(ts); - [item setTitle:(NSString*)title]; - CFRelease(title); - } - else if (operation == Fl_Sys_Menu_Bar::removeItem) { // arguments: NSMenu*, int - menu = va_arg(ap, NSMenu*); - value = va_arg(ap, int); - [menu removeItem:[menu itemAtIndex:value]]; - } - else if (operation == Fl_Sys_Menu_Bar::addNewItem) { // arguments: NSMenu *menu, Fl_Menu_Item* mitem, int *prank - // creates a new menu item at the end of 'menu' - // attaches the item of fl_sys_menu_bar to it - // upon return, puts the rank (counted in NSMenu) of the new item in *prank unless prank is NULL - menu = va_arg(ap, NSMenu*); - Fl_Menu_Item *mitem = va_arg(ap, Fl_Menu_Item *); - int *prank = va_arg(ap, int*); - char *name = remove_ampersand(mitem->label()); - CFStringRef cfname = CFStringCreateWithCString(NULL, name, kCFStringEncodingUTF8); - free(name); - FLMenuItem *item = [[FLMenuItem alloc] initWithTitle:(NSString*)cfname - action:@selector(doCallback:) - keyEquivalent:@""]; - NSData *pointer = [NSData dataWithBytes:&mitem length:sizeof(Fl_Menu_Item*)]; - [item setRepresentedObject:pointer]; - [menu addItem:item]; - CFRelease(cfname); - [item setTarget:item]; - if (prank != NULL) *prank = [menu indexOfItem:item]; - [item release]; - } - va_end(ap); - [localPool release]; - return retval; -} void Fl_X::set_key_window() { @@ -3215,7 +3699,7 @@ static NSImage *imageFromText(const char *text, int *pwidth, int *pheight) fl_font(FL_HELVETICA, 10); p = text; int nl = 0; - while((q=strchr(p, '\n')) != NULL) { + while(nl < 100 && (q=strchr(p, '\n')) != NULL) { nl++; w2 = int(fl_width(p, q - p)); if (w2 > width) width = w2; @@ -3256,14 +3740,30 @@ static NSImage *imageFromText(const char *text, int *pwidth, int *pheight) static NSImage *defaultDragImage(int *pwidth, int *pheight) { - const int width = 16, height = 16; + const int version_threshold = 100700; + int width, height; + if (fl_mac_os_version >= version_threshold) { + width = 50; height = 40; + } + else { + width = 16; height = 16; + } Fl_Offscreen off = Fl_Quartz_Graphics_Driver::create_offscreen_with_alpha(width, height); fl_begin_offscreen(off); - CGContextSetRGBFillColor( (CGContextRef)off, 0,0,0,0); - fl_rectf(0,0,width,height); - CGContextSetRGBStrokeColor( (CGContextRef)off, 0,0,0,0.6); - fl_rect(0,0,width,height); - fl_rect(2,2,width-4,height-4); + if (fl_mac_os_version >= version_threshold) { + fl_font(FL_HELVETICA, 20); + fl_color(FL_BLACK); + char str[4]; + int l = fl_utf8encode(0x1F69A, str); // the "Delivery truck" Unicode character from "Apple Color Emoji" font + fl_draw(str, l, 1, 16); + } + else { // draw two squares + CGContextSetRGBFillColor( (CGContextRef)off, 0,0,0,0); + fl_rectf(0,0,width,height); + CGContextSetRGBStrokeColor( (CGContextRef)off, 0,0,0,0.6); + fl_rect(0,0,width,height); + fl_rect(2,2,width-4,height-4); + } fl_end_offscreen(); NSImage* image = CGBitmapContextToNSImage( (CGContextRef)off ); fl_delete_offscreen( off ); @@ -3279,16 +3779,11 @@ int Fl::dnd(void) NSAutoreleasePool *localPool; localPool = [[NSAutoreleasePool alloc] init]; NSPasteboard *mypasteboard = [NSPasteboard pasteboardWithName:NSDragPboard]; - [mypasteboard declareTypes:[NSArray arrayWithObjects:@"public.utf8-plain-text", nil] owner:nil]; - [mypasteboard setData:(NSData*)text forType:@"public.utf8-plain-text"]; + [mypasteboard declareTypes:[NSArray arrayWithObject:utf8_format] owner:nil]; + [mypasteboard setData:(NSData*)text forType:utf8_format]; CFRelease(text); Fl_Widget *w = Fl::pushed(); - Fl_Window *win = w->window(); - if (win == NULL) { - win = (Fl_Window*)w; - } else { - while(win->window()) win = win->window(); - } + Fl_Window *win = w->top_window(); NSView *myview = [Fl_X::i(win)->xid contentView]; NSEvent *theEvent = [NSApp currentEvent]; @@ -3319,20 +3814,29 @@ int Fl::dnd(void) } static NSBitmapImageRep* rect_to_NSBitmapImageRep(Fl_Window *win, int x, int y, int w, int h) -// release the returned value after use +// the returned value is autoreleased { + NSRect rect; + NSView *winview = nil; while (win->window()) { x += win->x(); y += win->y(); win = win->window(); } - CGFloat epsilon = 0; - if (fl_mac_os_version >= 100600) epsilon = 0.5; // STR #2887 - // The epsilon offset is absolutely necessary under 10.6. Without it, the top pixel row and - // left pixel column are not read, and bitmap is read shifted by one pixel in both directions. - // Under 10.5, we want no offset. - NSRect rect = NSMakeRect(x - epsilon, y - epsilon, w, h); - return [[NSBitmapImageRep alloc] initWithFocusedViewRect:rect]; + if ( through_drawRect ) { + CGFloat epsilon = 0; + if (fl_mac_os_version >= 100600) epsilon = 0.5; // STR #2887 + rect = NSMakeRect(x - epsilon, y - epsilon, w, h); + } + else { + rect = NSMakeRect(x, win->h()-(y+h), w, h); + // lock focus to win's view + winview = [fl_xid(win) contentView]; + [winview lockFocus]; + } + NSBitmapImageRep *bitmap = [[[NSBitmapImageRep alloc] initWithFocusedViewRect:rect] autorelease]; + if ( !through_drawRect ) [winview unlockFocus]; + return bitmap; } unsigned char *Fl_X::bitmap_from_window_rect(Fl_Window *win, int x, int y, int w, int h, int *bytesPerPixel) @@ -3344,24 +3848,38 @@ unsigned char *Fl_X::bitmap_from_window_rect(Fl_Window *win, int x, int y, int w */ { NSBitmapImageRep *bitmap = rect_to_NSBitmapImageRep(win, x, y, w, h); + if (bitmap == nil) return NULL; *bytesPerPixel = [bitmap bitsPerPixel]/8; int bpp = (int)[bitmap bytesPerPlane]; int bpr = (int)[bitmap bytesPerRow]; - int hh = bpp/bpr; // sometimes hh = h-1 for unclear reason - int ww = bpr/(*bytesPerPixel); // sometimes ww = w-1 - unsigned char *data = new unsigned char[w * h * *bytesPerPixel]; - if (w == ww) { - memcpy(data, [bitmap bitmapData], w * hh * *bytesPerPixel); - } else { - unsigned char *p = [bitmap bitmapData]; - unsigned char *q = data; - for(int i = 0;i < hh; i++) { - memcpy(q, p, *bytesPerPixel * ww); - p += bpr; - q += w * *bytesPerPixel; + int hh = bpp/bpr; // sometimes hh = h-1 for unclear reason, and hh = 2*h with retina + int ww = bpr/(*bytesPerPixel); // sometimes ww = w-1, and ww = 2*w with retina + unsigned char *data; + if (ww > w) { // with a retina display + Fl_RGB_Image *rgb = new Fl_RGB_Image([bitmap bitmapData], ww, hh, 4); + Fl_RGB_Scaling save_scaling = Fl_Image::RGB_scaling(); + Fl_Image::RGB_scaling(FL_RGB_SCALING_BILINEAR); + Fl_RGB_Image *rgb2 = (Fl_RGB_Image*)rgb->copy(w, h); + Fl_Image::RGB_scaling(save_scaling); + delete rgb; + rgb2->alloc_array = 0; + data = (uchar*)rgb2->array; + delete rgb2; + } + else { + data = new unsigned char[w * h * *bytesPerPixel]; + if (w == ww) { + memcpy(data, [bitmap bitmapData], w * hh * *bytesPerPixel); + } else { + unsigned char *p = [bitmap bitmapData]; + unsigned char *q = data; + for(int i = 0;i < hh; i++) { + memcpy(q, p, *bytesPerPixel * ww); + p += bpr; + q += w * *bytesPerPixel; } + } } - [bitmap release]; return data; } @@ -3376,13 +3894,13 @@ CGImageRef Fl_X::CGImage_from_window_rect(Fl_Window *win, int x, int y, int w, i CGImageRef img; if (fl_mac_os_version >= 100500) { NSBitmapImageRep *bitmap = rect_to_NSBitmapImageRep(win, x, y, w, h); - img = [bitmap CGImage]; // requires Mac OS 10.5 + img = (CGImageRef)[bitmap performSelector:@selector(CGImage)]; // requires Mac OS 10.5 CGImageRetain(img); - [bitmap release]; } else { int bpp; unsigned char *bitmap = bitmap_from_window_rect(win, x, y, w, h, &bpp); + if (!bitmap) return NULL; CGColorSpaceRef lut = CGColorSpaceCreateDeviceRGB(); CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, bitmap, w*h*bpp, imgProviderReleaseData); img = CGImageCreate(w, h, 8, 8*bpp, w*bpp, lut, @@ -3401,7 +3919,7 @@ WindowRef Fl_X::window_ref() // so a CGRect matches exactly what is denoted x,y,w,h for clipping purposes CGRect fl_cgrectmake_cocoa(int x, int y, int w, int h) { - return CGRectMake(x, y, w > 0 ? w - 0.9 : 0, h > 0 ? h - 0.9 : 0); + return CGRectMake(x - 0.5, y - 0.5, w, h); } Window fl_xid(const Fl_Window* w) @@ -3428,30 +3946,110 @@ int Fl_Window::decorated_h() void Fl_Paged_Device::print_window(Fl_Window *win, int x_offset, int y_offset) { + NSButton *close = nil, *miniaturize = nil, *zoom = nil; if (!win->shown() || win->parent() || !win->border() || !win->visible()) { this->print_widget(win, x_offset, y_offset); return; } - int bx, by, bt; + int bx, by, bt, bpp; get_window_frame_sizes(bx, by, bt); Fl_Display_Device::display_device()->set_current(); // send win to front and make it current + const char *title = win->label(); + win->label(""); // temporarily set a void window title win->show(); + if (fl_mac_os_version >= 101000) { + // if linked for OS 10.10, capture of title bar does not capture the title bar buttons + // so we draw them in FLTK + NSWindow *xid = fl_xid(win); + close = [xid standardWindowButton:NSWindowCloseButton]; // 10.2 + miniaturize = [xid standardWindowButton:NSWindowMiniaturizeButton]; + zoom = [xid standardWindowButton:NSWindowZoomButton]; + [close setHidden:YES]; // 10.3 + [miniaturize setHidden:YES]; + [zoom setHidden:YES]; + } fl_gc = NULL; Fl::check(); - win->make_current(); + BOOL to_quartz = dynamic_cast<Fl_Printer*>(this) != NULL; + // capture the window title bar with no title + CGImageRef img = NULL; + unsigned char *bitmap = NULL; + if (to_quartz) + img = Fl_X::CGImage_from_window_rect(win, 0, -bt, win->w(), bt); + else + bitmap = Fl_X::bitmap_from_window_rect(win, 0, -bt, win->w(), bt, &bpp); + win->label(title); // put back the window title this->set_current(); // back to the Fl_Paged_Device - // capture the window title bar - CGImageRef img = Fl_X::CGImage_from_window_rect(win, 0, -bt, win->w(), bt); - // and print it - CGRect rect = { { x_offset, y_offset }, { win->w(), bt } }; - Fl_X::q_begin_image(rect, 0, 0, win->w(), bt); - CGContextDrawImage(fl_gc, rect, img); - Fl_X::q_end_image(); - CFRelease(img); + if (img && to_quartz) { // print the title bar + CGRect rect = { { x_offset, y_offset }, { win->w(), bt } }; + Fl_X::q_begin_image(rect, 0, 0, win->w(), bt); + CGContextDrawImage(fl_gc, rect, img); + Fl_X::q_end_image(); + CFRelease(img); + } + else if(!to_quartz) { + Fl_RGB_Image *rgb = new Fl_RGB_Image(bitmap, win->w(), bt, bpp); + rgb->draw(x_offset, y_offset); + delete rgb; + delete[] bitmap; + } + if (fl_mac_os_version >= 101000) { // print the title bar buttons + Fl_Color inactive = fl_rgb_color((uchar)0xCE, (uchar)0xCE, (uchar)0xCE); // inactive button color + Fl_Color redish, yellowish, greenish; + if ([[NSUserDefaults standardUserDefaults] integerForKey:@"AppleAquaColorVariant"] == 6) { // graphite appearance + redish = yellowish = greenish = fl_rgb_color((uchar)0x8C, (uchar)0x8C, (uchar)0x8C); + } + else { + redish = fl_rgb_color((uchar)0xFF, (uchar)0x63, (uchar)0x5A); + yellowish = fl_rgb_color((uchar)0xFF, (uchar)0xC6, (uchar)0x42); + greenish = fl_rgb_color((uchar)0x29, (uchar)0xD6, (uchar)0x52); + } + + if (![close isEnabled]) fl_color(inactive); else fl_color(redish); + fl_pie(x_offset+8, y_offset+5, 12, 12, 0, 360); + if (![miniaturize isEnabled]) fl_color(inactive); else fl_color(yellowish); + fl_pie(x_offset+28, y_offset+5, 12, 12, 0, 360); + if (![zoom isEnabled]) fl_color(inactive); else fl_color(greenish); + fl_pie(x_offset+48, y_offset+5, 12, 12, 0, 360); + + [close setHidden:NO]; // 10.3 + [miniaturize setHidden:NO]; + [zoom setHidden:NO]; + } + if (title) { // print the window title + const int skip = 65; // approx width of the zone of the 3 window control buttons +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 + if (fl_mac_os_version >= 100400 && to_quartz) { // use Cocoa string drawing with exact title bar font + // the exact font is LucidaGrande 13 pts (and HelveticaNeueDeskInterface-Regular with 10.10) + NSGraphicsContext *current = [NSGraphicsContext currentContext]; + [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithGraphicsPort:fl_gc flipped:YES]];//10.4 + NSDictionary *attr = [NSDictionary dictionaryWithObject:[NSFont titleBarFontOfSize:0] + forKey:NSFontAttributeName]; + NSString *title_s = [fl_xid(win) title]; + NSSize size = [title_s sizeWithAttributes:attr]; + int x = x_offset + win->w()/2 - size.width/2; + if (x < x_offset+skip) x = x_offset+skip; + NSRect r = {{x, y_offset+bt/2+4}, {win->w() - skip, bt}}; + [[NSGraphicsContext currentContext] setShouldAntialias:YES]; + [title_s drawWithRect:r options:(NSStringDrawingOptions)0 attributes:attr]; // 10.4 + [[NSGraphicsContext currentContext] setShouldAntialias:NO]; + [NSGraphicsContext setCurrentContext:current]; + } + else +#endif + { + fl_font(FL_HELVETICA, 14); + fl_color(FL_BLACK); + int x = x_offset + win->w()/2 - fl_width(title)/2; + if (x < x_offset+skip) x = x_offset+skip; + fl_push_clip(x_offset, y_offset, win->w(), bt); + fl_draw(title, x, y_offset+bt/2+4); + fl_pop_clip(); + } + } this->print_widget(win, x_offset, y_offset + bt); // print the window inner part } -#include <dlfcn.h> /* Returns the address of a Carbon function after dynamically loading the Carbon library if needed. Supports old Mac OS X versions that may use a couple of Carbon calls: @@ -3476,9 +4074,20 @@ void *Fl_X::get_carbon_function(const char *function_name) { static int calc_mac_os_version() { int M, m, b = 0; NSAutoreleasePool *localPool = [[NSAutoreleasePool alloc] init]; - NSDictionary * sv = [NSDictionary dictionaryWithContentsOfFile:@"/System/Library/CoreServices/SystemVersion.plist"]; - const char *s = [[sv objectForKey:@"ProductVersion"] UTF8String]; - sscanf(s, "%d.%d.%d", &M, &m, &b); +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_10 + if ([NSProcessInfo instancesRespondToSelector:@selector(operatingSystemVersion)]) { + NSOperatingSystemVersion version = [[NSProcessInfo processInfo] operatingSystemVersion]; + M = version.majorVersion; + m = version.minorVersion; + b = version.patchVersion; + } + else +#endif + { + NSDictionary * sv = [NSDictionary dictionaryWithContentsOfFile:@"/System/Library/CoreServices/SystemVersion.plist"]; + const char *s = [[sv objectForKey:@"ProductVersion"] UTF8String]; + sscanf(s, "%d.%d.%d", &M, &m, &b); + } [localPool release]; return M*10000 + m*100 + b; } @@ -3486,5 +4095,5 @@ static int calc_mac_os_version() { #endif // __APPLE__ // -// End of "$Id: Fl_cocoa.mm 9734 2012-11-30 18:20:36Z manolo $". +// End of "$Id: Fl_cocoa.mm 10427 2014-11-02 21:06:07Z manolo $". // diff --git a/src/Fl_compose.cxx b/src/Fl_compose.cxx index 03dd216..0cd2a57 100644 --- a/src/Fl_compose.cxx +++ b/src/Fl_compose.cxx @@ -1,5 +1,5 @@ // -// "$Id: Fl_compose.cxx 8864 2011-07-19 04:49:30Z greg.ercolano $" +// "$Id: Fl_compose.cxx 9966 2013-09-06 09:03:22Z manolo $" // // Character compose processing for the Fast Light Tool Kit (FLTK). // @@ -16,11 +16,20 @@ // http://www.fltk.org/str.php // +/** +\file Fl_compose.cxx +Utility functions to support text input. +*/ + + #include <FL/Fl.H> #include <FL/x.H> #ifndef FL_DOXYGEN int Fl::compose_state = 0; +#ifdef __APPLE__ +int Fl_X::next_marked_length = 0; +#endif #endif #if !defined(WIN32) && !defined(__APPLE__) @@ -32,7 +41,7 @@ extern XIC fl_xim_ic; <p>If <i>true</i> is returned, then it has modified the Fl::event_text() and Fl::event_length() to a set of <i>bytes</i> to - insert (it may be of zero length!). In will also set the "del" + insert (it may be of zero length!). It will also set the "del" parameter to the number of <i>bytes</i> to the left of the cursor to delete, this is used to delete the results of the previous call to Fl::compose(). @@ -41,38 +50,88 @@ extern XIC fl_xim_ic; keys, and del is set to zero. You could insert the text anyways, if you don't know what else to do. + <p>On the Mac OS platform, text input can involve marked text, that is, + temporary text replaced by other text during the input process. This occurs, + e.g., when using dead keys or when entering CJK characters. + Text editing widgets should preferentially signal + marked text, usually underlining it. Widgets can use + <tt>int Fl::compose_state</tt> <i>after</i> having called Fl::compose(int&) + to obtain the length in bytes of marked text that always finishes at the + current insertion point. It's the widget's task to underline marked text. + Widgets should also call <tt>void Fl::reset_marked_text()</tt> when processing FL_UNFOCUS + events. Optionally, widgets can also call + <tt>void Fl::insertion_point_location(int x, int y, int height)</tt> to indicate the window + coordinates of the bottom of the current insertion point and the line height. + This way, auxiliary windows that help choosing among alternative characters + appear just below the insertion point. If widgets don't do that, + auxiliary windows appear at the widget's bottom. The + Fl_Input and Fl_Text_Editor widgets underline marked text. + If none of this is done by a user-defined text editing widget, + text input will work, but will not signal to the user what text is marked. + Finally, text editing widgets should call <tt>set_flag(MAC_USE_ACCENTS_MENU);</tt> + in their constructor if they want to use the feature introduced with Mac OS 10.7 "Lion" + where pressing and holding a key on the keyboard opens an accented-character menu window. + <p>Though the current implementation returns immediately, future versions may take quite awhile, as they may pop up a window or do other user-interface things to allow characters to be selected. */ int Fl::compose(int& del) { - // character composition is now handled by the OS - del = 0; + int condition; #if defined(__APPLE__) - // this stuff is to be treated as a function key - if(Fl::e_length == 0 || Fl::e_keysym == FL_Enter || Fl::e_keysym == FL_KP_Enter || - Fl::e_keysym == FL_Tab || Fl::e_keysym == FL_Escape || Fl::e_state&(FL_META | FL_CTRL) ) { - return 0; - } -#elif defined(WIN32) - unsigned char ascii = (unsigned)e_text[0]; - if ((e_state & (FL_ALT | FL_META)) && !(ascii & 128)) return 0; + int has_text_key = Fl::compose_state || Fl::e_keysym <= '~' || Fl::e_keysym == FL_Iso_Key || + (Fl::e_keysym >= FL_KP && Fl::e_keysym <= FL_KP_Last && Fl::e_keysym != FL_KP_Enter); + condition = Fl::e_state&(FL_META | FL_CTRL) || + (Fl::e_keysym >= FL_Shift_L && Fl::e_keysym <= FL_Alt_R) || // called from flagsChanged + !has_text_key ; #else - unsigned char ascii = (unsigned)e_text[0]; - if ((e_state & (FL_ALT | FL_META | FL_CTRL)) && !(ascii & 128)) return 0; -#endif - if(Fl::compose_state) { - del = Fl::compose_state; - Fl::compose_state = 0; -#ifndef __APPLE__ - } else { - // Only insert non-control characters: - if (! (ascii & ~31 && ascii!=127)) { return 0; } +unsigned char ascii = (unsigned char)e_text[0]; +#if defined(WIN32) + condition = (e_state & (FL_ALT | FL_META)) && !(ascii & 128) ; +#else + condition = (e_state & (FL_ALT | FL_META | FL_CTRL)) && !(ascii & 128) ; +#endif // WIN32 +#endif // __APPLE__ + if (condition) { del = 0; return 0;} // this stuff is to be treated as a function key + del = Fl::compose_state; +#ifdef __APPLE__ + Fl::compose_state = Fl_X::next_marked_length; +#else + Fl::compose_state = 0; +// Only insert non-control characters: + if ( (!Fl::compose_state) && ! (ascii & ~31 && ascii!=127)) { return 0; } #endif - } return 1; } +#ifdef __APPLE__ +static int insertion_point_x = 0; +static int insertion_point_y = 0; +static int insertion_point_height = 0; +static bool insertion_point_location_is_valid = false; + +void Fl::reset_marked_text() { + Fl::compose_state = 0; + Fl_X::next_marked_length = 0; + insertion_point_location_is_valid = false; + } +int Fl_X::insertion_point_location(int *px, int *py, int *pheight) +// return true if the current coordinates of the insertion point are available +{ + if ( ! insertion_point_location_is_valid ) return false; + *px = insertion_point_x; + *py = insertion_point_y; + *pheight = insertion_point_height; + return true; +} +void Fl::insertion_point_location(int x, int y, int height) { + insertion_point_location_is_valid = true; + insertion_point_x = x; + insertion_point_y = y; + insertion_point_height = height; +} +#endif // __APPLE__ + /** If the user moves the cursor, be sure to call Fl::compose_reset(). The next call to Fl::compose() will start out in an initial state. In @@ -88,6 +147,6 @@ void Fl::compose_reset() } // -// End of "$Id: Fl_compose.cxx 8864 2011-07-19 04:49:30Z greg.ercolano $" +// End of "$Id: Fl_compose.cxx 9966 2013-09-06 09:03:22Z manolo $" // diff --git a/src/Fl_get_key_mac.cxx b/src/Fl_get_key_mac.cxx index 01c2c83..a59df4a 100644 --- a/src/Fl_get_key_mac.cxx +++ b/src/Fl_get_key_mac.cxx @@ -1,5 +1,5 @@ // -// "$Id: Fl_get_key_mac.cxx 9303 2012-03-26 16:54:54Z manolo $" +// "$Id: Fl_get_key_mac.cxx 9952 2013-07-23 16:02:44Z manolo $" // // MacOS keyboard state routines for the Fast Light Tool Kit (FLTK). // @@ -164,6 +164,15 @@ enum { kVK_ISO_Section = 0x0A }; +/* JIS keyboards only*/ +enum { + kVK_JIS_Yen = 0x5D, + kVK_JIS_Underscore = 0x5E, + kVK_JIS_KeypadComma = 0x5F, + kVK_JIS_Eisu = 0x66, + kVK_JIS_Kana = 0x68 +}; + #endif // convert an FLTK (X) keysym to a MacOS symbol: @@ -181,12 +190,16 @@ static const struct {unsigned short vk, fltk;} vktab[] = { { kVK_ANSI_U, 'U' }, { kVK_ANSI_V, 'V' }, { kVK_ANSI_W, 'W' }, { kVK_ANSI_X, 'X' }, { kVK_ANSI_Y, 'Y' }, { kVK_ANSI_Z, 'Z' }, { kVK_ANSI_LeftBracket, '[' }, { kVK_ANSI_Backslash, '\\' }, { kVK_ANSI_RightBracket, ']' }, { kVK_ANSI_Grave, '`' }, + { kVK_VolumeDown, FL_Volume_Down}, { kVK_Mute, FL_Volume_Mute}, { kVK_VolumeUp, FL_Volume_Up}, { kVK_Delete, FL_BackSpace }, { kVK_Tab, FL_Tab }, { kVK_ISO_Section, FL_Iso_Key }, { kVK_Return, FL_Enter }, /*{ 0x7F, FL_Pause }, - { 0x7F, FL_Scroll_Lock },*/ { kVK_Escape, FL_Escape }, { kVK_Home, FL_Home }, { kVK_LeftArrow, FL_Left }, + { 0x7F, FL_Scroll_Lock },*/ { kVK_Escape, FL_Escape }, + { kVK_JIS_Kana, FL_Kana}, { kVK_JIS_Eisu, FL_Eisu}, { kVK_JIS_Yen, FL_Yen}, { kVK_JIS_Underscore, FL_JIS_Underscore}, + { kVK_Home, FL_Home }, { kVK_LeftArrow, FL_Left }, { kVK_UpArrow, FL_Up }, { kVK_RightArrow, FL_Right }, { kVK_DownArrow, FL_Down }, { kVK_PageUp, FL_Page_Up }, { kVK_PageDown, FL_Page_Down }, { kVK_End, FL_End }, /*{ 0x7F, FL_Print }, { 0x7F, FL_Insert },*/ { 0x6e, FL_Menu }, { kVK_Help, FL_Help }, { kVK_ANSI_KeypadClear, FL_Num_Lock }, { kVK_ANSI_KeypadEnter, FL_KP_Enter }, { kVK_ANSI_KeypadMultiply, FL_KP+'*' }, { kVK_ANSI_KeypadPlus, FL_KP+'+'}, + { kVK_JIS_KeypadComma, FL_KP+',' }, { kVK_ANSI_KeypadMinus, FL_KP+'-' }, { kVK_ANSI_KeypadDecimal, FL_KP+'.' }, { kVK_ANSI_KeypadDivide, FL_KP+'/' }, { kVK_ANSI_Keypad0, FL_KP+'0' }, { kVK_ANSI_Keypad1, FL_KP+'1' }, { kVK_ANSI_Keypad2, FL_KP+'2' }, { kVK_ANSI_Keypad3, FL_KP+'3' }, { kVK_ANSI_Keypad4, FL_KP+'4' }, { kVK_ANSI_Keypad5, FL_KP+'5' }, { kVK_ANSI_Keypad6, FL_KP+'6' }, { kVK_ANSI_Keypad7, FL_KP+'7' }, @@ -195,6 +208,7 @@ static const struct {unsigned short vk, fltk;} vktab[] = { { kVK_F5, FL_F+5 }, { kVK_F6, FL_F+6 }, { kVK_F7, FL_F+7 }, { kVK_F8, FL_F+8 }, { kVK_F9, FL_F+9 }, { kVK_F10, FL_F+10 }, { kVK_F11, FL_F+11 }, { kVK_F12, FL_F+12 }, { kVK_F13, FL_F+13 }, { kVK_F14, FL_F+14 }, { kVK_F15, FL_F+15 }, { kVK_F16, FL_F+16 }, + { kVK_F17, FL_F+17 }, { kVK_F18, FL_F+18 }, { kVK_F19, FL_F+19 }, { kVK_F20, FL_F+20 }, { kVK_Shift, FL_Shift_L }, { kVK_RightShift, FL_Shift_R }, { kVK_Control, FL_Control_L }, { kVK_RightControl, FL_Control_R }, { kVK_CapsLock, FL_Caps_Lock }, { kVK_Command, FL_Meta_L }, { 0x36, FL_Meta_R }, { kVK_Option, FL_Alt_L }, { kVK_RightOption, FL_Alt_R }, { kVK_ForwardDelete, FL_Delete } @@ -219,7 +233,7 @@ static int fltk2mac(int fltk) { if (vktab[c].fltk == fltk) return vktab[c].vk; if (vktab[c].fltk < fltk) a = c+1; else b = c; } - return 127; + return vktab[a].vk; } //: returns true, if that key was pressed during the last event @@ -261,5 +275,5 @@ int Fl::get_key(int k) { } // -// End of "$Id: Fl_get_key_mac.cxx 9303 2012-03-26 16:54:54Z manolo $". +// End of "$Id: Fl_get_key_mac.cxx 9952 2013-07-23 16:02:44Z manolo $". // diff --git a/src/Fl_get_system_colors.cxx b/src/Fl_get_system_colors.cxx index fd64e54..b728b76 100644 --- a/src/Fl_get_system_colors.cxx +++ b/src/Fl_get_system_colors.cxx @@ -1,5 +1,5 @@ // -// "$Id: Fl_get_system_colors.cxx 9740 2012-12-09 17:45:24Z manolo $" +// "$Id: Fl_get_system_colors.cxx 10126 2014-04-19 14:55:15Z greg.ercolano $" // // System color support for the Fast Light Tool Kit (FLTK). // @@ -258,19 +258,28 @@ Fl_Image *Fl::scheme_bg_ = (Fl_Image *)0; // current background image for the static Fl_Pixmap tile(tile_xpm); /** - Gets or sets the current widget scheme. NULL will use - the scheme defined in the FLTK_SCHEME environment - variable or the scheme resource under X11. Otherwise, - any of the following schemes can be used: - - - "none" - This is the default look-n-feel which resembles old - Windows (95/98/Me/NT/2000) and old GTK/KDE - - - "plastic" - This scheme is inspired by the Aqua user interface - on Mac OS X - - - "gtk+" - This scheme is inspired by the Red Hat Bluecurve - theme + Sets the current widget scheme. NULL will use the scheme defined + in the FLTK_SCHEME environment variable or the scheme resource + under X11. Otherwise, any of the following schemes can be used: + + - "none" - This is the default look-n-feel which resembles old + Windows (95/98/Me/NT/2000) and old GTK/KDE + + - "base" - This is an alias for "none" + + - "plastic" - This scheme is inspired by the Aqua user interface + on Mac OS X + + - "gtk+" - This scheme is inspired by the Red Hat Bluecurve theme + + - "gleam" - This scheme is inspired by the Clearlooks Glossy scheme. + (Colin Jones and Edmanuel Torres). + + Uppercase scheme names are equivalent, but the stored scheme name will + always be lowercase and Fl::scheme() will return this lowercase name. + + If the resulting scheme name is not defined, the default scheme will + be used and Fl::scheme() will return NULL. */ int Fl::scheme(const char *s) { if (!s) { @@ -289,6 +298,7 @@ int Fl::scheme(const char *s) { if (!fl_ascii_strcasecmp(s, "none") || !fl_ascii_strcasecmp(s, "base") || !*s) s = 0; else if (!fl_ascii_strcasecmp(s, "gtk+")) s = strdup("gtk+"); else if (!fl_ascii_strcasecmp(s, "plastic")) s = strdup("plastic"); + else if (!fl_ascii_strcasecmp(s, "gleam")) s = strdup("gleam"); else s = 0; } if (scheme_) free((void*)scheme_); @@ -375,6 +385,27 @@ int Fl::reload_scheme() { // Use slightly thinner scrollbars... Fl::scrollbar_size(15); + } else if (scheme_ && !fl_ascii_strcasecmp(scheme_, "gleam")) { + // Use a GTK+ inspired look-n-feel... + if (scheme_bg_) { + delete scheme_bg_; + scheme_bg_ = (Fl_Image *)0; + } + + set_boxtype(FL_UP_FRAME, FL_GLEAM_UP_FRAME); + set_boxtype(FL_DOWN_FRAME, FL_GLEAM_DOWN_FRAME); + set_boxtype(FL_THIN_UP_FRAME, FL_GLEAM_UP_FRAME); + set_boxtype(FL_THIN_DOWN_FRAME, FL_GLEAM_DOWN_FRAME); + + set_boxtype(FL_UP_BOX, FL_GLEAM_UP_BOX); + set_boxtype(FL_DOWN_BOX, FL_GLEAM_DOWN_BOX); + set_boxtype(FL_THIN_UP_BOX, FL_GLEAM_THIN_UP_BOX); + set_boxtype(FL_THIN_DOWN_BOX, FL_GLEAM_THIN_DOWN_BOX); + set_boxtype(_FL_ROUND_UP_BOX, FL_GLEAM_ROUND_UP_BOX); + set_boxtype(_FL_ROUND_DOWN_BOX, FL_GLEAM_ROUND_DOWN_BOX); + + // Use slightly thinner scrollbars... + Fl::scrollbar_size(15); } else { // Use the standard FLTK look-n-feel... if (scheme_bg_) { @@ -411,5 +442,5 @@ int Fl::reload_scheme() { // -// End of "$Id: Fl_get_system_colors.cxx 9740 2012-12-09 17:45:24Z manolo $". +// End of "$Id: Fl_get_system_colors.cxx 10126 2014-04-19 14:55:15Z greg.ercolano $". // diff --git a/src/Fl_mac.cxx b/src/Fl_mac.cxx deleted file mode 100644 index 3fb4ffc..0000000 --- a/src/Fl_mac.cxx +++ /dev/null @@ -1,2861 +0,0 @@ -// -// "$Id: Fl_mac.cxx 8864 2011-07-19 04:49:30Z greg.ercolano $" -// -// MacOS specific code for the Fast Light Tool Kit (FLTK). -// -// Copyright 1998-2010 by Bill Spitzak and others. -// -// This library is free software. Distribution and use rights are outlined in -// the file "COPYING" which should have been included with this file. If this -// file is missing or damaged, see the license at: -// -// http://www.fltk.org/COPYING.php -// -// Please report all bugs and problems on the following page: -// -// http://www.fltk.org/str.php -// - -//// From the inner edge of a MetroWerks CodeWarrior CD: -// (without permission) -// -// "Three Compiles for 68Ks under the sky, -// Seven Compiles for PPCs in their fragments of code, -// Nine Compiles for Mortal Carbon doomed to die, -// One Compile for Mach-O Cocoa on its Mach-O throne, -// in the Land of MacOS X where the Drop-Shadows lie. -// -// One Compile to link them all, One Compile to merge them, -// One Compile to copy them all and in the bundle bind them, -// in the Land of MacOS X where the Drop-Shadows lie." - -// warning: the Apple Quartz version still uses some Quickdraw calls, -// mostly to get around the single active context in QD and -// to implement clipping. This should be changed into pure -// Quartz calls in the near future. - -// FIXME moving away from Carbon, I am replacing the Scrap manager calls with Pasteboard -// calls that support utf8 encoding. As soon as these function haven proven working -// the Scrap manager calls should be removed -#define USE_PASTEBOARD 1 - -// we don't need the following definition because we deliver only -// true mouse moves. On very slow systems however, this flag may -// still be useful. -#ifndef FL_DOXYGEN - -#define CONSOLIDATE_MOTION 0 -extern "C" { -#include <pthread.h> -} - -#include <config.h> -#include <FL/Fl.H> -#include <FL/x.H> -#include <FL/Fl_Window.H> -#include <FL/Fl_Tooltip.H> -#include <FL/Fl_Sys_Menu_Bar.H> -#include <stdio.h> -#include <stdlib.h> -#include "flstring.h" -#include <unistd.h> - -// #define DEBUG_SELECT // UNCOMMENT FOR SELECT()/THREAD DEBUGGING -#ifdef DEBUG_SELECT -#include <stdio.h> // testing -#define DEBUGMSG(msg) if ( msg ) fprintf(stderr, msg); -#define DEBUGPERRORMSG(msg) if ( msg ) perror(msg) -#define DEBUGTEXT(txt) txt -#else -#define DEBUGMSG(msg) -#define DEBUGPERRORMSG(msg) -#define DEBUGTEXT(txt) NULL -#endif /*DEBUG_SELECT*/ - -// external functions -extern Fl_Window* fl_find(Window); -extern void fl_fix_focus(); - -// forward definition of functions in this file -static void handleUpdateEvent( WindowPtr xid ); -//+ int fl_handle(const EventRecord &event); -static int FSSpec2UnixPath( FSSpec *fs, char *dst ); -// converting cr lf converter function -static void convert_crlf(char * string, size_t len); - -// public variables -int fl_screen; -CGContextRef fl_gc = 0; -Handle fl_system_menu; -Fl_Sys_Menu_Bar *fl_sys_menu_bar = 0; -CursHandle fl_default_cursor; -WindowRef fl_capture = 0; // we need this to compensate for a missing(?) mouse capture -ulong fl_event_time; // the last timestamp from an x event -char fl_key_vector[32]; // used by Fl::get_key() -bool fl_show_iconic; // true if called from iconize() - shows the next created window in collapsed state -int fl_disable_transient_for; // secret method of removing TRANSIENT_FOR -const Fl_Window* fl_modal_for; // parent of modal() window -Fl_Region fl_window_region = 0; -Window fl_window; -Fl_Window *Fl_Window::current_; -EventRef fl_os_event; // last (mouse) event - -// forward declarations of variables in this file -static int got_events = 0; -static Fl_Window* resize_from_system; -static CursPtr default_cursor_ptr; -static Cursor default_cursor; -static WindowRef fl_os_capture = 0; // the dispatch handler will redirect mose move and drag events to these windows - -#if CONSOLIDATE_MOTION -static Fl_Window* send_motion; -extern Fl_Window* fl_xmousewin; -#endif - -enum { kEventClassFLTK = 'fltk' }; -enum { kEventFLTKBreakLoop = 1, kEventFLTKDataReady }; - -/* fltk-utf8 placekeepers */ -void fl_reset_spot() -{ -} - -void fl_set_spot(int font, int size, int X, int Y, int W, int H, Fl_Window *win) -{ -} - -void fl_set_status(int x, int y, int w, int h) -{ -} - -/** -* Mac keyboard lookup table - */ -static unsigned short macKeyLookUp[128] = -{ - 'a', 's', 'd', 'f', 'h', 'g', 'z', 'x', - 'c', 'v', '^', 'b', 'q', 'w', 'e', 'r', - - 'y', 't', '1', '2', '3', '4', '6', '5', - '=', '9', '7', '-', '8', '0', ']', 'o', - - 'u', '[', 'i', 'p', FL_Enter, 'l', 'j', '\'', - 'k', ';', '\\', ',', '/', 'n', 'm', '.', - - FL_Tab, ' ', '`', FL_BackSpace, - FL_KP_Enter, FL_Escape, 0, 0/*FL_Meta_L*/, - 0/*FL_Shift_L*/, 0/*FL_Caps_Lock*/, 0/*FL_Alt_L*/, 0/*FL_Control_L*/, - 0/*FL_Shift_R*/, 0/*FL_Alt_R*/, 0/*FL_Control_R*/, 0, - - 0, FL_KP+'.', FL_Right, FL_KP+'*', 0, FL_KP+'+', FL_Left, FL_Delete, - FL_Down, 0, 0, FL_KP+'/', FL_KP_Enter, FL_Up, FL_KP+'-', 0, - - 0, FL_KP+'=', FL_KP+'0', FL_KP+'1', FL_KP+'2', FL_KP+'3', FL_KP+'4', FL_KP+'5', - FL_KP+'6', FL_KP+'7', 0, FL_KP+'8', FL_KP+'9', 0, 0, 0, - - FL_F+5, FL_F+6, FL_F+7, FL_F+3, FL_F+8, FL_F+9, 0, FL_F+11, - 0, 0/*FL_F+13*/, FL_Print, FL_Scroll_Lock, 0, FL_F+10, FL_Menu, FL_F+12, - - 0, FL_Pause, FL_Help, FL_Home, FL_Page_Up, FL_Delete, FL_F+4, FL_End, - FL_F+2, FL_Page_Down, FL_F+1, FL_Left, FL_Right, FL_Down, FL_Up, 0/*FL_Power*/, -}; - -/** - * convert the current mouse chord into the FLTK modifier state - */ -static unsigned int mods_to_e_state( UInt32 mods ) -{ - long state = 0; - if ( mods & kEventKeyModifierNumLockMask ) state |= FL_NUM_LOCK; - if ( mods & cmdKey ) state |= FL_META; - if ( mods & (optionKey|rightOptionKey) ) state |= FL_ALT; - if ( mods & (controlKey|rightControlKey) ) state |= FL_CTRL; - if ( mods & (shiftKey|rightShiftKey) ) state |= FL_SHIFT; - if ( mods & alphaLock ) state |= FL_CAPS_LOCK; - unsigned int ret = ( Fl::e_state & 0xff000000 ) | state; - Fl::e_state = ret; - //printf( "State 0x%08x (%04x)\n", Fl::e_state, mods ); - return ret; -} - - -/** - * convert the current mouse chord into the FLTK keysym - */ -static void mods_to_e_keysym( UInt32 mods ) -{ - if ( mods & cmdKey ) Fl::e_keysym = FL_Meta_L; - else if ( mods & kEventKeyModifierNumLockMask ) Fl::e_keysym = FL_Num_Lock; - else if ( mods & optionKey ) Fl::e_keysym = FL_Alt_L; - else if ( mods & rightOptionKey ) Fl::e_keysym = FL_Alt_R; - else if ( mods & controlKey ) Fl::e_keysym = FL_Control_L; - else if ( mods & rightControlKey ) Fl::e_keysym = FL_Control_R; - else if ( mods & shiftKey ) Fl::e_keysym = FL_Shift_L; - else if ( mods & rightShiftKey ) Fl::e_keysym = FL_Shift_R; - else if ( mods & alphaLock ) Fl::e_keysym = FL_Caps_Lock; - else Fl::e_keysym = 0; - //printf( "to sym 0x%08x (%04x)\n", Fl::e_keysym, mods ); -} -// these pointers are set by the Fl::lock() function: -static void nothing() {} -void (*fl_lock_function)() = nothing; -void (*fl_unlock_function)() = nothing; - -// -// Select interface -- how it's implemented: -// When the user app configures one or more file descriptors to monitor -// with Fl::add_fd(), we start a separate thread to select() the data, -// sending a custom OSX 'FLTK data ready event' to the parent thread's -// RunApplicationLoop(), so that it triggers the data ready callbacks -// in the parent thread. -erco 04/04/04 -// -#define POLLIN 1 -#define POLLOUT 4 -#define POLLERR 8 - -// Class to handle select() 'data ready' -class DataReady -{ - struct FD - { - int fd; - short events; - void (*cb)(int, void*); - void* arg; - }; - int nfds, fd_array_size; - FD *fds; - pthread_t tid; // select()'s thread id - - // Data that needs to be locked (all start with '_') - pthread_mutex_t _datalock; // data lock - fd_set _fdsets[3]; // r/w/x sets user wants to monitor - int _maxfd; // max fd count to monitor - int _cancelpipe[2]; // pipe used to help cancel thread - void *_userdata; // thread's userdata - -public: - DataReady() - { - nfds = 0; - fd_array_size = 0; - fds = 0; - tid = 0; - - pthread_mutex_init(&_datalock, NULL); - FD_ZERO(&_fdsets[0]); FD_ZERO(&_fdsets[1]); FD_ZERO(&_fdsets[2]); - _cancelpipe[0] = _cancelpipe[1] = 0; - _userdata = 0; - _maxfd = 0; - } - - ~DataReady() - { - CancelThread(DEBUGTEXT("DESTRUCTOR\n")); - if (fds) { free(fds); fds = 0; } - nfds = 0; - } - - // Locks - // The convention for locks: volatile vars start with '_', - // and must be locked before use. Locked code is prefixed - // with /*LOCK*/ to make painfully obvious esp. in debuggers. -erco - // - void DataLock() { pthread_mutex_lock(&_datalock); } - void DataUnlock() { pthread_mutex_unlock(&_datalock); } - - // Accessors - int IsThreadRunning() { return(tid ? 1 : 0); } - int GetNfds() { return(nfds); } - int GetCancelPipe(int ix) { return(_cancelpipe[ix]); } - fd_set GetFdset(int ix) { return(_fdsets[ix]); } - - // Methods - void AddFD(int n, int events, void (*cb)(int, void*), void *v); - void RemoveFD(int n, int events); - int CheckData(fd_set& r, fd_set& w, fd_set& x); - void HandleData(fd_set& r, fd_set& w, fd_set& x); - static void* DataReadyThread(void *self); - void StartThread(void *userdata); - void CancelThread(const char *reason); -}; - -static DataReady dataready; - -void DataReady::AddFD(int n, int events, void (*cb)(int, void*), void *v) -{ - RemoveFD(n, events); - int i = nfds++; - if (i >= fd_array_size) - { - FD *temp; - fd_array_size = 2*fd_array_size+1; - if (!fds) { temp = (FD*)malloc(fd_array_size*sizeof(FD)); } - else { temp = (FD*)realloc(fds, fd_array_size*sizeof(FD)); } - if (!temp) return; - fds = temp; - } - fds[i].cb = cb; - fds[i].arg = v; - fds[i].fd = n; - fds[i].events = events; - DataLock(); - /*LOCK*/ if (events & POLLIN) FD_SET(n, &_fdsets[0]); - /*LOCK*/ if (events & POLLOUT) FD_SET(n, &_fdsets[1]); - /*LOCK*/ if (events & POLLERR) FD_SET(n, &_fdsets[2]); - /*LOCK*/ if (n > _maxfd) _maxfd = n; - DataUnlock(); -} - -// Remove an FD from the array -void DataReady::RemoveFD(int n, int events) -{ - int i,j; - for (i=j=0; i<nfds; i++) - { - if (fds[i].fd == n) - { - int e = fds[i].events & ~events; - if (!e) continue; // if no events left, delete this fd - fds[i].events = e; - } - // move it down in the array if necessary: - if (j<i) - { fds[j] = fds[i]; } - j++; - } - nfds = j; - DataLock(); - /*LOCK*/ if (events & POLLIN) FD_CLR(n, &_fdsets[0]); - /*LOCK*/ if (events & POLLOUT) FD_CLR(n, &_fdsets[1]); - /*LOCK*/ if (events & POLLERR) FD_CLR(n, &_fdsets[2]); - /*LOCK*/ if (n == _maxfd) _maxfd--; - DataUnlock(); -} - -// CHECK IF USER DATA READY, RETURNS r/w/x INDICATING WHICH IF ANY -int DataReady::CheckData(fd_set& r, fd_set& w, fd_set& x) -{ - int ret; - DataLock(); - /*LOCK*/ timeval t = { 0, 1 }; // quick check - /*LOCK*/ r = _fdsets[0], w = _fdsets[1], x = _fdsets[2]; - /*LOCK*/ ret = ::select(_maxfd+1, &r, &w, &x, &t); - DataUnlock(); - if ( ret == -1 ) - { DEBUGPERRORMSG("CheckData(): select()"); } - return(ret); -} - -// HANDLE DATA READY CALLBACKS -void DataReady::HandleData(fd_set& r, fd_set& w, fd_set& x) -{ - for (int i=0; i<nfds; i++) - { - int f = fds[i].fd; - short revents = 0; - if (FD_ISSET(f, &r)) revents |= POLLIN; - if (FD_ISSET(f, &w)) revents |= POLLOUT; - if (FD_ISSET(f, &x)) revents |= POLLERR; - if (fds[i].events & revents) - { - DEBUGMSG("DOING CALLBACK: "); - fds[i].cb(f, fds[i].arg); - DEBUGMSG("DONE\n"); - } - } -} - -// DATA READY THREAD -// This thread watches for changes in user's file descriptors. -// Sends a 'data ready event' to the main thread if any change. -// -void* DataReady::DataReadyThread(void *o) -{ - DataReady *self = (DataReady*)o; - while ( 1 ) // loop until thread cancel or error - { - // Thread safe local copies of data before each select() - self->DataLock(); - /*LOCK*/ int maxfd = self->_maxfd; - /*LOCK*/ fd_set r = self->GetFdset(0); - /*LOCK*/ fd_set w = self->GetFdset(1); - /*LOCK*/ fd_set x = self->GetFdset(2); - /*LOCK*/ void *userdata = self->_userdata; - /*LOCK*/ int cancelpipe = self->GetCancelPipe(0); - /*LOCK*/ if ( cancelpipe > maxfd ) maxfd = cancelpipe; - /*LOCK*/ FD_SET(cancelpipe, &r); // add cancelpipe to fd's to watch - /*LOCK*/ FD_SET(cancelpipe, &x); - self->DataUnlock(); - // timeval t = { 1000, 0 }; // 1000 seconds; - timeval t = { 2, 0 }; // HACK: 2 secs prevents 'hanging' problem - int ret = ::select(maxfd+1, &r, &w, &x, &t); - pthread_testcancel(); // OSX 10.0.4 and older: needed for parent to cancel - switch ( ret ) - { - case 0: // NO DATA - continue; - case -1: // ERROR - { - DEBUGPERRORMSG("CHILD THREAD: select() failed"); - return(NULL); // error? exit thread - } - default: // DATA READY - { - if (FD_ISSET(cancelpipe, &r) || FD_ISSET(cancelpipe, &x)) // cancel? - { return(NULL); } // just exit - DEBUGMSG("CHILD THREAD: DATA IS READY\n"); - EventRef drEvent; - CreateEvent( 0, kEventClassFLTK, kEventFLTKDataReady, - 0, kEventAttributeUserEvent, &drEvent); - EventQueueRef eventqueue = (EventQueueRef)userdata; - PostEventToQueue(eventqueue, drEvent, kEventPriorityStandard ); - ReleaseEvent( drEvent ); - return(NULL); // done with thread - } - } - } -} - -// START 'DATA READY' THREAD RUNNING, CREATE INTER-THREAD PIPE -void DataReady::StartThread(void *new_userdata) -{ - CancelThread(DEBUGTEXT("STARTING NEW THREAD\n")); - DataLock(); - /*LOCK*/ pipe(_cancelpipe); // pipe for sending cancel msg to thread - /*LOCK*/ _userdata = new_userdata; - DataUnlock(); - DEBUGMSG("*** START THREAD\n"); - pthread_create(&tid, NULL, DataReadyThread, (void*)this); -} - -// CANCEL 'DATA READY' THREAD, CLOSE PIPE -void DataReady::CancelThread(const char *reason) -{ - if ( tid ) - { - DEBUGMSG("*** CANCEL THREAD: "); - DEBUGMSG(reason); - if ( pthread_cancel(tid) == 0 ) // cancel first - { - DataLock(); - /*LOCK*/ write(_cancelpipe[1], "x", 1); // wake thread from select - DataUnlock(); - pthread_join(tid, NULL); // wait for thread to finish - } - tid = 0; - DEBUGMSG("(JOINED) OK\n"); - } - // Close pipe if open - DataLock(); - /*LOCK*/ if ( _cancelpipe[0] ) { close(_cancelpipe[0]); _cancelpipe[0] = 0; } - /*LOCK*/ if ( _cancelpipe[1] ) { close(_cancelpipe[1]); _cancelpipe[1] = 0; } - DataUnlock(); -} - -void Fl::add_fd( int n, int events, void (*cb)(int, void*), void *v ) - { dataready.AddFD(n, events, cb, v); } - -void Fl::add_fd(int fd, void (*cb)(int, void*), void* v) - { dataready.AddFD(fd, POLLIN, cb, v); } - -void Fl::remove_fd(int n, int events) - { dataready.RemoveFD(n, events); } - -void Fl::remove_fd(int n) - { dataready.RemoveFD(n, -1); } - -/** - * Check if there is actually a message pending! - */ -int fl_ready() -{ - EventRef event; - return !ReceiveNextEvent(0, NULL, 0.0, false, &event); -} - -/** - * handle Apple Menu items (can be created using the Fl_Sys_Menu_Bar - * returns eventNotHandledErr if the menu item could not be handled - */ -OSStatus HandleMenu( HICommand *cmd ) -{ - OSStatus ret = eventNotHandledErr; - // attributes, commandIDm menu.menuRef, menu.menuItemIndex - UInt32 ref; - OSErr rrc = GetMenuItemRefCon( cmd->menu.menuRef, cmd->menu.menuItemIndex, &ref ); - //printf( "%d, %08x, %08x, %d, %d, %8x\n", rrc, cmd->attributes, cmd->commandID, cmd->menu.menuRef, cmd->menu.menuItemIndex, rrc ); - if ( rrc==noErr && ref ) - { - Fl_Menu_Item *m = (Fl_Menu_Item*)ref; - //printf( "Menu: %s\n", m->label() ); - fl_sys_menu_bar->picked( m ); - if ( m->flags & FL_MENU_TOGGLE ) // update the menu toggle symbol - SetItemMark( cmd->menu.menuRef, cmd->menu.menuItemIndex, (m->flags & FL_MENU_VALUE ) ? 0x12 : 0 ); - if ( m->flags & FL_MENU_RADIO ) // update all radio buttons in this menu - { - Fl_Menu_Item *j = m; - int i = cmd->menu.menuItemIndex; - for (;;) - { - if ( j->flags & FL_MENU_DIVIDER ) - break; - j++; i++; - if ( !j->text || !j->radio() ) - break; - SetItemMark( cmd->menu.menuRef, i, ( j->flags & FL_MENU_VALUE ) ? 0x13 : 0 ); - } - j = m-1; i = cmd->menu.menuItemIndex-1; - for ( ; i>0; j--, i-- ) - { - if ( !j->text || j->flags&FL_MENU_DIVIDER || !j->radio() ) - break; - SetItemMark( cmd->menu.menuRef, i, ( j->flags & FL_MENU_VALUE ) ? 0x13 : 0 ); - } - SetItemMark( cmd->menu.menuRef, cmd->menu.menuItemIndex, ( m->flags & FL_MENU_VALUE ) ? 0x13 : 0 ); - } - ret = noErr; // done handling this event - } - HiliteMenu(0); - return ret; -} - - -/** - * We can make every event pass through this function - * - mouse events need to be manipulated to use a mouse focus window - * - keyboard, mouse and some window events need to quit the Apple Event Loop - * so FLTK can continue its own management - */ -static pascal OSStatus carbonDispatchHandler( EventHandlerCallRef nextHandler, EventRef event, void *userData ) -{ - OSStatus ret = eventNotHandledErr; - HICommand cmd; - - fl_lock_function(); - - got_events = 1; - - switch ( GetEventClass( event ) ) - { - case kEventClassMouse: - switch ( GetEventKind( event ) ) - { - case kEventMouseUp: - case kEventMouseMoved: - case kEventMouseDragged: - if ( fl_capture ) - ret = SendEventToEventTarget( event, GetWindowEventTarget( fl_capture ) ); - else if ( fl_os_capture ){ - ret = SendEventToEventTarget( event, GetWindowEventTarget( fl_os_capture ) ); - fl_os_capture = 0; - } - break; - } - break; - case kEventClassCommand: - switch (GetEventKind( event ) ) - { - case kEventCommandProcess: - ret = GetEventParameter( event, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &cmd ); - if (ret == noErr && (cmd.attributes & kHICommandFromMenu) != 0) - ret = HandleMenu( &cmd ); - else - ret = eventNotHandledErr; - break; - } - break; - case kEventClassFLTK: - switch ( GetEventKind( event ) ) - { - case kEventFLTKBreakLoop: - ret = noErr; - break; - case kEventFLTKDataReady: - { - dataready.CancelThread(DEBUGTEXT("DATA READY EVENT\n")); - - // CHILD THREAD TELLS US DATA READY - // Check to see what's ready, and invoke user's cb's - // - fd_set r,w,x; - switch(dataready.CheckData(r,w,x)) - { - case 0: // NO DATA - break; - case -1: // ERROR - break; - default: // DATA READY - dataready.HandleData(r,w,x); - break; - } - } - ret = noErr; - break; - } - } - if ( ret == eventNotHandledErr ) - ret = CallNextEventHandler( nextHandler, event ); // let the OS handle the activation, but continue to get a click-through effect - - fl_unlock_function(); - - return ret; -} - - -/** - * break the current event loop - */ -static void breakMacEventLoop() -{ - EventRef breakEvent; - - fl_lock_function(); - - CreateEvent( 0, kEventClassFLTK, kEventFLTKBreakLoop, 0, kEventAttributeUserEvent, &breakEvent ); - PostEventToQueue( GetCurrentEventQueue(), breakEvent, kEventPriorityStandard ); - ReleaseEvent( breakEvent ); - - fl_unlock_function(); -} - -// -// MacOS X timers -// - -struct MacTimeout { - Fl_Timeout_Handler callback; - void* data; - EventLoopTimerRef timer; - EventLoopTimerUPP upp; - char pending; -}; -static MacTimeout* mac_timers; -static int mac_timer_alloc; -static int mac_timer_used; - - -static void realloc_timers() -{ - if (mac_timer_alloc == 0) { - mac_timer_alloc = 8; - } - mac_timer_alloc *= 2; - MacTimeout* new_timers = new MacTimeout[mac_timer_alloc]; - memset(new_timers, 0, sizeof(MacTimeout)*mac_timer_alloc); - memcpy(new_timers, mac_timers, sizeof(MacTimeout) * mac_timer_used); - MacTimeout* delete_me = mac_timers; - mac_timers = new_timers; - delete [] delete_me; -} - -static void delete_timer(MacTimeout& t) -{ - if (t.timer) { - RemoveEventLoopTimer(t.timer); - DisposeEventLoopTimerUPP(t.upp); - memset(&t, 0, sizeof(MacTimeout)); - } -} - - -static pascal void do_timer(EventLoopTimerRef timer, void* data) -{ - for (int i = 0; i < mac_timer_used; ++i) { - MacTimeout& t = mac_timers[i]; - if (t.timer == timer && t.data == data) { - t.pending = 0; - (*t.callback)(data); - if (t.pending==0) - delete_timer(t); - break; - } - } - breakMacEventLoop(); -} - -/** - * This function is the central event handler. - * It reads events from the event queue using the given maximum time - * Funny enough, it returns the same time that it got as the argument. - */ -static double do_queued_events( double time = 0.0 ) -{ - static bool been_here = false; - static RgnHandle rgn; - - // initialize events and a region that enables mouse move events - if (!been_here) { - rgn = NewRgn(); - Point mp; - GetMouse(&mp); - SetRectRgn(rgn, mp.h, mp.v, mp.h, mp.v); - SetEventMask(everyEvent); - been_here = true; - } - OSStatus ret; - static EventTargetRef target = 0; - if ( !target ) - { - target = GetEventDispatcherTarget(); - - EventHandlerUPP dispatchHandler = NewEventHandlerUPP( carbonDispatchHandler ); // will not be disposed by Carbon... - static EventTypeSpec dispatchEvents[] = { - { kEventClassWindow, kEventWindowShown }, - { kEventClassWindow, kEventWindowHidden }, - { kEventClassWindow, kEventWindowActivated }, - { kEventClassWindow, kEventWindowDeactivated }, - { kEventClassWindow, kEventWindowClose }, - { kEventClassKeyboard, kEventRawKeyDown }, - { kEventClassKeyboard, kEventRawKeyRepeat }, - { kEventClassKeyboard, kEventRawKeyUp }, - { kEventClassKeyboard, kEventRawKeyModifiersChanged }, - { kEventClassMouse, kEventMouseDown }, - { kEventClassMouse, kEventMouseUp }, - { kEventClassMouse, kEventMouseMoved }, - { kEventClassMouse, 11 }, // MightyMouse wheels - { kEventClassMouse, kEventMouseWheelMoved }, - { kEventClassMouse, kEventMouseDragged }, - { kEventClassFLTK, kEventFLTKBreakLoop }, - { kEventClassFLTK, kEventFLTKDataReady } }; - ret = InstallEventHandler( target, dispatchHandler, GetEventTypeCount(dispatchEvents), dispatchEvents, 0, 0L ); - static EventTypeSpec appEvents[] = { - { kEventClassCommand, kEventCommandProcess } }; - ret = InstallApplicationEventHandler( dispatchHandler, GetEventTypeCount(appEvents), appEvents, 0, 0L ); - } - - got_events = 0; - - // Check for re-entrant condition - if ( dataready.IsThreadRunning() ) - { dataready.CancelThread(DEBUGTEXT("AVOID REENTRY\n")); } - - // Start thread to watch for data ready - if ( dataready.GetNfds() ) - { dataready.StartThread((void*)GetCurrentEventQueue()); } - - fl_unlock_function(); - - EventRef event; - EventTimeout timeout = time; - if (!ReceiveNextEvent(0, NULL, timeout, true, &event)) { - got_events = 1; - OSErr ret = SendEventToEventTarget( event, target ); - if (ret!=noErr) { - EventRecord clevent; - ConvertEventRefToEventRecord(event, &clevent); - if (clevent.what==kHighLevelEvent) { - ret = AEProcessAppleEvent(&clevent); - } - } - if ( ret==eventNotHandledErr - && GetEventClass(event)==kEventClassMouse - && GetEventKind(event)==kEventMouseDown ) { - WindowRef win; Point pos; - GetEventParameter(event, kEventParamMouseLocation, typeQDPoint, - NULL, sizeof(pos), NULL, &pos); - if (MacFindWindow(pos, &win)==inMenuBar) { - MenuSelect(pos); - } - } - ReleaseEvent( event ); - } - - fl_lock_function(); - -#if CONSOLIDATE_MOTION - if (send_motion && send_motion == fl_xmousewin) { - send_motion = 0; - Fl::handle(FL_MOVE, fl_xmousewin); - } -#endif - - return time; -} - - -/** - * This public function handles all events. It wait a maximum of - * 'time' secods for an event. This version returns 1 if events - * other than the timeout timer were processed. - * - * \todo there is no socket handling in this code whatsoever - */ -int fl_wait( double time ) -{ - do_queued_events( time ); - return (got_events); -} - - -/** - * event handler for Apple-Q key combination - * this is also called from the Carbon Window handler after all windows were closed - */ -static OSErr QuitAppleEventHandler( const AppleEvent *appleEvt, AppleEvent* reply, UInt32 refcon ) -{ - fl_lock_function(); - - while ( Fl_X::first ) { - Fl_X *x = Fl_X::first; - Fl::handle( FL_CLOSE, x->w ); - if ( Fl_X::first == x ) { - fl_unlock_function(); - return noErr; // FLTK has not close all windows, so we return to the main program now - } - } - - fl_unlock_function(); - - return noErr; -} - - -/** - * Carbon Window handler - * This needs to be linked into all new window event handlers - */ -static pascal OSStatus carbonWindowHandler( EventHandlerCallRef nextHandler, EventRef event, void *userData ) -{ - UInt32 kind = GetEventKind( event ); - OSStatus ret = eventNotHandledErr; - Fl_Window *window = (Fl_Window*)userData; - Fl::first_window(window); - - Rect currentBounds, originalBounds; - WindowClass winClass; - static Fl_Window *activeWindow = 0; - - fl_lock_function(); - - switch ( kind ) - { - case kEventWindowBoundsChanging: - GetEventParameter( event, kEventParamCurrentBounds, typeQDRectangle, NULL, sizeof(Rect), NULL, ¤tBounds ); - GetEventParameter( event, kEventParamOriginalBounds, typeQDRectangle, NULL, sizeof(Rect), NULL, &originalBounds ); - break; - case kEventWindowDrawContent: - handleUpdateEvent( fl_xid( window ) ); - ret = noErr; - break; - case kEventWindowBoundsChanged: { - GetEventParameter( event, kEventParamCurrentBounds, typeQDRectangle, NULL, sizeof(Rect), NULL, ¤tBounds ); - GetEventParameter( event, kEventParamOriginalBounds, typeQDRectangle, NULL, sizeof(Rect), NULL, &originalBounds ); - int X = currentBounds.left, W = currentBounds.right-X; - int Y = currentBounds.top, H = currentBounds.bottom-Y; - resize_from_system = window; - window->resize( X, Y, W, H ); - if ( ( originalBounds.right - originalBounds.left != W ) - || ( originalBounds.bottom - originalBounds.top != H ) ) - { - if ( window->shown() ) - handleUpdateEvent( fl_xid( window ) ); - } - break; } - case kEventWindowShown: - if ( !window->parent() ) - { - GetWindowClass( fl_xid( window ), &winClass ); - if ( winClass != kHelpWindowClass ) { // help windows can't get the focus! - Fl::handle( FL_FOCUS, window); - activeWindow = window; - } - Fl::handle( FL_SHOW, window); - mods_to_e_state(GetCurrentKeyModifiers()); - } - break; - case kEventWindowHidden: - if ( !window->parent() ) Fl::handle( FL_HIDE, window); - break; - case kEventWindowActivated: - if ( window->shown() && window!=activeWindow ) - { - GetWindowClass( fl_xid( window ), &winClass ); - if ( winClass != kHelpWindowClass ) { // help windows can't get the focus! - Fl::handle( FL_FOCUS, window); - activeWindow = window; - } - } - break; - case kEventWindowDeactivated: - if ( window==activeWindow ) - { - Fl::handle( FL_UNFOCUS, window); - activeWindow = 0; - } - break; - case kEventWindowClose: - Fl::handle( FL_CLOSE, window ); // this might or might not close the window - // if there are no more windows, send a high-level quit event - if (!Fl_X::first) QuitAppleEventHandler( 0, 0, 0 ); - ret = noErr; // returning noErr tells Carbon to stop following up on this event - break; - case kEventWindowCollapsed: - window->clear_visible(); - break; - case kEventWindowExpanded: - window->set_visible(); - break; - } - - fl_unlock_function(); - - return ret; -} - - -/** - * Carbon Mousewheel handler - * This needs to be linked into all new window event handlers - */ -static pascal OSStatus carbonMousewheelHandler( EventHandlerCallRef nextHandler, EventRef event, void *userData ) -{ - // Handle the new "MightyMouse" mouse wheel events. Please, someone explain - // to me why Apple changed the API on this even though the current API - // supports two wheels just fine. Matthias, - fl_lock_function(); - - fl_os_event = event; - Fl_Window *window = (Fl_Window*)userData; - if ( !window->shown() ) - { - fl_unlock_function(); - return noErr; - } - Fl::first_window(window); - - EventMouseWheelAxis axis; - GetEventParameter( event, kEventParamMouseWheelAxis, typeMouseWheelAxis, NULL, sizeof(EventMouseWheelAxis), NULL, &axis ); - long delta; - GetEventParameter( event, kEventParamMouseWheelDelta, typeLongInteger, NULL, sizeof(long), NULL, &delta ); -// fprintf(stderr, "axis=%d, delta=%d\n", axis, delta); - if ( axis == kEventMouseWheelAxisX ) { - Fl::e_dx = -delta; - Fl::e_dy = 0; - if ( Fl::e_dx) Fl::handle( FL_MOUSEWHEEL, window ); - } else if ( axis == kEventMouseWheelAxisY ) { - Fl::e_dx = 0; - Fl::e_dy = -delta; - if ( Fl::e_dy) Fl::handle( FL_MOUSEWHEEL, window ); - } else { - fl_unlock_function(); - - return eventNotHandledErr; - } - - fl_unlock_function(); - - return noErr; -} - - -/** - * convert the current mouse chord into the FLTK modifier state - */ -static void chord_to_e_state( UInt32 chord ) -{ - static ulong state[] = - { - 0, FL_BUTTON1, FL_BUTTON3, FL_BUTTON1|FL_BUTTON3, FL_BUTTON2, - FL_BUTTON2|FL_BUTTON1, FL_BUTTON2|FL_BUTTON3, - FL_BUTTON2|FL_BUTTON1|FL_BUTTON3 - }; - Fl::e_state = ( Fl::e_state & 0xff0000 ) | state[ chord & 0x07 ]; -} - - -/** - * Carbon Mouse Button Handler - */ -static pascal OSStatus carbonMouseHandler( EventHandlerCallRef nextHandler, EventRef event, void *userData ) -{ - static int keysym[] = { 0, FL_Button+1, FL_Button+3, FL_Button+2 }; - static int px, py; - static char suppressed = 0; - - fl_lock_function(); - - fl_os_event = event; - Fl_Window *window = (Fl_Window*)userData; - if ( !window->shown() ) - { - fl_unlock_function(); - return noErr; - } - Fl::first_window(window); - Point pos; - GetEventParameter( event, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &pos ); - EventMouseButton btn; - GetEventParameter( event, kEventParamMouseButton, typeMouseButton, NULL, sizeof(EventMouseButton), NULL, &btn ); - UInt32 clickCount; - GetEventParameter( event, kEventParamClickCount, typeUInt32, NULL, sizeof(UInt32), NULL, &clickCount ); - UInt32 chord; - GetEventParameter( event, kEventParamMouseChord, typeUInt32, NULL, sizeof(UInt32), NULL, &chord ); - WindowRef xid = fl_xid(window), tempXid; - int sendEvent = 0, part = 0; - switch ( GetEventKind( event ) ) - { - case kEventMouseDown: - part = FindWindow( pos, &tempXid ); - if (!(Fl::grab() && window!=Fl::grab())) { - if ( part == inGrow ) { - fl_unlock_function(); - suppressed = 1; - Fl_Tooltip::current(0L); - return CallNextEventHandler( nextHandler, event ); // let the OS handle this for us - } - if ( part != inContent ) { - fl_unlock_function(); - suppressed = 1; - Fl_Tooltip::current(0L); - // anything else to here? - return CallNextEventHandler( nextHandler, event ); // let the OS handle this for us - } - } - suppressed = 0; - if (part==inContent && !IsWindowActive( xid ) ) { - CallNextEventHandler( nextHandler, event ); // let the OS handle the activation, but continue to get a click-through effect - } - // normal handling of mouse-down follows - fl_os_capture = xid; - sendEvent = FL_PUSH; - Fl::e_is_click = 1; px = pos.h; py = pos.v; - if (clickCount>1) - Fl::e_clicks++; - else - Fl::e_clicks = 0; - // fall through - case kEventMouseUp: - if (suppressed) { - suppressed = 0; - break; - } - if ( !window ) break; - if ( !sendEvent ) { - sendEvent = FL_RELEASE; - } - Fl::e_keysym = keysym[ btn ]; - // fall through - case kEventMouseMoved: - suppressed = 0; - if ( !sendEvent ) { - sendEvent = FL_MOVE; chord = 0; - } - // fall through - case kEventMouseDragged: - if (suppressed) break; - if ( !sendEvent ) { - sendEvent = FL_MOVE; // Fl::handle will convert into FL_DRAG - if (abs(pos.h-px)>5 || abs(pos.v-py)>5) - Fl::e_is_click = 0; - } - chord_to_e_state( chord ); - GrafPtr oldPort; - GetPort( &oldPort ); - SetPort( GetWindowPort(xid) ); // \todo replace this! There must be some GlobalToLocal call that has a port as an argument - SetOrigin(0, 0); - Fl::e_x_root = pos.h; - Fl::e_y_root = pos.v; - GlobalToLocal( &pos ); - Fl::e_x = pos.h; - Fl::e_y = pos.v; - SetPort( oldPort ); - if (GetEventKind(event)==kEventMouseDown && part!=inContent) { - int used = Fl::handle( sendEvent, window ); - CallNextEventHandler( nextHandler, event ); // let the OS handle this for us - if (!used) - suppressed = 1; - } else { - Fl::handle( sendEvent, window ); - } - break; - } - - fl_unlock_function(); - - return noErr; -} - - -/** - * convert the keyboard return code into the symbol on the keycaps - */ -static unsigned short keycode_to_sym( UInt32 keyCode, UInt32 mods, unsigned short deflt ) -{ - static Ptr map = 0; - UInt32 state = 0; - if (!map) { - map = (Ptr)GetScriptManagerVariable(smKCHRCache); - if (!map) { - long kbID = GetScriptManagerVariable(smKeyScript); - map = *GetResource('KCHR', kbID); - } - } - if (map) - return KeyTranslate(map, keyCode|mods, &state ); - return deflt; -} - -/* - * keycode_function for post-10.5 systems, allows more sophisticated decoding of keys - */ -static int keycodeToUnicode( - char * uniChars, int maxChars, - EventKind eKind, - UInt32 keycode, UInt32 modifiers, - UInt32 * deadKeyStatePtr, - unsigned char, // not used in this function - unsigned short) // not used in this function -{ - // first get the keyboard mapping in a post 10.2 way - - Ptr resource; - TextEncoding encoding; - static TextEncoding lastEncoding = kTextEncodingMacRoman; - int len = 0; - KeyboardLayoutRef currentLayout = NULL; - static KeyboardLayoutRef lastLayout = NULL; - SInt32 currentLayoutId = 0; - static SInt32 lastLayoutId; - int hasLayoutChanged = false; - static Ptr uchr = NULL; - static Ptr KCHR = NULL; - // ScriptCode currentKeyScript; - - KLGetCurrentKeyboardLayout(¤tLayout); - if (currentLayout) { - KLGetKeyboardLayoutProperty(currentLayout, kKLIdentifier, (const void**)¤tLayoutId); - if ( (lastLayout != currentLayout) || (lastLayoutId != currentLayoutId) ) { - lastLayout = currentLayout; - lastLayoutId = currentLayoutId; - uchr = NULL; - KCHR = NULL; - if ((KLGetKeyboardLayoutProperty(currentLayout, kKLuchrData, (const void**)&uchr) == noErr) && (uchr != NULL)) { - // done - } else if ((KLGetKeyboardLayoutProperty(currentLayout, kKLKCHRData, (const void**)&KCHR) == noErr) && (KCHR != NULL)) { - // done - } - // FIXME No Layout property found. Now we have a problem. - } - } - if (hasLayoutChanged) { - //deadKeyStateUp = deadKeyStateDown = 0; - if (KCHR != NULL) { - // FIXME this must not happen - } else if (uchr == NULL) { - KCHR = (Ptr) GetScriptManagerVariable(smKCHRCache); - } - } - if (uchr != NULL) { - // this is what I expect - resource = uchr; - } else { - resource = KCHR; - encoding = lastEncoding; - // this is actually not supported by the following code and will likely crash - } - - // now apply that keyboard mapping to our keycode - - int action; - //OptionBits options = 0; - // not used yet: OptionBits options = kUCKeyTranslateNoDeadKeysMask; - unsigned long keyboardType; - keycode &= 0xFF; - modifiers = (modifiers >> 8) & 0xFF; - keyboardType = LMGetKbdType(); - OSStatus status; - UniCharCount actuallength; - UniChar utext[10]; - - switch(eKind) { - case kEventRawKeyDown: action = kUCKeyActionDown; break; - case kEventRawKeyUp: action = kUCKeyActionUp; break; - case kEventRawKeyRepeat: action = kUCKeyActionAutoKey; break; - default: return 0; - } - - UInt32 deadKeyState = *deadKeyStatePtr; - if ((action==kUCKeyActionUp)&&(*deadKeyStatePtr)) - deadKeyStatePtr = &deadKeyState; - - status = UCKeyTranslate( - (const UCKeyboardLayout *) uchr, - keycode, action, modifiers, keyboardType, - 0, deadKeyStatePtr, - 10, &actuallength, utext); - - if (noErr != status) { - fprintf(stderr,"UCKeyTranslate failed: %d\n", (int) status); - actuallength = 0; - } - - // convert the list of unicode chars into utf8 - // FIXME no bounds check (see maxchars) - unsigned i; - for (i=0; i<actuallength; ++i) { - len += fl_utf8encode(utext[i], uniChars+len); - } - uniChars[len] = 0; - return len; -} - -/* - * keycode_function for pre-10.5 systems, this is the "historic" fltk Mac key handling - */ -static int keycode_wrap_old( - char * buffer, - int, EventKind, UInt32, // not used in this function - UInt32, UInt32 *, // not used in this function - unsigned char key, - unsigned short sym) -{ - if ( (sym >= FL_KP && sym <= FL_KP_Last) || !(sym & 0xff00) || - sym == FL_Tab || sym == FL_Enter) { - buffer[0] = key; - return 1; - } else { - buffer[0] = 0; - return 0; - } -} /* keycode_wrap_old */ -/* - * Stub pointer to select appropriate keycode_function per operating system version. This function pointer - * is initialised in fl_open_display, based on the runtime identification of the host OS version. This is - * intended to allow us to utilise 10.5 services dynamically to improve Unicode handling, whilst still - * allowing code to run satisfactorily on older systems. - */ -static int (*keycode_function)(char*, int, EventKind, UInt32, UInt32, UInt32*, unsigned char, unsigned short) = keycode_wrap_old; - - -// EXPERIMENTAL! -pascal OSStatus carbonTextHandler( - EventHandlerCallRef nextHandler, EventRef event, void *userData ) -{ - Fl_Window *window = (Fl_Window*)userData; - Fl::first_window(window); - fl_lock_function(); - //int kind = GetEventKind(event); - unsigned short buf[200]; - ByteCount size; - GetEventParameter( event, kEventParamTextInputSendText, typeUnicodeText, - NULL, 100, &size, &buf ); -// printf("TextEvent: %02x %02x %02x %02x\n", buf[0], buf[1], buf[2], buf[3]); - // FIXME: oversimplified! - unsigned ucs = buf[0]; - char utf8buf[20]; - int len = fl_utf8encode(ucs, utf8buf); - Fl::e_length = len; - Fl::e_text = utf8buf; - while (window->parent()) window = window->window(); - Fl::handle(FL_KEYBOARD, window); - fl_unlock_function(); - fl_lock_function(); - Fl::handle(FL_KEYUP, window); - fl_unlock_function(); - // for some reason, the window does not redraw until the next mouse move or button push - // sending a 'redraw()' or 'awake()' does not solve the issue! - Fl::flush(); - return noErr; -} - -/** - * handle carbon keyboard events - */ -pascal OSStatus carbonKeyboardHandler( - EventHandlerCallRef nextHandler, EventRef event, void *userData ) -{ - static char buffer[32]; - int sendEvent = 0; - Fl_Window *window = (Fl_Window*)userData; - Fl::first_window(window); - UInt32 mods; - static UInt32 prevMods = mods_to_e_state( GetCurrentKeyModifiers() ); - - fl_lock_function(); - - int kind = GetEventKind(event); - - // get the modifiers for any of the events - GetEventParameter( event, kEventParamKeyModifiers, typeUInt32, - NULL, sizeof(UInt32), NULL, &mods ); - - // get the key code only for key events - UInt32 keyCode = 0, maskedKeyCode = 0; - unsigned char key = 0; - unsigned short sym = 0; - if (kind!=kEventRawKeyModifiersChanged) { - GetEventParameter( event, kEventParamKeyCode, typeUInt32, - NULL, sizeof(UInt32), NULL, &keyCode ); - GetEventParameter( event, kEventParamKeyMacCharCodes, typeChar, - NULL, sizeof(char), NULL, &key ); - } - // extended keyboards can also send sequences on key-up to generate Kanji etc. codes. - // Some observed prefixes are 0x81 to 0x83, followed by an 8 bit keycode. - // In this mode, there seem to be no key-down codes -// printf("%08x %08x %08x\n", keyCode, mods, key); - maskedKeyCode = keyCode & 0x7f; - /* output a human readable event identifier for debugging - const char *ev = ""; - switch (kind) { - case kEventRawKeyDown: ev = "kEventRawKeyDown"; break; - case kEventRawKeyRepeat: ev = "kEventRawKeyRepeat"; break; - case kEventRawKeyUp: ev = "kEventRawKeyUp"; break; - case kEventRawKeyModifiersChanged: ev = "kEventRawKeyModifiersChanged"; break; - default: ev = "unknown"; - } - printf("%08x %08x %08x '%c' %s \n", mods, keyCode, key, key, ev); - */ - switch (kind) - { - case kEventRawKeyDown: - case kEventRawKeyRepeat: -/* - // FIXME Matt: For 10.5, the keycode_function will handle all this. This is untested for ealier versions of OS X. - // When the user presses a "dead key", no information is send about - // which dead key symbol was created. So we need to trick Carbon into - // giving us the code by sending a "space" after the "dead key". - if (key==0) { - UInt32 ktState = 0; - KeyboardLayoutRef klr; - KLGetCurrentKeyboardLayout(&klr); - const void *kchar = 0; KLGetKeyboardLayoutProperty(klr, kKLKCHRData, &kchar); - KeyTranslate(kchar, (mods&0xff00) | keyCode, &ktState); // send the dead key - key = KeyTranslate(kchar, 0x31, &ktState); // fake a space key press - Fl::e_state |= 0x40000000; // mark this as a dead key - } else { - Fl::e_state &= 0xbfffffff; // clear the deadkey flag - } -*/ - sendEvent = FL_KEYBOARD; - // fall through - case kEventRawKeyUp: - if ( !sendEvent ) { - sendEvent = FL_KEYUP; - Fl::e_state &= 0xbfffffff; // clear the deadkey flag - } - // if the user pressed alt/option, event_key should have the keycap, - // but event_text should generate the international symbol - sym = macKeyLookUp[maskedKeyCode]; - if ( isalpha(key) ) - sym = tolower(key); - else if ( Fl::e_state&FL_CTRL && key<32 && sym<0xff00) - sym = key+96; - else if ( Fl::e_state&FL_ALT && sym<0xff00) // find the keycap of this key - sym = keycode_to_sym( maskedKeyCode, 0, macKeyLookUp[ maskedKeyCode ] ); - Fl::e_keysym = Fl::e_original_keysym = sym; - // Handle FL_KP_Enter on regular keyboards and on Powerbooks - if ( maskedKeyCode==0x4c || maskedKeyCode==0x34) key=0x0d; - // Handle the Delete key on the keypad - // Matt: the Mac has no concept of a NumLock key, or at least not visible - // Matt: to Carbon. The kEventKeyModifierNumLockMask is only set when - // Matt: a numeric keypad key is pressed and does not correspond with - // Matt: the NumLock light in PowerBook keyboards. - - // Matt: attempt to get the correct Unicode character(s) from our keycode - // imm: keycode_function function pointer added to allow us to use different functions - // imm: depending on which OS version we are running on (tested and set in fl_open_display) - static UInt32 deadKeyState = 0; // must be cleared when losing focus - Fl::e_length = (*keycode_function)(buffer, 31, kind, keyCode, mods, &deadKeyState, key, sym); - Fl::e_text = buffer; - buffer[Fl::e_length] = 0; // just in case... - break; - case kEventRawKeyModifiersChanged: { - UInt32 tMods = prevMods ^ mods; - if ( tMods ) - { - mods_to_e_keysym( tMods ); - if ( Fl::e_keysym ) - sendEvent = ( prevMods<mods ) ? FL_KEYBOARD : FL_KEYUP; - Fl::e_length = 0; - buffer[0] = 0; - prevMods = mods; - } - mods_to_e_state( mods ); - break; } - } - while (window->parent()) window = window->window(); - if (sendEvent && Fl::handle(sendEvent,window)) { - fl_unlock_function(); - return noErr; // return noErr if FLTK handled the event - } else { - fl_unlock_function(); - //return CallNextEventHandler( nextHandler, event );; - // Matt: I had better results (no duplicate events) always returning - // Matt: 'noErr'. System keyboard events still seem to work just fine. - return noErr; - } -} - - - -/** - * Open callback function to call... - */ - -static void (*open_cb)(const char *) = 0; - - -/** - * Event handler for Apple-O key combination and also for file opens - * via the finder... - */ - -static OSErr OpenAppleEventHandler(const AppleEvent *appleEvt, - AppleEvent *reply, - UInt32 refcon) { - OSErr err; - AEDescList documents; - long i, n; - FSSpec fileSpec; - AEKeyword keyWd; - DescType typeCd; - Size actSz; - char filename[1024]; - - if (!open_cb) return noErr; - - // Initialize the document list... - AECreateDesc(typeNull, NULL, 0, &documents); - - // Get the open parameter(s)... - err = AEGetParamDesc(appleEvt, keyDirectObject, typeAEList, &documents); - if (err != noErr) { - AEDisposeDesc(&documents); - return err; - } - - // Lock access to FLTK in this thread... - fl_lock_function(); - - // Open the documents via the callback... - if (AECountItems(&documents, &n) == noErr) { - for (i = 1; i <= n; i ++) { - // Get the next FSSpec record... - AEGetNthPtr(&documents, i, typeFSS, &keyWd, &typeCd, - (Ptr)&fileSpec, sizeof(fileSpec), - (actSz = sizeof(fileSpec), &actSz)); - - // Convert to a UNIX path... - FSSpec2UnixPath(&fileSpec, filename); - - // Call the callback with the filename... - (*open_cb)(filename); - } - } - - // Unlock access to FLTK for all threads... - fl_unlock_function(); - - // Get rid of the document list... - AEDisposeDesc(&documents); - - return noErr; -} - - -/** - * Install an open documents event handler... - */ - -void fl_open_callback(void (*cb)(const char *)) { - open_cb = cb; - if (cb) { - AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, - NewAEEventHandlerUPP((AEEventHandlerProcPtr) - OpenAppleEventHandler), 0, false); - } else { - AERemoveEventHandler(kCoreEventClass, kAEOpenDocuments, - NewAEEventHandlerUPP((AEEventHandlerProcPtr) - OpenAppleEventHandler), false); - } -} - - -/** - * initialize the Mac toolboxes, dock status, and set the default menubar - */ - -extern "C" { - extern OSErr CPSEnableForegroundOperation(ProcessSerialNumber *psn, UInt32 _arg2, - UInt32 _arg3, UInt32 _arg4, UInt32 _arg5); -} - -void fl_open_display() { - static char beenHereDoneThat = 0; - if ( !beenHereDoneThat ) { - beenHereDoneThat = 1; - - FlushEvents(everyEvent,0); - - MoreMasters(); // \todo Carbon suggests MoreMasterPointers() - AEInstallEventHandler( kCoreEventClass, kAEQuitApplication, NewAEEventHandlerUPP((AEEventHandlerProcPtr)QuitAppleEventHandler), 0, false ); - - // create the Mac Handle for the default cursor (a pointer to a pointer) - GetQDGlobalsArrow(&default_cursor); - default_cursor_ptr = &default_cursor; - fl_default_cursor = &default_cursor_ptr; - - ClearMenuBar(); - AppendResMenu( GetMenuHandle( 1 ), 'DRVR' ); - DrawMenuBar(); - - // bring the application into foreground without a 'CARB' resource - Boolean same_psn; - ProcessSerialNumber cur_psn, front_psn; - if( !GetCurrentProcess( &cur_psn ) && !GetFrontProcess( &front_psn ) && - !SameProcess( &front_psn, &cur_psn, &same_psn ) && !same_psn ) - { - // only transform the application type for unbundled apps - CFBundleRef bundle = CFBundleGetMainBundle(); - if( bundle ) - { - FSRef execFs; - CFURLRef execUrl = CFBundleCopyExecutableURL( bundle ); - CFURLGetFSRef( execUrl, &execFs ); - - FSRef bundleFs; - GetProcessBundleLocation( &cur_psn, &bundleFs ); - - if( !FSCompareFSRefs( &execFs, &bundleFs ) ) - bundle = NULL; - - CFRelease(execUrl); - } - - if( !bundle ) - { - // Earlier versions of this code tried to use weak linking, however it - // appears that this does not work on 10.2. Since 10.3 and higher provide - // both TransformProcessType and CPSEnableForegroundOperation, the following - // conditional code compiled on 10.2 will still work on newer releases... - OSErr err; - -#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2 - if (TransformProcessType != NULL) { - err = TransformProcessType(&cur_psn, kProcessTransformToForegroundApplication); - } else -#endif // MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2 - err = CPSEnableForegroundOperation(&cur_psn, 0x03, 0x3C, 0x2C, 0x1103); - - if (err == noErr) { - SetFrontProcess( &cur_psn ); - } - } - } - - // imm: keycode handler stub setting - use Gestalt to determine the running system version, - // then set the keycode_function pointer accordingly - keycode_function = keycode_wrap_old; // default to pre-10.5 mechanism - SInt32 MacVersion; - if (Gestalt(gestaltSystemVersion, &MacVersion) == noErr) - { - if(MacVersion >= 0x1050) { // 10.5.0 or later - keycode_function = keycodeToUnicode; - } - } - } -} - - -/** - * get rid of allocated resources - */ -void fl_close_display() { -} - - -/** - * smallest x ccordinate in screen space - */ -int Fl::x() { - BitMap r; - GetQDGlobalsScreenBits(&r); - return r.bounds.left; -} - - -/** - * smallest y ccordinate in screen space - */ -int Fl::y() { - BitMap r; - GetQDGlobalsScreenBits(&r); - return r.bounds.top + 20; // \todo 20 pixel menu bar? -} - - -/** - * screen width (single monitor!?) - */ -int Fl::w() { - BitMap r; - GetQDGlobalsScreenBits(&r); - return r.bounds.right - r.bounds.left; -} - - -/** - * screen height (single monitor!?) - */ -int Fl::h() { - BitMap r; - GetQDGlobalsScreenBits(&r); - return r.bounds.bottom - r.bounds.top - 20; -} - - -/** - * get the current mouse pointer world coordinates - */ -void Fl::get_mouse(int &x, int &y) -{ - fl_open_display(); - Point loc; - GetMouse( &loc ); - LocalToGlobal( &loc ); - x = loc.h; - y = loc.v; -} - - -/** - * convert Mac keystrokes to FLTK - */ -unsigned short mac2fltk(ulong macKey) -{ - unsigned short cc = macKeyLookUp[(macKey>>8)&0x7f]; - if (cc) return cc; - return macKey&0xff; -} - - -/** - * Initialize the given port for redraw and call the windw's flush() to actually draw the content - */ -void Fl_X::flush() -{ - w->flush(); - if (fl_gc) - CGContextFlush(fl_gc); - SetOrigin( 0, 0 ); -} - - -/** - * Handle all clipping and redraw for the given port - * There are two different callers for this event: - * 1: the OS can request a redraw and provides all clipping itself - * 2: Fl::flush() wants all redraws now - */ -void handleUpdateEvent( WindowPtr xid ) -{ - Fl_Window *window = fl_find( xid ); - if ( !window ) return; - GrafPtr oldPort; - GetPort( &oldPort ); - SetPort( GetWindowPort(xid) ); - Fl_X *i = Fl_X::i( window ); - i->wait_for_expose = 0; - if ( window->damage() ) { - if ( i->region ) { - InvalWindowRgn( xid, i->region ); - } - } - if ( i->region ) { // no region, so the sytem will take the update region from the OS - DisposeRgn( i->region ); - i->region = 0; - } - for ( Fl_X *cx = i->xidChildren; cx; cx = cx->xidNext ) - { - cx->w->clear_damage(window->damage()|FL_DAMAGE_EXPOSE); - cx->flush(); - cx->w->clear_damage(); - } - window->clear_damage(window->damage()|FL_DAMAGE_EXPOSE); - i->flush(); - window->clear_damage(); - SetPort( oldPort ); -} - -// Gets the border sizes and the titlebar size -static void get_window_frame_sizes(int &bx, int &by, int &bt) { -#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2 - static HIRect contentRect = { {50,50}, {100,100} }; // a rect to stand in for the content rect of a real window - static HIThemeWindowDrawInfo metrics= {0, - kThemeStateActive, kThemeDocumentWindow, - kThemeWindowHasFullZoom + kThemeWindowHasCloseBox + - kThemeWindowHasCollapseBox + kThemeWindowHasTitleText, - 0, 0}; - HIShapeRef shape1=0, shape2=0, shape3=0; - HIRect rect1, rect2, rect3; - OSStatus status; - status = HIThemeGetWindowShape(&contentRect, &metrics, kWindowStructureRgn, &shape1); - status |= HIThemeGetWindowShape(&contentRect, &metrics, kWindowContentRgn, &shape2); - status |= HIThemeGetWindowShape(&contentRect, &metrics, kWindowTitleBarRgn, &shape3); - - if (!status) - { - HIShapeGetBounds(shape1, &rect1); - HIShapeGetBounds(shape2, &rect2); - HIShapeGetBounds(shape3, &rect3); - bt = rect3.size.height; - bx = rect2.origin.x - rect1.origin.x; - by = rect2.origin.y - rect1.origin.y - bt; - // fprintf(stderr, "HIThemeGetWindowShape succeeded bx=%d by=%d bt=%d\n", bx, by, bt); - } - else -#endif // MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2 - { - // sets default dimensions - bx = by = 6; - bt = 22; - // fprintf(stderr, "HIThemeGetWindowShape failed, bx=%d by=%d bt=%d\n", bx, by, bt); - } -#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2 - CFRelease(shape1); // we must free HIThemeGetWindowShape() (copied) handles - CFRelease(shape2); - CFRelease(shape3); -#endif // MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2 -} - -/** - * \todo this is a leftover from OS9 times. Please check how much applies to Carbon! - */ -int Fl_X::fake_X_wm(const Fl_Window* w,int &X,int &Y, int &bt,int &bx, int &by) { - int W, H, xoff, yoff, dx, dy; - int ret = bx = by = bt = 0; - if (w->border() && !w->parent()) { - if (w->maxw != w->minw || w->maxh != w->minh) { - ret = 2; - get_window_frame_sizes(bx, by, bt); - /* - bx = 6; // \todo Mac : GetSystemMetrics(SM_CXSIZEFRAME); - by = 6; // \todo Mac : get Mac window frame size GetSystemMetrics(SM_CYSIZEFRAME); - */ - } else { - ret = 1; - get_window_frame_sizes(bx, by, bt); - /* - bx = 6; // \todo Mac : GetSystemMetrics(SM_CXFIXEDFRAME); - by = 6; // \todo Mac : GetSystemMetrics(SM_CYFIXEDFRAME); - */ - } - } - //The coordinates of the whole window, including non-client area - xoff = bx; - yoff = by + bt; - dx = 2*bx; - dy = 2*by + bt; - X = w->x()-xoff; - Y = w->y()-yoff; - W = w->w()+dx; - H = w->h()+dy; - - //Proceed to positioning the window fully inside the screen, if possible - - // let's get a little elaborate here. Mac OS X puts a lot of stuff on the desk - // that we want to avoid when positioning our window, namely the Dock and the - // top menu bar (and even more stuff in 10.4 Tiger). So we will go through the - // list of all available screens and find the one that this window is most - // likely to go to, and then reposition it to fit withing the 'good' area. - Rect r; - // find the screen, that the center of this window will fall into - int R = X+W, B = Y+H; // right and bottom - int cx = (X+R)/2, cy = (Y+B)/2; // center of window; - GDHandle gd = 0L; - for (gd = GetDeviceList(); gd; gd = GetNextDevice(gd)) { - GDPtr gp = *gd; - if ( cx >= gp->gdRect.left && cx <= gp->gdRect.right - && cy >= gp->gdRect.top && cy <= gp->gdRect.bottom) - break; - } - // if the center doesn't fall on a screen, try the top left - if (!gd) { - for (gd = GetDeviceList(); gd; gd = GetNextDevice(gd)) { - GDPtr gp = *gd; - if ( X >= gp->gdRect.left && X <= gp->gdRect.right - && Y >= gp->gdRect.top && Y <= gp->gdRect.bottom) - break; - } - } - // if that doesn't fall on a screen, try the top right - if (!gd) { - for (gd = GetDeviceList(); gd; gd = GetNextDevice(gd)) { - GDPtr gp = *gd; - if ( R >= gp->gdRect.left && R <= gp->gdRect.right - && Y >= gp->gdRect.top && Y <= gp->gdRect.bottom) - break; - } - } - // if that doesn't fall on a screen, try the bottom left - if (!gd) { - for (gd = GetDeviceList(); gd; gd = GetNextDevice(gd)) { - GDPtr gp = *gd; - if ( X >= gp->gdRect.left && X <= gp->gdRect.right - && B >= gp->gdRect.top && B <= gp->gdRect.bottom) - break; - } - } - // last resort, try the bottom right - if (!gd) { - for (gd = GetDeviceList(); gd; gd = GetNextDevice(gd)) { - GDPtr gp = *gd; - if ( R >= gp->gdRect.left && R <= gp->gdRect.right - && B >= gp->gdRect.top && B <= gp->gdRect.bottom) - break; - } - } - // if we still have not found a screen, we will use the main - // screen, the one that has the application menu bar. - if (!gd) gd = GetMainDevice(); - if (gd) { - GetAvailableWindowPositioningBounds(gd, &r); - if ( R > r.right ) X -= R - r.right; - if ( B > r.bottom ) Y -= B - r.bottom; - if ( X < r.left ) X = r.left; - if ( Y < r.top ) Y = r.top; - } - - //Return the client area's top left corner in (X,Y) - X+=xoff; - Y+=yoff; - - return ret; -} - -/** - * convert a Mac FSSpec structure into a Unix filename - */ -static int FSSpec2UnixPath( FSSpec *fs, char *dst ) -{ - FSRef fsRef; - FSpMakeFSRef( fs, &fsRef ); - FSRefMakePath( &fsRef, (UInt8*)dst, 1024 ); - return strlen(dst); -} -static void convert_crlf(char * s, size_t len) -{ - // turn all \r characters into \n: - for (size_t x = 0; x < len; x++) if (s[x] == '\r') s[x] = '\n'; -} - - -static DragReference currDragRef = 0; -static char *currDragData = 0L; -static int currDragSize = 0; -static OSErr currDragErr = noErr; -Fl_Window *fl_dnd_target_window = 0; -#include <FL/fl_draw.H> - -/** - * Fill the currDrag* variables with the current DnD ASCII text. - */ -static OSErr fillCurrentDragData(DragReference dragRef) -{ - OSErr ret = noErr; - char *dst = 0L; - - // shortcut through this whole procedure if this is still the same drag event - if (dragRef==currDragRef) - return currDragErr; - - // clear currDrag* for a new drag event - currDragRef = dragRef; - if (currDragData) free(currDragData); - currDragData = 0; - currDragSize = 0; - - // fill currDRag* with ASCII data, if available - UInt16 i, nItem; - ItemReference itemRef; - FlavorFlags flags; - Size itemSize, size = 0; - CountDragItems( dragRef, &nItem ); - - for ( i = 1; i <= nItem; i++ ) - { - GetDragItemReferenceNumber( dragRef, i, &itemRef ); - ret = GetFlavorFlags( dragRef, itemRef, 'utf8', &flags ); - if ( ret == noErr ) - { - GetFlavorDataSize( dragRef, itemRef, 'utf8', &itemSize ); - size += itemSize; - continue; - } - ret = GetFlavorFlags( dragRef, itemRef, 'utxt', &flags ); - if ( ret == noErr ) - { - GetFlavorDataSize( dragRef, itemRef, 'utxt', &itemSize ); - size += itemSize; - continue; - } - ret = GetFlavorFlags( dragRef, itemRef, 'TEXT', &flags ); - if ( ret == noErr ) - { - GetFlavorDataSize( dragRef, itemRef, 'TEXT', &itemSize ); - size += itemSize; - continue; - } - ret = GetFlavorFlags( dragRef, itemRef, 'hfs ', &flags ); - if ( ret == noErr ) - { - size += 1024; //++ ouch! We should create the full pathname and figure out its length - continue; - } - } - - if ( !size ) - { - currDragErr = userCanceledErr; - return currDragErr; - } - - currDragSize = size + nItem - 1; - currDragData = dst = (char*)malloc( size+nItem );; - - for ( i = 1; i <= nItem; i++ ) - { - GetDragItemReferenceNumber( dragRef, i, &itemRef ); - ret = GetFlavorFlags( dragRef, itemRef, 'utf8', &flags ); - if ( ret == noErr ) - { - GetFlavorDataSize( dragRef, itemRef, 'utf8', &itemSize ); - GetFlavorData( dragRef, itemRef, 'utf8', dst, &itemSize, 0L ); - dst += itemSize; - *dst++ = '\n'; // add our element separator - continue; - } - GetDragItemReferenceNumber( dragRef, i, &itemRef ); - ret = GetFlavorFlags( dragRef, itemRef, 'utxt', &flags ); - if ( ret == noErr ) - { - GetFlavorDataSize( dragRef, itemRef, 'utxt', &itemSize ); - GetFlavorData( dragRef, itemRef, 'utxt', dst, &itemSize, 0L ); - dst += itemSize; - *dst++ = '\n'; // add our element separator - continue; - } - ret = GetFlavorFlags( dragRef, itemRef, 'TEXT', &flags ); - if ( ret == noErr ) - { - GetFlavorDataSize( dragRef, itemRef, 'TEXT', &itemSize ); - GetFlavorData( dragRef, itemRef, 'TEXT', dst, &itemSize, 0L ); - dst += itemSize; - *dst++ = '\n'; // add our element separator - continue; - } - ret = GetFlavorFlags( dragRef, itemRef, 'hfs ', &flags ); - if ( ret == noErr ) - { - HFSFlavor hfs; itemSize = sizeof( hfs ); - GetFlavorData( dragRef, itemRef, 'hfs ', &hfs, &itemSize, 0L ); - itemSize = FSSpec2UnixPath( &hfs.fileSpec, dst ); // return the path name in UTF8 - dst += itemSize; - if ( itemSize>1 && ( hfs.fileType=='fold' || hfs.fileType=='disk' ) ) - *dst++ = '/'; - *dst++ = '\n'; // add our element separator - continue; - } - } - - dst[-1] = 0; - currDragSize = dst - currDragData - 1; - currDragErr = ret; - return ret; -} - -/** - * Drag'n'drop tracking handler - */ -static pascal OSErr dndTrackingHandler( DragTrackingMessage msg, WindowPtr w, void *userData, DragReference dragRef ) -{ - Fl_Window *target = (Fl_Window*)userData; - Fl::first_window(target); - Point mp; - static int px, py; - - fillCurrentDragData(dragRef); - Fl::e_length = currDragSize; - Fl::e_text = currDragData; - - switch ( msg ) - { - case kDragTrackingEnterWindow: - // check if 'TEXT' is available - GetDragMouse( dragRef, &mp, 0 ); - Fl::e_x_root = px = mp.h; - Fl::e_y_root = py = mp.v; - Fl::e_x = px - target->x(); - Fl::e_y = py - target->y(); - fl_dnd_target_window = target; - if ( Fl::handle( FL_DND_ENTER, target ) ) - fl_cursor( FL_CURSOR_HAND ); //ShowDragHilite( ); // modify the mouse cursor?! - else - fl_cursor( FL_CURSOR_DEFAULT ); //HideDragHilite( dragRef ); - breakMacEventLoop(); - return noErr; - case kDragTrackingInWindow: - GetDragMouse( dragRef, &mp, 0 ); - if ( mp.h==px && mp.v==py ) - break; //+ return previous condition for dnd hiliting - Fl::e_x_root = px = mp.h; - Fl::e_y_root = py = mp.v; - Fl::e_x = px - target->x(); - Fl::e_y = py - target->y(); - fl_dnd_target_window = target; - if ( Fl::handle( FL_DND_DRAG, target ) ) - fl_cursor( FL_CURSOR_HAND ); //ShowDragHilite( ); // modify the mouse cursor?! - else - fl_cursor( FL_CURSOR_DEFAULT ); //HideDragHilite( dragRef ); - breakMacEventLoop(); - return noErr; - break; - case kDragTrackingLeaveWindow: - // HideDragHilite() - fl_cursor( FL_CURSOR_DEFAULT ); //HideDragHilite( dragRef ); - if ( fl_dnd_target_window ) - { - Fl::handle( FL_DND_LEAVE, fl_dnd_target_window ); - fl_dnd_target_window = 0; - } - breakMacEventLoop(); - return noErr; - } - return noErr; -} - - -/** - * Drag'n'drop receive handler - */ -static pascal OSErr dndReceiveHandler( WindowPtr w, void *userData, DragReference dragRef ) -{ - Point mp; - OSErr ret; - - Fl_Window *target = fl_dnd_target_window = (Fl_Window*)userData; - Fl::first_window(target); - GetDragMouse( dragRef, &mp, 0 ); - Fl::e_x_root = mp.h; - Fl::e_y_root = mp.v; - Fl::e_x = Fl::e_x_root - target->x(); - Fl::e_y = Fl::e_y_root - target->y(); - if ( !Fl::handle( FL_DND_RELEASE, target ) ) - return userCanceledErr; - - ret = fillCurrentDragData(dragRef); - if (ret==userCanceledErr) - return userCanceledErr; - - Fl::e_length = currDragSize; - Fl::e_text = currDragData; -// printf("Sending following text to widget %p:\n%s\n", Fl::belowmouse(), Fl::e_text); - int old_event = Fl::e_number; - Fl::belowmouse()->handle(Fl::e_number = FL_PASTE); - Fl::e_number = old_event; - - if (currDragData) { - free(currDragData); - } - currDragData = 0L; - currDragRef = 0; - Fl::e_text = 0L; - Fl::e_length = 0; - fl_dnd_target_window = 0L; - - breakMacEventLoop(); - return noErr; -} -// fc: -static void q_set_window_title(Window xid, const char * name ) { -#if 1 - CFStringRef utf8_title = CFStringCreateWithCString(NULL, (name ? name : ""), kCFStringEncodingUTF8); - SetWindowTitleWithCFString(xid, utf8_title); - CFRelease(utf8_title); -#else // old non-utf8 code to remove after new utf8 code approval : - Str255 pTitle; - if (name) { - if (strlen(name) > 255) pTitle[0] = 255; - else pTitle[0] = strlen(name); - memcpy(pTitle+1, name, pTitle[0]); - } - else - pTitle[0] = 0; - SetWTitle(xid, pTitle); -#endif -} - -/** - * go ahead, create that (sub)window - * \todo we should make menu windows slightly transparent for the new Mac look - */ -void Fl_X::make(Fl_Window* w) -{ - static int xyPos = 100; - if ( w->parent() ) // create a subwindow - { - Fl_Group::current(0); - Rect wRect; - wRect.top = w->y(); - wRect.left = w->x(); - wRect.bottom = w->y() + w->h(); if (wRect.bottom<=wRect.top) wRect.bottom = wRect.top+1; - wRect.right = w->x() + w->w(); if (wRect.right<=wRect.left) wRect.right = wRect.left+1; - // our subwindow needs this structure to know about its clipping. - Fl_X* x = new Fl_X; - x->other_xid = 0; - x->region = 0; - x->subRegion = 0; - x->cursor = fl_default_cursor; - x->gc = 0; // stay 0 for Quickdraw; fill with CGContext for Quartz - Fl_Window *win = w->window(); - Fl_X *xo = Fl_X::i(win); - if (xo) { - x->xidNext = xo->xidChildren; - x->xidChildren = 0L; - xo->xidChildren = x; - x->xid = fl_xid(win); - x->w = w; w->i = x; - x->wait_for_expose = 0; - x->next = Fl_X::first; // must be in the list for ::flush() - Fl_X::first = x; - int old_event = Fl::e_number; - w->handle(Fl::e_number = FL_SHOW); - Fl::e_number = old_event; - w->redraw(); // force draw to happen - } - fl_show_iconic = 0; - } - else // create a desktop window - { - Fl_Group::current(0); - fl_open_display(); - int winclass = kDocumentWindowClass; - int winattr = kWindowStandardHandlerAttribute | kWindowCloseBoxAttribute | kWindowCollapseBoxAttribute; - int xp = w->x(); - int yp = w->y(); - int wp = w->w(); - int hp = w->h(); - if (w->size_range_set) { - if ( w->minh != w->maxh || w->minw != w->maxw) - winattr |= kWindowFullZoomAttribute | kWindowResizableAttribute | kWindowLiveResizeAttribute; - } else { - if (w->resizable()) { - Fl_Widget *o = w->resizable(); - int minw = o->w(); if (minw > 100) minw = 100; - int minh = o->h(); if (minh > 100) minh = 100; - w->size_range(w->w() - o->w() + minw, w->h() - o->h() + minh, 0, 0); - winattr |= kWindowFullZoomAttribute | kWindowResizableAttribute | kWindowLiveResizeAttribute; - } else { - w->size_range(w->w(), w->h(), w->w(), w->h()); - } - } - int xwm = xp, ywm = yp, bt, bx, by; - - if (!fake_X_wm(w, xwm, ywm, bt, bx, by)) { - // menu windows and tooltips - if (w->modal()||w->override()) { - winclass = kHelpWindowClass; - winattr = 0; - } else { - winattr = 512; // kWindowNoTitleBarAttribute; - } - } else if (w->modal()) { - winclass = kMovableModalWindowClass; - } - - if (by+bt) { - wp += 2*bx; - hp += 2*by+bt; - } - if (!(w->flags() & Fl_Widget::FORCE_POSITION)) { - // use the Carbon functions below for default window positioning - w->x(xyPos+Fl::x()); - w->y(xyPos+Fl::y()); - xyPos += 25; - if (xyPos>200) xyPos = 100; - } else { - if (!Fl::grab()) { - xp = xwm; yp = ywm; - w->x(xp);w->y(yp); - } - xp -= bx; - yp -= by+bt; - } - - if (w->non_modal() && Fl_X::first && !fl_disable_transient_for) { - // find some other window to be "transient for": - Fl_Window* w = Fl_X::first->w; - while (w->parent()) w = w->window(); // todo: this code does not make any sense! (w!=w??) - } - - Rect wRect; - wRect.top = w->y(); - wRect.left = w->x(); - wRect.bottom = w->y() + w->h(); if (wRect.bottom<=wRect.top) wRect.bottom = wRect.top+1; - wRect.right = w->x() + w->w(); if (wRect.right<=wRect.left) wRect.right = wRect.left+1; - - const char *name = w->label(); - - Fl_X* x = new Fl_X; - x->other_xid = 0; // room for doublebuffering image map. On OS X this is only used by overlay windows - x->region = 0; - x->subRegion = 0; - x->cursor = fl_default_cursor; - x->xidChildren = 0; - x->xidNext = 0; - x->gc = 0; - - winattr &= GetAvailableWindowAttributes( winclass ); // make sure that the window will open - CreateNewWindow( winclass, winattr, &wRect, &(x->xid) ); - q_set_window_title(x->xid, name); - MoveWindow(x->xid, wRect.left, wRect.top, 1); // avoid Carbon Bug on old OS - if (w->non_modal() && !w->modal()) { - // Major kludge: this is to have the regular look, but stay above the document windows - SetWindowClass(x->xid, kFloatingWindowClass); - SetWindowActivationScope(x->xid, kWindowActivationScopeAll); - } - if (!(w->flags() & Fl_Widget::FORCE_POSITION)) - { - WindowRef pw = Fl_X::first ? Fl_X::first->xid : 0 ; - if (w->modal()) { - RepositionWindow(x->xid, pw, kWindowAlertPositionOnParentWindowScreen); - } else if (w->non_modal()) { - RepositionWindow(x->xid, pw, kWindowCenterOnParentWindowScreen); - } else { - RepositionWindow(x->xid, pw, kWindowCascadeOnParentWindowScreen); - } - } - x->w = w; w->i = x; - x->wait_for_expose = 1; - x->next = Fl_X::first; - Fl_X::first = x; - { // Install Carbon Event handlers - OSStatus ret; - EventHandlerUPP mousewheelHandler = NewEventHandlerUPP( carbonMousewheelHandler ); // will not be disposed by Carbon... - static EventTypeSpec mousewheelEvents[] = { - { kEventClassMouse, kEventMouseWheelMoved } }; - ret = InstallWindowEventHandler( x->xid, mousewheelHandler, - (int)(sizeof(mousewheelEvents)/sizeof(mousewheelEvents[0])), - mousewheelEvents, w, 0L ); - EventHandlerUPP mouseHandler = NewEventHandlerUPP( carbonMouseHandler ); // will not be disposed by Carbon... - static EventTypeSpec mouseEvents[] = { - { kEventClassMouse, kEventMouseDown }, - { kEventClassMouse, kEventMouseUp }, - { kEventClassMouse, kEventMouseMoved }, - { kEventClassMouse, kEventMouseDragged } }; - ret = InstallWindowEventHandler( x->xid, mouseHandler, 4, mouseEvents, w, 0L ); - - EventHandlerUPP keyboardHandler = NewEventHandlerUPP( carbonKeyboardHandler ); // will not be disposed by Carbon... - static EventTypeSpec keyboardEvents[] = { - { kEventClassKeyboard, kEventRawKeyDown }, - { kEventClassKeyboard, kEventRawKeyRepeat }, - { kEventClassKeyboard, kEventRawKeyUp }, - { kEventClassKeyboard, kEventRawKeyModifiersChanged } }; - ret = InstallWindowEventHandler( x->xid, keyboardHandler, 4, keyboardEvents, w, 0L ); - - EventHandlerUPP textHandler = NewEventHandlerUPP( carbonTextHandler ); // will not be disposed by Carbon... - static EventTypeSpec textEvents[] = { - { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent } }; - ret = InstallWindowEventHandler( x->xid, textHandler, 1, textEvents, w, 0L ); - - EventHandlerUPP windowHandler = NewEventHandlerUPP( carbonWindowHandler ); // will not be disposed by Carbon... - static EventTypeSpec windowEvents[] = { - { kEventClassWindow, kEventWindowDrawContent }, - { kEventClassWindow, kEventWindowShown }, - { kEventClassWindow, kEventWindowHidden }, - { kEventClassWindow, kEventWindowActivated }, - { kEventClassWindow, kEventWindowDeactivated }, - { kEventClassWindow, kEventWindowClose }, - { kEventClassWindow, kEventWindowCollapsed }, - { kEventClassWindow, kEventWindowExpanded }, - { kEventClassWindow, kEventWindowBoundsChanging }, - { kEventClassWindow, kEventWindowBoundsChanged } }; - ret = InstallWindowEventHandler( x->xid, windowHandler, 10, windowEvents, w, 0L ); - ret = InstallTrackingHandler( dndTrackingHandler, x->xid, w ); - ret = InstallReceiveHandler( dndReceiveHandler, x->xid, w ); - } - - if ( ! Fl_X::first->next ) // if this is the first window, we need to bring the application to the front - { - ProcessSerialNumber psn; - OSErr err = GetCurrentProcess( &psn ); - if ( err==noErr ) SetFrontProcess( &psn ); - } - - if (w->size_range_set) w->size_range_(); - - if (winclass != kHelpWindowClass) { - Fl_Tooltip::enter(0); - } - if (w->size_range_set) w->size_range_(); - ShowWindow(x->xid); - if (fl_show_iconic) { - fl_show_iconic = 0; - CollapseWindow( x->xid, true ); // \todo Mac ; untested - } else { - w->set_visible(); - } - - Rect rect; - GetWindowBounds(x->xid, kWindowContentRgn, &rect); - w->x(rect.left); w->y(rect.top); - w->w(rect.right-rect.left); w->h(rect.bottom-rect.top); - - int old_event = Fl::e_number; - w->handle(Fl::e_number = FL_SHOW); - Fl::e_number = old_event; - w->redraw(); // force draw to happen - - if (w->modal()) { Fl::modal_ = w; fl_fix_focus(); } - } -} - - -/** - * Tell the OS what window sizes we want to allow - */ -void Fl_Window::size_range_() { - size_range_set = 1; - HISize minSize = { minw, minh }; - HISize maxSize = { maxw?maxw:32000, maxh?maxh:32000 }; - if (i && i->xid) - SetWindowResizeLimits(i->xid, &minSize, &maxSize); -} - - -/** - * returns pointer to the filename, or null if name ends with ':' - */ -const char *fl_filename_name( const char *name ) -{ - const char *p, *q; - if (!name) return (0); - for ( p = q = name ; *p ; ) - { - if ( ( p[0] == ':' ) && ( p[1] == ':' ) ) - { - q = p+2; - p++; - } - else if (p[0] == '/') - q = p + 1; - p++; - } - return q; -} - - -/** - * set the window title bar - * \todo make the titlebar icon work! - */ -void Fl_Window::label(const char *name,const char */*iname*/) { - Fl_Widget::label(name); - - if (shown() || i) { - q_set_window_title(fl_xid(this), name); - } -} - - -/** - * make a window visible - */ -void Fl_Window::show() { - image(Fl::scheme_bg_); - if (Fl::scheme_bg_) { - labeltype(FL_NORMAL_LABEL); - align(FL_ALIGN_CENTER | FL_ALIGN_INSIDE | FL_ALIGN_CLIP); - } else { - labeltype(FL_NO_LABEL); - } - Fl_Tooltip::exit(this); - if (!shown() || !i) { - Fl_X::make(this); - } else { - if ( !parent() ) - { - if ( IsWindowCollapsed( i->xid ) ) CollapseWindow( i->xid, false ); - if (!fl_capture) { - BringToFront(i->xid); - SelectWindow(i->xid); - } - } - } -} - - -/** - * resize a window - */ -void Fl_Window::resize(int X,int Y,int W,int H) { - if (W<=0) W = 1; // OS X does not like zero width windows - if (H<=0) H = 1; - int is_a_resize = (W != w() || H != h()); -// printf("Fl_Winodw::resize(X=%d, Y=%d, W=%d, H=%d), is_a_resize=%d, resize_from_system=%p, this=%p\n", -// X, Y, W, H, is_a_resize, resize_from_system, this); - if (X != x() || Y != y()) set_flag(FORCE_POSITION); - else if (!is_a_resize) return; - if ( (resize_from_system!=this) && (!parent()) && shown()) { - if (is_a_resize) { - if (resizable()) { - if (W<minw) minw = W; // user request for resize takes priority - if (W>maxw) maxw = W; // over a previously set size_range - if (H<minh) minh = H; - if (H>maxh) maxh = H; - size_range(minw, minh, maxw, maxh); - } else { - size_range(W, H, W, H); - } - Rect dim; dim.left=X; dim.top=Y; dim.right=X+W; dim.bottom=Y+H; - SetWindowBounds(i->xid, kWindowContentRgn, &dim); - Rect all; all.top=-32000; all.bottom=32000; all.left=-32000; all.right=32000; - InvalWindowRect( i->xid, &all ); - } else { - MoveWindow(i->xid, X, Y, 0); - } - } - resize_from_system = 0; - if (is_a_resize) { - Fl_Group::resize(X,Y,W,H); - if (shown()) { - redraw(); - } - } else { - x(X); y(Y); - } -} - - -/** - * make all drawing go into this window (called by subclass flush() impl.) - */ -void Fl_Window::make_current() -{ - OSStatus err; - Fl_X::q_release_context(); - if ( !fl_window_region ) - fl_window_region = NewRgn(); - fl_window = i->xid; - current_ = this; - - SetPort( GetWindowPort(i->xid) ); // \todo check for the handling of doublebuffered windows - - int xp = 0, yp = 0; - Fl_Window *win = this; - while ( win ) - { - if ( !win->window() ) - break; - xp += win->x(); - yp += win->y(); - win = (Fl_Window*)win->window(); - } - SetOrigin( -xp, -yp ); - - SetRectRgn( fl_window_region, 0, 0, w(), h() ); - - // \todo for performance reasons: we don't have to create this unless the child windows moved - for ( Fl_X *cx = i->xidChildren; cx; cx = cx->xidNext ) - { - Fl_Window *cw = cx->w; - if (!cw->visible_r()) continue; - Fl_Region r = NewRgn(); - SetRectRgn( r, cw->x() - xp, cw->y() - yp, - cw->x() + cw->w() - xp, cw->y() + cw->h() - yp ); - DiffRgn( fl_window_region, r, fl_window_region ); - DisposeRgn( r ); - } - - err = QDBeginCGContext(GetWindowPort(i->xid), &i->gc); - if (err!=noErr) - fprintf(stderr, "Error %d in QDBeginCGContext\n", (int)err); - fl_gc = i->gc; - CGContextSaveGState(fl_gc); - Fl_X::q_fill_context(); -#if defined(USE_CAIRO) - if (Fl::cairo_autolink_context()) Fl::cairo_make_current(this); // capture gc changes automatically to update the cairo context adequately -#endif - - fl_clip_region( 0 ); - SetPortClipRegion( GetWindowPort(i->xid), fl_window_region ); - -#if defined(USE_CAIRO) - // update the cairo_t context - if (Fl::cairo_autolink_context()) Fl::cairo_make_current(this); -#endif -} - -// helper function to manage the current CGContext fl_gc -extern Fl_Color fl_color_; -extern class Fl_Font_Descriptor *fl_fontsize; -extern void fl_font(class Fl_Font_Descriptor*); -extern void fl_quartz_restore_line_style_(); - -// FLTK has only one global graphics state. This function copies the FLTK state into the -// current Quartz context -void Fl_X::q_fill_context() { - if (!fl_gc) return; - int hgt = 0; - if (fl_window) { - Rect portRect; - GetPortBounds(GetWindowPort( fl_window ), &portRect); - hgt = portRect.bottom-portRect.top; - } else { - hgt = CGBitmapContextGetHeight(fl_gc); - } - CGContextTranslateCTM(fl_gc, 0.5, hgt-0.5f); - CGContextScaleCTM(fl_gc, 1.0f, -1.0f); - fl_font(fl_fontsize); - fl_color(fl_color_); - fl_quartz_restore_line_style_(); -} - -// The only way to reset clipping to its original state is to pop the current graphics -// state and restore the global state. -void Fl_X::q_clear_clipping() { - if (!fl_gc) return; - CGContextRestoreGState(fl_gc); - CGContextSaveGState(fl_gc); -} - -// Give the Quartz context back to the system -void Fl_X::q_release_context(Fl_X *x) { - if (x && x->gc!=fl_gc) return; - if (!fl_gc) return; - CGContextRestoreGState(fl_gc); - if (fl_window) { - OSStatus err = QDEndCGContext(GetWindowPort(fl_window), &fl_gc); - if (err!=noErr) - fprintf(stderr, "Error %d in QDEndCGContext\n", (int)err); - } - fl_gc = 0; -#if defined(USE_CAIRO) - if (Fl::cairo_autolink_context()) Fl::cairo_make_current((Fl_Window*) 0); // capture gc changes automatically to update the cairo context adequately -#endif -} - -void Fl_X::q_begin_image(CGRect &rect, int cx, int cy, int w, int h) { - CGContextSaveGState(fl_gc); - CGAffineTransform mx = CGContextGetCTM(fl_gc); - CGRect r2 = rect; - r2.origin.x -= 0.5f; - r2.origin.y -= 0.5f; - CGContextClipToRect(fl_gc, r2); - mx.d = -1.0; mx.tx = -mx.tx; - CGContextConcatCTM(fl_gc, mx); - rect.origin.x = -(mx.tx+0.5f) + rect.origin.x - cx; - rect.origin.y = (mx.ty+0.5f) - rect.origin.y - h + cy; - rect.size.width = w; - rect.size.height = h; -} - -void Fl_X::q_end_image() { - CGContextRestoreGState(fl_gc); -} - -//////////////////////////////////////////////////////////////// -// Copy & Paste fltk implementation. -//////////////////////////////////////////////////////////////// - -// fltk 1.3 clipboard support constant definitions: -const CFStringRef flavorNames[] = { - CFSTR("public.utf16-plain-text"), - CFSTR("public.utf8-plain-text"), - CFSTR("com.apple.traditional-mac-plain-text") }; -const CFStringEncoding encodings[] = { - kCFStringEncodingUTF16, - kCFStringEncodingUTF8, - kCFStringEncodingMacRoman}; -const size_t handledFlavorsCount = sizeof(encodings)/sizeof(CFStringEncoding); - -// clipboard variables definitions : -Fl_Widget *fl_selection_requestor = 0; -char *fl_selection_buffer[2]; -int fl_selection_length[2]; -static int fl_selection_buffer_length[2]; - -#ifdef USE_PASTEBOARD -static PasteboardRef myPasteboard = 0; -static void allocatePasteboard() { - if (!myPasteboard) - PasteboardCreate(kPasteboardClipboard, &myPasteboard); -} -#else -#endif - -#ifndef USE_PASTEBOARD -static ScrapRef myScrap = 0; -#endif - -/** - * create a selection - * owner: widget that created the selection - * stuff: pointer to selected data - * size of selected data - */ -void Fl::copy(const char *stuff, int len, int clipboard) { - if (!stuff || len<0) return; - if (len+1 > fl_selection_buffer_length[clipboard]) { - delete[] fl_selection_buffer[clipboard]; - fl_selection_buffer[clipboard] = new char[len+100]; - fl_selection_buffer_length[clipboard] = len+100; - } - memcpy(fl_selection_buffer[clipboard], stuff, len); - fl_selection_buffer[clipboard][len] = 0; // needed for direct paste - fl_selection_length[clipboard] = len; - if (clipboard) { -#ifdef USE_PASTEBOARD - // FIXME no error checking done yet! - allocatePasteboard(); - OSStatus err = PasteboardClear(myPasteboard); - if (err!=noErr) return; // clear did not work, maybe not owner of clipboard. - PasteboardSynchronize(myPasteboard); - CFDataRef text = CFDataCreate(kCFAllocatorDefault, (UInt8*)fl_selection_buffer[1], len); - if (text==NULL) return; // there was a pb creating the object, abort. - err=PasteboardPutItemFlavor(myPasteboard, (PasteboardItemID)1, CFSTR("public.utf8-plain-text"), text, 0); - CFRelease(text); -#else - OSStatus err = ClearCurrentScrap(); // whatever happens we should clear the current scrap. - if(err!=noErr) {myScrap=0; return;} // don't get current scrap if a prev err occured. - err = GetCurrentScrap( &myScrap ); - if ( err != noErr ) { - myScrap = 0; - return; - } - // Previous version changed \n to \r before sending the text, but I would - // prefer to leave the local buffer alone, so a copied buffer may be - // needed. Check to see if this is necessary on OS/X. - PutScrapFlavor( myScrap, kScrapFlavorTypeText, 0, - len, fl_selection_buffer[1] ); -#endif - } -} - -// Call this when a "paste" operation happens: -void Fl::paste(Fl_Widget &receiver, int clipboard) { - if (clipboard) { - // see if we own the selection, if not go get it: - fl_selection_length[1] = 0; -#ifdef USE_PASTEBOARD - OSStatus err = noErr; - Boolean found = false; - CFDataRef flavorData = NULL; - CFStringEncoding encoding = 0; - - allocatePasteboard(); - PasteboardSynchronize(myPasteboard); - ItemCount nFlavor = 0, i, j; - err = PasteboardGetItemCount(myPasteboard, &nFlavor); - if (err==noErr) { - for (i=1; i<=nFlavor; i++) { - PasteboardItemID itemID = 0; - CFArrayRef flavorTypeArray = NULL; - found = false; - err = PasteboardGetItemIdentifier(myPasteboard, i, &itemID); - if (err!=noErr) continue; - err = PasteboardCopyItemFlavors(myPasteboard, itemID, &flavorTypeArray); - if (err!=noErr) { - if (flavorTypeArray) {CFRelease(flavorTypeArray); flavorTypeArray = NULL;} - continue; - } - CFIndex flavorCount = CFArrayGetCount(flavorTypeArray); - for (j = 0; j < handledFlavorsCount; j++) { - for (CFIndex flavorIndex=0; flavorIndex<flavorCount; flavorIndex++) { - CFStringRef flavorType = (CFStringRef)CFArrayGetValueAtIndex(flavorTypeArray, flavorIndex); - if (UTTypeConformsTo(flavorType, flavorNames[j])) { - err = PasteboardCopyItemFlavorData( myPasteboard, itemID, flavorNames[j], &flavorData ); - if(err != noErr) continue; - encoding = encodings[j]; - found = true; - break; - } - } - if(found) break; - } - if (flavorTypeArray) {CFRelease(flavorTypeArray); flavorTypeArray = NULL;} - if (found) break; - } - if(found) { - CFIndex len = CFDataGetLength(flavorData); - CFStringRef mycfs = CFStringCreateWithBytes(NULL, CFDataGetBytePtr(flavorData), len, encoding, false); - CFRelease(flavorData); - len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(mycfs), kCFStringEncodingUTF8) + 1; - if ( len >= fl_selection_buffer_length[1] ) { - fl_selection_buffer_length[1] = len; - delete[] fl_selection_buffer[1]; - fl_selection_buffer[1] = new char[len]; - } - CFStringGetCString(mycfs, fl_selection_buffer[1], len, kCFStringEncodingUTF8); - CFRelease(mycfs); - len = strlen(fl_selection_buffer[1]); - fl_selection_length[1] = len; - convert_crlf(fl_selection_buffer[1],len); // turn all \r characters into \n: - } - } -#else - ScrapRef scrap = 0; - if (GetCurrentScrap(&scrap) == noErr && scrap != myScrap && - GetScrapFlavorSize(scrap, kScrapFlavorTypeText, &len) == noErr) { - if ( len >= fl_selection_buffer_length[1] ) { - fl_selection_buffer_length[1] = len + 32; - delete[] fl_selection_buffer[1]; - fl_selection_buffer[1] = new char[len + 32]; - } - fl_selection_length[1] = len; len++; - GetScrapFlavorData( scrap, kScrapFlavorTypeText, &len, - fl_selection_buffer[1] ); - fl_selection_buffer[1][fl_selection_length[1]] = 0; - convert_crlf(fl_selection_buffer[1],len); - } -#endif - } - Fl::e_text = fl_selection_buffer[clipboard]; - Fl::e_length = fl_selection_length[clipboard]; - if (!Fl::e_text) Fl::e_text = (char *)""; - receiver.handle(FL_PASTE); -} - -void Fl::add_timeout(double time, Fl_Timeout_Handler cb, void* data) -{ - // check, if this timer slot exists already - for (int i = 0; i < mac_timer_used; ++i) { - MacTimeout& t = mac_timers[i]; - // if so, simply change the fire interval - if (t.callback == cb && t.data == data) { - SetEventLoopTimerNextFireTime(t.timer, (EventTimerInterval)time); - t.pending = 1; - return; - } - } - // no existing timer to use. Create a new one: - int timer_id = -1; - // find an empty slot in the timer array - for (int i = 0; i < mac_timer_used; ++i) { - if ( !mac_timers[i].timer ) { - timer_id = i; - break; - } - } - // if there was no empty slot, append a new timer - if (timer_id == -1) { - // make space if needed - if (mac_timer_used == mac_timer_alloc) { - realloc_timers(); - } - timer_id = mac_timer_used++; - } - // now install a brand new timer - MacTimeout& t = mac_timers[timer_id]; - EventTimerInterval fireDelay = (EventTimerInterval)time; - EventLoopTimerUPP timerUPP = NewEventLoopTimerUPP(do_timer); - EventLoopTimerRef timerRef = 0; - OSStatus err = InstallEventLoopTimer(GetMainEventLoop(), fireDelay, 0, timerUPP, data, &timerRef); - if (err == noErr) { - t.callback = cb; - t.data = data; - t.timer = timerRef; - t.upp = timerUPP; - t.pending = 1; - } else { - if (timerRef) - RemoveEventLoopTimer(timerRef); - if (timerUPP) - DisposeEventLoopTimerUPP(timerUPP); - } -} - -void Fl::repeat_timeout(double time, Fl_Timeout_Handler cb, void* data) -{ - // currently, repeat_timeout does not subtract the trigger time of the previous timer event as it should. - add_timeout(time, cb, data); -} - -int Fl::has_timeout(Fl_Timeout_Handler cb, void* data) -{ - for (int i = 0; i < mac_timer_used; ++i) { - MacTimeout& t = mac_timers[i]; - if (t.callback == cb && t.data == data && t.pending) { - return 1; - } - } - return 0; -} - -void Fl::remove_timeout(Fl_Timeout_Handler cb, void* data) -{ - for (int i = 0; i < mac_timer_used; ++i) { - MacTimeout& t = mac_timers[i]; - if (t.callback == cb && ( t.data == data || data == NULL)) { - delete_timer(t); - } - } -} - -int MacUnlinkWindow(Fl_X *ip, Fl_X *start) { - if (!ip) return 0; - if (start) { - Fl_X *pc = start; - while (pc) { - if (pc->xidNext == ip) { - pc->xidNext = ip->xidNext; - return 1; - } - if (pc->xidChildren) { - if (pc->xidChildren == ip) { - pc->xidChildren = ip->xidNext; - return 1; - } - if (MacUnlinkWindow(ip, pc->xidChildren)) - return 1; - } - pc = pc->xidNext; - } - } else { - for ( Fl_X *pc = Fl_X::first; pc; pc = pc->next ) { - if (MacUnlinkWindow(ip, pc)) - return 1; - } - } - return 0; -} - -static void MacRelinkWindow(Fl_X *x, Fl_X *p) { - if (!x || !p) return; - // first, check if 'x' is already registered as a child of 'p' - for (Fl_X *i = p->xidChildren; i; i=i->xidNext) { - if (i == x) return; - } - // now add 'x' as the first child of 'p' - x->xidNext = p->xidChildren; - p->xidChildren = x; -} - -void MacDestroyWindow(Fl_Window *w, WindowPtr p) { - MacUnmapWindow(w, p); - if (w && !w->parent() && p) - DisposeWindow(p); -} - -void MacMapWindow(Fl_Window *w, WindowPtr p) { - if (w && p) - ShowWindow(p); - //+ link to window list - if (w && w->parent()) { - MacRelinkWindow(Fl_X::i(w), Fl_X::i(w->window())); - w->redraw(); - } -} - -void MacUnmapWindow(Fl_Window *w, WindowPtr p) { - if (w && !w->parent() && p) - HideWindow(p); - if (w && Fl_X::i(w)) - MacUnlinkWindow(Fl_X::i(w)); -} -#endif // FL_DOXYGEN - -// -// End of "$Id: Fl_mac.cxx 8864 2011-07-19 04:49:30Z greg.ercolano $". -// diff --git a/src/Fl_win32.cxx b/src/Fl_win32.cxx index fa1fc26..23f1422 100644 --- a/src/Fl_win32.cxx +++ b/src/Fl_win32.cxx @@ -1,5 +1,5 @@ // -// "$Id: Fl_win32.cxx 9624 2012-06-21 08:52:29Z manolo $" +// "$Id: Fl_win32.cxx 10387 2014-10-20 15:14:12Z ossman $" // // WIN32-specific code for the Fast Light Tool Kit (FLTK). // @@ -36,6 +36,7 @@ #include <stdlib.h> #include <sys/types.h> #include <time.h> +#include <signal.h> #ifdef __CYGWIN__ # include <sys/time.h> # include <unistd.h> @@ -59,8 +60,6 @@ #include <ole2.h> #include <shellapi.h> -#include "aimm.h" - // // USE_ASYNC_SELECT - define it if you have WSAAsyncSelect()... // USE_ASYNC_SELECT is OBSOLETED in 1.3 for the following reasons: @@ -83,10 +82,20 @@ for async mode proper operation, not mentioning the side effects... */ +// Internal functions +static void fl_clipboard_notify_target(HWND wnd); +static void fl_clipboard_notify_untarget(HWND wnd); + +// Internal variables static Fl_GDI_Graphics_Driver fl_gdi_driver; static Fl_Display_Device fl_gdi_display(&fl_gdi_driver); Fl_Display_Device *Fl_Display_Device::_display = &fl_gdi_display; // the platform display +static HWND clipboard_wnd = 0; +static HWND next_clipboard_wnd = 0; + +static bool initial_clipboard = true; + // dynamic wsock dll handling api: #if defined(__CYGWIN__) && !defined(SOCKET) # define SOCKET int @@ -120,27 +129,24 @@ static HMODULE get_wsock_mod() { * size and link dependencies. */ static HMODULE s_imm_module = 0; +typedef BOOL (WINAPI* flTypeImmAssociateContextEx)(HWND, HIMC, DWORD); +static flTypeImmAssociateContextEx flImmAssociateContextEx = 0; typedef HIMC (WINAPI* flTypeImmGetContext)(HWND); static flTypeImmGetContext flImmGetContext = 0; typedef BOOL (WINAPI* flTypeImmSetCompositionWindow)(HIMC, LPCOMPOSITIONFORM); static flTypeImmSetCompositionWindow flImmSetCompositionWindow = 0; typedef BOOL (WINAPI* flTypeImmReleaseContext)(HWND, HIMC); static flTypeImmReleaseContext flImmReleaseContext = 0; -typedef BOOL (WINAPI* flTypeImmIsIME)(HKL); -static flTypeImmIsIME flImmIsIME = 0; - -static HMODULE get_imm_module() { - if (!s_imm_module) { - s_imm_module = LoadLibrary("IMM32.DLL"); - if (!s_imm_module) - Fl::fatal("FLTK Lib Error: IMM32.DLL file not found!\n\n" - "Please check your input method manager library accessibility."); - flImmGetContext = (flTypeImmGetContext)GetProcAddress(s_imm_module, "ImmGetContext"); - flImmSetCompositionWindow = (flTypeImmSetCompositionWindow)GetProcAddress(s_imm_module, "ImmSetCompositionWindow"); - flImmReleaseContext = (flTypeImmReleaseContext)GetProcAddress(s_imm_module, "ImmReleaseContext"); - flImmIsIME = (flTypeImmIsIME)GetProcAddress(s_imm_module, "ImmIsIME"); - } - return s_imm_module; + +static void get_imm_module() { + s_imm_module = LoadLibrary("IMM32.DLL"); + if (!s_imm_module) + Fl::fatal("FLTK Lib Error: IMM32.DLL file not found!\n\n" + "Please check your input method manager library accessibility."); + flImmAssociateContextEx = (flTypeImmAssociateContextEx)GetProcAddress(s_imm_module, "ImmAssociateContextEx"); + flImmGetContext = (flTypeImmGetContext)GetProcAddress(s_imm_module, "ImmGetContext"); + flImmSetCompositionWindow = (flTypeImmSetCompositionWindow)GetProcAddress(s_imm_module, "ImmSetCompositionWindow"); + flImmReleaseContext = (flTypeImmReleaseContext)GetProcAddress(s_imm_module, "ImmReleaseContext"); } // USE_TRACK_MOUSE - define NO_TRACK_MOUSE if you don't have @@ -205,6 +211,9 @@ static Fl_Window *track_mouse_win=0; // current TrackMouseEvent() window # define WHEEL_DELTA 120 // according to MSDN. #endif +#ifndef SM_CXPADDEDBORDER +# define SM_CXPADDEDBORDER (92) // STR #3061 +#endif // // WM_FLSELECT is the user-defined message that we get when one of @@ -258,7 +267,9 @@ void fl_set_spot(int font, int size, int X, int Y, int W, int H, Fl_Window *win) Fl_Window* tw = win; while (tw->parent()) tw = tw->window(); // find top level window - get_imm_module(); + if (!tw->shown()) + return; + HIMC himc = flImmGetContext(fl_xid(tw)); if (himc) { @@ -335,7 +346,8 @@ void* Fl::thread_message() { return r; } -IActiveIMMApp *fl_aimm = NULL; +extern int fl_send_system_handlers(void *e); + MSG fl_msg; // This is never called with time_to_wait < 0.0. @@ -400,23 +412,25 @@ int fl_wait(double time_to_wait) { // Execute the message we got, and all other pending messages: // have_message = PeekMessage(&fl_msg, NULL, 0, 0, PM_REMOVE); - have_message = PeekMessageW(&fl_msg, NULL, 0, 0, PM_REMOVE); - if (have_message > 0) { - while (have_message != 0 && have_message != -1) { - if (fl_msg.message == fl_wake_msg) { - // Used for awaking wait() from another thread - thread_message_ = (void*)fl_msg.wParam; - Fl_Awake_Handler func; - void *data; - while (Fl::get_awake_handler_(func, data)==0) { - func(data); - } - } - - TranslateMessage(&fl_msg); - DispatchMessageW(&fl_msg); - have_message = PeekMessageW(&fl_msg, NULL, 0, 0, PM_REMOVE); + while ((have_message = PeekMessageW(&fl_msg, NULL, 0, 0, PM_REMOVE)) > 0) { + if (fl_send_system_handlers(&fl_msg)) + continue; + + // Let applications treat WM_QUIT identical to SIGTERM on *nix + if (fl_msg.message == WM_QUIT) + raise(SIGTERM); + + if (fl_msg.message == fl_wake_msg) { + // Used for awaking wait() from another thread + thread_message_ = (void*)fl_msg.wParam; + Fl_Awake_Handler func; + void *data; + while (Fl::get_awake_handler_(func, data)==0) + func(data); } + + TranslateMessage(&fl_msg); + DispatchMessageW(&fl_msg); } Fl::flush(); @@ -436,6 +450,63 @@ int fl_ready() { return get_wsock_mod() ? s_wsock_select(0,&fdt[0],&fdt[1],&fdt[2],&t) : 0; } +void fl_open_display() { + static char beenHereDoneThat = 0; + + if (beenHereDoneThat) + return; + + beenHereDoneThat = 1; + + OleInitialize(0L); + + get_imm_module(); +} + +class Fl_Win32_At_Exit { +public: + Fl_Win32_At_Exit() { } + ~Fl_Win32_At_Exit() { + fl_free_fonts(); // do some WIN32 cleanup + fl_cleanup_pens(); + OleUninitialize(); + fl_brush_action(1); + fl_cleanup_dc_list(); + // This is actually too late in the cleanup process to remove the + // clipboard notifications, but we have no earlier hook so we try + // to work around it anyway. + if (clipboard_wnd != NULL) + fl_clipboard_notify_untarget(clipboard_wnd); + } +}; +static Fl_Win32_At_Exit win32_at_exit; + +static char im_enabled = 1; + +void Fl::enable_im() { + fl_open_display(); + + Fl_X* i = Fl_X::first; + while (i) { + flImmAssociateContextEx(i->xid, 0, IACE_DEFAULT); + i = i->next; + } + + im_enabled = 1; +} + +void Fl::disable_im() { + fl_open_display(); + + Fl_X* i = Fl_X::first; + while (i) { + flImmAssociateContextEx(i->xid, 0, 0); + i = i->next; + } + + im_enabled = 0; +} + //////////////////////////////////////////////////////////////// int Fl::x() @@ -531,8 +602,39 @@ public: const char* GetValue() const { return(out); } }; +void fl_update_clipboard(void) { + Fl_Window *w1 = Fl::first_window(); + if (!w1) + return; + + HWND hwnd = fl_xid(w1); + + if (!OpenClipboard(hwnd)) + return; + + EmptyClipboard(); + + int utf16_len = fl_utf8toUtf16(fl_selection_buffer[1], + fl_selection_length[1], 0, 0); + + HGLOBAL hMem = GlobalAlloc(GHND, utf16_len * 2 + 2); // moveable and zero'ed mem alloc. + LPVOID memLock = GlobalLock(hMem); + + fl_utf8toUtf16(fl_selection_buffer[1], fl_selection_length[1], + (unsigned short*) memLock, utf16_len + 1); + + GlobalUnlock(hMem); + SetClipboardData(CF_UNICODETEXT, hMem); + + CloseClipboard(); + + // In case Windows managed to lob of a WM_DESTROYCLIPBOARD during + // the above. + fl_i_own_selection[1] = 1; +} + // call this when you create a selection: -void Fl::copy(const char *stuff, int len, int clipboard) { +void Fl::copy(const char *stuff, int len, int clipboard, const char *type) { if (!stuff || len<0) return; // Convert \n -> \r\n (for old apps like Notepad, DOS) @@ -548,35 +650,17 @@ void Fl::copy(const char *stuff, int len, int clipboard) { memcpy(fl_selection_buffer[clipboard], stuff, len); fl_selection_buffer[clipboard][len] = 0; // needed for direct paste fl_selection_length[clipboard] = len; - if (clipboard) { - // set up for "delayed rendering": - if (OpenClipboard(NULL)) { - // if the system clipboard works, use it - int utf16_len = fl_utf8toUtf16(fl_selection_buffer[clipboard], fl_selection_length[clipboard], 0, 0); - EmptyClipboard(); - HGLOBAL hMem = GlobalAlloc(GHND, utf16_len * 2 + 2); // moveable and zero'ed mem alloc. - LPVOID memLock = GlobalLock(hMem); - fl_utf8toUtf16(fl_selection_buffer[clipboard], fl_selection_length[clipboard], (unsigned short*) memLock, utf16_len + 1); - GlobalUnlock(hMem); - SetClipboardData(CF_UNICODETEXT, hMem); - CloseClipboard(); - GlobalFree(hMem); - fl_i_own_selection[clipboard] = 0; - } else { - // only if it fails, instruct paste() to use the internal buffers - fl_i_own_selection[clipboard] = 1; - } - } + fl_i_own_selection[clipboard] = 1; + if (clipboard) + fl_update_clipboard(); } // Call this when a "paste" operation happens: -void Fl::paste(Fl_Widget &receiver, int clipboard) { - if (!clipboard || fl_i_own_selection[clipboard]) { +void Fl::paste(Fl_Widget &receiver, int clipboard, const char *type) { + if (!clipboard || (fl_i_own_selection[clipboard] && strcmp(type, Fl::clipboard_plain_text) == 0)) { // We already have it, do it quickly without window server. // Notice that the text is clobbered if set_selection is // called in response to FL_PASTE! - - // Convert \r\n -> \n char *i = fl_selection_buffer[clipboard]; if (i==0L) { Fl::e_text = 0; @@ -584,43 +668,209 @@ void Fl::paste(Fl_Widget &receiver, int clipboard) { } Fl::e_text = new char[fl_selection_length[clipboard]+1]; char *o = Fl::e_text; - while (*i) { + while (*i) { // Convert \r\n -> \n if ( *i == '\r' && *(i+1) == '\n') i++; else *o++ = *i++; } *o = 0; Fl::e_length = (int) (o - Fl::e_text); + Fl::e_clipboard_type = Fl::clipboard_plain_text; receiver.handle(FL_PASTE); delete [] Fl::e_text; Fl::e_text = 0; - } else { + } else if (clipboard) { + HANDLE h; if (!OpenClipboard(NULL)) return; - HANDLE h = GetClipboardData(CF_UNICODETEXT); - if (h) { - wchar_t *memLock = (wchar_t*) GlobalLock(h); - size_t utf16_len = wcslen(memLock); - Fl::e_text = (char*) malloc (utf16_len * 4 + 1); - unsigned utf8_len = fl_utf8fromwc(Fl::e_text, (unsigned) (utf16_len * 4), memLock, (unsigned) utf16_len); - *(Fl::e_text + utf8_len) = 0; - LPSTR a,b; - a = b = Fl::e_text; - while (*a) { // strip the CRLF pairs ($%$#@^) - if (*a == '\r' && a[1] == '\n') a++; - else *b++ = *a++; + if (strcmp(type, Fl::clipboard_plain_text) == 0) { // we want plain text from clipboard + if ((h = GetClipboardData(CF_UNICODETEXT))) { // there's text in the clipboard + wchar_t *memLock = (wchar_t*) GlobalLock(h); + size_t utf16_len = wcslen(memLock); + Fl::e_text = new char[utf16_len * 4 + 1]; + unsigned utf8_len = fl_utf8fromwc(Fl::e_text, (unsigned) (utf16_len * 4), memLock, (unsigned) utf16_len); + *(Fl::e_text + utf8_len) = 0; + GlobalUnlock(h); + LPSTR a,b; + a = b = Fl::e_text; + while (*a) { // strip the CRLF pairs ($%$#@^) + if (*a == '\r' && a[1] == '\n') a++; + else *b++ = *a++; + } + *b = 0; + Fl::e_length = (int) (b - Fl::e_text); + Fl::e_clipboard_type = Fl::clipboard_plain_text; // indicates that the paste event is for plain UTF8 text + receiver.handle(FL_PASTE); // send the FL_PASTE event to the widget + delete[] Fl::e_text; + Fl::e_text = 0; + } + } + else if (strcmp(type, Fl::clipboard_image) == 0) { // we want an image from clipboard + uchar *rgb = NULL; + int width, height, depth; + if ( (h = GetClipboardData(CF_DIB)) ) { // if there's a DIB in clipboard + LPBITMAPINFO lpBI = (LPBITMAPINFO)GlobalLock(h) ; + width = lpBI->bmiHeader.biWidth; // bitmap width & height + height = lpBI->bmiHeader.biHeight; + if ( (lpBI->bmiHeader.biBitCount == 24 || lpBI->bmiHeader.biBitCount == 32) && + lpBI->bmiHeader.biCompression == BI_RGB && + lpBI->bmiHeader.biClrUsed == 0) { // direct use of the DIB data if it's RGB or RGBA + int linewidth; // row length + depth = lpBI->bmiHeader.biBitCount/8; // 3 or 4 + if (depth == 3) linewidth = 4 * ((3*width + 3)/4); // row length: series of groups of 3 bytes, rounded to multiple of 4 bytes + else linewidth = 4*width; + rgb = new uchar[width * height * depth]; // will hold the image data + uchar *p = rgb, *r, rr, gg, bb; + for (int i=height-1; i>=0; i--) { // for each row, from last to first + r = (uchar*)(lpBI->bmiColors) + i*linewidth; // beginning of pixel data for the ith row + for (int j=0; j<width; j++) { // for each pixel in a row + bb = *r++; // BGR is in DIB + gg = *r++; + rr = *r++; + *p++ = rr; // we want RGB + *p++ = gg; + *p++ = bb; + if (depth == 4) *p++ = *r++; // copy alpha if present + } + } + } + else { // the system will decode a complex DIB + void *pDIBBits = (void*)(lpBI->bmiColors); + if (lpBI->bmiHeader.biCompression == BI_BITFIELDS) pDIBBits = (void*)(lpBI->bmiColors + 3); + else if (lpBI->bmiHeader.biClrUsed > 0) pDIBBits = (void*)(lpBI->bmiColors + lpBI->bmiHeader.biClrUsed); + Fl_Offscreen off = fl_create_offscreen(width, height); + fl_begin_offscreen(off); + SetDIBitsToDevice(fl_gc, 0, 0, width, height, 0, 0, 0, height, pDIBBits, lpBI, DIB_RGB_COLORS); + rgb = fl_read_image(NULL, 0, 0, width, height); + depth = 3; + fl_end_offscreen(); + fl_delete_offscreen(off); + } + GlobalUnlock(h); + } + else if ((h = GetClipboardData(CF_ENHMETAFILE))) { // if there's an enhanced metafile in clipboard + ENHMETAHEADER header; + GetEnhMetaFileHeader((HENHMETAFILE)h, sizeof(header), &header); // get structure containing metafile dimensions + width = (header.rclFrame.right - header.rclFrame.left + 1); // in .01 mm units + height = (header.rclFrame.bottom - header.rclFrame.top + 1); + HDC hdc = GetDC(NULL); // get unit correspondance between .01 mm and screen pixels + int hmm = GetDeviceCaps(hdc, HORZSIZE); + int hdots = GetDeviceCaps(hdc, HORZRES); + int vmm = GetDeviceCaps(hdc, VERTSIZE); + int vdots = GetDeviceCaps(hdc, VERTRES); + ReleaseDC(NULL, hdc); + float factorw = (100. * hmm) / hdots; + float factorh = (100. * vmm) / vdots + 0.5; + width /= factorw; height /= factorh; // convert to screen pixel unit + RECT rect = {0, 0, width, height}; + Fl_Offscreen off = fl_create_offscreen(width, height); + fl_begin_offscreen(off); + fl_color(FL_WHITE); fl_rectf(0,0,width, height); // draw white background + PlayEnhMetaFile(fl_gc, (HENHMETAFILE)h, &rect); // draw metafile to offscreen buffer + rgb = fl_read_image(NULL, 0, 0, width, height); // read pixels from offscreen buffer + depth = 3; + fl_end_offscreen(); + fl_delete_offscreen(off); + } + if (rgb) { + Fl_RGB_Image *image = new Fl_RGB_Image(rgb, width, height, depth); // create new image from pixel data + image->alloc_array = 1; + Fl::e_clipboard_data = image; + Fl::e_clipboard_type = Fl::clipboard_image; // indicates that the paste event is for image data + int done = receiver.handle(FL_PASTE); // send FL_PASTE event to widget + Fl::e_clipboard_type = ""; + if (done == 0) { // if widget did not handle the event, delete the image + Fl::e_clipboard_data = NULL; + delete image; + } + } } - *b = 0; - Fl::e_length = (int) (b - Fl::e_text); - receiver.handle(FL_PASTE); - GlobalUnlock(h); - free(Fl::e_text); - Fl::e_text = 0; + CloseClipboard(); + } +} + +int Fl::clipboard_contains(const char *type) +{ + int retval = 0; + if (!OpenClipboard(NULL)) return 0; + if (strcmp(type, Fl::clipboard_plain_text) == 0 || type[0] == 0) { + retval = IsClipboardFormatAvailable(CF_UNICODETEXT); + } + else if (strcmp(type, Fl::clipboard_image) == 0) { + retval = IsClipboardFormatAvailable(CF_DIB) || IsClipboardFormatAvailable(CF_ENHMETAFILE); + } + CloseClipboard(); + return retval; +} + +static void fl_clipboard_notify_target(HWND wnd) { + if (clipboard_wnd) + return; + + // We get one fake WM_DRAWCLIPBOARD immediately, which we therefore + // need to ignore. + initial_clipboard = true; + + clipboard_wnd = wnd; + next_clipboard_wnd = SetClipboardViewer(wnd); +} + +static void fl_clipboard_notify_untarget(HWND wnd) { + if (wnd != clipboard_wnd) + return; + + // We might be called late in the cleanup where Windows has already + // implicitly destroyed our clipboard window. At that point we need + // to do some extra work to manually repair the clipboard chain. + if (IsWindow(wnd)) + ChangeClipboardChain(wnd, next_clipboard_wnd); + else { + HWND tmp, head; + + tmp = CreateWindow("STATIC", "Temporary FLTK Clipboard Window", 0, + 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL); + if (tmp == NULL) + return; + + head = SetClipboardViewer(tmp); + if (head == NULL) + ChangeClipboardChain(tmp, next_clipboard_wnd); + else { + SendMessage(head, WM_CHANGECBCHAIN, (WPARAM)wnd, (LPARAM)next_clipboard_wnd); + ChangeClipboardChain(tmp, head); } - CloseClipboard(); + + DestroyWindow(tmp); + } + + clipboard_wnd = next_clipboard_wnd = 0; +} + +void fl_clipboard_notify_retarget(HWND wnd) { + // The given window is getting destroyed. If it's part of the + // clipboard chain then we need to unregister it and find a + // replacement window. + if (wnd != clipboard_wnd) + return; + + fl_clipboard_notify_untarget(wnd); + + if (Fl::first_window()) + fl_clipboard_notify_target(fl_xid(Fl::first_window())); +} + +void fl_clipboard_notify_change() { + // untarget clipboard monitor if no handlers are registered + if (clipboard_wnd != NULL && fl_clipboard_notify_empty()) { + fl_clipboard_notify_untarget(clipboard_wnd); + return; } + + // if there are clipboard notify handlers but no window targeted + // target first window if available + if (clipboard_wnd == NULL && Fl::first_window()) + fl_clipboard_notify_target(fl_xid(Fl::first_window())); } //////////////////////////////////////////////////////////////// -char fl_is_ime = 0; void fl_get_codepage() { HKL hkl = GetKeyboardLayout(0); @@ -628,14 +878,7 @@ void fl_get_codepage() GetLocaleInfo (LOWORD(hkl), LOCALE_IDEFAULTANSICODEPAGE, ld, 6); DWORD ccp = atol(ld); - fl_is_ime = 0; - fl_codepage = ccp; - if (fl_aimm) { - fl_aimm->GetCodePageA(GetKeyboardLayout(0), &fl_codepage); - } else if (get_imm_module() && flImmIsIME(hkl)) { - fl_is_ime = 1; - } } HWND fl_capture; @@ -856,7 +1099,6 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar case WM_CLOSE: // user clicked close box Fl::handle(FL_CLOSE, window); - PostQuitMessage(0); return 0; case WM_SYNCPAINT : @@ -942,6 +1184,10 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar break; case WM_SETFOCUS: + if ((Fl::modal_) && (Fl::modal_ != window)) { + SetFocus(fl_xid(Fl::modal_)); + return 0; + } Fl::handle(FL_FOCUS, window); break; @@ -1191,38 +1437,31 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar fl_i_own_selection[1] = 0; return 1; - case WM_RENDERALLFORMATS: - fl_i_own_selection[1] = 0; - // Windoze seems unhappy unless I do these two steps. Documentation - // seems to vary on whether opening the clipboard is necessary or - // is in fact wrong: - CloseClipboard(); - OpenClipboard(NULL); - // fall through... - case WM_RENDERFORMAT: { - HANDLE h; - -// int l = fl_utf_nb_char((unsigned char*)fl_selection_buffer[1], fl_selection_length[1]); - int l = fl_utf8toUtf16(fl_selection_buffer[1], fl_selection_length[1], NULL, 0); // Pass NULL buffer to query length required - h = GlobalAlloc(GHND, (l+1) * sizeof(unsigned short)); - if (h) { - unsigned short *g = (unsigned short*) GlobalLock(h); -// fl_utf2unicode((unsigned char *)fl_selection_buffer[1], fl_selection_length[1], (xchar*)g); - l = fl_utf8toUtf16(fl_selection_buffer[1], fl_selection_length[1], g, (l+1)); - g[l] = 0; - GlobalUnlock(h); - SetClipboardData(CF_UNICODETEXT, h); - } - - // Windoze also seems unhappy if I don't do this. Documentation very - // unclear on what is correct: - if (fl_msg.message == WM_RENDERALLFORMATS) CloseClipboard(); - return 1;} case WM_DISPLAYCHANGE: // occurs when screen configuration (number, position) changes Fl::call_screen_init(); Fl::handle(FL_SCREEN_CONFIGURATION_CHANGED, NULL); return 0; + case WM_CHANGECBCHAIN: + if ((hWnd == clipboard_wnd) && (next_clipboard_wnd == (HWND)wParam)) + next_clipboard_wnd = (HWND)lParam; + else + SendMessage(next_clipboard_wnd, WM_CHANGECBCHAIN, wParam, lParam); + return 0; + + case WM_DRAWCLIPBOARD: + // When the clipboard moves between two FLTK windows, + // fl_i_own_selection will temporarily be false as we are + // processing this message. Hence the need to use fl_find(). + if (!initial_clipboard && !fl_find(GetClipboardOwner())) + fl_trigger_clipboard_notify(1); + initial_clipboard = false; + + if (next_clipboard_wnd) + SendMessage(next_clipboard_wnd, WM_DRAWCLIPBOARD, wParam, lParam); + + return 0; + default: if (Fl::handle(0,0)) return 0; break; @@ -1290,13 +1529,17 @@ int Fl_X::fake_X_wm(const Fl_Window* w,int &X,int &Y, int &bt,int &bx, int &by) if (fallback) { if (w->border() && !w->parent()) { if (w->size_range_set && (w->maxw != w->minw || w->maxh != w->minh)) { - ret = 2; - bx = GetSystemMetrics(SM_CXSIZEFRAME); - by = GetSystemMetrics(SM_CYSIZEFRAME); + ret = 2; + bx = GetSystemMetrics(SM_CXSIZEFRAME); + by = GetSystemMetrics(SM_CYSIZEFRAME); } else { - ret = 1; - bx = GetSystemMetrics(SM_CXFIXEDFRAME); - by = GetSystemMetrics(SM_CYFIXEDFRAME); + ret = 1; + int padding = GetSystemMetrics(SM_CXPADDEDBORDER); + NONCLIENTMETRICS ncm; + ncm.cbSize = sizeof(NONCLIENTMETRICS); + SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0); + bx = GetSystemMetrics(SM_CXFIXEDFRAME) + (padding ? padding + ncm.iBorderWidth : 0); + by = GetSystemMetrics(SM_CYFIXEDFRAME) + (padding ? padding + ncm.iBorderWidth : 0); } bt = GetSystemMetrics(SM_CYCAPTION); } @@ -1333,7 +1576,6 @@ int Fl_X::fake_X_wm(const Fl_Window* w,int &X,int &Y, int &bt,int &bx, int &by) Y+=yoff; if (w->fullscreen_active()) { - X = Y = 0; bx = by = bt = 0; } @@ -1387,19 +1629,42 @@ void Fl_Window::resize(int X,int Y,int W,int H) { } } -static void make_fullscreen(Fl_Window *w, Window xid, int X, int Y, int W, int H) { +void Fl_X::make_fullscreen(int X, int Y, int W, int H) { + int top, bottom, left, right; int sx, sy, sw, sh; - Fl::screen_xywh(sx, sy, sw, sh, X, Y, W, H); + + top = w->fullscreen_screen_top; + bottom = w->fullscreen_screen_bottom; + left = w->fullscreen_screen_left; + right = w->fullscreen_screen_right; + + if ((top < 0) || (bottom < 0) || (left < 0) || (right < 0)) { + top = Fl::screen_num(X, Y, W, H); + bottom = top; + left = top; + right = top; + } + + Fl::screen_xywh(sx, sy, sw, sh, top); + Y = sy; + Fl::screen_xywh(sx, sy, sw, sh, bottom); + H = sy + sh - Y; + Fl::screen_xywh(sx, sy, sw, sh, left); + X = sx; + Fl::screen_xywh(sx, sy, sw, sh, right); + W = sx + sw - X; + DWORD flags = GetWindowLong(xid, GWL_STYLE); flags = flags & ~(WS_THICKFRAME|WS_CAPTION); SetWindowLong(xid, GWL_STYLE, flags); + // SWP_NOSENDCHANGING is so that we can override size limits - SetWindowPos(xid, HWND_TOP, sx, sy, sw, sh, SWP_NOSENDCHANGING | SWP_FRAMECHANGED); + SetWindowPos(xid, HWND_TOP, X, Y, W, H, SWP_NOSENDCHANGING | SWP_FRAMECHANGED); } void Fl_Window::fullscreen_x() { _set_fullscreen(); - make_fullscreen(this, fl_xid(this), x(), y(), w(), h()); + i->make_fullscreen(x(), y(), w(), h()); Fl::handle(FL_FULLSCREEN, this); } @@ -1477,13 +1742,14 @@ void fl_fix_focus(); // in Fl.cxx char fl_show_iconic; // hack for Fl_Window::iconic() // int fl_background_pixel = -1; // color to use for background -HCURSOR fl_default_cursor; UINT fl_wake_msg = 0; int fl_disable_transient_for; // secret method of removing TRANSIENT_FOR Fl_X* Fl_X::make(Fl_Window* w) { Fl_Group::current(0); // get rid of very common user bug: forgot end() + fl_open_display(); + // if the window is a subwindow and our parent is not mapped yet, we // mark this window visible, so that mapping the parent at a later // point in time will call this function again to finally map the subwindow. @@ -1526,7 +1792,7 @@ Fl_X* Fl_X::make(Fl_Window* w) { if (!w->icon()) w->icon((void *)LoadIcon(NULL, IDI_APPLICATION)); wcw.hIcon = wcw.hIconSm = (HICON)w->icon(); - wcw.hCursor = fl_default_cursor = LoadCursor(NULL, IDC_ARROW); + wcw.hCursor = LoadCursor(NULL, IDC_ARROW); //uchar r,g,b; Fl::get_color(FL_GRAY,r,g,b); //wc.hbrBackground = (HBRUSH)CreateSolidBrush(RGB(r,g,b)); wcw.hbrBackground = NULL; @@ -1618,7 +1884,8 @@ Fl_X* Fl_X::make(Fl_Window* w) { x->setwindow(w); x->region = 0; x->private_dc = 0; - x->cursor = fl_default_cursor; + x->cursor = LoadCursor(NULL, IDC_ARROW); + x->custom_cursor = 0; if (!fl_codepage) fl_get_codepage(); WCHAR *lab = NULL; @@ -1644,6 +1911,11 @@ Fl_X* Fl_X::make(Fl_Window* w) { ); if (lab) free(lab); + x->next = Fl_X::first; + Fl_X::first = x; + + x->set_icons(); + if (w->fullscreen_active()) { /* We need to make sure that the fullscreen is created on the default monitor, ie the desktop where the shortcut is located @@ -1652,12 +1924,14 @@ Fl_X* Fl_X::make(Fl_Window* w) { monitor the window was placed on. */ RECT rect; GetWindowRect(x->xid, &rect); - make_fullscreen(w, x->xid, rect.left, rect.top, - rect.right - rect.left, rect.bottom - rect.top); + x->make_fullscreen(rect.left, rect.top, + rect.right - rect.left, rect.bottom - rect.top); } - x->next = Fl_X::first; - Fl_X::first = x; + // Setup clipboard monitor target if there are registered handlers and + // no window is targeted. + if (!fl_clipboard_notify_empty() && clipboard_wnd == NULL) + fl_clipboard_notify_target(x->xid); x->wait_for_expose = 1; if (fl_show_iconic) {showit = 0; fl_show_iconic = 0;} @@ -1668,24 +1942,22 @@ Fl_X* Fl_X::make(Fl_Window* w) { Fl::e_number = old_event; w->redraw(); // force draw to happen } + + // Needs to be done before ShowWindow() to get the correct behaviour + // when we get WM_SETFOCUS. + if (w->modal()) {Fl::modal_ = w; fl_fix_focus();} + // If we've captured the mouse, we dont want to activate any // other windows from the code, or we lose the capture. ShowWindow(x->xid, !showit ? SW_SHOWMINNOACTIVE : (Fl::grab() || (styleEx & WS_EX_TOOLWINDOW)) ? SW_SHOWNOACTIVATE : SW_SHOWNORMAL); // Register all windows for potential drag'n'drop operations - fl_OleInitialize(); RegisterDragDrop(x->xid, flIDropTarget); - if (!fl_aimm) { - CoCreateInstance(CLSID_CActiveIMM, NULL, CLSCTX_INPROC_SERVER, - IID_IActiveIMMApp, (void**) &fl_aimm); - if (fl_aimm) { - fl_aimm->Activate(TRUE); - } - } + if (!im_enabled) + flImmAssociateContextEx(x->xid, 0, 0); - if (w->modal()) {Fl::modal_ = w; fl_fix_focus();} return x; } @@ -1867,6 +2139,329 @@ void Fl_Window::label(const char *name,const char *iname) { } //////////////////////////////////////////////////////////////// + +static HICON image_to_icon(const Fl_RGB_Image *image, bool is_icon, + int hotx, int hoty) { + BITMAPV5HEADER bi; + HBITMAP bitmap, mask; + DWORD *bits; + HICON icon; + + if (!is_icon) { + if ((hotx < 0) || (hotx >= image->w())) + return NULL; + if ((hoty < 0) || (hoty >= image->h())) + return NULL; + } + + memset(&bi, 0, sizeof(BITMAPV5HEADER)); + + bi.bV5Size = sizeof(BITMAPV5HEADER); + bi.bV5Width = image->w(); + bi.bV5Height = -image->h(); // Negative for top-down + bi.bV5Planes = 1; + bi.bV5BitCount = 32; + bi.bV5Compression = BI_BITFIELDS; + bi.bV5RedMask = 0x00FF0000; + bi.bV5GreenMask = 0x0000FF00; + bi.bV5BlueMask = 0x000000FF; + bi.bV5AlphaMask = 0xFF000000; + + HDC hdc; + + hdc = GetDC(NULL); + bitmap = CreateDIBSection(hdc, (BITMAPINFO*)&bi, DIB_RGB_COLORS, (void**)&bits, NULL, 0); + ReleaseDC(NULL, hdc); + + if (bits == NULL) + return NULL; + + const uchar *i = (const uchar*)*image->data(); + for (int y = 0;y < image->h();y++) { + for (int x = 0;x < image->w();x++) { + switch (image->d()) { + case 1: + *bits = (0xff<<24) | (i[0]<<16) | (i[0]<<8) | i[0]; + break; + case 2: + *bits = (i[1]<<24) | (i[0]<<16) | (i[0]<<8) | i[0]; + break; + case 3: + *bits = (0xff<<24) | (i[0]<<16) | (i[1]<<8) | i[2]; + break; + case 4: + *bits = (i[3]<<24) | (i[0]<<16) | (i[1]<<8) | i[2]; + break; + } + i += image->d(); + bits++; + } + i += image->ld(); + } + + // A mask bitmap is still needed even though it isn't used + mask = CreateBitmap(image->w(),image->h(),1,1,NULL); + if (mask == NULL) { + DeleteObject(bitmap); + return NULL; + } + + ICONINFO ii; + + ii.fIcon = is_icon; + ii.xHotspot = hotx; + ii.yHotspot = hoty; + ii.hbmMask = mask; + ii.hbmColor = bitmap; + + icon = CreateIconIndirect(&ii); + + DeleteObject(bitmap); + DeleteObject(mask); + + if (icon == NULL) + return NULL; + + return icon; +} + +//////////////////////////////////////////////////////////////// + +static HICON default_big_icon = NULL; +static HICON default_small_icon = NULL; + +static const Fl_RGB_Image *find_best_icon(int ideal_width, + const Fl_RGB_Image *icons[], + int count) { + const Fl_RGB_Image *best; + + best = NULL; + + for (int i = 0;i < count;i++) { + if (best == NULL) + best = icons[i]; + else { + if (best->w() < ideal_width) { + if (icons[i]->w() > best->w()) + best = icons[i]; + } else { + if ((icons[i]->w() >= ideal_width) && + (icons[i]->w() < best->w())) + best = icons[i]; + } + } + } + + return best; +} + +void Fl_X::set_default_icons(const Fl_RGB_Image *icons[], int count) { + const Fl_RGB_Image *best_big, *best_small; + + if (default_big_icon != NULL) + DestroyIcon(default_big_icon); + if (default_small_icon != NULL) + DestroyIcon(default_small_icon); + + default_big_icon = NULL; + default_small_icon = NULL; + + best_big = find_best_icon(GetSystemMetrics(SM_CXICON), icons, count); + best_small = find_best_icon(GetSystemMetrics(SM_CXSMICON), icons, count); + + if (best_big != NULL) + default_big_icon = image_to_icon(best_big, true, 0, 0); + + if (best_small != NULL) + default_small_icon = image_to_icon(best_small, true, 0, 0); +} + +void Fl_X::set_default_icons(HICON big_icon, HICON small_icon) { + if (default_big_icon != NULL) + DestroyIcon(default_big_icon); + if (default_small_icon != NULL) + DestroyIcon(default_small_icon); + + default_big_icon = NULL; + default_small_icon = NULL; + + if (big_icon != NULL) + default_big_icon = CopyIcon(big_icon); + if (small_icon != NULL) + default_small_icon = CopyIcon(small_icon); +} + +void Fl_X::set_icons() { + HICON big_icon, small_icon; + + // Windows doesn't copy the icons, so we have to "leak" them when + // setting, and clean up when we change to some other icons. + big_icon = (HICON)SendMessage(xid, WM_GETICON, ICON_BIG, 0); + if ((big_icon != NULL) && (big_icon != default_big_icon)) + DestroyIcon(big_icon); + small_icon = (HICON)SendMessage(xid, WM_GETICON, ICON_SMALL, 0); + if ((small_icon != NULL) && (small_icon != default_small_icon)) + DestroyIcon(small_icon); + + big_icon = NULL; + small_icon = NULL; + + if (w->icon_->count) { + const Fl_RGB_Image *best_big, *best_small; + + best_big = find_best_icon(GetSystemMetrics(SM_CXICON), + (const Fl_RGB_Image **)w->icon_->icons, + w->icon_->count); + best_small = find_best_icon(GetSystemMetrics(SM_CXSMICON), + (const Fl_RGB_Image **)w->icon_->icons, + w->icon_->count); + + if (best_big != NULL) + big_icon = image_to_icon(best_big, true, 0, 0); + if (best_small != NULL) + small_icon = image_to_icon(best_small, true, 0, 0); + } else { + if ((w->icon_->big_icon != NULL) || (w->icon_->small_icon != NULL)) { + big_icon = w->icon_->big_icon; + small_icon = w->icon_->small_icon; + } else { + big_icon = default_big_icon; + small_icon = default_small_icon; + } + } + + SendMessage(xid, WM_SETICON, ICON_BIG, (LPARAM)big_icon); + SendMessage(xid, WM_SETICON, ICON_SMALL, (LPARAM)small_icon); +} + +/** Sets the default window icons. + + Convenience function to set the default icons using Windows' + native HICON icon handles. + + The given icons are copied. You can free the icons immediately after + this call. + + \param[in] big_icon default large icon for all windows + subsequently created + \param[in] small_icon default small icon for all windows + subsequently created + + \see Fl_Window::default_icon(const Fl_RGB_Image *) + \see Fl_Window::default_icons(const Fl_RGB_Image *[], int) + \see Fl_Window::icon(const Fl_RGB_Image *) + \see Fl_Window::icons(const Fl_RGB_Image *[], int) + \see Fl_Window::icons(HICON, HICON) + */ +void Fl_Window::default_icons(HICON big_icon, HICON small_icon) { + Fl_X::set_default_icons(big_icon, small_icon); +} + +/** Sets the window icons. + + Convenience function to set this window's icons using Windows' + native HICON icon handles. + + The given icons are copied. You can free the icons immediately after + this call. + + \param[in] big_icon large icon for this window + \param[in] small_icon small icon for this windows + + \see Fl_Window::default_icon(const Fl_RGB_Image *) + \see Fl_Window::default_icons(const Fl_RGB_Image *[], int) + \see Fl_Window::default_icons(HICON, HICON) + \see Fl_Window::icon(const Fl_RGB_Image *) + \see Fl_Window::icons(const Fl_RGB_Image *[], int) + */ +void Fl_Window::icons(HICON big_icon, HICON small_icon) { + free_icons(); + + if (big_icon != NULL) + icon_->big_icon = CopyIcon(big_icon); + if (small_icon != NULL) + icon_->small_icon = CopyIcon(small_icon); + + if (i) + i->set_icons(); +} + +//////////////////////////////////////////////////////////////// + +#ifndef IDC_HAND +# define IDC_HAND MAKEINTRESOURCE(32649) +#endif // !IDC_HAND + +int Fl_X::set_cursor(Fl_Cursor c) { + LPSTR n; + HCURSOR new_cursor; + + if (c == FL_CURSOR_NONE) + new_cursor = NULL; + else { + switch (c) { + case FL_CURSOR_ARROW: n = IDC_ARROW; break; + case FL_CURSOR_CROSS: n = IDC_CROSS; break; + case FL_CURSOR_WAIT: n = IDC_WAIT; break; + case FL_CURSOR_INSERT: n = IDC_IBEAM; break; + case FL_CURSOR_HAND: n = IDC_HAND; break; + case FL_CURSOR_HELP: n = IDC_HELP; break; + case FL_CURSOR_MOVE: n = IDC_SIZEALL; break; + case FL_CURSOR_N: + case FL_CURSOR_S: + // FIXME: Should probably have fallbacks for these instead + case FL_CURSOR_NS: n = IDC_SIZENS; break; + case FL_CURSOR_NE: + case FL_CURSOR_SW: + // FIXME: Dito. + case FL_CURSOR_NESW: n = IDC_SIZENESW; break; + case FL_CURSOR_E: + case FL_CURSOR_W: + // FIXME: Dito. + case FL_CURSOR_WE: n = IDC_SIZEWE; break; + case FL_CURSOR_SE: + case FL_CURSOR_NW: + // FIXME: Dito. + case FL_CURSOR_NWSE: n = IDC_SIZENWSE; break; + default: + return 0; + } + + new_cursor = LoadCursor(NULL, n); + if (new_cursor == NULL) + return 0; + } + + if ((cursor != NULL) && custom_cursor) + DestroyIcon(cursor); + + cursor = new_cursor; + custom_cursor = 0; + + SetCursor(cursor); + + return 1; +} + +int Fl_X::set_cursor(const Fl_RGB_Image *image, int hotx, int hoty) { + HCURSOR new_cursor; + + new_cursor = image_to_icon(image, false, hotx, hoty); + if (new_cursor == NULL) + return 0; + + if ((cursor != NULL) && custom_cursor) + DestroyIcon(cursor); + + cursor = new_cursor; + custom_cursor = 1; + + SetCursor(cursor); + + return 1; +} + +//////////////////////////////////////////////////////////////// // Implement the virtual functions for the base Fl_Window class: // If the box is a filled rectangle, we can make the redisplay *look* @@ -2166,5 +2761,5 @@ void preparePrintFront(void) #endif // FL_DOXYGEN // -// End of "$Id: Fl_win32.cxx 9624 2012-06-21 08:52:29Z manolo $". +// End of "$Id: Fl_win32.cxx 10387 2014-10-20 15:14:12Z ossman $". // diff --git a/src/Fl_x.cxx b/src/Fl_x.cxx index 5d8a8af..11d1b2f 100644 --- a/src/Fl_x.cxx +++ b/src/Fl_x.cxx @@ -1,5 +1,5 @@ // -// "$Id: Fl_x.cxx 9699 2012-10-16 15:35:34Z manolo $" +// "$Id: Fl_x.cxx 10412 2014-10-29 20:25:46Z cand $" // // X specific code for the Fast Light Tool Kit (FLTK). // @@ -19,7 +19,7 @@ #ifdef WIN32 //# include "Fl_win32.cxx" #elif defined(__APPLE__) -//# include "Fl_mac.cxx" +//# include "Fl_mac.cxx" // now Fl_cocoa.mm #elif !defined(FL_DOXYGEN) # define CONSOLIDATE_MOTION 1 @@ -34,15 +34,20 @@ # include <FL/Fl_Tooltip.H> # include <FL/fl_draw.H> # include <FL/Fl_Paged_Device.H> +# include <FL/Fl_Shared_Image.H> +# include <FL/fl_ask.H> +# include <FL/filename.H> # include <stdio.h> # include <stdlib.h> # include "flstring.h" # include <unistd.h> +# include <time.h> # include <sys/time.h> # include <X11/Xmd.h> # include <X11/Xlocale.h> # include <X11/Xlib.h> # include <X11/keysym.h> +# include "Xutf8.h" #define USE_XRANDR (HAVE_DLSYM && HAVE_DLFCN_H) // means attempt to dynamically load libXrandr.so #if USE_XRANDR #include <dlfcn.h> @@ -53,6 +58,17 @@ static XRRUpdateConfiguration_type XRRUpdateConfiguration_f; static int randrEventBase; // base of RandR-defined events #endif +# if HAVE_XFIXES +# include <X11/extensions/Xfixes.h> +static int xfixes_event_base = 0; +static bool have_xfixes = false; +# endif + +# include <X11/cursorfont.h> + +# if HAVE_XCURSOR +# include <X11/Xcursor/Xcursor.h> +# endif static Fl_Xlib_Graphics_Driver fl_xlib_driver; static Fl_Display_Device fl_xlib_display(&fl_xlib_driver); Fl_Display_Device *Fl_Display_Device::_display = &fl_xlib_display;// the platform display @@ -177,6 +193,8 @@ void Fl::remove_fd(int n) { remove_fd(n, -1); } +extern int fl_send_system_handlers(void *e); + #if CONSOLIDATE_MOTION static Fl_Window* send_motion; extern Fl_Window* fl_xmousewin; @@ -187,6 +205,8 @@ static void do_queued_events() { while (XEventsQueued(fl_display,QueuedAfterReading)) { XEvent xevent; XNextEvent(fl_display, &xevent); + if (fl_send_system_handlers(&xevent)) + continue; fl_handle(xevent); } // we send FL_LEAVE only if the mouse did not enter some other window: @@ -296,9 +316,10 @@ Window fl_message_window = 0; int fl_screen; XVisualInfo *fl_visual; Colormap fl_colormap; -XIM fl_xim_im = 0; +static XIM fl_xim_im = 0; XIC fl_xim_ic = 0; -char fl_is_over_the_spot = 0; +static Window fl_xim_win = 0; +static char fl_is_over_the_spot = 0; static XRectangle status_area; static Atom WM_DELETE_WINDOW; @@ -306,6 +327,9 @@ static Atom WM_PROTOCOLS; static Atom fl_MOTIF_WM_HINTS; static Atom TARGETS; static Atom CLIPBOARD; +static Atom TIMESTAMP; +static Atom PRIMARY_TIMESTAMP; +static Atom CLIPBOARD_TIMESTAMP; Atom fl_XdndAware; Atom fl_XdndSelection; Atom fl_XdndEnter; @@ -318,19 +342,25 @@ Atom fl_XdndActionCopy; Atom fl_XdndFinished; //Atom fl_XdndProxy; Atom fl_XdndURIList; -Atom fl_Xatextplainutf; -Atom fl_Xatextplainutf2; // STR#2930 -Atom fl_Xatextplain; +static Atom fl_Xatextplainutf; +static Atom fl_Xatextplainutf2; // STR#2930 +static Atom fl_Xatextplain; static Atom fl_XaText; -Atom fl_XaCompoundText; +static Atom fl_XaCompoundText; Atom fl_XaUtf8String; -Atom fl_XaTextUriList; -Atom fl_NET_WM_NAME; // utf8 aware window label -Atom fl_NET_WM_ICON_NAME; // utf8 aware window icon name -Atom fl_NET_SUPPORTING_WM_CHECK; -Atom fl_NET_WM_STATE; -Atom fl_NET_WM_STATE_FULLSCREEN; -Atom fl_NET_WORKAREA; +static Atom fl_XaTextUriList; +static Atom fl_XaImageBmp; +static Atom fl_XaImagePNG; +static Atom fl_INCR; +static Atom fl_NET_WM_NAME; // utf8 aware window label +static Atom fl_NET_WM_ICON_NAME; // utf8 aware window icon name +static Atom fl_NET_SUPPORTING_WM_CHECK; +static Atom fl_NET_WM_STATE; +static Atom fl_NET_WM_STATE_FULLSCREEN; +static Atom fl_NET_WM_FULLSCREEN_MONITORS; +static Atom fl_NET_WORKAREA; +static Atom fl_NET_WM_ICON; +static Atom fl_NET_ACTIVE_WINDOW; /* X defines 32-bit-entities to have a format value of max. 32, @@ -362,14 +392,14 @@ extern "C" { extern char *fl_get_font_xfld(int fnum, int size); -void fl_new_ic() +static void fl_new_ic() { XVaNestedList preedit_attr = NULL; XVaNestedList status_attr = NULL; static XFontSet fs = NULL; char *fnt; - char **missing_list; - int missing_count; + char **missing_list = 0; + int missing_count = 0; char *def_string; static XRectangle spot; int predit = 0; @@ -397,6 +427,9 @@ void fl_new_ic() if (must_free_fnt) free(fnt); } #endif + + if (missing_list) XFreeStringList(missing_list); + preedit_attr = XVaCreateNestedList(0, XNSpotLocation, &spot, XNFontSet, fs, NULL); @@ -539,7 +572,7 @@ void fl_set_status(int x, int y, int w, int h) XFree(status_attr); } -void fl_init_xim() { +static void fl_init_xim() { static int xim_warning = 2; if (xim_warning > 0) xim_warning--; @@ -584,6 +617,55 @@ void fl_init_xim() { if(xim_styles) XFree(xim_styles); } +void fl_xim_deactivate(void); + +void fl_xim_activate(Window xid) { + if (!fl_xim_im) + return; + + // If the focused window has changed, then use the brute force method + // of completely recreating the input context. + if (fl_xim_win != xid) { + fl_xim_deactivate(); + + fl_new_ic(); + fl_xim_win = xid; + + XSetICValues(fl_xim_ic, + XNFocusWindow, fl_xim_win, + XNClientWindow, fl_xim_win, + NULL); + } + + fl_set_spot(spotf, spots, spot.x, spot.y, spot.width, spot.height); +} + +void fl_xim_deactivate(void) { + if (!fl_xim_ic) + return; + + XDestroyIC(fl_xim_ic); + fl_xim_ic = NULL; + + fl_xim_win = 0; +} + +void Fl::enable_im() { + Fl_Window *win; + + win = Fl::first_window(); + if (win && win->shown()) { + fl_xim_activate(fl_xid(win)); + XSetICFocus(fl_xim_ic); + } else { + fl_new_ic(); + } +} + +void Fl::disable_im() { + fl_xim_deactivate(); +} + void fl_open_display() { if (fl_display) return; @@ -608,6 +690,9 @@ void fl_open_display(Display* d) { fl_MOTIF_WM_HINTS = XInternAtom(d, "_MOTIF_WM_HINTS", 0); TARGETS = XInternAtom(d, "TARGETS", 0); CLIPBOARD = XInternAtom(d, "CLIPBOARD", 0); + TIMESTAMP = XInternAtom(d, "TIMESTAMP", 0); + PRIMARY_TIMESTAMP = XInternAtom(d, "PRIMARY_TIMESTAMP", 0); + CLIPBOARD_TIMESTAMP = XInternAtom(d, "CLIPBOARD_TIMESTAMP", 0); fl_XdndAware = XInternAtom(d, "XdndAware", 0); fl_XdndSelection = XInternAtom(d, "XdndSelection", 0); fl_XdndEnter = XInternAtom(d, "XdndEnter", 0); @@ -628,12 +713,18 @@ void fl_open_display(Display* d) { fl_XaCompoundText = XInternAtom(d, "COMPOUND_TEXT", 0); fl_XaUtf8String = XInternAtom(d, "UTF8_STRING", 0); fl_XaTextUriList = XInternAtom(d, "text/uri-list", 0); + fl_XaImageBmp = XInternAtom(d, "image/bmp", 0); + fl_XaImagePNG = XInternAtom(d, "image/png", 0); + fl_INCR = XInternAtom(d, "INCR", 0); fl_NET_WM_NAME = XInternAtom(d, "_NET_WM_NAME", 0); fl_NET_WM_ICON_NAME = XInternAtom(d, "_NET_WM_ICON_NAME", 0); fl_NET_SUPPORTING_WM_CHECK = XInternAtom(d, "_NET_SUPPORTING_WM_CHECK", 0); fl_NET_WM_STATE = XInternAtom(d, "_NET_WM_STATE", 0); fl_NET_WM_STATE_FULLSCREEN = XInternAtom(d, "_NET_WM_STATE_FULLSCREEN", 0); + fl_NET_WM_FULLSCREEN_MONITORS = XInternAtom(d, "_NET_WM_FULLSCREEN_MONITORS", 0); fl_NET_WORKAREA = XInternAtom(d, "_NET_WORKAREA", 0); + fl_NET_WM_ICON = XInternAtom(d, "_NET_WM_ICON", 0); + fl_NET_ACTIVE_WINDOW = XInternAtom(d, "_NET_ACTIVE_WINDOW", 0); if (sizeof(Atom) < 4) atom_bits = sizeof(Atom) * 8; @@ -655,6 +746,15 @@ void fl_open_display(Display* d) { #if !USE_COLORMAP Fl::visual(FL_RGB); #endif + +#if HAVE_XFIXES + int error_base; + if (XFixesQueryExtension(fl_display, &xfixes_event_base, &error_base)) + have_xfixes = true; + else + have_xfixes = false; +#endif + #if USE_XRANDR void *libxrandr_addr = dlopen("libXrandr.so.2", RTLD_LAZY); if (!libxrandr_addr) libxrandr_addr = dlopen("libXrandr.so", RTLD_LAZY); @@ -688,7 +788,7 @@ static void fl_init_workarea() { Atom actual; unsigned long count, remaining; int format; - unsigned *xywh; + long *xywh = 0; /* If there are several screens, the _NET_WORKAREA property does not give the work area of the main screen, but that of all screens together. @@ -696,7 +796,7 @@ static void fl_init_workarea() { and fall back to the main screen full area when there are several screens. */ if (Fl::screen_count() > 1 || XGetWindowProperty(fl_display, RootWindow(fl_display, fl_screen), - fl_NET_WORKAREA, 0, 4 * sizeof(unsigned), False, + fl_NET_WORKAREA, 0, 4, False, XA_CARDINAL, &actual, &format, &count, &remaining, (unsigned char **)&xywh) || !xywh || !xywh[2] || !xywh[3]) @@ -712,8 +812,8 @@ static void fl_init_workarea() { fl_workarea_xywh[1] = (int)xywh[1]; fl_workarea_xywh[2] = (int)xywh[2]; fl_workarea_xywh[3] = (int)xywh[3]; - XFree(xywh); } + if ( xywh ) { XFree(xywh); xywh = 0; } } int Fl::x() { @@ -751,15 +851,18 @@ void Fl::get_mouse(int &xx, int &yy) { Fl_Widget *fl_selection_requestor; char *fl_selection_buffer[2]; int fl_selection_length[2]; +const char * fl_selection_type[2]; int fl_selection_buffer_length[2]; char fl_i_own_selection[2] = {0,0}; // Call this when a "paste" operation happens: -void Fl::paste(Fl_Widget &receiver, int clipboard) { +void Fl::paste(Fl_Widget &receiver, int clipboard, const char *type) { if (fl_i_own_selection[clipboard]) { // We already have it, do it quickly without window server. // Notice that the text is clobbered if set_selection is // called in response to FL_PASTE! + // However, for now, we only paste text in this function + if (fl_selection_type[clipboard] != Fl::clipboard_plain_text) return; //TODO: allow copy/paste of image within same app Fl::e_text = fl_selection_buffer[clipboard]; Fl::e_length = fl_selection_length[clipboard]; if (!Fl::e_text) Fl::e_text = (char *)""; @@ -769,15 +872,65 @@ void Fl::paste(Fl_Widget &receiver, int clipboard) { // otherwise get the window server to return it: fl_selection_requestor = &receiver; Atom property = clipboard ? CLIPBOARD : XA_PRIMARY; + Fl::e_clipboard_type = type; XConvertSelection(fl_display, property, TARGETS, property, fl_xid(Fl::first_window()), fl_event_time); } -Window fl_dnd_source_window; -Atom *fl_dnd_source_types; // null-terminated list of data types being supplied -Atom fl_dnd_type; -Atom fl_dnd_source_action; -Atom fl_dnd_action; +int Fl::clipboard_contains(const char *type) +{ + XEvent event; + Atom actual; int format; unsigned long count, remaining, i = 0; + unsigned char* portion = NULL; + Fl_Window *win = Fl::first_window(); + if (!win || !fl_xid(win)) return 0; + XConvertSelection(fl_display, CLIPBOARD, TARGETS, CLIPBOARD, fl_xid(win), CurrentTime); + XFlush(fl_display); + do { + XNextEvent(fl_display, &event); + if (event.type == SelectionNotify && event.xselection.property == None) return 0; + i++; + } + while (i < 10 && event.type != SelectionNotify); + if (i >= 10) return 0; + XGetWindowProperty(fl_display, + event.xselection.requestor, + event.xselection.property, + 0, 4000, 0, 0, + &actual, &format, &count, &remaining, &portion); + if (actual != XA_ATOM) return 0; + Atom t; + int retval = 0; + if (strcmp(type, Fl::clipboard_plain_text) == 0) { + for (i = 0; i<count; i++) { // searching for text data + t = ((Atom*)portion)[i]; + if (t == fl_Xatextplainutf || + t == fl_Xatextplainutf2 || + t == fl_Xatextplain || + t == fl_XaUtf8String) { + retval = 1; + break; + } + } + } + else if (strcmp(type, Fl::clipboard_image) == 0) { + for (i = 0; i<count; i++) { // searching for image data + t = ((Atom*)portion)[i]; + if (t == fl_XaImageBmp || t == fl_XaImagePNG) { + retval = 1; + break; + } + } + } + XFree(portion); + return retval; +} + +static Window fl_dnd_source_window; +static Atom *fl_dnd_source_types; // null-terminated list of data types being supplied +static Atom fl_dnd_type; +static Atom fl_dnd_source_action; +static Atom fl_dnd_action; void fl_sendClientMessage(Window window, Atom message, unsigned long d0, @@ -800,9 +953,19 @@ void fl_sendClientMessage(Window window, Atom message, } -/* - Get window property value (32 bit format) +/* + Get window property value (32 bit format) Returns zero on success, -1 on error + + 'data' should be freed with XFree() using this pattern: + + unsigned long *data = 0; + if (0 == get_xwinprop(....., &nitems, &data) ) { ..success.. } + else { ..fail.. } + if ( data ) { XFree(data); data=0; } + + Note: 'data' can be non-zero, even if the return value is -1 (error) and + should hence be XFree'd *after* the if/else statement, as described above. */ static int get_xwinprop(Window wnd, Atom prop, long max_length, unsigned long *nitems, unsigned long **data) { @@ -827,7 +990,7 @@ static int get_xwinprop(Window wnd, Atom prop, long max_length, //////////////////////////////////////////////////////////////// // Code for copying to clipboard and DnD out of the program: -void Fl::copy(const char *stuff, int len, int clipboard) { +void Fl::copy(const char *stuff, int len, int clipboard, const char *type) { if (!stuff || len<0) return; if (len+1 > fl_selection_buffer_length[clipboard]) { delete[] fl_selection_buffer[clipboard]; @@ -838,11 +1001,183 @@ void Fl::copy(const char *stuff, int len, int clipboard) { fl_selection_buffer[clipboard][len] = 0; // needed for direct paste fl_selection_length[clipboard] = len; fl_i_own_selection[clipboard] = 1; + fl_selection_type[clipboard] = Fl::clipboard_plain_text; + Atom property = clipboard ? CLIPBOARD : XA_PRIMARY; + XSetSelectionOwner(fl_display, property, fl_message_window, fl_event_time); +} + +static void write_short(unsigned char **cp,short i){ + unsigned char *c=*cp; + *c++=i&0xFF;i>>=8; + *c++=i&0xFF;i>>=8; + *cp=c; +} + +static void write_int(unsigned char **cp,int i){ + unsigned char *c=*cp; + *c++=i&0xFF;i>>=8; + *c++=i&0xFF;i>>=8; + *c++=i&0xFF;i>>=8; + *c++=i&0xFF;i>>=8; + *cp=c; +} + +static unsigned char *create_bmp(const unsigned char *data, int W, int H, int *return_size){ + int R=(3*W+3)/4 * 4; // the number of bytes per row, rounded up to multiple of 4 + int s=H*R; + int fs=14+40+s; + unsigned char *b=new unsigned char[fs]; + unsigned char *c=b; + // BMP header + *c++='B'; + *c++='M'; + write_int(&c,fs); + write_int(&c,0); + write_int(&c,14+40); + // DIB header: + write_int(&c,40); + write_int(&c,W); + write_int(&c,H); + write_short(&c,1); + write_short(&c,24);//bits ber pixel + write_int(&c,0);//RGB + write_int(&c,s); + write_int(&c,0);// horizontal resolution + write_int(&c,0);// vertical resolution + write_int(&c,0);//number of colors. 0 -> 1<<bits_per_pixel + write_int(&c,0); + // Pixel data + data+=3*W*H; + for (int y=0;y<H;++y){ + data-=3*W; + const unsigned char *s=data; + unsigned char *p=c; + for (int x=0;x<W;++x){ + *p++=s[2]; + *p++=s[1]; + *p++=s[0]; + s+=3; + } + c+=R; + } + *return_size = fs; + return b; +} + +void Fl::copy_image(const unsigned char *data, int W, int H, int clipboard){ + if(!data || W<=0 || H<=0) return; + delete[] fl_selection_buffer[clipboard]; + fl_selection_buffer[clipboard] = (char *) create_bmp(data,W,H,&fl_selection_length[clipboard]); + fl_selection_buffer_length[clipboard] = fl_selection_length[clipboard]; + fl_i_own_selection[clipboard] = 1; + fl_selection_type[clipboard] = Fl::clipboard_image; + Atom property = clipboard ? CLIPBOARD : XA_PRIMARY; XSetSelectionOwner(fl_display, property, fl_message_window, fl_event_time); } //////////////////////////////////////////////////////////////// +// Code for tracking clipboard changes: + +static Time primary_timestamp = (Time)-1; +static Time clipboard_timestamp = (Time)-1; + +extern bool fl_clipboard_notify_empty(void); +extern void fl_trigger_clipboard_notify(int source); + +static void poll_clipboard_owner(void) { + Window xid; + +#if HAVE_XFIXES + // No polling needed with Xfixes + if (have_xfixes) + return; +#endif + + // No one is interested, so no point polling + if (fl_clipboard_notify_empty()) + return; + + // We need a window for this to work + if (!Fl::first_window()) + return; + xid = fl_xid(Fl::first_window()); + if (!xid) + return; + + // Request an update of the selection time for both the primary and + // clipboard selections. Magic continues when we get a SelectionNotify. + if (!fl_i_own_selection[0]) + XConvertSelection(fl_display, XA_PRIMARY, TIMESTAMP, PRIMARY_TIMESTAMP, + xid, fl_event_time); + if (!fl_i_own_selection[1]) + XConvertSelection(fl_display, CLIPBOARD, TIMESTAMP, CLIPBOARD_TIMESTAMP, + xid, fl_event_time); +} + +static void clipboard_timeout(void *data) +{ + // No one is interested, so stop polling + if (fl_clipboard_notify_empty()) + return; + + poll_clipboard_owner(); + + Fl::repeat_timeout(0.5, clipboard_timeout); +} + +static void handle_clipboard_timestamp(int clipboard, Time time) +{ + Time *timestamp; + + timestamp = clipboard ? &clipboard_timestamp : &primary_timestamp; + +#if HAVE_XFIXES + if (!have_xfixes) +#endif + { + // Initial scan, just store the value + if (*timestamp == (Time)-1) { + *timestamp = time; + return; + } + } + + // Same selection + if (time == *timestamp) + return; + + *timestamp = time; + + // The clipboard change is the event that caused us to request + // the clipboard data, so use that time as the latest event. + if (time > fl_event_time) + fl_event_time = time; + + // Something happened! Let's tell someone! + fl_trigger_clipboard_notify(clipboard); +} + +void fl_clipboard_notify_change() { + // Reset the timestamps if we've going idle so that you don't + // get a bogus immediate trigger next time they're activated. + if (fl_clipboard_notify_empty()) { + primary_timestamp = (Time)-1; + clipboard_timestamp = (Time)-1; + } else { +#if HAVE_XFIXES + if (!have_xfixes) +#endif + { + poll_clipboard_owner(); + + if (!Fl::has_timeout(clipboard_timeout)) + Fl::add_timeout(0.5, clipboard_timeout); + } + } +} + +//////////////////////////////////////////////////////////////// const XEvent* fl_xevent; // the current x event ulong fl_event_time; // the last timestamp from an x event @@ -914,16 +1249,78 @@ static int wasXExceptionRaised() { } +static bool getNextEvent(XEvent *event_return) +{ + time_t t = time(NULL); + while(!XPending(fl_display)) + { + if(time(NULL) - t > 10.0) + { + //fprintf(stderr,"Error: The XNextEvent never came...\n"); + return false; + } + } + XNextEvent(fl_display, event_return); + return true; +} + +static long getIncrData(uchar* &data, const XSelectionEvent& selevent, long lower_bound) +{ +//fprintf(stderr,"Incremental transfer starting due to INCR property\n"); + size_t total = 0; + XEvent event; + XDeleteProperty(fl_display, selevent.requestor, selevent.property); + data = (uchar*)realloc(data, lower_bound); + for (;;) + { + if (!getNextEvent(&event)) break; + if (event.type == PropertyNotify) + { + if (event.xproperty.state != PropertyNewValue) continue; + Atom actual_type; + int actual_format; + unsigned long nitems; + unsigned long bytes_after; + unsigned char* prop = 0; + long offset = 0; + size_t num_bytes; + //size_t slice_size = 0; + do + { + XGetWindowProperty(fl_display, selevent.requestor, selevent.property, offset, 70000, True, + AnyPropertyType, &actual_type, &actual_format, &nitems, &bytes_after, &prop); + num_bytes = nitems * (actual_format / 8); + offset += num_bytes/4; + //slice_size += num_bytes; + if (total + num_bytes > (size_t)lower_bound) data = (uchar*)realloc(data, total + num_bytes); + memcpy(data + total, prop, num_bytes); total += num_bytes; + if (prop) XFree(prop); + } while (bytes_after != 0); +//fprintf(stderr,"INCR data size:%ld\n", slice_size); + if (num_bytes == 0) break; + } + else break; + } + XDeleteProperty(fl_display, selevent.requestor, selevent.property); + return (long)total; +} + +/* Internal function to reduce "deprecated" warnings for XKeycodeToKeysym(). + This way we get only one warning. The option to use XkbKeycodeToKeysym() + instead would not help much - see STR #2913 for more information. +*/ +static KeySym fl_KeycodeToKeysym(Display *d, KeyCode k, unsigned i) { + return XKeycodeToKeysym(d, k, i); +} int fl_handle(const XEvent& thisevent) { XEvent xevent = thisevent; fl_xevent = &thisevent; Window xid = xevent.xany.window; - static Window xim_win = 0; if (fl_xim_ic && xevent.type == DestroyNotify && - xid != xim_win && !fl_find(xid)) + xid != fl_xim_win && !fl_find(xid)) { XIM xim_im; xim_im = XOpenIM(fl_display, NULL, NULL, NULL); @@ -939,46 +1336,9 @@ int fl_handle(const XEvent& thisevent) } if (fl_xim_ic && (xevent.type == FocusIn)) - { -#define POOR_XIM -#ifdef POOR_XIM - if (xim_win != xid) - { - xim_win = xid; - XDestroyIC(fl_xim_ic); - fl_xim_ic = NULL; - fl_new_ic(); - XSetICValues(fl_xim_ic, - XNFocusWindow, xevent.xclient.window, - XNClientWindow, xid, - NULL); - } - fl_set_spot(spotf, spots, spot.x, spot.y, spot.width, spot.height); -#else - if (Fl::first_window() && Fl::first_window()->modal()) { - Window x = fl_xid(Fl::first_window()); - if (x != xim_win) { - xim_win = x; - XSetICValues(fl_xim_ic, - XNFocusWindow, xim_win, - XNClientWindow, xim_win, - NULL); - fl_set_spot(spotf, spots, spot.x, spot.y, spot.width, spot.height); - } - } else if (xim_win != xid && xid) { - xim_win = xid; - XSetICValues(fl_xim_ic, - XNFocusWindow, xevent.xclient.window, - XNClientWindow, xid, - //XNFocusWindow, xim_win, - //XNClientWindow, xim_win, - NULL); - fl_set_spot(spotf, spots, spot.x, spot.y, spot.width, spot.height); - } -#endif - } + fl_xim_activate(xid); - if ( XFilterEvent((XEvent *)&xevent, 0) ) + if (fl_xim_ic && XFilterEvent((XEvent *)&xevent, 0)) return(1); #if USE_XRANDR @@ -1005,9 +1365,9 @@ int fl_handle(const XEvent& thisevent) return 0; case SelectionNotify: { - if (!fl_selection_requestor) return 0; - static unsigned char* buffer = 0; - if (buffer) {XFree(buffer); buffer = 0;} + static unsigned char* sn_buffer = 0; + //static const char *buffer_format = 0; + if (sn_buffer) {XFree(sn_buffer); sn_buffer = 0;} long bytesread = 0; if (fl_xevent->xselection.property) for (;;) { // The Xdnd code pastes 64K chunks together, possibly to avoid @@ -1018,13 +1378,42 @@ int fl_handle(const XEvent& thisevent) if (XGetWindowProperty(fl_display, fl_xevent->xselection.requestor, fl_xevent->xselection.property, - bytesread/4, 65536, 1, 0, + bytesread/4, 65536, 1, AnyPropertyType, &actual, &format, &count, &remaining, &portion)) break; // quit on error + + if ((fl_xevent->xselection.property == PRIMARY_TIMESTAMP) || + (fl_xevent->xselection.property == CLIPBOARD_TIMESTAMP)) { + if (portion && format == 32 && count == 1) { + Time t = *(unsigned int*)portion; + if (fl_xevent->xselection.property == CLIPBOARD_TIMESTAMP) + handle_clipboard_timestamp(1, t); + else + handle_clipboard_timestamp(0, t); + } + XFree(portion); portion = 0; + return true; + } + if (actual == TARGETS || actual == XA_ATOM) { - Atom type = XA_STRING; - for (unsigned i = 0; i<count; i++) { - Atom t = ((Atom*)portion)[i]; +/*for (unsigned i = 0; i<count; i++) { + fprintf(stderr," %s", XGetAtomName(fl_display, ((Atom*)portion)[i]) ); + } +fprintf(stderr,"\n");*/ + Atom t, type = XA_STRING; + if (Fl::e_clipboard_type == Fl::clipboard_image) { // searching for image data + for (unsigned i = 0; i<count; i++) { + t = ((Atom*)portion)[i]; + if (t == fl_XaImageBmp || t == fl_XaImagePNG) { + type = t; + goto found; + } + } + XFree(portion); + return true; + } + for (unsigned i = 0; i<count; i++) { // searching for text data + t = ((Atom*)portion)[i]; if (t == fl_Xatextplainutf || t == fl_Xatextplainutf2 || t == fl_Xatextplain || @@ -1037,39 +1426,84 @@ int fl_handle(const XEvent& thisevent) t == fl_XaTextUriList || t == fl_XaCompoundText) type = t; } - XFree(portion); + found: + XFree(portion); portion = 0; Atom property = xevent.xselection.property; XConvertSelection(fl_display, property, type, property, fl_xid(Fl::first_window()), fl_event_time); + if (type == fl_XaImageBmp) { + Fl::e_clipboard_type = Fl::clipboard_image; + //buffer_format = "image/bmp"; + } + else if (type == fl_XaImagePNG) { + Fl::e_clipboard_type = Fl::clipboard_image; + //buffer_format = "image/png"; + } + else { + Fl::e_clipboard_type = Fl::clipboard_plain_text; + //buffer_format = Fl::clipboard_plain_text; + } +//fprintf(stderr,"used format=%s\n", buffer_format); return true; } - // Make sure we got something sane... + if (actual == fl_INCR) { + bytesread = getIncrData(sn_buffer, xevent.xselection, *(long*)portion); + XFree(portion); + break; + } + // Make sure we got something sane... if ((portion == NULL) || (format != 8) || (count == 0)) { - if (portion) XFree(portion); + if (portion) { XFree(portion); portion = 0; } return true; - } - buffer = (unsigned char*)realloc(buffer, bytesread+count+remaining+1); - memcpy(buffer+bytesread, portion, count); - XFree(portion); + } + sn_buffer = (unsigned char*)realloc(sn_buffer, bytesread+count+remaining+1); + memcpy(sn_buffer+bytesread, portion, count); + if (portion) { XFree(portion); portion = 0; } bytesread += count; // Cannot trust data to be null terminated - buffer[bytesread] = '\0'; + sn_buffer[bytesread] = '\0'; if (!remaining) break; } - if (buffer) { - buffer[bytesread] = 0; - convert_crlf(buffer, bytesread); + if (sn_buffer && Fl::e_clipboard_type == Fl::clipboard_plain_text) { + sn_buffer[bytesread] = 0; + convert_crlf(sn_buffer, bytesread); + } + if (Fl::e_clipboard_type == Fl::clipboard_image) { + if (bytesread == 0) return 0; + Fl_Image *image = 0; + static char tmp_fname[21]; + static Fl_Shared_Image *shared = 0; + strcpy(tmp_fname, "/tmp/clipboardXXXXXX"); + int fd = mkstemp(tmp_fname); + if (fd == -1) return 0; + uchar *p = sn_buffer; ssize_t towrite = bytesread, written; + while (towrite) { + written = write(fd, p, towrite); + p += written; towrite -= written; + } + close(fd); + free(sn_buffer); sn_buffer = 0; + shared = Fl_Shared_Image::get(tmp_fname); + unlink(tmp_fname); + if (!shared) return 0; + image = shared->copy(); + shared->release(); + Fl::e_clipboard_data = (void*)image; } - Fl::e_text = buffer ? (char*)buffer : (char *)""; - Fl::e_length = bytesread; + if (!fl_selection_requestor) return 0; + + if (Fl::e_clipboard_type == Fl::clipboard_plain_text) { + Fl::e_text = sn_buffer ? (char*)sn_buffer : (char *)""; + Fl::e_length = bytesread; + } int old_event = Fl::e_number; fl_selection_requestor->handle(Fl::e_number = FL_PASTE); Fl::e_number = old_event; // Detect if this paste is due to Xdnd by the property name (I use // XA_SECONDARY for that) and send an XdndFinished message. It is not // clear if this has to be delayed until now or if it can be done - // immediatly after calling XConvertSelection. + // immediately after calling XConvertSelection. if (fl_xevent->xselection.property == XA_SECONDARY && fl_dnd_source_window) { fl_sendClientMessage(fl_dnd_source_window, fl_XdndFinished, @@ -1081,6 +1515,7 @@ int fl_handle(const XEvent& thisevent) case SelectionClear: { int clipboard = fl_xevent->xselectionclear.selection == CLIPBOARD; fl_i_own_selection[clipboard] = 0; + poll_clipboard_owner(); return 1;} case SelectionRequest: { @@ -1092,32 +1527,51 @@ int fl_handle(const XEvent& thisevent) e.target = fl_xevent->xselectionrequest.target; e.time = fl_xevent->xselectionrequest.time; e.property = fl_xevent->xselectionrequest.property; - if (e.target == TARGETS) { - Atom a[3] = {fl_XaUtf8String, XA_STRING, fl_XaText}; - XChangeProperty(fl_display, e.requestor, e.property, - XA_ATOM, atom_bits, 0, (unsigned char*)a, 3); - } else if (/*e.target == XA_STRING &&*/ fl_selection_length[clipboard]) { - if (e.target == fl_XaUtf8String || - e.target == XA_STRING || - e.target == fl_XaCompoundText || - e.target == fl_XaText || - e.target == fl_Xatextplain || - e.target == fl_Xatextplainutf || - e.target == fl_Xatextplainutf2) { - // clobber the target type, this seems to make some applications - // behave that insist on asking for XA_TEXT instead of UTF8_STRING - // Does not change XA_STRING as that breaks xclipboard. - if (e.target != XA_STRING) e.target = fl_XaUtf8String; + if (fl_selection_type[clipboard] == Fl::clipboard_plain_text) { + if (e.target == TARGETS) { + Atom a[3] = {fl_XaUtf8String, XA_STRING, fl_XaText}; + XChangeProperty(fl_display, e.requestor, e.property, + XA_ATOM, atom_bits, 0, (unsigned char*)a, 3); + } else { + if (/*e.target == XA_STRING &&*/ fl_selection_length[clipboard]) { + if (e.target == fl_XaUtf8String || + e.target == XA_STRING || + e.target == fl_XaCompoundText || + e.target == fl_XaText || + e.target == fl_Xatextplain || + e.target == fl_Xatextplainutf || + e.target == fl_Xatextplainutf2) { + // clobber the target type, this seems to make some applications + // behave that insist on asking for XA_TEXT instead of UTF8_STRING + // Does not change XA_STRING as that breaks xclipboard. + if (e.target != XA_STRING) e.target = fl_XaUtf8String; + XChangeProperty(fl_display, e.requestor, e.property, + e.target, 8, 0, + (unsigned char *)fl_selection_buffer[clipboard], + fl_selection_length[clipboard]); + } + } else { + // char* x = XGetAtomName(fl_display,e.target); + // fprintf(stderr,"selection request of %s\n",x); + // XFree(x); + e.property = 0; + } + } + } else { // image in clipboard + if (e.target == TARGETS) { + Atom a[1] = {fl_XaImageBmp}; XChangeProperty(fl_display, e.requestor, e.property, - e.target, 8, 0, - (unsigned char *)fl_selection_buffer[clipboard], - fl_selection_length[clipboard]); + XA_ATOM, atom_bits, 0, (unsigned char*)a, 1); + } else { + if (e.target == fl_XaImageBmp && fl_selection_length[clipboard]) { + XChangeProperty(fl_display, e.requestor, e.property, + e.target, 8, 0, + (unsigned char *)fl_selection_buffer[clipboard], + fl_selection_length[clipboard]); + } else { + e.property = 0; + } } - } else { -// char* x = XGetAtomName(fl_display,e.target); -// fprintf(stderr,"selection request of %s\n",x); -// XFree(x); - e.property = 0; } XSendEvent(fl_display, e.requestor, 0, 0, (XEvent *)&e);} return 1; @@ -1170,18 +1624,21 @@ int fl_handle(const XEvent& thisevent) if (data[1]&1) { // get list of data types: Atom actual; int format; unsigned long count, remaining; - unsigned char *buffer = 0; + unsigned char *cm_buffer = 0; XGetWindowProperty(fl_display, fl_dnd_source_window, fl_XdndTypeList, 0, 0x8000000L, False, XA_ATOM, &actual, &format, - &count, &remaining, &buffer); - if (actual != XA_ATOM || format != 32 || count<4 || !buffer) + &count, &remaining, &cm_buffer); + if (actual != XA_ATOM || format != 32 || count<4 || !cm_buffer) { + if ( cm_buffer ) { XFree(cm_buffer); cm_buffer = 0; } goto FAILED; + } delete [] fl_dnd_source_types; fl_dnd_source_types = new Atom[count+1]; for (unsigned i = 0; i < count; i++) { - fl_dnd_source_types[i] = ((Atom*)buffer)[i]; + fl_dnd_source_types[i] = ((Atom*)cm_buffer)[i]; } fl_dnd_source_types[count] = 0; + XFree(cm_buffer); cm_buffer = 0; } else { FAILED: // less than four data types, or if the above messes up: @@ -1258,6 +1715,7 @@ int fl_handle(const XEvent& thisevent) Fl::e_length = unknown_len; if (Fl::handle(FL_DND_RELEASE, window)) { fl_selection_requestor = Fl::belowmouse(); + Fl::e_clipboard_type = Fl::clipboard_plain_text; XConvertSelection(fl_display, fl_XdndSelection, fl_dnd_type, XA_SECONDARY, to_window, fl_event_time); @@ -1295,6 +1753,9 @@ int fl_handle(const XEvent& thisevent) case FocusIn: if (fl_xim_ic) XSetICFocus(fl_xim_ic); event = FL_FOCUS; + // If the user has toggled from another application to this one, + // then it's a good time to check for clipboard changes. + poll_clipboard_owner(); break; case FocusOut: @@ -1307,13 +1768,13 @@ int fl_handle(const XEvent& thisevent) KEYPRESS: int keycode = xevent.xkey.keycode; fl_key_vector[keycode/8] |= (1 << (keycode%8)); - static char *buffer = NULL; - static int buffer_len = 0; + static char *kp_buffer = NULL; + static int kp_buffer_len = 0; int len=0; KeySym keysym; - if (buffer_len == 0) { - buffer_len = 4096; - buffer = (char*) malloc(buffer_len); + if (kp_buffer_len == 0) { + kp_buffer_len = 4096; + kp_buffer = (char*) malloc(kp_buffer_len); } if (xevent.type == KeyPress) { event = FL_KEYDOWN; @@ -1322,34 +1783,31 @@ int fl_handle(const XEvent& thisevent) if (fl_xim_ic) { Status status; len = XUtf8LookupString(fl_xim_ic, (XKeyPressedEvent *)&xevent.xkey, - buffer, buffer_len, &keysym, &status); + kp_buffer, kp_buffer_len, &keysym, &status); - while (status == XBufferOverflow && buffer_len < 50000) { - buffer_len = buffer_len * 5 + 1; - buffer = (char*)realloc(buffer, buffer_len); + while (status == XBufferOverflow && kp_buffer_len < 50000) { + kp_buffer_len = kp_buffer_len * 5 + 1; + kp_buffer = (char*)realloc(kp_buffer, kp_buffer_len); len = XUtf8LookupString(fl_xim_ic, (XKeyPressedEvent *)&xevent.xkey, - buffer, buffer_len, &keysym, &status); + kp_buffer, kp_buffer_len, &keysym, &status); } - keysym = XKeycodeToKeysym(fl_display, keycode, 0); + keysym = fl_KeycodeToKeysym(fl_display, keycode, 0); } else { //static XComposeStatus compose; len = XLookupString((XKeyEvent*)&(xevent.xkey), - buffer, buffer_len, &keysym, 0/*&compose*/); + kp_buffer, kp_buffer_len, &keysym, 0/*&compose*/); if (keysym && keysym < 0x400) { // a character in latin-1,2,3,4 sets // force it to type a character (not sure if this ever is needed): - // if (!len) {buffer[0] = char(keysym); len = 1;} - len = fl_utf8encode(XKeysymToUcs(keysym), buffer); + // if (!len) {kp_buffer[0] = char(keysym); len = 1;} + len = fl_utf8encode(XKeysymToUcs(keysym), kp_buffer); if (len < 1) len = 1; // ignore all effects of shift on the keysyms, which makes it a lot // easier to program shortcuts and is Windoze-compatible: - keysym = XKeycodeToKeysym(fl_display, keycode, 0); + keysym = fl_KeycodeToKeysym(fl_display, keycode, 0); } } - // MRS: Can't use Fl::event_state(FL_CTRL) since the state is not - // set until set_event_xy() is called later... - if ((xevent.xkey.state & ControlMask) && keysym == '-') buffer[0] = 0x1f; // ^_ - buffer[len] = 0; - Fl::e_text = buffer; + kp_buffer[len] = 0; + Fl::e_text = kp_buffer; Fl::e_length = len; } else { // Stupid X sends fake key-up events when a repeating key is held @@ -1357,17 +1815,17 @@ int fl_handle(const XEvent& thisevent) // we can detect this because the repeating KeyPress event is in // the queue, get it and execute it instead: - // Bool XkbSetDetectableAutorepeat ( display, detectable, supported_rtrn ) + // Bool XkbSetDetectableAutoRepeat ( display, detectable, supported_rtrn ) // Display * display ; // Bool detectable ; // Bool * supported_rtrn ; - // ...would be the easy way to corrct this isuue. Unfortunatly, this call is also + // ...would be the easy way to correct this issue. Unfortunately, this call is also // broken on many Unix distros including Ubuntu and Solaris (as of Dec 2009) // Bogus KeyUp events are generated by repeated KeyDown events. One - // neccessary condition is an identical key event pending right after + // necessary condition is an identical key event pending right after // the bogus KeyUp. - // The new code introduced Dec 2009 differs in that it only check the very + // The new code introduced Dec 2009 differs in that it only checks the very // next event in the queue, not the entire queue of events. // This function wrongly detects a repeat key if a software keyboard // sends a burst of events containing two consecutive equal keys. However, @@ -1388,7 +1846,7 @@ int fl_handle(const XEvent& thisevent) event = FL_KEYUP; fl_key_vector[keycode/8] &= ~(1 << (keycode%8)); // keyup events just get the unshifted keysym: - keysym = XKeycodeToKeysym(fl_display, keycode, 0); + keysym = fl_KeycodeToKeysym(fl_display, keycode, 0); } # ifdef __sgi // You can plug a microsoft keyboard into an sgi but the extra shift @@ -1481,14 +1939,14 @@ int fl_handle(const XEvent& thisevent) if (keysym >= 0xff91 && keysym <= 0xff9f) { // Map keypad keysym to character or keysym depending on // numlock state... - unsigned long keysym1 = XKeycodeToKeysym(fl_display, keycode, 1); + unsigned long keysym1 = fl_KeycodeToKeysym(fl_display, keycode, 1); if (keysym1 <= 0x7f || (keysym1 > 0xff9f && keysym1 <= FL_KP_Last)) Fl::e_original_keysym = (int)(keysym1 | FL_KP); if ((xevent.xkey.state & Mod2Mask) && (keysym1 <= 0x7f || (keysym1 > 0xff9f && keysym1 <= FL_KP_Last))) { // Store ASCII numeric keypad value... keysym = keysym1 | FL_KP; - buffer[0] = char(keysym1) & 0x7F; + kp_buffer[0] = char(keysym1) & 0x7F; len = 1; } else { // Map keypad to special key... @@ -1551,6 +2009,7 @@ int fl_handle(const XEvent& thisevent) } } } + if ( words ) { XFree(words); words = 0; } } if (window->fullscreen_active() && !fullscreen_state) { window->_clear_fullscreen(); @@ -1663,6 +2122,25 @@ int fl_handle(const XEvent& thisevent) } } +#if HAVE_XFIXES + switch (xevent.type - xfixes_event_base) { + case XFixesSelectionNotify: { + // Someone feeding us bogus events? + if (!have_xfixes) + return true; + + XFixesSelectionNotifyEvent *selection_notify = (XFixesSelectionNotifyEvent *)&xevent; + + if ((selection_notify->selection == XA_PRIMARY) && !fl_i_own_selection[0]) + handle_clipboard_timestamp(0, selection_notify->selection_timestamp); + else if ((selection_notify->selection == CLIPBOARD) && !fl_i_own_selection[1]) + handle_clipboard_timestamp(1, selection_notify->selection_timestamp); + + return true; + } + } +#endif + return Fl::handle(event, window); } @@ -1705,22 +2183,30 @@ void Fl_Window::resize(int X,int Y,int W,int H) { #define _NET_WM_STATE_ADD 1 /* add/set property */ #define _NET_WM_STATE_TOGGLE 2 /* toggle property */ -static void send_wm_state_event(Window wnd, int add, Atom prop) { +static void send_wm_event(Window wnd, Atom message, + unsigned long d0, unsigned long d1=0, + unsigned long d2=0, unsigned long d3=0, + unsigned long d4=0) { XEvent e; e.xany.type = ClientMessage; e.xany.window = wnd; - e.xclient.message_type = fl_NET_WM_STATE; + e.xclient.message_type = message; e.xclient.format = 32; - e.xclient.data.l[0] = add ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE; - e.xclient.data.l[1] = prop; - e.xclient.data.l[2] = 0; - e.xclient.data.l[3] = 0; - e.xclient.data.l[4] = 0; + e.xclient.data.l[0] = d0; + e.xclient.data.l[1] = d1; + e.xclient.data.l[2] = d2; + e.xclient.data.l[3] = d3; + e.xclient.data.l[4] = d4; XSendEvent(fl_display, RootWindow(fl_display, fl_screen), 0, SubstructureNotifyMask | SubstructureRedirectMask, &e); } +static void send_wm_state_event(Window wnd, int add, Atom prop) { + send_wm_event(wnd, fl_NET_WM_STATE, + add ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE, prop); +} + int Fl_X::ewmh_supported() { static int result = -1; @@ -1731,19 +2217,56 @@ int Fl_X::ewmh_supported() { if (0 == get_xwinprop(XRootWindow(fl_display, fl_screen), fl_NET_SUPPORTING_WM_CHECK, 64, &nitems, &words) && nitems == 1) { Window child = words[0]; + if ( words ) { XFree(words); words = 0; } if (0 == get_xwinprop(child, fl_NET_SUPPORTING_WM_CHECK, 64, - &nitems, &words) && nitems == 1) { - result = (child == words[0]); + &nitems, &words) ) { + if ( nitems == 1) result = (child == words[0]); } } + if ( words ) { XFree(words); words = 0; } } return result; } +extern Fl_Window *fl_xfocus; + +void Fl_X::activate_window(Window w) { + if (!ewmh_supported()) + return; + + Window prev = 0; + + if (fl_xfocus) { + Fl_X *x = Fl_X::i(fl_xfocus); + if (!x) + return; + prev = x->xid; + } + + send_wm_event(w, fl_NET_ACTIVE_WINDOW, 1 /* application */, + 0 /* timestamp */, prev /* previously active window */); +} + /* Change an existing window to fullscreen */ void Fl_Window::fullscreen_x() { if (Fl_X::ewmh_supported()) { + int top, bottom, left, right; + + top = fullscreen_screen_top; + bottom = fullscreen_screen_bottom; + left = fullscreen_screen_left; + right = fullscreen_screen_right; + + if ((top < 0) || (bottom < 0) || (left < 0) || (right < 0)) { + top = Fl::screen_num(x(), y(), w(), h()); + bottom = top; + left = top; + right = top; + } + + send_wm_event(fl_xid(this), fl_NET_WM_FULLSCREEN_MONITORS, + top, bottom, left, right); send_wm_state_event(fl_xid(this), 1, fl_NET_WM_STATE_FULLSCREEN); } else { _set_fullscreen(); @@ -1830,7 +2353,7 @@ void Fl_X::make_xid(Fl_Window* win, XVisualInfo *visual, Colormap colormap) // force the window to be on-screen. Usually the X window manager // does this, but a few don't, so we do it here for consistency: int scr_x, scr_y, scr_w, scr_h; - Fl::screen_xywh(scr_x, scr_y, scr_w, scr_h, X, Y); + Fl::screen_xywh(scr_x, scr_y, scr_w, scr_h, X, Y, W, H); if (win->border()) { // ensure border is on screen: @@ -1859,6 +2382,23 @@ void Fl_X::make_xid(Fl_Window* win, XVisualInfo *visual, Colormap colormap) return; } + // Compute which screen(s) we should be on if we want to go fullscreen + int fullscreen_top, fullscreen_bottom, fullscreen_left, fullscreen_right; + + fullscreen_top = win->fullscreen_screen_top; + fullscreen_bottom = win->fullscreen_screen_bottom; + fullscreen_left = win->fullscreen_screen_left; + fullscreen_right = win->fullscreen_screen_right; + + if ((fullscreen_top < 0) || (fullscreen_bottom < 0) || + (fullscreen_left < 0) || (fullscreen_right < 0)) { + fullscreen_top = Fl::screen_num(X, Y, W, H); + fullscreen_bottom = fullscreen_top; + fullscreen_left = fullscreen_top; + fullscreen_right = fullscreen_top; + } + + ulong root = win->parent() ? fl_xid(win->window()) : RootWindow(fl_display, fl_screen); @@ -1882,9 +2422,17 @@ void Fl_X::make_xid(Fl_Window* win, XVisualInfo *visual, Colormap colormap) // border, and cannot grab without an existing window. Besides, // there is no clear_override(). if (win->fullscreen_active() && !Fl_X::ewmh_supported()) { + int sx, sy, sw, sh; attr.override_redirect = 1; mask |= CWOverrideRedirect; - Fl::screen_xywh(X, Y, W, H, X, Y, W, H); + Fl::screen_xywh(sx, sy, sw, sh, fullscreen_left); + X = sx; + Fl::screen_xywh(sx, sy, sw, sh, fullscreen_right); + W = sx + sw - X; + Fl::screen_xywh(sx, sy, sw, sh, fullscreen_top); + Y = sy; + Fl::screen_xywh(sx, sy, sw, sh, fullscreen_bottom); + H = sy + sh - Y; } if (fl_background_pixel >= 0) { @@ -1937,6 +2485,12 @@ void Fl_X::make_xid(Fl_Window* win, XVisualInfo *visual, Colormap colormap) while (wp->parent()) wp = wp->window(); XSetTransientForHint(fl_display, xp->xid, fl_xid(wp)); if (!wp->visible()) showit = 0; // guess that wm will not show it + if (win->modal()) { + Atom net_wm_state = XInternAtom (fl_display, "_NET_WM_STATE", 0); + Atom net_wm_state_skip_taskbar = XInternAtom (fl_display, "_NET_WM_STATE_MODAL", 0); + XChangeProperty (fl_display, xp->xid, net_wm_state, XA_ATOM, 32, + PropModeAppend, (unsigned char*) &net_wm_state_skip_taskbar, 1); + } } // Make sure that borderless windows do not show in the task bar @@ -1949,6 +2503,13 @@ void Fl_X::make_xid(Fl_Window* win, XVisualInfo *visual, Colormap colormap) // If asked for, create fullscreen if (win->fullscreen_active() && Fl_X::ewmh_supported()) { + unsigned long data[4]; + data[0] = fullscreen_top; + data[1] = fullscreen_bottom; + data[2] = fullscreen_left; + data[3] = fullscreen_right; + XChangeProperty (fl_display, xp->xid, fl_NET_WM_FULLSCREEN_MONITORS, XA_ATOM, 32, + PropModeReplace, (unsigned char*) data, 4); XChangeProperty (fl_display, xp->xid, fl_NET_WM_STATE, XA_ATOM, 32, PropModeAppend, (unsigned char*) &fl_NET_WM_STATE_FULLSCREEN, 1); } @@ -1967,12 +2528,14 @@ void Fl_X::make_xid(Fl_Window* win, XVisualInfo *visual, Colormap colormap) fl_show_iconic = 0; showit = 0; } - if (win->icon()) { - hints->icon_pixmap = (Pixmap)win->icon(); + if (win->icon_->legacy_icon) { + hints->icon_pixmap = (Pixmap)win->icon_->legacy_icon; hints->flags |= IconPixmapHint; } XSetWMHints(fl_display, xp->xid, hints); XFree(hints); + + xp->set_icons(); } // set the window type for menu and tooltip windows to avoid animations (compiz) @@ -1982,6 +2545,19 @@ void Fl_X::make_xid(Fl_Window* win, XVisualInfo *visual, Colormap colormap) XChangeProperty(fl_display, xp->xid, net_wm_type, XA_ATOM, 32, PropModeReplace, (unsigned char*)&net_wm_type_kind, 1); } +#if HAVE_XFIXES + // register for clipboard change notifications + if (have_xfixes && !win->parent()) { + XFixesSelectSelectionInput(fl_display, xp->xid, XA_PRIMARY, + XFixesSetSelectionOwnerNotifyMask); + XFixesSelectSelectionInput(fl_display, xp->xid, CLIPBOARD, + XFixesSetSelectionOwnerNotifyMask); + } +#endif + + if (win->shape_data_) { + win->combine_mask(); + } XMapWindow(fl_display, xp->xid); if (showit) { win->set_visible(); @@ -2082,6 +2658,207 @@ void Fl_Window::size_range_() { //////////////////////////////////////////////////////////////// +static unsigned long *default_net_wm_icons = 0L; +static size_t default_net_wm_icons_size = 0; + +static void icons_to_property(const Fl_RGB_Image *icons[], int count, + unsigned long **property, size_t *len) { + size_t sz; + unsigned long *data; + + sz = 0; + for (int i = 0;i < count;i++) + sz += 2 + icons[i]->w() * icons[i]->h(); + + // FIXME: Might want to sort the icons + + *property = data = new unsigned long[sz]; + *len = sz; + + for (int i = 0;i < count;i++) { + const Fl_RGB_Image *image; + + image = icons[i]; + + data[0] = image->w(); + data[1] = image->h(); + data += 2; + + const uchar *in = (const uchar*)*image->data(); + for (int y = 0;y < image->h();y++) { + for (int x = 0;x < image->w();x++) { + switch (image->d()) { + case 1: + *data = ( 0xff<<24) | (in[0]<<16) | (in[0]<<8) | in[0]; + break; + case 2: + *data = (in[1]<<24) | (in[0]<<16) | (in[0]<<8) | in[0]; + break; + case 3: + *data = ( 0xff<<24) | (in[0]<<16) | (in[1]<<8) | in[2]; + break; + case 4: + *data = (in[3]<<24) | (in[0]<<16) | (in[1]<<8) | in[2]; + break; + } + in += image->d(); + data++; + } + in += image->ld(); + } + } +} + +void Fl_X::set_default_icons(const Fl_RGB_Image *icons[], int count) { + if (default_net_wm_icons) { + delete [] default_net_wm_icons; + default_net_wm_icons = 0L; + default_net_wm_icons_size = 0; + } + + if (count > 0) + icons_to_property(icons, count, + &default_net_wm_icons, &default_net_wm_icons_size); +} + +void Fl_X::set_icons() { + unsigned long *net_wm_icons; + size_t net_wm_icons_size; + + if (w->icon_->count) { + icons_to_property((const Fl_RGB_Image **)w->icon_->icons, w->icon_->count, + &net_wm_icons, &net_wm_icons_size); + } else { + net_wm_icons = default_net_wm_icons; + net_wm_icons_size = default_net_wm_icons_size; + } + + XChangeProperty (fl_display, xid, fl_NET_WM_ICON, XA_CARDINAL, 32, + PropModeReplace, (unsigned char*) net_wm_icons, net_wm_icons_size); + + if (w->icon_->count) { + delete [] net_wm_icons; + net_wm_icons = 0L; + net_wm_icons_size = 0; + } +} + +//////////////////////////////////////////////////////////////// + +int Fl_X::set_cursor(Fl_Cursor c) { + + /* The cursors are cached, because creating one takes 0.5ms including + opening, reading, and closing theme files. They are kept until program + exit by design, which valgrind will note as reachable. */ + static Cursor xc_arrow = None; + static Cursor xc_cross = None; + static Cursor xc_wait = None; + static Cursor xc_insert = None; + static Cursor xc_hand = None; + static Cursor xc_help = None; + static Cursor xc_move = None; + static Cursor xc_ns = None; + static Cursor xc_we = None; + static Cursor xc_ne = None; + static Cursor xc_n = None; + static Cursor xc_nw = None; + static Cursor xc_e = None; + static Cursor xc_w = None; + static Cursor xc_se = None; + static Cursor xc_s = None; + static Cursor xc_sw = None; + + Cursor xc; + +#define cache_cursor(name, var) if (var == None) { \ + var = XCreateFontCursor(fl_display, name); \ + } \ + xc = var + + switch (c) { + case FL_CURSOR_ARROW: cache_cursor(XC_left_ptr, xc_arrow); break; + case FL_CURSOR_CROSS: cache_cursor(XC_tcross, xc_cross); break; + case FL_CURSOR_WAIT: cache_cursor(XC_watch, xc_wait); break; + case FL_CURSOR_INSERT: cache_cursor(XC_xterm, xc_insert); break; + case FL_CURSOR_HAND: cache_cursor(XC_hand2, xc_hand); break; + case FL_CURSOR_HELP: cache_cursor(XC_question_arrow, xc_help); break; + case FL_CURSOR_MOVE: cache_cursor(XC_fleur, xc_move); break; + case FL_CURSOR_NS: cache_cursor(XC_sb_v_double_arrow, xc_ns); break; + case FL_CURSOR_WE: cache_cursor(XC_sb_h_double_arrow, xc_we); break; + case FL_CURSOR_NE: cache_cursor(XC_top_right_corner, xc_ne); break; + case FL_CURSOR_N: cache_cursor(XC_top_side, xc_n); break; + case FL_CURSOR_NW: cache_cursor(XC_top_left_corner, xc_nw); break; + case FL_CURSOR_E: cache_cursor(XC_right_side, xc_e); break; + case FL_CURSOR_W: cache_cursor(XC_left_side, xc_w); break; + case FL_CURSOR_SE: cache_cursor(XC_bottom_right_corner, xc_se); break; + case FL_CURSOR_S: cache_cursor(XC_bottom_side, xc_s); break; + case FL_CURSOR_SW: cache_cursor(XC_bottom_left_corner, xc_sw); break; + default: + return 0; + } + +#undef cache_cursor + + XDefineCursor(fl_display, xid, xc); + + return 1; +} + +int Fl_X::set_cursor(const Fl_RGB_Image *image, int hotx, int hoty) { +#if ! HAVE_XCURSOR + return 0; +#else + XcursorImage *cursor; + Cursor xc; + + if ((hotx < 0) || (hotx >= image->w())) + return 0; + if ((hoty < 0) || (hoty >= image->h())) + return 0; + + cursor = XcursorImageCreate(image->w(), image->h()); + if (!cursor) + return 0; + + const uchar *i = (const uchar*)*image->data(); + XcursorPixel *o = cursor->pixels; + for (int y = 0;y < image->h();y++) { + for (int x = 0;x < image->w();x++) { + switch (image->d()) { + case 1: + *o = (0xff<<24) | (i[0]<<16) | (i[0]<<8) | i[0]; + break; + case 2: + *o = (i[1]<<24) | (i[0]<<16) | (i[0]<<8) | i[0]; + break; + case 3: + *o = (0xff<<24) | (i[0]<<16) | (i[1]<<8) | i[2]; + break; + case 4: + *o = (i[3]<<24) | (i[0]<<16) | (i[1]<<8) | i[2]; + break; + } + i += image->d(); + o++; + } + i += image->ld(); + } + + cursor->xhot = hotx; + cursor->yhot = hoty; + + xc = XcursorImageLoadCursor(fl_display, cursor); + XDefineCursor(fl_display, xid, xc); + XFreeCursor(fl_display, xc); + + XcursorImageDestroy(cursor); + + return 1; +#endif +} + +//////////////////////////////////////////////////////////////// + // returns pointer to the filename, or null if name ends with '/' const char *fl_filename_name(const char *name) { const char *p,*q; @@ -2132,7 +2909,7 @@ void Fl_Window::show() { if (!shown()) { fl_open_display(); // Don't set background pixel for double-buffered windows... - if (type() == FL_WINDOW && can_boxcheat(box())) { + if (type() != FL_DOUBLE_WINDOW && can_boxcheat(box())) { fl_background_pixel = int(fl_xpixel(color())); } Fl_X::make_xid(this); @@ -2152,6 +2929,10 @@ GC fl_gc; // make X drawing go into this window (called by subclass flush() impl.) void Fl_Window::make_current() { static GC gc; // the GC used by all X windows + if (!shown()) { + fl_alert("Fl_Window::make_current(), but window is not shown()."); + Fl::fatal("Fl_Window::make_current(), but window is not shown()."); + } if (!gc) gc = XCreateGC(fl_display, i->xid, 0, 0); fl_window = i->xid; fl_gc = gc; @@ -2164,7 +2945,7 @@ void Fl_Window::make_current() { #endif } -Window fl_xid_(const Fl_Window *w) { +FL_EXPORT Window fl_xid_(const Fl_Window *w) { Fl_X *temp = Fl_X::i(w); return temp ? temp->xid : 0; } @@ -2309,5 +3090,5 @@ void preparePrintFront(void) #endif // -// End of "$Id: Fl_x.cxx 9699 2012-10-16 15:35:34Z manolo $". +// End of "$Id: Fl_x.cxx 10412 2014-10-29 20:25:46Z cand $". // diff --git a/src/Makefile b/src/Makefile index c80a016..672cb60 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,9 +1,9 @@ # -# "$Id: Makefile 9707 2012-11-06 21:13:54Z matt $" +# "$Id: Makefile 10419 2014-10-30 16:05:22Z AlbrechtS $" # # Library makefile for the Fast Light Tool Kit (FLTK). # -# Copyright 1998-2010 by Bill Spitzak and others. +# Copyright 1998-2014 by Bill Spitzak and others. # # This library is free software. Distribution and use rights are outlined in # the file "COPYING" which should have been included with this file. If this @@ -31,6 +31,7 @@ CPPFILES = \ Fl_Choice.cxx \ Fl_Clock.cxx \ Fl_Color_Chooser.cxx \ + Fl_Copy_Surface.cxx \ Fl_Counter.cxx \ Fl_Dial.cxx \ Fl_Device.cxx \ @@ -43,13 +44,13 @@ CPPFILES = \ Fl_Group.cxx \ Fl_Help_View.cxx \ Fl_Image.cxx \ + Fl_Image_Surface.cxx \ Fl_Input.cxx \ Fl_Input_.cxx \ Fl_Light_Button.cxx \ Fl_Menu.cxx \ Fl_Menu_.cxx \ Fl_Menu_Bar.cxx \ - Fl_Sys_Menu_Bar.cxx \ Fl_Menu_Button.cxx \ Fl_Menu_Window.cxx \ Fl_Menu_add.cxx \ @@ -60,6 +61,7 @@ CPPFILES = \ Fl_Pack.cxx \ Fl_Paged_Device.cxx \ Fl_Pixmap.cxx \ + Fl_PostScript.cxx \ Fl_Positioner.cxx \ Fl_Preferences.cxx \ Fl_Printer.cxx \ @@ -95,6 +97,7 @@ CPPFILES = \ Fl_Window_fullscreen.cxx \ Fl_Window_hotspot.cxx \ Fl_Window_iconize.cxx \ + Fl_Window_shape.cxx \ Fl_Wizard.cxx \ Fl_XBM_Image.cxx \ Fl_XPM_Image.cxx \ @@ -134,6 +137,7 @@ CPPFILES = \ fl_engraved_label.cxx \ fl_file_dir.cxx \ fl_font.cxx \ + fl_gleam.cxx \ fl_gtk.cxx \ fl_labeltype.cxx \ fl_line_style.cxx \ @@ -157,12 +161,13 @@ CPPFILES = \ screen_xywh.cxx \ fl_utf8.cxx \ ps_image.cxx - + OBJCPPFILES = \ Fl_cocoa.mm \ Fl_Quartz_Printer.mm \ - Fl_Native_File_Chooser_MAC.mm - + Fl_Native_File_Chooser_MAC.mm \ + Fl_Sys_Menu_Bar.mm + FLCPPFILES = \ forms_compatability.cxx \ forms_bitmap.cxx \ @@ -248,7 +253,7 @@ libfltk.1.3.dylib: $(OBJECTS) echo $(DSOCOMMAND) $@ ... $(DSOCOMMAND) $@ \ -install_name $(libdir)/$@ \ - -current_version 1.3.1 \ + -current_version 1.3.3 \ -compatibility_version 1.3.0 \ $(OBJECTS) $(LDLIBS) $(RM) libfltk.dylib @@ -270,7 +275,7 @@ $(FLLIBNAME): $(FLOBJECTS) libfltk_forms.so.1.3: $(FLOBJECTS) libfltk.so.1.3 echo $(DSOCOMMAND) $@ ... - $(DSOCOMMAND) $@ $(FLOBJECTS) -L. -lfltk + $(DSOCOMMAND) $@ $(FLOBJECTS) -L. -lfltk $(LDLIBS) $(RM) libfltk_forms.so $(LN) libfltk_forms.so.1.3 libfltk_forms.so @@ -284,7 +289,7 @@ libfltk_forms.1.3.dylib: $(FLOBJECTS) libfltk.1.3.dylib echo $(DSOCOMMAND) $@ ... $(DSOCOMMAND) $@ \ -install_name $(libdir)/$@ \ - -current_version 1.3.1 \ + -current_version 1.3.3 \ -compatibility_version 1.3.0 \ $(FLOBJECTS) -L. $(LDLIBS) -lfltk $(RM) libfltk_forms.dylib @@ -320,7 +325,7 @@ libfltk_gl.1.3.dylib: $(GLOBJECTS) libfltk.1.3.dylib echo $(DSOCOMMAND) $@ ... $(DSOCOMMAND) $@ \ -install_name $(libdir)/$@ \ - -current_version 1.3.1 \ + -current_version 1.3.3 \ -compatibility_version 1.3.0 \ $(GLOBJECTS) -L. $(GLDLIBS) -lfltk $(RM) libfltk_gl.dylib @@ -342,7 +347,7 @@ $(IMGLIBNAME): $(IMGOBJECTS) libfltk_images.so.1.3: $(IMGOBJECTS) libfltk.so.1.3 echo $(DSOCOMMAND) $@ ... - $(DSOCOMMAND) $@ $(IMGOBJECTS) -L. $(IMAGELIBS) -lfltk + $(DSOCOMMAND) $@ $(IMGOBJECTS) -L. $(IMAGELIBS) -lfltk $(LDLIBS) $(RM) libfltk_images.so $(LN) libfltk_images.so.1.3 libfltk_images.so @@ -356,7 +361,7 @@ libfltk_images.1.3.dylib: $(IMGOBJECTS) libfltk.1.3.dylib echo $(DSOCOMMAND) $@ ... $(DSOCOMMAND) $@ \ -install_name $(libdir)/$@ \ - -current_version 1.3.1 \ + -current_version 1.3.3 \ -compatibility_version 1.3.0 \ $(IMGOBJECTS) -L. $(LDLIBS) $(IMAGELIBS) -lfltk $(RM) libfltk_images.dylib @@ -800,5 +805,5 @@ uninstall: fi # -# End of "$Id: Makefile 9707 2012-11-06 21:13:54Z matt $". +# End of "$Id: Makefile 10419 2014-10-30 16:05:22Z AlbrechtS $". # diff --git a/src/Xutf8.h b/src/Xutf8.h new file mode 100644 index 0000000..7e5d357 --- /dev/null +++ b/src/Xutf8.h @@ -0,0 +1,184 @@ +/* "$Id: Xutf8.h 10248 2014-08-23 08:41:58Z cand $" + * + * Author: Jean-Marc Lienher ( http://oksid.ch ) + * Copyright 2000-2010 by O'ksi'D. + * + * This library is free software. Distribution and use rights are outlined in + * the file "COPYING" which should have been included with this file. If this + * file is missing or damaged, see the license at: + * + * http://www.fltk.org/COPYING.php + * + * Please report all bugs and problems on the following page: + * + * http://www.fltk.org/str.php + */ + +#if ! ( defined(_Xutf8_h) || defined(FL_DOXYGEN) ) +#define _Xutf8_h + +# ifdef __cplusplus +extern "C" { +# endif + +#include <X11/X.h> +#include <X11/Xlib.h> +#include <X11/Xlocale.h> +#include <X11/Xutil.h> + +typedef struct { + int nb_font; + char **font_name_list; + int *encodings; + XFontStruct **fonts; + Font fid; + int ascent; + int descent; + int *ranges; +} XUtf8FontStruct; + +XUtf8FontStruct * +XCreateUtf8FontStruct ( + Display *dpy, + const char *base_font_name_list); + +void +XUtf8DrawString( + Display *display, + Drawable d, + XUtf8FontStruct *font_set, + GC gc, + int x, + int y, + const char *string, + int num_bytes); + +void +XUtf8_measure_extents( + Display *display, + Drawable d, + XUtf8FontStruct *font_set, + GC gc, + int *xx, + int *yy, + int *ww, + int *hh, + const char *string, + int num_bytes); + +void +XUtf8DrawRtlString( + Display *display, + Drawable d, + XUtf8FontStruct *font_set, + GC gc, + int x, + int y, + const char *string, + int num_bytes); + +void +XUtf8DrawImageString( + Display *display, + Drawable d, + XUtf8FontStruct *font_set, + GC gc, + int x, + int y, + const char *string, + int num_bytes); + +int +XUtf8TextWidth( + XUtf8FontStruct *font_set, + const char *string, + int num_bytes); +int +XUtf8UcsWidth( + XUtf8FontStruct *font_set, + unsigned int ucs); + +int +XGetUtf8FontAndGlyph( + XUtf8FontStruct *font_set, + unsigned int ucs, + XFontStruct **fnt, + unsigned short *id); + +void +XFreeUtf8FontStruct( + Display *dpy, + XUtf8FontStruct *font_set); + + +int +XConvertUtf8ToUcs( + const unsigned char *buf, + int len, + unsigned int *ucs); + +int +XConvertUcsToUtf8( + unsigned int ucs, + char *buf); + +int +XUtf8CharByteLen( + const unsigned char *buf, + int len); + +int +XCountUtf8Char( + const unsigned char *buf, + int len); + +int +XFastConvertUtf8ToUcs( + const unsigned char *buf, + int len, + unsigned int *ucs); + +long +XKeysymToUcs( + KeySym keysym); + +#ifdef X_HAVE_UTF8_STRING +#define XUtf8LookupString Xutf8LookupString +#else +int +XUtf8LookupString( + XIC ic, + XKeyPressedEvent* event, + char* buffer_return, + int bytes_buffer, + KeySym* keysym, + Status* status_return); +#endif + +unsigned short +XUtf8IsNonSpacing( + unsigned int ucs); + +unsigned short +XUtf8IsRightToLeft( + unsigned int ucs); + + +int +XUtf8Tolower( + int ucs); + +int +XUtf8Toupper( + int ucs); + + +# ifdef __cplusplus +} +# endif + +#endif + +/* + * End of "$Id: Xutf8.h 10248 2014-08-23 08:41:58Z cand $". + */ diff --git a/src/aimm.h b/src/aimm.h deleted file mode 100644 index b7de2d9..0000000 --- a/src/aimm.h +++ /dev/null @@ -1,422 +0,0 @@ -// -// "$Id: aimm.h 8864 2011-07-19 04:49:30Z greg.ercolano $" -// -// Standard dialog header file for the UTF-8 Fast Light Tool Kit (FLTK-UTF8). -// -// Copyright 2009-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: -// -// http://www.fltk.org/COPYING.php -// -// Please report all bugs and problems on the following page: -// -// http://www.fltk.org/str.php -// - -#ifndef AIMM_H -# define AIMM_H -//# define HANDLE_PTR HANDLE* -//# define DWORD_PTR DWORD* -//# define CLSCTX_INPROC_SERVER 0x1 -const GUID IID_IActiveIMMApp = { 0x8c0e040, 0x62d1, 0x11d1, {0x93, 0x26, 0x00, 0x60, 0xb0, 0x67, 0xb8, 0x6e}}; -const GUID CLSID_CActiveIMM = { 0x4955dd33, 0xb159, 0x11d0, {0x8f, 0xcf, 0x00, 0xaa, 0x00, 0x6b, 0xcc, 0x59}}; -/* - class IUnknown - { - public: - - virtual long __stdcall QueryInterface( - const GUID & riid, - void **ppvObject) = 0; - - virtual ULONG __stdcall AddRef( void) = 0; - - virtual ULONG __stdcall Release( void) = 0; - }; - -extern "C" __declspec(dllimport) long __stdcall CoInitialize(void far *pvReserved); -extern "C" __declspec(dllimport) long __stdcall CoCreateInstance(const GUID & rclsid, IUnknown * pUnkOuter, - DWORD dwClsContext, const GUID & riid, LPVOID FAR* ppv); - -*/ - - class IActiveIMMApp : public IUnknown - { - public: - virtual long __stdcall AssociateContext( - HWND hWnd, - HIMC hIME, - HIMC *phPrev) = 0; - - virtual long __stdcall ConfigureIMEA( - HKL hKL, - HWND hWnd, - DWORD dwMode, - void *pData) = 0; - - virtual long __stdcall ConfigureIMEW( - HKL hKL, - HWND hWnd, - DWORD dwMode, - void *pData) = 0; - - virtual long __stdcall CreateContext( - HIMC *phIMC) = 0; - - virtual long __stdcall DestroyContext( - HIMC hIME) = 0; - - virtual long __stdcall EnumRegisterWordA( - HKL hKL, - LPSTR szReading, - DWORD dwStyle, - LPSTR szRegister, - LPVOID pData, - void **pEnum) = 0; - - virtual long __stdcall EnumRegisterWordW( - HKL hKL, - LPWSTR szReading, - DWORD dwStyle, - LPWSTR szRegister, - LPVOID pData, - void **pEnum) = 0; - - virtual long __stdcall EscapeA( - HKL hKL, - HIMC hIMC, - UINT uEscape, - /* [out][in] */ LPVOID pData, - LRESULT *plResult) = 0; - - virtual long __stdcall EscapeW( - HKL hKL, - HIMC hIMC, - UINT uEscape, - /* [out][in] */ LPVOID pData, - LRESULT *plResult) = 0; - - virtual long __stdcall GetCandidateListA( - HIMC hIMC, - DWORD dwIndex, - UINT uBufLen, - void *pCandList, - UINT *puCopied) = 0; - - virtual long __stdcall GetCandidateListW( - HIMC hIMC, - DWORD dwIndex, - UINT uBufLen, - void *pCandList, - UINT *puCopied) = 0; - - virtual long __stdcall GetCandidateListCountA( - HIMC hIMC, - DWORD *pdwListSize, - DWORD *pdwBufLen) = 0; - - virtual long __stdcall GetCandidateListCountW( - HIMC hIMC, - DWORD *pdwListSize, - DWORD *pdwBufLen) = 0; - - virtual long __stdcall GetCandidateWindow( - HIMC hIMC, - DWORD dwIndex, - void *pCandidate) = 0; - - virtual long __stdcall GetCompositionFontA( - HIMC hIMC, - LOGFONTA *plf) = 0; - - virtual long __stdcall GetCompositionFontW( - HIMC hIMC, - LOGFONTW *plf) = 0; - - virtual long __stdcall GetCompositionStringA( - HIMC hIMC, - DWORD dwIndex, - DWORD dwBufLen, - LONG *plCopied, - LPVOID pBuf) = 0; - - virtual long __stdcall GetCompositionStringW( - HIMC hIMC, - DWORD dwIndex, - DWORD dwBufLen, - LONG *plCopied, - LPVOID pBuf) = 0; - - virtual long __stdcall GetCompositionWindow( - HIMC hIMC, - void *pCompForm) = 0; - - virtual long __stdcall GetContext( - HWND hWnd, - HIMC *phIMC) = 0; - - virtual long __stdcall GetConversionListA( - HKL hKL, - HIMC hIMC, - LPSTR pSrc, - UINT uBufLen, - UINT uFlag, - void *pDst, - UINT *puCopied) = 0; - - virtual long __stdcall GetConversionListW( - HKL hKL, - HIMC hIMC, - LPWSTR pSrc, - UINT uBufLen, - UINT uFlag, - void *pDst, - UINT *puCopied) = 0; - - virtual long __stdcall GetConversionStatus( - HIMC hIMC, - DWORD *pfdwConversion, - DWORD *pfdwSentence) = 0; - - virtual long __stdcall GetDefaultIMEWnd( - HWND hWnd, - HWND *phDefWnd) = 0; - - virtual long __stdcall GetDescriptionA( - HKL hKL, - UINT uBufLen, - LPSTR szDescription, - UINT *puCopied) = 0; - - virtual long __stdcall GetDescriptionW( - HKL hKL, - UINT uBufLen, - LPWSTR szDescription, - UINT *puCopied) = 0; - - virtual long __stdcall GetGuideLineA( - HIMC hIMC, - DWORD dwIndex, - DWORD dwBufLen, - LPSTR pBuf, - DWORD *pdwResult) = 0; - - virtual long __stdcall GetGuideLineW( - HIMC hIMC, - DWORD dwIndex, - DWORD dwBufLen, - LPWSTR pBuf, - DWORD *pdwResult) = 0; - - virtual long __stdcall GetIMEFileNameA( - HKL hKL, - UINT uBufLen, - LPSTR szFileName, - UINT *puCopied) = 0; - - virtual long __stdcall GetIMEFileNameW( - HKL hKL, - UINT uBufLen, - LPWSTR szFileName, - UINT *puCopied) = 0; - - virtual long __stdcall GetOpenStatus( - HIMC hIMC) = 0; - - virtual long __stdcall GetProperty( - HKL hKL, - DWORD fdwIndex, - DWORD *pdwProperty) = 0; - - virtual long __stdcall GetRegisterWordStyleA( - HKL hKL, - UINT nItem, - STYLEBUFA *pStyleBuf, - UINT *puCopied) = 0; - - virtual long __stdcall GetRegisterWordStyleW( - HKL hKL, - UINT nItem, - STYLEBUFW *pStyleBuf, - UINT *puCopied) = 0; - - virtual long __stdcall GetStatusWindowPos( - HIMC hIMC, - POINT *pptPos) = 0; - - virtual long __stdcall GetVirtualKey( - HWND hWnd, - UINT *puVirtualKey) = 0; - - virtual long __stdcall InstallIMEA( - LPSTR szIMEFileName, - LPSTR szLayoutText, - HKL *phKL) = 0; - - virtual long __stdcall InstallIMEW( - LPWSTR szIMEFileName, - LPWSTR szLayoutText, - HKL *phKL) = 0; - - virtual long __stdcall IsIME( - HKL hKL) = 0; - - virtual long __stdcall IsUIMessageA( - HWND hWndIME, - UINT msg, - WPARAM wParam, - LPARAM lParam) = 0; - - virtual long __stdcall IsUIMessageW( - HWND hWndIME, - UINT msg, - WPARAM wParam, - LPARAM lParam) = 0; - - virtual long __stdcall NotifyIME( - HIMC hIMC, - DWORD dwAction, - DWORD dwIndex, - DWORD dwValue) = 0; - - virtual long __stdcall RegisterWordA( - HKL hKL, - LPSTR szReading, - DWORD dwStyle, - LPSTR szRegister) = 0; - - virtual long __stdcall RegisterWordW( - HKL hKL, - LPWSTR szReading, - DWORD dwStyle, - LPWSTR szRegister) = 0; - - virtual long __stdcall ReleaseContext( - HWND hWnd, - HIMC hIMC) = 0; - - virtual long __stdcall SetCandidateWindow( - HIMC hIMC, - void *pCandidate) = 0; - - virtual long __stdcall SetCompositionFontA( - HIMC hIMC, - LOGFONTA *plf) = 0; - - virtual long __stdcall SetCompositionFontW( - HIMC hIMC, - LOGFONTW *plf) = 0; - - virtual long __stdcall SetCompositionStringA( - HIMC hIMC, - DWORD dwIndex, - LPVOID pComp, - DWORD dwCompLen, - LPVOID pRead, - DWORD dwReadLen) = 0; - - virtual long __stdcall SetCompositionStringW( - HIMC hIMC, - DWORD dwIndex, - LPVOID pComp, - DWORD dwCompLen, - LPVOID pRead, - DWORD dwReadLen) = 0; - - virtual long __stdcall SetCompositionWindow( - HIMC hIMC, - void *pCompForm) = 0; - - virtual long __stdcall SetConversionStatus( - HIMC hIMC, - DWORD fdwConversion, - DWORD fdwSentence) = 0; - - virtual long __stdcall SetOpenStatus( - HIMC hIMC, - BOOL fOpen) = 0; - - virtual long __stdcall SetStatusWindowPos( - HIMC hIMC, - POINT *pptPos) = 0; - - virtual long __stdcall SimulateHotKey( - HWND hWnd, - DWORD dwHotKeyID) = 0; - - virtual long __stdcall UnregisterWordA( - HKL hKL, - LPSTR szReading, - DWORD dwStyle, - LPSTR szUnregister) = 0; - - virtual long __stdcall UnregisterWordW( - HKL hKL, - LPWSTR szReading, - DWORD dwStyle, - LPWSTR szUnregister) = 0; - - virtual long __stdcall Activate( - BOOL fRestoreLayout) = 0; - - virtual long __stdcall Deactivate( void) = 0; - - virtual long __stdcall OnDefWindowProc( - HWND hWnd, - UINT Msg, - WPARAM wParam, - LPARAM lParam, - LRESULT *plResult) = 0; - - virtual long __stdcall FilterClientWindows( - ATOM *aaClassList, - UINT uSize) = 0; - - virtual long __stdcall GetCodePageA( - HKL hKL, - UINT *uCodePage) = 0; - - virtual long __stdcall GetLangId( - HKL hKL, - WORD *plid) = 0; - - virtual long __stdcall AssociateContextEx( - HWND hWnd, - HIMC hIMC, - DWORD dwFlags) = 0; - - virtual long __stdcall DisableIME( - DWORD idThread) = 0; - - virtual long __stdcall GetImeMenuItemsA( - HIMC hIMC, - DWORD dwFlags, - DWORD dwType, - void *pImeParentMenu, - void *pImeMenu, - DWORD dwSize, - DWORD *pdwResult) = 0; - - virtual long __stdcall GetImeMenuItemsW( - HIMC hIMC, - DWORD dwFlags, - DWORD dwType, - void *pImeParentMenu, - void *pImeMenu, - DWORD dwSize, - DWORD *pdwResult) = 0; - - virtual long __stdcall EnumInputContext( - DWORD idThread, - void **ppEnum) = 0; - - }; - -#endif - -// -// End of "$Id: aimm.h 8864 2011-07-19 04:49:30Z greg.ercolano $". -// diff --git a/src/fastarrow.h b/src/fastarrow.h index e381acd..9af76dd 100644 --- a/src/fastarrow.h +++ b/src/fastarrow.h @@ -1,6 +1,6 @@ #define fastarrow_width 16 #define fastarrow_height 16 -static unsigned char fastarrow_bits[] = { +static const unsigned char fastarrow_bits[] = { 0x00, 0x00, 0x00, 0x07, 0xe0, 0x07, 0xfc, 0x03, 0xff, 0xff, 0xfc, 0x03, 0xe0, 0x07, 0x00, 0x07, 0xe0, 0x00, 0xe0, 0x07, 0xc0, 0x3f, 0xff, 0xff, 0xc0, 0x3f, 0xe0, 0x07, 0xe0, 0x00, 0x00, 0x00}; diff --git a/src/fl_ask.cxx b/src/fl_ask.cxx index cd9de23..051b67f 100644 --- a/src/fl_ask.cxx +++ b/src/fl_ask.cxx @@ -1,5 +1,5 @@ // -// "$Id: fl_ask.cxx 9373 2012-04-22 02:45:09Z fabien $" +// "$Id: fl_ask.cxx 10232 2014-08-21 12:13:47Z cand $" // // Standard dialog functions for the Fast Light Tool Kit (FLTK). // @@ -16,6 +16,11 @@ // http://www.fltk.org/str.php // +/** + \file fl_ask.cxx + \brief Utility functions for common dialogs. + */ + // Implementation of fl_message, fl_ask, fl_choice, fl_input // The three-message fl_show_x functions are for forms compatibility // mostly. In most cases it is easier to get a multi-line message @@ -61,8 +66,8 @@ static char avoidRecursion = 0; // The first argument (Fl_Widget *) can either be an Fl_Button* // pointer to one of the buttons or an Fl_Window* pointer to the // message window (message_form). -static void button_cb(Fl_Widget *, void *val) { - ret_val = (int) (fl_intptr_t)val; +static void button_cb(Fl_Widget *, long val) { + ret_val = (int) val; message_form->hide(); } @@ -77,7 +82,7 @@ static Fl_Window *makeform() { Fl_Group::current(0); // create a new top level window Fl_Window *w = message_form = new Fl_Window(410,103); - message_form->callback(button_cb,(void *)0); + message_form->callback(button_cb); // w->clear_border(); // w->box(FL_UP_BOX); (message = new Fl_Box(60, 25, 340, 20)) @@ -99,11 +104,7 @@ static Fl_Window *makeform() { else button[b] = new Fl_Button(x, 70, 90, 23); button[b]->align(FL_ALIGN_INSIDE|FL_ALIGN_WRAP); -#if defined (__LP64__) - button[b]->callback(button_cb,(void *)(long long) b); -#else - button[b]->callback(button_cb,(void *)b); -#endif + button[b]->callback(button_cb, b); } } button[0]->shortcut(FL_Escape); @@ -125,7 +126,7 @@ static Fl_Window *makeform() { * that is asked of them... */ -void resizeform() { +static void resizeform() { int i; int message_w, message_h; int text_height; @@ -272,6 +273,7 @@ const char* fl_close= "Close"; ///< string pointer used in common dialogs, you // fltk functions: /** Emits a system beep message. + \param[in] type The beep type from the \ref Fl_Beep enumeration. \note \#include <FL/fl_ask.H> */ void fl_beep(int type) { @@ -566,5 +568,5 @@ void fl_message_title_default(const char *title) { /** @} */ // -// End of "$Id: fl_ask.cxx 9373 2012-04-22 02:45:09Z fabien $". +// End of "$Id: fl_ask.cxx 10232 2014-08-21 12:13:47Z cand $". // diff --git a/src/fl_boxtype.cxx b/src/fl_boxtype.cxx index fadd3b5..6d688b5 100644 --- a/src/fl_boxtype.cxx +++ b/src/fl_boxtype.cxx @@ -1,5 +1,5 @@ // -// "$Id: fl_boxtype.cxx 8864 2011-07-19 04:49:30Z greg.ercolano $" +// "$Id: fl_boxtype.cxx 10253 2014-08-23 09:27:30Z cand $" // // Box drawing code for the Fast Light Tool Kit (FLTK). // @@ -32,14 +32,14 @@ //////////////////////////////////////////////////////////////// -static uchar active_ramp[24] = { +static const uchar active_ramp[24] = { FL_GRAY_RAMP+0, FL_GRAY_RAMP+1, FL_GRAY_RAMP+2, FL_GRAY_RAMP+3, FL_GRAY_RAMP+4, FL_GRAY_RAMP+5, FL_GRAY_RAMP+6, FL_GRAY_RAMP+7, FL_GRAY_RAMP+8, FL_GRAY_RAMP+9, FL_GRAY_RAMP+10,FL_GRAY_RAMP+11, FL_GRAY_RAMP+12,FL_GRAY_RAMP+13,FL_GRAY_RAMP+14,FL_GRAY_RAMP+15, FL_GRAY_RAMP+16,FL_GRAY_RAMP+17,FL_GRAY_RAMP+18,FL_GRAY_RAMP+19, FL_GRAY_RAMP+20,FL_GRAY_RAMP+21,FL_GRAY_RAMP+22,FL_GRAY_RAMP+23}; -static uchar inactive_ramp[24] = { +static const uchar inactive_ramp[24] = { 43, 43, 44, 44, 44, 45, 45, 46, 46, 46, 47, 47, @@ -54,7 +54,7 @@ static int draw_it_active = 1; */ int Fl::draw_box_active() { return draw_it_active; } -uchar *fl_gray_ramp() {return (draw_it_active?active_ramp:inactive_ramp)-'A';} +const uchar *fl_gray_ramp() {return (draw_it_active?active_ramp:inactive_ramp)-'A';} /** Draws a series of line segments around the given box. @@ -69,7 +69,7 @@ uchar *fl_gray_ramp() {return (draw_it_active?active_ramp:inactive_ramp)-'A';} \param[in] x, y, w, h position and size */ void fl_frame(const char* s, int x, int y, int w, int h) { - uchar *g = fl_gray_ramp(); + const uchar *g = fl_gray_ramp(); if (h > 0 && w > 0) for (;*s;) { // draw top line: fl_color(g[(int)*s++]); @@ -103,7 +103,7 @@ void fl_frame(const char* s, int x, int y, int w, int h) { \param[in] x, y, w, h position and size */ void fl_frame2(const char* s, int x, int y, int w, int h) { - uchar *g = fl_gray_ramp(); + const uchar *g = fl_gray_ramp(); if (h > 0 && w > 0) for (;*s;) { // draw bottom line: fl_color(g[(int)*s++]); @@ -416,5 +416,5 @@ void Fl_Widget::draw_box(Fl_Boxtype t, int X, int Y, int W, int H, Fl_Color c) c } // -// End of "$Id: fl_boxtype.cxx 8864 2011-07-19 04:49:30Z greg.ercolano $". +// End of "$Id: fl_boxtype.cxx 10253 2014-08-23 09:27:30Z cand $". // diff --git a/src/fl_call_main.c b/src/fl_call_main.c index 4476c38..b300696 100644 --- a/src/fl_call_main.c +++ b/src/fl_call_main.c @@ -1,5 +1,5 @@ /* - * "$Id: fl_call_main.c 9325 2012-04-05 05:12:30Z fabien $" + * "$Id: fl_call_main.c 9984 2013-09-22 17:20:48Z greg.ercolano $" * * Copyright 1998-2010 by Bill Spitzak and others. * @@ -123,12 +123,12 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, return rc; } -#elif defined(__hpux) -/* This code to prevent "empty translation unit" or similar warnings... */ -static void dummy(void) {} +#else +/* STR# 2973: solves "empty translation unit" error (Sun, HP-UX..) */ +typedef int dummy; #endif /* WIN32 && !FL_DLL && !__GNUC__ */ /* - * End of "$Id: fl_call_main.c 9325 2012-04-05 05:12:30Z fabien $". + * End of "$Id: fl_call_main.c 9984 2013-09-22 17:20:48Z greg.ercolano $". */ diff --git a/src/fl_cursor.cxx b/src/fl_cursor.cxx index c9b6c98..d563fce 100644 --- a/src/fl_cursor.cxx +++ b/src/fl_cursor.cxx @@ -1,5 +1,5 @@ // -// "$Id: fl_cursor.cxx 9278 2012-03-12 11:55:50Z manolo $" +// "$Id: fl_cursor.cxx 10405 2014-10-29 15:53:52Z manolo $" // // Mouse cursor support for the Fast Light Tool Kit (FLTK). // @@ -24,298 +24,173 @@ #include <FL/Fl.H> #include <FL/Fl_Window.H> +#include <FL/Fl_Pixmap.H> +#include <FL/Fl_RGB_Image.H> #include <FL/x.H> -#if !defined(WIN32) && !defined(__APPLE__) -# include <X11/cursorfont.h> -#endif #include <FL/fl_draw.H> +#include "fl_cursor_wait.xpm" +#include "fl_cursor_help.xpm" +#include "fl_cursor_nwse.xpm" +#include "fl_cursor_nesw.xpm" +#include "fl_cursor_none.xpm" + /** Sets the cursor for the current window to the specified shape and colors. The cursors are defined in the <FL/Enumerations.H> header file. */ +void fl_cursor(Fl_Cursor c) { + if (Fl::first_window()) Fl::first_window()->cursor(c); +} + +/* For back compatibility only. */ void fl_cursor(Fl_Cursor c, Fl_Color fg, Fl_Color bg) { - if (Fl::first_window()) Fl::first_window()->cursor(c,fg,bg); + fl_cursor(c); } + + /** - Sets the default window cursor as well as its color. + Sets the default window cursor. This is the cursor that will be used + after the mouse pointer leaves a widget with a custom cursor set. - For back compatibility only. + \see cursor(const Fl_RGB_Image*, int, int), default_cursor() */ -void Fl_Window::default_cursor(Fl_Cursor c, Fl_Color fg, Fl_Color bg) { -// if (c == FL_CURSOR_DEFAULT) c = FL_CURSOR_ARROW; - +void Fl_Window::default_cursor(Fl_Cursor c) { cursor_default = c; - cursor_fg = fg; - cursor_bg = bg; + cursor(c); +} + + +static void fallback_cursor(Fl_Window *w, Fl_Cursor c) { + const char **xpm; + int hotx, hoty; + + // The standard arrow is our final fallback, so something is broken + // if we get called back here with that as an argument. + if (c == FL_CURSOR_ARROW) + return; + + switch (c) { + case FL_CURSOR_WAIT: + xpm = (const char**)fl_cursor_wait_xpm; + hotx = 7; + hoty = 9; + break; + case FL_CURSOR_HELP: + xpm = (const char**)fl_cursor_help_xpm; + hotx = 1; + hoty = 3; + break; + case FL_CURSOR_NWSE: + xpm = (const char**)fl_cursor_nwse_xpm; + hotx = 7; + hoty = 7; + break; + case FL_CURSOR_NESW: + xpm = (const char**)fl_cursor_nesw_xpm; + hotx = 7; + hoty = 7; + break; + case FL_CURSOR_NONE: + xpm = (const char**)fl_cursor_none_xpm; + hotx = 0; + hoty = 0; + break; + default: + w->cursor(FL_CURSOR_ARROW); + return; + } + + Fl_Pixmap pxm(xpm); + Fl_RGB_Image image(&pxm); - cursor(c, fg, bg); + w->cursor(&image, hotx, hoty); } -#ifdef WIN32 -# ifndef IDC_HAND -# define IDC_HAND MAKEINTRESOURCE(32649) -# endif // !IDC_HAND +void Fl_Window::cursor(Fl_Cursor c) { + int ret; -void Fl_Window::cursor(Fl_Cursor c, Fl_Color c1, Fl_Color c2) { - if (!shown()) return; // the cursor must be set for the top level window, not for subwindows Fl_Window *w = window(), *toplevel = this; - while (w) { toplevel = w; w = w->window(); } - if (toplevel != this) { toplevel->cursor(c, c1, c2); return; } - // now set the actual cursor - if (c == FL_CURSOR_DEFAULT) { - c = cursor_default; + + while (w) { + toplevel = w; + w = w->window(); } - if (c > FL_CURSOR_NESW) { - i->cursor = 0; - } else if (c == FL_CURSOR_DEFAULT) { - i->cursor = fl_default_cursor; - } else { - LPSTR n; - switch (c) { - case FL_CURSOR_ARROW: n = IDC_ARROW; break; - case FL_CURSOR_CROSS: n = IDC_CROSS; break; - case FL_CURSOR_WAIT: n = IDC_WAIT; break; - case FL_CURSOR_INSERT: n = IDC_IBEAM; break; - case FL_CURSOR_HELP: n = IDC_HELP; break; - case FL_CURSOR_HAND: { - OSVERSIONINFO osvi; - - // Get the OS version: Windows 98 and 2000 have a standard - // hand cursor. - memset(&osvi, 0, sizeof(OSVERSIONINFO)); - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - GetVersionEx(&osvi); - - if (osvi.dwMajorVersion > 4 || - (osvi.dwMajorVersion == 4 && osvi.dwMinorVersion > 0 && - osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)) n = IDC_HAND; - else n = IDC_UPARROW; - } break; - case FL_CURSOR_MOVE: n = IDC_SIZEALL; break; - case FL_CURSOR_N: - case FL_CURSOR_S: - case FL_CURSOR_NS: n = IDC_SIZENS; break; - case FL_CURSOR_NE: - case FL_CURSOR_SW: - case FL_CURSOR_NESW: n = IDC_SIZENESW; break; - case FL_CURSOR_E: - case FL_CURSOR_W: - case FL_CURSOR_WE: n = IDC_SIZEWE; break; - case FL_CURSOR_SE: - case FL_CURSOR_NW: - case FL_CURSOR_NWSE: n = IDC_SIZENWSE; break; - default: n = IDC_NO; break; - } - i->cursor = LoadCursor(NULL, n); + + if (toplevel != this) { + toplevel->cursor(c); + return; } - SetCursor(i->cursor); -} -#elif defined(__APPLE__) - -#ifdef __BIG_ENDIAN__ -# define E(x) x -#elif defined __LITTLE_ENDIAN__ -// Don't worry. This will be resolved at compile time -# define E(x) (x>>8)|((x<<8)&0xff00) -#else -# error "Either __LITTLE_ENDIAN__ or __BIG_ENDIAN__ must be defined" -#endif - -CGContextRef Fl_X::help_cursor_image(void) -{ - int w = 20, h = 20; - Fl_Offscreen off = Fl_Quartz_Graphics_Driver::create_offscreen_with_alpha(w, h); - fl_begin_offscreen(off); - CGContextSetRGBFillColor( (CGContextRef)off, 0,0,0,0); - fl_rectf(0,0,w,h); - fl_color(FL_BLACK); - fl_font(FL_COURIER_BOLD, 20); - fl_draw("?", 1, h-1); - fl_end_offscreen(); - return (CGContextRef)off; -} + if (c == FL_CURSOR_DEFAULT) + c = cursor_default; -CGContextRef Fl_X::none_cursor_image(void) -{ - int w = 20, h = 20; - Fl_Offscreen off = Fl_Quartz_Graphics_Driver::create_offscreen_with_alpha(w, h); - fl_begin_offscreen(off); - CGContextSetRGBFillColor( (CGContextRef)off, 0,0,0,0); - fl_rectf(0,0,w,h); - fl_end_offscreen(); - return (CGContextRef)off; -} + if (!i) + return; -CGContextRef Fl_X::watch_cursor_image(void) -{ - int w, h, r = 5; - w = 2*r+6; - h = 4*r; - Fl_Offscreen off = Fl_Quartz_Graphics_Driver::create_offscreen_with_alpha(w, h); - fl_begin_offscreen(off); - CGContextSetRGBFillColor( (CGContextRef)off, 0,0,0,0); - fl_rectf(0,0,w,h); - CGContextTranslateCTM( (CGContextRef)off, w/2, h/2); - fl_color(FL_WHITE); - fl_circle(0, 0, r+1); - fl_color(FL_BLACK); - fl_rectf(int(-r*0.7), int(-r*1.7), int(1.4*r), int(3.4*r)); - fl_rectf(r-1, -1, 3, 3); - fl_color(FL_WHITE); - fl_pie(-r, -r, 2*r, 2*r, 0, 360); - fl_color(FL_BLACK); - fl_circle(0,0,r); - fl_xyline(0, 0, int(-r*.7)); - fl_xyline(0, 0, 0, int(-r*.7)); - fl_end_offscreen(); - return (CGContextRef)off; -} + ret = i->set_cursor(c); + if (ret) + return; -CGContextRef Fl_X::nesw_cursor_image(void) -{ - int c = 7, r = 2*c; - int w = r, h = r; - Fl_Offscreen off = Fl_Quartz_Graphics_Driver::create_offscreen_with_alpha(w, h); - fl_begin_offscreen(off); - CGContextSetRGBFillColor( (CGContextRef)off, 0,0,0,0); - fl_rectf(0,0,w,h); - CGContextTranslateCTM( (CGContextRef)off, 0, h); - CGContextScaleCTM( (CGContextRef)off, 1, -1); - fl_color(FL_BLACK); - fl_polygon(0, 0, c, 0, 0, c); - fl_polygon(r, r, r, r-c, r-c, r); - fl_line_style(FL_SOLID, 2, 0); - fl_line(0,1, r,r+1); - fl_line_style(FL_SOLID, 0, 0); - fl_end_offscreen(); - return (CGContextRef)off; + fallback_cursor(this, c); } -CGContextRef Fl_X::nwse_cursor_image(void) -{ - int c = 7, r = 2*c; - int w = r, h = r; - Fl_Offscreen off = Fl_Quartz_Graphics_Driver::create_offscreen_with_alpha(w, h); - fl_begin_offscreen(off); - CGContextSetRGBFillColor( (CGContextRef)off, 0,0,0,0); - fl_rectf(0,0,w,h); - CGContextTranslateCTM( (CGContextRef)off, 0, h); - CGContextScaleCTM( (CGContextRef)off, 1, -1); - fl_color(FL_BLACK); - fl_polygon(r-1, 0, r-1, c, r-1-c, 0); - fl_polygon(-1, r, c-1, r, -1, r-c); - fl_line_style(FL_SOLID, 2, 0); - fl_line(r-1,1, -1,r+1); - fl_line_style(FL_SOLID, 0, 0); - fl_end_offscreen(); - return (CGContextRef)off; -} +/** + Changes the cursor for this window. This always calls the system, if + you are changing the cursor a lot you may want to keep track of how + you set it in a static variable and call this only if the new cursor + is different. -void Fl_Window::cursor(Fl_Cursor c, Fl_Color, Fl_Color) { - if (c == FL_CURSOR_DEFAULT) { - c = cursor_default; - } - if (i) i->set_cursor(c); -} + The default cursor will be used if the provided image cannot be used + as a cursor. -#else - -// I like the MSWindows resize cursors, so I duplicate them here: - -#define CURSORSIZE 16 -#define HOTXY 7 -static struct TableEntry { - uchar bits[CURSORSIZE*CURSORSIZE/8]; - uchar mask[CURSORSIZE*CURSORSIZE/8]; - Cursor cursor; -} table[] = { - {{ // FL_CURSOR_NS - 0x00, 0x00, 0x80, 0x01, 0xc0, 0x03, 0xe0, 0x07, 0x80, 0x01, 0x80, 0x01, - 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, - 0xe0, 0x07, 0xc0, 0x03, 0x80, 0x01, 0x00, 0x00}, - { - 0x80, 0x01, 0xc0, 0x03, 0xe0, 0x07, 0xf0, 0x0f, 0xf0, 0x0f, 0xc0, 0x03, - 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xf0, 0x0f, - 0xf0, 0x0f, 0xe0, 0x07, 0xc0, 0x03, 0x80, 0x01}}, - {{ // FL_CURSOR_EW - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, - 0x0c, 0x30, 0xfe, 0x7f, 0xfe, 0x7f, 0x0c, 0x30, 0x08, 0x10, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x1c, 0x38, - 0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0x1c, 0x38, 0x18, 0x18, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}, - {{ // FL_CURSOR_NWSE - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x38, 0x00, 0x78, 0x00, - 0xe8, 0x00, 0xc0, 0x01, 0x80, 0x03, 0x00, 0x17, 0x00, 0x1e, 0x00, 0x1c, - 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - { - 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0x7c, 0x00, 0xfc, 0x00, - 0xfc, 0x01, 0xec, 0x03, 0xc0, 0x37, 0x80, 0x3f, 0x00, 0x3f, 0x00, 0x3e, - 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00}}, - {{ // FL_CURSOR_NESW - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x1c, 0x00, 0x1e, - 0x00, 0x17, 0x80, 0x03, 0xc0, 0x01, 0xe8, 0x00, 0x78, 0x00, 0x38, 0x00, - 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x3e, 0x00, 0x3f, - 0x80, 0x3f, 0xc0, 0x37, 0xec, 0x03, 0xfc, 0x01, 0xfc, 0x00, 0x7c, 0x00, - 0xfc, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00}}, - {{0}, {0}} // FL_CURSOR_NONE & unknown -}; + \see cursor(Fl_Cursor), default_cursor() +*/ +void Fl_Window::cursor(const Fl_RGB_Image *image, int hotx, int hoty) { + int ret; -void Fl_Window::cursor(Fl_Cursor c, Fl_Color fg, Fl_Color bg) { - if (!shown()) return; - Cursor xc; - int deleteit = 0; - if (c == FL_CURSOR_DEFAULT) { - c = cursor_default; - fg = cursor_fg; - bg = cursor_bg; + // the cursor must be set for the top level window, not for subwindows + Fl_Window *w = window(), *toplevel = this; + + while (w) { + toplevel = w; + w = w->window(); } - if (!c) { - xc = None; - } else { - if (c >= FL_CURSOR_NS) { - TableEntry *q = (c > FL_CURSOR_NESW) ? table+4 : table+(c-FL_CURSOR_NS); - if (!(q->cursor)) { - XColor dummy = { 0 }; - Pixmap p = XCreateBitmapFromData(fl_display, - RootWindow(fl_display, fl_screen), (const char*)(q->bits), - CURSORSIZE, CURSORSIZE); - Pixmap m = XCreateBitmapFromData(fl_display, - RootWindow(fl_display, fl_screen), (const char*)(q->mask), - CURSORSIZE, CURSORSIZE); - q->cursor = XCreatePixmapCursor(fl_display, p,m,&dummy, &dummy, - HOTXY, HOTXY); - XFreePixmap(fl_display, m); - XFreePixmap(fl_display, p); - } - xc = q->cursor; - } else { - xc = XCreateFontCursor(fl_display, (c-1)*2); - deleteit = 1; - } - XColor fgc; - uchar r,g,b; - Fl::get_color(fg,r,g,b); - fgc.red = r<<8; fgc.green = g<<8; fgc.blue = b<<8; - XColor bgc; - Fl::get_color(bg,r,g,b); - bgc.red = r<<8; bgc.green = g<<8; bgc.blue = b<<8; - XRecolorCursor(fl_display, xc, &fgc, &bgc); + if (toplevel != this) { + toplevel->cursor(image, hotx, hoty); + return; } - XDefineCursor(fl_display, fl_xid(this), xc); - if (deleteit) XFreeCursor(fl_display, xc); + + if (!i) + return; + + ret = i->set_cursor(image, hotx, hoty); + if (ret) + return; + + cursor(FL_CURSOR_DEFAULT); } -#endif +/** + For back compatibility only. + Same as Fl_Window::cursor(Fl_Cursor) +*/ +void Fl_Window::cursor(Fl_Cursor c, Fl_Color, Fl_Color) { + cursor(c); +}; + +/** + For back compatibility only. + same as Fl_Window::default_cursor(Fl_Cursor) +*/ +void Fl_Window::default_cursor(Fl_Cursor c, Fl_Color, Fl_Color) { + default_cursor(c); +}; + // -// End of "$Id: fl_cursor.cxx 9278 2012-03-12 11:55:50Z manolo $". +// End of "$Id: fl_cursor.cxx 10405 2014-10-29 15:53:52Z manolo $". // diff --git a/src/fl_cursor_help.xpm b/src/fl_cursor_help.xpm new file mode 100644 index 0000000..2c21983 --- /dev/null +++ b/src/fl_cursor_help.xpm @@ -0,0 +1,39 @@ +/* XPM */ +static const char * const fl_cursor_help_xpm[] = { +"16 27 9 1", +" c None", +". c #FFFFFF", +"+ c #DBDBDB", +"@ c #242424", +"# c #000000", +"$ c #494949", +"% c #6D6D6D", +"& c #929292", +"* c #B6B6B6", +" ", +". ", +".+ ", +".@+ ", +".#@+ ", +".##@. ", +".###@. ", +".####@. ", +".#####$. ", +".######$. ", +".#######$. ", +".#####@@@%. ", +".#####+..... ", +".##$%#%. ", +".#$..@#. ", +".$. .&#%. ", +".. .##. .... ", +". .&#.+%$%&. ", +" ...*#@##%.", +" ++.*#@.", +" .%#$.", +" .%#@. ", +" .##+ ", +" .++. ", +" +##. ", +" +##. ", +" .... "}; diff --git a/src/fl_cursor_nesw.xpm b/src/fl_cursor_nesw.xpm new file mode 100644 index 0000000..4fbdcc9 --- /dev/null +++ b/src/fl_cursor_nesw.xpm @@ -0,0 +1,46 @@ +/* XPM */ +static const char * const fl_cursor_nesw_xpm[] = { +"15 15 28 1", +" c None", +". c #FFFFFF", +"+ c #767676", +"@ c #000000", +"# c #4E4E4E", +"$ c #0C0C0C", +"% c #494949", +"& c #4D4D4D", +"* c #1B1B1B", +"= c #515151", +"- c #646464", +"; c #363636", +"> c #6A6A6A", +", c #545454", +"' c #585858", +") c #242424", +"! c #797979", +"~ c #2E2E2E", +"{ c #444444", +"] c #3B3B3B", +"^ c #0A0A0A", +"/ c #595959", +"( c #F7F7F7", +"_ c #080808", +": c #6B6B6B", +"< c #FDFDFD", +"[ c #FCFCFC", +"} c #FEFEFE", +" ..........", +" .+@@@@@@.", +" .#@@@@@.", +" .$@@@@.", +" .%@@@@@.", +". .&@@@*@@.", +".. .=@@@-.;@.", +".>. .,@@@'. .).", +".@!.'@@@#. ..", +".@@~@@@{. .", +".@@@@@]. ", +".@@@@^. ", +".@@@@@/( ", +".______:( ", +"<[[[[[[[[} "}; diff --git a/src/fl_cursor_none.xpm b/src/fl_cursor_none.xpm new file mode 100644 index 0000000..fb53c6d --- /dev/null +++ b/src/fl_cursor_none.xpm @@ -0,0 +1,19 @@ +/* XPM */ +static const char * const fl_cursor_none_xpm[] = { +"15 15 1 1", +" c None", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" "}; diff --git a/src/fl_cursor_nwse.xpm b/src/fl_cursor_nwse.xpm new file mode 100644 index 0000000..f5e4ebb --- /dev/null +++ b/src/fl_cursor_nwse.xpm @@ -0,0 +1,46 @@ +/* XPM */ +static const char * const fl_cursor_nwse_xpm[] = { +"15 15 28 1", +" c None", +". c #FFFFFF", +"+ c #000000", +"@ c #767676", +"# c #4E4E4E", +"$ c #0C0C0C", +"% c #494949", +"& c #1B1B1B", +"* c #4D4D4D", +"= c #363636", +"- c #646464", +"; c #515151", +"> c #242424", +", c #585858", +"' c #545454", +") c #6A6A6A", +"! c #797979", +"~ c #444444", +"{ c #2E2E2E", +"] c #3B3B3B", +"^ c #0A0A0A", +"/ c #F7F7F7", +"( c #595959", +"_ c #6B6B6B", +": c #080808", +"< c #FEFEFE", +"[ c #FCFCFC", +"} c #FDFDFD", +".......... ", +".++++++@. ", +".+++++#. ", +".++++$. ", +".+++++%. ", +".++&+++*. .", +".+=.-+++;. ..", +".>. .,+++'. .).", +".. .#+++,.!+.", +". .~+++{++.", +" .]+++++.", +" .^++++.", +" /(+++++.", +" /_::::::.", +" <[[[[[[[[}"}; diff --git a/src/fl_cursor_wait.xpm b/src/fl_cursor_wait.xpm new file mode 100644 index 0000000..da02784 --- /dev/null +++ b/src/fl_cursor_wait.xpm @@ -0,0 +1,28 @@ +/* XPM */ +static const char * const fl_cursor_wait_xpm[] = { +/* width height ncolors chars_per_pixel */ +"13 18 3 1", +/* colors */ +" c None", +". c #FFFFFF", +"B c #000000", +/* pixels */ +" ........ ", +" .BBBBBB. ", +" .BBBBBB. ", +" .BBBBBB. ", +" .BBBBBB. ", +" .B......B. ", +".B....B...B. ", +".B....B...B. ", +".B....B...BB.", +".B.BBBB...BB.", +".B........B. ", +".B........B. ", +" .B......B. ", +" .BBBBBB. ", +" .BBBBBB. ", +" .BBBBBB. ", +" .BBBBBB. ", +" ........ ", +}; diff --git a/src/fl_diamond_box.cxx b/src/fl_diamond_box.cxx index b775e05..db2bfb2 100644 --- a/src/fl_diamond_box.cxx +++ b/src/fl_diamond_box.cxx @@ -1,5 +1,5 @@ // -// "$Id: fl_diamond_box.cxx 8864 2011-07-19 04:49:30Z greg.ercolano $" +// "$Id: fl_diamond_box.cxx 10306 2014-09-13 16:49:47Z manolo $" // // Diamond box code for the Fast Light Tool Kit (FLTK). // @@ -25,7 +25,7 @@ #include <FL/Fl.H> #include <FL/fl_draw.H> -extern uchar* fl_gray_ramp(); +extern const uchar* fl_gray_ramp(); static void fl_diamond_up_box(int x,int y,int w,int h,Fl_Color bgcolor) { w &= -2; @@ -33,14 +33,14 @@ static void fl_diamond_up_box(int x,int y,int w,int h,Fl_Color bgcolor) { int x1 = x+w/2; int y1 = y+h/2; fl_color(bgcolor); fl_polygon(x+3, y1, x1,y+3, x+w-3,y1, x1,y+h-3); - uchar *g = fl_gray_ramp(); - fl_color(g['W']); fl_line(x+1, y1, x1, y+1, x+w-1, y1); - fl_color(g['U']); fl_line(x+2, y1, x1, y+2, x+w-2, y1); - fl_color(g['S']); fl_line(x+3, y1, x1, y+3, x+w-3, y1); - fl_color(g['P']); fl_line(x+3, y1, x1, y+h-3, x+w-3, y1); - fl_color(g['N']); fl_line(x+2, y1, x1, y+h-2, x+w-2, y1); - fl_color(g['H']); fl_line(x+1, y1, x1, y+h-1, x+w-1, y1); - fl_color(g['A']); fl_loop(x, y1, x1, y, x+w, y1, x1, y+h); + const uchar *g = fl_gray_ramp(); + fl_color(g[(int)'W']); fl_line(x+1, y1, x1, y+1, x+w-1, y1); + fl_color(g[(int)'U']); fl_line(x+2, y1, x1, y+2, x+w-2, y1); + fl_color(g[(int)'S']); fl_line(x+3, y1, x1, y+3, x+w-3, y1); + fl_color(g[(int)'P']); fl_line(x+3, y1, x1, y+h-3, x+w-3, y1); + fl_color(g[(int)'N']); fl_line(x+2, y1, x1, y+h-2, x+w-2, y1); + fl_color(g[(int)'H']); fl_line(x+1, y1, x1, y+h-1, x+w-1, y1); + fl_color(g[(int)'A']); fl_loop(x, y1, x1, y, x+w, y1, x1, y+h); } static void fl_diamond_down_box(int x,int y,int w,int h,Fl_Color bgcolor) { @@ -48,15 +48,15 @@ static void fl_diamond_down_box(int x,int y,int w,int h,Fl_Color bgcolor) { h &= -2; int x1 = x+w/2; int y1 = y+h/2; - uchar *g = fl_gray_ramp(); - fl_color(g['P']); fl_line(x+0, y1, x1, y+0, x+w-0, y1); - fl_color(g['N']); fl_line(x+1, y1, x1, y+1, x+w-1, y1); - fl_color(g['H']); fl_line(x+2, y1, x1, y+2, x+w-2, y1); - fl_color(g['W']); fl_line(x+2, y1, x1, y+h-2, x+w-2, y1); - fl_color(g['U']); fl_line(x+1, y1, x1, y+h-1, x+w-1, y1); - fl_color(g['S']); fl_line(x+0, y1, x1, y+h-0, x+w-0, y1); + const uchar *g = fl_gray_ramp(); + fl_color(g[(int)'P']); fl_line(x+0, y1, x1, y+0, x+w-0, y1); + fl_color(g[(int)'N']); fl_line(x+1, y1, x1, y+1, x+w-1, y1); + fl_color(g[(int)'H']); fl_line(x+2, y1, x1, y+2, x+w-2, y1); + fl_color(g[(int)'W']); fl_line(x+2, y1, x1, y+h-2, x+w-2, y1); + fl_color(g[(int)'U']); fl_line(x+1, y1, x1, y+h-1, x+w-1, y1); + fl_color(g[(int)'S']); fl_line(x+0, y1, x1, y+h-0, x+w-0, y1); fl_color(bgcolor); fl_polygon(x+3, y1, x1,y+3, x+w-3,y1, x1,y+h-3); - fl_color(g['A']); fl_loop(x+3, y1, x1, y+3, x+w-3, y1, x1, y+h-3); + fl_color(g[(int)'A']); fl_loop(x+3, y1, x1, y+3, x+w-3, y1, x1, y+h-3); } extern void fl_internal_boxtype(Fl_Boxtype, Fl_Box_Draw_F*); @@ -67,5 +67,5 @@ Fl_Boxtype fl_define_FL_DIAMOND_BOX() { } // -// End of "$Id: fl_diamond_box.cxx 8864 2011-07-19 04:49:30Z greg.ercolano $". +// End of "$Id: fl_diamond_box.cxx 10306 2014-09-13 16:49:47Z manolo $". // diff --git a/src/fl_dnd_x.cxx b/src/fl_dnd_x.cxx index 6d47a46..b5fe857 100644 --- a/src/fl_dnd_x.cxx +++ b/src/fl_dnd_x.cxx @@ -1,5 +1,5 @@ // -// "$Id: fl_dnd_x.cxx 8864 2011-07-19 04:49:30Z greg.ercolano $" +// "$Id: fl_dnd_x.cxx 9979 2013-09-20 03:36:02Z greg.ercolano $" // // Drag & Drop code for the Fast Light Tool Kit (FLTK). // @@ -55,9 +55,11 @@ static int dnd_aware(Window& window) { 0, 4, False, XA_ATOM, &actual, &format, &count, &remaining, &data); + int ret = 0; if (actual == XA_ATOM && format==32 && count && data) - return int(*(Atom*)data); - return 0; + ret = int(*(Atom*)data); + if (data) { XFree(data); data = 0; } + return ret; } static int grabfunc(int event) { @@ -189,5 +191,5 @@ int Fl::dnd() { // -// End of "$Id: fl_dnd_x.cxx 8864 2011-07-19 04:49:30Z greg.ercolano $". +// End of "$Id: fl_dnd_x.cxx 9979 2013-09-20 03:36:02Z greg.ercolano $". // diff --git a/src/fl_draw.cxx b/src/fl_draw.cxx index 2fa499b..355b04a 100644 --- a/src/fl_draw.cxx +++ b/src/fl_draw.cxx @@ -1,5 +1,5 @@ // -// "$Id: fl_draw.cxx 9326 2012-04-05 14:30:19Z AlbrechtS $" +// "$Id: fl_draw.cxx 10265 2014-09-03 10:07:33Z AlbrechtS $" // // Label drawing code for the Fast Light Tool Kit (FLTK). // @@ -32,83 +32,28 @@ #include <ctype.h> #include <math.h> -#define MAXBUF 1024 char fl_draw_shortcut; // set by fl_labeltypes.cxx static char* underline_at; -/** - utf8 multibyte char seq. detection an pass-thru routine. - \retval false if no utf8 seq detected, no change made. true if utf8 and d copied with s seq. - note that for n bytes copied dest incremented of n, but s of n-1 for compatible loop use see below. -*/ -#define C_IN(c,a,b) ((c)>=(a) && (c)<=(b)) -#define C_UTF8(c) C_IN(c,0x80,0xBF) - -static bool handle_utf8_seq(const char * &s,char * &d) { - register const unsigned char* p=(const unsigned char*)s; - if (p[0] < 0xc2 || p[0] > 0xf4) - return false; // not adressed in this function - else if ( C_IN(p[0], 0xc2, 0xdf) && C_UTF8(p[1]) ) { - d[0]=s[0]; d[1]=s[1]; - d+=2; s++; - // non-overlong 2-byte - } - else if ( p[0]==0xe0 && C_IN(p[1], 0xa0, 0xbf) && C_UTF8(p[2]) ) { - d[0]=s[0]; d[1]=s[1];d[2]=s[2]; - d+=3; s+=2; - // excluding overlongs - } - else if (p[0]==0xed && C_IN(p[1], 0x80, 0x9f) && C_UTF8(p[2]) ) { - d[0]=s[0]; d[1]=s[1];d[2]=s[2]; - d+=3; s+=2; - // excluding surrogates - } - else if (p[0]!=0xed && C_IN(p[0], 0xe1, 0xef) && C_UTF8(p[1]) && C_UTF8(p[2]) ) { - d[0]=s[0]; d[1]=s[1];d[2]=s[2]; - d+=3; s+=2; - // straight 3-byte - } - else if (p[0]==0xf0 && C_IN(p[1], 0x90, 0xbf) && C_UTF8(p[2]) && C_UTF8(p[3]) ) { - d[0]=s[0]; d[1]=s[1]; d[2]=s[2]; d[3]=s[3]; - d+=4; s+=3; - // planes 1-3 - } - else if (C_IN(p[0], 0xf1, 0xf3) && C_UTF8(p[1]) && C_UTF8(p[2]) && C_UTF8(p[3]) ) { - d[0]=s[0]; d[1]=s[1]; d[2]=s[2]; d[3]=s[3]; - d+=4; s+=3; - // planes 4-15 - } - else if (p[0]==0xf4 && C_IN(p[1], 0x80, 0x8f) && C_UTF8(p[2]) && C_UTF8(p[3]) ) { - d[0]=s[0]; d[1]=s[1]; d[2]=s[2]; d[3]=s[3]; - d+=4; s+=3; - // planes 16 - } else { // non utf8 compliant, maybe CP125x or broken utf8 string - // fprintf(stderr, "Not UTF8 char \n"); - return false; - } - return true; // we did handled and copied the utf8 multibyte char seq. -} - -/** - Copy \p from to \p buf, replacing unprintable characters with ^X and \\nnn. - - Stop at a newline or if MAXBUF characters written to buffer. - Also word-wrap if width exceeds maxw. - Returns a pointer to the start of the next line of characters. - Sets n to the number of characters put into the buffer. - Sets width to the width of the string in the current font. -*/ -const char* -fl_expand_text(const char* from, char* buf, int maxbuf, double maxw, int& n, - double &width, int wrap, int draw_symbols) { - char* o = buf; +/* If called with maxbuf==0, use an internally allocated buffer and enlarge it as needed. + Otherwise, use buf as buffer but don't go beyond its length of maxbuf. + */ +static const char* expand_text_(const char* from, char*& buf, int maxbuf, double maxw, int& n, + double &width, int wrap, int draw_symbols) { char* e = buf+(maxbuf-4); underline_at = 0; + double w = 0; + static int l_local_buff = 500; + static char *local_buf = (char*)malloc(l_local_buff); // initial buffer allocation + if (maxbuf == 0) { + buf = local_buf; + e = buf + l_local_buff - 4; + } + char* o = buf; char* word_end = o; const char* word_start = from; - double w = 0; const char* p = from; for (;; p++) { @@ -132,10 +77,18 @@ fl_expand_text(const char* from, char* buf, int maxbuf, double maxw, int& n, word_start = p+1; } - if (o > e) break; // don't overflow buffer + if (o > e) { + if (maxbuf) break; // don't overflow buffer + l_local_buff += (o - e) + 200; // enlarge buffer + buf = (char*)realloc(local_buf, l_local_buff); + e = buf + l_local_buff - 4; // update pointers to buffer content + o = buf + (o - local_buf); + word_end = buf + (word_end - local_buf); + local_buf = buf; + } if (c == '\t') { - for (c = fl_utf_nb_char((uchar*)buf, (int) (o-buf) )%8; c<8 && o<e; c++) + for (c = fl_utf_nb_char((uchar*)buf, (int) (o-buf) )%8; c<8 && o<e; c++) *o++ = ' '; } else if (c == '&' && fl_draw_shortcut && *(p+1)) { if (*(p+1) == '&') {p++; *o++ = '&';} @@ -143,14 +96,17 @@ fl_expand_text(const char* from, char* buf, int maxbuf, double maxw, int& n, } else if (c < ' ' || c == 127) { // ^X *o++ = '^'; *o++ = c ^ 0x40; - } else if (handle_utf8_seq(p, o)) { // figure out if we have an utf8 valid sequence before we determine the nbsp test validity: +/* This is in fact not useful: the point is that a valid UTF-8 sequence for a non-ascii char contains no ascii char, + thus no tab, space, control, & or @ we want to process differently. + Also, invalid UTF-8 sequences are copied unchanged by this procedure. + Therefore, checking for tab, space, control, & or @, and copying the byte otherwise, is enough. + } else if (handle_utf8_seq(p, o)) { // figure out if we have an utf8 valid sequence before we determine the nbsp test validity: #ifdef __APPLE__ } else if (c == 0xCA) { // non-breaking space in MacRoman #else } else if (c == 0xA0) { // non-breaking space in ISO 8859 #endif - *o++ = ' '; - + *o++ = ' ';*/ } else if (c == '@' && draw_symbols) { // Symbol??? if (p[1] && p[1] != '@') break; *o++ = c; @@ -167,6 +123,21 @@ fl_expand_text(const char* from, char* buf, int maxbuf, double maxw, int& n, } /** + Copy \p from to \p buf, replacing control characters with ^X. + + Stop at a newline or if \p maxbuf characters written to buffer. + Also word-wrap if width exceeds maxw. + Returns a pointer to the start of the next line of characters. + Sets n to the number of characters put into the buffer. + Sets width to the width of the string in the current font. + */ +const char* +fl_expand_text(const char* from, char* buf, int maxbuf, double maxw, int& n, + double &width, int wrap, int draw_symbols) { + return expand_text_(from, buf, maxbuf, maxw, n, width, wrap, draw_symbols); +} + +/** The same as fl_draw(const char*,int,int,int,int,Fl_Align,Fl_Image*,int) with the addition of the \p callthis parameter, which is a pointer to a text drawing function such as fl_draw(const char*, int, int, int) to do the real work @@ -176,11 +147,11 @@ void fl_draw( int x, int y, int w, int h, // bounding box Fl_Align align, void (*callthis)(const char*,int,int,int), - Fl_Image* img, int draw_symbols) + Fl_Image* img, int draw_symbols) { + char *linebuf = NULL; const char* p; const char* e; - char buf[MAXBUF]; int buflen; char symbol[2][255], *symptr; int symwidth[2], symoffset, symtotal, imgtotal; @@ -191,7 +162,7 @@ void fl_draw( // if the image is set as a backdrop, ignore it here if (img && (align & FL_ALIGN_IMAGE_BACKDROP)) img = 0; - + symbol[0][0] = '\0'; symwidth[0] = 0; @@ -217,13 +188,13 @@ void fl_draw( symtotal = symwidth[0] + symwidth[1]; imgtotal = (img && (align&FL_ALIGN_IMAGE_NEXT_TO_TEXT)) ? img->w() : 0; - + int strw = 0; int strh; if (str) { for (p = str, lines=0; p;) { - e = fl_expand_text(p, buf, MAXBUF, w - symtotal - imgtotal, buflen, width, + e = expand_text_(p, linebuf, 0, w - symtotal - imgtotal, buflen, width, align&FL_ALIGN_WRAP, draw_symbols); if (strw<width) strw = (int)width; lines++; @@ -231,7 +202,7 @@ void fl_draw( p = e; } } else lines = 0; - + if ((symwidth[0] || symwidth[1]) && lines) { if (symwidth[0]) symwidth[0] = lines * fl_height(); if (symwidth[1]) symwidth[1] = lines * fl_height(); @@ -239,7 +210,7 @@ void fl_draw( symtotal = symwidth[0] + symwidth[1]; strh = lines * fl_height(); - + // figure out vertical position of the first line: int xpos; int ypos; @@ -285,12 +256,12 @@ void fl_draw( else yimg += (strh - img->h() - 1) / 2; img->draw(xpos, yimg); } - + // now draw all the lines: if (str) { int desc = fl_descent(); for (p=str; ; ypos += height) { - if (lines>1) e = fl_expand_text(p, buf, MAXBUF, w - symtotal - imgtotal, buflen, + if (lines>1) e = expand_text_(p, linebuf, 0, w - symtotal - imgtotal, buflen, width, align&FL_ALIGN_WRAP, draw_symbols); else e = ""; @@ -300,10 +271,10 @@ void fl_draw( else if (align & FL_ALIGN_RIGHT) xpos = x + w - (int)(width + .5) - symwidth[1] - imgw[1]; else xpos = x + (w - (int)(width + .5) - symtotal - imgw[0] - imgw[1]) / 2 + symwidth[0] + imgw[0]; - callthis(buf,buflen,xpos,ypos-desc); + callthis(linebuf,buflen,xpos,ypos-desc); - if (underline_at && underline_at >= buf && underline_at < (buf + buflen)) - callthis("_",1,xpos+int(fl_width(buf,(int) (underline_at-buf))),ypos-desc); + if (underline_at && underline_at >= linebuf && underline_at < (linebuf + buflen)) + callthis("_",1,xpos+int(fl_width(linebuf,(int) (underline_at-linebuf))),ypos-desc); if (!*e || (*e == '@' && e[1] != '@')) break; p = e; @@ -361,7 +332,6 @@ void fl_draw( below the text as specified by the \p align value. The \p draw_symbols argument specifies whether or not to look for symbol names starting with the '\@' character' - The text length is limited to 1024 characters per line. */ void fl_draw( const char* str, @@ -372,10 +342,10 @@ void fl_draw( { if ((!str || !*str) && !img) return; if (w && h && !fl_not_clipped(x, y, w, h) && (align & FL_ALIGN_INSIDE)) return; - if (align & FL_ALIGN_CLIP) + if (align & FL_ALIGN_CLIP) fl_push_clip(x, y, w, h); fl_draw(str, x, y, w, h, align, fl_draw, img, draw_symbols); - if (align & FL_ALIGN_CLIP) + if (align & FL_ALIGN_CLIP) fl_pop_clip(); } @@ -383,7 +353,7 @@ void fl_draw( Measure how wide and tall the string will be when printed by the fl_draw() function with \p align parameter. If the incoming \p w is non-zero it will wrap to that width. - + The 'current font' is used to do the width/height calculations, so unless its value is known at the time fl_measure() is called, it is advised to first set the current font with fl_font(). @@ -406,45 +376,38 @@ void fl_draw( void fl_measure(const char* str, int& w, int& h, int draw_symbols) { if (!str || !*str) {w = 0; h = 0; return;} h = fl_height(); + char *linebuf = NULL; const char* p; const char* e; - char buf[MAXBUF]; int buflen; int lines; double width=0; int W = 0; - char symbol[2][255], *symptr; int symwidth[2], symtotal; - // count how many lines and put the last one into the buffer: - symbol[0][0] = '\0'; - symwidth[0] = 0; - - symbol[1][0] = '\0'; - symwidth[1] = 0; + symwidth[0] = 0; // size of symbol at beginning of string (if any) + symwidth[1] = 0; // size of symbol at end of string (if any) if (draw_symbols) { - if (str && str[0] == '@' && str[1] && str[1] != '@') { - // Start with a symbol... - for (symptr = symbol[0]; - *str && !isspace(*str) && symptr < (symbol[0] + sizeof(symbol[0]) - 1); - *symptr++ = *str++); - *symptr = '\0'; - if (isspace(*str)) str++; + // Symbol at beginning of string? + const char *sym2 = (str[0]=='@' && str[1]=='@') ? str+2 : str; // sym2 check will skip leading @@ + if (str[0] == '@' && str[1] != '@') { + while (*str && !isspace(*str)) { ++str; } // skip over symbol + if (isspace(*str)) ++str; // skip over trailing space + sym2 = str; // sym2 check will skip leading symbol symwidth[0] = h; } - - if (str && (p = strrchr(str, '@')) != NULL && p > (str + 1) && p[-1]!='@') { - strlcpy(symbol[1], p, sizeof(symbol[1])); + // Symbol at end of string? + if ((p=strchr(sym2,'@')) != NULL && p[1] != '@') { symwidth[1] = h; } } symtotal = symwidth[0] + symwidth[1]; - + for (p = str, lines=0; p;) { -// e = expand(p, buf, w - symtotal, buflen, width, w != 0, draw_symbols); - e = fl_expand_text(p, buf, MAXBUF, w - symtotal, buflen, width, +// e = expand(p, linebuf, w - symtotal, buflen, width, w != 0, draw_symbols); + e = expand_text_(p, linebuf, 0, w - symtotal, buflen, width, w != 0, draw_symbols); if ((int)ceil(width) > W) W = (int)ceil(width); lines++; @@ -469,13 +432,13 @@ void fl_measure(const char* str, int& w, int& h, int draw_symbols) { but with the advent of XFT, there are (currently) complexities that seem to only be solved by asking the font what its actual font height is. (See STR#2115) - + This function was originally undocumented in 1.1.x, and was used only by Fl_Text_Display. We're now documenting it in 1.3.x so that apps that need precise height info can get it with this function. \returns the height of the font in pixels. - + \todo In the future, when the XFT issues are resolved, this function should simply return the 'size' value. */ @@ -489,5 +452,5 @@ int fl_height(int font, int size) { } // -// End of "$Id: fl_draw.cxx 9326 2012-04-05 14:30:19Z AlbrechtS $". +// End of "$Id: fl_draw.cxx 10265 2014-09-03 10:07:33Z AlbrechtS $". // diff --git a/src/fl_draw_pixmap.cxx b/src/fl_draw_pixmap.cxx index 7a85b76..8440d55 100644 --- a/src/fl_draw_pixmap.cxx +++ b/src/fl_draw_pixmap.cxx @@ -1,5 +1,5 @@ // -// "$Id: fl_draw_pixmap.cxx 9375 2012-04-22 03:09:31Z fabien $" +// "$Id: fl_draw_pixmap.cxx 10242 2014-08-22 10:28:50Z AlbrechtS $" // // Pixmap drawing code for the Fast Light Tool Kit (FLTK). // @@ -16,6 +16,9 @@ // http://www.fltk.org/str.php // +// NOTE: I believe many of the following comments (between the dash markers) +// are no longer accurate: +// -------------------------------------------------------------------- // Implemented without using the xpm library (which I can't use because // it interferes with the color cube used by fl_draw_image). // Current implementation is cheap and slow, and works best on a full-color @@ -25,6 +28,9 @@ // Notice that there is no pixmap file interface. This is on purpose, // as I want to discourage programs that require support files to work. // All data needed by a program ui should be compiled in!!! +// -------------------------------------------------------------------- +// The above comments were checked in as r2, and much has changed since then; +// transparency added, color cube not required, etc. -erco Oct 20 2013 #include <FL/Fl.H> #include <FL/fl_draw.H> @@ -37,7 +43,7 @@ static int ncolors, chars_per_pixel; /** Get the dimensions of a pixmap. An XPM image contains the dimensions in its data. This function - returns te width and height. + returns the width and height. \param[in] data pointer to XPM image data. \param[out] w,h width and height of image \returns non-zero if the dimensions were parsed OK @@ -58,99 +64,6 @@ int fl_measure_pixmap(const char * const *cdata, int &w, int &h) { return 1; } -#ifdef U64 - -// The callback from fl_draw_image to get a row of data passes this: -struct pixmap_data { - int w, h; - const uchar*const* data; - union { - U64 colors[256]; - U64* byte1[256]; - }; -}; - -// callback for 1 byte per pixel: -static void cb1(void*v, int x, int y, int w, uchar* buf) { - pixmap_data& d = *(pixmap_data*)v; - const uchar* p = d.data[y]+x; - U64* q = (U64*)buf; - for (int X=w; X>0; X-=2, p += 2) { - if (X>1) { -# if WORDS_BIGENDIAN - *q++ = (d.colors[p[0]]<<32) | d.colors[p[1]]; -# else - *q++ = (d.colors[p[1]]<<32) | d.colors[p[0]]; -# endif - } else { -# if WORDS_BIGENDIAN - *q++ = d.colors[p[0]]<<32; -# else - *q++ = d.colors[p[0]]; -# endif - } - } -} - -// callback for 2 bytes per pixel: -static void cb2(void*v, int x, int y, int w, uchar* buf) { - pixmap_data& d = *(pixmap_data*)v; - const uchar* p = d.data[y]+2*x; - U64* q = (U64*)buf; - for (int X=w; X>0; X-=2) { - U64* colors = d.byte1[*p++]; - int index = *p++; - if (X>1) { - U64* colors1 = d.byte1[*p++]; - int index1 = *p++; -# if WORDS_BIGENDIAN - *q++ = (colors[index]<<32) | colors1[index1]; -# else - *q++ = (colors1[index1]<<32) | colors[index]; -# endif - } else { -# if WORDS_BIGENDIAN - *q++ = colors[index]<<32; -# else - *q++ = colors[index]; -# endif - } - } -} - -#else // U32 - -// The callback from fl_draw_image to get a row of data passes this: -struct pixmap_data { - int w, h; - const uchar*const* data; - union { - U32 colors[256]; - U32* byte1[256]; - }; -}; - -// callback for 1 byte per pixel: -static void cb1(void*v, int x, int y, int w, uchar* buf) { - pixmap_data& d = *(pixmap_data*)v; - const uchar* p = d.data[y]+x; - U32* q = (U32*)buf; - for (int X=w; X--;) *q++ = d.colors[*p++]; -} - -// callback for 2 bytes per pixel: -static void cb2(void*v, int x, int y, int w, uchar* buf) { - pixmap_data& d = *(pixmap_data*)v; - const uchar* p = d.data[y]+2*x; - U32* q = (U32*)buf; - for (int X=w; X--;) { - U32* colors = d.byte1[*p++]; - *q++ = colors[*p++]; - } -} - -#endif // U64 else U32 - uchar **fl_mask_bitmap; // if non-zero, create bitmap and store pointer here /** @@ -169,50 +82,58 @@ int fl_draw_pixmap(/*const*/ char* const* data, int x,int y,Fl_Color bg) { #ifdef WIN32 // to compute an unused color to be used for the pixmap background FL_EXPORT UINT win_pixmap_bg_color; // the RGB() of the pixmap background color -static int color_count; // # of non-transparent colors used in pixmap -static uchar *used_colors; // used_colors[3*i+j] j=0,1,2 are the RGB values of the ith used color +static int color_count; // # of non-transparent colors used in pixmap +typedef struct { uchar r; uchar g; uchar b; } UsedColor; +static UsedColor *used_colors; -static void make_unused_color(uchar &r, uchar &g, uchar &b) -// makes an RGB triplet different from all the colors used in the pixmap +// Makes an RGB triplet different from all the colors used in the pixmap // and compute win_pixmap_bg_color from this triplet -{ +static void make_unused_color(uchar &r, uchar &g, uchar &b) { int i; r = 2; g = 3; b = 4; while (1) { - for ( i = 0; i < color_count; i++) { - if(used_colors[3*i] == r && used_colors[3*i+1] == g && used_colors[3*i+2] == b) break; - } + for ( i=0; i<color_count; i++ ) + if ( used_colors[i].r == r && + used_colors[i].g == g && + used_colors[i].b == b ) + break; if (i >= color_count) { - free(used_colors); + free((void*)used_colors); used_colors = NULL; win_pixmap_bg_color = RGB(r, g, b); return; - } - if (r < 255) r++; - else { + } + if (r < 255) { + r++; + } else { r = 0; - if (g < 255) g++; - else { + if (g < 255) { + g++; + } else { g = 0; b++; - } } } + } } #endif -/** - Draw XPM image data, with the top-left corner at the given position. - \see fl_draw_pixmap(char* const* data, int x, int y, Fl_Color bg) - */ -int fl_draw_pixmap(const char*const* cdata, int x, int y, Fl_Color bg) { - pixmap_data d; - if (!fl_measure_pixmap(cdata, d.w, d.h)) return 0; +int fl_convert_pixmap(const char*const* cdata, uchar* out, Fl_Color bg) { + int w, h; const uchar*const* data = (const uchar*const*)(cdata+1); - int transparent_index = -1; + + if (!fl_measure_pixmap(cdata, w, h)) + return 0; + + if ((chars_per_pixel < 1) || (chars_per_pixel > 2)) + return 0; + + typedef uchar uchar4[4]; + uchar4 *colors = new uchar4[1<<(chars_per_pixel*8)]; + #ifdef WIN32 uchar *transparent_c = (uchar *)0; // such that transparent_c[0,1,2] are the RGB of the transparent color color_count = 0; - used_colors = (uchar *)malloc(abs(ncolors)*3*sizeof(uchar)); + used_colors = (UsedColor*)malloc(abs(ncolors) * sizeof(UsedColor)); #endif if (ncolors < 0) { // FLTK (non standard) compressed colormap @@ -221,14 +142,7 @@ int fl_draw_pixmap(const char*const* cdata, int x, int y, Fl_Color bg) { // if first color is ' ' it is transparent (put it later to make // it not be transparent): if (*p == ' ') { - uchar* c = (uchar*)&d.colors[(int)' ']; -#ifdef U64 - *(U64*)c = 0; -# if WORDS_BIGENDIAN - c += 4; -# endif -#endif - transparent_index = ' '; + uchar* c = colors[(int)' ']; Fl::get_color(bg, c[0], c[1], c[2]); c[3] = 0; #ifdef WIN32 transparent_c = c; @@ -238,48 +152,27 @@ int fl_draw_pixmap(const char*const* cdata, int x, int y, Fl_Color bg) { } // read all the rest of the colors: for (int i=0; i < ncolors; i++) { - uchar* c = (uchar*)&d.colors[*p++]; -#ifdef U64 - *(U64*)c = 0; -# if WORDS_BIGENDIAN - c += 4; -# endif -#endif + uchar* c = colors[*p++]; #ifdef WIN32 - used_colors[3*color_count] = *p; - used_colors[3*color_count+1] = *(p+1); - used_colors[3*color_count+2] = *(p+2); + used_colors[color_count].r = *(p+0); + used_colors[color_count].g = *(p+1); + used_colors[color_count].b = *(p+2); color_count++; #endif *c++ = *p++; *c++ = *p++; *c++ = *p++; -#ifdef __APPLE_QUARTZ__ *c = 255; -#else - *c = 0; -#endif } } else { // normal XPM colormap with names - if (chars_per_pixel>1) memset(d.byte1, 0, sizeof(d.byte1)); for (int i=0; i<ncolors; i++) { const uchar *p = *data++; // the first 1 or 2 characters are the color index: int ind = *p++; uchar* c; - if (chars_per_pixel>1) { -#ifdef U64 - U64* colors = d.byte1[ind]; - if (!colors) colors = d.byte1[ind] = new U64[256]; -#else - U32* colors = d.byte1[ind]; - if (!colors) colors = d.byte1[ind] = new U32[256]; -#endif - c = (uchar*)&colors[*p]; + if (chars_per_pixel>1) ind = (ind<<8)|*p++; - } else { - c = (uchar *)&d.colors[ind]; - } + c = colors[ind]; // look for "c word", or last word if none: const uchar *previous_word = p; for (;;) { @@ -292,122 +185,109 @@ int fl_draw_pixmap(const char*const* cdata, int x, int y, Fl_Color bg) { previous_word = p; while (*p && !isspace(*p)) p++; } -#ifdef U64 - *(U64*)c = 0; -# if WORDS_BIGENDIAN - c += 4; -# endif -#endif -#ifdef __APPLE_QUARTZ__ - c[3] = 255; -#endif int parse = fl_parse_color((const char*)p, c[0], c[1], c[2]); + c[3] = 255; if (parse) { #ifdef WIN32 - used_colors[3*color_count] = c[0]; - used_colors[3*color_count+1] = c[1]; - used_colors[3*color_count+2] = c[2]; + used_colors[color_count].r = c[0]; + used_colors[color_count].g = c[1]; + used_colors[color_count].b = c[2]; color_count++; #endif - } - else { + } else { // assume "None" or "#transparent" for any errors // "bg" should be transparent... Fl::get_color(bg, c[0], c[1], c[2]); -#ifdef __APPLE_QUARTZ__ c[3] = 0; -#endif - transparent_index = ind; #ifdef WIN32 transparent_c = c; #endif - } - } - } - d.data = data; + } // if parse + } // for ncolors + } // if ncolors #ifdef WIN32 if (transparent_c) { make_unused_color(transparent_c[0], transparent_c[1], transparent_c[2]); - } - else { + } else { uchar r, g, b; make_unused_color(r, g, b); } #endif - -#ifdef __APPLE_QUARTZ__ - if (Fl_Surface_Device::surface() == Fl_Display_Device::display_device()) { - U32 *array = new U32[d.w * d.h], *q = array; - for (int Y = 0; Y < d.h; Y++) { + + U32 *q = (U32*)out; + for (int Y = 0; Y < h; Y++) { const uchar* p = data[Y]; if (chars_per_pixel <= 1) { - for (int X = 0; X < d.w; X++) { - *q++ = d.colors[*p++]; - } + for (int X = 0; X < w; X++) + memcpy(q++, colors[*p++], 4); } else { - for (int X = 0; X < d.w; X++) { - U32* colors = (U32*)d.byte1[*p++]; - *q++ = colors[*p++]; + for (int X = 0; X < w; X++) { + int ind = (*p++)<<8; + ind |= *p++; + memcpy(q++, colors[ind], 4); } } } - Fl_RGB_Image* rgb = new Fl_RGB_Image((uchar*)array, d.w, d.h, 4); + delete[] colors; + return 1; +} + +/** + Draw XPM image data, with the top-left corner at the given position. + \see fl_draw_pixmap(char* const* data, int x, int y, Fl_Color bg) + */ +int fl_draw_pixmap(const char*const* cdata, int x, int y, Fl_Color bg) { + int w, h; + + if (!fl_measure_pixmap(cdata, w, h)) + return 0; + + uchar *buffer = new uchar[w*h*4]; + + if (!fl_convert_pixmap(cdata, buffer, bg)) { + delete[] buffer; + return 0; + } + + // FIXME: Hack until fl_draw_image() supports alpha properly +#ifdef __APPLE_QUARTZ__ + if (Fl_Surface_Device::surface() == Fl_Display_Device::display_device()) { + Fl_RGB_Image* rgb = new Fl_RGB_Image(buffer, w, h, 4); rgb->draw(x, y); delete rgb; - delete[] array; - } - else { + } else { #endif // __APPLE_QUARTZ__ - // build the mask bitmap used by Fl_Pixmap: - if (fl_mask_bitmap && transparent_index >= 0) { - int W = (d.w+7)/8; - uchar* bitmap = new uchar[W * d.h]; + if (fl_mask_bitmap) { + int W = (w+7)/8; + uchar* bitmap = new uchar[W * h]; *fl_mask_bitmap = bitmap; - for (int Y = 0; Y < d.h; Y++) { - const uchar* p = data[Y]; - if (chars_per_pixel <= 1) { - int dw = d.w; - for (int X = 0; X < W; X++) { - uchar b = (dw-->0 && *p++ != transparent_index); - if (dw-->0 && *p++ != transparent_index) b |= 2; - if (dw-->0 && *p++ != transparent_index) b |= 4; - if (dw-->0 && *p++ != transparent_index) b |= 8; - if (dw-->0 && *p++ != transparent_index) b |= 16; - if (dw-->0 && *p++ != transparent_index) b |= 32; - if (dw-->0 && *p++ != transparent_index) b |= 64; - if (dw-->0 && *p++ != transparent_index) b |= 128; - *bitmap++ = b; - } - } else { - uchar b = 0, bit = 1; - for (int X = 0; X < d.w; X++) { - int ind = *p++; - ind = (ind<<8) | (*p++); - if (ind != transparent_index) b |= bit; - - if (bit < 128) bit <<= 1; - else { + const uchar *p = &buffer[3]; + uchar b = 0; + for (int Y = 0; Y < h; Y++) { + b = 0; + for (int X = 0, bit = 1; X < w; X++, p += 4) { + if (*p > 127) + b |= bit; + bit <<= 1; + if (bit > 0x80 || X == w-1) { *bitmap++ = b; + bit = 1; b = 0; - bit = 1; } - } - - if (bit > 1) *bitmap++ = b; - } - } + } // if chars_per_pixel + } // for Y } - fl_draw_image(chars_per_pixel==1 ? cb1 : cb2, &d, x, y, d.w, d.h, 4); + fl_draw_image(buffer, x, y, w, h, 4); + #ifdef __APPLE_QUARTZ__ - } + } #endif - - if (chars_per_pixel > 1) for (int i = 0; i < 256; i++) delete[] d.byte1[i]; + delete[] buffer; return 1; } // -// End of "$Id: fl_draw_pixmap.cxx 9375 2012-04-22 03:09:31Z fabien $". +// End of "$Id: fl_draw_pixmap.cxx 10242 2014-08-22 10:28:50Z AlbrechtS $". // diff --git a/src/fl_engraved_label.cxx b/src/fl_engraved_label.cxx index 9a95daf..c94bfb6 100644 --- a/src/fl_engraved_label.cxx +++ b/src/fl_engraved_label.cxx @@ -1,5 +1,5 @@ // -// "$Id: fl_engraved_label.cxx 8864 2011-07-19 04:49:30Z greg.ercolano $" +// "$Id: fl_engraved_label.cxx 10252 2014-08-23 09:22:17Z cand $" // // Engraved label drawing routines for the Fast Light Tool Kit (FLTK). // @@ -26,7 +26,7 @@ static void innards( const Fl_Label* o, int X, int Y, int W, int H, Fl_Align align, - int data[][3], int n) + const int data[][3], int n) { Fl_Align a1 = align; if (a1 & FL_ALIGN_CLIP) { @@ -42,14 +42,14 @@ static void innards( static void fl_shadow_label( const Fl_Label* o, int X, int Y, int W, int H, Fl_Align align) { - static int data[2][3] = {{2,2,FL_DARK3},{0,0,0}}; + static const int data[2][3] = {{2,2,FL_DARK3},{0,0,0}}; innards(o, X, Y, W, H, align, data, 2); } static void fl_engraved_label( const Fl_Label* o, int X, int Y, int W, int H, Fl_Align align) { - static int data[7][3] = { + static const int data[7][3] = { {1,0,FL_LIGHT3},{1,1,FL_LIGHT3},{0,1,FL_LIGHT3}, {-1,0,FL_DARK3},{-1,-1,FL_DARK3},{0,-1,FL_DARK3}, {0,0,0}}; @@ -59,7 +59,7 @@ static void fl_engraved_label( static void fl_embossed_label( const Fl_Label* o, int X, int Y, int W, int H, Fl_Align align) { - static int data[7][3] = { + static const int data[7][3] = { {-1,0,FL_LIGHT3},{-1,-1,FL_LIGHT3},{0,-1,FL_LIGHT3}, {1,0,FL_DARK3},{1,1,FL_DARK3},{0,1,FL_DARK3}, {0,0,0}}; @@ -80,5 +80,5 @@ Fl_Labeltype fl_define_FL_EMBOSSED_LABEL() { } // -// End of "$Id: fl_engraved_label.cxx 8864 2011-07-19 04:49:30Z greg.ercolano $". +// End of "$Id: fl_engraved_label.cxx 10252 2014-08-23 09:22:17Z cand $". // diff --git a/src/fl_font_mac.cxx b/src/fl_font_mac.cxx index 624c98d..dac6f81 100644 --- a/src/fl_font_mac.cxx +++ b/src/fl_font_mac.cxx @@ -1,5 +1,5 @@ // -// "$Id: fl_font_mac.cxx 9120 2011-10-03 09:22:57Z manolo $" +// "$Id: fl_font_mac.cxx 10193 2014-06-14 11:06:42Z manolo $" // // MacOS font selection routines for the Fast Light Tool Kit (FLTK). // @@ -26,6 +26,8 @@ static CGAffineTransform font_mx = { 1, 0, 0, -1, 0, 0 }; static CFMutableDictionaryRef attributes = NULL; #endif +const int Fl_X::CoreText_threshold = 100500; // this represents Mac OS 10.5 + Fl_Font_Descriptor::Fl_Font_Descriptor(const char* name, Fl_Fontsize Size) { next = 0; # if HAVE_GL @@ -34,10 +36,9 @@ Fl_Font_Descriptor::Fl_Font_Descriptor(const char* name, Fl_Fontsize Size) { // knowWidths = 0; // OpenGL needs those for its font handling - q_name = strdup(name); size = Size; #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 -if (fl_mac_os_version >= 100500) {//unfortunately, CTFontCreateWithName != NULL on 10.4 also! +if (fl_mac_os_version >= Fl_X::CoreText_threshold) { CFStringRef str = CFStringCreateWithCString(NULL, name, kCFStringEncodingUTF8); fontref = CTFontCreateWithName(str, size, NULL); CGGlyph glyph[2]; @@ -88,22 +89,9 @@ else { #if ! __LP64__ OSStatus err; // fill our structure with a few default values - ascent = Size*3/4; + ascent = Size*3/4.; descent = Size-ascent; - q_width = Size*2/3; - // now use ATS to get the actual Glyph size information - // say that our passed-in name is encoded as UTF-8, since this works for plain ASCII names too... - CFStringRef cfname = CFStringCreateWithCString(0L, name, kCFStringEncodingUTF8); - ATSFontRef font = ATSFontFindFromName(cfname, kATSOptionFlagsDefault); - if (font) { - ATSFontMetrics m = { 0 }; - ATSFontGetHorizontalMetrics(font, kATSOptionFlagsDefault, &m); - if (m.avgAdvanceWidth) q_width = int(m.avgAdvanceWidth*Size); - // playing with the offsets a little to make standard sizes fit - if (m.ascent) ascent = int(m.ascent*Size-0.5f); - if (m.descent) descent = -int(m.descent*Size-1.5f); - } - CFRelease(cfname); + q_width = Size*2/3.; // now we allocate everything needed to render text in this font later // get us the default layout and style err = ATSUCreateTextLayout(&layout); @@ -115,15 +103,15 @@ else { // render our font up-side-down, so when rendered through our inverted CGContext, // text will appear normal again. Fixed fsize = IntToFixed(Size); -// ATSUFontID fontID = FMGetFontFromATSFontRef(font); ATSUFontID fontID; - ATSUFindFontFromName(name, strlen(name), kFontFullName, kFontMacintoshPlatform, kFontRomanScript, kFontEnglishLanguage, &fontID); + ATSUFindFontFromName(name, strlen(name), kFontFullName, kFontMacintoshPlatform, kFontNoScriptCode, kFontEnglishLanguage, &fontID); // draw the font upside-down... Compensate for fltk/OSX origin differences ATSUAttributeTag sTag[] = { kATSUFontTag, kATSUSizeTag, kATSUFontMatrixTag }; ByteCount sBytes[] = { sizeof(ATSUFontID), sizeof(Fixed), sizeof(CGAffineTransform) }; ATSUAttributeValuePtr sAttr[] = { &fontID, &fsize, &font_mx }; - err = ATSUSetAttributes(style, 3, sTag, sBytes, sAttr); + if (fontID != kATSUInvalidFontID) err = ATSUSetAttributes(style, 1, sTag, sBytes, sAttr); // set the font attribute + err = ATSUSetAttributes(style, 2, sTag + 1, sBytes + 1, sAttr + 1); // then the size and matrix attributes // next, make sure that Quartz will only render at integer coordinates ATSLineLayoutOptions llo = kATSLineUseDeviceMetrics | kATSLineDisableAllLayoutOperations; ATSUAttributeTag aTag[] = { kATSULineLayoutOptionsTag }; @@ -176,7 +164,7 @@ Fl_Font_Descriptor::~Fl_Font_Descriptor() { */ if (this == fl_graphics_driver->font_descriptor()) fl_graphics_driver->font_descriptor(NULL); #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 - if (fl_mac_os_version >= 100500) { + if (fl_mac_os_version >= Fl_X::CoreText_threshold) { CFRelease(fontref); for (unsigned i = 0; i < sizeof(width)/sizeof(float*); i++) { if (width[i]) free(width[i]); @@ -187,23 +175,44 @@ Fl_Font_Descriptor::~Fl_Font_Descriptor() { //////////////////////////////////////////////////////////////// -static Fl_Fontdesc built_in_table[] = { -{"Arial"}, -{"Arial Bold"}, -{"Arial Italic"}, -{"Arial Bold Italic"}, -{"Courier New"}, -{"Courier New Bold"}, -{"Courier New Italic"}, -{"Courier New Bold Italic"}, -{"Times New Roman"}, -{"Times New Roman Bold"}, -{"Times New Roman Italic"}, -{"Times New Roman Bold Italic"}, +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 +static Fl_Fontdesc built_in_table_PS[] = { // PostScript font names preferred when Mac OS ≥ 10.5 +{"ArialMT"}, +{"Arial-BoldMT"}, +{"Arial-ItalicMT"}, +{"Arial-BoldItalicMT"}, +{"CourierNewPSMT"}, +{"CourierNewPS-BoldMT"}, +{"CourierNewPS-ItalicMT"}, +{"CourierNewPS-BoldItalicMT"}, +{"TimesNewRomanPSMT"}, +{"TimesNewRomanPS-BoldMT"}, +{"TimesNewRomanPS-ItalicMT"}, +{"TimesNewRomanPS-BoldItalicMT"}, {"Symbol"}, {"Monaco"}, -{"Andale Mono"}, // there is no bold Monaco font on standard Mac -{"Webdings"}, +{"AndaleMono"}, // there is no bold Monaco font on standard Mac +{"ZapfDingbatsITC"} +}; +#endif + +static Fl_Fontdesc built_in_table_full[] = { // full font names used before 10.5 + {"Arial"}, + {"Arial Bold"}, + {"Arial Italic"}, + {"Arial Bold Italic"}, + {"Courier New"}, + {"Courier New Bold"}, + {"Courier New Italic"}, + {"Courier New Bold Italic"}, + {"Times New Roman"}, + {"Times New Roman Bold"}, + {"Times New Roman Italic"}, + {"Times New Roman Bold Italic"}, + {"Symbol"}, + {"Monaco"}, + {"Andale Mono"}, // there is no bold Monaco font on standard Mac + {"Webdings"} }; static UniChar *utfWbuf = 0; @@ -223,7 +232,14 @@ static UniChar *mac_Utf8_to_Utf16(const char *txt, int len, int *new_len) return utfWbuf; } // mac_Utf8_to_Utf16 -Fl_Fontdesc* fl_fonts = built_in_table; +Fl_Fontdesc* Fl_X::calc_fl_fonts(void) +{ +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 + return (fl_mac_os_version >= Fl_X::CoreText_threshold ? built_in_table_PS : built_in_table_full); +#else + return built_in_table_full; +#endif +} static Fl_Font_Descriptor* find(Fl_Font fnum, Fl_Fontsize size) { Fl_Fontdesc* s = fl_fonts+fnum; @@ -287,7 +303,7 @@ static CGFloat surrogate_width(const UniChar *txt, Fl_Font_Descriptor *fl_fontsi static double fl_mac_width(const UniChar* txt, int n, Fl_Font_Descriptor *fl_fontsize) { #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 -if (fl_mac_os_version >= 100500) { +if (fl_mac_os_version >= Fl_X::CoreText_threshold) { double retval = 0; UniChar uni; int i; @@ -302,7 +318,7 @@ if (fl_mac_os_version >= 100500) { // r: index of the character block containing uni unsigned int r = uni >> 7; // change 7 if sizeof(width) is changed if (!fl_fontsize->width[r]) { // this character block has not been hit yet - //fprintf(stderr,"r=%d size=%d name=%s\n",r,fl_fontsize->size, fl_fontsize->q_name); + //fprintf(stderr,"r=%d size=%d name=%s\n",r,fl_fontsize->size,fl_fonts[fl_font()].name); // allocate memory to hold width of each character in the block fl_fontsize->width[r] = (float*) malloc(sizeof(float) * block); UniChar ii = r * block; @@ -406,7 +422,7 @@ void Fl_Quartz_Graphics_Driver::text_extents(const char *str8, int n, int &dx, i Fl_Font_Descriptor *fl_fontsize = font_descriptor(); UniChar *txt = mac_Utf8_to_Utf16(str8, n, &n); #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 -if (fl_mac_os_version >= 100500) { +if (fl_mac_os_version >= Fl_X::CoreText_threshold) { CFStringRef str16 = CFStringCreateWithCharactersNoCopy(NULL, txt, n, kCFAllocatorNull); CFDictionarySetValue (attributes, kCTFontAttributeName, fl_fontsize->fontref); CFAttributedStringRef mastr = CFAttributedStringCreate(kCFAllocatorDefault, str16, attributes); @@ -474,7 +490,7 @@ static void fl_mac_draw(const char *str, int n, float x, float y, Fl_Graphics_Dr // convert to UTF-16 first UniChar *uniStr = mac_Utf8_to_Utf16(str, n, &n); #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 - if (fl_mac_os_version >= 100500) { + if (fl_mac_os_version >= Fl_X::CoreText_threshold) { CFStringRef str16 = CFStringCreateWithCharactersNoCopy(NULL, uniStr, n, kCFAllocatorNull); if (str16 == NULL) return; // shd not happen CGColorRef color = flcolortocgcolor(driver->color()); @@ -540,5 +556,5 @@ void Fl_Quartz_Graphics_Driver::rtl_draw(const char* c, int n, int x, int y) { } // -// End of "$Id: fl_font_mac.cxx 9120 2011-10-03 09:22:57Z manolo $". +// End of "$Id: fl_font_mac.cxx 10193 2014-06-14 11:06:42Z manolo $". // diff --git a/src/fl_font_win32.cxx b/src/fl_font_win32.cxx index f526105..3970f08 100644 --- a/src/fl_font_win32.cxx +++ b/src/fl_font_win32.cxx @@ -1,5 +1,5 @@ // -// "$Id: fl_font_win32.cxx 9293 2012-03-18 18:48:29Z manolo $" +// "$Id: fl_font_win32.cxx 10226 2014-08-19 12:36:12Z AlbrechtS $" // // WIN32 font selection routines for the Fast Light Tool Kit (FLTK). // @@ -55,7 +55,7 @@ Fl_Font_Descriptor::Fl_Font_Descriptor(const char* name, Fl_Fontsize fsize) { // ...would be the right call, but is not implemented into Window95! (WinNT?) //GetCharWidth(fl_gc, 0, 255, width); int i; - for (i = 0; i < 64; i++) width[i] = NULL; + memset(width, 0, 64 * sizeof(int*)); #if HAVE_GL listbase = 0; for (i = 0; i < 64; i++) glok[i] = 0; @@ -77,8 +77,9 @@ Fl_Font_Descriptor::~Fl_Font_Descriptor() { #endif if (this == fl_graphics_driver->font_descriptor()) fl_graphics_driver->font_descriptor(NULL); DeleteObject(fid); - int i; - for (i = 0; i < 64; i++) free(width[i]); + for (int i = 0; i < 64; i++) { + if ( width[i] ) free(width[i]); + } } //////////////////////////////////////////////////////////////// @@ -203,30 +204,32 @@ double Fl_GDI_Graphics_Driver::width(unsigned int c) { r = (c & 0xFC00) >> 10; if (!fl_fontsize->width[r]) { fl_fontsize->width[r] = (int*) malloc(sizeof(int) * 0x0400); - unsigned short i = 0, ii = r * 0x400; - // The following code makes a best effort attempt to obtain a valid fl_gc. - // If no fl_gc is available at the time we call fl_width(), then we first - // try to obtain a gc from the first fltk window. - // If that is null then we attempt to obtain the gc from the current screen - // using (GetDC(NULL)). - // This should resolve STR #2086 - HDC gc = fl_gc; - HWND hWnd = 0; - if (!gc) { // We have no valid gc, try and obtain one - // Use our first fltk window, or fallback to using the screen via GetDC(NULL) - hWnd = Fl::first_window() ? fl_xid(Fl::first_window()) : NULL; - gc = GetDC(hWnd); - } - if (!gc) - Fl::fatal("Invalid graphic context: fl_width() failed because no valid HDC was found!"); - SelectObject(gc, fl_fontsize->fid); - for (; i < 0x400; i++) { - GetTextExtentPoint32W(gc, (WCHAR*)&ii, 1, &s); - fl_fontsize->width[r][i] = s.cx; - ii++; + for (int i = 0; i < 0x0400; i++) fl_fontsize->width[r][i] = -1; + } else { + if ( fl_fontsize->width[r][c&0x03FF] >= 0 ) { // already cached + return (double) fl_fontsize->width[r][c & 0x03FF]; } - if (gc && gc!=fl_gc) ReleaseDC(hWnd, gc); } + unsigned short ii = r * 0x400; + // The following code makes a best effort attempt to obtain a valid fl_gc. + // If no fl_gc is available at the time we call fl_width(), then we first + // try to obtain a gc from the first fltk window. + // If that is null then we attempt to obtain the gc from the current screen + // using (GetDC(NULL)). + // This should resolve STR #2086 + HDC gc = fl_gc; + HWND hWnd = 0; + if (!gc) { // We have no valid gc, try and obtain one + // Use our first fltk window, or fallback to using the screen via GetDC(NULL) + hWnd = Fl::first_window() ? fl_xid(Fl::first_window()) : NULL; + gc = GetDC(hWnd); + } + if (!gc) Fl::fatal("Invalid graphic context: fl_width() failed because no valid HDC was found!"); + SelectObject(gc, fl_fontsize->fid); + ii += c &0x03FF; + GetTextExtentPoint32W(gc, (WCHAR*)&ii, 1, &s); + fl_fontsize->width[r][c&0x03FF] = s.cx; + if (gc && gc!=fl_gc) ReleaseDC(hWnd, gc); return (double) fl_fontsize->width[r][c & 0x03FF]; } @@ -439,5 +442,5 @@ void Fl_GDI_Graphics_Driver::rtl_draw(const char* c, int n, int x, int y) { } #endif // -// End of "$Id: fl_font_win32.cxx 9293 2012-03-18 18:48:29Z manolo $". +// End of "$Id: fl_font_win32.cxx 10226 2014-08-19 12:36:12Z AlbrechtS $". // diff --git a/src/fl_font_xft.cxx b/src/fl_font_xft.cxx index 7e4824c..1f2bbda 100644 --- a/src/fl_font_xft.cxx +++ b/src/fl_font_xft.cxx @@ -1,5 +1,5 @@ // -// "$Id: fl_font_xft.cxx 8864 2011-07-19 04:49:30Z greg.ercolano $" +// "$Id: fl_font_xft.cxx 10232 2014-08-21 12:13:47Z cand $" // // Xft font code for the Fast Light Tool Kit (FLTK). // @@ -101,8 +101,8 @@ Fl_Fontdesc* fl_fonts = built_in_table; Fl_XFont_On_Demand fl_xfont; void *fl_xftfont = 0; -//const char* fl_encoding_ = "iso8859-1"; -const char* fl_encoding_ = "iso10646-1"; +//static const char* fl_encoding_ = "iso8859-1"; +static const char* fl_encoding_ = "iso10646-1"; static void fl_xft_font(Fl_Xlib_Graphics_Driver *driver, Fl_Font fnum, Fl_Fontsize size, int angle) { if (fnum==-1) { // special case to stop font caching @@ -153,7 +153,7 @@ static XftFont* fontopen(const char* name, Fl_Fontsize size, bool core, int angl fl_open_display(); if(!is_xlfd) { // Not an XLFD - open as a XFT style name - XftFont *the_font; // the font we will return; + XftFont *the_font = NULL; // the font we will return; XftPattern *fnt_pat = XftPatternCreate(); // the pattern we will use for matching int slant = XFT_SLANT_ROMAN; int weight = XFT_WEIGHT_MEDIUM; @@ -270,7 +270,10 @@ static XftFont* fontopen(const char* name, Fl_Fontsize size, bool core, int angl free(picked_name); #endif - if (!match_pat) { + // open the matched font + if (match_pat) the_font = XftFontOpenPattern(fl_display, match_pat); + + if (!match_pat || !the_font) { // last chance, just open any font in the right size the_font = XftFontOpen (fl_display, fl_screen, XFT_FAMILY, XftTypeString, "sans", @@ -284,9 +287,6 @@ static XftFont* fontopen(const char* name, Fl_Fontsize size, bool core, int angl return the_font; } - // open the matched font - the_font = XftFontOpenPattern(fl_display, match_pat); - #if 0 // diagnostic to print the "full name" of the font we actually opened. This works. FcChar8 *picked_name2 = FcNameUnparse(the_font->pattern); printf("Open : %s\n", picked_name2); @@ -673,9 +673,9 @@ void Fl_Xlib_Graphics_Driver::rtl_draw(const char* c, int n, int x, int y) { if (num_chars < n) n = num_chars; // limit drawing to usable characters in input array FcChar32 *ucs_txt = new FcChar32[n+1]; FcChar32* pu; - int in, out, sz; + int out, sz; ucs_txt[n] = 0; - in = 0; out = n-1; + out = n-1; while ((out >= 0) && (utf_len > 0)) { pu = &ucs_txt[out]; @@ -693,5 +693,5 @@ void Fl_Xlib_Graphics_Driver::rtl_draw(const char* c, int n, int x, int y) { #endif // -// End of "$Id: fl_font_xft.cxx 8864 2011-07-19 04:49:30Z greg.ercolano $" +// End of "$Id: fl_font_xft.cxx 10232 2014-08-21 12:13:47Z cand $" // diff --git a/src/fl_gleam.cxx b/src/fl_gleam.cxx new file mode 100644 index 0000000..b1c3bc5 --- /dev/null +++ b/src/fl_gleam.cxx @@ -0,0 +1,137 @@ +// +// "$Id: fl_gleam.cxx 10143 2014-05-02 09:13:29Z ianmacarthur $" +// +// "Gleam" drawing routines for the Fast Light Tool Kit (FLTK). +// +// Copyright 1998-2010 by Bill Spitzak and others. +// +// This library is free software. Distribution and use rights are outlined in +// the file "COPYING" which should have been included with this file. If this +// file is missing or damaged, see the license at: +// +// http://www.fltk.org/COPYING.php +// +// Please report all bugs and problems on the following page: +// +// http://www.fltk.org/str.php +// +// These box types provide a sort of Clearlooks Glossy scheme +// for FLTK. +// +// Copyright 2001-2005 by Colin Jones. +// +// Modified 2012-2013 by Edmanuel Torres +// This is a new version of the fl_gleam. The gradients are on the top +// an the bottom, the text area looks like in the classic FLTK way. +// + +#include <FL/Fl.H> +#include <FL/fl_draw.H> + + +static void gleam_color(Fl_Color c) { + if (Fl::draw_box_active()) fl_color(c); + else fl_color(fl_inactive(c)); +} + +static void shade_rect_top_bottom(int x, int y, int w, int h, Fl_Color fg1, Fl_Color fg2, float th) { + // Draws the shiny using maximum limits + int h_top = ((h/2) < (20) ? (h/2) : (20)); // min(h/2,20); + int h_bottom = ((h/6) < (15) ? (h/6) : (15)); // min(h/6,15); + int h_flat = h-(h_top+h_bottom); + int j = 0; + float step_size_top = h_top>1?(0.999/(float)(h_top)):1; + float step_size_bottom = h_bottom>1?(0.999/(float)(h_bottom)):1; + // This loop generates the gradient at the top of the widget + for (float k = 1; k >= 0; k -= step_size_top){ + gleam_color(fl_color_average(fl_color_average(fg1, fg2, th), fg1, k)); + fl_line(x, y+j, x+w, y+j); + j++; + } + gleam_color(fg1); + fl_rectf(x, y+h_top, w+1, h_flat); + // This loop generates the gradient at the bottom of the widget + for (float k = 1; k >= 0; k -= step_size_bottom){ + gleam_color(fl_color_average(fg1,fl_color_average(fg1, fg2, th), k)); + fl_line(x, y+j+h_flat-1, x+w, y+j+h_flat-1); + j++; + } +} + +static void shade_rect_top_bottom_up(int x, int y, int w, int h, Fl_Color bc, float th) { + shade_rect_top_bottom(x,y,w,h,bc,FL_WHITE,th); +} + +static void shade_rect_top_bottom_down(int x, int y, int w, int h, Fl_Color bc, float th) { + shade_rect_top_bottom(x,y,w,h,bc,FL_BLACK,th); +} + +static void frame_rect(int x, int y, int w, int h, Fl_Color fg1, Fl_Color fg2, Fl_Color lc) { + gleam_color(fg1); + fl_line(x, y+h-1, x, y+1); //Go from bottom to top left side + fl_line(x+w, y+h-1, x+w, y+1); //Go from bottom to top right side + fl_line(x+1, y, x+w-1, y); //Go across the top + fl_line(x+1, y+h, x+w-1, y+h); //Go across the bottom + gleam_color(fg2); + fl_line(x+1, y+h-2, x+1, y+2); //Go from bottom to top left side + fl_line(x+w-1, y+h-2, x+w-1, y+2); //Go from bottom to top right side + gleam_color(lc); + fl_line(x+2, y+1, x+w-3, y+1); //Go across the top + fl_line(x+2, y+h-1, x+w-3, y+h-1); //Go across the bottom +} + +static void frame_rect_up(int x, int y, int w, int h, Fl_Color bc, Fl_Color lc, float th1, float th2) { + frame_rect(x,y,w,h,fl_color_average(fl_darker(bc), FL_BLACK, th1),fl_color_average(bc, FL_WHITE, th2),lc); +} + +static void frame_rect_down(int x, int y, int w, int h, Fl_Color bc, Fl_Color lc, float th1, float th2) { + frame_rect(x,y,w,h,fl_color_average(bc, FL_WHITE, th1),fl_color_average(FL_BLACK, bc, th2),lc); +} + +static void up_frame(int x, int y, int w, int h, Fl_Color c) { + frame_rect_up(x, y, w-1, h-1, c, fl_color_average(c, FL_WHITE, .25f), .55f, .05f); +} + +static void up_box(int x, int y, int w, int h, Fl_Color c) { + shade_rect_top_bottom_up(x+2, y+1, w-5, h-3, c, .15f); + frame_rect_up(x, y, w-1, h-1, c, fl_color_average(c, FL_WHITE, .05f), .15f, .05f); +} + +static void thin_up_box(int x, int y, int w, int h, Fl_Color c) { + shade_rect_top_bottom_up(x+2, y+1, w-5, h-3, c, .25f); + frame_rect_up(x, y, w-1, h-1, c, fl_color_average(c, FL_WHITE, .45f), .25f, .15f); +} + +static void down_frame(int x, int y, int w, int h, Fl_Color c) { + frame_rect_down(x, y, w-1, h-1, fl_darker(c), fl_darker(c), .25f, .95f); +} + +static void down_box(int x, int y, int w, int h, Fl_Color c) { + shade_rect_top_bottom_down(x+1, y+1, w-3, h-3, c, .65f); + frame_rect_down(x, y, w-1, h-1, c, fl_color_average(c, FL_BLACK, .05f), .05f, .95f); +} + +static void thin_down_box(int x, int y, int w, int h, Fl_Color c) { + shade_rect_top_bottom_down(x+1, y+1, w-3, h-3, c, .85f); + frame_rect_down(x, y, w-1, h-1, c, fl_color_average(c, FL_BLACK, .45f), .35f, 0.85f); +} + +extern void fl_internal_boxtype(Fl_Boxtype, Fl_Box_Draw_F*); + +Fl_Boxtype fl_define_FL_GLEAM_UP_BOX() { + fl_internal_boxtype(_FL_GLEAM_UP_BOX, up_box); + fl_internal_boxtype(_FL_GLEAM_DOWN_BOX, down_box); + fl_internal_boxtype(_FL_GLEAM_UP_FRAME, up_frame); + fl_internal_boxtype(_FL_GLEAM_DOWN_FRAME, down_frame); + fl_internal_boxtype(_FL_GLEAM_THIN_UP_BOX, thin_up_box); + fl_internal_boxtype(_FL_GLEAM_THIN_DOWN_BOX, thin_down_box); + fl_internal_boxtype(_FL_GLEAM_ROUND_UP_BOX, up_box); + fl_internal_boxtype(_FL_GLEAM_ROUND_DOWN_BOX, down_box); + return _FL_GLEAM_UP_BOX; +} + + +// +// End of "$Id: fl_gleam.cxx 10143 2014-05-02 09:13:29Z ianmacarthur $". +// + diff --git a/src/fl_gtk.cxx b/src/fl_gtk.cxx index ce44136..ac7780d 100644 --- a/src/fl_gtk.cxx +++ b/src/fl_gtk.cxx @@ -1,5 +1,5 @@ // -// "$Id: fl_gtk.cxx 8864 2011-07-19 04:49:30Z greg.ercolano $" +// "$Id: fl_gtk.cxx 10232 2014-08-21 12:13:47Z cand $" // // "GTK" drawing routines for the Fast Light Tool Kit (FLTK). // @@ -203,7 +203,7 @@ static void draw(int which, int x,int y,int w,int h, int inset) } } -void gtk_round_up_box(int x, int y, int w, int h, Fl_Color c) { +static void gtk_round_up_box(int x, int y, int w, int h, Fl_Color c) { fl_color(c); draw(FILL, x, y, w, h, 2); @@ -234,7 +234,7 @@ void gtk_round_up_box(int x, int y, int w, int h, Fl_Color c) { draw(CLOSED, x, y, w, h, 0); } -void gtk_round_down_box(int x, int y, int w, int h, Fl_Color c) { +static void gtk_round_down_box(int x, int y, int w, int h, Fl_Color c) { fl_color(c); draw(FILL, x, y, w, h, 2); @@ -291,5 +291,5 @@ Fl_Boxtype fl_define_FL_GTK_UP_BOX() { // -// End of "$Id: fl_gtk.cxx 8864 2011-07-19 04:49:30Z greg.ercolano $". +// End of "$Id: fl_gtk.cxx 10232 2014-08-21 12:13:47Z cand $". // diff --git a/src/fl_open_uri.cxx b/src/fl_open_uri.cxx index c5b7fd0..cff26b8 100644 --- a/src/fl_open_uri.cxx +++ b/src/fl_open_uri.cxx @@ -1,5 +1,5 @@ // -// "$Id: fl_open_uri.cxx 9580 2012-06-10 09:24:33Z manolo $" +// "$Id: fl_open_uri.cxx 9995 2013-10-04 16:48:08Z greg.ercolano $" // // fl_open_uri() code for FLTK. // @@ -68,6 +68,14 @@ static int run_program(const char *program, char **argv, char *msg, int msglen); * * On failure, the msg buffer is filled with an English error message. * + * \note + * \b Platform \b Specific \b Issues: \b Windows \n + * With "file:" based URIs on Windows, you may encounter issues with + * anchors being ignored. Example: "file:///c:/some/index.html#anchor" + * may open in the browser without the "#anchor" suffix. The behavior + * seems to vary across different Windows versions. Workaround: open a link + * to a separate html file that redirects to the desired "file:" URI. + * * \b Example * \code * #include <FL/filename.H> @@ -395,5 +403,5 @@ int main(int argc, char **argv) { // -// End of "$Id: fl_open_uri.cxx 9580 2012-06-10 09:24:33Z manolo $". +// End of "$Id: fl_open_uri.cxx 9995 2013-10-04 16:48:08Z greg.ercolano $". // diff --git a/src/fl_plastic.cxx b/src/fl_plastic.cxx index 1b1df7e..e749b54 100644 --- a/src/fl_plastic.cxx +++ b/src/fl_plastic.cxx @@ -1,5 +1,5 @@ // -// "$Id: fl_plastic.cxx 9326 2012-04-05 14:30:19Z AlbrechtS $" +// "$Id: fl_plastic.cxx 10307 2014-09-13 17:04:20Z manolo $" // // "Plastic" drawing routines for the Fast Light Tool Kit (FLTK). // @@ -35,7 +35,7 @@ //#define USE_OLD_PLASTIC_BOX #define USE_OLD_PLASTIC_COLOR -extern uchar *fl_gray_ramp(); +extern const uchar *fl_gray_ramp(); inline Fl_Color shade_color(uchar gc, Fl_Color bc) { #ifdef USE_OLD_PLASTIC_COLOR @@ -71,7 +71,7 @@ inline Fl_Color shade_color(uchar gc, Fl_Color bc) { static void frame_rect(int x, int y, int w, int h, const char *c, Fl_Color bc) { - uchar *g = fl_gray_ramp(); + const uchar *g = fl_gray_ramp(); int b = ((int) strlen(c)) / 4 + 1; for (x += b, y += b, w -= 2 * b, h -= 2 * b; b > 1; b --) @@ -91,7 +91,7 @@ static void frame_rect(int x, int y, int w, int h, const char *c, Fl_Color bc) { static void frame_round(int x, int y, int w, int h, const char *c, Fl_Color bc) { - uchar *g = fl_gray_ramp(); + const uchar *g = fl_gray_ramp(); size_t b = strlen(c) / 4 + 1; if (w==h) { @@ -145,7 +145,7 @@ static void frame_round(int x, int y, int w, int h, const char *c, Fl_Color bc) static void shade_rect(int x, int y, int w, int h, const char *c, Fl_Color bc) { - uchar *g = fl_gray_ramp(); + const uchar *g = fl_gray_ramp(); int i, j; int clen = (int) strlen(c) - 1; int chalf = clen / 2; @@ -217,7 +217,7 @@ static void shade_rect(int x, int y, int w, int h, const char *c, Fl_Color bc) { } static void shade_round(int x, int y, int w, int h, const char *c, Fl_Color bc) { - uchar *g = fl_gray_ramp(); + const uchar *g = fl_gray_ramp(); int i; int clen = (int) (strlen(c) - 1); int chalf = clen / 2; @@ -277,10 +277,10 @@ static void up_frame(int x, int y, int w, int h, Fl_Color c) { static void narrow_thin_box(int x, int y, int w, int h, Fl_Color c) { if (h<=0 || w<=0) return; - uchar *g = fl_gray_ramp(); - fl_color(shade_color(g['R'], c)); + const uchar *g = fl_gray_ramp(); + fl_color(shade_color(g[(int)'R'], c)); fl_rectf(x+1, y+1, w-2, h-2); - fl_color(shade_color(g['I'], c)); + fl_color(shade_color(g[(int)'I'], c)); if (w > 1) { fl_xyline(x+1, y, x+w-2); fl_xyline(x+1, y+h-1, x+w-2); @@ -368,5 +368,5 @@ Fl_Boxtype fl_define_FL_PLASTIC_UP_BOX() { // -// End of "$Id: fl_plastic.cxx 9326 2012-04-05 14:30:19Z AlbrechtS $". +// End of "$Id: fl_plastic.cxx 10307 2014-09-13 17:04:20Z manolo $". // diff --git a/src/fl_read_image.cxx b/src/fl_read_image.cxx index 41d5458..9a12aa0 100644 --- a/src/fl_read_image.cxx +++ b/src/fl_read_image.cxx @@ -1,5 +1,5 @@ // -// "$Id: fl_read_image.cxx 8864 2011-07-19 04:49:30Z greg.ercolano $" +// "$Id: fl_read_image.cxx 10388 2014-10-22 16:27:20Z manolo $" // // X11 image reading routines for the Fast Light Tool Kit (FLTK). // @@ -70,8 +70,10 @@ fl_subimage_offsets(int a, int aw, int b, int bw, int &obw) // this handler will catch and ignore exceptions during XGetImage // to avoid an application crash -static int xgetimageerrhandler(Display *display, XErrorEvent *error) { - return 0; +extern "C" { + static int xgetimageerrhandler(Display *display, XErrorEvent *error) { + return 0; + } } // @@ -135,7 +137,7 @@ fl_read_image(uchar *p, // I - Pixel buffer or NULL to allocate // screen dimensions Fl::screen_xywh(sx, sy, sw, sh, fl_screen); } - if (!win || (dx >= sx && dy >= sy && dx + w <= sw && dy + h <= sh)) { + if (!win || (dx >= sx && dy >= sy && dx + w <= sx+sw && dy + h <= sy+sh)) { // the image is fully contained, we can use the traditional method // however, if the window is obscured etc. the function will still fail. Make sure we // catch the error and continue, otherwise an exception will be thrown. @@ -496,5 +498,5 @@ fl_read_image(uchar *p, // I - Pixel buffer or NULL to allocate #endif // -// End of "$Id: fl_read_image.cxx 8864 2011-07-19 04:49:30Z greg.ercolano $". +// End of "$Id: fl_read_image.cxx 10388 2014-10-22 16:27:20Z manolo $". // diff --git a/src/fl_read_image_mac.cxx b/src/fl_read_image_mac.cxx index ae2963f..d9a20df 100644 --- a/src/fl_read_image_mac.cxx +++ b/src/fl_read_image_mac.cxx @@ -1,5 +1,5 @@ // -// "$Id: fl_read_image_mac.cxx 8864 2011-07-19 04:49:30Z greg.ercolano $" +// "$Id: fl_read_image_mac.cxx 10078 2014-01-22 20:39:21Z manolo $" // // WIN32 image reading routines for the Fast Light Tool Kit (FLTK). // @@ -45,6 +45,7 @@ fl_read_image(uchar *p, // I - Pixel buffer or NULL to allocate Fl_Window *window = Fl_Window::current(); while(window->window()) window = window->window(); base = Fl_X::bitmap_from_window_rect(window,x,y,w,h,&delta); + if (!base) return NULL; rowBytes = delta*w; x = y = 0; } @@ -69,5 +70,5 @@ fl_read_image(uchar *p, // I - Pixel buffer or NULL to allocate // -// End of "$Id: fl_read_image_mac.cxx 8864 2011-07-19 04:49:30Z greg.ercolano $". +// End of "$Id: fl_read_image_mac.cxx 10078 2014-01-22 20:39:21Z manolo $". // diff --git a/src/fl_rect.cxx b/src/fl_rect.cxx index e63ca13..d96b35f 100644 --- a/src/fl_rect.cxx +++ b/src/fl_rect.cxx @@ -1,5 +1,5 @@ // -// "$Id: fl_rect.cxx 9293 2012-03-18 18:48:29Z manolo $" +// "$Id: fl_rect.cxx 10401 2014-10-28 13:44:09Z manolo $" // // Rectangle drawing routines for the Fast Light Tool Kit (FLTK). // @@ -188,7 +188,7 @@ void Fl_Graphics_Driver::rectf(int x, int y, int w, int h) { rect.right = x + w; rect.bottom = y + h; FillRect(fl_gc, &rect, fl_brush()); #elif defined(__APPLE_QUARTZ__) - CGRect rect = CGRectMake(x, y, w - 0.9 , h - 0.9); + CGRect rect = CGRectMake(x - 0.5, y - 0.5, w , h); CGContextFillRect(fl_gc, rect); #else # error unsupported platform @@ -708,5 +708,5 @@ int Fl_Graphics_Driver::clip_box(int x, int y, int w, int h, int& X, int& Y, int } // -// End of "$Id: fl_rect.cxx 9293 2012-03-18 18:48:29Z manolo $". +// End of "$Id: fl_rect.cxx 10401 2014-10-28 13:44:09Z manolo $". // diff --git a/src/fl_round_box.cxx b/src/fl_round_box.cxx index e143e0b..eb0b31a 100644 --- a/src/fl_round_box.cxx +++ b/src/fl_round_box.cxx @@ -1,5 +1,5 @@ // -// "$Id: fl_round_box.cxx 9211 2011-12-21 12:01:50Z AlbrechtS $" +// "$Id: fl_round_box.cxx 10307 2014-09-13 17:04:20Z manolo $" // // Round box drawing routines for the Fast Light Tool Kit (FLTK). // @@ -71,34 +71,34 @@ static void draw(int which, int x,int y,int w,int h, int inset, Fl_Color color) } } -extern uchar* fl_gray_ramp(); +extern const uchar* fl_gray_ramp(); void fl_round_down_box(int x, int y, int w, int h, Fl_Color bgcolor) { - uchar *g = fl_gray_ramp(); + const uchar *g = fl_gray_ramp(); draw(FILL, x, y, w, h, 2, bgcolor); - draw(UPPER_LEFT, x+1, y, w-2, h, 0, (Fl_Color)g['N']); - draw(UPPER_LEFT, x+1, y, w-2, h, 1, (Fl_Color)g['H']); - draw(UPPER_LEFT, x, y, w, h, 0, (Fl_Color)g['N']); - draw(UPPER_LEFT, x, y, w, h, 1, (Fl_Color)g['H']); - draw(LOWER_RIGHT, x, y, w, h, 0, (Fl_Color)g['S']); - draw(LOWER_RIGHT, x+1, y, w-2, h, 0, (Fl_Color)g['U']); - draw(LOWER_RIGHT, x, y, w, h, 1, (Fl_Color)g['U']); - draw(LOWER_RIGHT, x+1, y, w-2, h, 1, (Fl_Color)g['W']); - draw(CLOSED, x, y, w, h, 2, (Fl_Color)g['A']); + draw(UPPER_LEFT, x+1, y, w-2, h, 0, (Fl_Color)g[(int)'N']); + draw(UPPER_LEFT, x+1, y, w-2, h, 1, (Fl_Color)g[(int)'H']); + draw(UPPER_LEFT, x, y, w, h, 0, (Fl_Color)g[(int)'N']); + draw(UPPER_LEFT, x, y, w, h, 1, (Fl_Color)g[(int)'H']); + draw(LOWER_RIGHT, x, y, w, h, 0, (Fl_Color)g[(int)'S']); + draw(LOWER_RIGHT, x+1, y, w-2, h, 0, (Fl_Color)g[(int)'U']); + draw(LOWER_RIGHT, x, y, w, h, 1, (Fl_Color)g[(int)'U']); + draw(LOWER_RIGHT, x+1, y, w-2, h, 1, (Fl_Color)g[(int)'W']); + draw(CLOSED, x, y, w, h, 2, (Fl_Color)g[(int)'A']); } void fl_round_up_box(int x, int y, int w, int h, Fl_Color bgcolor) { - uchar *g = fl_gray_ramp(); + const uchar *g = fl_gray_ramp(); draw(FILL, x, y, w, h, 2, bgcolor); - draw(LOWER_RIGHT, x+1, y, w-2, h, 0, (Fl_Color)g['H']); - draw(LOWER_RIGHT, x+1, y, w-2, h, 1, (Fl_Color)g['N']); - draw(LOWER_RIGHT, x, y, w, h, 1, (Fl_Color)g['H']); - draw(LOWER_RIGHT, x, y, w, h, 2, (Fl_Color)g['N']); - draw(UPPER_LEFT, x, y, w, h, 2, (Fl_Color)g['U']); - draw(UPPER_LEFT, x+1, y, w-2, h, 1, (Fl_Color)g['S']); - draw(UPPER_LEFT, x, y, w, h, 1, (Fl_Color)g['W']); - draw(UPPER_LEFT, x+1, y, w-2, h, 0, (Fl_Color)g['U']); - draw(CLOSED, x, y, w, h, 0, (Fl_Color)g['A']); + draw(LOWER_RIGHT, x+1, y, w-2, h, 0, (Fl_Color)g[(int)'H']); + draw(LOWER_RIGHT, x+1, y, w-2, h, 1, (Fl_Color)g[(int)'N']); + draw(LOWER_RIGHT, x, y, w, h, 1, (Fl_Color)g[(int)'H']); + draw(LOWER_RIGHT, x, y, w, h, 2, (Fl_Color)g[(int)'N']); + draw(UPPER_LEFT, x, y, w, h, 2, (Fl_Color)g[(int)'U']); + draw(UPPER_LEFT, x+1, y, w-2, h, 1, (Fl_Color)g[(int)'S']); + draw(UPPER_LEFT, x, y, w, h, 1, (Fl_Color)g[(int)'W']); + draw(UPPER_LEFT, x+1, y, w-2, h, 0, (Fl_Color)g[(int)'U']); + draw(CLOSED, x, y, w, h, 0, (Fl_Color)g[(int)'A']); } extern void fl_internal_boxtype(Fl_Boxtype, Fl_Box_Draw_F*); @@ -109,5 +109,5 @@ Fl_Boxtype fl_define_FL_ROUND_UP_BOX() { } // -// End of "$Id: fl_round_box.cxx 9211 2011-12-21 12:01:50Z AlbrechtS $". +// End of "$Id: fl_round_box.cxx 10307 2014-09-13 17:04:20Z manolo $". // diff --git a/src/fl_scroll_area.cxx b/src/fl_scroll_area.cxx index 99d0640..a694da2 100644 --- a/src/fl_scroll_area.cxx +++ b/src/fl_scroll_area.cxx @@ -1,5 +1,5 @@ // -// "$Id: fl_scroll_area.cxx 8864 2011-07-19 04:49:30Z greg.ercolano $" +// "$Id: fl_scroll_area.cxx 10078 2014-01-22 20:39:21Z manolo $" // // Scrolling routines for the Fast Light Tool Kit (FLTK). // @@ -143,11 +143,13 @@ void fl_scroll(int X, int Y, int W, int H, int dx, int dy, #elif defined(__APPLE_QUARTZ__) CGImageRef img = Fl_X::CGImage_from_window_rect(Fl_Window::current(), src_x, src_y, src_w, src_h); - CGRect rect = { { dest_x, dest_y }, { src_w, src_h } }; - Fl_X::q_begin_image(rect, 0, 0, src_w, src_h); - CGContextDrawImage(fl_gc, rect, img); - Fl_X::q_end_image(); - CFRelease(img); + if (img) { + CGRect rect = { { dest_x, dest_y }, { src_w, src_h } }; + Fl_X::q_begin_image(rect, 0, 0, src_w, src_h); + CGContextDrawImage(fl_gc, rect, img); + Fl_X::q_end_image(); + CFRelease(img); + } #else # error unsupported platform #endif @@ -156,5 +158,5 @@ void fl_scroll(int X, int Y, int W, int H, int dx, int dy, } // -// End of "$Id: fl_scroll_area.cxx 8864 2011-07-19 04:49:30Z greg.ercolano $". +// End of "$Id: fl_scroll_area.cxx 10078 2014-01-22 20:39:21Z manolo $". // diff --git a/src/fl_set_fonts_mac.cxx b/src/fl_set_fonts_mac.cxx index 43a5fcb..81f4207 100644 --- a/src/fl_set_fonts_mac.cxx +++ b/src/fl_set_fonts_mac.cxx @@ -1,5 +1,5 @@ // -// "$Id: fl_set_fonts_mac.cxx 8864 2011-07-19 04:49:30Z greg.ercolano $" +// "$Id: fl_set_fonts_mac.cxx 10014 2013-10-30 13:36:16Z manolo $" // // MacOS font utilities for the Fast Light Tool Kit (FLTK). // @@ -20,27 +20,35 @@ // #inclde <SFNTTypes.h> -// This function fills in the fltk font table with all the fonts that -// are found on the X server. It tries to place the fonts into families -// and to sort them so the first 4 in a family are normal, bold, italic, -// and bold italic. // Bug: older versions calculated the value for *ap as a side effect of // making the name, and then forgot about it. To avoid having to change // the header files I decided to store this value in the last character // of the font name array. -#define ENDOFBUFFER 127 // sizeof(Fl_Font.fontname)-1 +#define ENDOFBUFFER sizeof(fl_fonts->fontname)-1 // turn a stored font name into a pretty name: const char* Fl::get_font_name(Fl_Font fnum, int* ap) { Fl_Fontdesc *f = fl_fonts + fnum; if (!f->fontname[0]) { +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 + if (fl_mac_os_version >= Fl_X::CoreText_threshold) { + CFStringRef cfname = CFStringCreateWithCString(NULL, f->name, kCFStringEncodingUTF8); + CTFontRef ctfont = CTFontCreateWithName(cfname, 0, NULL); + CFRelease(cfname); + cfname = CTFontCopyFullName(ctfont); + CFRelease(ctfont); + CFStringGetCString(cfname, f->fontname, ENDOFBUFFER, kCFStringEncodingUTF8); + CFRelease(cfname); + } + else +#endif + strlcpy(f->fontname, f->name, ENDOFBUFFER); const char* p = f->name; if (!p || !*p) {if (ap) *ap = 0; return "";} - strlcpy(f->fontname, p, ENDOFBUFFER); int type = 0; if (strstr(f->name, "Bold")) type |= FL_BOLD; - if (strstr(f->name, "Italic")) type |= FL_ITALIC; + if (strstr(f->name, "Italic") || strstr(f->name, "Oblique")) type |= FL_ITALIC; f->fontname[ENDOFBUFFER] = (char)type; } if (ap) *ap = f->fontname[ENDOFBUFFER]; @@ -48,21 +56,55 @@ const char* Fl::get_font_name(Fl_Font fnum, int* ap) { } #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 + +static char *skip(char *p, int& derived) +{ + if (memcmp(p, "-BoldItalic", 11) == 0) { p += 11; derived = 3; } + else if (memcmp(p, "-BoldOblique", 12) == 0) { p += 12; derived = 3; } + else if (memcmp(p, "-Bold", 5) == 0) {p += 5; derived = 1; } + else if (memcmp(p, "-Italic", 7) == 0) {p += 7; derived = 2; } + else if (memcmp(p, "-Oblique", 8) == 0) {p += 8; derived = 2; } + else if (memcmp(p, "-Regular", 8) == 0) {p += 8; } + else if (memcmp(p, "-Roman", 6) == 0) {p += 6; } + return p; +} + static int name_compare(const void *a, const void *b) { - return strcmp(*(char**)a, *(char**)b); + /* Compare PostScript font names. + First compare font family names ignoring bold, italic and oblique qualifiers. + When families are identical, order them according to regular, bold, italic, bolditalic. + */ + char *n1 = *(char**)a; + char *n2 = *(char**)b; + int derived1 = 0; + int derived2 = 0; + while (true) { + if (*n1 == '-') n1 = skip(n1, derived1); + if (*n2 == '-') n2 = skip(n2, derived2); + if (*n1 < *n2) return -1; + if (*n1 > *n2) return +1; + if (*n1 == 0) { + return derived1 - derived2; + } + n1++; n2++; + } } #endif static int fl_free_font = FL_FREE_FONT; +// This function fills in the fltk font table with all the fonts that +// are found on the X server. It tries to place the fonts into families +// and to sort them so the first 4 in a family are normal, bold, italic, +// and bold italic. + Fl_Font Fl::set_fonts(const char* xstarname) { #pragma unused ( xstarname ) if (fl_free_font > FL_FREE_FONT) return (Fl_Font)fl_free_font; // if already called #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 -if(fl_mac_os_version >= 100500) { -//if(CTFontCreateWithFontDescriptor != NULL) {// CTFontCreateWithFontDescriptor != NULL on 10.4 also! +if(fl_mac_os_version >= Fl_X::CoreText_threshold) { int value[1] = {1}; CFDictionaryRef dict = CFDictionaryCreate(NULL, (const void **)kCTFontCollectionRemoveDuplicatesOption, @@ -77,9 +119,9 @@ if(fl_mac_os_version >= 100500) { for (i = 0; i < count; i++) { CTFontDescriptorRef fdesc = (CTFontDescriptorRef)CFArrayGetValueAtIndex(arrayref, i); CTFontRef font = CTFontCreateWithFontDescriptor(fdesc, 0., NULL); - CFStringRef cfname = CTFontCopyFullName(font); + CFStringRef cfname = CTFontCopyPostScriptName(font); CFRelease(font); - static char fname[100]; + static char fname[200]; CFStringGetCString(cfname, fname, sizeof(fname), kCFStringEncodingUTF8); tabfontnames[i] = strdup(fname); // never free'ed CFRelease(cfname); @@ -151,5 +193,5 @@ int Fl::get_font_sizes(Fl_Font fnum, int*& sizep) { } // -// End of "$Id: fl_set_fonts_mac.cxx 8864 2011-07-19 04:49:30Z greg.ercolano $". +// End of "$Id: fl_set_fonts_mac.cxx 10014 2013-10-30 13:36:16Z manolo $". // diff --git a/src/fl_set_fonts_xft.cxx b/src/fl_set_fonts_xft.cxx index dbaf1b9..87dfeed 100644 --- a/src/fl_set_fonts_xft.cxx +++ b/src/fl_set_fonts_xft.cxx @@ -1,5 +1,5 @@ // -// "$Id: fl_set_fonts_xft.cxx 9396 2012-04-24 03:52:00Z fabien $" +// "$Id: fl_set_fonts_xft.cxx 10041 2014-01-03 16:17:05Z AlbrechtS $" // // More font utilities for the Fast Light Tool Kit (FLTK). // @@ -29,7 +29,7 @@ // of the font name array. #define ENDOFBUFFER 127 // sizeof(Fl_Font.fontname)-1 -// turn a stored font name into a pretty name: +// turn a stored font name in "fltk format" into a pretty name: const char* Fl::get_font_name(Fl_Font fnum, int* ap) { Fl_Fontdesc *f = fl_fonts + fnum; if (!f->fontname[0]) { @@ -82,7 +82,6 @@ static void make_raw_name(char *raw, char *pretty) // italic, bold, bold italic or normal - this seems to be the fltk way... char *style = strchr(pretty, ':'); - char *last = style + strlen(style) - 2; if (style) { @@ -102,12 +101,16 @@ static void make_raw_name(char *raw, char *pretty) nm2 = strchr(nm1, ','); } raw[0] = ' '; raw[1] = 0; // Default start of "raw name" text - strncat(raw, nm1, LOCAL_RAW_NAME_MAX); + strncat(raw, nm1, LOCAL_RAW_NAME_MAX-1); // only copy MAX-1 chars, we have already set cell 0 + // Ensure raw is terminated, just in case the given name is infeasibly long... + raw[LOCAL_RAW_NAME_MAX-1] = 0; #else // keep the first remaining name entry char *nm2 = strchr(pretty, ','); if(nm2) *nm2 = 0; // terminate name after first entry raw[0] = ' '; raw[1] = 0; // Default start of "raw name" text - strncat(raw, pretty, LOCAL_RAW_NAME_MAX-1); + strncat(raw, pretty, LOCAL_RAW_NAME_MAX-1); // only copy MAX-1 chars, we have already set cell 0 + // Ensure raw is terminated, just in case the given name is infeasibly long... + raw[LOCAL_RAW_NAME_MAX-1] = 0; #endif // At this point, the name is "marked" as regular... if (style) @@ -116,7 +119,10 @@ static void make_raw_name(char *raw, char *pretty) #define BOLD 1 #define ITALIC 2 #define BITALIC (BOLD | ITALIC) + int mods = PLAIN; + char *last = style + strlen(style) - 2; + // Now try and parse the style string - look for the "=" sign style = strchr(style, '='); while ((style) && (style < last)) @@ -153,14 +159,14 @@ static void make_raw_name(char *raw, char *pretty) mods |= ITALIC; } goto NEXT_STYLE; - - case 's': + + case 'S': if (strncasecmp(style, "SuperBold", 9) == 0) { mods |= BOLD; } goto NEXT_STYLE; - + default: // find the next gap goto NEXT_STYLE; } // switch end @@ -202,17 +208,17 @@ Fl_Font Fl::set_fonts(const char* pattern_name) { FcFontSet *fnt_set; // Will hold the list of fonts we find FcPattern *fnt_pattern; // Holds the generic "match all names" pattern - FcObjectSet *fnt_obj_set = 0; // Holds the generic "match all objects" - + FcObjectSet *fnt_obj_set = 0; // Holds the generic "match all objects" + int j; // loop iterator variable int font_count; // Total number of fonts found to process char **full_list; // The list of font names we build if (fl_free_font > FL_FREE_FONT) // already been here return (Fl_Font)fl_free_font; - + fl_open_display(); // Just in case... - + // Make sure fontconfig is ready... is this necessary? The docs say it is // safe to call it multiple times, so just go for it anyway! if (!FcInit()) @@ -228,10 +234,10 @@ Fl_Font Fl::set_fonts(const char* pattern_name) // "pattern_name"? fnt_pattern = FcPatternCreate(); fnt_obj_set = FcObjectSetBuild(FC_FAMILY, FC_STYLE, (void *)0); - + // Hopefully, this is a set of all the fonts... fnt_set = FcFontList(0, fnt_pattern, fnt_obj_set); - + // We don't need the fnt_pattern and fnt_obj_set any more, release them FcPatternDestroy(fnt_pattern); FcObjectSetDestroy(fnt_obj_set); @@ -242,22 +248,22 @@ Fl_Font Fl::set_fonts(const char* pattern_name) char *stop; char *start; char *first; - + font_count = fnt_set->nfont; // How many fonts? - + // Allocate array of char*'s to hold the name strings full_list = (char **)malloc(sizeof(char *) * font_count); - + // iterate through all the font patterns and get the names out... for (j = 0; j < font_count; j++) { // NOTE: FcChar8 is a typedef of "unsigned char"... FcChar8 *font; // String to hold the font's name - + // Convert from fontconfig internal pattern to human readable name // NOTE: This WILL malloc storage, so we need to free it later... font = FcNameUnparse(fnt_set->fonts[j]); - + // The returned strings look like this... // Century Schoolbook:style=Bold Italic,fed kursiv,Fett Kursiv,... // So the bit we want is up to the first comma - BUT some strings have @@ -300,13 +306,13 @@ Fl_Font Fl::set_fonts(const char* pattern_name) if (reg) reg[1]='.'; } } - + // Release the fnt_set - we don't need it any more FcFontSetDestroy(fnt_set); - + // Sort the list into alphabetic order qsort(full_list, font_count, sizeof(*full_list), name_sort); - + // Now let us add the names we got to fltk's font list... for (j = 0; j < font_count; j++) { @@ -321,7 +327,7 @@ Fl_Font Fl::set_fonts(const char* pattern_name) stored_name = strdup(xft_name); Fl::set_font((Fl_Font)(j + FL_FREE_FONT), stored_name); fl_free_font ++; - + free(full_list[j]); // release that name from our internal array } } @@ -374,5 +380,5 @@ int Fl::get_font_sizes(Fl_Font fnum, int*& sizep) { } // -// End of "$Id: fl_set_fonts_xft.cxx 9396 2012-04-24 03:52:00Z fabien $". +// End of "$Id: fl_set_fonts_xft.cxx 10041 2014-01-03 16:17:05Z AlbrechtS $". // diff --git a/src/fl_shortcut.cxx b/src/fl_shortcut.cxx index 4c91c6e..28e59a9 100644 --- a/src/fl_shortcut.cxx +++ b/src/fl_shortcut.cxx @@ -1,5 +1,5 @@ // -// "$Id: fl_shortcut.cxx 8864 2011-07-19 04:49:30Z greg.ercolano $" +// "$Id: fl_shortcut.cxx 10250 2014-08-23 09:10:50Z cand $" // // Shortcut support routines for the Fast Light Tool Kit (FLTK). // @@ -179,7 +179,7 @@ const char* fl_shortcut_label(unsigned int shortcut) { \see fl_shortcut_label(unsigned int shortcut) */ const char* fl_shortcut_label(unsigned int shortcut, const char **eom) { - static char buf[20]; + static char buf[40]; char *p = buf; if (eom) *eom = p; if (!shortcut) {*p = 0; return buf;} @@ -189,11 +189,11 @@ const char* fl_shortcut_label(unsigned int shortcut, const char **eom) { shortcut |= FL_SHIFT; } #ifdef __APPLE__ - // this column contains utf8 characters - v - if (shortcut & FL_SHIFT) {strcpy(p,"\xe2\x87\xa7"); p += 3;} // upwards white arrow - if (shortcut & FL_CTRL) {strcpy(p,"\xe2\x8c\x83"); p += 3;} // up arrowhead - if (shortcut & FL_ALT) {strcpy(p,"\xe2\x8c\xa5"); p += 3;} // alternative key symbol - if (shortcut & FL_META) {strcpy(p,"\xe2\x8c\x98"); p += 3;} // place of interest sign + // this column contains utf8 characters - v + if (shortcut & FL_SHIFT) {strcpy(p,"\xe2\x87\xa7"); p += 3;} // U+21E7 (upwards white arrow) + if (shortcut & FL_CTRL) {strcpy(p,"\xe2\x8c\x83"); p += 3;} // U+2303 (up arrowhead) + if (shortcut & FL_ALT) {strcpy(p,"\xe2\x8c\xa5"); p += 3;} // U+2325 (option key) + if (shortcut & FL_META) {strcpy(p,"\xe2\x8c\x98"); p += 3;} // U+2318 (place of interest sign) #else if (shortcut & FL_META) {strcpy(p,"Meta+"); p += 5;} if (shortcut & FL_ALT) {strcpy(p,"Alt+"); p += 4;} @@ -270,14 +270,73 @@ const char* fl_shortcut_label(unsigned int shortcut, const char **eom) { # - Alt + - Shift ^ - Control + ! - Meta + @ - Command (Ctrl on linux/win, Meta on OSX) \endverbatim + + These special characters can be combined to form chords of modifier + keys. (See 'Remarks' below) + + After the optional modifier key prefixes listed above, one can either + specify a single keyboard character to use as the shortcut, or a + numeric sequence in hex, decimal or octal. + + Examples: + \verbatim + "c" -- Uses 'c' as the shortcut + "#^c" -- Same as FL_ALT|FL_CTRL|'c' + "#^!c" -- Same as FL_ALT|FL_CTRL|FL_META|'c' + "@c" -- Same as FL_COMMAND|'c' (see FL_COMMAND for platform specific behavior) + "0x63" -- Same as "c" (hex 63=='c') + "99" -- Same as "c" (dec 99=='c') + "0143" -- Same as "c" (octal 0143=='c') + "^0x63" -- Same as (FL_CTRL|'c'), or (FL_CTRL|0x63) + "^99" -- Same as (FL_CTRL|'c'), or (FL_CTRL|99) + "^0143" -- Same as (FL_CTRL|'c'), or (FL_CTRL|0143) + \endverbatim + + \remarks + Due to XForms legacy, there are some odd things to consider + when using the modifier characters. + \remarks + (1) You can use the special modifier keys for chords *only* + if the modifiers are provided in this order: #, +, ^, !, \@. + Other ordering can yield undefined results. + \remarks + So for instance, Ctrl-Alt-c must be specified as "#^c" (and not + "^#c"), due to the above ordering rule. + \remarks + (2) If you want to make a shortcut that uses one of the special + modifier characters (as the character being modified), then to + avoid confusion, specify the numeric equivalent, e.g. + \remarks + \verbatim + If you want.. Then use.. + ----------------------------- ------------------------------ + '#' as the shortcut.. "0x23" (instead of just "#"). + '+' as the shortcut.. "0x2b" (instead of just "+"). + '^' as the shortcut.. "0x5e" (instead of just "^"). + Alt-+ as the shortcut.. "#0x2b" (instead of "#+"). + Alt-^ as the shortcut.. "#0x5e" (instead of "#^"). + ..etc.. + \endverbatim + \remarks + As a general rule that's easy to remember, unless the shortcut + key to be modified is a single alpha-numeric character [A-Z,a-z,0-9), + it's probably best to use the numeric equivalents. + + \todo Fix these silly legacy issues in a future release + to support more predictable behavior for the modifier keys. */ unsigned int fl_old_shortcut(const char* s) { if (!s || !*s) return 0; + if (s[1]==0 && strchr("@!",s[0])) return s[0]; // maintain legacy behavior for "!" and "@" unsigned int n = 0; if (*s == '#') {n |= FL_ALT; s++;} if (*s == '+') {n |= FL_SHIFT; s++;} if (*s == '^') {n |= FL_CTRL; s++;} + if (*s == '!') {n |= FL_META; s++;} // added in 1.3.3 + if (*s == '@') {n |= FL_COMMAND; s++;} // added in 1.3.3 if (*s && s[1]) return n | (int)strtol(s,0,0); // allow 0xf00 to get any key return n | *s; } @@ -373,5 +432,5 @@ int Fl_Widget::test_shortcut() { } // -// End of "$Id: fl_shortcut.cxx 8864 2011-07-19 04:49:30Z greg.ercolano $". +// End of "$Id: fl_shortcut.cxx 10250 2014-08-23 09:10:50Z cand $". // diff --git a/src/fl_utf8.cxx b/src/fl_utf8.cxx index 857642f..8ad2f3b 100644 --- a/src/fl_utf8.cxx +++ b/src/fl_utf8.cxx @@ -1,5 +1,5 @@ // -// "$Id: fl_utf8.cxx 9704 2012-10-19 11:23:51Z manolo $" +// "$Id: fl_utf8.cxx 10248 2014-08-23 08:41:58Z cand $" // // Unicode to UTF-8 conversion functions. // @@ -58,7 +58,7 @@ extern "C" { #else // X-windows platform -# include <FL/Xutf8.h> +# include "Xutf8.h" # include <sys/types.h> # include <sys/stat.h> # include <fcntl.h> @@ -609,7 +609,7 @@ int fl_execvp(const char *file, char *const *argv) return _execvp(fl_utf2mbcs(file), argv); #else size_t l = strlen(file); - int i, n, ret; + int i, n; xchar **ar; // wbuf = (xchar*)realloc(wbuf, sizeof(xchar) * (l+1)); // wbuf[fl_utf2unicode((const unsigned char*)file, l, wbuf)] = 0; @@ -634,14 +634,14 @@ int fl_execvp(const char *file, char *const *argv) i++; } ar[n] = NULL; - ret = _wexecvp(wbuf, ar); + _wexecvp(wbuf, ar); // STR #3040 i = 0; while (i <= n) { free(ar[i]); i++; } free(ar); - return ret; + return -1; // STR #3040 #endif #else return execvp(file, argv); @@ -825,5 +825,5 @@ void fl_make_path_for_file( const char *path ) /** @} */ // -// End of "$Id: fl_utf8.cxx 9704 2012-10-19 11:23:51Z manolo $". +// End of "$Id: fl_utf8.cxx 10248 2014-08-23 08:41:58Z cand $". // diff --git a/src/flstring.h b/src/flstring.h index cc0e1ee..2c6aff4 100644 --- a/src/flstring.h +++ b/src/flstring.h @@ -1,5 +1,5 @@ /* - * "$Id: flstring.h 9573 2012-06-06 03:38:02Z fabien $" + * "$Id: flstring.h 10074 2014-01-21 11:07:43Z AlbrechtS $" * * Common string header file for the Fast Light Tool Kit (FLTK). * @@ -39,7 +39,7 @@ # undef index # endif /* index */ -# if defined(WIN32) && !defined(__CYGWIN__) +# if defined(WIN32) && !defined(__CYGWIN__) && !defined(__MINGW32__) # define strcasecmp(s,t) _stricmp((s), (t)) # define strncasecmp(s,t,n) _strnicmp((s), (t), (n)) /* Visual C++ 2005 incorrectly displays a warning about the use of POSIX APIs @@ -97,5 +97,5 @@ FL_EXPORT extern int fl_ascii_strcasecmp(const char *s, const char *t); #endif /* !flstring_h */ /* - * End of "$Id: flstring.h 9573 2012-06-06 03:38:02Z fabien $". + * End of "$Id: flstring.h 10074 2014-01-21 11:07:43Z AlbrechtS $". */ diff --git a/src/forms_timer.cxx b/src/forms_timer.cxx index 6fad755..6b66eeb 100644 --- a/src/forms_timer.cxx +++ b/src/forms_timer.cxx @@ -1,5 +1,5 @@ // -// "$Id: forms_timer.cxx 9325 2012-04-05 05:12:30Z fabien $" +// "$Id: forms_timer.cxx 10413 2014-10-30 09:16:49Z cand $" // // Forms timer object for the Fast Light Tool Kit (FLTK). // @@ -23,6 +23,7 @@ #include <FL/Fl.H> #include <FL/Fl_Timer.H> #include <FL/fl_draw.H> +#include <FL/forms.H> #ifdef WIN32 # ifdef __MWERKS__ # include <time.h> @@ -173,5 +174,5 @@ void Fl_Timer::suspended(char d) { } // -// End of "$Id: forms_timer.cxx 9325 2012-04-05 05:12:30Z fabien $". +// End of "$Id: forms_timer.cxx 10413 2014-10-30 09:16:49Z cand $". // diff --git a/src/gl_draw.cxx b/src/gl_draw.cxx index 2bc8c7b..5f78902 100644 --- a/src/gl_draw.cxx +++ b/src/gl_draw.cxx @@ -1,5 +1,5 @@ // -// "$Id: gl_draw.cxx 8864 2011-07-19 04:49:30Z greg.ercolano $" +// "$Id: gl_draw.cxx 10414 2014-10-30 09:18:45Z cand $" // // OpenGL drawing support routines for the Fast Light Tool Kit (FLTK). // @@ -24,6 +24,7 @@ #include <FL/Fl.H> #include <FL/gl.h> +#include <FL/gl_draw.H> #include <FL/x.H> #include <FL/fl_draw.H> #include <FL/Fl_Device.H> @@ -32,7 +33,7 @@ #include <FL/fl_utf8.h> #if !defined(WIN32) && !defined(__APPLE__) -#include <FL/Xutf8.h> +#include "Xutf8.h" #endif #if USE_XFT @@ -101,8 +102,9 @@ void gl_font(int fontid, int size) { //http://developer.apple.com/mac/library/documentation/Carbon/Conceptual/Carbon64BitGuide/OtherAPIChanges/OtherAPIChanges.html short font, face, size; uchar fn[256]; - fn[0]=strlen(fl_fontsize->q_name); - strcpy((char*)(fn+1), fl_fontsize->q_name); + const char *pname = Fl::get_font_name(fontid, NULL); + fn[0]=strlen(pname); + strcpy((char*)(fn+1), pname); GetFNum(fn, &font); face = 0; size = fl_fontsize->size; @@ -472,6 +474,7 @@ int gl_texture_fifo::compute_texture(const char* str, int n) CGColorSpaceRef lut = CGColorSpaceCreateDeviceRGB(); void *base = calloc(4*fifo[current].width, fifo[current].height); if (base == NULL) return -1; + CGContextRef save_gc = fl_gc; fl_gc = CGBitmapContextCreate(base, fifo[current].width, fifo[current].height, 8, fifo[current].width*4, lut, kCGImageAlphaPremultipliedLast); CGColorSpaceRelease(lut); fl_graphics_driver->font_descriptor(gl_fontsize); @@ -487,7 +490,7 @@ int gl_texture_fifo::compute_texture(const char* str, int n) glTexImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, GL_RGBA, fifo[current].width, fifo[current].height, 0, GL_RGBA, GL_UNSIGNED_BYTE, base); glPopAttrib(); CGContextRelease(fl_gc); - fl_gc = NULL; + fl_gc = save_gc; free(base); fifo[current].fdesc = gl_fontsize; return current; @@ -567,5 +570,5 @@ void gl_texture_reset() #endif // HAVE_GL // -// End of "$Id: gl_draw.cxx 8864 2011-07-19 04:49:30Z greg.ercolano $". +// End of "$Id: gl_draw.cxx 10414 2014-10-30 09:18:45Z cand $". // diff --git a/src/gl_start.cxx b/src/gl_start.cxx index 515d95c..416b3f6 100644 --- a/src/gl_start.cxx +++ b/src/gl_start.cxx @@ -1,5 +1,5 @@ // -// "$Id: gl_start.cxx 8864 2011-07-19 04:49:30Z greg.ercolano $" +// "$Id: gl_start.cxx 10414 2014-10-30 09:18:45Z cand $" // // OpenGL context routines for the Fast Light Tool Kit (FLTK). // @@ -35,6 +35,7 @@ #include <FL/Fl_Window.H> #include <FL/x.H> #include <FL/fl_draw.H> +#include <FL/gl.h> #include "Fl_Gl_Choice.H" static GLContext context; @@ -119,5 +120,5 @@ int Fl::gl_visual(int mode, int *alist) { #endif // -// End of "$Id: gl_start.cxx 8864 2011-07-19 04:49:30Z greg.ercolano $". +// End of "$Id: gl_start.cxx 10414 2014-10-30 09:18:45Z cand $". // diff --git a/src/makedepend b/src/makedepend index 74c05fb..32d5ff0 100644 --- a/src/makedepend +++ b/src/makedepend @@ -1,98 +1,102 @@ -# DO NOT DELETE THIS LINE -- make depend depends on it. +# DO NOT DELETE Fl.o: ../config.h ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H -Fl.o: ../FL/fl_types.h ../FL/Xutf8.h ../FL/Enumerations.H ../FL/Fl_Window.H -Fl.o: ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Tooltip.H ../FL/Fl_Widget.H -Fl.o: ../FL/x.H ../FL/Fl_Window.H flstring.h ../FL/Fl_Export.H -Fl.o: ../FL/fl_draw.H ../FL/Enumerations.H ../FL/Fl_Device.H -Fl.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H -Fl.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Pixmap.H +Fl.o: ../FL/fl_types.h ../FL/Enumerations.H ../FL/Fl_Window.H +Fl.o: ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Bitmap.H ../FL/Fl_Image.H +Fl.o: ../FL/Fl_Tooltip.H ../FL/Fl_Widget.H ../FL/x.H ../FL/Fl_Window.H +Fl.o: flstring.h ../FL/Fl_Export.H ../FL/fl_draw.H ../FL/Enumerations.H +Fl.o: ../FL/Fl_Device.H ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H +Fl.o: ../FL/Fl_Image.H ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H Fl.o: ../FL/Fl_RGB_Image.H Fl_Adjuster.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h -Fl_Adjuster.o: ../FL/Xutf8.h ../FL/Enumerations.H ../FL/Fl_Adjuster.H -Fl_Adjuster.o: ../FL/Fl_Valuator.H ../FL/Fl_Widget.H ../FL/Fl_Bitmap.H -Fl_Adjuster.o: ../FL/Fl_Image.H ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H -Fl_Adjuster.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Group.H +Fl_Adjuster.o: ../FL/Enumerations.H ../FL/Fl_Adjuster.H ../FL/Fl_Valuator.H +Fl_Adjuster.o: ../FL/Fl_Widget.H ../FL/Fl_Bitmap.H ../FL/fl_draw.H ../FL/x.H +Fl_Adjuster.o: ../FL/Fl_Window.H ../FL/Enumerations.H ../FL/Fl_Window.H +Fl_Adjuster.o: ../FL/Fl_Group.H ../FL/Fl_Bitmap.H ../FL/Fl_Image.H Fl_Adjuster.o: ../FL/Fl_Device.H ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H Fl_Adjuster.o: ../FL/Fl_Image.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H Fl_Adjuster.o: fastarrow.h mediumarrow.h slowarrow.h Fl_Bitmap.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h -Fl_Bitmap.o: ../FL/Xutf8.h ../FL/Enumerations.H ../FL/x.H ../FL/Fl_Window.H -Fl_Bitmap.o: ../FL/fl_draw.H ../FL/Enumerations.H ../FL/Fl_Window.H -Fl_Bitmap.o: ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Device.H -Fl_Bitmap.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H -Fl_Bitmap.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Pixmap.H +Fl_Bitmap.o: ../FL/Enumerations.H ../FL/x.H ../FL/Fl_Window.H ../FL/fl_draw.H +Fl_Bitmap.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Group.H +Fl_Bitmap.o: ../FL/Fl_Widget.H ../FL/Fl_Bitmap.H ../FL/Fl_Image.H +Fl_Bitmap.o: ../FL/Fl_Device.H ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H +Fl_Bitmap.o: ../FL/Fl_Image.H ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H Fl_Bitmap.o: ../FL/Fl_RGB_Image.H ../FL/Fl_Widget.H ../FL/Fl_Menu_Item.H Fl_Bitmap.o: ../FL/Fl_Printer.H ../FL/Fl_Paged_Device.H ../FL/Fl_PostScript.H Fl_Bitmap.o: flstring.h ../FL/Fl_Export.H ../config.h Fl_Browser.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h -Fl_Browser.o: ../FL/Xutf8.h ../FL/Enumerations.H ../FL/Fl_Browser.H -Fl_Browser.o: ../FL/Fl_Browser_.H ../FL/Fl_Group.H ../FL/Fl_Widget.H -Fl_Browser.o: ../FL/Fl_Scrollbar.H ../FL/Fl_Slider.H ../FL/Fl_Valuator.H -Fl_Browser.o: ../FL/Fl_Image.H ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H -Fl_Browser.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Device.H -Fl_Browser.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H -Fl_Browser.o: ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H -Fl_Browser.o: flstring.h ../FL/Fl_Export.H ../config.h +Fl_Browser.o: ../FL/Enumerations.H ../FL/Fl_Browser.H ../FL/Fl_Browser_.H +Fl_Browser.o: ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Scrollbar.H +Fl_Browser.o: ../FL/Fl_Slider.H ../FL/Fl_Valuator.H ../FL/Fl_Image.H +Fl_Browser.o: ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H +Fl_Browser.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Bitmap.H +Fl_Browser.o: ../FL/Fl_Device.H ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H +Fl_Browser.o: ../FL/Fl_Image.H ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H +Fl_Browser.o: ../FL/Fl_RGB_Image.H flstring.h ../FL/Fl_Export.H ../config.h +Fl_Browser.o: ../FL/Fl_Hold_Browser.H ../FL/Fl_Browser.H +Fl_Browser.o: ../FL/Fl_Multi_Browser.H ../FL/Fl_Select_Browser.H Fl_Browser_.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h -Fl_Browser_.o: ../FL/Xutf8.h ../FL/Enumerations.H ../FL/Fl_Widget.H -Fl_Browser_.o: ../FL/Fl_Browser_.H ../FL/Fl_Group.H ../FL/Fl_Widget.H -Fl_Browser_.o: ../FL/Fl_Scrollbar.H ../FL/Fl_Slider.H ../FL/Fl_Valuator.H -Fl_Browser_.o: ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H -Fl_Browser_.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Device.H -Fl_Browser_.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H -Fl_Browser_.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Pixmap.H +Fl_Browser_.o: ../FL/Enumerations.H ../FL/Fl_Widget.H ../FL/Fl_Browser_.H +Fl_Browser_.o: ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Scrollbar.H +Fl_Browser_.o: ../FL/Fl_Slider.H ../FL/Fl_Valuator.H ../FL/fl_draw.H +Fl_Browser_.o: ../FL/x.H ../FL/Fl_Window.H ../FL/Enumerations.H +Fl_Browser_.o: ../FL/Fl_Window.H ../FL/Fl_Bitmap.H ../FL/Fl_Image.H +Fl_Browser_.o: ../FL/Fl_Device.H ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H +Fl_Browser_.o: ../FL/Fl_Image.H ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H Fl_Browser_.o: ../FL/Fl_RGB_Image.H Fl_Browser_load.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H -Fl_Browser_load.o: ../FL/fl_types.h ../FL/Xutf8.h ../FL/Enumerations.H -Fl_Browser_load.o: ../FL/Fl_Browser.H ../FL/Fl_Browser_.H ../FL/Fl_Group.H -Fl_Browser_load.o: ../FL/Fl_Widget.H ../FL/Fl_Scrollbar.H ../FL/Fl_Slider.H -Fl_Browser_load.o: ../FL/Fl_Valuator.H ../FL/Fl_Image.H ../FL/fl_utf8.h +Fl_Browser_load.o: ../FL/fl_types.h ../FL/Enumerations.H ../FL/Fl_Browser.H +Fl_Browser_load.o: ../FL/Fl_Browser_.H ../FL/Fl_Group.H ../FL/Fl_Widget.H +Fl_Browser_load.o: ../FL/Fl_Scrollbar.H ../FL/Fl_Slider.H ../FL/Fl_Valuator.H +Fl_Browser_load.o: ../FL/Fl_Image.H ../FL/fl_utf8.h Fl_Box.o: ../FL/Fl_Widget.H ../FL/Fl_Box.H ../FL/Fl_Widget.H Fl_Box.o: ../FL/Enumerations.H ../FL/Fl_Export.H ../FL/fl_types.h Fl_Button.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h -Fl_Button.o: ../FL/Xutf8.h ../FL/Enumerations.H ../FL/Fl_Button.H -Fl_Button.o: ../FL/Fl_Widget.H ../FL/Fl_Group.H ../FL/Fl_Window.H -Fl_Button.o: ../FL/Fl_Group.H +Fl_Button.o: ../FL/Enumerations.H ../FL/Fl_Button.H ../FL/Fl_Widget.H +Fl_Button.o: ../FL/Fl_Group.H ../FL/Fl_Window.H ../FL/Fl_Group.H +Fl_Button.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Radio_Button.H +Fl_Button.o: ../FL/Fl_Button.H ../FL/Fl_Toggle_Button.H Fl_Chart.o: ../FL/math.h ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H -Fl_Chart.o: ../FL/fl_types.h ../FL/Xutf8.h ../FL/Enumerations.H -Fl_Chart.o: ../FL/Fl_Chart.H ../FL/Fl_Widget.H ../FL/fl_draw.H ../FL/x.H -Fl_Chart.o: ../FL/Fl_Window.H ../FL/Enumerations.H ../FL/Fl_Window.H -Fl_Chart.o: ../FL/Fl_Group.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H -Fl_Chart.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H -Fl_Chart.o: ../FL/Fl_Image.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H +Fl_Chart.o: ../FL/fl_types.h ../FL/Enumerations.H ../FL/Fl_Chart.H +Fl_Chart.o: ../FL/Fl_Widget.H ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H +Fl_Chart.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Group.H +Fl_Chart.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Device.H +Fl_Chart.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H +Fl_Chart.o: ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H Fl_Chart.o: flstring.h ../FL/Fl_Export.H ../config.h Fl_Check_Browser.o: flstring.h ../FL/Fl_Export.H ../config.h ../FL/fl_draw.H Fl_Check_Browser.o: ../FL/x.H ../FL/Enumerations.H ../FL/Fl_Export.H -Fl_Check_Browser.o: ../FL/fl_types.h ../FL/Fl_Window.H ../FL/Xutf8.h -Fl_Check_Browser.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Group.H -Fl_Check_Browser.o: ../FL/Fl_Widget.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H -Fl_Check_Browser.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H -Fl_Check_Browser.o: ../FL/Fl_Image.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H +Fl_Check_Browser.o: ../FL/fl_types.h ../FL/Fl_Window.H ../FL/Enumerations.H +Fl_Check_Browser.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H +Fl_Check_Browser.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Device.H +Fl_Check_Browser.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H +Fl_Check_Browser.o: ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H Fl_Check_Browser.o: ../FL/Fl_Check_Browser.H ../FL/Fl.H ../FL/fl_utf8.h Fl_Check_Browser.o: ../FL/Fl_Browser_.H ../FL/Fl_Scrollbar.H Fl_Check_Browser.o: ../FL/Fl_Slider.H ../FL/Fl_Valuator.H ../FL/Fl.H Fl_Check_Button.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H -Fl_Check_Button.o: ../FL/fl_types.h ../FL/Xutf8.h ../FL/Enumerations.H +Fl_Check_Button.o: ../FL/fl_types.h ../FL/Enumerations.H Fl_Check_Button.o: ../FL/Fl_Check_Button.H ../FL/Fl_Light_Button.H -Fl_Check_Button.o: ../FL/Fl_Button.H ../FL/Fl_Widget.H +Fl_Check_Button.o: ../FL/Fl_Button.H Fl_Choice.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h -Fl_Choice.o: ../FL/Xutf8.h ../FL/Enumerations.H ../FL/Fl_Choice.H -Fl_Choice.o: ../FL/Fl_Menu_.H ../FL/Fl_Widget.H ../FL/Fl_Menu_Item.H -Fl_Choice.o: ../FL/Fl_Image.H ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H -Fl_Choice.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Group.H +Fl_Choice.o: ../FL/Enumerations.H ../FL/Fl_Choice.H ../FL/Fl_Menu_.H +Fl_Choice.o: ../FL/Fl_Widget.H ../FL/Fl_Menu_Item.H ../FL/Fl_Image.H +Fl_Choice.o: ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H ../FL/Enumerations.H +Fl_Choice.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Bitmap.H Fl_Choice.o: ../FL/Fl_Device.H ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H Fl_Choice.o: ../FL/Fl_Image.H ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H Fl_Choice.o: ../FL/Fl_RGB_Image.H flstring.h ../FL/Fl_Export.H ../config.h Fl_Clock.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h -Fl_Clock.o: ../FL/Xutf8.h ../FL/Enumerations.H ../FL/Fl_Clock.H -Fl_Clock.o: ../FL/Fl_Widget.H ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H -Fl_Clock.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Group.H +Fl_Clock.o: ../FL/Enumerations.H ../FL/Fl_Clock.H ../FL/Fl_Widget.H +Fl_Clock.o: ../FL/Fl_Round_Clock.H ../FL/Fl_Clock.H ../FL/fl_draw.H ../FL/x.H +Fl_Clock.o: ../FL/Fl_Window.H ../FL/Enumerations.H ../FL/Fl_Window.H +Fl_Clock.o: ../FL/Fl_Group.H ../FL/Fl_Bitmap.H ../FL/Fl_Image.H Fl_Clock.o: ../FL/Fl_Device.H ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H -Fl_Clock.o: ../FL/Fl_Image.H ../FL/Fl_Bitmap.H ../FL/Fl_Image.H -Fl_Clock.o: ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H +Fl_Clock.o: ../FL/Fl_Image.H ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H +Fl_Clock.o: ../FL/Fl_RGB_Image.H Fl_Color_Chooser.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H -Fl_Color_Chooser.o: ../FL/fl_types.h ../FL/Xutf8.h ../FL/Enumerations.H +Fl_Color_Chooser.o: ../FL/fl_types.h ../FL/Enumerations.H Fl_Color_Chooser.o: ../FL/Fl_Color_Chooser.H ../FL/Fl_Group.H ../FL/Fl_Box.H Fl_Color_Chooser.o: ../FL/Fl_Widget.H ../FL/Fl_Return_Button.H Fl_Color_Chooser.o: ../FL/Fl_Button.H ../FL/Fl_Choice.H ../FL/Fl_Menu_.H @@ -100,210 +104,238 @@ Fl_Color_Chooser.o: ../FL/Fl_Menu_Item.H ../FL/Fl_Image.H Fl_Color_Chooser.o: ../FL/Fl_Value_Input.H ../FL/Fl_Valuator.H Fl_Color_Chooser.o: ../FL/Fl_Input.H ../FL/Fl_Input_.H ../FL/fl_draw.H Fl_Color_Chooser.o: ../FL/x.H ../FL/Fl_Window.H ../FL/Enumerations.H -Fl_Color_Chooser.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Device.H -Fl_Color_Chooser.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H -Fl_Color_Chooser.o: ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H -Fl_Color_Chooser.o: ../FL/math.h +Fl_Color_Chooser.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Bitmap.H +Fl_Color_Chooser.o: ../FL/Fl_Device.H ../FL/Fl_Plugin.H +Fl_Color_Chooser.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H +Fl_Color_Chooser.o: ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H ../FL/math.h +Fl_Copy_Surface.o: ../FL/Fl_Copy_Surface.H ../FL/Fl_Paged_Device.H +Fl_Copy_Surface.o: ../FL/Fl_Device.H ../FL/x.H ../FL/Enumerations.H +Fl_Copy_Surface.o: ../FL/Fl_Export.H ../FL/fl_types.h ../FL/Fl_Window.H +Fl_Copy_Surface.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H +Fl_Copy_Surface.o: ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H ../FL/Fl_Image.H +Fl_Copy_Surface.o: ../FL/Fl_RGB_Image.H ../FL/Fl_Window.H ../FL/Fl_Group.H +Fl_Copy_Surface.o: ../FL/Fl_Widget.H ../FL/Fl_Bitmap.H ../FL/Fl_Printer.H +Fl_Copy_Surface.o: ../FL/fl_draw.H ../FL/Enumerations.H ../FL/Fl_PostScript.H +Fl_Copy_Surface.o: ../FL/Fl.H ../FL/fl_utf8.h Fl_Counter.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h -Fl_Counter.o: ../FL/Xutf8.h ../FL/Enumerations.H ../FL/Fl_Counter.H -Fl_Counter.o: ../FL/Fl_Valuator.H ../FL/Fl_Widget.H ../FL/fl_draw.H ../FL/x.H -Fl_Counter.o: ../FL/Fl_Window.H ../FL/Enumerations.H ../FL/Fl_Window.H -Fl_Counter.o: ../FL/Fl_Group.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H -Fl_Counter.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H -Fl_Counter.o: ../FL/Fl_Image.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H +Fl_Counter.o: ../FL/Enumerations.H ../FL/Fl_Counter.H ../FL/Fl_Valuator.H +Fl_Counter.o: ../FL/Fl_Widget.H ../FL/Fl_Simple_Counter.H ../FL/Fl_Counter.H +Fl_Counter.o: ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H +Fl_Counter.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Group.H +Fl_Counter.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Device.H +Fl_Counter.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H +Fl_Counter.o: ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H Fl_Dial.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h -Fl_Dial.o: ../FL/Xutf8.h ../FL/Enumerations.H ../FL/Fl_Dial.H -Fl_Dial.o: ../FL/Fl_Valuator.H ../FL/Fl_Widget.H ../FL/fl_draw.H ../FL/x.H -Fl_Dial.o: ../FL/Fl_Window.H ../FL/Enumerations.H ../FL/Fl_Window.H -Fl_Dial.o: ../FL/Fl_Group.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H -Fl_Dial.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H -Fl_Dial.o: ../FL/Fl_Image.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H +Fl_Dial.o: ../FL/Enumerations.H ../FL/Fl_Dial.H ../FL/Fl_Valuator.H +Fl_Dial.o: ../FL/Fl_Widget.H ../FL/Fl_Fill_Dial.H ../FL/Fl_Dial.H +Fl_Dial.o: ../FL/Fl_Line_Dial.H ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H +Fl_Dial.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Group.H +Fl_Dial.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Device.H +Fl_Dial.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H +Fl_Dial.o: ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H Fl_Dial.o: ../FL/math.h Fl_Device.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h -Fl_Device.o: ../FL/Xutf8.h ../FL/Enumerations.H ../FL/Fl_Device.H ../FL/x.H +Fl_Device.o: ../FL/Enumerations.H ../FL/Fl_Device.H ../FL/x.H Fl_Device.o: ../FL/Fl_Window.H ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H -Fl_Device.o: ../FL/Fl_Image.H ../FL/Fl_Bitmap.H ../FL/Fl_Image.H -Fl_Device.o: ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H +Fl_Device.o: ../FL/Fl_Image.H ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H +Fl_Device.o: ../FL/Fl_Image.H ../FL/Fl_RGB_Image.H Fl_Double_Window.o: ../config.h ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H -Fl_Double_Window.o: ../FL/fl_types.h ../FL/Xutf8.h ../FL/Enumerations.H +Fl_Double_Window.o: ../FL/fl_types.h ../FL/Enumerations.H Fl_Double_Window.o: ../FL/Fl_Double_Window.H ../FL/Fl_Window.H +Fl_Double_Window.o: ../FL/Fl_Overlay_Window.H ../FL/Fl_Double_Window.H Fl_Double_Window.o: ../FL/Fl_Printer.H ../FL/x.H ../FL/Fl_Paged_Device.H Fl_Double_Window.o: ../FL/Fl_Device.H ../FL/Fl_Plugin.H Fl_Double_Window.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H -Fl_Double_Window.o: ../FL/Fl_Image.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H +Fl_Double_Window.o: ../FL/Fl_Pixmap.H ../FL/Fl_Image.H ../FL/Fl_RGB_Image.H Fl_Double_Window.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H -Fl_Double_Window.o: ../FL/fl_draw.H ../FL/Enumerations.H +Fl_Double_Window.o: ../FL/Fl_Bitmap.H ../FL/fl_draw.H ../FL/Enumerations.H Fl_Double_Window.o: ../FL/Fl_PostScript.H Fl_File_Browser.o: ../FL/Fl_File_Browser.H ../FL/Fl_Browser.H -Fl_File_Browser.o: ../FL/Fl_Browser_.H ../FL/Fl_Group.H ../FL/Fl_Widget.H -Fl_File_Browser.o: ../FL/Enumerations.H ../FL/Fl_Export.H ../FL/fl_types.h -Fl_File_Browser.o: ../FL/Fl_Scrollbar.H ../FL/Fl_Slider.H ../FL/Fl_Valuator.H -Fl_File_Browser.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Xutf8.h ../FL/Fl_Image.H -Fl_File_Browser.o: ../FL/Fl_File_Icon.H ../FL/Fl.H ../FL/filename.H -Fl_File_Browser.o: ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H -Fl_File_Browser.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Device.H -Fl_File_Browser.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H -Fl_File_Browser.o: ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H -Fl_File_Browser.o: ../FL/filename.H flstring.h ../FL/Fl_Export.H ../config.h +Fl_File_Browser.o: ../FL/Fl_File_Icon.H ../FL/Fl.H ../FL/fl_utf8.h +Fl_File_Browser.o: ../FL/Fl_Export.H ../FL/fl_types.h ../FL/Enumerations.H +Fl_File_Browser.o: ../FL/filename.H ../FL/fl_draw.H ../FL/x.H +Fl_File_Browser.o: ../FL/Fl_Window.H ../FL/Enumerations.H ../FL/Fl_Window.H +Fl_File_Browser.o: ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Bitmap.H +Fl_File_Browser.o: ../FL/Fl_Image.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H +Fl_File_Browser.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H +Fl_File_Browser.o: ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H ../FL/filename.H +Fl_File_Browser.o: flstring.h ../FL/Fl_Export.H ../config.h Fl_File_Chooser.o: ../FL/Fl_File_Chooser.H ../FL/Fl.H ../FL/fl_utf8.h -Fl_File_Chooser.o: ../FL/Fl_Export.H ../FL/fl_types.h ../FL/Xutf8.h -Fl_File_Chooser.o: ../FL/Enumerations.H ../FL/Fl_Double_Window.H -Fl_File_Chooser.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Choice.H -Fl_File_Chooser.o: ../FL/Fl_Menu_.H ../FL/Fl_Widget.H ../FL/Fl_Menu_Item.H -Fl_File_Chooser.o: ../FL/Fl_Image.H ../FL/Fl_Menu_Button.H ../FL/Fl_Button.H +Fl_File_Chooser.o: ../FL/Fl_Export.H ../FL/fl_types.h ../FL/Enumerations.H +Fl_File_Chooser.o: ../FL/Fl_Double_Window.H ../FL/Fl_Window.H +Fl_File_Chooser.o: ../FL/Fl_Group.H ../FL/Fl_Choice.H ../FL/Fl_Menu_.H +Fl_File_Chooser.o: ../FL/Fl_Widget.H ../FL/Fl_Menu_Item.H ../FL/Fl_Image.H +Fl_File_Chooser.o: ../FL/Fl_Menu_Button.H ../FL/Fl_Button.H Fl_File_Chooser.o: ../FL/Fl_Preferences.H ../FL/Fl_Tile.H ../FL/Fl_Group.H Fl_File_Chooser.o: ../FL/Fl_File_Browser.H ../FL/Fl_Browser.H -Fl_File_Chooser.o: ../FL/Fl_Browser_.H ../FL/Fl_Scrollbar.H ../FL/Fl_Slider.H -Fl_File_Chooser.o: ../FL/Fl_Valuator.H ../FL/Fl_File_Icon.H ../FL/Fl.H -Fl_File_Chooser.o: ../FL/filename.H ../FL/Fl_Box.H ../FL/Fl_Check_Button.H +Fl_File_Chooser.o: ../FL/Fl_File_Icon.H ../FL/Fl.H ../FL/filename.H +Fl_File_Chooser.o: ../FL/Fl_Box.H ../FL/Fl_Check_Button.H Fl_File_Chooser.o: ../FL/Fl_Light_Button.H ../FL/Fl_Button.H Fl_File_Chooser.o: ../FL/Fl_File_Input.H ../FL/Fl_Input.H ../FL/Fl_Input_.H Fl_File_Chooser.o: ../FL/Fl_Return_Button.H ../FL/fl_ask.H ../FL/fl_draw.H Fl_File_Chooser.o: ../FL/x.H ../FL/Enumerations.H ../FL/Fl_Window.H -Fl_File_Chooser.o: ../FL/Fl_Device.H ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H -Fl_File_Chooser.o: ../FL/Fl_Image.H ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H -Fl_File_Chooser.o: ../FL/Fl_RGB_Image.H +Fl_File_Chooser.o: ../FL/Fl_Bitmap.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H +Fl_File_Chooser.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H +Fl_File_Chooser.o: ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H Fl_File_Chooser2.o: ../FL/Fl_File_Chooser.H ../FL/Fl.H ../FL/fl_utf8.h -Fl_File_Chooser2.o: ../FL/Fl_Export.H ../FL/fl_types.h ../FL/Xutf8.h -Fl_File_Chooser2.o: ../FL/Enumerations.H ../FL/Fl_Double_Window.H -Fl_File_Chooser2.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Choice.H -Fl_File_Chooser2.o: ../FL/Fl_Menu_.H ../FL/Fl_Widget.H ../FL/Fl_Menu_Item.H -Fl_File_Chooser2.o: ../FL/Fl_Image.H ../FL/Fl_Menu_Button.H ../FL/Fl_Button.H +Fl_File_Chooser2.o: ../FL/Fl_Export.H ../FL/fl_types.h ../FL/Enumerations.H +Fl_File_Chooser2.o: ../FL/Fl_Double_Window.H ../FL/Fl_Window.H +Fl_File_Chooser2.o: ../FL/Fl_Group.H ../FL/Fl_Choice.H ../FL/Fl_Menu_.H +Fl_File_Chooser2.o: ../FL/Fl_Widget.H ../FL/Fl_Menu_Item.H ../FL/Fl_Image.H +Fl_File_Chooser2.o: ../FL/Fl_Menu_Button.H ../FL/Fl_Button.H Fl_File_Chooser2.o: ../FL/Fl_Preferences.H ../FL/Fl_Tile.H ../FL/Fl_Group.H Fl_File_Chooser2.o: ../FL/Fl_File_Browser.H ../FL/Fl_Browser.H -Fl_File_Chooser2.o: ../FL/Fl_Browser_.H ../FL/Fl_Scrollbar.H -Fl_File_Chooser2.o: ../FL/Fl_Slider.H ../FL/Fl_Valuator.H Fl_File_Chooser2.o: ../FL/Fl_File_Icon.H ../FL/Fl.H ../FL/filename.H Fl_File_Chooser2.o: ../FL/Fl_Box.H ../FL/Fl_Check_Button.H Fl_File_Chooser2.o: ../FL/Fl_Light_Button.H ../FL/Fl_Button.H Fl_File_Chooser2.o: ../FL/Fl_File_Input.H ../FL/Fl_Input.H ../FL/Fl_Input_.H Fl_File_Chooser2.o: ../FL/Fl_Return_Button.H ../FL/fl_ask.H ../FL/filename.H Fl_File_Chooser2.o: ../FL/x.H ../FL/Fl_Shared_Image.H ../FL/fl_draw.H -Fl_File_Chooser2.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Device.H -Fl_File_Chooser2.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H -Fl_File_Chooser2.o: ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H -Fl_File_Chooser2.o: flstring.h ../FL/Fl_Export.H ../config.h +Fl_File_Chooser2.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Bitmap.H +Fl_File_Chooser2.o: ../FL/Fl_Device.H ../FL/Fl_Plugin.H +Fl_File_Chooser2.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H +Fl_File_Chooser2.o: ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H flstring.h +Fl_File_Chooser2.o: ../FL/Fl_Export.H ../config.h Fl_File_Icon.o: ../FL/fl_utf8.h flstring.h ../FL/Fl_Export.H ../config.h Fl_File_Icon.o: ../FL/Fl_File_Icon.H ../FL/Fl.H ../FL/fl_utf8.h -Fl_File_Icon.o: ../FL/Fl_Export.H ../FL/fl_types.h ../FL/Xutf8.h -Fl_File_Icon.o: ../FL/Enumerations.H ../FL/Fl_Widget.H ../FL/fl_draw.H -Fl_File_Icon.o: ../FL/x.H ../FL/Fl_Window.H ../FL/Enumerations.H -Fl_File_Icon.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H +Fl_File_Icon.o: ../FL/Fl_Export.H ../FL/fl_types.h ../FL/Enumerations.H +Fl_File_Icon.o: ../FL/Fl_Widget.H ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H +Fl_File_Icon.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Group.H +Fl_File_Icon.o: ../FL/Fl_Widget.H ../FL/Fl_Bitmap.H ../FL/Fl_Image.H Fl_File_Icon.o: ../FL/Fl_Device.H ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H -Fl_File_Icon.o: ../FL/Fl_Image.H ../FL/Fl_Bitmap.H ../FL/Fl_Image.H -Fl_File_Icon.o: ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H ../FL/filename.H +Fl_File_Icon.o: ../FL/Fl_Image.H ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H +Fl_File_Icon.o: ../FL/Fl_RGB_Image.H ../FL/filename.H Fl_File_Input.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H -Fl_File_Input.o: ../FL/fl_types.h ../FL/Xutf8.h ../FL/Enumerations.H -Fl_File_Input.o: ../FL/Fl_File_Input.H ../FL/Fl_Input.H ../FL/Fl_Input_.H -Fl_File_Input.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H -Fl_File_Input.o: ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H +Fl_File_Input.o: ../FL/fl_types.h ../FL/Enumerations.H ../FL/Fl_File_Input.H +Fl_File_Input.o: ../FL/Fl_Input.H ../FL/Fl_Input_.H ../FL/Fl_Window.H +Fl_File_Input.o: ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Bitmap.H +Fl_File_Input.o: ../FL/Fl_Image.H ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H Fl_File_Input.o: ../FL/Enumerations.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H Fl_File_Input.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H -Fl_File_Input.o: ../FL/Fl_Image.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H -Fl_File_Input.o: ../FL/filename.H flstring.h ../FL/Fl_Export.H ../config.h +Fl_File_Input.o: ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H ../FL/filename.H +Fl_File_Input.o: flstring.h ../FL/Fl_Export.H ../config.h Fl_Group.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h -Fl_Group.o: ../FL/Xutf8.h ../FL/Enumerations.H ../FL/Fl_Group.H -Fl_Group.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H -Fl_Group.o: ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H ../FL/Enumerations.H -Fl_Group.o: ../FL/Fl_Device.H ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H -Fl_Group.o: ../FL/Fl_Image.H ../FL/Fl_Bitmap.H ../FL/Fl_Image.H -Fl_Group.o: ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H +Fl_Group.o: ../FL/Enumerations.H ../FL/Fl_Group.H ../FL/Fl_Window.H +Fl_Group.o: ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Bitmap.H +Fl_Group.o: ../FL/Fl_Image.H ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H +Fl_Group.o: ../FL/Enumerations.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H +Fl_Group.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H +Fl_Group.o: ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H ../FL/Fl_Input_Choice.H +Fl_Group.o: ../FL/Fl_Input.H ../FL/Fl_Input_.H ../FL/Fl_Menu_Button.H +Fl_Group.o: ../FL/Fl_Menu_.H ../FL/Fl_Menu_Item.H ../FL/Fl_Spinner.H +Fl_Group.o: ../FL/Fl_Repeat_Button.H ../FL/Fl.H ../FL/Fl_Button.H Fl_Help_View.o: ../FL/Fl_Help_View.H ../FL/Fl.H ../FL/fl_utf8.h -Fl_Help_View.o: ../FL/Fl_Export.H ../FL/fl_types.h ../FL/Xutf8.h -Fl_Help_View.o: ../FL/Enumerations.H ../FL/Fl_Group.H ../FL/Fl_Widget.H -Fl_Help_View.o: ../FL/Fl_Scrollbar.H ../FL/Fl_Slider.H ../FL/Fl_Valuator.H -Fl_Help_View.o: ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H -Fl_Help_View.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Device.H -Fl_Help_View.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H -Fl_Help_View.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Pixmap.H +Fl_Help_View.o: ../FL/Fl_Export.H ../FL/fl_types.h ../FL/Enumerations.H +Fl_Help_View.o: ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Scrollbar.H +Fl_Help_View.o: ../FL/Fl_Slider.H ../FL/Fl_Valuator.H ../FL/fl_draw.H +Fl_Help_View.o: ../FL/x.H ../FL/Fl_Window.H ../FL/Enumerations.H +Fl_Help_View.o: ../FL/Fl_Window.H ../FL/Fl_Bitmap.H ../FL/Fl_Image.H +Fl_Help_View.o: ../FL/Fl_Device.H ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H +Fl_Help_View.o: ../FL/Fl_Image.H ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H Fl_Help_View.o: ../FL/Fl_RGB_Image.H ../FL/Fl_Shared_Image.H ../FL/filename.H Fl_Help_View.o: ../FL/fl_utf8.h ../FL/filename.H flstring.h ../FL/Fl_Export.H Fl_Help_View.o: ../config.h Fl_Image.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h -Fl_Image.o: ../FL/Xutf8.h ../FL/Enumerations.H ../FL/fl_draw.H ../FL/x.H -Fl_Image.o: ../FL/Fl_Window.H ../FL/Enumerations.H ../FL/Fl_Window.H -Fl_Image.o: ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Device.H -Fl_Image.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H -Fl_Image.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Pixmap.H +Fl_Image.o: ../FL/Enumerations.H ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H +Fl_Image.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Group.H +Fl_Image.o: ../FL/Fl_Widget.H ../FL/Fl_Bitmap.H ../FL/Fl_Image.H +Fl_Image.o: ../FL/Fl_Device.H ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H +Fl_Image.o: ../FL/Fl_Image.H ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H Fl_Image.o: ../FL/Fl_RGB_Image.H ../FL/Fl_Widget.H ../FL/Fl_Menu_Item.H Fl_Image.o: flstring.h ../FL/Fl_Export.H ../config.h +Fl_Image_Surface.o: ../FL/Fl_Image_Surface.H ../FL/Fl_Copy_Surface.H +Fl_Image_Surface.o: ../FL/Fl_Paged_Device.H ../FL/Fl_Device.H ../FL/x.H +Fl_Image_Surface.o: ../FL/Enumerations.H ../FL/Fl_Export.H ../FL/fl_types.h +Fl_Image_Surface.o: ../FL/Fl_Window.H ../FL/Fl_Plugin.H +Fl_Image_Surface.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H +Fl_Image_Surface.o: ../FL/Fl_Pixmap.H ../FL/Fl_Image.H ../FL/Fl_RGB_Image.H +Fl_Image_Surface.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H +Fl_Image_Surface.o: ../FL/Fl_Bitmap.H ../FL/Fl_Printer.H ../FL/fl_draw.H +Fl_Image_Surface.o: ../FL/Enumerations.H ../FL/Fl_PostScript.H ../FL/Fl.H +Fl_Image_Surface.o: ../FL/fl_utf8.h Fl_Input.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h -Fl_Input.o: ../FL/Xutf8.h ../FL/Enumerations.H ../FL/Fl_Window.H -Fl_Input.o: ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Input.H -Fl_Input.o: ../FL/Fl_Input_.H ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H -Fl_Input.o: ../FL/Enumerations.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H -Fl_Input.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H -Fl_Input.o: ../FL/Fl_Image.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H +Fl_Input.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Group.H +Fl_Input.o: ../FL/Fl_Widget.H ../FL/Fl_Bitmap.H ../FL/Fl_Image.H +Fl_Input.o: ../FL/Fl_Input.H ../FL/Fl_Input_.H ../FL/fl_draw.H ../FL/x.H +Fl_Input.o: ../FL/Fl_Window.H ../FL/Enumerations.H ../FL/Fl_Device.H +Fl_Input.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H +Fl_Input.o: ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H Fl_Input.o: ../FL/fl_ask.H flstring.h ../FL/Fl_Export.H ../config.h +Fl_Input.o: ../FL/Fl_Float_Input.H ../FL/Fl_Input.H ../FL/Fl_Int_Input.H +Fl_Input.o: ../FL/Fl_Multiline_Input.H ../FL/Fl_Output.H +Fl_Input.o: ../FL/Fl_Multiline_Output.H ../FL/Fl_Output.H +Fl_Input.o: ../FL/Fl_Secret_Input.H Fl_Input_.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h -Fl_Input_.o: ../FL/Xutf8.h ../FL/Enumerations.H ../FL/Fl_Input_.H -Fl_Input_.o: ../FL/Fl_Widget.H ../FL/Fl_Window.H ../FL/Fl_Group.H -Fl_Input_.o: ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H ../FL/Enumerations.H -Fl_Input_.o: ../FL/Fl_Device.H ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H -Fl_Input_.o: ../FL/Fl_Image.H ../FL/Fl_Bitmap.H ../FL/Fl_Image.H +Fl_Input_.o: ../FL/Enumerations.H ../FL/Fl_Input_.H ../FL/Fl_Widget.H +Fl_Input_.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Bitmap.H +Fl_Input_.o: ../FL/Fl_Image.H ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H +Fl_Input_.o: ../FL/Enumerations.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H +Fl_Input_.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H Fl_Input_.o: ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H ../FL/fl_ask.H Fl_Input_.o: ../FL/fl_utf8.h flstring.h ../FL/Fl_Export.H ../config.h Fl_Light_Button.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H -Fl_Light_Button.o: ../FL/fl_types.h ../FL/Xutf8.h ../FL/Enumerations.H +Fl_Light_Button.o: ../FL/fl_types.h ../FL/Enumerations.H Fl_Light_Button.o: ../FL/Fl_Light_Button.H ../FL/Fl_Button.H -Fl_Light_Button.o: ../FL/Fl_Widget.H ../FL/fl_draw.H ../FL/x.H -Fl_Light_Button.o: ../FL/Fl_Window.H ../FL/Enumerations.H ../FL/Fl_Window.H -Fl_Light_Button.o: ../FL/Fl_Group.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H -Fl_Light_Button.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H -Fl_Light_Button.o: ../FL/Fl_Image.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H -Fl_Light_Button.o: flstring.h ../FL/Fl_Export.H ../config.h +Fl_Light_Button.o: ../FL/Fl_Radio_Light_Button.H ../FL/Fl_Light_Button.H +Fl_Light_Button.o: ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H +Fl_Light_Button.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Group.H +Fl_Light_Button.o: ../FL/Fl_Widget.H ../FL/Fl_Bitmap.H ../FL/Fl_Image.H +Fl_Light_Button.o: ../FL/Fl_Device.H ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H +Fl_Light_Button.o: ../FL/Fl_Image.H ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H +Fl_Light_Button.o: ../FL/Fl_RGB_Image.H flstring.h ../FL/Fl_Export.H +Fl_Light_Button.o: ../config.h Fl_Menu.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h -Fl_Menu.o: ../FL/Xutf8.h ../FL/Enumerations.H ../FL/Fl_Menu_Window.H +Fl_Menu.o: ../FL/Enumerations.H ../FL/Fl_Menu_Window.H Fl_Menu.o: ../FL/Fl_Single_Window.H ../FL/Fl_Window.H ../FL/Fl_Menu_.H Fl_Menu.o: ../FL/Fl_Widget.H ../FL/Fl_Menu_Item.H ../FL/Fl_Image.H Fl_Menu.o: ../FL/fl_draw.H ../FL/x.H ../FL/Enumerations.H ../FL/Fl_Window.H -Fl_Menu.o: ../FL/Fl_Group.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H -Fl_Menu.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H -Fl_Menu.o: ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H flstring.h -Fl_Menu.o: ../FL/Fl_Export.H ../config.h +Fl_Menu.o: ../FL/Fl_Group.H ../FL/Fl_Bitmap.H ../FL/Fl_Device.H +Fl_Menu.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H +Fl_Menu.o: ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H +Fl_Menu.o: flstring.h ../FL/Fl_Export.H ../config.h Fl_Menu_.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h -Fl_Menu_.o: ../FL/Xutf8.h ../FL/Enumerations.H ../FL/Fl_Menu_.H -Fl_Menu_.o: ../FL/Fl_Widget.H ../FL/Fl_Menu_Item.H ../FL/Fl_Image.H -Fl_Menu_.o: flstring.h ../FL/Fl_Export.H ../config.h +Fl_Menu_.o: ../FL/Enumerations.H ../FL/Fl_Menu_.H ../FL/Fl_Widget.H +Fl_Menu_.o: ../FL/Fl_Menu_Item.H ../FL/Fl_Image.H flstring.h +Fl_Menu_.o: ../FL/Fl_Export.H ../config.h Fl_Menu_Bar.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h -Fl_Menu_Bar.o: ../FL/Xutf8.h ../FL/Enumerations.H ../FL/Fl_Menu_Bar.H -Fl_Menu_Bar.o: ../FL/Fl_Menu_.H ../FL/Fl_Widget.H ../FL/Fl_Menu_Item.H -Fl_Menu_Bar.o: ../FL/Fl_Image.H ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H +Fl_Menu_Bar.o: ../FL/Enumerations.H ../FL/Fl_Menu_Bar.H ../FL/Fl_Menu_.H +Fl_Menu_Bar.o: ../FL/Fl_Widget.H ../FL/Fl_Menu_Item.H ../FL/Fl_Image.H +Fl_Menu_Bar.o: ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H Fl_Menu_Bar.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Group.H -Fl_Menu_Bar.o: ../FL/Fl_Device.H ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H -Fl_Menu_Bar.o: ../FL/Fl_Image.H ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H -Fl_Menu_Bar.o: ../FL/Fl_RGB_Image.H +Fl_Menu_Bar.o: ../FL/Fl_Bitmap.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H +Fl_Menu_Bar.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H +Fl_Menu_Bar.o: ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H Fl_Menu_Button.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H -Fl_Menu_Button.o: ../FL/fl_types.h ../FL/Xutf8.h ../FL/Enumerations.H +Fl_Menu_Button.o: ../FL/fl_types.h ../FL/Enumerations.H Fl_Menu_Button.o: ../FL/Fl_Menu_Button.H ../FL/Fl_Menu_.H ../FL/Fl_Widget.H Fl_Menu_Button.o: ../FL/Fl_Menu_Item.H ../FL/Fl_Image.H ../FL/fl_draw.H Fl_Menu_Button.o: ../FL/x.H ../FL/Fl_Window.H ../FL/Enumerations.H -Fl_Menu_Button.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Device.H -Fl_Menu_Button.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H -Fl_Menu_Button.o: ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H +Fl_Menu_Button.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Bitmap.H +Fl_Menu_Button.o: ../FL/Fl_Device.H ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H +Fl_Menu_Button.o: ../FL/Fl_Image.H ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H +Fl_Menu_Button.o: ../FL/Fl_RGB_Image.H Fl_Menu_Window.o: ../config.h ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H -Fl_Menu_Window.o: ../FL/fl_types.h ../FL/Xutf8.h ../FL/Enumerations.H -Fl_Menu_Window.o: ../FL/x.H ../FL/Fl_Window.H ../FL/fl_draw.H -Fl_Menu_Window.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Group.H -Fl_Menu_Window.o: ../FL/Fl_Widget.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H -Fl_Menu_Window.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H -Fl_Menu_Window.o: ../FL/Fl_Image.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H +Fl_Menu_Window.o: ../FL/fl_types.h ../FL/Enumerations.H ../FL/x.H +Fl_Menu_Window.o: ../FL/Fl_Window.H ../FL/fl_draw.H ../FL/Enumerations.H +Fl_Menu_Window.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H +Fl_Menu_Window.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Device.H +Fl_Menu_Window.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H +Fl_Menu_Window.o: ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H Fl_Menu_Window.o: ../FL/Fl_Menu_Window.H ../FL/Fl_Single_Window.H Fl_Menu_add.o: ../FL/Fl_Menu_.H ../FL/Fl_Widget.H ../FL/Enumerations.H Fl_Menu_add.o: ../FL/Fl_Export.H ../FL/fl_types.h ../FL/Fl_Menu_Item.H Fl_Menu_add.o: ../FL/Fl_Image.H flstring.h ../FL/Fl_Export.H ../config.h Fl_Menu_global.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H -Fl_Menu_global.o: ../FL/fl_types.h ../FL/Xutf8.h ../FL/Enumerations.H -Fl_Menu_global.o: ../FL/Fl_Menu_.H ../FL/Fl_Widget.H ../FL/Fl_Menu_Item.H -Fl_Menu_global.o: ../FL/Fl_Image.H +Fl_Menu_global.o: ../FL/fl_types.h ../FL/Enumerations.H ../FL/Fl_Menu_.H +Fl_Menu_global.o: ../FL/Fl_Widget.H ../FL/Fl_Menu_Item.H ../FL/Fl_Image.H Fl_Multi_Label.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H -Fl_Multi_Label.o: ../FL/fl_types.h ../FL/Xutf8.h ../FL/Enumerations.H -Fl_Multi_Label.o: ../FL/Fl_Widget.H ../FL/Fl_Menu_Item.H ../FL/Fl_Widget.H -Fl_Multi_Label.o: ../FL/Fl_Image.H ../FL/Fl_Multi_Label.H -Fl_Native_File_Chooser.o: Fl_Native_File_Chooser_FLTK.cxx +Fl_Multi_Label.o: ../FL/fl_types.h ../FL/Enumerations.H ../FL/Fl_Widget.H +Fl_Multi_Label.o: ../FL/Fl_Menu_Item.H ../FL/Fl_Widget.H ../FL/Fl_Image.H +Fl_Multi_Label.o: ../FL/Fl_Multi_Label.H +Fl_Native_File_Chooser.o: Fl_Native_File_Chooser_FLTK.cxx ../config.h Fl_Native_File_Chooser.o: ../FL/Fl_Native_File_Chooser.H Fl_Native_File_Chooser.o: ../FL/Fl_File_Chooser.H ../FL/Fl.H ../FL/fl_utf8.h -Fl_Native_File_Chooser.o: ../FL/Fl_Export.H ../FL/fl_types.h ../FL/Xutf8.h +Fl_Native_File_Chooser.o: ../FL/Fl_Export.H ../FL/fl_types.h Fl_Native_File_Chooser.o: ../FL/Enumerations.H ../FL/Fl_Double_Window.H Fl_Native_File_Chooser.o: ../FL/Fl_Window.H ../FL/Fl_Group.H Fl_Native_File_Chooser.o: ../FL/Fl_Choice.H ../FL/Fl_Menu_.H @@ -312,8 +344,6 @@ Fl_Native_File_Chooser.o: ../FL/Fl_Image.H ../FL/Fl_Menu_Button.H Fl_Native_File_Chooser.o: ../FL/Fl_Button.H ../FL/Fl_Preferences.H Fl_Native_File_Chooser.o: ../FL/Fl_Tile.H ../FL/Fl_Group.H Fl_Native_File_Chooser.o: ../FL/Fl_File_Browser.H ../FL/Fl_Browser.H -Fl_Native_File_Chooser.o: ../FL/Fl_Browser_.H ../FL/Fl_Scrollbar.H -Fl_Native_File_Chooser.o: ../FL/Fl_Slider.H ../FL/Fl_Valuator.H Fl_Native_File_Chooser.o: ../FL/Fl_File_Icon.H ../FL/Fl.H ../FL/filename.H Fl_Native_File_Chooser.o: ../FL/Fl_Box.H ../FL/Fl_Check_Button.H Fl_Native_File_Chooser.o: ../FL/Fl_Light_Button.H ../FL/Fl_Button.H @@ -321,355 +351,381 @@ Fl_Native_File_Chooser.o: ../FL/Fl_File_Input.H ../FL/Fl_Input.H Fl_Native_File_Chooser.o: ../FL/Fl_Input_.H ../FL/Fl_Return_Button.H Fl_Native_File_Chooser.o: ../FL/fl_ask.H ../FL/Fl_File_Icon.H Fl_Native_File_Chooser.o: Fl_Native_File_Chooser_common.cxx -Fl_Native_File_Chooser.o: ../FL/Enumerations.H +Fl_Native_File_Chooser.o: ../FL/Enumerations.H Fl_Native_File_Chooser_GTK.cxx +Fl_Native_File_Chooser.o: ../FL/x.H Fl_Overlay_Window.o: ../config.h ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H -Fl_Overlay_Window.o: ../FL/fl_types.h ../FL/Xutf8.h ../FL/Enumerations.H +Fl_Overlay_Window.o: ../FL/fl_types.h ../FL/Enumerations.H Fl_Overlay_Window.o: ../FL/Fl_Overlay_Window.H ../FL/Fl_Double_Window.H Fl_Overlay_Window.o: ../FL/Fl_Window.H ../FL/fl_draw.H ../FL/x.H Fl_Overlay_Window.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Group.H -Fl_Overlay_Window.o: ../FL/Fl_Widget.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H +Fl_Overlay_Window.o: ../FL/Fl_Widget.H ../FL/Fl_Bitmap.H ../FL/Fl_Image.H +Fl_Overlay_Window.o: ../FL/Fl_Device.H ../FL/Fl_Plugin.H Fl_Overlay_Window.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H -Fl_Overlay_Window.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Pixmap.H -Fl_Overlay_Window.o: ../FL/Fl_RGB_Image.H +Fl_Overlay_Window.o: ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H Fl_Pack.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h -Fl_Pack.o: ../FL/Xutf8.h ../FL/Enumerations.H ../FL/Fl_Pack.H -Fl_Pack.o: ../FL/Fl_Group.H ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H -Fl_Pack.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Group.H -Fl_Pack.o: ../FL/Fl_Widget.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H -Fl_Pack.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H -Fl_Pack.o: ../FL/Fl_Image.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H +Fl_Pack.o: ../FL/Enumerations.H ../FL/Fl_Pack.H ../FL/Fl_Group.H +Fl_Pack.o: ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H ../FL/Enumerations.H +Fl_Pack.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H +Fl_Pack.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Device.H +Fl_Pack.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H +Fl_Pack.o: ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H Fl_Paged_Device.o: ../FL/Fl_Paged_Device.H ../FL/Fl_Device.H ../FL/x.H Fl_Paged_Device.o: ../FL/Enumerations.H ../FL/Fl_Export.H ../FL/fl_types.h -Fl_Paged_Device.o: ../FL/Fl_Window.H ../FL/Xutf8.h ../FL/Fl_Plugin.H -Fl_Paged_Device.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H -Fl_Paged_Device.o: ../FL/Fl_Image.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H -Fl_Paged_Device.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H +Fl_Paged_Device.o: ../FL/Fl_Window.H ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H +Fl_Paged_Device.o: ../FL/Fl_Image.H ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H +Fl_Paged_Device.o: ../FL/Fl_Image.H ../FL/Fl_RGB_Image.H ../FL/Fl_Window.H +Fl_Paged_Device.o: ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Bitmap.H Fl_Paged_Device.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/fl_draw.H Fl_Paged_Device.o: ../FL/Enumerations.H Fl_Pixmap.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h -Fl_Pixmap.o: ../FL/Xutf8.h ../FL/Enumerations.H ../FL/fl_draw.H ../FL/x.H -Fl_Pixmap.o: ../FL/Fl_Window.H ../FL/Enumerations.H ../FL/Fl_Window.H -Fl_Pixmap.o: ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Device.H -Fl_Pixmap.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H -Fl_Pixmap.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Pixmap.H +Fl_Pixmap.o: ../FL/Enumerations.H ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H +Fl_Pixmap.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Group.H +Fl_Pixmap.o: ../FL/Fl_Widget.H ../FL/Fl_Bitmap.H ../FL/Fl_Image.H +Fl_Pixmap.o: ../FL/Fl_Device.H ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H +Fl_Pixmap.o: ../FL/Fl_Image.H ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H Fl_Pixmap.o: ../FL/Fl_RGB_Image.H ../FL/Fl_Widget.H ../FL/Fl_Menu_Item.H Fl_Pixmap.o: ../FL/Fl_Printer.H ../FL/Fl_Paged_Device.H ../FL/Fl_PostScript.H Fl_Pixmap.o: flstring.h ../FL/Fl_Export.H ../config.h +Fl_PostScript.o: ../FL/Fl_Printer.H ../FL/x.H ../FL/Enumerations.H +Fl_PostScript.o: ../FL/Fl_Export.H ../FL/fl_types.h ../FL/Fl_Window.H +Fl_PostScript.o: ../FL/Fl_Paged_Device.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H +Fl_PostScript.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H +Fl_PostScript.o: ../FL/Fl_Pixmap.H ../FL/Fl_Image.H ../FL/Fl_RGB_Image.H +Fl_PostScript.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H +Fl_PostScript.o: ../FL/Fl_Bitmap.H ../FL/fl_draw.H ../FL/Enumerations.H +Fl_PostScript.o: ../FL/Fl_PostScript.H ../config.h ../FL/Fl.H ../FL/fl_utf8.h +Fl_PostScript.o: ../FL/fl_ask.H ../FL/Fl_Native_File_Chooser.H +Fl_PostScript.o: ../FL/Fl_File_Chooser.H ../FL/Fl_Double_Window.H +Fl_PostScript.o: ../FL/Fl_Group.H ../FL/Fl_Choice.H ../FL/Fl_Menu_.H +Fl_PostScript.o: ../FL/Fl_Menu_Item.H ../FL/Fl_Menu_Button.H +Fl_PostScript.o: ../FL/Fl_Button.H ../FL/Fl_Preferences.H ../FL/Fl_Tile.H +Fl_PostScript.o: ../FL/Fl_File_Browser.H ../FL/Fl_Browser.H +Fl_PostScript.o: ../FL/Fl_File_Icon.H ../FL/Fl.H ../FL/filename.H +Fl_PostScript.o: ../FL/Fl_Box.H ../FL/Fl_Check_Button.H +Fl_PostScript.o: ../FL/Fl_Light_Button.H ../FL/Fl_Button.H +Fl_PostScript.o: ../FL/Fl_File_Input.H ../FL/Fl_Input.H ../FL/Fl_Input_.H +Fl_PostScript.o: ../FL/Fl_Return_Button.H Fl_Font.H print_panel.cxx +Fl_PostScript.o: print_panel.h ../FL/Fl_Round_Button.H ../FL/Fl_Spinner.H +Fl_PostScript.o: ../FL/Fl_Repeat_Button.H ../FL/Fl_Progress.H +Fl_PostScript.o: ../src/flstring.h ../FL/Fl_Export.H ../FL/Fl_Int_Input.H +Fl_PostScript.o: ../FL/Fl_Input.H Fl_Positioner.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H -Fl_Positioner.o: ../FL/fl_types.h ../FL/Xutf8.h ../FL/Enumerations.H -Fl_Positioner.o: ../FL/Fl_Positioner.H ../FL/Fl_Widget.H ../FL/fl_draw.H -Fl_Positioner.o: ../FL/x.H ../FL/Fl_Window.H ../FL/Enumerations.H -Fl_Positioner.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Device.H -Fl_Positioner.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H -Fl_Positioner.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Pixmap.H +Fl_Positioner.o: ../FL/fl_types.h ../FL/Enumerations.H ../FL/Fl_Positioner.H +Fl_Positioner.o: ../FL/Fl_Widget.H ../FL/fl_draw.H ../FL/x.H +Fl_Positioner.o: ../FL/Fl_Window.H ../FL/Enumerations.H ../FL/Fl_Window.H +Fl_Positioner.o: ../FL/Fl_Group.H ../FL/Fl_Bitmap.H ../FL/Fl_Image.H +Fl_Positioner.o: ../FL/Fl_Device.H ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H +Fl_Positioner.o: ../FL/Fl_Image.H ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H Fl_Positioner.o: ../FL/Fl_RGB_Image.H Fl_Preferences.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H -Fl_Preferences.o: ../FL/fl_types.h ../FL/Xutf8.h ../FL/Enumerations.H +Fl_Preferences.o: ../FL/fl_types.h ../FL/Enumerations.H Fl_Preferences.o: ../FL/Fl_Preferences.H ../FL/Fl_Plugin.H Fl_Preferences.o: ../FL/Fl_Preferences.H ../FL/filename.H ../FL/fl_utf8.h Fl_Preferences.o: flstring.h ../FL/Fl_Export.H ../config.h Fl_Printer.o: ../FL/Fl_Printer.H ../FL/x.H ../FL/Enumerations.H Fl_Printer.o: ../FL/Fl_Export.H ../FL/fl_types.h ../FL/Fl_Window.H -Fl_Printer.o: ../FL/Xutf8.h ../FL/Fl_Paged_Device.H ../FL/Fl_Device.H -Fl_Printer.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H -Fl_Printer.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Pixmap.H -Fl_Printer.o: ../FL/Fl_RGB_Image.H ../FL/Fl_Window.H ../FL/Fl_Group.H -Fl_Printer.o: ../FL/Fl_Widget.H ../FL/fl_draw.H ../FL/Enumerations.H -Fl_Printer.o: ../FL/Fl_PostScript.H Fl_PostScript.cxx ../config.h ../FL/Fl.H -Fl_Printer.o: ../FL/fl_utf8.h ../FL/fl_ask.H ../FL/Fl_Native_File_Chooser.H -Fl_Printer.o: ../FL/Fl_File_Chooser.H ../FL/Fl_Double_Window.H -Fl_Printer.o: ../FL/Fl_Group.H ../FL/Fl_Choice.H ../FL/Fl_Menu_.H -Fl_Printer.o: ../FL/Fl_Menu_Item.H ../FL/Fl_Menu_Button.H ../FL/Fl_Button.H -Fl_Printer.o: ../FL/Fl_Preferences.H ../FL/Fl_Tile.H ../FL/Fl_File_Browser.H -Fl_Printer.o: ../FL/Fl_Browser.H ../FL/Fl_Browser_.H ../FL/Fl_Scrollbar.H -Fl_Printer.o: ../FL/Fl_Slider.H ../FL/Fl_Valuator.H ../FL/Fl_File_Icon.H -Fl_Printer.o: ../FL/Fl.H ../FL/filename.H ../FL/Fl_Box.H -Fl_Printer.o: ../FL/Fl_Check_Button.H ../FL/Fl_Light_Button.H -Fl_Printer.o: ../FL/Fl_Button.H ../FL/Fl_File_Input.H ../FL/Fl_Input.H -Fl_Printer.o: ../FL/Fl_Input_.H ../FL/Fl_Return_Button.H Fl_Font.H -Fl_Printer.o: print_panel.cxx print_panel.h ../FL/Fl_Round_Button.H -Fl_Printer.o: ../FL/Fl_Spinner.H ../FL/Fl_Repeat_Button.H ../FL/Fl_Progress.H -Fl_Printer.o: ../src/flstring.h ../FL/Fl_Export.H ../FL/Fl_Int_Input.H -Fl_Printer.o: ../FL/Fl_Input.H +Fl_Printer.o: ../FL/Fl_Paged_Device.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H +Fl_Printer.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H +Fl_Printer.o: ../FL/Fl_Pixmap.H ../FL/Fl_Image.H ../FL/Fl_RGB_Image.H +Fl_Printer.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H +Fl_Printer.o: ../FL/Fl_Bitmap.H ../FL/fl_draw.H ../FL/Enumerations.H +Fl_Printer.o: ../FL/Fl_PostScript.H Fl_Progress.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h -Fl_Progress.o: ../FL/Xutf8.h ../FL/Enumerations.H ../FL/Fl_Progress.H -Fl_Progress.o: ../FL/Fl_Widget.H ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H +Fl_Progress.o: ../FL/Enumerations.H ../FL/Fl_Progress.H ../FL/Fl_Widget.H +Fl_Progress.o: ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H Fl_Progress.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Group.H -Fl_Progress.o: ../FL/Fl_Device.H ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H -Fl_Progress.o: ../FL/Fl_Image.H ../FL/Fl_Bitmap.H ../FL/Fl_Image.H -Fl_Progress.o: ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H +Fl_Progress.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Device.H +Fl_Progress.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H +Fl_Progress.o: ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H Fl_Repeat_Button.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H -Fl_Repeat_Button.o: ../FL/fl_types.h ../FL/Xutf8.h ../FL/Enumerations.H +Fl_Repeat_Button.o: ../FL/fl_types.h ../FL/Enumerations.H Fl_Repeat_Button.o: ../FL/Fl_Repeat_Button.H ../FL/Fl.H ../FL/Fl_Button.H -Fl_Repeat_Button.o: ../FL/Fl_Widget.H Fl_Return_Button.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H -Fl_Return_Button.o: ../FL/fl_types.h ../FL/Xutf8.h ../FL/Enumerations.H +Fl_Return_Button.o: ../FL/fl_types.h ../FL/Enumerations.H Fl_Return_Button.o: ../FL/Fl_Return_Button.H ../FL/Fl_Button.H -Fl_Return_Button.o: ../FL/Fl_Widget.H ../FL/fl_draw.H ../FL/x.H -Fl_Return_Button.o: ../FL/Fl_Window.H ../FL/Enumerations.H ../FL/Fl_Window.H -Fl_Return_Button.o: ../FL/Fl_Group.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H +Fl_Return_Button.o: ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H +Fl_Return_Button.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Group.H +Fl_Return_Button.o: ../FL/Fl_Widget.H ../FL/Fl_Bitmap.H ../FL/Fl_Image.H +Fl_Return_Button.o: ../FL/Fl_Device.H ../FL/Fl_Plugin.H Fl_Return_Button.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H -Fl_Return_Button.o: ../FL/Fl_Image.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H +Fl_Return_Button.o: ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H Fl_Roller.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h -Fl_Roller.o: ../FL/Xutf8.h ../FL/Enumerations.H ../FL/Fl_Roller.H -Fl_Roller.o: ../FL/Fl_Valuator.H ../FL/Fl_Widget.H ../FL/fl_draw.H ../FL/x.H -Fl_Roller.o: ../FL/Fl_Window.H ../FL/Enumerations.H ../FL/Fl_Window.H -Fl_Roller.o: ../FL/Fl_Group.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H -Fl_Roller.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H -Fl_Roller.o: ../FL/Fl_Image.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H +Fl_Roller.o: ../FL/Enumerations.H ../FL/Fl_Roller.H ../FL/Fl_Valuator.H +Fl_Roller.o: ../FL/Fl_Widget.H ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H +Fl_Roller.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Group.H +Fl_Roller.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Device.H +Fl_Roller.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H +Fl_Roller.o: ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H Fl_Round_Button.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H -Fl_Round_Button.o: ../FL/fl_types.h ../FL/Xutf8.h ../FL/Enumerations.H +Fl_Round_Button.o: ../FL/fl_types.h ../FL/Enumerations.H Fl_Round_Button.o: ../FL/Fl_Round_Button.H ../FL/Fl_Light_Button.H -Fl_Round_Button.o: ../FL/Fl_Button.H ../FL/Fl_Widget.H +Fl_Round_Button.o: ../FL/Fl_Button.H ../FL/Fl_Radio_Round_Button.H +Fl_Round_Button.o: ../FL/Fl_Round_Button.H Fl_Scroll.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h -Fl_Scroll.o: ../FL/Xutf8.h ../FL/Enumerations.H ../FL/Fl_Tiled_Image.H -Fl_Scroll.o: ../FL/Fl_Image.H ../FL/Fl_Scroll.H ../FL/Fl_Group.H -Fl_Scroll.o: ../FL/Fl_Widget.H ../FL/Fl_Scrollbar.H ../FL/Fl_Slider.H -Fl_Scroll.o: ../FL/Fl_Valuator.H ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H -Fl_Scroll.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Device.H +Fl_Scroll.o: ../FL/Enumerations.H ../FL/Fl_Tiled_Image.H ../FL/Fl_Image.H +Fl_Scroll.o: ../FL/Fl_Scroll.H ../FL/Fl_Group.H ../FL/Fl_Widget.H +Fl_Scroll.o: ../FL/Fl_Scrollbar.H ../FL/Fl_Slider.H ../FL/Fl_Valuator.H +Fl_Scroll.o: ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H ../FL/Enumerations.H +Fl_Scroll.o: ../FL/Fl_Window.H ../FL/Fl_Bitmap.H ../FL/Fl_Device.H Fl_Scroll.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H Fl_Scroll.o: ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H Fl_Scrollbar.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h -Fl_Scrollbar.o: ../FL/Xutf8.h ../FL/Enumerations.H ../FL/Fl_Scrollbar.H -Fl_Scrollbar.o: ../FL/Fl_Slider.H ../FL/Fl_Valuator.H ../FL/Fl_Widget.H -Fl_Scrollbar.o: ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H -Fl_Scrollbar.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Group.H -Fl_Scrollbar.o: ../FL/Fl_Device.H ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H -Fl_Scrollbar.o: ../FL/Fl_Image.H ../FL/Fl_Bitmap.H ../FL/Fl_Image.H +Fl_Scrollbar.o: ../FL/Enumerations.H ../FL/Fl_Scrollbar.H ../FL/Fl_Slider.H +Fl_Scrollbar.o: ../FL/Fl_Valuator.H ../FL/Fl_Widget.H ../FL/fl_draw.H +Fl_Scrollbar.o: ../FL/x.H ../FL/Fl_Window.H ../FL/Enumerations.H +Fl_Scrollbar.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Bitmap.H +Fl_Scrollbar.o: ../FL/Fl_Image.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H +Fl_Scrollbar.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H Fl_Scrollbar.o: ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H flstring.h Fl_Scrollbar.o: ../FL/Fl_Export.H ../config.h Fl_Shared_Image.o: ../FL/fl_utf8.h flstring.h ../FL/Fl_Export.H ../config.h Fl_Shared_Image.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H -Fl_Shared_Image.o: ../FL/fl_types.h ../FL/Xutf8.h ../FL/Enumerations.H +Fl_Shared_Image.o: ../FL/fl_types.h ../FL/Enumerations.H Fl_Shared_Image.o: ../FL/Fl_Shared_Image.H ../FL/Fl_Image.H Fl_Shared_Image.o: ../FL/Fl_XBM_Image.H ../FL/Fl_Bitmap.H Fl_Shared_Image.o: ../FL/Fl_XPM_Image.H ../FL/Fl_Pixmap.H Fl_Single_Window.o: ../FL/Fl_Single_Window.H ../FL/Fl_Window.H Fl_Slider.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h -Fl_Slider.o: ../FL/Xutf8.h ../FL/Enumerations.H ../FL/Fl_Slider.H -Fl_Slider.o: ../FL/Fl_Valuator.H ../FL/Fl_Widget.H ../FL/fl_draw.H ../FL/x.H -Fl_Slider.o: ../FL/Fl_Window.H ../FL/Enumerations.H ../FL/Fl_Window.H -Fl_Slider.o: ../FL/Fl_Group.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H +Fl_Slider.o: ../FL/Enumerations.H ../FL/Fl_Slider.H ../FL/Fl_Valuator.H +Fl_Slider.o: ../FL/Fl_Widget.H ../FL/Fl_Fill_Slider.H ../FL/Fl_Slider.H +Fl_Slider.o: ../FL/Fl_Hor_Slider.H ../FL/Fl_Hor_Fill_Slider.H +Fl_Slider.o: ../FL/Fl_Hor_Nice_Slider.H ../FL/Fl_Nice_Slider.H +Fl_Slider.o: ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H ../FL/Enumerations.H +Fl_Slider.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Bitmap.H +Fl_Slider.o: ../FL/Fl_Image.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H Fl_Slider.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H -Fl_Slider.o: ../FL/Fl_Image.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H -Fl_Slider.o: flstring.h ../FL/Fl_Export.H ../config.h +Fl_Slider.o: ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H flstring.h +Fl_Slider.o: ../FL/Fl_Export.H ../config.h Fl_Table.o: ../FL/fl_draw.H ../FL/x.H ../FL/Enumerations.H ../FL/Fl_Export.H -Fl_Table.o: ../FL/fl_types.h ../FL/Fl_Window.H ../FL/Xutf8.h -Fl_Table.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Group.H -Fl_Table.o: ../FL/Fl_Widget.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H -Fl_Table.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H -Fl_Table.o: ../FL/Fl_Image.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H +Fl_Table.o: ../FL/fl_types.h ../FL/Fl_Window.H ../FL/Enumerations.H +Fl_Table.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H +Fl_Table.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Device.H +Fl_Table.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H +Fl_Table.o: ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H Fl_Table.o: ../FL/Fl_Table.H ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Group.H Fl_Table.o: ../FL/Fl_Scroll.H ../FL/Fl_Scrollbar.H ../FL/Fl_Slider.H Fl_Table.o: ../FL/Fl_Valuator.H ../FL/Fl_Box.H ../FL/Fl_Scrollbar.H Fl_Table_Row.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h -Fl_Table_Row.o: ../FL/Xutf8.h ../FL/Enumerations.H ../FL/fl_draw.H ../FL/x.H +Fl_Table_Row.o: ../FL/Enumerations.H ../FL/fl_draw.H ../FL/x.H Fl_Table_Row.o: ../FL/Fl_Window.H ../FL/Enumerations.H ../FL/Fl_Window.H -Fl_Table_Row.o: ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Device.H -Fl_Table_Row.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H -Fl_Table_Row.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Pixmap.H -Fl_Table_Row.o: ../FL/Fl_RGB_Image.H ../FL/Fl_Table_Row.H ../FL/Fl_Table.H -Fl_Table_Row.o: ../FL/Fl_Group.H ../FL/Fl_Scroll.H ../FL/Fl_Scrollbar.H -Fl_Table_Row.o: ../FL/Fl_Slider.H ../FL/Fl_Valuator.H ../FL/Fl_Box.H -Fl_Table_Row.o: ../FL/Fl_Scrollbar.H +Fl_Table_Row.o: ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Bitmap.H +Fl_Table_Row.o: ../FL/Fl_Image.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H +Fl_Table_Row.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H +Fl_Table_Row.o: ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H ../FL/Fl_Table_Row.H +Fl_Table_Row.o: ../FL/Fl_Table.H ../FL/Fl_Group.H ../FL/Fl_Scroll.H +Fl_Table_Row.o: ../FL/Fl_Scrollbar.H ../FL/Fl_Slider.H ../FL/Fl_Valuator.H +Fl_Table_Row.o: ../FL/Fl_Box.H ../FL/Fl_Scrollbar.H Fl_Tabs.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h -Fl_Tabs.o: ../FL/Xutf8.h ../FL/Enumerations.H ../FL/Fl_Tabs.H -Fl_Tabs.o: ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/fl_draw.H ../FL/x.H -Fl_Tabs.o: ../FL/Fl_Window.H ../FL/Enumerations.H ../FL/Fl_Window.H -Fl_Tabs.o: ../FL/Fl_Device.H ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H -Fl_Tabs.o: ../FL/Fl_Image.H ../FL/Fl_Bitmap.H ../FL/Fl_Image.H +Fl_Tabs.o: ../FL/Enumerations.H ../FL/Fl_Tabs.H ../FL/Fl_Group.H +Fl_Tabs.o: ../FL/Fl_Widget.H ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H +Fl_Tabs.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Bitmap.H +Fl_Tabs.o: ../FL/Fl_Image.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H +Fl_Tabs.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H Fl_Tabs.o: ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H ../FL/Fl_Tooltip.H Fl_Tabs.o: ../FL/Fl_Widget.H Fl_Text_Buffer.o: ../FL/fl_utf8.h flstring.h ../FL/Fl_Export.H ../config.h Fl_Text_Buffer.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H -Fl_Text_Buffer.o: ../FL/fl_types.h ../FL/Xutf8.h ../FL/Enumerations.H +Fl_Text_Buffer.o: ../FL/fl_types.h ../FL/Enumerations.H Fl_Text_Buffer.o: ../FL/Fl_Text_Buffer.H ../FL/fl_ask.H Fl_Text_Display.o: ../FL/fl_utf8.h flstring.h ../FL/Fl_Export.H ../config.h Fl_Text_Display.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H -Fl_Text_Display.o: ../FL/fl_types.h ../FL/Xutf8.h ../FL/Enumerations.H +Fl_Text_Display.o: ../FL/fl_types.h ../FL/Enumerations.H Fl_Text_Display.o: ../FL/Fl_Text_Buffer.H ../FL/Fl_Text_Display.H Fl_Text_Display.o: ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H Fl_Text_Display.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Group.H -Fl_Text_Display.o: ../FL/Fl_Widget.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H -Fl_Text_Display.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H -Fl_Text_Display.o: ../FL/Fl_Image.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H -Fl_Text_Display.o: ../FL/Fl_Scrollbar.H ../FL/Fl_Slider.H ../FL/Fl_Valuator.H +Fl_Text_Display.o: ../FL/Fl_Widget.H ../FL/Fl_Bitmap.H ../FL/Fl_Image.H +Fl_Text_Display.o: ../FL/Fl_Device.H ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H +Fl_Text_Display.o: ../FL/Fl_Image.H ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H +Fl_Text_Display.o: ../FL/Fl_RGB_Image.H ../FL/Fl_Scrollbar.H +Fl_Text_Display.o: ../FL/Fl_Slider.H ../FL/Fl_Valuator.H Fl_Text_Display.o: ../FL/Fl_Text_Buffer.H ../FL/Fl_Printer.H Fl_Text_Display.o: ../FL/Fl_Paged_Device.H ../FL/fl_draw.H Fl_Text_Display.o: ../FL/Fl_PostScript.H Fl_Text_Editor.o: flstring.h ../FL/Fl_Export.H ../config.h ../FL/Fl.H Fl_Text_Editor.o: ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h -Fl_Text_Editor.o: ../FL/Xutf8.h ../FL/Enumerations.H ../FL/Fl_Window.H -Fl_Text_Editor.o: ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Text_Editor.H -Fl_Text_Editor.o: ../FL/Fl_Text_Display.H ../FL/fl_draw.H ../FL/x.H -Fl_Text_Editor.o: ../FL/Fl_Window.H ../FL/Enumerations.H ../FL/Fl_Device.H -Fl_Text_Editor.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H -Fl_Text_Editor.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Pixmap.H -Fl_Text_Editor.o: ../FL/Fl_RGB_Image.H ../FL/Fl_Scrollbar.H ../FL/Fl_Slider.H -Fl_Text_Editor.o: ../FL/Fl_Valuator.H ../FL/Fl_Text_Buffer.H ../FL/fl_ask.H +Fl_Text_Editor.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Group.H +Fl_Text_Editor.o: ../FL/Fl_Widget.H ../FL/Fl_Bitmap.H ../FL/Fl_Image.H +Fl_Text_Editor.o: ../FL/Fl_Text_Editor.H ../FL/Fl_Text_Display.H +Fl_Text_Editor.o: ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H +Fl_Text_Editor.o: ../FL/Enumerations.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H +Fl_Text_Editor.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H +Fl_Text_Editor.o: ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H ../FL/Fl_Scrollbar.H +Fl_Text_Editor.o: ../FL/Fl_Slider.H ../FL/Fl_Valuator.H +Fl_Text_Editor.o: ../FL/Fl_Text_Buffer.H ../FL/fl_ask.H Fl_Tile.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h -Fl_Tile.o: ../FL/Xutf8.h ../FL/Enumerations.H ../FL/Fl_Tile.H -Fl_Tile.o: ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Window.H +Fl_Tile.o: ../FL/Enumerations.H ../FL/Fl_Tile.H ../FL/Fl_Group.H +Fl_Tile.o: ../FL/Fl_Widget.H ../FL/Fl_Window.H ../FL/Fl_Bitmap.H +Fl_Tile.o: ../FL/Fl_Image.H Fl_Tiled_Image.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H -Fl_Tiled_Image.o: ../FL/fl_types.h ../FL/Xutf8.h ../FL/Enumerations.H -Fl_Tiled_Image.o: ../FL/Fl_Tiled_Image.H ../FL/Fl_Image.H ../FL/fl_draw.H -Fl_Tiled_Image.o: ../FL/x.H ../FL/Fl_Window.H ../FL/Enumerations.H -Fl_Tiled_Image.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H -Fl_Tiled_Image.o: ../FL/Fl_Device.H ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H -Fl_Tiled_Image.o: ../FL/Fl_Image.H ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H -Fl_Tiled_Image.o: ../FL/Fl_RGB_Image.H +Fl_Tiled_Image.o: ../FL/fl_types.h ../FL/Enumerations.H +Fl_Tiled_Image.o: ../FL/Fl_Tiled_Image.H ../FL/Fl_Image.H ../FL/Fl_Window.H +Fl_Tiled_Image.o: ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Bitmap.H +Fl_Tiled_Image.o: ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H +Fl_Tiled_Image.o: ../FL/Enumerations.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H +Fl_Tiled_Image.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H +Fl_Tiled_Image.o: ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H Fl_Tree.o: ../FL/Fl_Tree.H ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H -Fl_Tree.o: ../FL/fl_types.h ../FL/Xutf8.h ../FL/Enumerations.H -Fl_Tree.o: ../FL/Fl_Group.H ../FL/Fl_Scrollbar.H ../FL/Fl_Slider.H -Fl_Tree.o: ../FL/Fl_Valuator.H ../FL/Fl_Widget.H ../FL/fl_draw.H ../FL/x.H -Fl_Tree.o: ../FL/Fl_Window.H ../FL/Enumerations.H ../FL/Fl_Window.H -Fl_Tree.o: ../FL/Fl_Group.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H -Fl_Tree.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H -Fl_Tree.o: ../FL/Fl_Image.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H +Fl_Tree.o: ../FL/fl_types.h ../FL/Enumerations.H ../FL/Fl_Group.H +Fl_Tree.o: ../FL/Fl_Scrollbar.H ../FL/Fl_Slider.H ../FL/Fl_Valuator.H +Fl_Tree.o: ../FL/Fl_Widget.H ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H +Fl_Tree.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Group.H +Fl_Tree.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Device.H +Fl_Tree.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H +Fl_Tree.o: ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H Fl_Tree.o: ../FL/Fl_Tree_Item.H ../FL/Fl_Widget.H ../FL/Fl_Tree_Item_Array.H Fl_Tree.o: ../FL/Fl_Tree_Prefs.H ../FL/Fl_Preferences.H Fl_Tree_Item.o: ../FL/Fl_Widget.H ../FL/Fl_Tree_Item.H ../FL/Fl.H Fl_Tree_Item.o: ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h -Fl_Tree_Item.o: ../FL/Xutf8.h ../FL/Enumerations.H ../FL/Fl_Image.H -Fl_Tree_Item.o: ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H -Fl_Tree_Item.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Group.H -Fl_Tree_Item.o: ../FL/Fl_Widget.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H -Fl_Tree_Item.o: ../FL/Fl_Preferences.H ../FL/Fl_Bitmap.H ../FL/Fl_Image.H +Fl_Tree_Item.o: ../FL/Enumerations.H ../FL/Fl_Image.H ../FL/fl_draw.H +Fl_Tree_Item.o: ../FL/x.H ../FL/Fl_Window.H ../FL/Enumerations.H +Fl_Tree_Item.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H +Fl_Tree_Item.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Device.H +Fl_Tree_Item.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Bitmap.H Fl_Tree_Item.o: ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H Fl_Tree_Item.o: ../FL/Fl_Tree_Item_Array.H ../FL/Fl_Tree_Prefs.H -Fl_Tree_Item_Array.o: ../FL/Fl_Tree_Item_Array.H ../FL/Fl_Export.H -Fl_Tree_Item_Array.o: ../FL/Fl_Tree_Item.H ../FL/Fl.H ../FL/fl_utf8.h -Fl_Tree_Item_Array.o: ../FL/fl_types.h ../FL/Xutf8.h ../FL/Enumerations.H -Fl_Tree_Item_Array.o: ../FL/Fl_Widget.H ../FL/Fl_Image.H ../FL/fl_draw.H -Fl_Tree_Item_Array.o: ../FL/x.H ../FL/Fl_Window.H ../FL/Enumerations.H -Fl_Tree_Item_Array.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H +Fl_Tree_Item.o: ../FL/Fl_Tree.H ../FL/Fl_Group.H ../FL/Fl_Scrollbar.H +Fl_Tree_Item.o: ../FL/Fl_Slider.H ../FL/Fl_Valuator.H +Fl_Tree_Item_Array.o: ../FL/Fl_Tree_Item_Array.H ../FL/Fl.H ../FL/fl_utf8.h +Fl_Tree_Item_Array.o: ../FL/Fl_Export.H ../FL/fl_types.h ../FL/Enumerations.H +Fl_Tree_Item_Array.o: ../FL/Fl_Tree_Item.H ../FL/Fl_Widget.H ../FL/Fl_Image.H +Fl_Tree_Item_Array.o: ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H +Fl_Tree_Item_Array.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Group.H +Fl_Tree_Item_Array.o: ../FL/Fl_Widget.H ../FL/Fl_Bitmap.H ../FL/Fl_Image.H Fl_Tree_Item_Array.o: ../FL/Fl_Device.H ../FL/Fl_Plugin.H Fl_Tree_Item_Array.o: ../FL/Fl_Preferences.H ../FL/Fl_Bitmap.H -Fl_Tree_Item_Array.o: ../FL/Fl_Image.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H +Fl_Tree_Item_Array.o: ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H Fl_Tree_Item_Array.o: ../FL/Fl_Tree_Prefs.H Fl_Tree_Prefs.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H -Fl_Tree_Prefs.o: ../FL/fl_types.h ../FL/Xutf8.h ../FL/Enumerations.H -Fl_Tree_Prefs.o: ../FL/Fl_Pixmap.H ../FL/Fl_Image.H ../FL/Fl_Tree_Prefs.H +Fl_Tree_Prefs.o: ../FL/fl_types.h ../FL/Enumerations.H ../FL/Fl_Pixmap.H +Fl_Tree_Prefs.o: ../FL/Fl_Image.H ../FL/Fl_Tree_Prefs.H Fl_Tooltip.o: ../FL/Fl_Tooltip.H ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H -Fl_Tooltip.o: ../FL/fl_types.h ../FL/Xutf8.h ../FL/Enumerations.H -Fl_Tooltip.o: ../FL/Fl_Widget.H ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H +Fl_Tooltip.o: ../FL/fl_types.h ../FL/Enumerations.H ../FL/Fl_Widget.H +Fl_Tooltip.o: ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H Fl_Tooltip.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Group.H -Fl_Tooltip.o: ../FL/Fl_Widget.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H -Fl_Tooltip.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H -Fl_Tooltip.o: ../FL/Fl_Image.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H -Fl_Tooltip.o: ../FL/Fl_Menu_Window.H ../FL/Fl_Single_Window.H +Fl_Tooltip.o: ../FL/Fl_Widget.H ../FL/Fl_Bitmap.H ../FL/Fl_Image.H +Fl_Tooltip.o: ../FL/Fl_Device.H ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H +Fl_Tooltip.o: ../FL/Fl_Image.H ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H +Fl_Tooltip.o: ../FL/Fl_RGB_Image.H ../FL/Fl_Menu_Window.H +Fl_Tooltip.o: ../FL/Fl_Single_Window.H Fl_Valuator.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h -Fl_Valuator.o: ../FL/Xutf8.h ../FL/Enumerations.H ../FL/Fl_Valuator.H -Fl_Valuator.o: ../FL/Fl_Widget.H ../FL/math.h flstring.h ../FL/Fl_Export.H -Fl_Valuator.o: ../config.h +Fl_Valuator.o: ../FL/Enumerations.H ../FL/Fl_Valuator.H ../FL/Fl_Widget.H +Fl_Valuator.o: ../FL/math.h flstring.h ../FL/Fl_Export.H ../config.h Fl_Value_Input.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H -Fl_Value_Input.o: ../FL/fl_types.h ../FL/Xutf8.h ../FL/Enumerations.H +Fl_Value_Input.o: ../FL/fl_types.h ../FL/Enumerations.H Fl_Value_Input.o: ../FL/Fl_Value_Input.H ../FL/Fl_Valuator.H Fl_Value_Input.o: ../FL/Fl_Widget.H ../FL/Fl_Input.H ../FL/Fl_Input_.H Fl_Value_Input.o: ../FL/Fl_Group.H ../FL/math.h Fl_Value_Output.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H -Fl_Value_Output.o: ../FL/fl_types.h ../FL/Xutf8.h ../FL/Enumerations.H +Fl_Value_Output.o: ../FL/fl_types.h ../FL/Enumerations.H Fl_Value_Output.o: ../FL/Fl_Value_Output.H ../FL/Fl_Valuator.H Fl_Value_Output.o: ../FL/Fl_Widget.H ../FL/fl_draw.H ../FL/x.H Fl_Value_Output.o: ../FL/Fl_Window.H ../FL/Enumerations.H ../FL/Fl_Window.H -Fl_Value_Output.o: ../FL/Fl_Group.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H -Fl_Value_Output.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H -Fl_Value_Output.o: ../FL/Fl_Image.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H +Fl_Value_Output.o: ../FL/Fl_Group.H ../FL/Fl_Bitmap.H ../FL/Fl_Image.H +Fl_Value_Output.o: ../FL/Fl_Device.H ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H +Fl_Value_Output.o: ../FL/Fl_Image.H ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H +Fl_Value_Output.o: ../FL/Fl_RGB_Image.H Fl_Value_Slider.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H -Fl_Value_Slider.o: ../FL/fl_types.h ../FL/Xutf8.h ../FL/Enumerations.H +Fl_Value_Slider.o: ../FL/fl_types.h ../FL/Enumerations.H Fl_Value_Slider.o: ../FL/Fl_Value_Slider.H ../FL/Fl_Slider.H -Fl_Value_Slider.o: ../FL/Fl_Valuator.H ../FL/Fl_Widget.H ../FL/fl_draw.H -Fl_Value_Slider.o: ../FL/x.H ../FL/Fl_Window.H ../FL/Enumerations.H -Fl_Value_Slider.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Device.H +Fl_Value_Slider.o: ../FL/Fl_Valuator.H ../FL/Fl_Widget.H +Fl_Value_Slider.o: ../FL/Fl_Hor_Value_Slider.H ../FL/Fl_Value_Slider.H +Fl_Value_Slider.o: ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H +Fl_Value_Slider.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Group.H +Fl_Value_Slider.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Device.H Fl_Value_Slider.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H -Fl_Value_Slider.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Pixmap.H -Fl_Value_Slider.o: ../FL/Fl_RGB_Image.H +Fl_Value_Slider.o: ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H Fl_Widget.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h -Fl_Widget.o: ../FL/Xutf8.h ../FL/Enumerations.H ../FL/Fl_Widget.H -Fl_Widget.o: ../FL/Fl_Group.H ../FL/Fl_Tooltip.H ../FL/fl_draw.H ../FL/x.H -Fl_Widget.o: ../FL/Fl_Window.H ../FL/Enumerations.H ../FL/Fl_Window.H -Fl_Widget.o: ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Device.H -Fl_Widget.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H -Fl_Widget.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Pixmap.H +Fl_Widget.o: ../FL/Enumerations.H ../FL/Fl_Widget.H ../FL/Fl_Group.H +Fl_Widget.o: ../FL/Fl_Tooltip.H ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H +Fl_Widget.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Group.H +Fl_Widget.o: ../FL/Fl_Widget.H ../FL/Fl_Bitmap.H ../FL/Fl_Image.H +Fl_Widget.o: ../FL/Fl_Device.H ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H +Fl_Widget.o: ../FL/Fl_Image.H ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H Fl_Widget.o: ../FL/Fl_RGB_Image.H flstring.h ../FL/Fl_Export.H ../config.h Fl_Window.o: ../config.h ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H -Fl_Window.o: ../FL/fl_types.h ../FL/Xutf8.h ../FL/Enumerations.H ../FL/x.H -Fl_Window.o: ../FL/Fl_Window.H ../FL/Fl_Window.H ../FL/Fl_Group.H -Fl_Window.o: ../FL/Fl_Widget.H flstring.h ../FL/Fl_Export.H +Fl_Window.o: ../FL/fl_types.h ../FL/Enumerations.H ../FL/x.H +Fl_Window.o: ../FL/Fl_Window.H ../FL/Fl_RGB_Image.H ../FL/Fl_Image.H +Fl_Window.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H +Fl_Window.o: ../FL/Fl_Bitmap.H flstring.h ../FL/Fl_Export.H Fl_Window_fullscreen.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H -Fl_Window_fullscreen.o: ../FL/fl_types.h ../FL/Xutf8.h ../FL/Enumerations.H -Fl_Window_fullscreen.o: ../FL/x.H ../FL/Fl_Window.H ../config.h +Fl_Window_fullscreen.o: ../FL/fl_types.h ../FL/Enumerations.H ../FL/x.H +Fl_Window_fullscreen.o: ../FL/Fl_Window.H ../config.h Fl_Window_hotspot.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H -Fl_Window_hotspot.o: ../FL/fl_types.h ../FL/Xutf8.h ../FL/Enumerations.H -Fl_Window_hotspot.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H -Fl_Window_hotspot.o: ../FL/x.H ../FL/Fl_Window.H +Fl_Window_hotspot.o: ../FL/fl_types.h ../FL/Enumerations.H ../FL/Fl_Window.H +Fl_Window_hotspot.o: ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Bitmap.H +Fl_Window_hotspot.o: ../FL/Fl_Image.H ../FL/x.H ../FL/Fl_Window.H Fl_Window_iconize.o: ../FL/x.H ../FL/Enumerations.H ../FL/Fl_Export.H -Fl_Window_iconize.o: ../FL/fl_types.h ../FL/Fl_Window.H ../FL/Xutf8.h +Fl_Window_iconize.o: ../FL/fl_types.h ../FL/Fl_Window.H +Fl_Window_shape.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H +Fl_Window_shape.o: ../FL/fl_types.h ../FL/Enumerations.H ../FL/fl_draw.H +Fl_Window_shape.o: ../FL/x.H ../FL/Fl_Window.H ../FL/Enumerations.H +Fl_Window_shape.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H +Fl_Window_shape.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Device.H +Fl_Window_shape.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H +Fl_Window_shape.o: ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H +Fl_Window_shape.o: ../config.h Fl_Wizard.o: ../FL/Fl_Wizard.H ../FL/Fl_Group.H ../FL/Fl_Window.H Fl_Wizard.o: ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Enumerations.H -Fl_Wizard.o: ../FL/Fl_Export.H ../FL/fl_types.h ../FL/fl_draw.H ../FL/x.H -Fl_Wizard.o: ../FL/Fl_Window.H ../FL/Xutf8.h ../FL/Enumerations.H -Fl_Wizard.o: ../FL/Fl_Device.H ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H -Fl_Wizard.o: ../FL/Fl_Image.H ../FL/Fl_Bitmap.H ../FL/Fl_Image.H +Fl_Wizard.o: ../FL/Fl_Export.H ../FL/fl_types.h ../FL/Fl_Bitmap.H +Fl_Wizard.o: ../FL/Fl_Image.H ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H +Fl_Wizard.o: ../FL/Enumerations.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H +Fl_Wizard.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H Fl_Wizard.o: ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H Fl_XBM_Image.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h -Fl_XBM_Image.o: ../FL/Xutf8.h ../FL/Enumerations.H ../FL/Fl_XBM_Image.H -Fl_XBM_Image.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/fl_utf8.h flstring.h -Fl_XBM_Image.o: ../FL/Fl_Export.H ../config.h +Fl_XBM_Image.o: ../FL/Enumerations.H ../FL/Fl_XBM_Image.H ../FL/Fl_Bitmap.H +Fl_XBM_Image.o: ../FL/Fl_Image.H ../FL/fl_utf8.h flstring.h ../FL/Fl_Export.H +Fl_XBM_Image.o: ../config.h Fl_XPM_Image.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h -Fl_XPM_Image.o: ../FL/Xutf8.h ../FL/Enumerations.H ../FL/Fl_XPM_Image.H -Fl_XPM_Image.o: ../FL/Fl_Pixmap.H ../FL/Fl_Image.H ../FL/fl_utf8.h flstring.h -Fl_XPM_Image.o: ../FL/Fl_Export.H ../config.h +Fl_XPM_Image.o: ../FL/Enumerations.H ../FL/Fl_XPM_Image.H ../FL/Fl_Pixmap.H +Fl_XPM_Image.o: ../FL/Fl_Image.H ../FL/fl_utf8.h flstring.h ../FL/Fl_Export.H +Fl_XPM_Image.o: ../config.h Fl_abort.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h -Fl_abort.o: ../FL/Xutf8.h ../FL/Enumerations.H flstring.h ../FL/Fl_Export.H -Fl_abort.o: ../config.h +Fl_abort.o: ../FL/Enumerations.H flstring.h ../FL/Fl_Export.H ../config.h Fl_add_idle.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h -Fl_add_idle.o: ../FL/Xutf8.h ../FL/Enumerations.H +Fl_add_idle.o: ../FL/Enumerations.H Fl_arg.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h -Fl_arg.o: ../FL/Xutf8.h ../FL/Enumerations.H ../FL/x.H ../FL/Fl_Window.H -Fl_arg.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H -Fl_arg.o: ../FL/Fl_Tooltip.H ../FL/Fl_Widget.H ../FL/filename.H -Fl_arg.o: ../FL/fl_draw.H ../FL/Enumerations.H ../FL/Fl_Device.H -Fl_arg.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H -Fl_arg.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Pixmap.H +Fl_arg.o: ../FL/Enumerations.H ../FL/x.H ../FL/Fl_Window.H ../FL/Fl_Window.H +Fl_arg.o: ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Bitmap.H +Fl_arg.o: ../FL/Fl_Image.H ../FL/Fl_Tooltip.H ../FL/Fl_Widget.H +Fl_arg.o: ../FL/filename.H ../FL/fl_draw.H ../FL/Enumerations.H +Fl_arg.o: ../FL/Fl_Device.H ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H +Fl_arg.o: ../FL/Fl_Image.H ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H Fl_arg.o: ../FL/Fl_RGB_Image.H flstring.h ../FL/Fl_Export.H ../config.h Fl_compose.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h -Fl_compose.o: ../FL/Xutf8.h ../FL/Enumerations.H ../FL/x.H ../FL/Fl_Window.H +Fl_compose.o: ../FL/Enumerations.H ../FL/x.H ../FL/Fl_Window.H Fl_display.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h -Fl_display.o: ../FL/Xutf8.h ../FL/Enumerations.H flstring.h ../FL/Fl_Export.H -Fl_display.o: ../config.h +Fl_display.o: ../FL/Enumerations.H flstring.h ../FL/Fl_Export.H ../config.h Fl_get_key.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h -Fl_get_key.o: ../FL/Xutf8.h ../FL/Enumerations.H ../FL/x.H ../FL/Fl_Window.H +Fl_get_key.o: ../FL/Enumerations.H ../FL/x.H ../FL/Fl_Window.H Fl_get_system_colors.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H -Fl_get_system_colors.o: ../FL/fl_types.h ../FL/Xutf8.h ../FL/Enumerations.H -Fl_get_system_colors.o: ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H -Fl_get_system_colors.o: ../FL/Enumerations.H ../FL/Fl_Window.H -Fl_get_system_colors.o: ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Device.H +Fl_get_system_colors.o: ../FL/fl_types.h ../FL/Enumerations.H ../FL/fl_draw.H +Fl_get_system_colors.o: ../FL/x.H ../FL/Fl_Window.H ../FL/Enumerations.H +Fl_get_system_colors.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H +Fl_get_system_colors.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Device.H Fl_get_system_colors.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H -Fl_get_system_colors.o: ../FL/Fl_Image.H ../FL/Fl_Bitmap.H ../FL/Fl_Image.H -Fl_get_system_colors.o: ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H ../FL/math.h -Fl_get_system_colors.o: ../FL/fl_utf8.h flstring.h ../FL/Fl_Export.H -Fl_get_system_colors.o: ../config.h ../FL/Fl_Tiled_Image.H tile.xpm +Fl_get_system_colors.o: ../FL/Fl_Image.H ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H +Fl_get_system_colors.o: ../FL/Fl_RGB_Image.H ../FL/math.h ../FL/fl_utf8.h +Fl_get_system_colors.o: flstring.h ../FL/Fl_Export.H ../config.h +Fl_get_system_colors.o: ../FL/Fl_Tiled_Image.H tile.xpm Fl_grab.o: ../config.h ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H -Fl_grab.o: ../FL/fl_types.h ../FL/Xutf8.h ../FL/Enumerations.H ../FL/x.H -Fl_grab.o: ../FL/Fl_Window.H +Fl_grab.o: ../FL/fl_types.h ../FL/Enumerations.H ../FL/x.H ../FL/Fl_Window.H Fl_lock.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h -Fl_lock.o: ../FL/Xutf8.h ../FL/Enumerations.H ../config.h +Fl_lock.o: ../FL/Enumerations.H ../config.h Fl_own_colormap.o: ../config.h ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H -Fl_own_colormap.o: ../FL/fl_types.h ../FL/Xutf8.h ../FL/Enumerations.H -Fl_own_colormap.o: ../FL/x.H ../FL/Fl_Window.H +Fl_own_colormap.o: ../FL/fl_types.h ../FL/Enumerations.H ../FL/x.H +Fl_own_colormap.o: ../FL/Fl_Window.H Fl_visual.o: ../config.h ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H -Fl_visual.o: ../FL/fl_types.h ../FL/Xutf8.h ../FL/Enumerations.H ../FL/x.H +Fl_visual.o: ../FL/fl_types.h ../FL/Enumerations.H ../FL/x.H Fl_visual.o: ../FL/Fl_Window.H Fl_x.o: ../config.h ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H -Fl_x.o: ../FL/fl_types.h ../FL/Xutf8.h ../FL/Enumerations.H ../FL/x.H -Fl_x.o: ../FL/Fl_Window.H ../FL/Fl_Window.H ../FL/Fl_Group.H -Fl_x.o: ../FL/Fl_Widget.H ../FL/fl_utf8.h ../FL/Fl_Tooltip.H +Fl_x.o: ../FL/fl_types.h ../FL/Enumerations.H ../FL/x.H ../FL/Fl_Window.H +Fl_x.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H +Fl_x.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/fl_utf8.h ../FL/Fl_Tooltip.H Fl_x.o: ../FL/Fl_Widget.H ../FL/fl_draw.H ../FL/Enumerations.H Fl_x.o: ../FL/Fl_Device.H ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H -Fl_x.o: ../FL/Fl_Image.H ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Pixmap.H -Fl_x.o: ../FL/Fl_RGB_Image.H ../FL/Fl_Paged_Device.H flstring.h -Fl_x.o: ../FL/Fl_Export.H +Fl_x.o: ../FL/Fl_Image.H ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H +Fl_x.o: ../FL/Fl_RGB_Image.H ../FL/Fl_Paged_Device.H ../FL/Fl_Shared_Image.H +Fl_x.o: ../FL/fl_ask.H ../FL/filename.H flstring.h ../FL/Fl_Export.H Xutf8.h filename_absolute.o: ../FL/filename.H ../FL/fl_utf8.h flstring.h filename_absolute.o: ../FL/Fl_Export.H ../config.h filename_expand.o: ../FL/filename.H ../FL/fl_utf8.h flstring.h @@ -682,305 +738,313 @@ filename_list.o: ../FL/Fl_Export.H ../config.h filename_match.o: ../FL/filename.H filename_setext.o: ../FL/filename.H flstring.h ../FL/Fl_Export.H ../config.h fl_arc.o: ../FL/fl_draw.H ../FL/x.H ../FL/Enumerations.H ../FL/Fl_Export.H -fl_arc.o: ../FL/fl_types.h ../FL/Fl_Window.H ../FL/Xutf8.h -fl_arc.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Group.H -fl_arc.o: ../FL/Fl_Widget.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H -fl_arc.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H -fl_arc.o: ../FL/Fl_Image.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H +fl_arc.o: ../FL/fl_types.h ../FL/Fl_Window.H ../FL/Enumerations.H +fl_arc.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H +fl_arc.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Device.H +fl_arc.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H +fl_arc.o: ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H fl_arc.o: ../FL/math.h fl_arci.o: ../FL/fl_draw.H ../FL/x.H ../FL/Enumerations.H ../FL/Fl_Export.H -fl_arci.o: ../FL/fl_types.h ../FL/Fl_Window.H ../FL/Xutf8.h -fl_arci.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Group.H -fl_arci.o: ../FL/Fl_Widget.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H -fl_arci.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H -fl_arci.o: ../FL/Fl_Image.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H +fl_arci.o: ../FL/fl_types.h ../FL/Fl_Window.H ../FL/Enumerations.H +fl_arci.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H +fl_arci.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Device.H +fl_arci.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H +fl_arci.o: ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H fl_arci.o: ../config.h fl_ask.o: flstring.h ../FL/Fl_Export.H ../config.h ../FL/Fl.H ../FL/fl_utf8.h -fl_ask.o: ../FL/Fl_Export.H ../FL/fl_types.h ../FL/Xutf8.h -fl_ask.o: ../FL/Enumerations.H ../FL/fl_ask.H ../FL/Fl_Box.H -fl_ask.o: ../FL/Fl_Widget.H ../FL/Fl_Button.H ../FL/Fl_Return_Button.H -fl_ask.o: ../FL/Fl_Button.H ../FL/Fl_Window.H ../FL/Fl_Group.H +fl_ask.o: ../FL/Fl_Export.H ../FL/fl_types.h ../FL/Enumerations.H +fl_ask.o: ../FL/fl_ask.H ../FL/Fl_Box.H ../FL/Fl_Widget.H ../FL/Fl_Button.H +fl_ask.o: ../FL/Fl_Return_Button.H ../FL/Fl_Button.H ../FL/Fl_Window.H +fl_ask.o: ../FL/Fl_Group.H ../FL/Fl_Bitmap.H ../FL/Fl_Image.H fl_ask.o: ../FL/Fl_Input.H ../FL/Fl_Input_.H ../FL/Fl_Secret_Input.H fl_ask.o: ../FL/Fl_Input.H ../FL/x.H ../FL/Fl_Window.H ../FL/fl_draw.H fl_ask.o: ../FL/Enumerations.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H fl_ask.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H -fl_ask.o: ../FL/Fl_Image.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H +fl_ask.o: ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H fl_boxtype.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h -fl_boxtype.o: ../FL/Xutf8.h ../FL/Enumerations.H ../FL/Fl_Widget.H -fl_boxtype.o: ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H -fl_boxtype.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Group.H -fl_boxtype.o: ../FL/Fl_Widget.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H -fl_boxtype.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H -fl_boxtype.o: ../FL/Fl_Image.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H +fl_boxtype.o: ../FL/Enumerations.H ../FL/Fl_Widget.H ../FL/fl_draw.H +fl_boxtype.o: ../FL/x.H ../FL/Fl_Window.H ../FL/Enumerations.H +fl_boxtype.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H +fl_boxtype.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Device.H +fl_boxtype.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H +fl_boxtype.o: ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H fl_boxtype.o: ../config.h -fl_color.o: Fl_XColor.H ../config.h ../FL/Enumerations.H ../FL/Fl.H -fl_color.o: ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h ../FL/Xutf8.h -fl_color.o: ../FL/Enumerations.H ../FL/x.H ../FL/Fl_Window.H ../FL/fl_draw.H -fl_color.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H -fl_color.o: ../FL/Fl_Device.H ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H -fl_color.o: ../FL/Fl_Image.H ../FL/Fl_Bitmap.H ../FL/Fl_Image.H +fl_color.o: Fl_XColor.H ../config.h ../FL/Enumerations.H ../FL/Fl_Export.H +fl_color.o: ../FL/fl_types.h ../FL/Fl.H ../FL/fl_utf8.h ../FL/Enumerations.H +fl_color.o: ../FL/x.H ../FL/Fl_Window.H ../FL/fl_draw.H ../FL/Fl_Window.H +fl_color.o: ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Bitmap.H +fl_color.o: ../FL/Fl_Image.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H +fl_color.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H fl_color.o: ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H fl_cmap.h fl_cursor.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h -fl_cursor.o: ../FL/Xutf8.h ../FL/Enumerations.H ../FL/Fl_Window.H -fl_cursor.o: ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/x.H ../FL/Fl_Window.H -fl_cursor.o: ../FL/fl_draw.H ../FL/Enumerations.H ../FL/Fl_Device.H -fl_cursor.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H -fl_cursor.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Pixmap.H -fl_cursor.o: ../FL/Fl_RGB_Image.H +fl_cursor.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Group.H +fl_cursor.o: ../FL/Fl_Widget.H ../FL/Fl_Bitmap.H ../FL/Fl_Image.H +fl_cursor.o: ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H ../FL/x.H +fl_cursor.o: ../FL/Fl_Window.H ../FL/fl_draw.H ../FL/Enumerations.H +fl_cursor.o: ../FL/Fl_Device.H ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H +fl_cursor.o: ../FL/Fl_Image.H ../FL/Fl_Bitmap.H fl_cursor_wait.xpm +fl_cursor.o: fl_cursor_help.xpm fl_cursor_nwse.xpm fl_cursor_nesw.xpm +fl_cursor.o: fl_cursor_none.xpm fl_curve.o: ../FL/fl_draw.H ../FL/x.H ../FL/Enumerations.H ../FL/Fl_Export.H -fl_curve.o: ../FL/fl_types.h ../FL/Fl_Window.H ../FL/Xutf8.h -fl_curve.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Group.H -fl_curve.o: ../FL/Fl_Widget.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H -fl_curve.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H -fl_curve.o: ../FL/Fl_Image.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H +fl_curve.o: ../FL/fl_types.h ../FL/Fl_Window.H ../FL/Enumerations.H +fl_curve.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H +fl_curve.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Device.H +fl_curve.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H +fl_curve.o: ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H fl_diamond_box.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H -fl_diamond_box.o: ../FL/fl_types.h ../FL/Xutf8.h ../FL/Enumerations.H -fl_diamond_box.o: ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H -fl_diamond_box.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Group.H -fl_diamond_box.o: ../FL/Fl_Widget.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H -fl_diamond_box.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H -fl_diamond_box.o: ../FL/Fl_Image.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H +fl_diamond_box.o: ../FL/fl_types.h ../FL/Enumerations.H ../FL/fl_draw.H +fl_diamond_box.o: ../FL/x.H ../FL/Fl_Window.H ../FL/Enumerations.H +fl_diamond_box.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H +fl_diamond_box.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Device.H +fl_diamond_box.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H +fl_diamond_box.o: ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H fl_dnd.o: fl_dnd_x.cxx ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H -fl_dnd.o: ../FL/fl_types.h ../FL/Xutf8.h ../FL/Enumerations.H -fl_dnd.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/x.H -fl_dnd.o: ../FL/Fl_Window.H flstring.h ../FL/Fl_Export.H ../config.h +fl_dnd.o: ../FL/fl_types.h ../FL/Enumerations.H ../FL/Fl_Window.H +fl_dnd.o: ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Bitmap.H +fl_dnd.o: ../FL/Fl_Image.H ../FL/x.H ../FL/Fl_Window.H flstring.h +fl_dnd.o: ../FL/Fl_Export.H ../config.h fl_draw.o: ../FL/fl_utf8.h ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H -fl_draw.o: ../FL/fl_types.h ../FL/Xutf8.h ../FL/Enumerations.H -fl_draw.o: ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H ../FL/Enumerations.H -fl_draw.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H -fl_draw.o: ../FL/Fl_Device.H ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H -fl_draw.o: ../FL/Fl_Image.H ../FL/Fl_Bitmap.H ../FL/Fl_Image.H +fl_draw.o: ../FL/fl_types.h ../FL/Enumerations.H ../FL/fl_draw.H ../FL/x.H +fl_draw.o: ../FL/Fl_Window.H ../FL/Enumerations.H ../FL/Fl_Window.H +fl_draw.o: ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Bitmap.H +fl_draw.o: ../FL/Fl_Image.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H +fl_draw.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H fl_draw.o: ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H flstring.h fl_draw.o: ../FL/Fl_Export.H ../config.h fl_draw_image.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H -fl_draw_image.o: ../FL/fl_types.h ../FL/Xutf8.h ../FL/Enumerations.H -fl_draw_image.o: ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H -fl_draw_image.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Group.H -fl_draw_image.o: ../FL/Fl_Widget.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H -fl_draw_image.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H -fl_draw_image.o: ../FL/Fl_Image.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H +fl_draw_image.o: ../FL/fl_types.h ../FL/Enumerations.H ../FL/fl_draw.H +fl_draw_image.o: ../FL/x.H ../FL/Fl_Window.H ../FL/Enumerations.H +fl_draw_image.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H +fl_draw_image.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Device.H +fl_draw_image.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H +fl_draw_image.o: ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H fl_draw_image.o: Fl_XColor.H ../config.h flstring.h ../FL/Fl_Export.H fl_draw_pixmap.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H -fl_draw_pixmap.o: ../FL/fl_types.h ../FL/Xutf8.h ../FL/Enumerations.H -fl_draw_pixmap.o: ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H -fl_draw_pixmap.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Group.H -fl_draw_pixmap.o: ../FL/Fl_Widget.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H -fl_draw_pixmap.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H -fl_draw_pixmap.o: ../FL/Fl_Image.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H +fl_draw_pixmap.o: ../FL/fl_types.h ../FL/Enumerations.H ../FL/fl_draw.H +fl_draw_pixmap.o: ../FL/x.H ../FL/Fl_Window.H ../FL/Enumerations.H +fl_draw_pixmap.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H +fl_draw_pixmap.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Device.H +fl_draw_pixmap.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H +fl_draw_pixmap.o: ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H fl_draw_pixmap.o: flstring.h ../FL/Fl_Export.H ../config.h fl_encoding_latin1.o: ../FL/fl_draw.H ../FL/x.H ../FL/Enumerations.H fl_encoding_latin1.o: ../FL/Fl_Export.H ../FL/fl_types.h ../FL/Fl_Window.H -fl_encoding_latin1.o: ../FL/Xutf8.h ../FL/Enumerations.H ../FL/Fl_Window.H -fl_encoding_latin1.o: ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Device.H -fl_encoding_latin1.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H -fl_encoding_latin1.o: ../FL/Fl_Image.H ../FL/Fl_Bitmap.H ../FL/Fl_Image.H -fl_encoding_latin1.o: ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H flstring.h -fl_encoding_latin1.o: ../FL/Fl_Export.H ../config.h +fl_encoding_latin1.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Group.H +fl_encoding_latin1.o: ../FL/Fl_Widget.H ../FL/Fl_Bitmap.H ../FL/Fl_Image.H +fl_encoding_latin1.o: ../FL/Fl_Device.H ../FL/Fl_Plugin.H +fl_encoding_latin1.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H +fl_encoding_latin1.o: ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H +fl_encoding_latin1.o: ../FL/Fl_RGB_Image.H flstring.h ../FL/Fl_Export.H +fl_encoding_latin1.o: ../config.h fl_encoding_mac_roman.o: ../FL/fl_draw.H ../FL/x.H ../FL/Enumerations.H fl_encoding_mac_roman.o: ../FL/Fl_Export.H ../FL/fl_types.h ../FL/Fl_Window.H -fl_encoding_mac_roman.o: ../FL/Xutf8.h ../FL/Enumerations.H ../FL/Fl_Window.H -fl_encoding_mac_roman.o: ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Device.H -fl_encoding_mac_roman.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H -fl_encoding_mac_roman.o: ../FL/Fl_Image.H ../FL/Fl_Bitmap.H ../FL/Fl_Image.H -fl_encoding_mac_roman.o: ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H flstring.h -fl_encoding_mac_roman.o: ../FL/Fl_Export.H ../config.h +fl_encoding_mac_roman.o: ../FL/Enumerations.H ../FL/Fl_Window.H +fl_encoding_mac_roman.o: ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Bitmap.H +fl_encoding_mac_roman.o: ../FL/Fl_Image.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H +fl_encoding_mac_roman.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H +fl_encoding_mac_roman.o: ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H +fl_encoding_mac_roman.o: ../FL/Fl_RGB_Image.H flstring.h ../FL/Fl_Export.H +fl_encoding_mac_roman.o: ../config.h fl_engraved_label.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H -fl_engraved_label.o: ../FL/fl_types.h ../FL/Xutf8.h ../FL/Enumerations.H -fl_engraved_label.o: ../FL/Fl_Widget.H ../FL/fl_draw.H ../FL/x.H -fl_engraved_label.o: ../FL/Fl_Window.H ../FL/Enumerations.H ../FL/Fl_Window.H -fl_engraved_label.o: ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Device.H -fl_engraved_label.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H -fl_engraved_label.o: ../FL/Fl_Image.H ../FL/Fl_Bitmap.H ../FL/Fl_Image.H -fl_engraved_label.o: ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H +fl_engraved_label.o: ../FL/fl_types.h ../FL/Enumerations.H ../FL/Fl_Widget.H +fl_engraved_label.o: ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H +fl_engraved_label.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Group.H +fl_engraved_label.o: ../FL/Fl_Widget.H ../FL/Fl_Bitmap.H ../FL/Fl_Image.H +fl_engraved_label.o: ../FL/Fl_Device.H ../FL/Fl_Plugin.H +fl_engraved_label.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H +fl_engraved_label.o: ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H fl_file_dir.o: flstring.h ../FL/Fl_Export.H ../config.h ../FL/filename.H fl_file_dir.o: ../FL/Fl_File_Chooser.H ../FL/Fl.H ../FL/fl_utf8.h -fl_file_dir.o: ../FL/Fl_Export.H ../FL/fl_types.h ../FL/Xutf8.h -fl_file_dir.o: ../FL/Enumerations.H ../FL/Fl_Double_Window.H -fl_file_dir.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Choice.H -fl_file_dir.o: ../FL/Fl_Menu_.H ../FL/Fl_Widget.H ../FL/Fl_Menu_Item.H -fl_file_dir.o: ../FL/Fl_Image.H ../FL/Fl_Menu_Button.H ../FL/Fl_Button.H -fl_file_dir.o: ../FL/Fl_Preferences.H ../FL/Fl_Tile.H ../FL/Fl_Group.H -fl_file_dir.o: ../FL/Fl_File_Browser.H ../FL/Fl_Browser.H ../FL/Fl_Browser_.H -fl_file_dir.o: ../FL/Fl_Scrollbar.H ../FL/Fl_Slider.H ../FL/Fl_Valuator.H +fl_file_dir.o: ../FL/Fl_Export.H ../FL/fl_types.h ../FL/Enumerations.H +fl_file_dir.o: ../FL/Fl_Double_Window.H ../FL/Fl_Window.H ../FL/Fl_Group.H +fl_file_dir.o: ../FL/Fl_Choice.H ../FL/Fl_Menu_.H ../FL/Fl_Widget.H +fl_file_dir.o: ../FL/Fl_Menu_Item.H ../FL/Fl_Image.H ../FL/Fl_Menu_Button.H +fl_file_dir.o: ../FL/Fl_Button.H ../FL/Fl_Preferences.H ../FL/Fl_Tile.H +fl_file_dir.o: ../FL/Fl_Group.H ../FL/Fl_File_Browser.H ../FL/Fl_Browser.H fl_file_dir.o: ../FL/Fl_File_Icon.H ../FL/Fl.H ../FL/filename.H fl_file_dir.o: ../FL/Fl_Box.H ../FL/Fl_Check_Button.H ../FL/Fl_Light_Button.H fl_file_dir.o: ../FL/Fl_Button.H ../FL/Fl_File_Input.H ../FL/Fl_Input.H fl_file_dir.o: ../FL/Fl_Input_.H ../FL/Fl_Return_Button.H ../FL/fl_ask.H fl_font.o: flstring.h ../FL/Fl_Export.H ../config.h ../FL/Fl.H -fl_font.o: ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h ../FL/Xutf8.h +fl_font.o: ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h fl_font.o: ../FL/Enumerations.H ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H fl_font.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Group.H -fl_font.o: ../FL/Fl_Widget.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H -fl_font.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H -fl_font.o: ../FL/Fl_Image.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H Fl_Font.H -fl_font.o: fl_font_xft.cxx +fl_font.o: ../FL/Fl_Widget.H ../FL/Fl_Bitmap.H ../FL/Fl_Image.H +fl_font.o: ../FL/Fl_Device.H ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H +fl_font.o: ../FL/Fl_Image.H ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H +fl_font.o: ../FL/Fl_RGB_Image.H Fl_Font.H fl_font_xft.cxx +fl_gleam.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h +fl_gleam.o: ../FL/Enumerations.H ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H +fl_gleam.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Group.H +fl_gleam.o: ../FL/Fl_Widget.H ../FL/Fl_Bitmap.H ../FL/Fl_Image.H +fl_gleam.o: ../FL/Fl_Device.H ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H +fl_gleam.o: ../FL/Fl_Image.H ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H +fl_gleam.o: ../FL/Fl_RGB_Image.H fl_gtk.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h -fl_gtk.o: ../FL/Xutf8.h ../FL/Enumerations.H ../FL/fl_draw.H ../FL/x.H -fl_gtk.o: ../FL/Fl_Window.H ../FL/Enumerations.H ../FL/Fl_Window.H -fl_gtk.o: ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Device.H -fl_gtk.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H -fl_gtk.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Pixmap.H +fl_gtk.o: ../FL/Enumerations.H ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H +fl_gtk.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Group.H +fl_gtk.o: ../FL/Fl_Widget.H ../FL/Fl_Bitmap.H ../FL/Fl_Image.H +fl_gtk.o: ../FL/Fl_Device.H ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H +fl_gtk.o: ../FL/Fl_Image.H ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H fl_gtk.o: ../FL/Fl_RGB_Image.H fl_labeltype.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h -fl_labeltype.o: ../FL/Xutf8.h ../FL/Enumerations.H ../FL/Fl_Widget.H -fl_labeltype.o: ../FL/Fl_Group.H ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H +fl_labeltype.o: ../FL/Enumerations.H ../FL/Fl_Widget.H ../FL/Fl_Group.H +fl_labeltype.o: ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H fl_labeltype.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Group.H -fl_labeltype.o: ../FL/Fl_Widget.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H -fl_labeltype.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H -fl_labeltype.o: ../FL/Fl_Image.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H -fl_labeltype.o: ../FL/Fl_Input_.H +fl_labeltype.o: ../FL/Fl_Widget.H ../FL/Fl_Bitmap.H ../FL/Fl_Image.H +fl_labeltype.o: ../FL/Fl_Device.H ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H +fl_labeltype.o: ../FL/Fl_Image.H ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H +fl_labeltype.o: ../FL/Fl_RGB_Image.H ../FL/Fl_Input_.H fl_line_style.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H -fl_line_style.o: ../FL/fl_types.h ../FL/Xutf8.h ../FL/Enumerations.H -fl_line_style.o: ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H -fl_line_style.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Group.H -fl_line_style.o: ../FL/Fl_Widget.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H -fl_line_style.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H -fl_line_style.o: ../FL/Fl_Image.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H +fl_line_style.o: ../FL/fl_types.h ../FL/Enumerations.H ../FL/fl_draw.H +fl_line_style.o: ../FL/x.H ../FL/Fl_Window.H ../FL/Enumerations.H +fl_line_style.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H +fl_line_style.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Device.H +fl_line_style.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H +fl_line_style.o: ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H fl_line_style.o: ../FL/Fl_Printer.H ../FL/Fl_Paged_Device.H fl_line_style.o: ../FL/Fl_PostScript.H flstring.h ../FL/Fl_Export.H fl_line_style.o: ../config.h fl_open_uri.o: ../FL/filename.H flstring.h ../FL/Fl_Export.H ../config.h fl_oval_box.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h -fl_oval_box.o: ../FL/Xutf8.h ../FL/Enumerations.H ../FL/fl_draw.H ../FL/x.H +fl_oval_box.o: ../FL/Enumerations.H ../FL/fl_draw.H ../FL/x.H fl_oval_box.o: ../FL/Fl_Window.H ../FL/Enumerations.H ../FL/Fl_Window.H -fl_oval_box.o: ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Device.H -fl_oval_box.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H -fl_oval_box.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Pixmap.H -fl_oval_box.o: ../FL/Fl_RGB_Image.H +fl_oval_box.o: ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Bitmap.H +fl_oval_box.o: ../FL/Fl_Image.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H +fl_oval_box.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H +fl_oval_box.o: ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H fl_overlay.o: ../FL/x.H ../FL/Enumerations.H ../FL/Fl_Export.H -fl_overlay.o: ../FL/fl_types.h ../FL/Fl_Window.H ../FL/Xutf8.h -fl_overlay.o: ../FL/fl_draw.H ../FL/Enumerations.H ../FL/Fl_Window.H -fl_overlay.o: ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Device.H -fl_overlay.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H -fl_overlay.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Pixmap.H +fl_overlay.o: ../FL/fl_types.h ../FL/Fl_Window.H ../FL/fl_draw.H +fl_overlay.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Group.H +fl_overlay.o: ../FL/Fl_Widget.H ../FL/Fl_Bitmap.H ../FL/Fl_Image.H +fl_overlay.o: ../FL/Fl_Device.H ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H +fl_overlay.o: ../FL/Fl_Image.H ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H fl_overlay.o: ../FL/Fl_RGB_Image.H fl_overlay_visual.o: ../config.h fl_plastic.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h -fl_plastic.o: ../FL/Xutf8.h ../FL/Enumerations.H ../FL/fl_draw.H ../FL/x.H +fl_plastic.o: ../FL/Enumerations.H ../FL/fl_draw.H ../FL/x.H fl_plastic.o: ../FL/Fl_Window.H ../FL/Enumerations.H ../FL/Fl_Window.H -fl_plastic.o: ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Device.H -fl_plastic.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H -fl_plastic.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Pixmap.H -fl_plastic.o: ../FL/Fl_RGB_Image.H flstring.h ../FL/Fl_Export.H ../config.h +fl_plastic.o: ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Bitmap.H +fl_plastic.o: ../FL/Fl_Image.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H +fl_plastic.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H +fl_plastic.o: ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H flstring.h +fl_plastic.o: ../FL/Fl_Export.H ../config.h fl_read_image.o: ../FL/x.H ../FL/Enumerations.H ../FL/Fl_Export.H -fl_read_image.o: ../FL/fl_types.h ../FL/Fl_Window.H ../FL/Xutf8.h ../FL/Fl.H +fl_read_image.o: ../FL/fl_types.h ../FL/Fl_Window.H ../FL/Fl.H fl_read_image.o: ../FL/fl_utf8.h ../FL/fl_draw.H ../FL/Enumerations.H fl_read_image.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H -fl_read_image.o: ../FL/Fl_Device.H ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H -fl_read_image.o: ../FL/Fl_Image.H ../FL/Fl_Bitmap.H ../FL/Fl_Image.H -fl_read_image.o: ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H flstring.h -fl_read_image.o: ../FL/Fl_Export.H ../config.h +fl_read_image.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Device.H +fl_read_image.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H +fl_read_image.o: ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H +fl_read_image.o: flstring.h ../FL/Fl_Export.H ../config.h fl_rect.o: ../config.h ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H -fl_rect.o: ../FL/fl_types.h ../FL/Xutf8.h ../FL/Enumerations.H -fl_rect.o: ../FL/Fl_Widget.H ../FL/Fl_Printer.H ../FL/x.H ../FL/Fl_Window.H +fl_rect.o: ../FL/fl_types.h ../FL/Enumerations.H ../FL/Fl_Widget.H +fl_rect.o: ../FL/Fl_Printer.H ../FL/x.H ../FL/Fl_Window.H fl_rect.o: ../FL/Fl_Paged_Device.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H fl_rect.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H -fl_rect.o: ../FL/Fl_Image.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H +fl_rect.o: ../FL/Fl_Pixmap.H ../FL/Fl_Image.H ../FL/Fl_RGB_Image.H fl_rect.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H -fl_rect.o: ../FL/fl_draw.H ../FL/Enumerations.H ../FL/Fl_PostScript.H +fl_rect.o: ../FL/Fl_Bitmap.H ../FL/fl_draw.H ../FL/Enumerations.H +fl_rect.o: ../FL/Fl_PostScript.H fl_round_box.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h -fl_round_box.o: ../FL/Xutf8.h ../FL/Enumerations.H ../FL/fl_draw.H ../FL/x.H +fl_round_box.o: ../FL/Enumerations.H ../FL/fl_draw.H ../FL/x.H fl_round_box.o: ../FL/Fl_Window.H ../FL/Enumerations.H ../FL/Fl_Window.H -fl_round_box.o: ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Device.H -fl_round_box.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H -fl_round_box.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Pixmap.H -fl_round_box.o: ../FL/Fl_RGB_Image.H +fl_round_box.o: ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Bitmap.H +fl_round_box.o: ../FL/Fl_Image.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H +fl_round_box.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H +fl_round_box.o: ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H fl_rounded_box.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H -fl_rounded_box.o: ../FL/fl_types.h ../FL/Xutf8.h ../FL/Enumerations.H -fl_rounded_box.o: ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H -fl_rounded_box.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Group.H -fl_rounded_box.o: ../FL/Fl_Widget.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H -fl_rounded_box.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H -fl_rounded_box.o: ../FL/Fl_Image.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H +fl_rounded_box.o: ../FL/fl_types.h ../FL/Enumerations.H ../FL/fl_draw.H +fl_rounded_box.o: ../FL/x.H ../FL/Fl_Window.H ../FL/Enumerations.H +fl_rounded_box.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H +fl_rounded_box.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Device.H +fl_rounded_box.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H +fl_rounded_box.o: ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H fl_set_font.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h -fl_set_font.o: ../FL/Xutf8.h ../FL/Enumerations.H ../FL/x.H ../FL/Fl_Window.H +fl_set_font.o: ../FL/Enumerations.H ../FL/x.H ../FL/Fl_Window.H fl_set_font.o: ../FL/fl_draw.H ../FL/Enumerations.H ../FL/Fl_Window.H -fl_set_font.o: ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Device.H -fl_set_font.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H -fl_set_font.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Pixmap.H -fl_set_font.o: ../FL/Fl_RGB_Image.H flstring.h ../FL/Fl_Export.H ../config.h -fl_set_font.o: Fl_Font.H +fl_set_font.o: ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Bitmap.H +fl_set_font.o: ../FL/Fl_Image.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H +fl_set_font.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H +fl_set_font.o: ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H flstring.h +fl_set_font.o: ../FL/Fl_Export.H ../config.h Fl_Font.H fl_set_fonts.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h -fl_set_fonts.o: ../FL/Xutf8.h ../FL/Enumerations.H ../FL/x.H -fl_set_fonts.o: ../FL/Fl_Window.H Fl_Font.H ../config.h flstring.h -fl_set_fonts.o: ../FL/Fl_Export.H fl_set_fonts_xft.cxx +fl_set_fonts.o: ../FL/Enumerations.H ../FL/x.H ../FL/Fl_Window.H Fl_Font.H +fl_set_fonts.o: ../config.h flstring.h ../FL/Fl_Export.H fl_set_fonts_xft.cxx fl_scroll_area.o: ../config.h ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H -fl_scroll_area.o: ../FL/fl_types.h ../FL/Xutf8.h ../FL/Enumerations.H -fl_scroll_area.o: ../FL/x.H ../FL/Fl_Window.H ../FL/fl_draw.H -fl_scroll_area.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Group.H -fl_scroll_area.o: ../FL/Fl_Widget.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H -fl_scroll_area.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H -fl_scroll_area.o: ../FL/Fl_Image.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H +fl_scroll_area.o: ../FL/fl_types.h ../FL/Enumerations.H ../FL/x.H +fl_scroll_area.o: ../FL/Fl_Window.H ../FL/fl_draw.H ../FL/Enumerations.H +fl_scroll_area.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H +fl_scroll_area.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Device.H +fl_scroll_area.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H +fl_scroll_area.o: ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H fl_shadow_box.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H -fl_shadow_box.o: ../FL/fl_types.h ../FL/Xutf8.h ../FL/Enumerations.H -fl_shadow_box.o: ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H -fl_shadow_box.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Group.H -fl_shadow_box.o: ../FL/Fl_Widget.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H -fl_shadow_box.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H -fl_shadow_box.o: ../FL/Fl_Image.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H +fl_shadow_box.o: ../FL/fl_types.h ../FL/Enumerations.H ../FL/fl_draw.H +fl_shadow_box.o: ../FL/x.H ../FL/Fl_Window.H ../FL/Enumerations.H +fl_shadow_box.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H +fl_shadow_box.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Device.H +fl_shadow_box.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H +fl_shadow_box.o: ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H fl_shortcut.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h -fl_shortcut.o: ../FL/Xutf8.h ../FL/Enumerations.H ../FL/Fl_Widget.H -fl_shortcut.o: ../FL/Fl_Button.H ../FL/Fl_Widget.H ../FL/fl_draw.H ../FL/x.H -fl_shortcut.o: ../FL/Fl_Window.H ../FL/Enumerations.H ../FL/Fl_Window.H -fl_shortcut.o: ../FL/Fl_Group.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H -fl_shortcut.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H -fl_shortcut.o: ../FL/Fl_Image.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H +fl_shortcut.o: ../FL/Enumerations.H ../FL/Fl_Widget.H ../FL/Fl_Button.H +fl_shortcut.o: ../FL/Fl_Widget.H ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H +fl_shortcut.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Group.H +fl_shortcut.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Device.H +fl_shortcut.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H +fl_shortcut.o: ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H fl_shortcut.o: flstring.h ../FL/Fl_Export.H ../config.h fl_show_colormap.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H -fl_show_colormap.o: ../FL/fl_types.h ../FL/Xutf8.h ../FL/Enumerations.H +fl_show_colormap.o: ../FL/fl_types.h ../FL/Enumerations.H fl_show_colormap.o: ../FL/Fl_Single_Window.H ../FL/Fl_Window.H fl_show_colormap.o: ../FL/fl_draw.H ../FL/x.H ../FL/Enumerations.H fl_show_colormap.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H -fl_show_colormap.o: ../FL/Fl_Device.H ../FL/Fl_Plugin.H -fl_show_colormap.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H -fl_show_colormap.o: ../FL/Fl_Image.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H +fl_show_colormap.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Device.H +fl_show_colormap.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H +fl_show_colormap.o: ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H fl_show_colormap.o: ../FL/fl_show_colormap.H ../config.h fl_symbols.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h -fl_symbols.o: ../FL/Xutf8.h ../FL/Enumerations.H ../FL/fl_draw.H ../FL/x.H +fl_symbols.o: ../FL/Enumerations.H ../FL/fl_draw.H ../FL/x.H fl_symbols.o: ../FL/Fl_Window.H ../FL/Enumerations.H ../FL/Fl_Window.H -fl_symbols.o: ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Device.H -fl_symbols.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H -fl_symbols.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Pixmap.H -fl_symbols.o: ../FL/Fl_RGB_Image.H ../FL/math.h flstring.h ../FL/Fl_Export.H -fl_symbols.o: ../config.h +fl_symbols.o: ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Bitmap.H +fl_symbols.o: ../FL/Fl_Image.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H +fl_symbols.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H +fl_symbols.o: ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H ../FL/math.h flstring.h +fl_symbols.o: ../FL/Fl_Export.H ../config.h fl_vertex.o: ../config.h ../FL/fl_draw.H ../FL/x.H ../FL/Enumerations.H fl_vertex.o: ../FL/Fl_Export.H ../FL/fl_types.h ../FL/Fl_Window.H -fl_vertex.o: ../FL/Xutf8.h ../FL/Enumerations.H ../FL/Fl_Window.H -fl_vertex.o: ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Device.H -fl_vertex.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H -fl_vertex.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Pixmap.H +fl_vertex.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Group.H +fl_vertex.o: ../FL/Fl_Widget.H ../FL/Fl_Bitmap.H ../FL/Fl_Image.H +fl_vertex.o: ../FL/Fl_Device.H ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H +fl_vertex.o: ../FL/Fl_Image.H ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H fl_vertex.o: ../FL/Fl_RGB_Image.H ../FL/Fl.H ../FL/fl_utf8.h ../FL/math.h screen_xywh.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h -screen_xywh.o: ../FL/Xutf8.h ../FL/Enumerations.H ../FL/x.H ../FL/Fl_Window.H -screen_xywh.o: ../config.h -fl_utf8.o: ../config.h ../FL/filename.H ../FL/Xutf8.h ../FL/fl_utf8.h +screen_xywh.o: ../FL/Enumerations.H ../FL/x.H ../FL/Fl_Window.H ../config.h +fl_utf8.o: ../config.h ../FL/filename.H Xutf8.h ../FL/fl_utf8.h ps_image.o: ../FL/Fl_PostScript.H ../FL/Fl_Paged_Device.H ../FL/Fl_Device.H ps_image.o: ../FL/x.H ../FL/Enumerations.H ../FL/Fl_Export.H ../FL/fl_types.h -ps_image.o: ../FL/Fl_Window.H ../FL/Xutf8.h ../FL/Fl_Plugin.H -ps_image.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H -ps_image.o: ../FL/Fl_Image.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H -ps_image.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H +ps_image.o: ../FL/Fl_Window.H ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H +ps_image.o: ../FL/Fl_Image.H ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H +ps_image.o: ../FL/Fl_Image.H ../FL/Fl_RGB_Image.H ../FL/Fl_Window.H +ps_image.o: ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Bitmap.H ps_image.o: ../FL/fl_draw.H ../FL/Enumerations.H ../FL/Fl.H ../FL/fl_utf8.h forms_compatability.o: ../FL/forms.H ../FL/Fl.H ../FL/fl_utf8.h -forms_compatability.o: ../FL/Fl_Export.H ../FL/fl_types.h ../FL/Xutf8.h +forms_compatability.o: ../FL/Fl_Export.H ../FL/fl_types.h forms_compatability.o: ../FL/Enumerations.H ../FL/Fl_Group.H forms_compatability.o: ../FL/Fl_Widget.H ../FL/Fl_Window.H ../FL/fl_draw.H forms_compatability.o: ../FL/x.H ../FL/Enumerations.H ../FL/Fl_Window.H -forms_compatability.o: ../FL/Fl_Device.H ../FL/Fl_Plugin.H -forms_compatability.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H -forms_compatability.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Pixmap.H +forms_compatability.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Device.H +forms_compatability.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H +forms_compatability.o: ../FL/Fl_Image.H ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H forms_compatability.o: ../FL/Fl_RGB_Image.H ../FL/Fl_FormsBitmap.H -forms_compatability.o: ../FL/Fl_Bitmap.H ../FL/Fl_FormsPixmap.H -forms_compatability.o: ../FL/Fl_Pixmap.H ../FL/Fl_Box.H ../FL/Fl_Browser.H -forms_compatability.o: ../FL/Fl_Browser_.H ../FL/Fl_Scrollbar.H -forms_compatability.o: ../FL/Fl_Slider.H ../FL/Fl_Valuator.H ../FL/Fl.H -forms_compatability.o: ../FL/Fl_Button.H ../FL/Fl_Light_Button.H -forms_compatability.o: ../FL/Fl_Round_Button.H ../FL/Fl_Check_Button.H -forms_compatability.o: ../FL/Fl_Chart.H ../FL/Fl_Choice.H ../FL/Fl_Menu_.H +forms_compatability.o: ../FL/Fl_FormsPixmap.H ../FL/Fl_Pixmap.H +forms_compatability.o: ../FL/Fl_Box.H ../FL/Fl_Browser.H ../FL/Fl_Button.H +forms_compatability.o: ../FL/Fl_Light_Button.H ../FL/Fl_Round_Button.H +forms_compatability.o: ../FL/Fl_Check_Button.H ../FL/Fl_Chart.H +forms_compatability.o: ../FL/Fl_Choice.H ../FL/Fl_Menu_.H forms_compatability.o: ../FL/Fl_Menu_Item.H ../FL/Fl_Clock.H forms_compatability.o: ../FL/Fl_Counter.H ../FL/Fl_Dial.H ../FL/Fl_Free.H forms_compatability.o: ../FL/fl_ask.H ../FL/fl_show_colormap.H -forms_compatability.o: ../FL/filename.H ../FL/Fl_File_Chooser.H +forms_compatability.o: ../FL/filename.H ../FL/Fl_File_Chooser.H ../FL/Fl.H forms_compatability.o: ../FL/Fl_Double_Window.H ../FL/Fl_Group.H forms_compatability.o: ../FL/Fl_Choice.H ../FL/Fl_Menu_Button.H forms_compatability.o: ../FL/Fl_Button.H ../FL/Fl_Preferences.H @@ -990,230 +1054,238 @@ forms_compatability.o: ../FL/Fl_Check_Button.H ../FL/Fl_File_Input.H forms_compatability.o: ../FL/Fl_Input.H ../FL/Fl_Input_.H forms_compatability.o: ../FL/Fl_Return_Button.H ../FL/fl_ask.H forms_compatability.o: ../FL/Fl_Input.H ../FL/Fl_Menu_Button.H -forms_compatability.o: ../FL/Fl_Positioner.H ../FL/Fl_Value_Slider.H +forms_compatability.o: ../FL/Fl_Positioner.H ../FL/Fl_Slider.H +forms_compatability.o: ../FL/Fl_Valuator.H ../FL/Fl_Value_Slider.H forms_compatability.o: ../FL/Fl_Timer.H ../FL/Fl_Repeat_Button.H forms_bitmap.o: ../FL/forms.H ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H -forms_bitmap.o: ../FL/fl_types.h ../FL/Xutf8.h ../FL/Enumerations.H -forms_bitmap.o: ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Window.H -forms_bitmap.o: ../FL/fl_draw.H ../FL/x.H ../FL/Enumerations.H -forms_bitmap.o: ../FL/Fl_Window.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H +forms_bitmap.o: ../FL/fl_types.h ../FL/Enumerations.H ../FL/Fl_Group.H +forms_bitmap.o: ../FL/Fl_Widget.H ../FL/Fl_Window.H ../FL/fl_draw.H ../FL/x.H +forms_bitmap.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Bitmap.H +forms_bitmap.o: ../FL/Fl_Image.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H forms_bitmap.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H -forms_bitmap.o: ../FL/Fl_Image.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H -forms_bitmap.o: ../FL/Fl_FormsBitmap.H ../FL/Fl_Bitmap.H +forms_bitmap.o: ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H ../FL/Fl_FormsBitmap.H forms_bitmap.o: ../FL/Fl_FormsPixmap.H ../FL/Fl_Pixmap.H ../FL/Fl_Box.H -forms_bitmap.o: ../FL/Fl_Browser.H ../FL/Fl_Browser_.H ../FL/Fl_Scrollbar.H -forms_bitmap.o: ../FL/Fl_Slider.H ../FL/Fl_Valuator.H ../FL/Fl.H -forms_bitmap.o: ../FL/Fl_Button.H ../FL/Fl_Light_Button.H +forms_bitmap.o: ../FL/Fl_Browser.H ../FL/Fl_Button.H ../FL/Fl_Light_Button.H forms_bitmap.o: ../FL/Fl_Round_Button.H ../FL/Fl_Check_Button.H forms_bitmap.o: ../FL/Fl_Chart.H ../FL/Fl_Choice.H ../FL/Fl_Menu_.H forms_bitmap.o: ../FL/Fl_Menu_Item.H ../FL/Fl_Clock.H ../FL/Fl_Counter.H forms_bitmap.o: ../FL/Fl_Dial.H ../FL/Fl_Free.H ../FL/fl_ask.H forms_bitmap.o: ../FL/fl_show_colormap.H ../FL/filename.H -forms_bitmap.o: ../FL/Fl_File_Chooser.H ../FL/Fl_Double_Window.H +forms_bitmap.o: ../FL/Fl_File_Chooser.H ../FL/Fl.H ../FL/Fl_Double_Window.H forms_bitmap.o: ../FL/Fl_Group.H ../FL/Fl_Choice.H ../FL/Fl_Menu_Button.H forms_bitmap.o: ../FL/Fl_Button.H ../FL/Fl_Preferences.H ../FL/Fl_Tile.H forms_bitmap.o: ../FL/Fl_File_Browser.H ../FL/Fl_File_Icon.H ../FL/Fl_Box.H forms_bitmap.o: ../FL/Fl_Check_Button.H ../FL/Fl_File_Input.H forms_bitmap.o: ../FL/Fl_Input.H ../FL/Fl_Input_.H ../FL/Fl_Return_Button.H forms_bitmap.o: ../FL/fl_ask.H ../FL/Fl_Input.H ../FL/Fl_Menu_Button.H -forms_bitmap.o: ../FL/Fl_Positioner.H ../FL/Fl_Value_Slider.H -forms_bitmap.o: ../FL/Fl_Timer.H +forms_bitmap.o: ../FL/Fl_Positioner.H ../FL/Fl_Slider.H ../FL/Fl_Valuator.H +forms_bitmap.o: ../FL/Fl_Value_Slider.H ../FL/Fl_Timer.H forms_free.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h -forms_free.o: ../FL/Xutf8.h ../FL/Enumerations.H ../FL/Fl_Free.H -forms_free.o: ../FL/Fl_Widget.H +forms_free.o: ../FL/Enumerations.H ../FL/Fl_Free.H ../FL/Fl_Widget.H forms_fselect.o: ../FL/forms.H ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H -forms_fselect.o: ../FL/fl_types.h ../FL/Xutf8.h ../FL/Enumerations.H -forms_fselect.o: ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Window.H -forms_fselect.o: ../FL/fl_draw.H ../FL/x.H ../FL/Enumerations.H -forms_fselect.o: ../FL/Fl_Window.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H -forms_fselect.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H -forms_fselect.o: ../FL/Fl_Image.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H -forms_fselect.o: ../FL/Fl_FormsBitmap.H ../FL/Fl_Bitmap.H -forms_fselect.o: ../FL/Fl_FormsPixmap.H ../FL/Fl_Pixmap.H ../FL/Fl_Box.H -forms_fselect.o: ../FL/Fl_Browser.H ../FL/Fl_Browser_.H ../FL/Fl_Scrollbar.H -forms_fselect.o: ../FL/Fl_Slider.H ../FL/Fl_Valuator.H ../FL/Fl.H +forms_fselect.o: ../FL/fl_types.h ../FL/Enumerations.H ../FL/Fl_Group.H +forms_fselect.o: ../FL/Fl_Widget.H ../FL/Fl_Window.H ../FL/fl_draw.H +forms_fselect.o: ../FL/x.H ../FL/Enumerations.H ../FL/Fl_Window.H +forms_fselect.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Device.H +forms_fselect.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H +forms_fselect.o: ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H +forms_fselect.o: ../FL/Fl_FormsBitmap.H ../FL/Fl_FormsPixmap.H +forms_fselect.o: ../FL/Fl_Pixmap.H ../FL/Fl_Box.H ../FL/Fl_Browser.H forms_fselect.o: ../FL/Fl_Button.H ../FL/Fl_Light_Button.H forms_fselect.o: ../FL/Fl_Round_Button.H ../FL/Fl_Check_Button.H forms_fselect.o: ../FL/Fl_Chart.H ../FL/Fl_Choice.H ../FL/Fl_Menu_.H forms_fselect.o: ../FL/Fl_Menu_Item.H ../FL/Fl_Clock.H ../FL/Fl_Counter.H forms_fselect.o: ../FL/Fl_Dial.H ../FL/Fl_Free.H ../FL/fl_ask.H forms_fselect.o: ../FL/fl_show_colormap.H ../FL/filename.H -forms_fselect.o: ../FL/Fl_File_Chooser.H ../FL/Fl_Double_Window.H +forms_fselect.o: ../FL/Fl_File_Chooser.H ../FL/Fl.H ../FL/Fl_Double_Window.H forms_fselect.o: ../FL/Fl_Group.H ../FL/Fl_Choice.H ../FL/Fl_Menu_Button.H forms_fselect.o: ../FL/Fl_Button.H ../FL/Fl_Preferences.H ../FL/Fl_Tile.H forms_fselect.o: ../FL/Fl_File_Browser.H ../FL/Fl_File_Icon.H ../FL/Fl_Box.H forms_fselect.o: ../FL/Fl_Check_Button.H ../FL/Fl_File_Input.H forms_fselect.o: ../FL/Fl_Input.H ../FL/Fl_Input_.H ../FL/Fl_Return_Button.H forms_fselect.o: ../FL/fl_ask.H ../FL/Fl_Input.H ../FL/Fl_Menu_Button.H -forms_fselect.o: ../FL/Fl_Positioner.H ../FL/Fl_Value_Slider.H -forms_fselect.o: ../FL/Fl_Timer.H flstring.h ../FL/Fl_Export.H ../config.h +forms_fselect.o: ../FL/Fl_Positioner.H ../FL/Fl_Slider.H ../FL/Fl_Valuator.H +forms_fselect.o: ../FL/Fl_Value_Slider.H ../FL/Fl_Timer.H flstring.h +forms_fselect.o: ../FL/Fl_Export.H ../config.h forms_pixmap.o: ../FL/forms.H ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H -forms_pixmap.o: ../FL/fl_types.h ../FL/Xutf8.h ../FL/Enumerations.H -forms_pixmap.o: ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Window.H -forms_pixmap.o: ../FL/fl_draw.H ../FL/x.H ../FL/Enumerations.H -forms_pixmap.o: ../FL/Fl_Window.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H +forms_pixmap.o: ../FL/fl_types.h ../FL/Enumerations.H ../FL/Fl_Group.H +forms_pixmap.o: ../FL/Fl_Widget.H ../FL/Fl_Window.H ../FL/fl_draw.H ../FL/x.H +forms_pixmap.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Bitmap.H +forms_pixmap.o: ../FL/Fl_Image.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H forms_pixmap.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H -forms_pixmap.o: ../FL/Fl_Image.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H -forms_pixmap.o: ../FL/Fl_FormsBitmap.H ../FL/Fl_Bitmap.H +forms_pixmap.o: ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H ../FL/Fl_FormsBitmap.H forms_pixmap.o: ../FL/Fl_FormsPixmap.H ../FL/Fl_Pixmap.H ../FL/Fl_Box.H -forms_pixmap.o: ../FL/Fl_Browser.H ../FL/Fl_Browser_.H ../FL/Fl_Scrollbar.H -forms_pixmap.o: ../FL/Fl_Slider.H ../FL/Fl_Valuator.H ../FL/Fl.H -forms_pixmap.o: ../FL/Fl_Button.H ../FL/Fl_Light_Button.H +forms_pixmap.o: ../FL/Fl_Browser.H ../FL/Fl_Button.H ../FL/Fl_Light_Button.H forms_pixmap.o: ../FL/Fl_Round_Button.H ../FL/Fl_Check_Button.H forms_pixmap.o: ../FL/Fl_Chart.H ../FL/Fl_Choice.H ../FL/Fl_Menu_.H forms_pixmap.o: ../FL/Fl_Menu_Item.H ../FL/Fl_Clock.H ../FL/Fl_Counter.H forms_pixmap.o: ../FL/Fl_Dial.H ../FL/Fl_Free.H ../FL/fl_ask.H forms_pixmap.o: ../FL/fl_show_colormap.H ../FL/filename.H -forms_pixmap.o: ../FL/Fl_File_Chooser.H ../FL/Fl_Double_Window.H +forms_pixmap.o: ../FL/Fl_File_Chooser.H ../FL/Fl.H ../FL/Fl_Double_Window.H forms_pixmap.o: ../FL/Fl_Group.H ../FL/Fl_Choice.H ../FL/Fl_Menu_Button.H forms_pixmap.o: ../FL/Fl_Button.H ../FL/Fl_Preferences.H ../FL/Fl_Tile.H forms_pixmap.o: ../FL/Fl_File_Browser.H ../FL/Fl_File_Icon.H ../FL/Fl_Box.H forms_pixmap.o: ../FL/Fl_Check_Button.H ../FL/Fl_File_Input.H forms_pixmap.o: ../FL/Fl_Input.H ../FL/Fl_Input_.H ../FL/Fl_Return_Button.H forms_pixmap.o: ../FL/fl_ask.H ../FL/Fl_Input.H ../FL/Fl_Menu_Button.H -forms_pixmap.o: ../FL/Fl_Positioner.H ../FL/Fl_Value_Slider.H -forms_pixmap.o: ../FL/Fl_Timer.H +forms_pixmap.o: ../FL/Fl_Positioner.H ../FL/Fl_Slider.H ../FL/Fl_Valuator.H +forms_pixmap.o: ../FL/Fl_Value_Slider.H ../FL/Fl_Timer.H forms_timer.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h -forms_timer.o: ../FL/Xutf8.h ../FL/Enumerations.H ../FL/Fl_Timer.H -forms_timer.o: ../FL/Fl_Widget.H ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H +forms_timer.o: ../FL/Enumerations.H ../FL/Fl_Timer.H ../FL/Fl_Widget.H +forms_timer.o: ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H forms_timer.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Group.H -forms_timer.o: ../FL/Fl_Device.H ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H -forms_timer.o: ../FL/Fl_Image.H ../FL/Fl_Bitmap.H ../FL/Fl_Image.H -forms_timer.o: ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H +forms_timer.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Device.H +forms_timer.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H +forms_timer.o: ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H +forms_timer.o: ../FL/forms.H ../FL/Fl.H ../FL/fl_draw.H +forms_timer.o: ../FL/Fl_FormsBitmap.H ../FL/Fl_FormsPixmap.H +forms_timer.o: ../FL/Fl_Pixmap.H ../FL/Fl_Box.H ../FL/Fl_Browser.H +forms_timer.o: ../FL/Fl_Button.H ../FL/Fl_Light_Button.H +forms_timer.o: ../FL/Fl_Round_Button.H ../FL/Fl_Check_Button.H +forms_timer.o: ../FL/Fl_Chart.H ../FL/Fl_Choice.H ../FL/Fl_Menu_.H +forms_timer.o: ../FL/Fl_Menu_Item.H ../FL/Fl_Clock.H ../FL/Fl_Counter.H +forms_timer.o: ../FL/Fl_Dial.H ../FL/Fl_Free.H ../FL/fl_ask.H +forms_timer.o: ../FL/fl_show_colormap.H ../FL/filename.H +forms_timer.o: ../FL/Fl_File_Chooser.H ../FL/Fl_Double_Window.H +forms_timer.o: ../FL/Fl_Group.H ../FL/Fl_Choice.H ../FL/Fl_Menu_Button.H +forms_timer.o: ../FL/Fl_Button.H ../FL/Fl_Preferences.H ../FL/Fl_Tile.H +forms_timer.o: ../FL/Fl_File_Browser.H ../FL/Fl_File_Icon.H ../FL/Fl_Box.H +forms_timer.o: ../FL/Fl_Check_Button.H ../FL/Fl_File_Input.H ../FL/Fl_Input.H +forms_timer.o: ../FL/Fl_Input_.H ../FL/Fl_Return_Button.H ../FL/fl_ask.H +forms_timer.o: ../FL/Fl_Input.H ../FL/Fl_Menu_Button.H ../FL/Fl_Positioner.H +forms_timer.o: ../FL/Fl_Slider.H ../FL/Fl_Valuator.H ../FL/Fl_Value_Slider.H +forms_timer.o: ../FL/Fl_Timer.H Fl_Gl_Choice.o: ../config.h ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H -Fl_Gl_Choice.o: ../FL/fl_types.h ../FL/Xutf8.h ../FL/Enumerations.H ../FL/x.H +Fl_Gl_Choice.o: ../FL/fl_types.h ../FL/Enumerations.H ../FL/x.H Fl_Gl_Choice.o: ../FL/Fl_Window.H Fl_Gl_Choice.H ../FL/gl_draw.H ../FL/gl.h Fl_Gl_Choice.o: flstring.h ../FL/Fl_Export.H ../FL/fl_utf8.h Fl_Gl_Overlay.o: ../config.h ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H -Fl_Gl_Overlay.o: ../FL/fl_types.h ../FL/Xutf8.h ../FL/Enumerations.H -Fl_Gl_Overlay.o: ../FL/x.H ../FL/Fl_Window.H Fl_Gl_Choice.H -Fl_Gl_Overlay.o: ../FL/Fl_Gl_Window.H +Fl_Gl_Overlay.o: ../FL/fl_types.h ../FL/Enumerations.H ../FL/x.H +Fl_Gl_Overlay.o: ../FL/Fl_Window.H Fl_Gl_Choice.H ../FL/Fl_Gl_Window.H Fl_Gl_Device_Plugin.o: ../config.h ../FL/Fl_Printer.H ../FL/x.H Fl_Gl_Device_Plugin.o: ../FL/Enumerations.H ../FL/Fl_Export.H -Fl_Gl_Device_Plugin.o: ../FL/fl_types.h ../FL/Fl_Window.H ../FL/Xutf8.h +Fl_Gl_Device_Plugin.o: ../FL/fl_types.h ../FL/Fl_Window.H Fl_Gl_Device_Plugin.o: ../FL/Fl_Paged_Device.H ../FL/Fl_Device.H Fl_Gl_Device_Plugin.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H -Fl_Gl_Device_Plugin.o: ../FL/Fl_Image.H ../FL/Fl_Bitmap.H ../FL/Fl_Image.H -Fl_Gl_Device_Plugin.o: ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H +Fl_Gl_Device_Plugin.o: ../FL/Fl_Image.H ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H +Fl_Gl_Device_Plugin.o: ../FL/Fl_Image.H ../FL/Fl_RGB_Image.H Fl_Gl_Device_Plugin.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H -Fl_Gl_Device_Plugin.o: ../FL/fl_draw.H ../FL/Enumerations.H +Fl_Gl_Device_Plugin.o: ../FL/Fl_Bitmap.H ../FL/fl_draw.H ../FL/Enumerations.H Fl_Gl_Device_Plugin.o: ../FL/Fl_PostScript.H ../FL/Fl_Gl_Window.H Fl_Gl_Device_Plugin.o: Fl_Gl_Choice.H ../FL/Fl.H ../FL/fl_utf8.h Fl_Gl_Window.o: flstring.h ../FL/Fl_Export.H ../config.h ../FL/Fl.H Fl_Gl_Window.o: ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h -Fl_Gl_Window.o: ../FL/Xutf8.h ../FL/Enumerations.H ../FL/x.H -Fl_Gl_Window.o: ../FL/Fl_Window.H Fl_Gl_Choice.H ../FL/Fl_Gl_Window.H -Fl_Gl_Window.o: ../FL/fl_utf8.h +Fl_Gl_Window.o: ../FL/Enumerations.H ../FL/x.H ../FL/Fl_Window.H +Fl_Gl_Window.o: Fl_Gl_Choice.H ../FL/Fl_Gl_Window.H ../FL/fl_utf8.h freeglut_geometry.o: ../FL/glut.H ../FL/gl.h ../FL/Enumerations.H freeglut_geometry.o: ../FL/Fl_Export.H ../FL/fl_types.h ../FL/Fl.H -freeglut_geometry.o: ../FL/fl_utf8.h ../FL/Xutf8.h ../FL/Fl_Gl_Window.H -freeglut_geometry.o: ../FL/Fl_Window.H ../FL/math.h +freeglut_geometry.o: ../FL/fl_utf8.h ../FL/Fl_Gl_Window.H ../FL/Fl_Window.H +freeglut_geometry.o: ../FL/math.h freeglut_stroke_mono_roman.o: ../FL/glut.H ../FL/gl.h ../FL/Enumerations.H freeglut_stroke_mono_roman.o: ../FL/Fl_Export.H ../FL/fl_types.h ../FL/Fl.H -freeglut_stroke_mono_roman.o: ../FL/fl_utf8.h ../FL/Xutf8.h -freeglut_stroke_mono_roman.o: ../FL/Fl_Gl_Window.H ../FL/Fl_Window.H +freeglut_stroke_mono_roman.o: ../FL/fl_utf8.h ../FL/Fl_Gl_Window.H +freeglut_stroke_mono_roman.o: ../FL/Fl_Window.H freeglut_stroke_roman.o: ../FL/glut.H ../FL/gl.h ../FL/Enumerations.H freeglut_stroke_roman.o: ../FL/Fl_Export.H ../FL/fl_types.h ../FL/Fl.H -freeglut_stroke_roman.o: ../FL/fl_utf8.h ../FL/Xutf8.h ../FL/Fl_Gl_Window.H +freeglut_stroke_roman.o: ../FL/fl_utf8.h ../FL/Fl_Gl_Window.H freeglut_stroke_roman.o: ../FL/Fl_Window.H freeglut_teapot.o: ../FL/glut.H ../FL/gl.h ../FL/Enumerations.H freeglut_teapot.o: ../FL/Fl_Export.H ../FL/fl_types.h ../FL/Fl.H -freeglut_teapot.o: ../FL/fl_utf8.h ../FL/Xutf8.h ../FL/Fl_Gl_Window.H -freeglut_teapot.o: ../FL/Fl_Window.H freeglut_teapot_data.h +freeglut_teapot.o: ../FL/fl_utf8.h ../FL/Fl_Gl_Window.H ../FL/Fl_Window.H +freeglut_teapot.o: freeglut_teapot_data.h gl_draw.o: flstring.h ../FL/Fl_Export.H ../config.h ../FL/Fl.H -gl_draw.o: ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h ../FL/Xutf8.h -gl_draw.o: ../FL/Enumerations.H ../FL/gl.h ../FL/x.H ../FL/Fl_Window.H -gl_draw.o: ../FL/fl_draw.H ../FL/Enumerations.H ../FL/Fl_Window.H -gl_draw.o: ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Device.H +gl_draw.o: ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h +gl_draw.o: ../FL/Enumerations.H ../FL/gl.h ../FL/gl_draw.H ../FL/gl.h +gl_draw.o: ../FL/x.H ../FL/Fl_Window.H ../FL/fl_draw.H ../FL/Enumerations.H +gl_draw.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H +gl_draw.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Device.H gl_draw.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H -gl_draw.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Pixmap.H -gl_draw.o: ../FL/Fl_RGB_Image.H Fl_Gl_Choice.H Fl_Font.H ../FL/fl_utf8.h -gl_draw.o: ../FL/Xutf8.h +gl_draw.o: ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H +gl_draw.o: Fl_Gl_Choice.H Fl_Font.H ../FL/fl_utf8.h Xutf8.h gl_start.o: ../config.h ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H -gl_start.o: ../FL/fl_types.h ../FL/Xutf8.h ../FL/Enumerations.H -gl_start.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/x.H -gl_start.o: ../FL/Fl_Window.H ../FL/fl_draw.H ../FL/Enumerations.H -gl_start.o: ../FL/Fl_Device.H ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H -gl_start.o: ../FL/Fl_Image.H ../FL/Fl_Bitmap.H ../FL/Fl_Image.H -gl_start.o: ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H Fl_Gl_Choice.H +gl_start.o: ../FL/fl_types.h ../FL/Enumerations.H ../FL/Fl_Window.H +gl_start.o: ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Bitmap.H +gl_start.o: ../FL/Fl_Image.H ../FL/x.H ../FL/Fl_Window.H ../FL/fl_draw.H +gl_start.o: ../FL/Enumerations.H ../FL/Fl_Device.H ../FL/Fl_Plugin.H +gl_start.o: ../FL/Fl_Preferences.H ../FL/Fl_Image.H ../FL/Fl_Bitmap.H +gl_start.o: ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H ../FL/gl.h Fl_Gl_Choice.H glut_compatability.o: flstring.h ../FL/Fl_Export.H ../config.h ../FL/glut.H glut_compatability.o: ../FL/gl.h ../FL/Enumerations.H ../FL/Fl_Export.H glut_compatability.o: ../FL/fl_types.h ../FL/Fl.H ../FL/fl_utf8.h -glut_compatability.o: ../FL/Xutf8.h ../FL/Fl_Gl_Window.H ../FL/Fl_Window.H +glut_compatability.o: ../FL/Fl_Gl_Window.H ../FL/Fl_Window.H glut_compatability.o: ../FL/Fl_Menu_Item.H ../FL/Fl_Widget.H ../FL/Fl_Image.H glut_font.o: ../config.h ../FL/glut.H ../FL/gl.h ../FL/Enumerations.H glut_font.o: ../FL/Fl_Export.H ../FL/fl_types.h ../FL/Fl.H ../FL/fl_utf8.h -glut_font.o: ../FL/Xutf8.h ../FL/Fl_Gl_Window.H ../FL/Fl_Window.H +glut_font.o: ../FL/Fl_Gl_Window.H ../FL/Fl_Window.H fl_images_core.o: ../FL/Fl_Shared_Image.H ../FL/Fl_Image.H +fl_images_core.o: ../FL/Enumerations.H ../FL/Fl_Export.H ../FL/fl_types.h fl_images_core.o: ../FL/Fl_BMP_Image.H ../FL/Fl_GIF_Image.H ../FL/Fl_Pixmap.H fl_images_core.o: ../FL/Fl_JPEG_Image.H ../FL/Fl_PNG_Image.H fl_images_core.o: ../FL/Fl_PNM_Image.H flstring.h ../FL/Fl_Export.H fl_images_core.o: ../config.h -Fl_BMP_Image.o: ../FL/Fl_BMP_Image.H ../FL/Fl_Image.H ../FL/fl_utf8.h -Fl_BMP_Image.o: ../config.h +Fl_BMP_Image.o: ../FL/Fl_BMP_Image.H ../FL/Fl_Image.H ../FL/Enumerations.H +Fl_BMP_Image.o: ../FL/Fl_Export.H ../FL/fl_types.h ../FL/fl_utf8.h ../FL/Fl.H +Fl_BMP_Image.o: ../FL/fl_utf8.h ../config.h Fl_File_Icon2.o: ../FL/fl_utf8.h flstring.h ../FL/Fl_Export.H ../config.h Fl_File_Icon2.o: ../FL/math.h ../FL/Fl_File_Icon.H ../FL/Fl.H ../FL/fl_utf8.h -Fl_File_Icon2.o: ../FL/Fl_Export.H ../FL/fl_types.h ../FL/Xutf8.h -Fl_File_Icon2.o: ../FL/Enumerations.H ../FL/Fl_Shared_Image.H -Fl_File_Icon2.o: ../FL/Fl_Image.H ../FL/Fl_Widget.H ../FL/fl_draw.H ../FL/x.H -Fl_File_Icon2.o: ../FL/Fl_Window.H ../FL/Enumerations.H ../FL/Fl_Window.H -Fl_File_Icon2.o: ../FL/Fl_Group.H ../FL/Fl_Widget.H ../FL/Fl_Device.H +Fl_File_Icon2.o: ../FL/Fl_Export.H ../FL/fl_types.h ../FL/Enumerations.H +Fl_File_Icon2.o: ../FL/Fl_Shared_Image.H ../FL/Fl_Image.H ../FL/Fl_Widget.H +Fl_File_Icon2.o: ../FL/fl_draw.H ../FL/x.H ../FL/Fl_Window.H +Fl_File_Icon2.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Group.H +Fl_File_Icon2.o: ../FL/Fl_Widget.H ../FL/Fl_Bitmap.H ../FL/Fl_Device.H Fl_File_Icon2.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H Fl_File_Icon2.o: ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H Fl_File_Icon2.o: ../FL/filename.H Fl_GIF_Image.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h -Fl_GIF_Image.o: ../FL/Xutf8.h ../FL/Enumerations.H ../FL/Fl_GIF_Image.H -Fl_GIF_Image.o: ../FL/Fl_Pixmap.H ../FL/Fl_Image.H ../FL/fl_utf8.h flstring.h -Fl_GIF_Image.o: ../FL/Fl_Export.H ../config.h +Fl_GIF_Image.o: ../FL/Enumerations.H ../FL/Fl_GIF_Image.H ../FL/Fl_Pixmap.H +Fl_GIF_Image.o: ../FL/Fl_Image.H ../FL/fl_utf8.h flstring.h ../FL/Fl_Export.H +Fl_GIF_Image.o: ../config.h Fl_Help_Dialog.o: ../FL/Fl_Help_Dialog.H ../FL/Fl.H ../FL/fl_utf8.h -Fl_Help_Dialog.o: ../FL/Fl_Export.H ../FL/fl_types.h ../FL/Xutf8.h -Fl_Help_Dialog.o: ../FL/Enumerations.H ../FL/Fl_Double_Window.H -Fl_Help_Dialog.o: ../FL/Fl_Window.H ../FL/Fl_Group.H ../FL/Fl_Button.H -Fl_Help_Dialog.o: ../FL/Fl_Widget.H ../FL/Fl_Input.H ../FL/Fl_Input_.H -Fl_Help_Dialog.o: ../FL/Fl_Box.H ../FL/Fl_Help_View.H ../FL/Fl.H -Fl_Help_Dialog.o: ../FL/Fl_Group.H ../FL/Fl_Scrollbar.H ../FL/Fl_Slider.H -Fl_Help_Dialog.o: ../FL/Fl_Valuator.H ../FL/fl_draw.H ../FL/x.H -Fl_Help_Dialog.o: ../FL/Enumerations.H ../FL/Fl_Window.H ../FL/Fl_Device.H +Fl_Help_Dialog.o: ../FL/Fl_Export.H ../FL/fl_types.h ../FL/Enumerations.H +Fl_Help_Dialog.o: ../FL/Fl_Double_Window.H ../FL/Fl_Window.H ../FL/Fl_Group.H +Fl_Help_Dialog.o: ../FL/Fl_Button.H ../FL/Fl_Widget.H ../FL/Fl_Input.H +Fl_Help_Dialog.o: ../FL/Fl_Input_.H ../FL/Fl_Box.H ../FL/Fl_Help_View.H +Fl_Help_Dialog.o: ../FL/Fl.H ../FL/Fl_Group.H ../FL/Fl_Scrollbar.H +Fl_Help_Dialog.o: ../FL/Fl_Slider.H ../FL/Fl_Valuator.H ../FL/fl_draw.H +Fl_Help_Dialog.o: ../FL/x.H ../FL/Enumerations.H ../FL/Fl_Window.H +Fl_Help_Dialog.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Device.H Fl_Help_Dialog.o: ../FL/Fl_Plugin.H ../FL/Fl_Preferences.H ../FL/Fl_Image.H -Fl_Help_Dialog.o: ../FL/Fl_Bitmap.H ../FL/Fl_Image.H ../FL/Fl_Pixmap.H -Fl_Help_Dialog.o: ../FL/Fl_RGB_Image.H ../FL/Fl_Shared_Image.H -Fl_Help_Dialog.o: ../FL/filename.H flstring.h ../FL/Fl_Export.H ../config.h -Fl_Help_Dialog.o: ../FL/fl_ask.H -Fl_JPEG_Image.o: ../FL/Fl_JPEG_Image.H ../FL/Fl_Image.H -Fl_JPEG_Image.o: ../FL/Fl_Shared_Image.H ../FL/fl_utf8.h ../config.h +Fl_Help_Dialog.o: ../FL/Fl_Bitmap.H ../FL/Fl_Pixmap.H ../FL/Fl_RGB_Image.H +Fl_Help_Dialog.o: ../FL/Fl_Shared_Image.H ../FL/filename.H flstring.h +Fl_Help_Dialog.o: ../FL/Fl_Export.H ../config.h ../FL/fl_ask.H +Fl_JPEG_Image.o: ../FL/Fl_JPEG_Image.H ../FL/Fl_Image.H ../FL/Enumerations.H +Fl_JPEG_Image.o: ../FL/Fl_Export.H ../FL/fl_types.h ../FL/Fl_Shared_Image.H +Fl_JPEG_Image.o: ../FL/fl_utf8.h ../FL/Fl.H ../FL/fl_utf8.h ../config.h Fl_PNG_Image.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h -Fl_PNG_Image.o: ../FL/Xutf8.h ../FL/Enumerations.H ../FL/Fl_PNG_Image.H -Fl_PNG_Image.o: ../FL/Fl_Image.H ../FL/Fl_Shared_Image.H ../config.h -Fl_PNG_Image.o: ../FL/fl_utf8.h +Fl_PNG_Image.o: ../FL/Enumerations.H ../FL/Fl_PNG_Image.H ../FL/Fl_Image.H +Fl_PNG_Image.o: ../FL/Fl_Shared_Image.H ../config.h ../FL/fl_utf8.h Fl_PNM_Image.o: ../FL/Fl.H ../FL/fl_utf8.h ../FL/Fl_Export.H ../FL/fl_types.h -Fl_PNM_Image.o: ../FL/Xutf8.h ../FL/Enumerations.H ../FL/Fl_PNM_Image.H -Fl_PNM_Image.o: ../FL/Fl_Image.H ../FL/fl_utf8.h flstring.h ../FL/Fl_Export.H -Fl_PNM_Image.o: ../config.h +Fl_PNM_Image.o: ../FL/Enumerations.H ../FL/Fl_PNM_Image.H ../FL/Fl_Image.H +Fl_PNM_Image.o: ../FL/fl_utf8.h flstring.h ../FL/Fl_Export.H ../config.h flstring.o: flstring.h ../FL/Fl_Export.H ../config.h -scandir.o: flstring.h ../FL/Fl_Export.H ../config.h -numericsort.o: ../config.h +scandir.o: ../config.h +numericsort.o: ../config.h ../FL/filename.H vsnprintf.o: flstring.h ../FL/Fl_Export.H ../config.h fl_utf.o: ../FL/fl_utf8.h xutf8/mk_wcwidth.c xutf8/case.o: xutf8/headers/case.h +xutf8/is_right2left.o: Xutf8.h xutf8/is_spacing.o: xutf8/headers/spacing.h -xutf8/keysym2Ucs.o: ../FL/Xutf8.h xutf8/imKStoUCS.c xutf8/Xlibint.h -xutf8/keysym2Ucs.o: xutf8/Ximint.h -xutf8/utf8Input.o: ../config.h ../FL/Xutf8.h xutf8/lcUniConv/big5.h +xutf8/keysym2Ucs.o: Xutf8.h xutf8/imKStoUCS.c xutf8/Xlibint.h xutf8/Ximint.h +xutf8/utf8Input.o: ../config.h Xutf8.h xutf8/lcUniConv/big5.h xutf8/utf8Input.o: xutf8/lcUniConv/gb2312.h xutf8/lcUniConv/cp936ext.h xutf8/utf8Input.o: xutf8/lcUniConv/jisx0201.h xutf8/lcUniConv/jisx0208.h xutf8/utf8Input.o: xutf8/lcUniConv/jisx0212.h xutf8/lcUniConv/ksc5601.h -xutf8/utf8Utils.o: ../FL/Xutf8.h -xutf8/utf8Wrap.o: ../FL/Xutf8.h xutf8/ucs2fontmap.c -xutf8/utf8Wrap.o: xutf8/lcUniConv/cp936ext.h xutf8/lcUniConv/big5.h -xutf8/utf8Wrap.o: xutf8/lcUniConv/gb2312.h xutf8/lcUniConv/iso8859_10.h -xutf8/utf8Wrap.o: xutf8/lcUniConv/iso8859_11.h xutf8/lcUniConv/iso8859_13.h -xutf8/utf8Wrap.o: xutf8/lcUniConv/iso8859_14.h xutf8/lcUniConv/iso8859_15.h -xutf8/utf8Wrap.o: xutf8/lcUniConv/iso8859_2.h xutf8/lcUniConv/iso8859_3.h -xutf8/utf8Wrap.o: xutf8/lcUniConv/iso8859_4.h xutf8/lcUniConv/iso8859_5.h -xutf8/utf8Wrap.o: xutf8/lcUniConv/iso8859_6.h xutf8/lcUniConv/iso8859_7.h -xutf8/utf8Wrap.o: xutf8/lcUniConv/iso8859_8.h xutf8/lcUniConv/iso8859_9.h -xutf8/utf8Wrap.o: xutf8/lcUniConv/jisx0201.h xutf8/lcUniConv/jisx0208.h -xutf8/utf8Wrap.o: xutf8/lcUniConv/jisx0212.h xutf8/lcUniConv/koi8_r.h -xutf8/utf8Wrap.o: xutf8/lcUniConv/koi8_u.h xutf8/lcUniConv/ksc5601.h -xutf8/utf8Wrap.o: xutf8/lcUniConv/cp1251.h xutf8/headers/symbol_.h -xutf8/utf8Wrap.o: xutf8/headers/dingbats_.h +xutf8/utf8Utils.o: Xutf8.h +xutf8/utf8Wrap.o: Xutf8.h xutf8/ucs2fontmap.c xutf8/lcUniConv/cp936ext.h +xutf8/utf8Wrap.o: xutf8/lcUniConv/big5.h xutf8/lcUniConv/gb2312.h +xutf8/utf8Wrap.o: xutf8/lcUniConv/iso8859_10.h xutf8/lcUniConv/iso8859_11.h +xutf8/utf8Wrap.o: xutf8/lcUniConv/iso8859_13.h xutf8/lcUniConv/iso8859_14.h +xutf8/utf8Wrap.o: xutf8/lcUniConv/iso8859_15.h xutf8/lcUniConv/iso8859_2.h +xutf8/utf8Wrap.o: xutf8/lcUniConv/iso8859_3.h xutf8/lcUniConv/iso8859_4.h +xutf8/utf8Wrap.o: xutf8/lcUniConv/iso8859_5.h xutf8/lcUniConv/iso8859_6.h +xutf8/utf8Wrap.o: xutf8/lcUniConv/iso8859_7.h xutf8/lcUniConv/iso8859_8.h +xutf8/utf8Wrap.o: xutf8/lcUniConv/iso8859_9.h xutf8/lcUniConv/jisx0201.h +xutf8/utf8Wrap.o: xutf8/lcUniConv/jisx0208.h xutf8/lcUniConv/jisx0212.h +xutf8/utf8Wrap.o: xutf8/lcUniConv/koi8_r.h xutf8/lcUniConv/koi8_u.h +xutf8/utf8Wrap.o: xutf8/lcUniConv/ksc5601.h xutf8/lcUniConv/cp1251.h +xutf8/utf8Wrap.o: xutf8/headers/symbol_.h xutf8/headers/dingbats_.h diff --git a/src/mediumarrow.h b/src/mediumarrow.h index 8a1fe8c..a25f728 100644 --- a/src/mediumarrow.h +++ b/src/mediumarrow.h @@ -1,6 +1,6 @@ #define mediumarrow_width 16 #define mediumarrow_height 16 -static unsigned char mediumarrow_bits[] = { +static const unsigned char mediumarrow_bits[] = { 0x40, 0x00, 0x60, 0x00, 0x70, 0x00, 0x78, 0x00, 0xfc, 0x3f, 0x78, 0x00, 0x70, 0x00, 0x60, 0x02, 0x40, 0x06, 0x00, 0x0e, 0x00, 0x1e, 0xfc, 0x3f, 0x00, 0x1e, 0x00, 0x0e, 0x00, 0x06, 0x00, 0x02}; diff --git a/src/numericsort.c b/src/numericsort.c index 84172a3..bd37d6e 100644 --- a/src/numericsort.c +++ b/src/numericsort.c @@ -1,5 +1,5 @@ /* - * "$Id: numericsort.c 8864 2011-07-19 04:49:30Z greg.ercolano $" + * "$Id: numericsort.c 10236 2014-08-21 12:29:48Z cand $" * * Numeric sorting routine for the Fast Light Tool Kit (FLTK). * @@ -39,10 +39,10 @@ # include <ndir.h> # endif /* HAVE_NDIR_H */ # endif /* HAVE_DIRENT_H */ -#else /* For WIN32 variants */ -# include <FL/filename.H> #endif /* !WIN32 || __CYGWIN__ */ +#include <FL/filename.H> + /* * 'numericsort()' - Compare two directory entries, possibly with * a case-insensitive comparison... @@ -98,5 +98,5 @@ int fl_numericsort(struct dirent **A, struct dirent **B) { } /* - * End of "$Id: numericsort.c 8864 2011-07-19 04:49:30Z greg.ercolano $". + * End of "$Id: numericsort.c 10236 2014-08-21 12:29:48Z cand $". */ diff --git a/src/print_panel.cxx b/src/print_panel.cxx index 478b7b5..ec622ca 100644 --- a/src/print_panel.cxx +++ b/src/print_panel.cxx @@ -1,5 +1,5 @@ // -// "$Id: print_panel.cxx 9158 2011-10-29 14:50:04Z manolo $" +// "$Id: print_panel.cxx 10234 2014-08-21 12:18:32Z cand $" // // Print panel for the Fast Light Tool Kit (FLTK). // @@ -110,7 +110,7 @@ static void cb_print_properties_panel(Fl_Double_Window*, void*) { print_update_status(); } -static Fl_Menu_Item menu_print_page_size[] = { +static const Fl_Menu_Item menu_print_page_size[] = { {"Letter", 0, 0, 0, 0, FL_NORMAL_LABEL, 0, 14, 0}, {"A4", 0, 0, 0, 0, FL_NORMAL_LABEL, 0, 14, 0}, {"Legal", 0, 0, 0, 0, FL_NORMAL_LABEL, 0, 14, 0}, @@ -124,7 +124,7 @@ static Fl_Menu_Item menu_print_page_size[] = { }; #include <FL/Fl_Pixmap.H> -static const char *idata_print_color[] = { +static const char * const idata_print_color[] = { "24 24 17 1", " \tc None", ".\tc #FFFF00", @@ -170,7 +170,7 @@ static const char *idata_print_color[] = { }; static Fl_Pixmap image_print_color(idata_print_color); -static const char *idata_print_gray[] = { +static const char * const idata_print_gray[] = { "24 24 17 1", " \tc None", ".\tc #E3E3E3", @@ -591,5 +591,5 @@ void print_update_status() { } // -// End of "$Id: print_panel.cxx 9158 2011-10-29 14:50:04Z manolo $". +// End of "$Id: print_panel.cxx 10234 2014-08-21 12:18:32Z cand $". // diff --git a/src/ps_image.cxx b/src/ps_image.cxx index 35d0d0e..41dc299 100644 --- a/src/ps_image.cxx +++ b/src/ps_image.cxx @@ -185,72 +185,38 @@ static inline uchar swap_byte(const uchar b) { extern uchar **fl_mask_bitmap; +struct callback_data { + const uchar *data; + int D, LD; +}; -void Fl_PostScript_Graphics_Driver::draw_image(const uchar *data, int ix, int iy, int iw, int ih, int D, int LD) { - double x = ix, y = iy, w = iw, h = ih; - if (D<3){ //mono - draw_image_mono(data, ix, iy, iw, ih, D, LD); - return; - } +static void draw_image_cb(void *data, int x, int y, int w, uchar *buf) { + struct callback_data *cb_data; + const uchar *curdata; + cb_data = (struct callback_data*)data; + curdata = cb_data->data + x*cb_data->D + y*cb_data->LD; - int i,j, k; + memcpy(buf, curdata, w*cb_data->D); +} - fprintf(output,"save\n"); - const char * interpol; - if (lang_level_>1){ - if (interpolate_) - interpol="true"; - else - interpol="false"; - if (mask && lang_level_>2) - fprintf(output, "%g %g %g %g %i %i %i %i %s CIM\n", x , y+h , w , -h , iw , ih, mx, my, interpol); - else - fprintf(output, "%g %g %g %g %i %i %s CII\n", x , y+h , w , -h , iw , ih, interpol); - } else - fprintf(output , "%g %g %g %g %i %i CI", x , y+h , w , -h , iw , ih); +void Fl_PostScript_Graphics_Driver::draw_image(const uchar *data, int ix, int iy, int iw, int ih, int D, int LD) { + if (D<3){ //mono + draw_image_mono(data, ix, iy, iw, ih, D, LD); + return; + } + struct callback_data cb_data; if (!LD) LD = iw*D; - uchar *curmask=mask; - - for (j=0; j<ih;j++){ - if (mask){ - - for (k=0;k<my/ih;k++){ - for (i=0; i<((mx+7)/8);i++){ - if (!(i%80)) fprintf(output, "\n"); - fprintf(output, "%.2x",swap_byte(*curmask)); - curmask++; - } - fprintf(output,"\n"); - } - } - const uchar *curdata=data+j*LD; - for (i=0 ; i<iw ; i++) { - uchar r = curdata[0]; - uchar g = curdata[1]; - uchar b = curdata[2]; - if (lang_level_<3 && D>3) { //can do mixing using bg_* colors) - unsigned int a2 = curdata[3]; //must be int - unsigned int a = 255-a2; - r = (a2 * r + bg_r * a)/255; - g = (a2 * g + bg_g * a)/255; - b = (a2 * b + bg_b * a)/255; - } - if (!(i%40)) fprintf(output, "\n"); - fprintf(output, "%.2x%.2x%.2x", r, g, b); - curdata +=D; - } - fprintf(output,"\n"); - - } - - fprintf(output," >\nrestore\n" ); + cb_data.data = data; + cb_data.D = D; + cb_data.LD = LD; + draw_image(draw_image_cb, &cb_data, ix, iy, iw, ih, D); } void Fl_PostScript_Graphics_Driver::draw_image(Fl_Draw_Image_Cb call, void *data, int ix, int iy, int iw, int ih, int D) { @@ -325,6 +291,14 @@ void Fl_PostScript_Graphics_Driver::draw_image(Fl_Draw_Image_Cb call, void *data uchar g = curdata[1]; uchar b = curdata[2]; + if (lang_level_<3 && D>3) { //can do mixing using bg_* colors) + unsigned int a2 = curdata[3]; //must be int + unsigned int a = 255-a2; + r = (a2 * r + bg_r * a)/255; + g = (a2 * g + bg_g * a)/255; + b = (a2 * b + bg_b * a)/255; + } + if (!(i%40)) fputs("\n", output); fprintf(output, "%.2x%.2x%.2x", r, g, b); diff --git a/src/scandir.c b/src/scandir.c index e39c6ca..27d40dc 100644 --- a/src/scandir.c +++ b/src/scandir.c @@ -1,10 +1,10 @@ /* - * "$Id: scandir.c 9210 2011-12-21 10:42:14Z ianmacarthur $" + * "$Id: scandir.c 9858 2013-04-05 14:14:08Z manolo $" * - * This is a placekeeper stub that puuls in scandir implementations for host + * This is a placekeeper stub that pulls in scandir implementations for host * systems that do not provide a compatible one natively * - * Copyright 1998-2010 by Bill Spitzak and others. + * Copyright 1998-2013 by Bill Spitzak and others. * * This library is free software. Distribution and use rights are outlined in * the file "COPYING" which should have been included with this file. If this @@ -21,42 +21,12 @@ #if defined(WIN32) && !defined(__CYGWIN__) # include "scandir_win32.c" #else - -# include "flstring.h" - -/* NOTE: Most (all?) modern non-WIN32 hosts DO have a usable scandir */ -# if !HAVE_SCANDIR -# include <stdlib.h> -# include <sys/types.h> -# include <errno.h> - -# if HAVE_DIRENT_H -# include <dirent.h> -# define NAMLEN(dirent) strlen((dirent)->d_name) -# else /* HAVE_DIRENT_H */ -# define dirent direct -# define NAMLEN(dirent) (dirent)->d_namlen -# if HAVE_SYS_NDIR_H -# include <sys/ndir.h> -# endif /* HAVE_SYS_NDIR_H */ -# if HAVE_SYS_DIR_H -# include <sys/dir.h> -# endif /* HAVE_SYS_DIR_H */ -# if HAVE_NDIR_H -# include <ndir.h> -# endif /* HAVE_NDIR_H */ -# endif - -/* This warning added to help identify any non-WIN32 hosts that actually try to use - * our "private" implementation of the scandir function, which was suspect... */ -# if defined(__GNUC__) -# warning Attempting to use the deprecated scandir() replacement function -# endif /*__GNUC__*/ -# error No compatible scandir implementation found (STR 2687 applies!) - -# endif /* !HAVE_SCANDIR */ +# include <config.h> +# ifndef HAVE_SCANDIR +# include "scandir_posix.c" +# endif /* HAVE_SCANDIR */ #endif /* - * End of "$Id: scandir.c 9210 2011-12-21 10:42:14Z ianmacarthur $". + * End of "$Id: scandir.c 9858 2013-04-05 14:14:08Z manolo $". */ diff --git a/src/scandir_posix.c b/src/scandir_posix.c new file mode 100644 index 0000000..f032d7f --- /dev/null +++ b/src/scandir_posix.c @@ -0,0 +1,205 @@ +/* + * "$Id: scandir_posix.c 9832 2013-03-06 22:15:01Z ianmacarthur $" + * + * This implementation of 'scandir()' is intended to be POSIX.1-2008 compliant. + * A POSIX.1-1990 compliant system is required as minimum base. + * Note: + * The 'const' declarations were removed to match FLTK 1.3 wrapper (STR #2931) + * + * Copyright (c) 2013 by Michael Baeuerle + * + * This library is free software. Distribution and use rights are outlined in + * the file "COPYING" which should have been included with this file. If this + * file is missing or damaged, see the license at: + * + * http://www.fltk.org/COPYING.php + * + * Please report all bugs and problems on the following page: + * + * http://www.fltk.org/str.php + * + * It is required that 'SIZE_MAX' is at least 'INT_MAX'. + * Don't use a C++ compiler to build this module. + * + * The build system must define 'HAVE_PTHREAD' and link against a potentially + * required library to switch this implementation into thread-safe mode. + * The POSIX.1c-1995 extension is required if 'HAVE_PTHREAD' is defined. + * + * Note: + * In theory, a system that provide threads should also provide 'readdir_r()', + * a thread-safe version of 'readdir()'. In reality this is not always the case. + * In addition there may be a race condition that can lead to a buffer overflow: + * http://womble.decadent.org.uk/readdir_r-advisory.html + */ + +#ifndef HAVE_PTHREAD + /* Switch system headers into POSIX.1-1990 mode */ +# define _POSIX_SOURCE +#else /* HAVE_PTHREAD */ + /* Switch system headers into POSIX.1c-1995 mode */ +# define _POSIX_C_SOURCE 199506L +#endif /* HAVE_PTHREAD */ + +#include <sys/types.h> /* XPG2 require this for '*dir()' functions */ +#include <dirent.h> +#include <errno.h> +#include <stdlib.h> /* For 'malloc()', 'realloc()' and 'qsort()' */ +#include <stddef.h> /* For 'offsetof()', 'NULL' and 'size_t' */ +#include <limits.h> /* For 'INT_MAX' */ +#include <string.h> /* For 'memcpy()' */ +#if defined(HAVE_PTHREAD) && defined(HAVE_PTHREAD_H) +# include <pthread.h> +#endif /* HAVE_PTHREAD */ + + +/* ========================================================================== */ +/* At startup allocate memory for this number of result array elements */ +#define ENTRIES_MIN (size_t) 32 + + +/* ========================================================================== */ +#ifdef HAVE_PTHREAD +static pthread_mutex_t scandir_mutex = PTHREAD_MUTEX_INITIALIZER; +#endif /* HAVE_PTHREAD */ + + +/* ========================================================================== */ +/* + * This function reads the next entry from the directory referenced by 'dirp', + * allocate a buffer for the entry and copy it into this buffer. + * A pointer to this buffer is written to 'entryp' and the size of the buffer is + * written to 'len'. + * Success and a NULL pointer is returned for 'entryp' if there are no more + * entries in the directory. + * On sucess zero is returned and the caller is responsible for 'free()'ing the + * buffer after use. + * On error the return value is nonzero, 'entryp' and 'len' are invalid. + * + * Should be declared as 'static inline' if the compiler support that. + */ +static int +readentry(DIR *dirp, struct dirent **entryp, size_t *len) +{ + int result = -1; + struct dirent *e; + +#ifdef HAVE_PTHREAD + if (!pthread_mutex_lock(&scandir_mutex)) + { + /* Ensure that there is no code path that bypass the '_unlock()' call! */ +#endif /* HAVE_PTHREAD */ + errno = 0; + e = readdir(dirp); + if (NULL == e) + { + if (!errno) + { + /* No more entries in directory */ + *entryp = NULL; + *len = 0; + result = 0; + } + } + else + { + /* Entry found, allocate local buffer */ + *len = offsetof(struct dirent, d_name) + strlen(e->d_name) + (size_t) 1; + *entryp = (struct dirent *) malloc(*len); + if (NULL != *entryp) + { + memcpy((void *) *entryp, (void *) e, *len); + /* Force NUL termination at end of buffer */ + ((char *) *entryp)[*len - (size_t) 1] = 0; + result = 0; + } + } +#ifdef HAVE_PTHREAD + /* + * In a multithreading environment the systems dirent buffer may be shared + * between all threads. Therefore the mutex must stay locked until we have + * copied the data to our thread local buffer. + */ + pthread_mutex_unlock(&scandir_mutex); + } +#endif /* HAVE_PTHREAD */ + + return result; +} + + +/* ========================================================================== */ +int +fl_scandir(const char *dir, struct dirent ***namelist, + int (*sel)(struct dirent *), + int (*compar)(struct dirent **, struct dirent **)) +{ + int result = -1; + DIR *dirp; + size_t len, num = 0, max = ENTRIES_MIN; + struct dirent *entryp, **entries, **p; + + entries = (struct dirent **) malloc(sizeof(*entries) * max); + if (NULL != entries) + { + /* Open directory 'dir' (and verify that it really is a directory) */ + dirp = opendir(dir); + if (NULL != dirp) + { + /* Read next directory entry */ + while (!readentry(dirp, &entryp, &len)) + { + if (NULL == entryp) + { + /* EOD => Return number of directory entries */ + result = (int) num; + break; + } + /* Apply select function if there is one provided */ + if (NULL != sel) { if (!sel(entryp)) continue; } + entries[num++] = entryp; + if (num >= max) + { + /* Allocate exponentially increasing sized memory chunks */ + if (INT_MAX / 2 >= (int) max) { max *= (size_t) 2; } + else + { + errno = ENOMEM; + break; + } + p = (struct dirent **) realloc((void *) entries, + sizeof(*entries) * max); + if (NULL != p) { entries = p; } + else break; + } + } + closedir(dirp); + /* + * A standard compliant 'closedir()' is allowed to fail with 'EINTR', but + * the state of the directory structure is undefined in this case. + * Therefore we ignore the return value because we can't call 'closedir()' + * again and must hope that the system has released all ressources. + */ + } + /* Sort entries in array if there is a compare function provided */ + if (NULL != compar) + { + qsort((void *) entries, num, sizeof(*entries), + (int (*)(const void *, const void *)) compar); + } + *namelist = entries; + } + + /* Check for error */ + if (-1 == result) + { + /* Free all memory we have allocated */ + while (num--) { free(entries[num]); } + free(entries); + } + + return result; +} + +/* + * End of "$Id: scandir_posix.c 9832 2013-03-06 22:15:01Z ianmacarthur $". + */ diff --git a/src/scandir_win32.c b/src/scandir_win32.c index 9f2e582..adf21c1 100644 --- a/src/scandir_win32.c +++ b/src/scandir_win32.c @@ -1,5 +1,5 @@ /* - * "$Id: scandir_win32.c 9325 2012-04-05 05:12:30Z fabien $" + * "$Id: scandir_win32.c 10082 2014-01-25 23:04:36Z AlbrechtS $" * * WIN32 scandir function for the Fast Light Tool Kit (FLTK). * @@ -44,7 +44,7 @@ int fl_scandir(const char *dirname, struct dirent ***namelist, /* #warning FIXME This probably needs to be MORE UTF8 aware now */ /* #endif */ for (d = findIn; *d; d++) if (*d=='/') *d='\\'; - if ((len==0)) { strcpy(findIn, ".\\*"); } + if (len==0) { strcpy(findIn, ".\\*"); } if ((len==2)&&findIn[1]==':'&&isalpha(findIn[0])) { *d++ = '\\'; *d = 0; } if ((len==1)&& (d[-1]=='.')) { strcpy(findIn, ".\\*"); is_dir = 1; } if ((len>0) && (d[-1]=='\\')) { *d++ = '*'; *d = 0; is_dir = 1; } @@ -122,5 +122,5 @@ int fl_scandir(const char *dirname, struct dirent ***namelist, #endif /* - * End of "$Id: scandir_win32.c 9325 2012-04-05 05:12:30Z fabien $". + * End of "$Id: scandir_win32.c 10082 2014-01-25 23:04:36Z AlbrechtS $". */ diff --git a/src/screen_xywh.cxx b/src/screen_xywh.cxx index bae6a2f..67f7ed7 100644 --- a/src/screen_xywh.cxx +++ b/src/screen_xywh.cxx @@ -1,5 +1,5 @@ // -// "$Id: screen_xywh.cxx 9299 2012-03-23 16:47:53Z manolo $" +// "$Id: screen_xywh.cxx 10228 2014-08-21 08:14:19Z cand $" // // Screen/monitor bounding box API for the Fast Light Tool Kit (FLTK). // @@ -58,7 +58,7 @@ static BOOL CALLBACK screen_cb(HMONITOR mon, HDC, LPRECT r, LPARAM) { mi.cbSize = sizeof(mi); // GetMonitorInfo(mon, &mi); -// (but we use our self-aquired function pointer instead) +// (but we use our self-acquired function pointer instead) if (fl_gmi(mon, &mi)) { screens[num_screens] = mi.rcMonitor; // If we also want to record the work area, we would also store mi.rcWork at this point @@ -97,7 +97,7 @@ static void screen_init() { if (fl_gmi) { // We have GetMonitorInfoA, enumerate all the screens... // EnumDisplayMonitors(0,0,screen_cb,0); -// (but we use our self-aquired function pointer instead) +// (but we use our self-acquired function pointer instead) // NOTE: num_screens is incremented in screen_cb so we must first reset it here... num_screens = 0; fl_edm(0, 0, screen_cb, 0); @@ -135,10 +135,9 @@ static void screen_init() { CGSize s = CGDisplayScreenSize(displays[i]); // from 10.3 dpi_h[i] = screens[i].width / (s.width/25.4); dpi_v[i] = screens[i].height / (s.height/25.4); - } - else { + } else { dpi_h[i] = dpi_v[i] = 75.; - } + } } num_screens = count; } @@ -149,11 +148,11 @@ static void screen_init() { # include <X11/extensions/Xinerama.h> #endif typedef struct { - short x_org; - short y_org; - short width; - short height; - } FLScreenInfo; + short x_org; + short y_org; + short width; + short height; +} FLScreenInfo; static FLScreenInfo screens[MAX_SCREENS]; static float dpi[MAX_SCREENS][2]; @@ -215,21 +214,6 @@ int Fl::screen_count() { return num_screens ? num_screens : 1; } -static int find_screen_with_point(int mx, int my) { - int screen = 0; - if (num_screens < 0) screen_init(); - - for (int i = 0; i < num_screens; i ++) { - int sx, sy, sw, sh; - Fl::screen_xywh(sx, sy, sw, sh, i); - if ((mx >= sx) && (mx < (sx+sw)) && (my >= sy) && (my < (sy+sh))) { - screen = i; - break; - } - } - return screen; -} - /** Gets the bounding box of a screen that contains the specified screen position \p mx, \p my @@ -237,7 +221,7 @@ static int find_screen_with_point(int mx, int my) { \param[in] mx, my the absolute screen position */ void Fl::screen_xywh(int &X, int &Y, int &W, int &H, int mx, int my) { - screen_xywh(X, Y, W, H, find_screen_with_point(mx, my)); + screen_xywh(X, Y, W, H, screen_num(mx, my)); } @@ -248,7 +232,7 @@ void Fl::screen_xywh(int &X, int &Y, int &W, int &H, int mx, int my) { \param[in] mx, my the absolute screen position */ void Fl::screen_work_area(int &X, int &Y, int &W, int &H, int mx, int my) { - screen_work_area(X, Y, W, H, find_screen_with_point(mx, my)); + screen_work_area(X, Y, W, H, screen_num(mx, my)); } /** @@ -273,10 +257,9 @@ void Fl::screen_work_area(int &X, int &Y, int &W, int &H, int n) { Y = Fl::y(); W = Fl::w(); H = Fl::h(); - } - else { // for other screens, work area is full screen, + } else { // for other screens, work area is full screen, screen_xywh(X, Y, W, H, n); - } + } #endif } @@ -307,10 +290,10 @@ void Fl::screen_xywh(int &X, int &Y, int &W, int &H, int n) { H = GetSystemMetrics(SM_CYSCREEN); } #elif defined(__APPLE__) - X = screens[n].x; - Y = screens[n].y; - W = screens[n].width; - H = screens[n].height; + X = screens[n].x; + Y = screens[n].y; + W = screens[n].width; + H = screens[n].height; #else if (num_screens > 0) { X = screens[n].x_org; @@ -321,8 +304,41 @@ void Fl::screen_xywh(int &X, int &Y, int &W, int &H, int n) { #endif // WIN32 } +/** + Gets the screen bounding rect for the screen + which intersects the most with the rectangle + defined by \p mx, \p my, \p mw, \p mh. + \param[out] X,Y,W,H the corresponding screen bounding box + \param[in] mx, my, mw, mh the rectangle to search for intersection with + \see void screen_xywh(int &X, int &Y, int &W, int &H, int n) + */ +void Fl::screen_xywh(int &X, int &Y, int &W, int &H, int mx, int my, int mw, int mh) { + screen_xywh(X, Y, W, H, screen_num(mx, my, mw, mh)); +} + +/** + Gets the screen number of a screen + that contains the specified screen position \p x, \p y + \param[in] x, y the absolute screen position +*/ +int Fl::screen_num(int x, int y) { + int screen = 0; + if (num_screens < 0) screen_init(); + + for (int i = 0; i < num_screens; i ++) { + int sx, sy, sw, sh; + Fl::screen_xywh(sx, sy, sw, sh, i); + if ((x >= sx) && (x < (sx+sw)) && (y >= sy) && (y < (sy+sh))) { + screen = i; + break; + } + } + return screen; +} + +// Return the number of pixels common to the two rectangular areas static inline float fl_intersection(int x1, int y1, int w1, int h1, - int x2, int y2, int w2, int h2) { + int x2, int y2, int w2, int h2) { if(x1+w1 < x2 || x2+w2 < x1 || y1+h1 < y2 || y2+h2 < y1) return 0.; int int_left = x1 > x2 ? x1 : x2; @@ -333,30 +349,26 @@ static inline float fl_intersection(int x1, int y1, int w1, int h1, } /** - Gets the screen bounding rect for the screen + Gets the screen number for the screen which intersects the most with the rectangle - defined by \p mx, \p my, \p mw, \p mh. - \param[out] X,Y,W,H the corresponding screen bounding box - \param[in] mx, my, mw, mh the rectangle to search for intersection with - \see void screen_xywh(int &X, int &Y, int &W, int &H, int n) + defined by \p x, \p y, \p w, \p h. + \param[in] x, y, w, h the rectangle to search for intersection with */ -void Fl::screen_xywh(int &X, int &Y, int &W, int &H, int mx, int my, int mw, int mh) { +int Fl::screen_num(int x, int y, int w, int h) { int best_screen = 0; float best_intersection = 0.; - for(int i = 0; i < Fl::screen_count(); i++) { + for (int i = 0; i < Fl::screen_count(); i++) { int sx, sy, sw, sh; Fl::screen_xywh(sx, sy, sw, sh, i); - float sintersection = fl_intersection(mx, my, mw, mh, sx, sy, sw, sh); - if(sintersection > best_intersection) { + float sintersection = fl_intersection(x, y, w, h, sx, sy, sw, sh); + if (sintersection > best_intersection) { best_screen = i; best_intersection = sintersection; } } - screen_xywh(X, Y, W, H, best_screen); + return best_screen; } - - /** Gets the screen resolution in dots-per-inch for the given screen. \param[out] h, v horizontal and vertical resolution @@ -389,5 +401,5 @@ void Fl::screen_dpi(float &h, float &v, int n) // -// End of "$Id: screen_xywh.cxx 9299 2012-03-23 16:47:53Z manolo $". +// End of "$Id: screen_xywh.cxx 10228 2014-08-21 08:14:19Z cand $". // diff --git a/src/slowarrow.h b/src/slowarrow.h index 46a572c..4ad428a 100644 --- a/src/slowarrow.h +++ b/src/slowarrow.h @@ -1,6 +1,6 @@ #define slowarrow_width 16 #define slowarrow_height 16 -static unsigned char slowarrow_bits[] = { +static const unsigned char slowarrow_bits[] = { 0x40, 0x00, 0x40, 0x00, 0x60, 0x00, 0x60, 0x00, 0xf0, 0x0f, 0x60, 0x00, 0x60, 0x00, 0x40, 0x02, 0x40, 0x02, 0x00, 0x06, 0x00, 0x06, 0xf0, 0x0f, 0x00, 0x06, 0x00, 0x06, 0x00, 0x02, 0x00, 0x02}; diff --git a/src/tile.xpm b/src/tile.xpm index 872e0f7..1fa410c 100644 --- a/src/tile.xpm +++ b/src/tile.xpm @@ -4,7 +4,7 @@ static char tile_cmap[3][32] = { "o c #EFEFEF", ". c #E8E8E8" }; -static const char * tile_xpm[] = { +static const char * const tile_xpm[] = { "64 64 3 1", tile_cmap[0], tile_cmap[1], diff --git a/src/vsnprintf.c b/src/vsnprintf.c index be93ba6..bbf4229 100644 --- a/src/vsnprintf.c +++ b/src/vsnprintf.c @@ -1,5 +1,5 @@ /* - * "$Id: vsnprintf.c 9325 2012-04-05 05:12:30Z fabien $" + * "$Id: vsnprintf.c 10229 2014-08-21 12:01:46Z cand $" * * snprintf() and vsnprintf() functions for the Fast Light Tool Kit (FLTK). * @@ -28,6 +28,9 @@ extern "C" { #endif int fl_vsnprintf(char* buffer, size_t bufsize, const char* format, va_list ap) { +#if defined(HAVE_VSNPRINTF) && defined(__linux__) + return vsnprintf(buffer, bufsize, format, ap); +#else char *bufptr, /* Pointer to position in buffer */ *bufend, /* Pointer to end of buffer */ sign, /* Sign of format width */ @@ -251,6 +254,7 @@ int fl_vsnprintf(char* buffer, size_t bufsize, const char* format, va_list ap) { if (bufptr) *bufptr = '\0'; return (bytes); +#endif //HAVE_VSNPRINTF } int fl_snprintf(char* str, size_t size, const char* fmt, ...) { @@ -267,6 +271,6 @@ int fl_snprintf(char* str, size_t size, const char* fmt, ...) { #endif /* - * End of "$Id: vsnprintf.c 9325 2012-04-05 05:12:30Z fabien $". + * End of "$Id: vsnprintf.c 10229 2014-08-21 12:01:46Z cand $". */ diff --git a/src/xutf8/headers/dingbats_.h b/src/xutf8/headers/dingbats_.h index 9f1f225..a08bbf0 100644 --- a/src/xutf8/headers/dingbats_.h +++ b/src/xutf8/headers/dingbats_.h @@ -133,23 +133,23 @@ static const char unicode_to_dingbats_1b_0020[] = { }; static const char unicode_to_dingbats_1b_2192[] = { -/* U+2192 */ 0xD5, +/* U+2192 */ (char)0xD5, 0x00, -/* U+2194 */ 0xD6, -/* U+2195 */ 0xD7, +/* U+2194 */ (char)0xD6, +/* U+2195 */ (char)0xD7, }; static const char unicode_to_dingbats_1b_2460[] = { -/* U+2460 */ 0xAC, -/* U+2461 */ 0xAD, -/* U+2462 */ 0xAE, -/* U+2463 */ 0xAF, -/* U+2464 */ 0xB0, -/* U+2465 */ 0xB1, -/* U+2466 */ 0xB2, -/* U+2467 */ 0xB3, -/* U+2468 */ 0xB4, -/* U+2469 */ 0xB5, +/* U+2460 */ (char)0xAC, +/* U+2461 */ (char)0xAD, +/* U+2462 */ (char)0xAE, +/* U+2463 */ (char)0xAF, +/* U+2464 */ (char)0xB0, +/* U+2465 */ (char)0xB1, +/* U+2466 */ (char)0xB2, +/* U+2467 */ (char)0xB3, +/* U+2468 */ (char)0xB4, +/* U+2469 */ (char)0xB5, }; static const char unicode_to_dingbats_1b_25A0[] = { @@ -345,13 +345,13 @@ static const char unicode_to_dingbats_1b_25A0[] = { 0x00, 0x00, 0x00, -/* U+2660 */ 0xAB, +/* U+2660 */ (char)0xAB, 0x00, 0x00, -/* U+2663 */ 0xA8, +/* U+2663 */ (char)0xA8, 0x00, -/* U+2665 */ 0xAA, -/* U+2666 */ 0xA9, +/* U+2665 */ (char)0xAA, +/* U+2666 */ (char)0xA9, }; static const char unicode_to_dingbats_1b_2701[] = { @@ -451,115 +451,115 @@ static const char unicode_to_dingbats_1b_2701[] = { /* U+275E */ 0x7E, 0x00, 0x00, -/* U+2761 */ 0xA1, -/* U+2762 */ 0xA2, -/* U+2763 */ 0xA3, -/* U+2764 */ 0xA4, -/* U+2765 */ 0xA5, -/* U+2766 */ 0xA6, -/* U+2767 */ 0xA7, -0x00, -0x00, -0x00, -0x00, -0x00, -0x00, -0x00, -0x00, -0x00, -0x00, -0x00, -0x00, -0x00, -0x00, -/* U+2776 */ 0xB6, -/* U+2777 */ 0xB7, -/* U+2778 */ 0xB8, -/* U+2779 */ 0xB9, -/* U+277A */ 0xBA, -/* U+277B */ 0xBB, -/* U+277C */ 0xBC, -/* U+277D */ 0xBD, -/* U+277E */ 0xBE, -/* U+277F */ 0xBF, -/* U+2780 */ 0xC0, -/* U+2781 */ 0xC1, -/* U+2782 */ 0xC2, -/* U+2783 */ 0xC3, -/* U+2784 */ 0xC4, -/* U+2785 */ 0xC5, -/* U+2786 */ 0xC6, -/* U+2787 */ 0xC7, -/* U+2788 */ 0xC8, -/* U+2789 */ 0xC9, -/* U+278A */ 0xCA, -/* U+278B */ 0xCB, -/* U+278C */ 0xCC, -/* U+278D */ 0xCD, -/* U+278E */ 0xCE, -/* U+278F */ 0xCF, -/* U+2790 */ 0xD0, -/* U+2791 */ 0xD1, -/* U+2792 */ 0xD2, -/* U+2793 */ 0xD3, -/* U+2794 */ 0xD4, -0x00, -0x00, -0x00, -/* U+2798 */ 0xD8, -/* U+2799 */ 0xD9, -/* U+279A */ 0xDA, -/* U+279B */ 0xDB, -/* U+279C */ 0xDC, -/* U+279D */ 0xDD, -/* U+279E */ 0xDE, -/* U+279F */ 0xDF, -/* U+27A0 */ 0xE0, -/* U+27A1 */ 0xE1, -/* U+27A2 */ 0xE2, -/* U+27A3 */ 0xE3, -/* U+27A4 */ 0xE4, -/* U+27A5 */ 0xE5, -/* U+27A6 */ 0xE6, -/* U+27A7 */ 0xE7, -/* U+27A8 */ 0xE8, -/* U+27A9 */ 0xE9, -/* U+27AA */ 0xEA, -/* U+27AB */ 0xEB, -/* U+27AC */ 0xEC, -/* U+27AD */ 0xED, -/* U+27AE */ 0xEE, -/* U+27AF */ 0xEF, -0x00, -/* U+27B1 */ 0xF1, -/* U+27B2 */ 0xF2, -/* U+27B3 */ 0xF3, -/* U+27B4 */ 0xF4, -/* U+27B5 */ 0xF5, -/* U+27B6 */ 0xF6, -/* U+27B7 */ 0xF7, -/* U+27B8 */ 0xF8, -/* U+27B9 */ 0xF9, -/* U+27BA */ 0xFA, -/* U+27BB */ 0xFB, -/* U+27BC */ 0xFC, -/* U+27BD */ 0xFD, -/* U+27BE */ 0xFE, +/* U+2761 */ (char)0xA1, +/* U+2762 */ (char)0xA2, +/* U+2763 */ (char)0xA3, +/* U+2764 */ (char)0xA4, +/* U+2765 */ (char)0xA5, +/* U+2766 */ (char)0xA6, +/* U+2767 */ (char)0xA7, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +/* U+2776 */ (char)0xB6, +/* U+2777 */ (char)0xB7, +/* U+2778 */ (char)0xB8, +/* U+2779 */ (char)0xB9, +/* U+277A */ (char)0xBA, +/* U+277B */ (char)0xBB, +/* U+277C */ (char)0xBC, +/* U+277D */ (char)0xBD, +/* U+277E */ (char)0xBE, +/* U+277F */ (char)0xBF, +/* U+2780 */ (char)0xC0, +/* U+2781 */ (char)0xC1, +/* U+2782 */ (char)0xC2, +/* U+2783 */ (char)0xC3, +/* U+2784 */ (char)0xC4, +/* U+2785 */ (char)0xC5, +/* U+2786 */ (char)0xC6, +/* U+2787 */ (char)0xC7, +/* U+2788 */ (char)0xC8, +/* U+2789 */ (char)0xC9, +/* U+278A */ (char)0xCA, +/* U+278B */ (char)0xCB, +/* U+278C */ (char)0xCC, +/* U+278D */ (char)0xCD, +/* U+278E */ (char)0xCE, +/* U+278F */ (char)0xCF, +/* U+2790 */ (char)0xD0, +/* U+2791 */ (char)0xD1, +/* U+2792 */ (char)0xD2, +/* U+2793 */ (char)0xD3, +/* U+2794 */ (char)0xD4, +0x00, +0x00, +0x00, +/* U+2798 */ (char)0xD8, +/* U+2799 */ (char)0xD9, +/* U+279A */ (char)0xDA, +/* U+279B */ (char)0xDB, +/* U+279C */ (char)0xDC, +/* U+279D */ (char)0xDD, +/* U+279E */ (char)0xDE, +/* U+279F */ (char)0xDF, +/* U+27A0 */ (char)0xE0, +/* U+27A1 */ (char)0xE1, +/* U+27A2 */ (char)0xE2, +/* U+27A3 */ (char)0xE3, +/* U+27A4 */ (char)0xE4, +/* U+27A5 */ (char)0xE5, +/* U+27A6 */ (char)0xE6, +/* U+27A7 */ (char)0xE7, +/* U+27A8 */ (char)0xE8, +/* U+27A9 */ (char)0xE9, +/* U+27AA */ (char)0xEA, +/* U+27AB */ (char)0xEB, +/* U+27AC */ (char)0xEC, +/* U+27AD */ (char)0xED, +/* U+27AE */ (char)0xEE, +/* U+27AF */ (char)0xEF, +0x00, +/* U+27B1 */ (char)0xF1, +/* U+27B2 */ (char)0xF2, +/* U+27B3 */ (char)0xF3, +/* U+27B4 */ (char)0xF4, +/* U+27B5 */ (char)0xF5, +/* U+27B6 */ (char)0xF6, +/* U+27B7 */ (char)0xF7, +/* U+27B8 */ (char)0xF8, +/* U+27B9 */ (char)0xF9, +/* U+27BA */ (char)0xFA, +/* U+27BB */ (char)0xFB, +/* U+27BC */ (char)0xFC, +/* U+27BD */ (char)0xFD, +/* U+27BE */ (char)0xFE, }; static const char unicode_to_dingbats_1b_F8D7[] = { -/* U+F8D7 */ 0x80, -/* U+F8D8 */ 0x81, -/* U+F8D9 */ 0x82, -/* U+F8DA */ 0x83, -/* U+F8DB */ 0x84, -/* U+F8DC */ 0x85, -/* U+F8DD */ 0x86, -/* U+F8DE */ 0x87, -/* U+F8DF */ 0x88, -/* U+F8E0 */ 0x89, -/* U+F8E1 */ 0x8A, -/* U+F8E2 */ 0x8B, -/* U+F8E3 */ 0x8C, -/* U+F8E4 */ 0x8D, +/* U+F8D7 */ (char)0x80, +/* U+F8D8 */ (char)0x81, +/* U+F8D9 */ (char)0x82, +/* U+F8DA */ (char)0x83, +/* U+F8DB */ (char)0x84, +/* U+F8DC */ (char)0x85, +/* U+F8DD */ (char)0x86, +/* U+F8DE */ (char)0x87, +/* U+F8DF */ (char)0x88, +/* U+F8E0 */ (char)0x89, +/* U+F8E1 */ (char)0x8A, +/* U+F8E2 */ (char)0x8B, +/* U+F8E3 */ (char)0x8C, +/* U+F8E4 */ (char)0x8D, }; diff --git a/src/xutf8/headers/symbol_.h b/src/xutf8/headers/symbol_.h index a9d8fd3..481c5e7 100644 --- a/src/xutf8/headers/symbol_.h +++ b/src/xutf8/headers/symbol_.h @@ -141,12 +141,12 @@ static const char unicode_to_symbol_1b_0020[] = { 0x00, 0x00, 0x00, -/* U+00AC */ 0xD8, +/* U+00AC */ (char)0xD8, 0x00, 0x00, 0x00, -/* U+00B0 */ 0xB0, -/* U+00B1 */ 0xB1, +/* U+00B0 */ (char)0xB0, +/* U+00B1 */ (char)0xB1, 0x00, 0x00, 0x00, @@ -184,7 +184,7 @@ static const char unicode_to_symbol_1b_0020[] = { 0x00, 0x00, 0x00, -/* U+00D7 */ 0xB4, +/* U+00D7 */ (char)0xB4, 0x00, 0x00, 0x00, @@ -216,11 +216,11 @@ static const char unicode_to_symbol_1b_0020[] = { 0x00, 0x00, 0x00, -/* U+00F7 */ 0xB8, +/* U+00F7 */ (char)0xB8, }; static const char unicode_to_symbol_1b_0192[] = { -/* U+0192 */ 0xA6, +/* U+0192 */ (char)0xA6, }; static const char unicode_to_symbol_1b_0391[] = { @@ -289,7 +289,7 @@ static const char unicode_to_symbol_1b_0391[] = { 0x00, 0x00, /* U+03D1 */ 0x4A, -/* U+03D2 */ 0xA1, +/* U+03D2 */ (char)0xA1, 0x00, 0x00, /* U+03D5 */ 0x6A, @@ -297,11 +297,11 @@ static const char unicode_to_symbol_1b_0391[] = { }; static const char unicode_to_symbol_1b_2022[] = { -/* U+2022 */ 0xB7, +/* U+2022 */ (char)0xB7, 0x00, 0x00, 0x00, -/* U+2026 */ 0xBC, +/* U+2026 */ (char)0xBC, 0x00, 0x00, 0x00, @@ -313,8 +313,8 @@ static const char unicode_to_symbol_1b_2022[] = { 0x00, 0x00, 0x00, -/* U+2032 */ 0xA2, -/* U+2033 */ 0xB2, +/* U+2032 */ (char)0xA2, +/* U+2033 */ (char)0xB2, 0x00, 0x00, 0x00, @@ -331,7 +331,7 @@ static const char unicode_to_symbol_1b_2022[] = { 0x00, 0x00, 0x00, -/* U+2044 */ 0xA4, +/* U+2044 */ (char)0xA4, 0x00, 0x00, 0x00, @@ -435,7 +435,7 @@ static const char unicode_to_symbol_1b_2022[] = { 0x00, 0x00, 0x00, -/* U+20AC */ 0xA0, +/* U+20AC */ (char)0xA0, 0x00, 0x00, 0x00, @@ -536,18 +536,18 @@ static const char unicode_to_symbol_1b_2022[] = { 0x00, 0x00, 0x00, -/* U+2111 */ 0xC1, +/* U+2111 */ (char)0xC1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* U+2118 */ 0xC3, +/* U+2118 */ (char)0xC3, 0x00, 0x00, 0x00, -/* U+211C */ 0xC2, +/* U+211C */ (char)0xC2, 0x00, 0x00, 0x00, @@ -572,7 +572,7 @@ static const char unicode_to_symbol_1b_2022[] = { 0x00, 0x00, 0x00, -/* U+2135 */ 0xC0, +/* U+2135 */ (char)0xC0, 0x00, 0x00, 0x00, @@ -663,11 +663,11 @@ static const char unicode_to_symbol_1b_2022[] = { 0x00, 0x00, 0x00, -/* U+2190 */ 0xAC, -/* U+2191 */ 0xAD, -/* U+2192 */ 0xAE, -/* U+2193 */ 0xAF, -/* U+2194 */ 0xAB, +/* U+2190 */ (char)0xAC, +/* U+2191 */ (char)0xAD, +/* U+2192 */ (char)0xAE, +/* U+2193 */ (char)0xAF, +/* U+2194 */ (char)0xAB, 0x00, 0x00, 0x00, @@ -700,7 +700,7 @@ static const char unicode_to_symbol_1b_2022[] = { 0x00, 0x00, 0x00, -/* U+21B5 */ 0xBF, +/* U+21B5 */ (char)0xBF, 0x00, 0x00, 0x00, @@ -727,11 +727,11 @@ static const char unicode_to_symbol_1b_2022[] = { 0x00, 0x00, 0x00, -/* U+21D0 */ 0xDC, -/* U+21D1 */ 0xDD, -/* U+21D2 */ 0xDE, -/* U+21D3 */ 0xDF, -/* U+21D4 */ 0xDB, +/* U+21D0 */ (char)0xDC, +/* U+21D1 */ (char)0xDD, +/* U+21D2 */ (char)0xDE, +/* U+21D3 */ (char)0xDF, +/* U+21D4 */ (char)0xDB, 0x00, 0x00, 0x00, @@ -777,48 +777,48 @@ static const char unicode_to_symbol_1b_2022[] = { 0x00, /* U+2200 */ 0x22, 0x00, -/* U+2202 */ 0xB6, +/* U+2202 */ (char)0xB6, /* U+2203 */ 0x24, 0x00, -/* U+2205 */ 0xC6, +/* U+2205 */ (char)0xC6, /* U+2206 */ 0x44, -/* U+2207 */ 0xD1, -/* U+2208 */ 0xCE, -/* U+2209 */ 0xCF, +/* U+2207 */ (char)0xD1, +/* U+2208 */ (char)0xCE, +/* U+2209 */ (char)0xCF, 0x00, /* U+220B */ 0x27, 0x00, 0x00, 0x00, -/* U+220F */ 0xD5, +/* U+220F */ (char)0xD5, 0x00, -/* U+2211 */ 0xE5, +/* U+2211 */ (char)0xE5, /* U+2212 */ 0x2D, 0x00, 0x00, -/* U+2215 */ 0xA4, +/* U+2215 */ (char)0xA4, 0x00, /* U+2217 */ 0x2A, 0x00, 0x00, -/* U+221A */ 0xD6, +/* U+221A */ (char)0xD6, 0x00, 0x00, -/* U+221D */ 0xB5, -/* U+221E */ 0xA5, +/* U+221D */ (char)0xB5, +/* U+221E */ (char)0xA5, 0x00, -/* U+2220 */ 0xD0, +/* U+2220 */ (char)0xD0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -/* U+2227 */ 0xD9, -/* U+2228 */ 0xDA, -/* U+2229 */ 0xC7, -/* U+222A */ 0xC8, -/* U+222B */ 0xF2, +/* U+2227 */ (char)0xD9, +/* U+2228 */ (char)0xDA, +/* U+2229 */ (char)0xC7, +/* U+222A */ (char)0xC8, +/* U+222B */ (char)0xF2, 0x00, 0x00, 0x00, @@ -847,7 +847,7 @@ static const char unicode_to_symbol_1b_2022[] = { /* U+2245 */ 0x40, 0x00, 0x00, -/* U+2248 */ 0xBB, +/* U+2248 */ (char)0xBB, 0x00, 0x00, 0x00, @@ -871,12 +871,12 @@ static const char unicode_to_symbol_1b_2022[] = { 0x00, 0x00, 0x00, -/* U+2260 */ 0xB9, -/* U+2261 */ 0xBA, +/* U+2260 */ (char)0xB9, +/* U+2261 */ (char)0xBA, 0x00, 0x00, -/* U+2264 */ 0xA3, -/* U+2265 */ 0xB3, +/* U+2264 */ (char)0xA3, +/* U+2265 */ (char)0xB3, 0x00, 0x00, 0x00, @@ -905,12 +905,12 @@ static const char unicode_to_symbol_1b_2022[] = { 0x00, 0x00, 0x00, -/* U+2282 */ 0xCC, -/* U+2283 */ 0xC9, -/* U+2284 */ 0xCB, +/* U+2282 */ (char)0xCC, +/* U+2283 */ (char)0xC9, +/* U+2284 */ (char)0xCB, 0x00, -/* U+2286 */ 0xCD, -/* U+2287 */ 0xCA, +/* U+2286 */ (char)0xCD, +/* U+2287 */ (char)0xCA, 0x00, 0x00, 0x00, @@ -924,9 +924,9 @@ static const char unicode_to_symbol_1b_2022[] = { 0x00, 0x00, 0x00, -/* U+2295 */ 0xC5, +/* U+2295 */ (char)0xC5, 0x00, -/* U+2297 */ 0xC4, +/* U+2297 */ (char)0xC4, 0x00, 0x00, 0x00, @@ -972,7 +972,7 @@ static const char unicode_to_symbol_1b_2022[] = { 0x00, 0x00, 0x00, -/* U+22C5 */ 0xD7, +/* U+22C5 */ (char)0xD7, 0x00, 0x00, 0x00, @@ -1063,8 +1063,8 @@ static const char unicode_to_symbol_1b_2022[] = { 0x00, 0x00, 0x00, -/* U+2320 */ 0xF3, -/* U+2321 */ 0xF5, +/* U+2320 */ (char)0xF3, +/* U+2321 */ (char)0xF5, 0x00, 0x00, 0x00, @@ -1072,55 +1072,55 @@ static const char unicode_to_symbol_1b_2022[] = { 0x00, 0x00, 0x00, -/* U+2329 */ 0xE1, -/* U+232A */ 0xF1, +/* U+2329 */ (char)0xE1, +/* U+232A */ (char)0xF1, }; static const char unicode_to_symbol_1b_25CA[] = { -/* U+25CA */ 0xE0, +/* U+25CA */ (char)0xE0, }; static const char unicode_to_symbol_1b_2660[] = { -/* U+2660 */ 0xAA, +/* U+2660 */ (char)0xAA, 0x00, 0x00, -/* U+2663 */ 0xA7, +/* U+2663 */ (char)0xA7, 0x00, -/* U+2665 */ 0xA9, -/* U+2666 */ 0xA8, +/* U+2665 */ (char)0xA9, +/* U+2666 */ (char)0xA8, }; static const char unicode_to_symbol_1b_F6D9[] = { -/* U+F6D9 */ 0xD3, -/* U+F6DA */ 0xD2, -/* U+F6DB */ 0xD4, +/* U+F6D9 */ (char)0xD3, +/* U+F6DA */ (char)0xD2, +/* U+F6DB */ (char)0xD4, }; static const char unicode_to_symbol_1b_F8E5[] = { /* U+F8E5 */ 0x60, -/* U+F8E6 */ 0xBD, -/* U+F8E7 */ 0xBE, -/* U+F8E8 */ 0xE2, -/* U+F8E9 */ 0xE3, -/* U+F8EA */ 0xE4, -/* U+F8EB */ 0xE6, -/* U+F8EC */ 0xE7, -/* U+F8ED */ 0xE8, -/* U+F8EE */ 0xE9, -/* U+F8EF */ 0xEA, -/* U+F8F0 */ 0xEB, -/* U+F8F1 */ 0xEC, -/* U+F8F2 */ 0xED, -/* U+F8F3 */ 0xEE, -/* U+F8F4 */ 0xEF, -/* U+F8F5 */ 0xF4, -/* U+F8F6 */ 0xF6, -/* U+F8F7 */ 0xF7, -/* U+F8F8 */ 0xF8, -/* U+F8F9 */ 0xF9, -/* U+F8FA */ 0xFA, -/* U+F8FB */ 0xFB, -/* U+F8FC */ 0xFC, -/* U+F8FD */ 0xFD, -/* U+F8FE */ 0xFE, +/* U+F8E6 */ (char)0xBD, +/* U+F8E7 */ (char)0xBE, +/* U+F8E8 */ (char)0xE2, +/* U+F8E9 */ (char)0xE3, +/* U+F8EA */ (char)0xE4, +/* U+F8EB */ (char)0xE6, +/* U+F8EC */ (char)0xE7, +/* U+F8ED */ (char)0xE8, +/* U+F8EE */ (char)0xE9, +/* U+F8EF */ (char)0xEA, +/* U+F8F0 */ (char)0xEB, +/* U+F8F1 */ (char)0xEC, +/* U+F8F2 */ (char)0xED, +/* U+F8F3 */ (char)0xEE, +/* U+F8F4 */ (char)0xEF, +/* U+F8F5 */ (char)0xF4, +/* U+F8F6 */ (char)0xF6, +/* U+F8F7 */ (char)0xF7, +/* U+F8F8 */ (char)0xF8, +/* U+F8F9 */ (char)0xF9, +/* U+F8FA */ (char)0xFA, +/* U+F8FB */ (char)0xFB, +/* U+F8FC */ (char)0xFC, +/* U+F8FD */ (char)0xFD, +/* U+F8FE */ (char)0xFE, }; diff --git a/src/xutf8/imKStoUCS.c b/src/xutf8/imKStoUCS.c index 0af9a80..aa67020 100644 --- a/src/xutf8/imKStoUCS.c +++ b/src/xutf8/imKStoUCS.c @@ -266,7 +266,7 @@ static unsigned short const keysym_to_unicode_20a0_20ac[] = { 0x20a8, 0x20a9, 0x20aa, 0x20ab, 0x20ac /* 0x20a8-0x20af */ }; -unsigned int +static unsigned int KeySymToUcs4(KeySym keysym) { /* 'Unicode keysym' */ diff --git a/src/xutf8/is_right2left.c b/src/xutf8/is_right2left.c index 7b49af1..69a612a 100644 --- a/src/xutf8/is_right2left.c +++ b/src/xutf8/is_right2left.c @@ -18,7 +18,11 @@ * This file is required on all platforms for utf8 support */ -unsigned short +#if !defined(WIN32) && !defined(__APPLE__) +# include "../Xutf8.h" +#endif /* !defined(WIN32) && !defined(__APPLE__) */ + +unsigned short XUtf8IsRightToLeft(unsigned int ucs) { #if 0 @@ -34,7 +38,7 @@ XUtf8IsRightToLeft(unsigned int ucs) { if (ucs >= 0x0591) return 1; return 0; } - + /* ARABIC */ if (ucs <= 0x06ED) { if (ucs >= 0x060C) return 1; @@ -56,7 +60,7 @@ XUtf8IsRightToLeft(unsigned int ucs) { if (ucs >= 0xFB1E) return 1; return 0; } - + if (ucs <= 0xFDFB) { if (ucs >= 0xFB50) return 1; return 0; diff --git a/src/xutf8/keysym2Ucs.c b/src/xutf8/keysym2Ucs.c index 052a7c7..d01a3a7 100644 --- a/src/xutf8/keysym2Ucs.c +++ b/src/xutf8/keysym2Ucs.c @@ -18,7 +18,7 @@ #if !defined(WIN32) && !defined(__APPLE__) -#include "../../FL/Xutf8.h" +#include "../Xutf8.h" #include "imKStoUCS.c" long XKeysymToUcs(KeySym keysym) { diff --git a/src/xutf8/ucs2fontmap.c b/src/xutf8/ucs2fontmap.c index da08052..8446b08 100644 --- a/src/xutf8/ucs2fontmap.c +++ b/src/xutf8/ucs2fontmap.c @@ -57,13 +57,12 @@ typedef struct { /*************** conv_gen.c ************/ /*const*/ -int ucs2fontmap(char *s, unsigned int ucs, int enc) { +static int ucs2fontmap(char *s, unsigned int ucs, int enc) { switch(enc) { case 0: /* iso10646-1 */ s[0] = (char) ((ucs & 0xFF00) >> 8); s[1] = (char) (ucs & 0xFF); return 0; - break; case 1: /* iso8859-1 */ if (ucs <= 0x00FF) { if (ucs >= 0x0001) { @@ -299,7 +298,7 @@ int ucs2fontmap(char *s, unsigned int ucs, int enc) { } /*const*/ -int encoding_number(const char *enc) { +static int encoding_number(const char *enc) { if (!enc || !strncmp(enc, "iso10646-1", 10)) { return 0; } else if (!strcmp(enc, "iso8859-1")) { diff --git a/src/xutf8/utf8Input.c b/src/xutf8/utf8Input.c index ee2c229..5682ac7 100644 --- a/src/xutf8/utf8Input.c +++ b/src/xutf8/utf8Input.c @@ -17,7 +17,7 @@ #if !defined(WIN32) && !defined(__APPLE__) #include <config.h> -#include "../../FL/Xutf8.h" +#include "../Xutf8.h" #include <X11/X.h> #include <X11/Xlib.h> #include <X11/Xutil.h> @@ -43,6 +43,7 @@ typedef struct { unsigned short used; } Summary16; +#ifndef X_HAVE_UTF8_STRING #define NEED_TOWC /* indicates what part of these include files is needed here (avoid compilation warnings) */ #include "lcUniConv/big5.h" #include "lcUniConv/gb2312.h" @@ -52,7 +53,7 @@ typedef struct { #include "lcUniConv/jisx0212.h" #include "lcUniConv/ksc5601.h" -int +static int XConvertEucTwToUtf8(char* buffer_return, int len) { /* FIXME */ #if HAVE_LIBC_ICONV @@ -119,7 +120,7 @@ XConvertEucTwToUtf8(char* buffer_return, int len) { return l; } -int +static int XConvertEucKrToUtf8(char* buffer_return, int len) { int i = 0, l = 0; char *buf; @@ -159,7 +160,7 @@ XConvertEucKrToUtf8(char* buffer_return, int len) { return l; } -int +static int XConvertBig5ToUtf8(char* buffer_return, int len) { int i = 0, l = 0; char *buf; @@ -188,7 +189,7 @@ XConvertBig5ToUtf8(char* buffer_return, int len) { return l; } -int +static int XConvertCp936extToUtf8(char* buffer_return, int len) { int i = 0, l = 0; @@ -225,7 +226,7 @@ XConvertCp936extToUtf8(char* buffer_return, int len) return l; } -int +static int XConvertGb2312ToUtf8(char* buffer_return, int len) { int i = 0, l = 0; char *buf; @@ -260,7 +261,7 @@ XConvertGb2312ToUtf8(char* buffer_return, int len) { return l; } -int +static int XConvertEucCnToUtf8(char* buffer_return, int len) { int i = 0, l = 0; char *buf; @@ -299,7 +300,7 @@ XConvertEucCnToUtf8(char* buffer_return, int len) { return l; } -int +static int XConvertEucJpToUtf8(char* buffer_return, int len) { int i = 0, l = 0; char *buf; @@ -372,7 +373,7 @@ XConvertEucJpToUtf8(char* buffer_return, int len) { return l; } -int +static int XConvertEucToUtf8(const char* locale, char* buffer_return, int len, @@ -447,6 +448,7 @@ XUtf8LookupString(XIC ic, } return len; } +#endif /* X11 has utf-8 */ #endif /* X11 only */ diff --git a/src/xutf8/utf8Utils.c b/src/xutf8/utf8Utils.c index 1e60b76..54bbccf 100644 --- a/src/xutf8/utf8Utils.c +++ b/src/xutf8/utf8Utils.c @@ -20,7 +20,7 @@ #if !defined(WIN32) && !defined(__APPLE__) -#include "../../FL/Xutf8.h" +#include "../Xutf8.h" /*** NOTE : all functions are LIMITED to 24 bits Unicode values !!! ***/ diff --git a/src/xutf8/utf8Wrap.c b/src/xutf8/utf8Wrap.c index 9c44f47..d26eba1 100644 --- a/src/xutf8/utf8Wrap.c +++ b/src/xutf8/utf8Wrap.c @@ -1,4 +1,4 @@ -/* "$Id: utf8Wrap.c 9549 2012-05-26 22:51:07Z greg.ercolano $" +/* "$Id: utf8Wrap.c 10248 2014-08-23 08:41:58Z cand $" * * Author: Jean-Marc Lienher ( http://oksid.ch ) * Copyright 2000-2003 by O'ksi'D. @@ -19,7 +19,7 @@ */ #if !defined(WIN32) && !defined(__APPLE__) -#include "../../FL/Xutf8.h" +#include "../Xutf8.h" #include <X11/Xlib.h> #include <ctype.h> #include <stdlib.h> @@ -79,7 +79,7 @@ get_font_list( while (*ptr) { int l = 0, i = 0; - while(isspace(*ptr)) ptr++; + while(isspace((int)(unsigned char)*ptr)) ptr++; p = ptr; while (*ptr && *ptr != ',') { ptr++; l++; } if (l > 2) { @@ -203,7 +203,7 @@ get_encodings(char **font_name_list, /*********************************************************************/ /** find the first font which matches the name and load it. **/ /*********************************************************************/ -XFontStruct * +static XFontStruct * find_best_font(Display *dpy, char **name) { @@ -1039,5 +1039,5 @@ XFreeUtf8FontStruct(Display *dpy, #endif /* X11 only */ /* - * End of "$Id: utf8Wrap.c 9549 2012-05-26 22:51:07Z greg.ercolano $". + * End of "$Id: utf8Wrap.c 10248 2014-08-23 08:41:58Z cand $". */ |