diff options
128 files changed, 4995 insertions, 4274 deletions
@@ -2,12 +2,72 @@ Dillo project ============================================================================= -dillo-2.2.1 [not released yet] +dillo-3.0.1 [not released yet] -+- Implemented "View source" as a dpi. ++- Add preference for UI theme. + - Allow key bindings for paging left/right. + - Privacy -- never send cookies when making third-party requests, and + never accept cookies in the responses to these requests. + Patches: corvid ++- Add show_quit_dialog dillorc option. + Patch: Johannes Hofmann + +----------------------------------------------------------------------------- + +dillo-3.0 [September 06, 2011] + ++- Ported Dillo to FLTK-1.3. + Patch: corvid, Johannes Hofmann, Jorge Arellano Cid ++- Rewrote the User Interface: much simpler design and event handling. + - Avoid double render after going Back or Forward (takes half the time now!). + - Added on-the-fly panel resize (tiny/small/medium and normal/small icons). + - Implemented a custom tabs handler (to allow fine control of it). + - Rewrote dw's crossing-events dispatcher (avoids redundant events). + - Fixed a years old bug: stamped tooltips when scrolling with keyboard. + - Allow multiple search engines to be set in dillorc, with a menu in the web + search dialog to select between them. + - Added an optional label to dillorc's search_url. Format: "[<label> ]<url>" + - Fixed a border case in URL resolver: empty path + {query|fragment} (BUG#948) + - Avoid a certificate dialog storm on some HTTPS sites (BUG#868). + - Cancel the expected URL after offering a download (BUG#982) + - Default binding for close-all changed from Alt-q to Ctrl-q. + - Default binding for close-tab changed from Ctrl-q to Ctrl-w. + - Add right_click_closes_tab preference (default is middle click). + - 'hide-panels' key action now hides the findbar if present, and toggles + display of the control panels otherwise. + - Removed 'large' option of panel_size preference. + - Remove 'fullscreen' key action. + - Eliminated a pack of 22 compiler warnings (gcc-4.6.1 amd64) + - Lots of minor bug-fixes. + Patches: Jorge Arellano Cid ++- Remove --enable-ansi configure option. + - Limit saved cookie size. + - Allow binding to non-ASCII keys and multimedia keys. + - Enable line wrapping for <textarea>. (BUG#903) + - Wrap image alt text. + Patches: corvid ++- Add support for CSS adjacent sibling selectors. + - Collapse parent's and first child's top margin. + - Fix redraw loops and reenable limit_text_width dillorc option. + Patch: Johannes Hofmann ++- Default binding for left-tab changed to Shift-Ctrl-Tab. + Patch: Jeremy Henty + +Note: these are user-visible changes. The full Changelog is kept + in our Mercurial repository at http://hg.dillo.org/dillo + + +----------------------------------------------------------------------------- + +dillo-2.2.1 [July 18, 2011] + ++- Fix fullwindow start. + - Implemented "View source" as a dpi. + - Fix: vsource html, fix entities display, indentation. - Accept application/xhtml+xml. - Small caps support. - Border-collapse, border-style properties. + - Removed gcc warnings for 64bit Patches: Jorge Arellano Cid +- Configurable User-Agent HTTP header. Patch: Alexander Voigt, corvid @@ -27,6 +87,7 @@ dillo-2.2.1 [not released yet] +- Reintroduce bg_color dillorc option. - Make Dillo compile with Clang. - Fix Textblock flushing. + - Support !important in style attributes. Patches: Johannes Hofmann +- Implement line-height. - Draw image maps when image not loaded. @@ -27,6 +27,16 @@ Sep 2007 The new FLTK2-based dillo code is released! (under GPL3) +Jul 2011 + + Dillo switches to fltk-1.3.0. + dillo-2.2.1, the last of the 2.x series is released. + +Sep 2011 + + dillo-3.0, the first of the 3.x series is released. + + Jorge.- jcid@dillo.org Project maintainer, core developer, patcher, you name it! :-) @@ -2,28 +2,67 @@ Dillo web browser =================== - Dillo 2.2 features a major overhaul of the cookies subsystem, -a reimplementation of the Dillo Plugin (DPI) API, a configurable -connection limit, and various CSS improvements. +Dillo-3.0 is the first release of the newest branch, which is +based on the already released fltk-1.3 toolkit. This is big news +because it clears the way for Dillo to return to those +distributions which had excluded Dillo2 due to FLTK2 never +being officially released. - This release is part of the Dillo2 series. In Dillo2, significant -parts of the codebase were ported to C++, and the rendering engine was -modified to use the FLTK2 library rather than GTK1. +The development effort shifted to the dillo-3.x branch long ago, +and it became the active one; dillo-2.x received less and less +attention, and dillo-2.2.1 became the last of its series. - Here's a list of some well-known problems: +The core team will focus on implementing the CSS feature of +floating elements. This will greatly improve dillo's web page +rendering since many sites have adopted floats instead of tables. + +The new dillo3 has shown excellent stability. + +The core team welcomes developers willing to join our workforce. + + +NOTE: With FLTK-1.3, when running on X with Xft enabled (the +default), font naming is more restricted than it was with FLTK2. +If your font_* preferences are no longer working well, please try +the fc-list command as given in dillorc. + + + Here's a list of some old well-known problems of dillo: * no FRAMES rendering * no https (there's a barebones prototype). ------ -FLTK2 ------ - The FLTK2 library is statically linked into Dillo2. - You can get it from fltk.org. -The recommended version is >= r6916. e.g. in: +------- +FLTK1.3 +------- + + You can get FLTK-1.3 here: + + http://fltk.org/software.php?VERSION=1.3.0 + + +--------------------------- +Building dillo from sources +--------------------------- + + 1.- Install fltk: + + tar zxvf fltk-1.3.0-source.tar.gz + cd fltk-1.3.0 + less README.Unix.txt + make + sudo make install + cd .. + + (don't configure fltk with --enable-cairo) + + 2.- Then dillo3: - http://fltk.org/software.php?VERSION=2.0.x-r6916 + tar jxvf dillo-3.0.tar.bz2 + cd dillo-3.0 + ./configure; make + sudo make install-strip ------------ @@ -67,4 +106,4 @@ Solaris Jorge.- (jcid@dillo.org) -June, 2009 +August, 2011 diff --git a/configure.in b/configure.in index 6ddf8642..ddf500d1 100644 --- a/configure.in +++ b/configure.in @@ -1,6 +1,6 @@ dnl Process this file with aclocal, autoconf and automake. -AC_INIT([dillo], [2.2]) +AC_INIT([dillo], [3.0]) dnl Detect the canonical target build environment AC_CANONICAL_TARGET @@ -22,8 +22,6 @@ AC_ARG_ENABLE(gprof, [ --enable-gprof Try to compile and run with pro , enable_gprof=no) AC_ARG_ENABLE(insure, [ --enable-insure Try to compile and run with Insure++], , enable_insure=no) -AC_ARG_ENABLE(ansi, [ --enable-ansi Try to compile and run with ANSI flags], - , enable_ansi=no) AC_ARG_ENABLE(ssl, [ --enable-ssl Enable ssl, https (ALPHA CODE)], , enable_ssl=no) AC_ARG_ENABLE(ipv6, [ --enable-ipv6 Build with support for IPv6], , ) @@ -37,7 +35,7 @@ AC_ARG_ENABLE(gif, [ --disable-gif Disable support for GIF images] enable_gif=$enableval, enable_gif=yes) AC_ARG_ENABLE(threaded-dns,[ --disable-threaded-dns Disable the advantage of a reentrant resolver library], enable_threaded_dns=$enableval, enable_threaded_dns=yes) -AC_ARG_ENABLE(rtfl, [ --enable-rtfl Build with rtfl messages]) +AC_ARG_ENABLE(rtfl, [ --enable-rtfl Build with rtfl messages (for debugging rendering)]) AC_PROG_CC AC_PROG_CXX AC_PROG_RANLIB @@ -109,19 +107,22 @@ fi dnl ---------------------- -dnl Test for FLTK2 library +dnl Test for FLTK 1.3 library dnl ---------------------- dnl dnl For debugging and to be user friendly -AC_MSG_CHECKING([FLTK2]) -if sh -c "fltk2-config --version" >/dev/null 2>&1 -then AC_MSG_RESULT(yes) - LIBFLTK_CXXFLAGS=`fltk2-config --cxxflags` - LIBFLTK_CFLAGS=`fltk2-config --cflags` - LIBFLTK_LIBS=`fltk2-config --ldflags` -else AC_MSG_RESULT(no) - AC_MSG_ERROR(FLTK2 must be installed!) -fi +AC_MSG_CHECKING([FLTK 1.3]) +fltk_version="`fltk-config --version 2>/dev/null`" +case $fltk_version in + 1.3.*) AC_MSG_RESULT(yes) + LIBFLTK_CXXFLAGS=`fltk-config --cxxflags` + LIBFLTK_CFLAGS=`fltk-config --cflags` + LIBFLTK_LIBS=`fltk-config --ldflags`;; + ?*) AC_MSG_RESULT(no) + AC_ERROR(FLTK 1.3 required; version found: $fltk_version);; + *) AC_MSG_RESULT(no) + AC_ERROR(FLTK 1.3 required; fltk-config not found) +esac dnl ---------------- @@ -441,24 +442,12 @@ if eval "test x$GCC = xyes"; then if test "`echo $CFLAGS | grep -e '-W ' -e '-W$' 2> /dev/null`" = ""; then CFLAGS="$CFLAGS -W" fi - if test "`echo $CFLAGS | grep '\-W[^a]' 2> /dev/null`" = ""; then - if test "`$CC -v 2>&1 | grep 'version 3'`" != ""; then - CFLAGS="$CFLAGS -W -Wno-unused-parameter" - fi + if test "`echo $CFLAGS | grep '\-Wno-unused-parameter' 2> /dev/null`" = ""; then + CFLAGS="$CFLAGS -Wno-unused-parameter" fi if test "`echo $CFLAGS | grep '\-Waggregate-return' 2> /dev/null`" = ""; then CFLAGS="$CFLAGS -Waggregate-return" fi - - if eval "test x$enable_ansi = xyes"; then - if test "`echo $CFLAGS | grep '\-ansi' 2> /dev/null`" = ""; then - CFLAGS="$CFLAGS -ansi" - fi - - if test "`echo $CFLAGS | grep '\-pedantic' 2> /dev/null`" = ""; then - CFLAGS="$CFLAGS -pedantic" - fi - fi fi dnl ----------- dnl CXX options @@ -48,8 +48,9 @@ # Default fonts: # -# If FLTK2 has been configured with Xft enabled (the default), you can -# use scalable fonts such as DejaVu or Liberation (try running "fc-list"). +# If FLTK has been configured with Xft enabled (the default), you can use +# scalable fonts such as DejaVu or Liberation (try running +# "fc-list : family | cut -d ',' -f 2 | sort"). #font_serif="DejaVu Serif" #font_sans_serif="DejaVu Sans" #font_cursive="URW Chancery L" @@ -79,8 +80,6 @@ # Set this to YES if you want to limit the word wrap width to the viewport # width (may be useful for iPAQ) -# *** NOT HOOKED UP YET *** -# #limit_text_width=NO @@ -108,12 +107,16 @@ # home="file:/home/jcid/HomePage/Home.html" #home="http://www.dillo.org/" -# Set the URL used by the web search dialog. +# Set the URLs used by the web search dialog. # "%s" is replaced with the search keywords separated by '+'. -# search_url="http://www.wikipedia.org/wiki/Special:Search?search=%s" -# search_url="http://search.lycos.com/?query=%s" -# search_url="http://duckduckgo.com/html?q=%s" -#search_url="http://www.google.com/search?ie=UTF-8&oe=UTF-8&q=%s" +# Format: search_url="[<label> ]<url>" +# You can enable multiple search_url strings at once and select from among +# them at runtime, with the first being the default. +search_url="http://duckduckgo.com/lite/?kp=-1&q=%s" +search_url="Scroogle https://ssl.scroogle.org/cgi-bin/nbbwssl.cgi?Gw=%s" +search_url="Wikipedia http://www.wikipedia.org/w/index.php?search=%s&go=Go" +search_url="Free Dictionary http://www.thefreedictionary.com/%s" +search_url="Google http://www.google.com/search?ie=UTF-8&oe=UTF-8&q=%s" # If set, dillo will ask web servers to send pages in this language. # This setting does NOT change dillo's user interface. @@ -187,15 +190,22 @@ # USER INTERFACE SECTION #------------------------------------------------------------------------- -# Size of dillo panel (used to enlarge the browsing area) -# tiny : recommended for iPAQ (with small_icons) -# small : very nice! (it's "medium" without icon titles) -# medium : nice! -# large : Traditional +# UI theme +# "none" is the default FLTK appearance, which "resembles old Windows...and +# old GTK/KDE". +# "plastic" "is inspired by the Aqua user interface on Mac OS X". +# "gtk+" "is inspired by the Red Hat Bluecurve theme". +#theme=none +# theme=gtk+ +# theme=plastic + +# Size of dillo panel +# tiny : buttons, location, and progress boxes in one row +# small : location in one row, buttons + progress boxes in another +# medium : adds text labels to buttons and boxes # panel_size=tiny # panel_size=small #panel_size=medium -# panel_size=large #small_icons=NO @@ -228,6 +238,10 @@ # If you prefer to open a new Window instead, set it to NO. #middle_click_opens_new_tab=YES +# A mouse's middle click over a tab closes the Tab. +# With mousewheel mouses, right click feels way better (set to YES). +#right_click_closes_tab=NO + # Mouse middle click by default drives drag-scrolling. # To paste an URL into the window instead of scrolling, set it to NO. # Note: You could always paste the URL onto the URL box clear button. @@ -237,6 +251,8 @@ # You can hold SHIFT to temporarily revert this behaviour. #focus_new_tab=YES +# Ask before quitting Dillo with more than one window or tab open. +#show_quit_dialog=YES #------------------------------------------------------------------------- # DEBUG MESSAGES SECTION diff --git a/dlib/dlib.c b/dlib/dlib.c index b87d0ce1..f2ef2dd1 100644 --- a/dlib/dlib.c +++ b/dlib/dlib.c @@ -877,11 +877,6 @@ char *dGetline (FILE *stream) dstr = dStr_sized_new(64); while ((ch = fgetc(stream)) != EOF) { - if (ch == '\\') { - /* continue with the next line */ - while ((ch = fgetc(stream)) != EOF && ch != '\n') ; - continue; - } dStr_append_c(dstr, ch); if (ch == '\n') break; diff --git a/doc/Cookies.txt b/doc/Cookies.txt index a8e82a83..49e743b3 100644 --- a/doc/Cookies.txt +++ b/doc/Cookies.txt @@ -7,14 +7,13 @@ Last update: March 2010 Cookies in Dillo ================== -Dillo's cookies implementation is guided by ongoing work by the HTTP State WG -( http://www.ietf.org/dyn/wg/charter/httpstate-charter ) to specify current -real-world cookies usage. +The current specification for cookies is RFC 6265 +( http://tools.ietf.org/html/rfc6265 ). Cookies are handled by a dpi (plugin) which shares them between your instances of Dillo. -Currently, cookie limits are: 20 per domain, and 1200 in total. +Current cookie limits are: 20 per domain, and 1200 in total. When the dpi exits, cookies that you have ACCEPTed are saved to ~/.dillo/cookies.txt, and ACCEPT_SESSION cookies are forgotten. @@ -66,15 +65,10 @@ information (SPAM, Spying, etc). with more information than you have about yourself. Some people may tell you this is "paranoid". But please, take my words -as those of someone that has written a web browser, a cookies implementation, -and that has deep understanding of HTTP (RFC-2068) and cookies (RFC-2965). - - Non technical persons may like to read: - http://www.junkbusters.com/cookies.html +as those of someone who has written a web browser, a cookies implementation, +and who has deep understanding of HTTP and cookies. The dillo project is especially concerned about privacy and security issues. Our advice is to avoid cookies whenever possible and at most set ACCEPT_SESSION to specific, trusted sites. -- You have been warned. - -Thats all folks! diff --git a/doc/Dillo.txt b/doc/Dillo.txt index b9ef0513..a63c9588 100644 --- a/doc/Dillo.txt +++ b/doc/Dillo.txt @@ -23,7 +23,7 @@ developers. Dillo can be viewed as the sum of five main parts: - 1.- Dillo Widget: A custom widget, FLTK2 based, that holds the + 1.- Dillo Widget: A custom widget, FLTK-based, that holds the necessary data structures and mechanisms for graphical rendering. (Described in Dw*.txt, dw*.c files among the sources.) @@ -1,7 +1,7 @@ README: Last update Jul 2009 These documents cover dillo's internals. -For user help, see http://www.dillo.org/dillo2-help.html +For user help, see http://www.dillo.org/dillo3-help.html -------------------------------------------------------------------------- diff --git a/doc/dw-usage.doc b/doc/dw-usage.doc index 32080d74..a23920b8 100644 --- a/doc/dw-usage.doc +++ b/doc/dw-usage.doc @@ -23,8 +23,8 @@ As described in \ref dw-overview, the following objects are needed: First of all, the necessary \#include's: \code -#include <fltk/Window.h> -#include <fltk/run.h> +#include <FL/Fl_Window.H> +#include <FL/Fl.H> #include "dw/core.hh" #include "dw/fltkcore.hh" @@ -54,7 +54,7 @@ Then, the layout is created, with the platform attached: For the view, we first need a FLTK window: \code - fltk::Window *window = new fltk::Window(200, 300, "Dw Example"); + Fl_Window *window = new Fl_Window(200, 300, "Dw Example"); window->begin(); \endcode @@ -88,6 +88,8 @@ defined: fontAttrs.size = 14; fontAttrs.weight = 400; fontAttrs.style = dw::core::style::FONT_STYLE_NORMAL; + fontAttrs.letterSpacing = 0; + fontAttrs.fontVariant = dw::core::style::FONT_VARIANT_NORMAL; \endcode Now, the font can be created: @@ -101,9 +103,9 @@ defined, here dw::core::style::Color::createSimple must be called: \code styleAttrs.color = - dw::core::style::Color::createSimple (layout, 0x000000); + dw::core::style::Color::create (layout, 0x000000); styleAttrs.backgroundColor = - dw::core::style::Color::createSimple (layout, 0xffffff); + dw::core::style::Color::create (layout, 0xffffff); \endcode Finally, the style for the widget is created: @@ -193,7 +195,7 @@ Some FLTK stuff to finally show the window: \code window->resizable(viewport); window->show(); - int errorCode = fltk::run(); + int errorCode = Fl::run(); \endcode For cleaning up, it is sufficient to destroy the layout: diff --git a/doc/fltk-problems.doc b/doc/fltk-problems.doc index 6f20c44d..df4f1f14 100644 --- a/doc/fltk-problems.doc +++ b/doc/fltk-problems.doc @@ -26,10 +26,8 @@ Current problems: <li> There is the problem, that fltk::font always returns a font, the required one, or a replacements. The latter is not wanted in all cases, e.g. when several fonts are tested. Perhaps, this could be - solved by searching in the font list. - -<li> In dw::fltk::FltkFont::FltkFont, fltk::measure does not seem to work - for the calculation of dw::core::style::Font::xHeight. + solved by searching in the font list. <i>[This was true of fltk2. + What is the state of font handling now with fltk-1.3?]</i> <li> Distinction between italics and oblique would be nice (dw::fltk::FltkFont::FltkFont). @@ -38,7 +36,7 @@ Current problems: <h2>dw::fltk::ui::FltkCheckButtonResource</h2> -Groups of fltk::RadioButton must be added to one fltk::Group, which is +Groups of Fl_Radio_Button must be added to one Fl_Group, which is not possible in this context. There are two alternatives: <ol> @@ -58,7 +56,7 @@ be used. Then, it is for X necessary to use GCs with clipping masks. <h2>dw::fltk::ui::ComplexButton</h2> -Unfortunately, FLTK does not provide a button with Group as parent, so +Unfortunately, FLTK does not provide a button with Fl_Group as parent, so that children may be added to the button. dw::fltk::ui::ComplexButton does exactly this, and is, in an ugly way, a modified copy of the FLTK button. @@ -70,7 +68,7 @@ If the files do not compile, it may be useful to create a new one from the FLTK source: <ol> -<li> Copy fltk/Button.h from FLTK to dw/fltkcomplexbutton.hh and +<li> Copy Fl_Button.H from FLTK to dw/fltkcomplexbutton.hh and src/Button.cxx to dw/fltkcomplexbutton.cc. <li> In both files, rename "Button" to "ComplexButton". Automatic replacing @@ -120,17 +118,15 @@ at the beginning and at the end. Most important, the base class is changed: \code --#ifndef fltk_Widget_h --#include "Widget.h" --#endif -+#include <fltk/Group.h> +-#include "FL/Fl_Widget.H" ++#include <FL/Fl_Group.H> \endcode and \code --class FL_API ComplexButton : public Widget { -+class ComplexButton: public ::fltk::Group +-class FL_API ComplexButton : public Fl_Widget { ++class ComplexButton: public Fl_Group +{ \endcode @@ -148,12 +144,10 @@ First, \#include's: \code - #include <fltk/events.h> - #include <fltk/damage.h> --#include <fltk/ComplexButton.h> // <fltk/Button.h> formerly - #include <fltk/Group.h> - #include <fltk/Box.h> - #include <stdlib.h> + #include <FL/Fl.H> +-#include <FL/ComplexButton.h> // <FL/Fl_Button.H> formerly + #include <FL/Fl_Group.H> + #include <FL/Fl_Window.H> + +#include "fltkcomplexbutton.hh" \endcode @@ -162,33 +156,23 @@ Second, namespaces: \code +using namespace dw::fltk::ui; - using namespace fltk; \endcode -Since the base class is now Group, the constructor must be changed: +Since the base class is now Fl_Group, the constructor must be changed: \code --ComplexButton::ComplexButton(int x,int y,int w,int h, const char *l) : Widget(x,y,w,h,l) { +-ComplexButton::ComplexButton(int x,int y,int w,int h, const char *l) : Fl_Widget(x,y,w,h,l) { +ComplexButton::ComplexButton(int x,int y,int w,int h, const char *l) : -+ Group(x,y,w,h,l) ++ Fl_Group(x,y,w,h,l) +{ \endcode -At the end of the constructor, - -\code -+ type (NORMAL); - } -\endcode - -must be added (I've forgotten, what this is for). - Finally, the button must draw its children (end of dw::fltk::ui::ComplexButton::draw()): \code + -+ for (int i = 0; i < children (); i++) ++ for (int i = children () - 1; i >= 0; i--) + draw_child (*child (i)); } \endcode diff --git a/doc/user_help.html b/doc/user_help.html index 91dc748f..4b35e6e3 100644 --- a/doc/user_help.html +++ b/doc/user_help.html @@ -2,17 +2,23 @@ <html> <head> - <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> - <title> Help for Dillo </title> + <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> + <title> Dillo Web Browser :: + + Help for New Users + +</title> </head> -<body bgcolor='#778899' text='#000000'> +<body text="#0f0f0f" link="#2020e0" vlink="#403090" bgcolor="#607cf8"> - <table bgcolor="#70a0c0" border="1" cellpadding="5"> - <tr><td><h1>Help for Dillo 2.2</h1> + <table width="100%" bgcolor="#8080f0" cellspacing="4" cellpadding="5" + border="0o"> + <tr><td><big><font color="#302080">Welcome to Dillo 3.0</font></big> </table> <p> - <table WIDTH="100%" BORDER=1 CELLSPACING=0 CELLPADDING=5> + + <table WIDTH="100%" BORDER=1 CELLSPACING=0 CELLPADDING=3> <tr ALIGN=LEFT VALIGN=TOP><td bgcolor="wheat"> <h4><font color="green">Basics:</font></h4> </td></tr> @@ -20,28 +26,35 @@ <tr><td WIDTH="100%" bgcolor="#70a0c0"> <ul> <li>You can tell a link from plain content by the hand-shaped cursor. + <li> Besides browsing the web, Dillo also has basic file browsing - capabilities included. So, entering <a href="file:">file:</a> in your + capabilities included. So, entering <code>file:</code> in your Dillo URL window will give you the contents of your current - working directory, and <a href="file:~">file:~</a> entered in the + working directory, and <code>file:~</code> entered in the same place will point your Dillo browser right to your home directory... - <li> Dillo, at this stage of development, is <u>not</u> not ready + + <li> Dillo, at this stage of development, is not ready to render pages that use <b><font color="#5040a0">frames</font></b>. Nevertheless, it comes with a tiny handler (lynx/w3m-like) that will let you choose which frame to visit, one by one. - <li> Dillo has <b><font color="#5040a0">context + + <li> Dillo has <b><font color="#5040a0">context sensitive menus</font></b> using the right mouse button (available on pages, links, images, forms, the Back and Forward buttons, and the bug meter). + <li> Some of the functions in Dillo are handled by independent - processes. For instance, downloads come through <em>wget</em>. - If Dillo exits, the download can continue (more details - below). + processes. For instance, downloads come through + <em><a href="http://www.gnu.org/software/wget/">wget</a></em>. + If Dillo exits, the downloads continue (more details + below). + + </ul> </td></tr> </table> - + <table WIDTH="100%" BORDER=1 CELLSPACING=0 CELLPADDING=3> <tr ALIGN=LEFT VALIGN=TOP><td bgcolor="wheat"> <h4><font color="green">Usage:</font></h4> @@ -54,24 +67,32 @@ or mouse wheel. If nothing happens when keys are pressed, try <b> <font color="#5040a0">focusing</font></b> your Dillo main window first by clicking it (not on any link!:)). - <li> You can use the space key as PgDn, and {'b' | 'B'} as PgUp.</li> + + <li>You can use the space key as PgDn, and {'b' | 'B'} as PgUp.</li> + <li> Similarly, you can use "<b>,</b>" and "<b>.</b>" as shortcuts for forward and backward buttons (mnemonic: those keys are usually labeled "<" and ">"). + <li> <b>Configuration:</b> If you want to change Dillo's appearance or behaviour, look at the options in your <b><font color="#5040a0">dillorc</font></b> - file (if you don't have a copy in your ~/.dillo/ directory, get it - <a href='http://www.dillo.org/dillorc'>here</a>). + file (if you don't have a copy in your ~/.dillo/ directory, get it + <a href='http://www.dillo.org/dillorc'>here</a>). + <li> Clicking the "Reload" button always requests an end-to-end reload of the page currently viewed, but it will *not* reload embedded images during this process. - <li> Dialogs can be closed with the ESC key. + + <li> Dialogs can be closed with the ESC key<br> + (ESC also hides the findbar and control panels). + <li> If you want to try a different control panel, right-click over the - search button until you find one that suits your needs, then make - it the default in your <code>dillorc</code> file. - <li> The whole window area can be used to display the page. Just hit - Ctrl-Space! + tools button and select one that suits your needs, then make + it the default in your <code>dillorc</code> file. + + <li> The whole window area can be used to display the page (ESC key). + </ul> </td></tr> </table> @@ -83,8 +104,11 @@ <tr><td BGCOLOR="#70a0c0"> <p> - Downloads are made using <b><font color="#5040a0">wget</font></b> - with a FLTK2-based GUI wrapper, through the Dillo plugin (dpi) framework. + Downloads are made using + <b><font color="#5040a0"> + <a href="http://www.gnu.org/software/wget/">wget</a></font></b> + with a <a href="http://www.fltk.org">FLTK</a>-based GUI wrapper, through + the Dillo plugin (dpi) framework. If you close the browser window, downloads will continue. <p> </td></tr> @@ -109,8 +133,8 @@ <li> To find a left-aligned substring, prepend it with a space. </li> <li> To find a right-aligned substring, append a space to it.</li> <li> To find full words only, prepend and append spaces to them. </li> - <li> To find a sentence, enter the words and remember that the above rules - apply for every word in it. </li> + <li> To find a sentence, enter the words and remember that + the above rules apply for every word in it. </li> </ul> <p> Dillo will scroll the page and highlight found text! @@ -171,9 +195,9 @@ That is, if you just compile and use dillo, it will reject every single cookie sent to it! <p> - If you want to enable cookies in dillo, just - <a href="http://www.dillo.org/Cookies.txt">set up a <code>cookiesrc</code> - file</a>. + If you want to enable cookies in dillo, please read + <a href="Cookies.txt">Cookies.txt</a>. It's very easy -- + just a matter of setting up a <code>cookiesrc</code> file). </td></tr> </table> @@ -193,6 +217,10 @@ </ul> Press SHIFT to temporarily reverse the focusing behaviour. <p> + You can <b><font color="#5040a0">close</font></b> + a tab with middle-click on its label (the default), + or with right-click by setting this dillorc option: + <ul><li><code>right_click_closes_tab</code></ul> </td></tr> </table> @@ -224,7 +252,7 @@ (<a href='http://www.dillo.org/dpi1.html'>dpi</a>) framework. This should be transparent to the end user. Please note that: <ul> - <li>It is a good idea to keep a backup of your + <li>It is a good idea to keep a backup of your <code>~/.dillo/bm.txt</code> <li>The server will stay alive after closing dillo. <li>You can stop the server by sending it a KILL signal. Dillo @@ -232,7 +260,7 @@ <li>If you don't have root access, install <em>dpid</em> and the <em>dpis</em> inside your <code>~/.dillo/</code> directory as explained - in the README file. + in the README file. </ul> </td></tr> </table> @@ -243,11 +271,11 @@ </td></tr> <tr><td bgcolor="#70a0c0"> <p> - Dillo's <a href='http://www.dillo.org/help/bug_meter.html'>bug meter</a> - shows the number of - <b><font color="#5040a0">detected bugs</font></b> inside the + Dillo's <em><a href='http://www.dillo.org/help/bug_meter.html'>Bug + meter</a></em> shows the + number of <b><font color="#5040a0">detected bugs</font></b> inside the page. The bugs are caught at parsing time, so the - error messages also show the line where they occur and provide a + error messages also show the line where they occur and provide a <b><font color="#5040a0">hint</font></b> of what was expected instead! <p> The primary purpose of the bug meter is to @@ -255,7 +283,7 @@ authors to polish the contents of their sites with a view to making them standards-compliant. <p> - The bug meter is located at the lower right corner of + The Bug meter is located at the lower right corner of Dillo. Left-click to see the messages, right-click for a menu. </td></tr> </table> @@ -273,26 +301,27 @@ <tr><td>Ctrl-R <td>Reload <td>reload current page <tr><td>Ctrl-N <td>New <td>New browser window <tr><td>Ctrl-T <td>Tab <td>New tab -<tr><td>Ctrl-Q <td>Quit <td>quit tab/window +<tr><td>Ctrl-W <td>Window <td>quit tab/window <tr><td>Ctrl-O <td>Open <td>Open file <tr><td>Ctrl-B <td>Bookmarks <td>view bookmarks -<tr><td>Ctrl-Space <td>"more space!" <td>Hide/show controls +<tr><td>Ctrl-Q <td>Quit <td>Quit dillo <tr><td>Back or "<b>,</b>" <td>< <td>previous page <tr><td>Shift-Back or "<b>.</b>" <td>> <td>next page -<tr><td>Esc <td>escape <td>close dialog <tr><td>Alt-F <td>File <td>file menu -<tr><td>Alt-X <td>eXit <td>exit Dillo -<tr><td>Shift-Right <td>Right <td>Next tab -<tr><td>Shift-Left <td>Left <td>Previous tab <tr><td>Ctrl-TabKey <td>TabKey <td>Next tab -<tr><td>Shift-Ctrl- TabKey <td>TabKey <td>Previous tab +<tr><td>Ctrl-Shift-TabKey <td>TabKey <td>Previous tab +<tr><td>Esc <td>escape <td>close dialog, + close findbar,<br> + Hide/show control panels </table> <p> -You can change the bindings using a +You can <b><font color="#5040a0">change</font></b> the bindings using a <code>~/.dillo/<a href="http://www.dillo.org/keysrc">keysrc</a></code> file. </td></tr> </table> + </body> </html> + diff --git a/dpi/cookies.c b/dpi/cookies.c index a5142224..734dc016 100644 --- a/dpi/cookies.c +++ b/dpi/cookies.c @@ -13,10 +13,9 @@ * */ -/* This is written to follow the HTTP State Working Group's - * draft-ietf-httpstate-cookie-01.txt. +/* The current standard for cookies is RFC 6265. * - * Info on cookies in the wild: + * Info from 2009 on cookies in the wild: * http://www.ietf.org/mail-archive/web/http-state/current/msg00078.html * And dates specifically: * http://www.ietf.org/mail-archive/web/http-state/current/msg00128.html @@ -413,15 +412,24 @@ static void Cookies_save_and_free() while ((node = dList_nth_data(domains, 0))) { for (i = 0; (cookie = dList_nth_data(node->cookies, i)); ++i) { if (!cookie->session_only && difftime(cookie->expires_at, now) > 0) { - fprintf(file_stream, "%s\t%s\t%s\t%s\t%ld\t%s\t%s\n", - cookie->domain, - cookie->host_only ? "FALSE" : "TRUE", - cookie->path, - cookie->secure ? "TRUE" : "FALSE", - (long)difftime(cookie->expires_at, cookies_epoch_time), - cookie->name, - cookie->value); - saved++; + int len; + char buf[LINE_MAXLEN]; + + len = snprintf(buf, LINE_MAXLEN, "%s\t%s\t%s\t%s\t%ld\t%s\t%s\n", + cookie->domain, + cookie->host_only ? "FALSE" : "TRUE", + cookie->path, + cookie->secure ? "TRUE" : "FALSE", + (long) difftime(cookie->expires_at, + cookies_epoch_time), + cookie->name, + cookie->value); + if (len < LINE_MAXLEN) { + fprintf(file_stream, "%s", buf); + saved++; + } else { + MSG("Not saving overly long cookie for %s.\n", cookie->domain); + } } Cookies_free_cookie(cookie); } @@ -481,7 +489,7 @@ static int Cookies_get_month(const char *month_name) * * Return a pointer to a struct tm, or NULL on error. * - * NOTE that the draft spec wants user agents to be more flexible in what + * NOTE that the RFC wants user agents to be more flexible in what * they accept. For now, let's hack in special cases when they're encountered. * Why? Because this function is currently understandable, and I don't want to * abandon that (or at best decrease that -- see section 5.1.1) until there @@ -1029,11 +1037,11 @@ static uint_t Cookies_internal_dots_required(const char *host) if (tld_len > 0) { /* These TLDs were chosen by examining the current publicsuffix list - * in January 2010 and picking out those where it was simplest for + * in September 2011 and picking out those where it was simplest for * them to describe the situation by beginning with a "*.[tld]" rule. */ - const char *const tlds[] = {"ar","au","bd","bn","bt","ck","cy","do", - "eg","er","et","fj","fk","gt","gu","id", + const char *const tlds[] = {"ar","au","bd","bn","bt","ck","cy", + "er","et","fj","fk","gt","gu","id", "il","jm","ke","kh","kw","ml","mm","mt", "mz","ni","np","nz","om","pg","py","qa", "sv","tr","uk","uy","ve","ye","yu","za", @@ -1136,8 +1144,8 @@ static bool_t Cookies_match(CookieData_t *cookie, const char *url_path, if (cookie->host_only != host_only_val) return FALSE; - /* Insecure cookies matches both secure and insecure urls, secure - cookies matches only secure urls */ + /* Insecure cookies match both secure and insecure urls, secure + cookies match only secure urls */ if (cookie->secure && !is_ssl) return FALSE; @@ -1274,10 +1282,10 @@ static char *Cookies_get(char *url_host, char *url_path, str = cookie_dstring->str; dStr_free(cookie_dstring, FALSE); - if (*str) + if (*str) { + MSG("%s GETTING: %s", url_host, str); cookies_use_counter++; - - MSG("%s GETTING: %s\n", url_host, str); + } return str; } diff --git a/dpi/downloads.cc b/dpi/downloads.cc index 1a70d235..9ed929ae 100644 --- a/dpi/downloads.cc +++ b/dpi/downloads.cc @@ -10,7 +10,7 @@ */ /* - * A FLTK2-based GUI for the downloads dpi (dillo plugin). + * A FLTK-based GUI for the downloads dpi (dillo plugin). */ #include <stdio.h> @@ -29,23 +29,20 @@ #include <sys/un.h> #include <sys/wait.h> -#include <fltk/run.h> -#include <fltk/Window.h> -#include <fltk/Widget.h> -#include <fltk/damage.h> -#include <fltk/Box.h> -#include <fltk/draw.h> -#include <fltk/HighlightButton.h> -#include <fltk/PackedGroup.h> -#include <fltk/ScrollGroup.h> -#include <fltk/ask.h> -#include <fltk/file_chooser.h> +#include <FL/Fl.H> +#include <FL/fl_draw.H> +#include <FL/Fl_File_Chooser.H> +#include <FL/Fl_Window.H> +#include <FL/Fl_Widget.H> +#include <FL/Fl_Group.H> +#include <FL/Fl_Scroll.H> +#include <FL/Fl_Pack.H> +#include <FL/Fl_Box.H> +#include <FL/Fl_Button.H> #include "dpiutil.h" #include "../dpip/dpip.h" -using namespace fltk; - /* * Debugging macros */ @@ -69,8 +66,7 @@ typedef enum { // ProgressBar widget -------------------------------------------------------- -// class FL_API ProgressBar : public Widget { -class ProgressBar : public Widget { +class ProgressBar : public Fl_Box { protected: double mMin; double mMax; @@ -78,7 +74,7 @@ protected: double mStep; bool mShowPct, mShowMsg; char mMsg[64]; - Color mTextColor; + Fl_Color mTextColor; void draw(); public: ProgressBar(int x, int y, int w, int h, const char *lbl = 0); @@ -97,8 +93,8 @@ public: void showtext(bool st) { mShowPct = st; } void message(char *msg) { mShowMsg = true; strncpy(mMsg,msg,63); redraw(); } bool showtext() { return mShowPct; } - void text_color(Color col) { mTextColor = col; } - Color text_color() { return mTextColor; } + void text_color(Fl_Color col) { mTextColor = col; } + Fl_Color text_color() { return mTextColor; } }; // Download-item class ------------------------------------------------------- @@ -112,7 +108,8 @@ class DLItem { int LogPipe[2]; char *shortname, *fullname; char *target_dir; - int log_len, log_max, log_state; + size_t log_len, log_max; + int log_state; char *log_text; time_t init_time; char **dl_argv; @@ -123,10 +120,10 @@ class DLItem { int WgetStatus; int gw, gh; - Group *group; + Fl_Group *group; ProgressBar *prBar; - HighlightButton *prButton; - Widget *prTitle, *prGot, *prSize, *prRate, *pr_Rate, *prETA, *prETAt; + Fl_Button *prButton; + Fl_Widget *prTitle, *prGot, *prSize, *prRate, *pr_Rate, *prETA, *prETAt; public: DLItem(const char *full_filename, const char *url, DLAction action); @@ -142,7 +139,7 @@ public: void pid(pid_t p) { mPid = p; } void child_finished(int status); void status_msg(const char *msg) { prBar->message((char*)msg); } - Widget *get_widget() { return group; } + Fl_Widget *get_widget() { return group; } int widget_done() { return WidgetDone; } void widget_done(int val) { WidgetDone = val; } int updates_done() { return UpdatesDone; } @@ -177,9 +174,9 @@ public: class DLWin { DLItemList *mDList; - Window *mWin; - ScrollGroup *mScroll; - PackedGroup *mPG; + Fl_Window *mWin; + Fl_Scroll *mScroll; + Fl_Pack *mPG; public: DLWin(int ww, int wh); @@ -194,6 +191,28 @@ public: DLAction check_filename(char **p_dl_dest); }; +/* + * FLTK cannot be dissuaded from interpreting '@' in a tooltip + * as indicating a symbol unless we escape it. + */ +static char *escape_tooltip(const char *buf, ssize_t len) +{ + if (len < 0) + len = 0; + + char *ret = (char *) malloc(2 * len + 1); + char *dest = ret; + + while (len-- > 0) { + if (*buf == '@') + *dest++ = *buf; + *dest++ = *buf++; + } + *dest = '\0'; + + return ret; +} + /* * Global variables @@ -221,67 +240,51 @@ void ProgressBar::move(double step) } ProgressBar::ProgressBar(int x, int y, int w, int h, const char *lbl) -: Widget(x, y, w, h, lbl) +: Fl_Box(x, y, w, h, lbl) { mMin = mPresent = 0; mMax = 100; mShowPct = true; mShowMsg = false; - box(DOWN_BOX); - selection_color(BLUE); - color(WHITE); - textcolor(RED); + box(FL_THIN_UP_BOX); + color(FL_WHITE); } void ProgressBar::draw() { - drawstyle(style(), flags()); - if (damage() & DAMAGE_ALL) - draw_box(); - Rectangle r(w(), h()); - box()->inset(r); + struct Rectangle { + int x, y, w, h; + }; + + //drawstyle(style(), flags()); + draw_box(); + Rectangle r = {x(), y(), w(), h()}; if (mPresent > mMax) mPresent = mMax; if (mPresent < mMin) mPresent = mMin; double pct = (mPresent - mMin) / mMax; - if (vertical()) { - int barHeight = int (r.h() * pct + .5); - r.y(r.y() + r.h() - barHeight); - r.h(barHeight); - } else { - r.w(int (r.w() * pct + .5)); - } - - setcolor(selection_color()); - - if (mShowPct) { - fillrect(r); - } else { - Rectangle r2(int (r.w() * pct), 0, int (w() * .1), h()); - push_clip(r2); - fillrect(r); - pop_clip(); - } + r.w = r.w * pct + .5; + fl_rectf(r.x, r.y, r.w, r.h, FL_BLUE); if (mShowMsg) { - setcolor(textcolor()); - setfont(this->labelfont(), this->labelsize()); - drawtext(mMsg, Rectangle(w(), h()), ALIGN_CENTER); + fl_color(FL_RED); + fl_font(this->labelfont(), this->labelsize()); + fl_draw(mMsg, x(), y(), w(), h(), FL_ALIGN_CENTER); } else if (mShowPct) { char buffer[30]; sprintf(buffer, "%d%%", int (pct * 100 + .5)); - setcolor(textcolor()); - setfont(this->labelfont(), this->labelsize()); - drawtext(buffer, Rectangle(w(), h()), ALIGN_CENTER); + fl_color(FL_RED); + fl_font(this->labelfont(), this->labelsize()); + fl_draw(buffer, x(), y(), w(), h(), FL_ALIGN_CENTER); } } // Download-item class ------------------------------------------------------- -static void prButton_scb(Widget *, void *cb_data) +static void prButton_scb(Fl_Widget *, void *cb_data) { DLItem *i = (DLItem *)cb_data; @@ -349,76 +352,85 @@ DLItem::DLItem(const char *full_filename, const char *url, DLAction action) WgetStatus = -1; gw = 400, gh = 70; - group = new Group(0,0,gw,gh); + group = new Fl_Group(0,0,gw,gh); group->begin(); - prTitle = new Widget(24, 7, 290, 23, shortname); - prTitle->box(RSHADOW_BOX); - prTitle->align(ALIGN_LEFT|ALIGN_INSIDE|ALIGN_CLIP); - prTitle->set_flag (RAW_LABEL); - // Attach this 'log_text' to the tooltip - log_text_add("Target File: ", 13); - log_text_add(fullname, strlen(fullname)); - log_text_add("\n\n", 2); - - prBar = new ProgressBar(24, 40, 92, 20); - prBar->box(BORDER_BOX); // ENGRAVED_BOX - prBar->tooltip("Progress Status"); - - int ix = 122, iy = 36, iw = 50, ih = 14; - Widget *o = new Widget(ix,iy,iw,ih, "Got"); - o->box(RFLAT_BOX); - o->color((Color)0xc0c0c000); - o->tooltip("Downloaded Size"); - prGot = new Widget(ix,iy+14,iw,ih, "0KB"); - prGot->align(ALIGN_CENTER|ALIGN_INSIDE); - prGot->labelcolor((Color)0x6c6cbd00); - prGot->box(NO_BOX); - - ix += iw; - o = new Widget(ix,iy,iw,ih, "Size"); - o->box(RFLAT_BOX); - o->color((Color)0xc0c0c000); - o->tooltip("Total Size"); - prSize = new Widget(ix,iy+14,iw,ih, "??"); - prSize->align(ALIGN_CENTER|ALIGN_INSIDE); - prSize->box(NO_BOX); - - ix += iw; - o = new Widget(ix,iy,iw,ih, "Rate"); - o->box(RFLAT_BOX); - o->color((Color)0xc0c0c000); - o->tooltip("Current transfer Rate (KBytes/sec)"); - prRate = new Widget(ix,iy+14,iw,ih, "??"); - prRate->align(ALIGN_CENTER|ALIGN_INSIDE); - prRate->box(NO_BOX); - - ix += iw; - o = new Widget(ix,iy,iw,ih, "~Rate"); - o->box(RFLAT_BOX); - o->color((Color)0xc0c0c000); - o->tooltip("Average transfer Rate (KBytes/sec)"); - pr_Rate = new Widget(ix,iy+14,iw,ih, "??"); - pr_Rate->align(ALIGN_CENTER|ALIGN_INSIDE); - pr_Rate->box(NO_BOX); - - ix += iw; - prETAt = o = new Widget(ix,iy,iw,ih, "ETA"); - o->box(RFLAT_BOX); - o->color((Color)0xc0c0c000); - o->tooltip("Estimated Time of Arrival"); - prETA = new Widget(ix,iy+14,iw,ih, "??"); - prETA->align(ALIGN_CENTER|ALIGN_INSIDE); - prETA->box(NO_BOX); - - //ix += 50; - //prButton = new HighlightButton(ix, 41, 38, 19, "Stop"); - prButton = new HighlightButton(328, 9, 38, 19, "Stop"); - prButton->tooltip("Stop this transfer"); - prButton->box(UP_BOX); - prButton->clear_tab_to_focus(); - prButton->callback(prButton_scb, this); - - group->box(ROUND_UP_BOX); + prTitle = new Fl_Box(24, 7, 290, 23); + prTitle->box(FL_RSHADOW_BOX); + prTitle->color(FL_WHITE); + prTitle->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE|FL_ALIGN_CLIP); + prTitle->copy_label(shortname); + // Attach this 'log_text' to the tooltip + log_text_add("Target File: ", 13); + log_text_add(fullname, strlen(fullname)); + log_text_add("\n\n", 2); + + prBar = new ProgressBar(24, 40, 92, 20); + prBar->box(FL_THIN_UP_BOX); + prBar->tooltip("Progress Status"); + + int ix = 122, iy = 37, iw = 50, ih = 14; + Fl_Widget *o = new Fl_Box(ix,iy,iw,ih, "Got"); + o->box(FL_RFLAT_BOX); + o->color(FL_DARK2); + o->labelsize(12); + o->tooltip("Downloaded Size"); + prGot = new Fl_Box(ix,iy+14,iw,ih, "0KB"); + prGot->align(FL_ALIGN_CENTER|FL_ALIGN_INSIDE); + prGot->labelcolor(FL_BLUE); + prGot->labelsize(12); + prGot->box(FL_NO_BOX); + + ix += iw; + o = new Fl_Box(ix,iy,iw,ih, "Size"); + o->box(FL_RFLAT_BOX); + o->color(FL_DARK2); + o->labelsize(12); + o->tooltip("Total Size"); + prSize = new Fl_Box(ix,iy+14,iw,ih, "??"); + prSize->align(FL_ALIGN_CENTER|FL_ALIGN_INSIDE); + prSize->labelsize(12); + prSize->box(FL_NO_BOX); + + ix += iw; + o = new Fl_Box(ix,iy,iw,ih, "Rate"); + o->box(FL_RFLAT_BOX); + o->color(FL_DARK2); + o->labelsize(12); + o->tooltip("Current transfer Rate (KBytes/sec)"); + prRate = new Fl_Box(ix,iy+14,iw,ih, "??"); + prRate->align(FL_ALIGN_CENTER|FL_ALIGN_INSIDE); + prRate->labelsize(12); + prRate->box(FL_NO_BOX); + + ix += iw; + o = new Fl_Box(ix,iy,iw,ih, "~Rate"); + o->box(FL_RFLAT_BOX); + o->color(FL_DARK2); + o->labelsize(12); + o->tooltip("Average transfer Rate (KBytes/sec)"); + pr_Rate = new Fl_Box(ix,iy+14,iw,ih, "??"); + pr_Rate->align(FL_ALIGN_CENTER|FL_ALIGN_INSIDE); + pr_Rate->labelsize(12); + pr_Rate->box(FL_NO_BOX); + + ix += iw; + prETAt = o = new Fl_Box(ix,iy,iw,ih, "ETA"); + o->box(FL_RFLAT_BOX); + o->color(FL_DARK2); + o->labelsize(12); + o->tooltip("Estimated Time of Arrival"); + prETA = new Fl_Box(ix,iy+14,iw,ih, "??"); + prETA->align(FL_ALIGN_CENTER|FL_ALIGN_INSIDE); + prETA->labelsize(12); + prETA->box(FL_NO_BOX); + + prButton = new Fl_Button(326, 9, 44, 19, "Stop"); + prButton->tooltip("Stop this transfer"); + prButton->box(FL_UP_BOX); + prButton->clear_visible_focus(); + prButton->callback(prButton_scb, this); + + group->box(FL_ROUNDED_BOX); group->end(); } @@ -431,7 +443,7 @@ DLItem::~DLItem() int idx = (strcmp(dl_argv[1], "-c")) ? 2 : 3; dFree(dl_argv[idx]); dFree(dl_argv[idx+3]); - delete(dl_argv); + delete [] dl_argv; delete(group); } @@ -443,7 +455,7 @@ void DLItem::abort_dl() { if (!log_done()) { close(LogPipe[0]); - remove_fd(LogPipe[0]); + Fl::remove_fd(LogPipe[0]); log_done(1); // Stop wget if (!fork_done()) @@ -482,25 +494,29 @@ void DLItem::update_prSize(int newsize) else snprintf(num, 64, "%.0fKB", (float)newsize / 1024); prSize->copy_label(num); - prSize->redraw_label(); } void DLItem::log_text_add(const char *buf, ssize_t st) { const char *p; - char *q, *d, num[64]; + char *esc_str, *q, *d, num[64]; + size_t esc_len; + + // WORKAROUND: We have to escape '@' in FLTK tooltips. + esc_str = escape_tooltip(buf, st); + esc_len = strlen(esc_str); // Make room... - if (log_len + st >= log_max) { - log_max = log_len + st + 1024; - log_text = (char *) realloc (log_text, log_max); + if (log_len + esc_len >= log_max) { + log_max = log_len + esc_len + 1024; + log_text = (char *) dRealloc (log_text, log_max); log_text[log_len] = 0; prTitle->tooltip(log_text); } // FSM to remove wget's "dot-progress" (i.e. "^ " || "^[0-9]+K") q = log_text + log_len; - for (p = buf; (p - buf) < st; ++p) { + for (p = esc_str; (size_t)(p - esc_str) < esc_len; ++p) { switch (log_state) { case ST_newline: if (*p == ' ') { @@ -535,6 +551,8 @@ void DLItem::log_text_add(const char *buf, ssize_t st) *q = 0; log_len = strlen(log_text); + free(esc_str); + // Now scan for the length of the file if (total_bytesize == -1) { p = strstr(log_text, "\nLength: "); @@ -546,13 +564,16 @@ void DLItem::log_text_add(const char *buf, ssize_t st) total_bytesize = strtol (num, NULL, 10); // Update displayed size update_prSize(total_bytesize); + + // WORKAROUND: For unknown reasons a redraw is needed here for some + // machines --jcid + group->redraw(); } } // Show we're connecting... if (curr_bytesize == 0) { - prTitle->label("Connecting..."); - prTitle->redraw_label(); + prTitle->copy_label("Connecting..."); } } @@ -570,8 +591,10 @@ void DLItem::update_size(int new_sz) // Start the timer with the first bytes got init_time = time(NULL); // Update the title - prTitle->label(shortname); - prTitle->redraw_label(); + prTitle->copy_label(shortname); + // WORKAROUND: For unknown reasons a redraw is needed here for some + // machines --jcid + group->redraw(); } curr_bytesize = new_sz; @@ -580,7 +603,6 @@ void DLItem::update_size(int new_sz) else snprintf(buf, 64, "%.0fKB", (float)curr_bytesize / 1024); prGot->copy_label(buf); - prGot->redraw_label(); if (total_bytesize == -1) { prBar->showtext(false); prBar->move(1); @@ -599,22 +621,19 @@ static void read_log_cb(int fd_in, void *data) const int BufLen = 4096; char Buf[BufLen]; ssize_t st; - int ret = -1; do { st = read(fd_in, Buf, BufLen); if (st < 0) { if (errno == EAGAIN) { - ret = 1; break; } perror("read, "); break; } else if (st == 0) { close(fd_in); - remove_fd(fd_in, 1); + Fl::remove_fd(fd_in, 1); dl_item->log_done(1); - ret = 0; break; } else { dl_item->log_text_add(Buf, st); @@ -625,7 +644,7 @@ static void read_log_cb(int fd_in, void *data) void DLItem::father_init() { close(LogPipe[1]); - add_fd(LogPipe[0], 1, read_log_cb, this); // Read + Fl::add_fd(LogPipe[0], 1, read_log_cb, this); // Read // Start the timer after the child is running. // (this makes a big difference with wget) @@ -648,8 +667,7 @@ void DLItem::child_finished(int status) status_msg("ABORTED"); if (curr_bytesize == 0) { // Update the title - prTitle->label(shortname); - prTitle->redraw_label(); + prTitle->copy_label(shortname); } } prButton->activate(); @@ -706,14 +724,12 @@ void DLItem::update() rate = ((float)(curr_bytesize-twosec_bytesize) / 1024) / tsec; snprintf(str, 64, (rate < 100) ? "%.1fK/s" : "%.0fK/s", rate); prRate->copy_label(str); - prRate->redraw_label(); } /* ~Rate */ if (csec >= 1) { _rate = ((float)(curr_bytesize-init_bytesize) / 1024) / csec; snprintf(str, 64, (_rate < 100) ? "%.1fK/s" : "%.0fK/s", _rate); pr_Rate->copy_label(str); - pr_Rate->redraw_label(); } /* ETA */ @@ -736,7 +752,6 @@ void DLItem::update() prETA->copy_label(str); } } - prETA->redraw_label(); /* Update one and two secs ago times and bytesizes */ twosec_time = onesec_time; @@ -792,7 +807,7 @@ static void cleanup_cb(void *data) } sigprocmask(SIG_UNBLOCK, &mask_sigchld, NULL); - repeat_timeout(1.0,cleanup_cb,data); + Fl::repeat_timeout(1.0,cleanup_cb,data); } /* @@ -819,7 +834,7 @@ static void update_cb(void *data) if (cb_used && list->num() == 0) exit(0); - repeat_timeout(1.0,update_cb,data); + Fl::repeat_timeout(1.0,update_cb,data); } @@ -939,14 +954,14 @@ end: /* * Callback for close window request (WM or EscapeKey press) */ -static void dlwin_esc_cb(Widget *, void *) +static void dlwin_esc_cb(Fl_Widget *, void *) { const char *msg = "There are running downloads.\n" "ABORT them and EXIT anyway?"; if (dl_win && dl_win->num_running() > 0) { - int ch = fltk::choice(msg, "Yes", "*No", "Cancel"); - if (ch != 0) + int ch = fl_choice("%s", "Cancel", "*No", "Yes", msg); + if (ch == 0 || ch == 1) return; } @@ -977,6 +992,7 @@ void DLWin::add(const char *full_filename, const char *url, DLAction action) exit(1); } else { /* father */ + dl_item->get_widget()->show(); dl_win->show(); dl_item->pid(f_pid); dl_item->father_init(); @@ -1001,12 +1017,12 @@ DLAction DLWin::check_filename(char **p_fullname) dStr_sprintf(ds, "The file:\n %s (%d Bytes)\nalready exists. What do we do?", *p_fullname, (int)ss.st_size); - ch = fltk::choice(ds->str, "Rename", "Continue", "Abort"); + ch = fl_choice("%s", "Abort", "Continue", "Rename", ds->str); dStr_free(ds, 1); MSG("Choice %d\n", ch); - if (ch == 0) { + if (ch == 2) { const char *p; - p = fltk::file_chooser("Enter a new name:", NULL, *p_fullname); + p = fl_file_chooser("Enter a new name:", NULL, *p_fullname); if (p) { dFree(*p_fullname); *p_fullname = dStrdup(p); @@ -1027,6 +1043,7 @@ void DLWin::del(int n_item) // Remove the widget from the packed group mPG->remove(dl_item->get_widget()); + mScroll->redraw(); mDList->del(n_item); delete(dl_item); } @@ -1057,7 +1074,7 @@ int DLWin::num_running() */ void DLWin::listen(int req_fd) { - add_fd(req_fd, 1, read_req_cb, NULL); // Read + Fl::add_fd(req_fd, 1, read_req_cb, NULL); // Read } /* @@ -1078,15 +1095,14 @@ DLWin::DLWin(int ww, int wh) { mDList = new DLItemList(); // Create the empty main window - mWin = new Window(ww, wh, "Downloads:"); + mWin = new Fl_Window(ww, wh, "Downloads:"); mWin->begin(); - mScroll = new ScrollGroup(0,0,ww,wh); - mScroll->begin(); - mPG = new PackedGroup(0,0,ww,wh); - mPG->end(); - //mPG->spacing(10); - mScroll->end(); - mScroll->type(ScrollGroup::VERTICAL); + mScroll = new Fl_Scroll(0,0,ww,wh); + mScroll->begin(); + mPG = new Fl_Pack(0,0,ww-18,wh); + mPG->end(); + mScroll->end(); + mScroll->type(Fl_Scroll::VERTICAL); mWin->end(); mWin->resizable(mScroll); mWin->callback(dlwin_esc_cb, NULL); @@ -1098,14 +1114,37 @@ DLWin::DLWin(int ww, int wh) { est_sigchld(); // Set the cleanup timeout - add_timeout(1.0, cleanup_cb, mDList); + Fl::add_timeout(1.0, cleanup_cb, mDList); // Set the update timeout - add_timeout(1.0, update_cb, mDList); + Fl::add_timeout(1.0, update_cb, mDList); } // --------------------------------------------------------------------------- +/* + * Set FL_NORMAL_LABEL to interpret neither symbols (@) nor shortcuts (&) + */ +static void custLabelDraw(const Fl_Label* o, int X, int Y, int W, int H, + Fl_Align align) +{ + const int interpret_symbols = 0; + + fl_draw_shortcut = 0; + fl_font(o->font, o->size); + fl_color((Fl_Color)o->color); + fl_draw(o->value, X, Y, W, H, align, o->image, interpret_symbols); +} + +static void custLabelMeasure(const Fl_Label* o, int& W, int& H) +{ + const int interpret_symbols = 0; + + fl_draw_shortcut = 0; + fl_font(o->font, o->size); + fl_measure(o->value, W, H, interpret_symbols); +} + //int main(int argc, char **argv) @@ -1113,7 +1152,12 @@ int main() { int ww = 420, wh = 85; - lock(); + Fl::lock(); + + // Disable '@' and '&' interpretation in normal labels. + Fl::set_labeltype(FL_NORMAL_LABEL, custLabelDraw, custLabelMeasure); + + Fl::scheme(NULL); // Create the download window dl_win = new DLWin(ww, wh); @@ -1123,6 +1167,6 @@ int main() MSG("started...\n"); - return run(); + return Fl::run(); } diff --git a/dpi/https.c b/dpi/https.c index 71b0c0f9..bea9de10 100644 --- a/dpi/https.c +++ b/dpi/https.c @@ -130,7 +130,7 @@ static void yes_ssl_support(void) SSL * ssl_connection = NULL; char *dpip_tag = NULL, *cmd = NULL, *url = NULL, *http_query = NULL, - *proxy_url = NULL, *proxy_connect = NULL; + *proxy_url = NULL, *proxy_connect = NULL, *check_cert = NULL; char buf[4096]; int ret = 0; int network_socket = -1; @@ -200,8 +200,12 @@ static void yes_ssl_support(void) a_Dpip_get_attr(dpip_tag, "proxy_connect"); url = a_Dpip_get_attr(dpip_tag, "url"); http_query = a_Dpip_get_attr(dpip_tag, "query"); + if (!(check_cert = a_Dpip_get_attr(dpip_tag, "check_cert"))) { + /* allow older dillo versions use this dpi */ + check_cert = dStrdup("true"); + } - if (cmd == NULL || url == NULL || http_query == NULL){ + if (!cmd || !url || !http_query) { MSG("***Value of cmd, url or http_query is NULL" " - cannot continue\n"); exit_error = 1; @@ -288,7 +292,8 @@ static void yes_ssl_support(void) /*Use handle error function to decide what to do*/ if (exit_error == 0){ - if (handle_certificate_problem(ssl_connection) < 0){ + if (strcmp(check_cert, "true") == 0 && + handle_certificate_problem(ssl_connection) < 0){ MSG("Certificate verification error\n"); exit_error = 1; } @@ -322,6 +327,7 @@ static void yes_ssl_support(void) dFree(http_query); dFree(proxy_url); dFree(proxy_connect); + dFree(check_cert); if (network_socket != -1){ close(network_socket); diff --git a/dpid/misc_new.c b/dpid/misc_new.c index 7f963aed..8c07a4eb 100644 --- a/dpid/misc_new.c +++ b/dpid/misc_new.c @@ -71,14 +71,12 @@ Dstr *a_Misc_rdtag(int socket) */ char *a_Misc_readtag(int sock) { - char *tag, c, buf[10]; - size_t buflen, i; + char *tag, c; + size_t i; size_t taglen = 0, tagmem = 10; ssize_t rdln = 1; tag = NULL; - buf[0] = '\0'; - buflen = sizeof(buf) / sizeof(buf[0]); // new start tag = (char *) dMalloc(tagmem + 1); for (i = 0; (rdln = read(sock, &c, 1)) != 0; i++) { diff --git a/dpip/dpip.c b/dpip/dpip.c index a5517784..170e4a88 100644 --- a/dpip/dpip.c +++ b/dpip/dpip.c @@ -214,11 +214,13 @@ int a_Dpip_check_auth(const char *auth_tag) MSG_ERR("[a_Dpip_check_auth] empty file: %s\n", fname); } else { port = strtol(rcline, &tail, 10); - for (i = 0; *tail && isxdigit(tail[i+1]); ++i) - SharedSecret[i] = tail[i+1]; - SharedSecret[i] = 0; - if (strcmp(msg, SharedSecret) == 0) - ret = 1; + if (tail && port != 0) { + for (i = 0; *tail && isxdigit(tail[i+1]); ++i) + SharedSecret[i] = tail[i+1]; + SharedSecret[i] = 0; + if (strcmp(msg, SharedSecret) == 0) + ret = 1; + } } if (In) fclose(In); @@ -376,7 +378,7 @@ int a_Dpip_dsh_write_str(Dsh *dsh, int flush, const char *str) static void Dpip_dsh_read(Dsh *dsh, int blocking) { char buf[RBUF_SZ]; - int req_mode, old_flags = 0, st, ret = -3, nb = !blocking; + int req_mode, old_flags = 0, st, nb = !blocking; dReturn_if (dsh->status == DPIP_ERROR || dsh->status == DPIP_EOF); @@ -395,7 +397,6 @@ static void Dpip_dsh_read(Dsh *dsh, int blocking) continue; } else if (errno == EAGAIN) { dsh->status = DPIP_EAGAIN; - ret = -1; break; } else { MSG_ERR("[Dpip_dsh_read] %s\n", dStrerror(errno)); diff --git a/dw/findtext.cc b/dw/findtext.cc index f3e0ba20..9793db91 100644 --- a/dw/findtext.cc +++ b/dw/findtext.cc @@ -37,7 +37,7 @@ FindtextState::FindtextState () FindtextState::~FindtextState () { if (key) - delete key; + free(key); if (nexttab) delete[] nexttab; if (iterator) @@ -52,7 +52,7 @@ void FindtextState::setWidget (Widget *widget) // A widget change will restart the search. if (key) - delete key; + free(key); key = NULL; if (nexttab) delete[] nexttab; @@ -81,7 +81,7 @@ FindtextState::Result FindtextState::search (const char *key, bool caseSens, strcmp (this->key, key) != 0) { newKey = true; if (this->key) - delete this->key; + free(this->key); this->key = strdup (key); this->caseSens = caseSens; @@ -106,7 +106,7 @@ FindtextState::Result FindtextState::search (const char *key, bool caseSens, bool firstTrial = !wasHighlighted || newKey; if (search0 (backwards, firstTrial)) { - // Highlighlighting is done with a clone. + // Highlighting is done with a clone. hlIterator = iterator->cloneCharIterator (); for (int i = 0; key[i]; i++) hlIterator->next (); @@ -147,7 +147,7 @@ void FindtextState::resetSearch () unhighlight (); if (key) - delete key; + free(key); key = NULL; } diff --git a/dw/fltkcomplexbutton.cc b/dw/fltkcomplexbutton.cc index f80d0eb0..89295190 100644 --- a/dw/fltkcomplexbutton.cc +++ b/dw/fltkcomplexbutton.cc @@ -1,7 +1,5 @@ - -// fltkcomplexbutton.cc contains code from FLTK2's src/Button.cxx -// that is Copyright 1998-2006 by Bill Spitzak and others. -// (see http://svn.easysw.com/public/fltk/fltk/trunk/src/Button.cxx) +// fltkcomplexbutton.cc contains code from FLTK 1.3's src/Fl_Button.cxx +// that is Copyright 1998-2010 by Bill Spitzak and others. /* * This program is free software; you can redistribute it and/or modify @@ -18,263 +16,128 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include <fltk/events.h> -#include <fltk/damage.h> -#include <fltk/Group.h> -#include <fltk/Box.h> -#include <stdlib.h> +#include <FL/Fl.H> +#include <FL/Fl_Button.H> +#include <FL/Fl_Group.H> +#include <FL/Fl_Window.H> #include "fltkcomplexbutton.hh" -using namespace fltk; using namespace dw::fltk::ui; -/*! \class fltk::ComplexButton - - ComplexButtons generate callbacks when they are clicked by the user. You - control exactly when and how by changing the values for when(): - - fltk::WHEN_NEVER: The callback is not done, instead changed() is - turned on. - - fltk::WHEN_RELEASE: This is the default, the callback is done - after the user successfully clicks the button (i.e. they let it go - with the mouse still pointing at it), or when a shortcut is typed. - - fltk::WHEN_CHANGED : The callback is done each time the value() - changes (when the user pushes and releases the button, and as the - mouse is dragged around in and out of the button). - - ComplexButtons can also generate callbacks in response to fltk::SHORTCUT - events. The button can either have an explicit shortcut() value or a - letter shortcut can be indicated in the label() with an '&' - character before it. For the label shortcut it does not matter if - Alt is held down, but if you have an input field in the same window, - the user will have to hold down the Alt key so that the input field - does not eat the event first as an fltk::KEY event. - - \image html buttons.gif -*/ - -/*! \fn bool ComplexButton::value() const - The current value. True means it is pushed down, false means it is - not pushed down. The ToggleComplexButton subclass provides the ability for - the user to change this value permanently, otherwise it is just - temporary while the user is holding the button down. - - This is the same as Widget::state(). -*/ - -/*! \fn bool ComplexButton::value(bool) - Change the value(). Redraws the button and returns true if the new - value is different. This is the same function as Widget::state(). - See also Widget::set(), Widget::clear(), and Widget::setonly(). - - If you turn it on, a normal button will draw pushed-in, until - the user clicks it and releases it. -*/ - -static bool initial_state; +/** + Sets the current value of the button. + A non-zero value sets the button to 1 (ON), and zero sets it to 0 (OFF). + \param[in] v button value. + */ +int ComplexButton::value(int v) { + v = v ? 1 : 0; + oldval = v; + clear_changed(); + if (value_ != v) { + value_ = v; + if (box()) redraw(); + return 1; + } else { + return 0; + } +} -int ComplexButton::handle(int event) { - return handle(event, Rectangle(w(),h())); +void ComplexButton::draw() { + Fl_Color col = value() ? selection_color() : color(); + draw_box(value() ? (down_box()?down_box():fl_down(box())) : box(), col); + if (Fl::focus() == this) draw_focus(); + + // ComplexButton is a Group; draw its children + for (int i = children () - 1; i >= 0; i--) { + // set absolute coordinates for fltk-1.3 --jcid + child (i)->position(x()+(w()-child(i)->w())/2,y()+(h()-child(i)->h())/2); + draw_child (*child (i)); + } } -int ComplexButton::handle(int event, const Rectangle& rectangle) { +int ComplexButton::handle(int event) { + int newval; switch (event) { - case ENTER: - case LEAVE: - redraw_highlight(); - case MOVE: + case FL_ENTER: /* FALLTHROUGH */ + case FL_LEAVE: return 1; - case PUSH: - if (pushed()) return 1; // ignore extra pushes on currently-pushed button - initial_state = state(); - clear_flag(PUSHED); - /* do_callback(); */ - case DRAG: { - bool inside = event_inside(rectangle); - if (inside) { - if (!flag(PUSHED)) { - set_flag(PUSHED); - redraw(DAMAGE_VALUE); - } - } else { - if (flag(PUSHED)) { - clear_flag(PUSHED); - redraw(DAMAGE_VALUE); - } - } - if (when() & WHEN_CHANGED) { // momentary button must record state() - if (state(inside ? !initial_state : initial_state)) - do_callback(); + case FL_PUSH: + if (Fl::visible_focus() && handle(FL_FOCUS)) Fl::focus(this); + case FL_DRAG: + if (Fl::event_inside(this)) { + newval = !oldval; + } else + { + clear_changed(); + newval = oldval; } - return 1;} - case RELEASE: - if (!flag(PUSHED)) return 1; - clear_flag(PUSHED); - redraw(DAMAGE_VALUE); - if (type() == RADIO) - setonly(); - else if (type() == TOGGLE) - state(!initial_state); - else { - state(initial_state); - if (when() & WHEN_CHANGED) {do_callback(); return 1;} + if (newval != value_) { + value_ = newval; + set_changed(); + redraw(); + if (when() & FL_WHEN_CHANGED) do_callback(); } - if (when() & WHEN_RELEASE) do_callback(); else set_changed(); return 1; - case FOCUS: - redraw(1); // minimal redraw to just add the focus box - // grab initial focus if we are an ReturnComplexButton: - return shortcut()==ReturnKey ? 2 : 1; - case UNFOCUS: - redraw(DAMAGE_HIGHLIGHT); - return 1; - case KEY: - if (event_key() == ' ' || event_key() == ReturnKey - || event_key() == KeypadEnter) goto EXECUTE; - return 0; - case SHORTCUT: - if (!test_shortcut()) return 0; - EXECUTE: - if (type() == RADIO) { - if (!state()) { - setonly(); - if (when() & WHEN_CHANGED) do_callback(); else set_changed(); - } - } else if (type() == TOGGLE) { - state(!state()); - if (when() & WHEN_CHANGED) do_callback(); else set_changed(); + case FL_RELEASE: + if (value_ == oldval) { + if (when() & FL_WHEN_NOT_CHANGED) do_callback(); + return 1; } - if (when() & WHEN_RELEASE) do_callback(); + set_changed(); + value(oldval); + set_changed(); + if (when() & FL_WHEN_CHANGED) { + Fl_Widget_Tracker wp(this); + do_callback(); + if (wp.deleted()) return 1; + } + if (when() & FL_WHEN_RELEASE) do_callback(); return 1; + case FL_FOCUS : /* FALLTHROUGH */ + case FL_UNFOCUS : + if (Fl::visible_focus()) { + if (box() == FL_NO_BOX) { + // Widgets with the FL_NO_BOX boxtype need a parent to + // redraw, since it is responsible for redrawing the + // background... + int X = x() > 0 ? x() - 1 : 0; + int Y = y() > 0 ? y() - 1 : 0; + if (window()) window()->damage(FL_DAMAGE_ALL, X, Y, w() + 2, h() + 2); + } else redraw(); + return 1; + } else return 0; + case FL_KEYBOARD : + if (Fl::focus() == this && Fl::event_key() == ' ' && + !(Fl::event_state() & (FL_SHIFT | FL_CTRL | FL_ALT | FL_META))) { + set_changed(); + Fl_Widget_Tracker wp(this); + if (wp.deleted()) return 1; + if (when() & FL_WHEN_RELEASE) do_callback(); + return 1; + } default: return 0; } } -//////////////////////////////////////////////////////////////// - -#include <fltk/draw.h> - -extern Widget* fl_did_clipping; - -/*! - This function provides a mess of back-compatabilty and Windows - emulation to subclasses of ComplexButton to draw with. It will draw the - button according to the current state of being pushed and it's - state(). If non-zero is passed for \a glyph_width then the glyph() - is drawn in that space on the left (or on the right if negative), - and it assummes the glyph indicates the state(), so the box is only - used to indicate the pushed state. -*/ -void ComplexButton::draw(int glyph_width) const -{ - // For back-compatability, setting color() or box() directly on a plain - // button will cause it to act like buttoncolor() or buttonbox() are - // set: - Style localstyle; - const Style* style = this->style(); - if (!glyph_width) { - localstyle = *style; - if (localstyle.color_) localstyle.buttoncolor_ = localstyle.color_; - if (localstyle.box_) localstyle.buttonbox_ = localstyle.box_; - if (localstyle.labelcolor_) localstyle.textcolor_ = localstyle.labelcolor_; - style = &localstyle; - } - - Box* box = style->buttonbox(); - - Flags box_flags = flags() | OUTPUT; - Flags glyph_flags = box_flags & ~(HIGHLIGHT|OUTPUT); - if (glyph_width) box_flags &= ~STATE; - - // only draw "inside" labels: - Rectangle r(0,0,w(),h()); - - if (box == NO_BOX) { - Color bg; - if (box_flags & HIGHLIGHT && (bg = style->highlight_color())) { - setcolor(bg); - fillrect(r); - } else if (label() || (damage()&(DAMAGE_EXPOSE|DAMAGE_HIGHLIGHT))) { - // erase the background so we can redraw the label in the new color: - draw_background(); - } - // this allows these buttons to be put into browser/menus: - //fg = fl_item_labelcolor(this); - } else { - if ((damage()&(DAMAGE_EXPOSE|DAMAGE_HIGHLIGHT)) - && !box->fills_rectangle()) { - // Erase the area behind non-square boxes - draw_background(); - } - } - - // Draw the box: - drawstyle(style,box_flags); - // For back-compatability we use any directly-set selection_color() - // to color the box: - if (!glyph_width && state() && style->selection_color_) { - setbgcolor(style->selection_color_); - setcolor(contrast(style->selection_textcolor(),style->selection_color_)); - } - box->draw(r); - Rectangle r1(r); box->inset(r1); - - if (glyph_width) { - int g = abs(glyph_width); - Rectangle lr(r1); - Rectangle gr(r1, g, g); - if (glyph_width < 0) { - lr.w(lr.w()-g-3); - gr.x(r1.r()-g-3); - } else { - lr.set_x(g+3); - gr.x(r1.x()+3); - } - this->draw_label(lr, box_flags); - drawstyle(style,glyph_flags); - this->glyph()->draw(gr); - drawstyle(style,box_flags); - } else { - this->draw_label(r1, box_flags); - } - box->draw_symbol_overlay(r); -} - -void ComplexButton::draw() { - if (type() == HIDDEN) { - fl_did_clipping = this; - return; - } - draw(0); - - // ComplexButton is a Group, draw its children - for (int i = children () - 1; i >= 0; i--) - draw_child (*child (i)); +/** + The constructor creates the button using the given position, size and label. + \param[in] X, Y, W, H position and size of the widget + \param[in] L widget label, default is no label + */ +ComplexButton::ComplexButton(int X, int Y, int W, int H, const char *L) +: Fl_Group(X,Y,W,H,L) { + Fl_Group::current(0); + box(FL_UP_BOX); + down_box(FL_NO_BOX); + value_ = oldval = 0; } -//////////////////////////////////////////////////////////////// - -static NamedStyle style("ComplexButton", 0, &ComplexButton::default_style); -NamedStyle* ComplexButton::default_style = &::style; - -ComplexButton::ComplexButton(int x,int y,int w,int h, const char *l) : - Group(x,y,w,h,l) -{ - style(default_style); - highlight_color(GRAY20); - //set_click_to_focus(); +ComplexButton::~ComplexButton() { + /* + * The Fl_Group destructor clear()s the children, but layout expects + * the flat view to be around until it deletes it. + */ + remove(0); } - -//////////////////////////////////////////////////////////////// - -/*! \class fltk::ToggleComplexButton - This button turns the state() on and off each release of a click - inside of it. - - You can also convert a regular button into this by doing - type(ComplexButton::TOGGLE) to it. -*/ - -// -// diff --git a/dw/fltkcomplexbutton.hh b/dw/fltkcomplexbutton.hh index 83160c06..3a14cfb2 100644 --- a/dw/fltkcomplexbutton.hh +++ b/dw/fltkcomplexbutton.hh @@ -1,7 +1,6 @@ -// fltkcomplexbutton.hh contains code from FLTK2's fltk/Button.h -// that is Copyright 2002 by Bill Spitzak and others. -// (see http://svn.easysw.com/public/fltk/fltk/trunk/fltk/Button.h) +// fltkcomplexbutton.hh contains code from FLTK 1.3's FL/Fl_Button.H +// that is Copyright 1998-2010 by Bill Spitzak and others. /* * This program is free software; you can redistribute it and/or modify @@ -21,35 +20,56 @@ #ifndef __FLTK_COMPLEX_BUTTON_HH__ #define __FLTK_COMPLEX_BUTTON_HH__ -#include <fltk/Group.h> +#include <FL/Fl_Group.H> + +extern FL_EXPORT Fl_Shortcut fl_old_shortcut(const char*); namespace dw { namespace fltk { namespace ui { -class ComplexButton: public ::fltk::Group -{ +class FL_EXPORT ComplexButton : public Fl_Group { + + int shortcut_; + char value_; + char oldval; + uchar down_box_; + +protected: + virtual void draw(); + public: - enum {HIDDEN=3}; // back-comptability value to hide the button + virtual int handle(int); - bool value() const { return state(); } - bool value(bool v) { return state(v); } + ComplexButton(int X, int Y, int W, int H, const char *L = 0); + ~ComplexButton(); - int handle(int); - int handle(int event, const Rectangle&); - ComplexButton(int,int,int,int,const char * = 0); - ~ComplexButton() { remove_all ();}; - static ::fltk::NamedStyle* default_style; + int value(int v); - virtual void draw(); - void draw(int glyph_width) const; + /** + Returns the current value of the button (0 or 1). + */ + char value() const {return value_;} + + /** + Returns the current down box type, which is drawn when value() is non-zero. + \retval Fl_Boxtype + */ + Fl_Boxtype down_box() const {return (Fl_Boxtype)down_box_;} + + /** + Sets the down box type. The default value of 0 causes FLTK to figure out + the correct matching down version of box(). + \param[in] b down box type + */ + void down_box(Fl_Boxtype b) {down_box_ = b;} }; } // namespace ui } // namespace fltk } // namespace dw -#endif // __FLTK_COMPLEX_BUTTON_HH__ +#endif // // diff --git a/dw/fltkcore.hh b/dw/fltkcore.hh index fbff3fad..376f588e 100644 --- a/dw/fltkcore.hh +++ b/dw/fltkcore.hh @@ -13,7 +13,7 @@ class FltkResource; } // namespace fltk } // namespace core -#include <fltk/Widget.h> +#include <FL/Fl_Widget.H> #include "core.hh" #include "fltkimgbuf.hh" diff --git a/dw/fltkflatview.cc b/dw/fltkflatview.cc index 85385394..b9e85d99 100644 --- a/dw/fltkflatview.cc +++ b/dw/fltkflatview.cc @@ -21,12 +21,8 @@ #include "fltkflatview.hh" -#include <fltk/draw.h> -#include <fltk/events.h> - #include <stdio.h> -using namespace fltk; using namespace lout::container::typed; namespace dw { @@ -82,24 +78,24 @@ void FltkFlatView::setViewportSize (int width, int height, { } -int FltkFlatView::translateViewXToCanvasX (int x) +int FltkFlatView::translateViewXToCanvasX (int X) { - return x; + return X - x (); } -int FltkFlatView::translateViewYToCanvasY (int y) +int FltkFlatView::translateViewYToCanvasY (int Y) { - return y; + return Y - y (); } -int FltkFlatView::translateCanvasXToViewX (int x) +int FltkFlatView::translateCanvasXToViewX (int X) { - return x; + return X + x (); } -int FltkFlatView::translateCanvasYToViewY (int y) +int FltkFlatView::translateCanvasYToViewY (int Y) { - return y; + return Y + y (); } diff --git a/dw/fltkflatview.hh b/dw/fltkflatview.hh index 5106cbdf..8d84fda9 100644 --- a/dw/fltkflatview.hh +++ b/dw/fltkflatview.hh @@ -1,9 +1,6 @@ #ifndef __DW_FLTKFLATVIEW_HH__ #define __DW_FLTKFLATVIEW_HH__ -#include <fltk/Group.h> -#include <fltk/Scrollbar.h> - #include "core.hh" #include "fltkcore.hh" #include "fltkviewbase.hh" diff --git a/dw/fltkimgbuf.cc b/dw/fltkimgbuf.cc index e3be41a9..97cbc1b4 100644 --- a/dw/fltkimgbuf.cc +++ b/dw/fltkimgbuf.cc @@ -23,13 +23,10 @@ #include "../lout/msg.h" #include "../lout/misc.hh" -#include <fltk/draw.h> -#include <fltk/Color.h> +#include <FL/fl_draw.H> #define IMAGE_MAX_AREA (6000 * 6000) -using namespace fltk; - namespace dw { namespace fltk { @@ -302,7 +299,7 @@ int FltkImgbuf::scaledY(int ySrc) return ySrc * height / root->height; } -void FltkImgbuf::draw (::fltk::Widget *target, int xRoot, int yRoot, +void FltkImgbuf::draw (Fl_Widget *target, int xRoot, int yRoot, int x, int y, int width, int height) { // TODO: Clarify the question, whether "target" is the current widget @@ -324,10 +321,9 @@ void FltkImgbuf::draw (::fltk::Widget *target, int xRoot, int yRoot, height = this->height - y; } - // Draw - ::fltk::Rectangle rect (xRoot + x, yRoot + y, width, height); - PixelType ptype = (type == RGBA) ? ::fltk::RGBA : ::fltk::RGB; - drawimage(rawdata+bpp*(y*this->width + x),ptype,rect,bpp*this->width); + fl_draw_image(rawdata+bpp*(y*this->width + x), xRoot + x, yRoot + y, width, + height, bpp, this->width * bpp); + } } // namespace dw diff --git a/dw/fltkimgbuf.hh b/dw/fltkimgbuf.hh index 54d9ca34..30e0cc37 100644 --- a/dw/fltkimgbuf.hh +++ b/dw/fltkimgbuf.hh @@ -55,7 +55,7 @@ public: void setDeleteOnUnref (bool deleteOnUnref); bool isReferred (); - void draw (::fltk::Widget *target, int xRoot, int yRoot, + void draw (Fl_Widget *target, int xRoot, int yRoot, int x, int y, int width, int height); }; diff --git a/dw/fltkmisc.cc b/dw/fltkmisc.cc index 5d20a87a..01024f25 100644 --- a/dw/fltkmisc.cc +++ b/dw/fltkmisc.cc @@ -18,11 +18,10 @@ */ - +#include "../lout/msg.h" #include "fltkmisc.hh" -#include <fltk/events.h> -#include <fltk/Monitor.h> +#include <FL/Fl.H> #include <stdio.h> namespace dw { @@ -31,17 +30,17 @@ namespace misc { int screenWidth () { - return ::fltk::Monitor::all ().w (); + return Fl::w (); } int screenHeight () { - return ::fltk::Monitor::all ().h (); + return Fl::h (); } void warpPointer (int x, int y) { - ::fltk::warp_mouse (x, y); + MSG_ERR("no warpPointer mechanism available.\n"); } } // namespace misc diff --git a/dw/fltkplatform.cc b/dw/fltkplatform.cc index 17eb5d51..68819c91 100644 --- a/dw/fltkplatform.cc +++ b/dw/fltkplatform.cc @@ -18,24 +18,36 @@ */ #include <stdio.h> -#include <wchar.h> -#include <wctype.h> #include "../lout/msg.h" #include "fltkcore.hh" -#include <fltk/draw.h> -#include <fltk/run.h> -#include <fltk/events.h> -#include <fltk/Monitor.h> -#include <fltk/InvisibleBox.h> -#include <fltk/Tooltip.h> -#include <fltk/utf.h> +#include <FL/fl_draw.H> +#include <FL/Fl_Box.H> +#include <FL/Fl_Tooltip.H> +#include <FL/Fl_Menu_Window.H> +#include <FL/Fl_Paged_Device.H> + +/* + * Local data + */ + +/* Use of Fl_Text_Display links in a lot of printer code that we don't have + * any need for currently. This stub prevents that. */ +class FL_EXPORT Fl_Printer : public Fl_Paged_Device { +public: + static const char *class_id; + Fl_Printer(void) {}; +}; +const char *Fl_Printer::class_id = "Fl_Printer"; + +/* Tooltips */ +static Fl_Menu_Window *tt_window = NULL; +static int in_tooltip = 0, req_tooltip = 0; namespace dw { namespace fltk { -using namespace ::fltk; using namespace lout; /** @@ -47,37 +59,78 @@ container::typed::HashTable <dw::core::style::FontAttrs, new container::typed::HashTable <dw::core::style::FontAttrs, FltkFont> (false, false); +container::typed::HashTable <lout::object::ConstString, + FltkFont::FontFamily> *FltkFont::systemFonts = + NULL; + +FltkFont::FontFamily FltkFont::standardFontFamily (FL_HELVETICA, + FL_HELVETICA_BOLD, + FL_HELVETICA_ITALIC, + FL_HELVETICA_BOLD_ITALIC); + +FltkFont::FontFamily::FontFamily (Fl_Font fontNormal, Fl_Font fontBold, + Fl_Font fontItalic, Fl_Font fontBoldItalic) +{ + font[0] = fontNormal; + font[1] = fontBold; + font[2] = fontItalic; + font[3] = fontBoldItalic; +} + +void FltkFont::FontFamily::set (Fl_Font f, int attrs) +{ + int idx = 0; + if (attrs & FL_BOLD) + idx += 1; + if (attrs & FL_ITALIC) + idx += 2; + font[idx] = f; +} + +Fl_Font FltkFont::FontFamily::get (int attrs) +{ + int idx = 0; + if (attrs & FL_BOLD) + idx += 1; + if (attrs & FL_ITALIC) + idx += 2; + + // should the desired font style not exist, we + // return the normal font of the fontFamily + return font[idx] >= 0 ? font[idx] : font[0]; +} + + + FltkFont::FltkFont (core::style::FontAttrs *attrs) { + if (!systemFonts) + initSystemFonts (); + copyAttrs (attrs); int fa = 0; if (weight >= 500) - fa |= BOLD; + fa |= FL_BOLD; if (style != core::style::FONT_STYLE_NORMAL) - fa |= ITALIC; + fa |= FL_ITALIC; - font = ::fltk::font(name, fa); - if (font == NULL) { - /* - * If using xft, fltk::HELVETICA just means sans, fltk::COURIER - * means mono, and fltk::TIMES means serif. - */ - font = HELVETICA->plus (fa); - } + object::ConstString nameString (name); + FontFamily *family = systemFonts->get (&nameString); + if (!family) + family = &standardFontFamily; - setfont(font, size); - spaceWidth = misc::max(0, (int)getwidth(" ") + letterSpacing); - int xw, xh; - measure("x", xw, xh); - xHeight = xh; - ascent = (int)getascent(); - descent = (int)getdescent(); + font = family->get (fa); - /** - * \bug The code above does not seem to work, so this workaround. - */ - xHeight = ascent * 3 / 5; + fl_font(font, size); + /* WORKAROUND: fl_width(uint_t) is not working on non-xft X. + * Reported to FLTK as STR #2688 */ + spaceWidth = misc::max(0, (int)fl_width(" ") + letterSpacing); + int xx, xy, xw, xh; + fl_text_extents("x", xx, xy, xw, xh); + xHeight = xh; + descent = fl_descent(); + ascent = fl_height() - descent; } FltkFont::~FltkFont () @@ -85,10 +138,75 @@ FltkFont::~FltkFont () fontsTable->remove (this); } +static void strstrip(char *big, const char *little) +{ + if (strlen(big) >= strlen(little) && + strcasecmp(big + strlen(big) - strlen(little), little) == 0) + *(big + strlen(big) - strlen(little)) = '\0'; +} + +void FltkFont::initSystemFonts () +{ + systemFonts = new container::typed::HashTable + <lout::object::ConstString, FontFamily> (true, true); + + int k = Fl::set_fonts ("-*-iso10646-1"); + for (int i = 0; i < k; i++) { + int t; + char *name = strdup (Fl::get_font_name ((Fl_Font) i, &t)); + + // normalize font family names (strip off "bold", "italic") + if (t & FL_ITALIC) + strstrip(name, " italic"); + if (t & FL_BOLD) + strstrip(name, " bold"); + + _MSG("Found font: %s%s%s\n", name, t & FL_BOLD ? " bold" : "", + t & FL_ITALIC ? " italic" : ""); + + object::String *familyName = new object::String(name); + free (name); + FontFamily *family = systemFonts->get (familyName); + + if (family) { + family->set ((Fl_Font) i, t); + delete familyName; + } else { + // set first font of family also as normal font in case there + // is no normal (non-bold, non-italic) font + family = new FontFamily ((Fl_Font) i, -1, -1, -1); + family->set ((Fl_Font) i, t); + systemFonts->put (familyName, family); + } + } +} + +bool +FltkFont::fontExists (const char *name) +{ + if (!systemFonts) + initSystemFonts (); + object::ConstString familyName (name); + return systemFonts->get (&familyName) != NULL; +} + +Fl_Font +FltkFont::get (const char *name, int attrs) +{ + if (!systemFonts) + initSystemFonts (); + object::ConstString familyName (name); + FontFamily *family = systemFonts->get (&familyName); + if (family) + return family->get (attrs); + else + return FL_HELVETICA; +} + bool FltkPlatform::fontExists (const char *name) { - return ::fltk::font(name) != NULL; + return FltkFont::fontExists (name); } FltkFont* @@ -114,26 +232,14 @@ FltkColor::FltkColor (int color): Color (color) { this->color = color; - /* - * fltk/setcolor.cxx: - * "A Color of zero (fltk::NO_COLOR) will draw black but is - * ambiguous. It is returned as an error value or to indicate portions - * of a Style that should be inherited, and it is also used as the - * default label color for everything so that changing color zero can - * be used by the -fg switch. You should use fltk::BLACK (56) to get - * black." - * - * i.e., zero only works sometimes. - */ - if (!(colors[SHADING_NORMAL] = shadeColor (color, SHADING_NORMAL) << 8)) - colors[SHADING_NORMAL] = ::fltk::BLACK; + colors[SHADING_NORMAL] = FL_BLACK; if (!(colors[SHADING_INVERSE] = shadeColor (color, SHADING_INVERSE) << 8)) - colors[SHADING_INVERSE] = ::fltk::BLACK; + colors[SHADING_INVERSE] = FL_BLACK; if (!(colors[SHADING_DARK] = shadeColor (color, SHADING_DARK) << 8)) - colors[SHADING_DARK] = ::fltk::BLACK; + colors[SHADING_DARK] = FL_BLACK; if (!(colors[SHADING_LIGHT] = shadeColor (color, SHADING_LIGHT) << 8)) - colors[SHADING_LIGHT] = ::fltk::BLACK; + colors[SHADING_LIGHT] = FL_BLACK; } FltkColor::~FltkColor () @@ -156,35 +262,12 @@ FltkColor * FltkColor::create (int col) FltkTooltip::FltkTooltip (const char *text) : Tooltip(text) { - shown = false; - - if (!text || !strpbrk(text, "&@")) { - escaped_str = NULL; - } else { - /* - * WORKAROUND: ::fltk::Tooltip::tooltip_timeout() makes instance_ - * if necessary, and immediately uses it. This means that we can't - * get our hands on it to set RAW_LABEL until after it has been shown - * once. So let's escape the special characters ourselves. - */ - const char *src = text; - char *dest = escaped_str = (char *) malloc(strlen(text) * 2 + 1); - - while (*src) { - if (*src == '&' || *src == '@') - *dest++ = *src; - *dest++ = *src++; - } - *dest = '\0'; - } } FltkTooltip::~FltkTooltip () { - if (shown) - ::fltk::Tooltip::exit(); - if (escaped_str) - free(escaped_str); + if (in_tooltip || req_tooltip) + cancel(); /* cancel tooltip window */ } FltkTooltip *FltkTooltip::create (const char *text) @@ -192,40 +275,115 @@ FltkTooltip *FltkTooltip::create (const char *text) return new FltkTooltip(text); } +/* + * Tooltip callback: used to delay it a bit + * INVARIANT: Only one instance of this function is requested. + */ +static void tooltip_tcb(void *data) +{ + req_tooltip = 2; + ((FltkTooltip *)data)->onEnter(); + req_tooltip = 0; +} + void FltkTooltip::onEnter() { - fltk::Widget *widget = fltk::belowmouse(); + _MSG("FltkTooltip::onEnter\n"); + if (!str || !*str) + return; + if (req_tooltip == 0) { + Fl::remove_timeout(tooltip_tcb); + Fl::add_timeout(1.0, tooltip_tcb, this); + req_tooltip = 1; + return; + } - ::fltk::Tooltip::enter(widget, *((fltk::Rectangle *)widget), - escaped_str ? escaped_str : str); - shown = true; + if (!tt_window) { + tt_window = new Fl_Menu_Window(0,0,100,24); + tt_window->set_override(); + tt_window->box(FL_NO_BOX); + Fl_Box *b = new Fl_Box(0,0,100,24); + b->box(FL_BORDER_BOX); + b->color(fl_color_cube(FL_NUM_RED-1, FL_NUM_GREEN-1, FL_NUM_BLUE-2)); + b->labelcolor(FL_BLACK); + b->labelfont(FL_HELVETICA); + b->labelsize(14); + b->align(FL_ALIGN_WRAP|FL_ALIGN_LEFT|FL_ALIGN_INSIDE); + tt_window->resizable(b); + tt_window->end(); + } + + /* prepare tooltip window */ + int x, y; + Fl_Box *box = (Fl_Box*)tt_window->child(0); + box->label(str); + Fl::get_mouse(x,y); y += 6; + /* calculate window size */ + int ww, hh; + ww = 800; // max width; + box->measure_label(ww, hh); + ww += 6 + 2 * Fl::box_dx(box->box()); + hh += 6 + 2 * Fl::box_dy(box->box()); + tt_window->resize(x,y,ww,hh); + tt_window->show(); + in_tooltip = 1; } +/* + * Leaving the widget cancels the tooltip + */ void FltkTooltip::onLeave() { - ::fltk::Tooltip::exit(); - shown = false; + _MSG(" FltkTooltip::onLeave in_tooltip=%d\n", in_tooltip); + cancel(); +} + +void FltkPlatform::cancelTooltip() +{ + FltkTooltip::cancel(); +} + +/* + * Remove a shown tooltip or cancel a pending one + */ +void FltkTooltip::cancel() +{ + if (req_tooltip) { + Fl::remove_timeout(tooltip_tcb); + req_tooltip = 0; + } + if (!in_tooltip) return; + in_tooltip = 0; + tt_window->hide(); + + /* WORKAROUND: (Black magic here) + * Hiding a tooltip with the keyboard or mousewheel doesn't work. + * The code below "fixes" the problem */ + Fl_Widget *widget = Fl::belowmouse(); + if (widget && widget->window()) { + widget->window()->damage(FL_DAMAGE_EXPOSE,0,0,1,1); + } } void FltkTooltip::onMotion() { } -void FltkView::addFltkWidget (::fltk::Widget *widget, +void FltkView::addFltkWidget (Fl_Widget *widget, core::Allocation *allocation) { } -void FltkView::removeFltkWidget (::fltk::Widget *widget) +void FltkView::removeFltkWidget (Fl_Widget *widget) { } -void FltkView::allocateFltkWidget (::fltk::Widget *widget, +void FltkView::allocateFltkWidget (Fl_Widget *widget, core::Allocation *allocation) { } -void FltkView::drawFltkWidget (::fltk::Widget *widget, core::Rectangle *area) +void FltkView::drawFltkWidget (Fl_Widget *widget, core::Rectangle *area) { } @@ -310,7 +468,7 @@ FltkPlatform::FltkPlatform () FltkPlatform::~FltkPlatform () { if (idleFuncRunning) - remove_idle (generalStaticIdle, (void*)this); + Fl::remove_idle (generalStaticIdle, (void*)this); delete idleQueue; delete resources; } @@ -354,32 +512,32 @@ int FltkPlatform::textWidth (core::style::Font *font, const char *text, int len) { char chbuf[4]; - wchar_t wc, wcu; + int c, cu; int width = 0; FltkFont *ff = (FltkFont*) font; int curr = 0, next = 0, nb; - if (font->fontVariant == 1) { + if (font->fontVariant == core::style::FONT_VARIANT_SMALL_CAPS) { int sc_fontsize = lout::misc::roundInt(ff->size * 0.78); for (curr = 0; next < len; curr = next) { next = nextGlyph(text, curr); - wc = utf8decode(text + curr, text + next, &nb); - if ((wcu = towupper(wc)) == wc) { + c = fl_utf8decode(text + curr, text + next, &nb); + if ((cu = fl_toupper(c)) == c) { /* already uppercase, just draw the character */ - setfont(ff->font, ff->size); + fl_font(ff->font, ff->size); width += font->letterSpacing; - width += (int)getwidth(text + curr, next - curr); + width += (int)fl_width(text + curr, next - curr); } else { /* make utf8 string for converted char */ - nb = utf8encode(wcu, chbuf); - setfont(ff->font, sc_fontsize); + nb = fl_utf8encode(cu, chbuf); + fl_font(ff->font, sc_fontsize); width += font->letterSpacing; - width += (int)getwidth(chbuf, nb); + width += (int)fl_width(chbuf, nb); } } } else { - setfont (ff->font, ff->size); - width = (int) getwidth (text, len); + fl_font (ff->font, ff->size); + width = (int) fl_width (text, len); if (font->letterSpacing) { int curr = 0, next = 0; @@ -397,22 +555,28 @@ int FltkPlatform::textWidth (core::style::Font *font, const char *text, int FltkPlatform::nextGlyph (const char *text, int idx) { - return utf8fwd (&text[idx + 1], text, &text[strlen (text)]) - text; + return fl_utf8fwd (&text[idx + 1], text, &text[strlen (text)]) - text; } int FltkPlatform::prevGlyph (const char *text, int idx) { - return utf8back (&text[idx - 1], text, &text[strlen (text)]) - text; + return fl_utf8back (&text[idx - 1], text, &text[strlen (text)]) - text; } float FltkPlatform::dpiX () { - return ::fltk::Monitor::all ().dpi_x (); + float horizontal, vertical; + + Fl::screen_dpi(horizontal, vertical); + return horizontal; } float FltkPlatform::dpiY () { - return ::fltk::Monitor::all ().dpi_y (); + float horizontal, vertical; + + Fl::screen_dpi(horizontal, vertical); + return vertical; } void FltkPlatform::generalStaticIdle (void *data) @@ -435,7 +599,7 @@ void FltkPlatform::generalIdle () if (idleQueue->isEmpty()) { idleFuncRunning = false; - remove_idle (generalStaticIdle, (void*)this); + Fl::remove_idle (generalStaticIdle, (void*)this); } } @@ -449,7 +613,7 @@ int FltkPlatform::addIdle (void (core::Layout::*func) ()) * idle function, the passed idle function is put into a queue. */ if (!idleFuncRunning) { - add_idle (generalStaticIdle, (void*)this); + Fl::add_idle (generalStaticIdle, (void*)this); idleFuncRunning = true; } @@ -478,7 +642,7 @@ void FltkPlatform::removeIdle (int idleId) } if (idleFuncRunning && idleQueue->isEmpty()) - remove_idle (generalStaticIdle, (void*)this); + Fl::remove_idle (generalStaticIdle, (void*)this); } core::style::Font *FltkPlatform::createFont (core::style::FontAttrs @@ -500,7 +664,7 @@ core::style::Tooltip *FltkPlatform::createTooltip (const char *text) void FltkPlatform::copySelection(const char *text) { - fltk::copy(text, strlen(text), false); + Fl::copy(text, strlen(text), 0); } core::Imgbuf *FltkPlatform::createImgbuf (core::Imgbuf::Type type, diff --git a/dw/fltkplatform.hh b/dw/fltkplatform.hh index 7a708938..db4bc794 100644 --- a/dw/fltkplatform.hh +++ b/dw/fltkplatform.hh @@ -5,8 +5,6 @@ # error Do not include this file directly, use "fltkcore.hh" instead. #endif -#include <fltk/Font.h> - namespace dw { /** @@ -16,16 +14,33 @@ namespace fltk { class FltkFont: public core::style::Font { + class FontFamily: public lout::object::Object { + Fl_Font font[4]; + public: + FontFamily (Fl_Font fontNormal, Fl_Font fontBold, + Fl_Font fontItalic, Fl_Font fontBoldItalic); + void set (Fl_Font, int attrs); + Fl_Font get (int attrs); + }; + + static FontFamily standardFontFamily; + + static lout::container::typed::HashTable <lout::object::ConstString, + FontFamily> *systemFonts; static lout::container::typed::HashTable <dw::core::style::FontAttrs, FltkFont> *fontsTable; FltkFont (core::style::FontAttrs *attrs); ~FltkFont (); + static void initSystemFonts (); + public: - ::fltk::Font *font; + Fl_Font font; static FltkFont *create (core::style::FontAttrs *attrs); + static bool fontExists (const char *name); + static Fl_Font get (const char *name, int attrs); }; @@ -48,10 +63,9 @@ class FltkTooltip: public core::style::Tooltip private: FltkTooltip (const char *text); ~FltkTooltip (); - bool shown; - char *escaped_str; /* fltk WORKAROUND */ public: static FltkTooltip *create(const char *text); + static void cancel(); void onEnter(); void onLeave(); void onMotion(); @@ -66,12 +80,12 @@ class FltkView: public core::View public: virtual bool usesFltkWidgets () = 0; - virtual void addFltkWidget (::fltk::Widget *widget, + virtual void addFltkWidget (Fl_Widget *widget, core::Allocation *allocation); - virtual void removeFltkWidget (::fltk::Widget *widget); - virtual void allocateFltkWidget (::fltk::Widget *widget, + virtual void removeFltkWidget (Fl_Widget *widget); + virtual void allocateFltkWidget (Fl_Widget *widget, core::Allocation *allocation); - virtual void drawFltkWidget (::fltk::Widget *widget, core::Rectangle *area); + virtual void drawFltkWidget (Fl_Widget *widget, core::Rectangle *area); }; @@ -152,6 +166,7 @@ public: bool fontExists (const char *name); core::style::Color *createColor (int color); core::style::Tooltip *createTooltip (const char *text); + void cancelTooltip(); core::Imgbuf *createImgbuf (core::Imgbuf::Type type, int width, int height); diff --git a/dw/fltkpreview.cc b/dw/fltkpreview.cc index 7096420f..ecb96f22 100644 --- a/dw/fltkpreview.cc +++ b/dw/fltkpreview.cc @@ -22,15 +22,13 @@ #include "fltkpreview.hh" #include "fltkmisc.hh" -#include <fltk/events.h> -#include <fltk/xbmImage.h> -#include <fltk/draw.h> +#include <FL/Fl.H> +#include <FL/Fl_Bitmap.H> +#include <FL/fl_draw.H> #include <stdio.h> #include "preview.xbm" -using namespace ::fltk; - namespace dw { namespace fltk { @@ -126,7 +124,7 @@ void FltkPreview::drawText (core::style::Font *font, * else that measures text). */ FltkFont *ff = (FltkFont*)font; - setfont(ff->font, translateCanvasXToViewX (ff->size)); + Fl::set_font(ff->font, translateCanvasXToViewX (ff->size)); #if 0 /** * \todo Normally, this should already be known, maybe it @@ -144,9 +142,16 @@ void FltkPreview::drawText (core::style::Font *font, setcolor(((FltkColor*)color)->colors[shading]); fillrect (rect); #endif - setcolor(((FltkColor*)color)->colors[shading]); - drawtext(text, len, - translateCanvasXToViewX (x), translateCanvasYToViewY (y)); + fl_color(((FltkColor*)color)->colors[shading]); + fl_draw(text, len, translateCanvasXToViewX (x), translateCanvasYToViewY(y)); +} + +void FltkPreview::drawSimpleWrappedText (core::style::Font *font, + core::style::Color *color, + core::style::Color::Shading shading, + int x, int y, int w, int h, + const char *text) +{ } void FltkPreview::drawImage (core::Imgbuf *imgbuf, int xRoot, int yRoot, @@ -159,7 +164,7 @@ bool FltkPreview::usesFltkWidgets () return false; } -void FltkPreview::drawFltkWidget (::fltk::Widget *widget, +void FltkPreview::drawFltkWidget (Fl_Widget *widget, core::Rectangle *area) { } @@ -167,9 +172,9 @@ void FltkPreview::drawFltkWidget (::fltk::Widget *widget, // ---------------------------------------------------------------------- FltkPreviewWindow::FltkPreviewWindow (dw::core::Layout *layout): - MenuWindow (1, 1) + Fl_Menu_Window (1, 1) { - box (EMBOSSED_BOX); + box (FL_EMBOSSED_BOX); begin (); preview = new FltkPreview (BORDER_WIDTH, BORDER_WIDTH, 1, 1, layout); @@ -205,7 +210,7 @@ void FltkPreviewWindow::reallocate () height = preview->canvasHeight * maxWidth / preview->canvasWidth; } - get_mouse(mx, my); + Fl::get_mouse(mx, my); posX = mx - preview->translateCanvasXToViewX (preview->scrollX + preview->scrollWidth / 2); @@ -237,13 +242,12 @@ void FltkPreviewWindow::reallocate () resize (posX, posY, width, height); - preview->w (w () - 2 * BORDER_WIDTH); - preview->h (h () - 2 * BORDER_WIDTH); + preview->size(w () - 2 * BORDER_WIDTH, h () - 2 * BORDER_WIDTH); } void FltkPreviewWindow::hideWindow () { - Window::hide (); + Fl_Window::hide (); } void FltkPreviewWindow::scrollTo (int mouseX, int mouseY) @@ -263,9 +267,9 @@ void FltkPreviewWindow::scrollTo (int mouseX, int mouseY) FltkPreviewButton::FltkPreviewButton (int x, int y, int w, int h, dw::core::Layout *layout, const char *label): - Button (x, y, w, h, label) + Fl_Button (x, y, w, h, label) { - image (new xbmImage (preview_bits, preview_width, preview_height)); + image (new Fl_Bitmap (preview_bits, preview_width, preview_height)); window = new FltkPreviewWindow (layout); } @@ -278,23 +282,23 @@ int FltkPreviewButton::handle (int event) /** \bug Some parts are missing. */ switch (event) { - case PUSH: + case FL_PUSH: window->showWindow (); - return Button::handle (event); + return Fl_Button::handle (event); - case DRAG: + case FL_DRAG: if (window->visible ()) { - window->scrollTo (event_x_root (), event_y_root ()); + window->scrollTo (Fl::event_x_root (), Fl::event_y_root ()); return 1; } - return Button::handle (event); + return Fl_Button::handle (event); - case RELEASE: + case FL_RELEASE: window->hideWindow (); - return Button::handle (event); + return Fl_Button::handle (event); default: - return Button::handle (event); + return Fl_Button::handle (event); } } diff --git a/dw/fltkpreview.hh b/dw/fltkpreview.hh index 13db2811..2382b861 100644 --- a/dw/fltkpreview.hh +++ b/dw/fltkpreview.hh @@ -1,8 +1,8 @@ #ifndef __FlTKPREVIEW_HH__ #define __FlTKPREVIEW_HH__ -#include <fltk/Button.h> -#include <fltk/MenuWindow.h> +#include <FL/Fl_Button.H> +#include <FL/Fl_Menu_Window.H> #include "fltkviewbase.hh" namespace dw { @@ -42,15 +42,20 @@ public: core::style::Color *color, core::style::Color::Shading shading, int x, int y, const char *text, int len); + void drawSimpleWrappedText (core::style::Font *font, + core::style::Color *color, + core::style::Color::Shading shading, + int x, int y, int w, int h, + const char *text); void drawImage (core::Imgbuf *imgbuf, int xRoot, int yRoot, int x, int y, int width, int height); bool usesFltkWidgets (); - void drawFltkWidget (::fltk::Widget *widget, core::Rectangle *area); + void drawFltkWidget (Fl_Widget *widget, core::Rectangle *area); }; -class FltkPreviewWindow: public ::fltk::MenuWindow +class FltkPreviewWindow: public Fl_Menu_Window { private: enum { BORDER_WIDTH = 2 }; @@ -71,7 +76,7 @@ public: }; -class FltkPreviewButton: public ::fltk::Button +class FltkPreviewButton: public Fl_Button { private: FltkPreviewWindow *window; diff --git a/dw/fltkui.cc b/dw/fltkui.cc index ff80e14c..c0c8ff42 100644 --- a/dw/fltkui.cc +++ b/dw/fltkui.cc @@ -25,21 +25,57 @@ #include "../lout/msg.h" #include "../lout/misc.hh" +#include <FL/Fl.H> +#include <FL/fl_draw.H> +#include <FL/Fl_Input.H> +#include <FL/Fl_Text_Editor.H> +#include <FL/Fl_Check_Button.H> +#include <FL/Fl_Round_Button.H> +#include <FL/Fl_Choice.H> +#include <FL/Fl_Tree.H> + #include <stdio.h> -#include <fltk/Widget.h> -#include <fltk/Group.h> -#include <fltk/Input.h> -#include <fltk/TextEditor.h> -#include <fltk/RadioButton.h> -#include <fltk/CheckButton.h> -#include <fltk/Choice.h> -#include <fltk/Browser.h> -#include <fltk/Font.h> -#include <fltk/draw.h> -#include <fltk/Symbol.h> -#include <fltk/Item.h> -#include <fltk/ItemGroup.h> -#include <fltk/events.h> + +//---------------------------------------------------------------------------- +/* + * Local sub classes + */ + +/* + * Used to enable CTRL+{a,e,d,k} in form inputs (for start,end,del,cut) + */ +class CustInput2 : public Fl_Input { +public: + CustInput2 (int x, int y, int w, int h, const char* l=0) : + Fl_Input(x,y,w,h,l) {}; + int handle(int e); +}; + +int CustInput2::handle(int e) +{ + int k = Fl::event_key(); + + _MSG("CustInput2::handle event=%d\n", e); + + // We're only interested in some flags + unsigned modifier = Fl::event_state() & (FL_SHIFT | FL_CTRL | FL_ALT); + + if (e == FL_KEYBOARD && modifier == FL_CTRL) { + if (k == 'a' || k == 'e') { + position(k == 'a' ? 0 : size()); + return 1; + } else if (k == 'k') { + cut(position(), size()); + return 1; + } else if (k == 'd') { + cut(position(), position()+1); + return 1; + } + } + return Fl_Input::handle(e); +} + +//---------------------------------------------------------------------------- namespace dw { namespace fltk { @@ -139,14 +175,12 @@ void FltkResource::setStyle (core::style::Style *style) setWidgetStyle (widget, style); } -void FltkResource::setWidgetStyle (::fltk::Widget *widget, +void FltkResource::setWidgetStyle (Fl_Widget *widget, core::style::Style *style) { FltkFont *font = (FltkFont*)style->font; widget->labelsize (font->size); widget->labelfont (font->font); - widget->textsize (font->size); - widget->textfont (font->font); FltkColor *bg = (FltkColor*)style->backgroundColor; if (bg) { @@ -155,21 +189,13 @@ void FltkResource::setWidgetStyle (::fltk::Widget *widget, if (style->color) { int style_fg = ((FltkColor*)style->color)->colors [FltkColor::SHADING_NORMAL]; - ::fltk::Color fg = ::fltk::contrast(style_fg, normal_bg); + Fl_Color fg = fl_contrast(style_fg, normal_bg); widget->labelcolor(fg); - widget->textcolor(fg); widget->selection_color(fg); } widget->color(normal_bg); - widget->buttoncolor(normal_bg); - widget->selection_textcolor(normal_bg); - if (widget->type() != ::fltk::Widget::RADIO && - widget->type() != ::fltk::Widget::TOGGLE) { - /* it looks awful to highlight the buttons */ - widget->highlight_color(bg->colors[FltkColor::SHADING_LIGHT]); - } } } @@ -250,19 +276,17 @@ FltkLabelButtonResource::FltkLabelButtonResource (FltkPlatform *platform, FltkLabelButtonResource::~FltkLabelButtonResource () { - delete label; + free((char *)label); } -::fltk::Widget *FltkLabelButtonResource::createNewWidget (core::Allocation - *allocation) +Fl_Widget *FltkLabelButtonResource::createNewWidget (core::Allocation + *allocation) { - ::fltk::Button *button = - new ::fltk::Button (allocation->x, allocation->y, allocation->width, - allocation->ascent + allocation->descent, - label); - button->set_flag (::fltk::RAW_LABEL); + Fl_Button *button = + new Fl_Button (allocation->x, allocation->y, allocation->width, + allocation->ascent + allocation->descent, label); button->callback (widgetCallback, this); - button->when (::fltk::WHEN_RELEASE); + button->when (FL_WHEN_RELEASE); return button; } @@ -270,9 +294,9 @@ void FltkLabelButtonResource::sizeRequest (core::Requisition *requisition) { if (style) { FltkFont *font = (FltkFont*)style->font; - ::fltk::setfont(font->font,font->size); + fl_font(font->font,font->size); requisition->width = - (int)::fltk::getwidth (label, strlen (label)) + (int)fl_width (label, strlen (label)) + 2 * RELIEF_X_THICKNESS; requisition->ascent = font->ascent + RELIEF_Y_THICKNESS; requisition->descent = font->descent + RELIEF_Y_THICKNESS; @@ -290,35 +314,32 @@ void FltkLabelButtonResource::sizeRequest (core::Requisition *requisition) */ static core::ButtonState getDwButtonState () { - int s1 = ::fltk::event_state (); + int s1 = Fl::event_state (); int s2 = (core::ButtonState)0; - if (s1 & ::fltk::SHIFT) s2 |= core::SHIFT_MASK; - if (s1 & ::fltk::CTRL) s2 |= core::CONTROL_MASK; - if (s1 & ::fltk::ALT) s2 |= core::META_MASK; - if (s1 & ::fltk::BUTTON1) s2 |= core::BUTTON1_MASK; - if (s1 & ::fltk::BUTTON2) s2 |= core::BUTTON2_MASK; - if (s1 & ::fltk::BUTTON3) s2 |= core::BUTTON3_MASK; + if (s1 & FL_SHIFT) s2 |= core::SHIFT_MASK; + if (s1 & FL_CTRL) s2 |= core::CONTROL_MASK; + if (s1 & FL_ALT) s2 |= core::META_MASK; + if (s1 & FL_BUTTON1) s2 |= core::BUTTON1_MASK; + if (s1 & FL_BUTTON2) s2 |= core::BUTTON2_MASK; + if (s1 & FL_BUTTON3) s2 |= core::BUTTON3_MASK; return (core::ButtonState)s2; } static void setButtonEvent(dw::core::EventButton *event) { - event->xCanvas = ::fltk::event_x(); - event->yCanvas = ::fltk::event_y(); + event->xCanvas = Fl::event_x(); + event->yCanvas = Fl::event_y(); event->state = getDwButtonState(); - event->button = ::fltk::event_button(); - event->numPressed = ::fltk::event_clicks() + 1; + event->button = Fl::event_button(); + event->numPressed = Fl::event_clicks() + 1; } -void FltkLabelButtonResource::widgetCallback (::fltk::Widget *widget, +void FltkLabelButtonResource::widgetCallback (Fl_Widget *widget, void *data) { - if ((widget->when () & ::fltk::WHEN_RELEASE) && - ((::fltk::event_key() == ::fltk::ReturnKey) || - (::fltk::event_button() == ::fltk::LeftButton || - ::fltk::event_button() == ::fltk::MiddleButton))) { + if (!Fl::event_button3()) { FltkLabelButtonResource *lbr = (FltkLabelButtonResource*) data; dw::core::EventButton event; setButtonEvent(&event); @@ -334,7 +355,7 @@ const char *FltkLabelButtonResource::getLabel () void FltkLabelButtonResource::setLabel (const char *label) { - delete this->label; + free((char *)this->label); this->label = strdup (label); widget->label (this->label); @@ -358,22 +379,17 @@ FltkComplexButtonResource::~FltkComplexButtonResource () { } -void FltkComplexButtonResource::widgetCallback (::fltk::Widget *widget, +void FltkComplexButtonResource::widgetCallback (Fl_Widget *widget, void *data) { FltkComplexButtonResource *res = (FltkComplexButtonResource*)data; - if (widget->when() == ::fltk::WHEN_RELEASE && - ((::fltk::event_key() == ::fltk::ReturnKey) || - (::fltk::event_button() == ::fltk::LeftButton || - ::fltk::event_button() == ::fltk::MiddleButton))) { - res->click_x = ::fltk::event_x(); - res->click_y = ::fltk::event_y(); + if (!Fl::event_button3()) { + res->click_x = Fl::event_x(); + res->click_y = Fl::event_y(); dw::core::EventButton event; setButtonEvent(&event); res->emitClicked(&event); - } else { - ((FltkViewBase*)res->flatView)->handle(::fltk::event()); } } @@ -423,16 +439,16 @@ int FltkComplexButtonResource::reliefYThickness () } -::fltk::Widget *FltkComplexButtonResource::createNewWidget (core::Allocation +Fl_Widget *FltkComplexButtonResource::createNewWidget (core::Allocation *allocation) { ComplexButton *button = new ComplexButton (allocation->x, allocation->y, allocation->width, allocation->ascent + allocation->descent); button->callback (widgetCallback, this); - button->when (::fltk::WHEN_RELEASE); + button->when (FL_WHEN_RELEASE); if (!relief) - button->box(::fltk::FLAT_BOX); + button->box(FL_FLAT_BOX); flatView = new FltkFlatView (allocation->x + reliefXThickness (), allocation->y + reliefYThickness (), @@ -455,6 +471,7 @@ FltkEntryResource::FltkEntryResource (FltkPlatform *platform, int maxLength, this->maxLength = maxLength; this->password = password; this->label = label ? strdup(label) : NULL; + this->label_w = 0; initText = NULL; editable = false; @@ -465,25 +482,25 @@ FltkEntryResource::FltkEntryResource (FltkPlatform *platform, int maxLength, FltkEntryResource::~FltkEntryResource () { if (initText) - delete initText; + free((char *)initText); if (label) - delete label; + free(label); } -::fltk::Widget *FltkEntryResource::createNewWidget (core::Allocation +Fl_Widget *FltkEntryResource::createNewWidget (core::Allocation *allocation) { - ::fltk::Input *input = - new ::fltk::Input (allocation->x, allocation->y, allocation->width, - allocation->ascent + allocation->descent); + Fl_Input *input = + new CustInput2(allocation->x, allocation->y, allocation->width, + allocation->ascent + allocation->descent); if (password) - input->type(::fltk::Input::SECRET); + input->type(FL_SECRET_INPUT); input->callback (widgetCallback, this); - input->when (::fltk::WHEN_ENTER_KEY_ALWAYS); + input->when (FL_WHEN_ENTER_KEY_ALWAYS); if (label) { input->label(label); - input->set_flag(::fltk::ALIGN_INSIDE_LEFT); + input->align(FL_ALIGN_LEFT); } if (initText) input->value (initText); @@ -491,6 +508,26 @@ FltkEntryResource::~FltkEntryResource () return input; } +void FltkEntryResource::setWidgetStyle (Fl_Widget *widget, + core::style::Style *style) +{ + Fl_Input *in = (Fl_Input *)widget; + + FltkResource::setWidgetStyle(widget, style); + + in->textcolor(widget->labelcolor()); + in->cursor_color(in->textcolor()); + in->textsize(in->labelsize()); + in->textfont(in->labelfont()); + + if (label) { + int h; + label_w = 0; + widget->measure_label(label_w, h); + label_w += RELIEF_X_THICKNESS; + } +} + void FltkEntryResource::setDisplayed(bool displayed) { FltkResource::setDisplayed(displayed); @@ -501,11 +538,13 @@ void FltkEntryResource::sizeRequest (core::Requisition *requisition) { if (displayed() && style) { FltkFont *font = (FltkFont*)style->font; - ::fltk::setfont(font->font,font->size); + fl_font(font->font,font->size); + /* WORKAROUND: fl_width(uint_t) is not working on non-xft X. + * Reported to FLTK as STR #2688 */ requisition->width = - (int)::fltk::getwidth ("n", 1) + (int)fl_width ("n") * (maxLength == UNLIMITED_MAX_LENGTH ? 10 : maxLength) - + 2 * RELIEF_X_THICKNESS; + + label_w + (2 * RELIEF_X_THICKNESS); requisition->ascent = font->ascent + RELIEF_Y_THICKNESS; requisition->descent = font->descent + RELIEF_Y_THICKNESS; } else { @@ -515,33 +554,38 @@ void FltkEntryResource::sizeRequest (core::Requisition *requisition) } } -void FltkEntryResource::widgetCallback (::fltk::Widget *widget, - void *data) +void FltkEntryResource::sizeAllocate (core::Allocation *allocation) { - /* The (::fltk::event_key() == ::fltk::ReturnKey) test - * is necessary because WHEN_ENTER_KEY also includes - * other events we're not interested in. For instance pressing - * The Back or Forward, buttons, or the first click on a rendered - * page. BUG: this must be investigated and reported to FLTK2 team - */ - _MSG("when = %d\n", widget->when ()); - if ((widget->when () & ::fltk::WHEN_ENTER_KEY_ALWAYS) && - (::fltk::event_key() == ::fltk::ReturnKey)) - ((FltkEntryResource*)data)->emitActivate (); + if (!label) { + FltkResource::sizeAllocate(allocation); + } else { + this->allocation = *allocation; + + /* push the Fl_Input over to the right of the label */ + core::Allocation a = this->allocation; + a.x += this->label_w; + a.width -= this->label_w; + view->allocateFltkWidget (widget, &a); + } +} + +void FltkEntryResource::widgetCallback (Fl_Widget *widget, void *data) +{ + ((FltkEntryResource*)data)->emitActivate (); } const char *FltkEntryResource::getText () { - return ((::fltk::Input*)widget)->value (); + return ((Fl_Input*)widget)->value (); } void FltkEntryResource::setText (const char *text) { if (initText) - delete initText; + free((char *)initText); initText = strdup (text); - ((::fltk::Input*)widget)->value (initText); + ((Fl_Input*)widget)->value (initText); } bool FltkEntryResource::isEditable () @@ -560,7 +604,8 @@ FltkMultiLineTextResource::FltkMultiLineTextResource (FltkPlatform *platform, int cols, int rows): FltkSpecificResource <dw::core::ui::MultiLineTextResource> (platform) { - buffer = new ::fltk::TextBuffer; + buffer = new Fl_Text_Buffer; + text_copy = NULL; editable = false; numCols = cols; @@ -582,29 +627,45 @@ FltkMultiLineTextResource::FltkMultiLineTextResource (FltkPlatform *platform, FltkMultiLineTextResource::~FltkMultiLineTextResource () { /* Free memory avoiding a double-free of text buffers */ - ((::fltk::TextEditor *) widget)->buffer (0); + ((Fl_Text_Editor *) widget)->buffer (0); delete buffer; + if (text_copy) + free(text_copy); } -::fltk::Widget *FltkMultiLineTextResource::createNewWidget (core::Allocation +Fl_Widget *FltkMultiLineTextResource::createNewWidget (core::Allocation *allocation) { - ::fltk::TextEditor *text = - new ::fltk::TextEditor (allocation->x, allocation->y, - allocation->width, - allocation->ascent + allocation->descent); + Fl_Text_Editor *text = + new Fl_Text_Editor (allocation->x, allocation->y, allocation->width, + allocation->ascent + allocation->descent); + text->wrap_mode(Fl_Text_Display::WRAP_AT_BOUNDS, 0); text->buffer (buffer); return text; } +void FltkMultiLineTextResource::setWidgetStyle (Fl_Widget *widget, + core::style::Style *style) +{ + Fl_Text_Editor *ed = (Fl_Text_Editor *)widget; + + FltkResource::setWidgetStyle(widget, style); + + ed->textcolor(widget->labelcolor()); + ed->cursor_color(ed->textcolor()); + ed->textsize(ed->labelsize()); + ed->textfont(ed->labelfont()); +} + void FltkMultiLineTextResource::sizeRequest (core::Requisition *requisition) { if (style) { FltkFont *font = (FltkFont*)style->font; - ::fltk::setfont(font->font,font->size); + fl_font(font->font,font->size); + /* WORKAROUND: fl_width(uint_t) is not working on non-xft X. + * Reported to FLTK as STR #2688 */ requisition->width = - (int)::fltk::getwidth ("n", 1) * numCols + - 2 * RELIEF_X_THICKNESS; + (int)fl_width ("n") * numCols + 2 * RELIEF_X_THICKNESS; requisition->ascent = RELIEF_Y_THICKNESS + font->ascent + (font->ascent + font->descent) * (numRows - 1); @@ -620,7 +681,13 @@ void FltkMultiLineTextResource::sizeRequest (core::Requisition *requisition) const char *FltkMultiLineTextResource::getText () { - return buffer->text (); + /* FLTK-1.3 insists upon returning a new copy of the buffer text, so + * we have to keep track of it. + */ + if (text_copy) + free(text_copy); + text_copy = buffer->text(); + return text_copy; } void FltkMultiLineTextResource::setText (const char *text) @@ -656,14 +723,23 @@ FltkToggleButtonResource<I>::~FltkToggleButtonResource () template <class I> -::fltk::Widget *FltkToggleButtonResource<I>::createNewWidget (core::Allocation +Fl_Widget *FltkToggleButtonResource<I>::createNewWidget (core::Allocation *allocation) { - ::fltk::Button *button = createNewButton (allocation); + Fl_Button *button = createNewButton (allocation); button->value (initActivated); return button; } +template <class I> +void FltkToggleButtonResource<I>::setWidgetStyle (Fl_Widget *widget, + core::style::Style *style) +{ + FltkResource::setWidgetStyle(widget, style); + + widget->selection_color(FL_BLACK); +} + template <class I> void FltkToggleButtonResource<I>::sizeRequest (core::Requisition *requisition) @@ -672,7 +748,7 @@ void FltkToggleButtonResource<I>::sizeRequest (core::Requisition *requisition) (this->FltkResource::style ? this->FltkResource::style->font : NULL); if (font) { - ::fltk::setfont(font->font, font->size); + fl_font(font->font, font->size); requisition->width = font->ascent + font->descent + 2*RELIEF_X_THICKNESS; requisition->ascent = font->ascent + RELIEF_Y_THICKNESS; requisition->descent = font->descent + RELIEF_Y_THICKNESS; @@ -687,7 +763,7 @@ void FltkToggleButtonResource<I>::sizeRequest (core::Requisition *requisition) template <class I> bool FltkToggleButtonResource<I>::FltkToggleButtonResource::isActivated () { - return ((::fltk::Button*)this->widget)->value (); + return ((Fl_Button*)this->widget)->value (); } @@ -695,7 +771,7 @@ template <class I> void FltkToggleButtonResource<I>::setActivated (bool activated) { initActivated = activated; - ((::fltk::Button*)this->widget)->value (initActivated); + ((Fl_Button*)this->widget)->value (initActivated); } // ---------------------------------------------------------------------- @@ -714,13 +790,12 @@ FltkCheckButtonResource::~FltkCheckButtonResource () } -::fltk::Button *FltkCheckButtonResource::createNewButton (core::Allocation +Fl_Button *FltkCheckButtonResource::createNewButton (core::Allocation *allocation) { - ::fltk::CheckButton *cb = - new ::fltk::CheckButton (allocation->x, allocation->y, allocation->width, - allocation->ascent + allocation->descent); - cb->set_flag (::fltk::RAW_LABEL); + Fl_Check_Button *cb = + new Fl_Check_Button (allocation->x, allocation->y, allocation->width, + allocation->ascent + allocation->descent); return cb; } @@ -798,10 +873,10 @@ dw::core::ui::RadioButtonResource::GroupIterator return group->groupIterator (); } -void FltkRadioButtonResource::widgetCallback (::fltk::Widget *widget, +void FltkRadioButtonResource::widgetCallback (Fl_Widget *widget, void *data) { - if (widget->when () & ::fltk::WHEN_CHANGED) + if (widget->when () & FL_WHEN_CHANGED) ((FltkRadioButtonResource*)data)->buttonClicked (); } @@ -814,11 +889,11 @@ void FltkRadioButtonResource::buttonClicked () } } -::fltk::Button *FltkRadioButtonResource::createNewButton (core::Allocation - *allocation) +Fl_Button *FltkRadioButtonResource::createNewButton (core::Allocation + *allocation) { /* - * Groups of fltk::RadioButton must be added to one fltk::Group, which is + * Groups of Fl_Radio_Button must be added to one Fl_Group, which is * not possible in this context. For this, we do the grouping ourself, * based on FltkRadioButtonResource::Group. * @@ -829,297 +904,191 @@ void FltkRadioButtonResource::buttonClicked () * (instead of creating a check button, and changing the style). */ - ::fltk::Button *button = - new ::fltk::RadioButton (allocation->x, allocation->y, - allocation->width, - allocation->ascent + allocation->descent); - button->set_flag (::fltk::RAW_LABEL); - button->when (::fltk::WHEN_CHANGED); + Fl_Button *button = + new Fl_Round_Button (allocation->x, allocation->y, allocation->width, + allocation->ascent + allocation->descent); + button->when (FL_WHEN_CHANGED); button->callback (widgetCallback, this); - button->type (::fltk::Button::TOGGLE); + button->type (FL_TOGGLE_BUTTON); return button; } // ---------------------------------------------------------------------- -template <class I> FltkSelectionResource<I>::Item::Item (Type type, - const char *name, - bool enabled, - bool selected) +template <class I> dw::core::Iterator * +FltkSelectionResource<I>::iterator (dw::core::Content::Type mask, bool atEnd) { - this->type = type; - this->name = name ? strdup (name) : NULL; - this->enabled = enabled; - initSelected = selected; + /** \bug Implementation. */ + return new core::EmptyIterator (this->getEmbed (), mask, atEnd); } -template <class I> FltkSelectionResource<I>::Item::~Item () -{ - if (name) - delete name; -} +// ---------------------------------------------------------------------- -template <class I> -::fltk::Item *FltkSelectionResource<I>::Item::createNewWidget (int index) +FltkOptionMenuResource::FltkOptionMenuResource (FltkPlatform *platform): + FltkSelectionResource <dw::core::ui::OptionMenuResource> (platform) { - ::fltk::Item *item = new ::fltk::Item (name); - item->set_flag (::fltk::RAW_LABEL); - item->user_data ((void *) index); - return item; -} + /* Fl_Menu_ does not like multiple menu items with the same label, and + * insert() treats some characters specially unless escaped, so let's + * do our own menu handling. + */ + itemsAllocated = 0x10; + menu = new Fl_Menu_Item[itemsAllocated]; + memset(menu, 0, itemsAllocated * sizeof(Fl_Menu_Item)); + itemsUsed = 1; // menu[0].text == NULL, which is an end-of-menu marker. + visibleItems = 0; -template <class I> -::fltk::ItemGroup * -FltkSelectionResource<I>::Item::createNewGroupWidget () -{ - ::fltk::ItemGroup *itemGroup = new ::fltk::ItemGroup (name); - itemGroup->set_flag (::fltk::RAW_LABEL); - itemGroup->user_data ((void *) -1L); - return itemGroup; + init (platform); } - -template <class I> -FltkSelectionResource<I>::WidgetStack::WidgetStack (::fltk::Menu *widget) +FltkOptionMenuResource::~FltkOptionMenuResource () { - this->widget = widget; - this->stack = new Stack <TypedPointer < ::fltk::Menu> > (true); + for (int i = 0; i < itemsUsed; i++) { + if (menu[i].text) + free((char *) menu[i].text); + } + delete[] menu; } -template <class I> FltkSelectionResource<I>::WidgetStack::~WidgetStack () +void FltkOptionMenuResource::setWidgetStyle (Fl_Widget *widget, + core::style::Style *style) { - delete stack; -} + Fl_Choice *ch = (Fl_Choice *)widget; + FltkResource::setWidgetStyle(widget, style); -template <class I> -FltkSelectionResource<I>::FltkSelectionResource (FltkPlatform *platform): - FltkSpecificResource<I> (platform) -{ - widgetStacks = new List <WidgetStack> (true); - allItems = new List <Item> (true); - items = new Vector <Item> (16, false); + ch->textcolor(widget->labelcolor()); + ch->textfont(ch->labelfont()); + ch->textsize(ch->labelsize()); } -template <class I> FltkSelectionResource<I>::~FltkSelectionResource () +Fl_Widget *FltkOptionMenuResource::createNewWidget (core::Allocation + *allocation) { - delete widgetStacks; - delete allItems; - delete items; + Fl_Choice *choice = + new Fl_Choice (allocation->x, allocation->y, + allocation->width, + allocation->ascent + allocation->descent); + choice->menu(menu); + return choice; } -template <class I> dw::core::Iterator * -FltkSelectionResource<I>::iterator (dw::core::Content::Type mask, bool atEnd) +void FltkOptionMenuResource::widgetCallback (Fl_Widget *widget, + void *data) { - /** \bug Implementation. */ - return new core::EmptyIterator (this->getEmbed (), mask, atEnd); } -template <class I> ::fltk::Widget * -FltkSelectionResource<I>::createNewWidget (core::Allocation *allocation) +int FltkOptionMenuResource::getMaxItemWidth() { - /** \todo Attributes (enabled, selected). */ - - ::fltk::Menu *menu = createNewMenu (allocation); - WidgetStack *widgetStack = new WidgetStack (menu); - widgetStack->stack->push (new TypedPointer < ::fltk::Menu> (menu)); - widgetStacks->append (widgetStack); - + int i, max = 0; - ::fltk::Menu *itemGroup; - ::fltk::Item *itemWidget; + for (i = 0; i < itemsUsed; i++) { + int width = 0; + const char *str = menu[i].text; - ::fltk::Group *currGroup = widgetStack->stack->getTop()->getTypedValue(); - - int index = 0; - for (Iterator <Item> it = allItems->iterator (); it.hasNext (); ) { - Item *item = it.getNext (); - switch (item->type) { - case Item::ITEM: - itemWidget = item->createNewWidget (index++); - currGroup->add (itemWidget); - break; - - case Item::START: - itemGroup = item->createNewGroupWidget (); - currGroup->add (itemGroup); - widgetStack->stack->push (new TypedPointer < ::fltk::Menu> (menu)); - currGroup = itemGroup; - break; - - case Item::END: - widgetStack->stack->pop (); - currGroup = widgetStack->stack->getTop()->getTypedValue(); - break; + if (str) { + width = fl_width(str); + if (width > max) + max = width; } } - - return menu; + return max; } -template <class I> -typename FltkSelectionResource<I>::Item * -FltkSelectionResource<I>::createNewItem (typename Item::Type type, - const char *name, - bool enabled, - bool selected) { - return new Item(type,name,enabled,selected); -} - -template <class I> void FltkSelectionResource<I>::addItem (const char *str, - bool enabled, - bool selected) -{ - int index = items->size (); - Item *item = createNewItem (Item::ITEM, str, enabled, selected); - items->put (item); - allItems->append (item); - - for (Iterator <WidgetStack> it = widgetStacks->iterator (); - it.hasNext(); ) { - WidgetStack *widgetStack = it.getNext (); - ::fltk::Item *itemWidget = item->createNewWidget (index); - widgetStack->stack->getTop()->getTypedValue()->add (itemWidget); - - if (!enabled) - itemWidget->deactivate (); - - if (selected) { - itemWidget->set_selected(); - if (setSelectedItems ()) { - // Handle multiple item selection. - int *pos = new int[widgetStack->stack->size ()]; - int i; - Iterator <TypedPointer < ::fltk::Menu> > it; - for (it = widgetStack->stack->iterator (), - i = widgetStack->stack->size () - 1; - it.hasNext (); - i--) { - TypedPointer < ::fltk::Menu> * p = it.getNext (); - pos[i] = p->getTypedValue()->children () - 1; - } - widgetStack->widget->set_item (pos, widgetStack->stack->size ()); - delete [] pos; - } - } +void FltkOptionMenuResource::sizeRequest (core::Requisition *requisition) +{ + if (style) { + FltkFont *font = (FltkFont*)style->font; + fl_font(font->font, font->size); + int maxItemWidth = getMaxItemWidth (); + requisition->ascent = font->ascent + RELIEF_Y_THICKNESS; + requisition->descent = font->descent + RELIEF_Y_THICKNESS; + requisition->width = maxItemWidth + + (requisition->ascent + requisition->descent) + + 2 * RELIEF_X_THICKNESS; + } else { + requisition->width = 1; + requisition->ascent = 1; + requisition->descent = 0; } } -template <class I> void FltkSelectionResource<I>::pushGroup (const char *name, - bool enabled) +void FltkOptionMenuResource::enlargeMenu () { - Item *item = createNewItem (Item::START, name, enabled); - allItems->append (item); + Fl_Choice *ch = (Fl_Choice *)widget; + int selected = ch->value(); + Fl_Menu_Item *newMenu; - for (Iterator <WidgetStack> it = widgetStacks->iterator (); - it.hasNext(); ) { - WidgetStack *widgetStack = it.getNext (); - ::fltk::ItemGroup *group = item->createNewGroupWidget (); - widgetStack->stack->getTop()->getTypedValue()->add (group); - widgetStack->stack->push (new TypedPointer < ::fltk::Menu> (group)); - if (!enabled) - group->deactivate (); - } + itemsAllocated += 0x10; + newMenu = new Fl_Menu_Item[itemsAllocated]; + memcpy(newMenu, menu, itemsUsed * sizeof(Fl_Menu_Item)); + memset(newMenu + itemsUsed, 0, 0x10 * sizeof(Fl_Menu_Item)); + delete[] menu; + menu = newMenu; + ch->menu(menu); + ch->value(selected); } -template <class I> void FltkSelectionResource<I>::popGroup () +Fl_Menu_Item *FltkOptionMenuResource::newItem() { - Item *item = createNewItem (Item::END); - allItems->append (item); + Fl_Menu_Item *item; - for (Iterator <WidgetStack> it = widgetStacks->iterator (); - it.hasNext(); ) { - WidgetStack *widgetStack = it.getNext (); - widgetStack->stack->pop (); - } -} + if (itemsUsed == itemsAllocated) + enlargeMenu(); -template <class I> int FltkSelectionResource<I>::getNumberOfItems () -{ - return items->size (); -} + item = menu + itemsUsed - 1; + itemsUsed++; -template <class I> const char *FltkSelectionResource<I>::getItem (int index) -{ - return items->get(index)->name; + return item; } -template <class I> int FltkSelectionResource<I>::getMaxStringWidth () +void FltkOptionMenuResource::addItem (const char *str, + bool enabled, bool selected) { - int width = 0, numberOfItems = getNumberOfItems (); - for (int i = 0; i < numberOfItems; i++) { - int len = (int)::fltk::getwidth (getItem(i)); - if (len > width) width = len; - } - return width; -} + Fl_Menu_Item *item = newItem(); -// ---------------------------------------------------------------------- + item->text = strdup(str); + item->argument(visibleItems++); -FltkOptionMenuResource::FltkOptionMenuResource (FltkPlatform *platform): - FltkSelectionResource <dw::core::ui::OptionMenuResource> (platform), - selection(-1) -{ - init (platform); + if (enabled == false) + item->flags = FL_MENU_INACTIVE; + + if (selected) + ((Fl_Choice *)widget)->value(item); + + queueResize (true); } -FltkOptionMenuResource::~FltkOptionMenuResource () +void FltkOptionMenuResource::pushGroup (const char *name, bool enabled) { -} + Fl_Menu_Item *item = newItem(); + item->text = strdup(name); + item->argument(visibleItems++); -::fltk::Menu *FltkOptionMenuResource::createNewMenu (core::Allocation - *allocation) -{ - ::fltk::Menu *menu = - new ::fltk::Choice (allocation->x, allocation->y, - allocation->width, - allocation->ascent + allocation->descent); - menu->set_flag (::fltk::RAW_LABEL); - menu->callback(widgetCallback,this); - return menu; -} + if (enabled == false) + item->flags = FL_MENU_INACTIVE; -void FltkOptionMenuResource::widgetCallback (::fltk::Widget *widget, - void *data) -{ - ((FltkOptionMenuResource *) data)->selection = - (long) (((::fltk::Menu *) widget)->item()->user_data()); -} + item->flags |= FL_SUBMENU; -void FltkOptionMenuResource::sizeRequest (core::Requisition *requisition) -{ - if (style) { - FltkFont *font = (FltkFont*)style->font; - ::fltk::setfont(font->font,font->size); - int maxStringWidth = getMaxStringWidth (); - requisition->ascent = font->ascent + RELIEF_Y_THICKNESS; - requisition->descent = font->descent + RELIEF_Y_THICKNESS; - requisition->width = maxStringWidth - + (requisition->ascent + requisition->descent) * 4 / 5 - + 2 * RELIEF_X_THICKNESS; - } else { - requisition->width = 1; - requisition->ascent = 1; - requisition->descent = 0; - } + queueResize (true); } -void FltkOptionMenuResource::addItem (const char *str, - bool enabled, bool selected) +void FltkOptionMenuResource::popGroup () { - FltkSelectionResource<dw::core::ui::OptionMenuResource>::addItem - (str,enabled,selected); - if (selected) - selection = (items->size ()) - 1; - + /* Item with NULL text field closes the submenu */ + newItem(); queueResize (true); } bool FltkOptionMenuResource::isSelected (int index) { - return index == selection; + return index == (long) ((Fl_Choice *)widget)->mvalue()->user_data(); +} + +int FltkOptionMenuResource::getNumberOfItems() +{ + return ((Fl_Choice*)widget)->size(); } // ---------------------------------------------------------------------- @@ -1140,70 +1109,133 @@ FltkListResource::~FltkListResource () } -::fltk::Menu *FltkListResource::createNewMenu (core::Allocation *allocation) +Fl_Widget *FltkListResource::createNewWidget (core::Allocation *allocation) { - ::fltk::Menu *menu = - new ::fltk::Browser (allocation->x, allocation->y, allocation->width, + Fl_Tree *tree = + new Fl_Tree (allocation->x, allocation->y, allocation->width, allocation->ascent + allocation->descent); - if (mode == SELECTION_MULTIPLE) - menu->type(::fltk::Browser::MULTI); - menu->set_flag (::fltk::RAW_LABEL); - menu->callback(widgetCallback,this); - menu->when(::fltk::WHEN_CHANGED); - return menu; + + tree->selectmode((mode == SELECTION_MULTIPLE) ? FL_TREE_SELECT_MULTI + : FL_TREE_SELECT_SINGLE); + tree->showroot(0); + tree->connectorstyle(FL_TREE_CONNECTOR_NONE); + tree->marginleft(-14); + tree->callback(widgetCallback,this); + tree->when(FL_WHEN_CHANGED); + + currParent = tree->root(); + return tree; } -void FltkListResource::widgetCallback (::fltk::Widget *widget, void *data) +void FltkListResource::setWidgetStyle (Fl_Widget *widget, + core::style::Style *style) { - ::fltk::Widget *fltkItem = ((::fltk::Menu *) widget)->item (); + Fl_Tree *t = (Fl_Tree *)widget; + + FltkResource::setWidgetStyle(widget, style); + + t->item_labelfont(widget->labelfont()); + t->item_labelsize(widget->labelsize()); + t->item_labelfgcolor(widget->labelcolor()); + t->item_labelbgcolor(widget->color()); +} + +void FltkListResource::widgetCallback (Fl_Widget *widget, void *data) +{ + Fl_Tree_Item *fltkItem = ((Fl_Tree *) widget)->callback_item (); int index = -1; if (fltkItem) index = (long) (fltkItem->user_data ()); if (index > -1) { - /* A MultiBrowser will trigger a callback for each item that is - * selected and each item that is deselected, but a "plain" - * Browser will only trigger the callback for the newly selected item - * (for which selected() is false, incidentally). - */ FltkListResource *res = (FltkListResource *) data; - if (res->mode == SELECTION_MULTIPLE) { - bool selected = fltkItem->selected (); - res->itemsSelected.set (index, selected); + bool selected = fltkItem->is_selected (); + res->itemsSelected.set (index, selected); + } +} + +void *FltkListResource::newItem (const char *str, bool enabled, bool selected) +{ + Fl_Tree *tree = (Fl_Tree *) widget; + Fl_Tree_Item *parent = (Fl_Tree_Item *)currParent; + Fl_Tree_Item *item = tree->add(parent, str); + int index = itemsSelected.size(); + + enabled &= parent->is_active(); + item->activate(enabled); + item->user_data((void*)(long)index); + itemsSelected.increase (); + itemsSelected.set (itemsSelected.size() - 1, selected); + + return item; +} + +void FltkListResource::addItem (const char *str, bool enabled, bool selected) +{ + Fl_Tree *tree = (Fl_Tree *) widget; + Fl_Tree_Item *item = (Fl_Tree_Item *) newItem(str, enabled, selected); + + if (selected) { + if (mode == SELECTION_MULTIPLE) { + item->select(selected); } else { - int size = res->itemsSelected.size(); - for (int i = 0; i < size; i++) - res->itemsSelected.set (i, false); - res->itemsSelected.set (index, true); + const bool do_callback = true; + tree->select_only(item, do_callback); } } + queueResize (true); } -void FltkListResource::addItem (const char *str, bool enabled, bool selected) +void FltkListResource::pushGroup (const char *name, bool enabled) { - FltkSelectionResource<dw::core::ui::ListResource>::addItem - (str,enabled,selected); - int index = itemsSelected.size (); - itemsSelected.increase (); - itemsSelected.set (index,selected); + bool selected = false; + + /* TODO: make it impossible to select a group */ + currParent = (Fl_Tree_Item *) newItem(name, enabled, selected); queueResize (true); } +void FltkListResource::popGroup () +{ + Fl_Tree_Item *p = (Fl_Tree_Item *)currParent; + + if (p->parent()) + currParent = p->parent(); +} + +int FltkListResource::getMaxItemWidth() +{ + Fl_Tree *tree = (Fl_Tree *)widget; + int max = 0; + + for (Fl_Tree_Item *i = tree->first(); i; i = tree->next(i)) { + int width = 0; + + if (i == tree->root()) + continue; + + for (Fl_Tree_Item *p = i->parent(); p != tree->root(); p = p->parent()) + width += tree->connectorwidth(); + + if (i->label()) + width += fl_width(i->label()); + + if (width > max) + max = width; + } + return max; +} + void FltkListResource::sizeRequest (core::Requisition *requisition) { if (style) { FltkFont *font = (FltkFont*)style->font; - ::fltk::setfont(font->font,font->size); + fl_font(font->font,font->size); int rows = getNumberOfItems(); if (showRows < rows) { rows = showRows; } - /* - * The widget sometimes shows scrollbars when they are not required. - * The following values try to keep any scrollbars from obscuring - * options, at the cost of showing too much whitespace at times. - */ - requisition->width = getMaxStringWidth() + 24; - requisition->ascent = font->ascent + 2 + + requisition->width = getMaxItemWidth() + 5 + Fl::scrollbar_size();; + requisition->ascent = font->ascent + 5 + (rows - 1) * (font->ascent + font->descent + 1); requisition->descent = font->descent + 3; } else { diff --git a/dw/fltkui.hh b/dw/fltkui.hh index 245d5aad..ff927c80 100644 --- a/dw/fltkui.hh +++ b/dw/fltkui.hh @@ -5,11 +5,9 @@ # error Do not include this file directly, use "fltkcore.hh" instead. #endif -#include <fltk/Button.h> -#include <fltk/Menu.h> -#include <fltk/TextBuffer.h> -#include <fltk/Item.h> -#include <fltk/ItemGroup.h> +#include <FL/Fl_Button.H> +#include <FL/Fl_Menu.H> +#include <FL/Fl_Text_Buffer.H> namespace dw { namespace fltk { @@ -179,7 +177,7 @@ private: protected: FltkView *view; - ::fltk::Widget *widget; + Fl_Widget *widget; core::Allocation allocation; FltkPlatform *platform; @@ -187,9 +185,9 @@ protected: FltkResource (FltkPlatform *platform); void init (FltkPlatform *platform); - virtual ::fltk::Widget *createNewWidget (core::Allocation *allocation) = 0; + virtual Fl_Widget *createNewWidget (core::Allocation *allocation) = 0; - void setWidgetStyle (::fltk::Widget *widget, core::style::Style *style); + virtual void setWidgetStyle (Fl_Widget *widget, core::style::Style *style); void setDisplayed (bool displayed); bool displayed(); public: @@ -229,10 +227,10 @@ class FltkLabelButtonResource: private: const char *label; - static void widgetCallback (::fltk::Widget *widget, void *data); + static void widgetCallback (Fl_Widget *widget, void *data); protected: - ::fltk::Widget *createNewWidget (core::Allocation *allocation); + Fl_Widget *createNewWidget (core::Allocation *allocation); public: FltkLabelButtonResource (FltkPlatform *platform, const char *label); @@ -251,7 +249,7 @@ class FltkComplexButtonResource: private: bool relief; - static void widgetCallback (::fltk::Widget *widget, void *data); + static void widgetCallback (Fl_Widget *widget, void *data); protected: FltkView *topView, *flatView; @@ -267,7 +265,7 @@ protected: int reliefXThickness (); int reliefYThickness (); - ::fltk::Widget *createNewWidget (core::Allocation *allocation); + Fl_Widget *createNewWidget (core::Allocation *allocation); public: FltkComplexButtonResource (FltkPlatform *platform, dw::core::Widget *widget, @@ -288,13 +286,15 @@ private: bool password; const char *initText; char *label; + int label_w; bool editable; - static void widgetCallback (::fltk::Widget *widget, void *data); + static void widgetCallback (Fl_Widget *widget, void *data); void setDisplayed (bool displayed); protected: - ::fltk::Widget *createNewWidget (core::Allocation *allocation); + Fl_Widget *createNewWidget (core::Allocation *allocation); + void setWidgetStyle (Fl_Widget *widget, core::style::Style *style); public: FltkEntryResource (FltkPlatform *platform, int maxLength, bool password, @@ -302,6 +302,7 @@ public: ~FltkEntryResource (); void sizeRequest (core::Requisition *requisition); + void sizeAllocate (core::Allocation *allocation); const char *getText (); void setText (const char *text); @@ -314,12 +315,14 @@ class FltkMultiLineTextResource: public FltkSpecificResource <dw::core::ui::MultiLineTextResource> { private: - ::fltk::TextBuffer *buffer; + Fl_Text_Buffer *buffer; + char *text_copy; bool editable; int numCols, numRows; protected: - ::fltk::Widget *createNewWidget (core::Allocation *allocation); + Fl_Widget *createNewWidget (core::Allocation *allocation); + void setWidgetStyle (Fl_Widget *widget, core::style::Style *style); public: FltkMultiLineTextResource (FltkPlatform *platform, int cols, int rows); @@ -341,8 +344,9 @@ private: bool initActivated; protected: - virtual ::fltk::Button *createNewButton (core::Allocation *allocation) = 0; - ::fltk::Widget *createNewWidget (core::Allocation *allocation); + virtual Fl_Button *createNewButton (core::Allocation *allocation) = 0; + Fl_Widget *createNewWidget (core::Allocation *allocation); + void setWidgetStyle (Fl_Widget *widget, core::style::Style *style); public: FltkToggleButtonResource (FltkPlatform *platform, @@ -360,7 +364,7 @@ class FltkCheckButtonResource: public FltkToggleButtonResource <dw::core::ui::CheckButtonResource> { protected: - ::fltk::Button *createNewButton (core::Allocation *allocation); + Fl_Button *createNewButton (core::Allocation *allocation); public: FltkCheckButtonResource (FltkPlatform *platform, @@ -401,7 +405,8 @@ private: public: Group (FltkRadioButtonResource *radioButtonResource); - inline lout::container::typed::Iterator <FltkRadioButtonResource> iterator () + inline lout::container::typed::Iterator <FltkRadioButtonResource> + iterator () { return list->iterator (); } @@ -418,11 +423,11 @@ private: Group *group; - static void widgetCallback (::fltk::Widget *widget, void *data); + static void widgetCallback (Fl_Widget *widget, void *data); void buttonClicked (); protected: - ::fltk::Button *createNewButton (core::Allocation *allocation); + Fl_Button *createNewButton (core::Allocation *allocation); public: FltkRadioButtonResource (FltkPlatform *platform, @@ -438,60 +443,14 @@ template <class I> class FltkSelectionResource: public FltkSpecificResource <I> { protected: - class Item: public lout::object::Object - { - public: - enum Type { ITEM, START, END } type; - - const char *name; - bool enabled, initSelected; - - Item (Type type, const char *name = NULL, bool enabled = true, - bool selected = false); - ~Item (); - - ::fltk::Item *createNewWidget (int index); - ::fltk::ItemGroup *createNewGroupWidget (); - }; - - class WidgetStack: public lout::object::Object - { - public: - ::fltk::Menu *widget; - lout::container::typed::Stack <lout::object::TypedPointer < ::fltk::Menu> > *stack; - - WidgetStack (::fltk::Menu *widget); - ~WidgetStack (); - }; - - lout::container::typed::List <WidgetStack> *widgetStacks; - lout::container::typed::List <Item> *allItems; - lout::container::typed::Vector <Item> *items; - - Item *createNewItem (typename Item::Type type, - const char *name = NULL, - bool enabled = true, - bool selected = false); - - ::fltk::Widget *createNewWidget (core::Allocation *allocation); - virtual ::fltk::Menu *createNewMenu (core::Allocation *allocation) = 0; virtual bool setSelectedItems() { return false; } - - int getMaxStringWidth (); - + virtual void addItem (const char *str, bool enabled, bool selected) = 0; + virtual void pushGroup (const char *name, bool enabled) = 0; + virtual void popGroup () = 0; public: - FltkSelectionResource (FltkPlatform *platform); - ~FltkSelectionResource (); - + FltkSelectionResource (FltkPlatform *platform) : + FltkSpecificResource<I> (platform) {}; dw::core::Iterator *iterator (dw::core::Content::Type mask, bool atEnd); - - void addItem (const char *str, bool enabled, bool selected); - - void pushGroup (const char *name, bool enabled); - void popGroup (); - - int getNumberOfItems (); - const char *getItem (int index); }; @@ -499,18 +458,25 @@ class FltkOptionMenuResource: public FltkSelectionResource <dw::core::ui::OptionMenuResource> { protected: - ::fltk::Menu *createNewMenu (core::Allocation *allocation); + Fl_Widget *createNewWidget (core::Allocation *allocation); virtual bool setSelectedItems() { return true; } - + void setWidgetStyle (Fl_Widget *widget, core::style::Style *style); + int getNumberOfItems(); + int getMaxItemWidth (); private: - static void widgetCallback (::fltk::Widget *widget, void *data); - int selection; - + static void widgetCallback (Fl_Widget *widget, void *data); + void enlargeMenu(); + Fl_Menu_Item *newItem(); + Fl_Menu_Item *menu; + int itemsAllocated, itemsUsed; + int visibleItems; /* not counting the invisible ones that close a group */ public: FltkOptionMenuResource (FltkPlatform *platform); ~FltkOptionMenuResource (); void addItem (const char *str, bool enabled, bool selected); + void pushGroup (const char *name, bool enabled); + void popGroup (); void sizeRequest (core::Requisition *requisition); bool isSelected (int index); @@ -520,10 +486,16 @@ class FltkListResource: public FltkSelectionResource <dw::core::ui::ListResource> { protected: - ::fltk::Menu *createNewMenu (core::Allocation *allocation); + Fl_Widget *createNewWidget (core::Allocation *allocation); + void setWidgetStyle (Fl_Widget *widget, core::style::Style *style); + + int getNumberOfItems () {return itemsSelected.size();}; + int getMaxItemWidth (); private: - static void widgetCallback (::fltk::Widget *widget, void *data); + static void widgetCallback (Fl_Widget *widget, void *data); + void *newItem (const char *str, bool enabled, bool selected); + void *currParent; lout::misc::SimpleVector <bool> itemsSelected; int showRows; ListResource::SelectionMode mode; @@ -534,6 +506,8 @@ public: ~FltkListResource (); void addItem (const char *str, bool enabled, bool selected); + void pushGroup (const char *name, bool enabled); + void popGroup (); void sizeRequest (core::Requisition *requisition); bool isSelected (int index); diff --git a/dw/fltkviewbase.cc b/dw/fltkviewbase.cc index cab22cf4..bf3aba22 100644 --- a/dw/fltkviewbase.cc +++ b/dw/fltkviewbase.cc @@ -21,40 +21,63 @@ #include "fltkviewport.hh" -#include <fltk/draw.h> -#include <fltk/damage.h> -#include <fltk/layout.h> -#include <fltk/events.h> -#include <fltk/Cursor.h> -#include <fltk/run.h> -#include <fltk/utf.h> +#include <FL/Fl.H> +#include <FL/fl_draw.H> #include <stdio.h> -#include <wchar.h> -#include <wctype.h> #include "../lout/msg.h" -using namespace fltk; +extern Fl_Widget* fl_oldfocus; + using namespace lout::object; using namespace lout::container::typed; namespace dw { namespace fltk { -::fltk::Image *FltkViewBase::backBuffer; +FltkViewBase::BackBuffer::BackBuffer () +{ + w = 0; + h = 0; + created = false; +} + +FltkViewBase::BackBuffer::~BackBuffer () +{ + if (created) + fl_delete_offscreen (offscreen); +} + +void FltkViewBase::BackBuffer::setSize (int w, int h) +{ + if (!created || w > this->w || h > this->h) { + this->w = w; + this->h = h; + if (created) + fl_delete_offscreen (offscreen); + offscreen = fl_create_offscreen (w, h); + created = true; + } +} + +FltkViewBase::BackBuffer *FltkViewBase::backBuffer; bool FltkViewBase::backBufferInUse; FltkViewBase::FltkViewBase (int x, int y, int w, int h, const char *label): - Group (x, y, w, h, label) + Fl_Group (x, y, w, h, label) { + Fl_Group::current(0); canvasWidth = 1; canvasHeight = 1; - bgColor = WHITE; + bgColor = FL_WHITE; mouse_x = mouse_y = 0; + focused_child = NULL; exposeArea = NULL; if (backBuffer == NULL) { - backBuffer = new Image (); + backBuffer = new BackBuffer (); } + box(FL_NO_BOX); + resizable(NULL); } FltkViewBase::~FltkViewBase () @@ -64,7 +87,7 @@ FltkViewBase::~FltkViewBase () void FltkViewBase::setBufferedDrawing (bool b) { if (b && backBuffer == NULL) { - backBuffer = new Image (); + backBuffer = new BackBuffer (); } else if (!b && backBuffer != NULL) { delete backBuffer; backBuffer = NULL; @@ -75,7 +98,7 @@ void FltkViewBase::draw () { int d = damage (); - if ((d & DAMAGE_VALUE) && !(d & DAMAGE_EXPOSE)) { + if ((d & FL_DAMAGE_USER1) && !(d & FL_DAMAGE_EXPOSE)) { lout::container::typed::Iterator <core::Rectangle> it; for (it = drawRegion.rectangles (); it.hasNext (); ) { @@ -83,22 +106,22 @@ void FltkViewBase::draw () } drawRegion.clear (); - d &= ~DAMAGE_VALUE; + d &= ~FL_DAMAGE_USER1; } - if (d & DAMAGE_CHILD) { + if (d & FL_DAMAGE_CHILD) { drawChildWidgets (); - d &= ~DAMAGE_CHILD; + d &= ~FL_DAMAGE_CHILD; } if (d) { dw::core::Rectangle rect ( - translateViewXToCanvasX (0), - translateViewYToCanvasY (0), + translateViewXToCanvasX (x ()), + translateViewYToCanvasY (y ()), w (), h ()); - if (d == DAMAGE_SCROLL) { + if (d == FL_DAMAGE_SCROLL) { // a clipping rectangle has already been set by fltk::scrollrect () draw (&rect, DRAW_PLAIN); } else { @@ -111,88 +134,84 @@ void FltkViewBase::draw () void FltkViewBase::draw (const core::Rectangle *rect, DrawType type) { - int offsetX = 0, offsetY = 0; - - /* fltk-clipping does not use widget coordinates */ - transform (offsetX, offsetY); - - ::fltk::Rectangle viewRect ( - translateCanvasXToViewX (rect->x) + offsetX, - translateCanvasYToViewY (rect->y) + offsetY, - rect->width, rect->height); - - ::fltk::intersect_with_clip (viewRect); - - viewRect.x (viewRect.x () - offsetX); - viewRect.y (viewRect.y () - offsetY); - - if (! viewRect.empty ()) { - dw::core::Rectangle r ( - translateViewXToCanvasX (viewRect.x ()), - translateViewYToCanvasY (viewRect.y ()), - viewRect.w (), - viewRect.h ()); - - exposeArea = &viewRect; - - if (type == DRAW_BUFFERED && backBuffer && !backBufferInUse) { - backBufferInUse = true; - { - GSave gsave; - - backBuffer->setsize (viewRect.w (), viewRect.h ()); - backBuffer->make_current (); - translate (-viewRect.x (), -viewRect.y ()); - - setcolor (bgColor); - fillrect (viewRect); - theLayout->expose (this, &r); - } - - backBuffer->draw (Rectangle (0, 0, viewRect.w (), viewRect.h ()), - viewRect); - - backBufferInUse = false; - } else if (type == DRAW_BUFFERED || type == DRAW_CLIPPED) { - // if type == DRAW_BUFFERED but we do not have backBuffer available - // we fall back to clipped drawing - push_clip (viewRect); - setcolor (bgColor); - fillrect (viewRect); - theLayout->expose (this, &r); - pop_clip (); - } else { - setcolor (bgColor); - fillrect (viewRect); - theLayout->expose (this, &r); - } - - exposeArea = NULL; + int X = translateCanvasXToViewX (rect->x); + int Y = translateCanvasYToViewY (rect->y); + int W, H; + + // fl_clip_box() can't handle values greater than SHRT_MAX! + if (X > x () + w () || Y > y () + h ()) + return; + + W = X + rect->width > x () + w () ? x () + w () - X : rect->width; + H = Y + rect->height > y () + h () ? y () + h () - Y : rect->height; + + fl_clip_box(X, Y, W, H, X, Y, W, H); + + core::Rectangle r (translateViewXToCanvasX (X), + translateViewYToCanvasY (Y), W, H); + + if (r.isEmpty ()) + return; + + exposeArea = &r; + + if (type == DRAW_BUFFERED && backBuffer && !backBufferInUse) { + backBufferInUse = true; + backBuffer->setSize (X + W, Y + H); // would be nicer to use (W, H)... + fl_begin_offscreen (backBuffer->offscreen); + fl_push_matrix (); + fl_color (bgColor); + fl_rectf (X, Y, W, H); + theLayout->expose (this, &r); + fl_pop_matrix (); + fl_end_offscreen (); + fl_copy_offscreen (X, Y, W, H, backBuffer->offscreen, X, Y); + backBufferInUse = false; + } else if (type == DRAW_BUFFERED || type == DRAW_CLIPPED) { + // if type == DRAW_BUFFERED but we do not have backBuffer available + // we fall back to clipped drawing + fl_push_clip (X, Y, W, H); + fl_color (bgColor); + fl_rectf (X, Y, W, H); + theLayout->expose (this, &r); + fl_pop_clip (); + } else { + fl_color (bgColor); + fl_rectf (X, Y, W, H); + theLayout->expose (this, &r); } + // DEBUG: + //fl_color(FL_RED); + //fl_rect(X, Y, W, H); + + exposeArea = NULL; } void FltkViewBase::drawChildWidgets () { for (int i = children () - 1; i >= 0; i--) { - Widget& w = *child(i); + Fl_Widget& w = *child(i); +#if 0 +PORT1.3 if (w.damage() & DAMAGE_CHILD_LABEL) { draw_outside_label(w); w.set_damage(w.damage() & ~DAMAGE_CHILD_LABEL); } +#endif update_child(w); } } core::ButtonState getDwButtonState () { - int s1 = event_state (); + int s1 = Fl::event_state (); int s2 = (core::ButtonState)0; - if (s1 & SHIFT) s2 |= core::SHIFT_MASK; - if (s1 & CTRL) s2 |= core::CONTROL_MASK; - if (s1 & ALT) s2 |= core::META_MASK; - if (s1 & BUTTON1) s2 |= core::BUTTON1_MASK; - if (s1 & BUTTON2) s2 |= core::BUTTON2_MASK; - if (s1 & BUTTON3) s2 |= core::BUTTON3_MASK; + if (s1 & FL_SHIFT) s2 |= core::SHIFT_MASK; + if (s1 & FL_CTRL) s2 |= core::CONTROL_MASK; + if (s1 & FL_ALT) s2 |= core::META_MASK; + if (s1 & FL_BUTTON1) s2 |= core::BUTTON1_MASK; + if (s1 & FL_BUTTON2) s2 |= core::BUTTON2_MASK; + if (s1 & FL_BUTTON3) s2 |= core::BUTTON3_MASK; return (core::ButtonState)s2; } @@ -207,61 +226,79 @@ int FltkViewBase::handle (int event) * when passed a fltk::PUSH event. " */ switch(event) { - case PUSH: + case FL_PUSH: + /* Hide the tooltip */ + theLayout->cancelTooltip(); + processed = - theLayout->buttonPress (this, event_clicks () + 1, - translateViewXToCanvasX (event_x ()), - translateViewYToCanvasY (event_y ()), - getDwButtonState (), event_button ()); + theLayout->buttonPress (this, Fl::event_clicks () + 1, + translateViewXToCanvasX (Fl::event_x ()), + translateViewYToCanvasY (Fl::event_y ()), + getDwButtonState (), Fl::event_button ()); _MSG("PUSH => %s\n", processed ? "true" : "false"); if (processed) { /* pressed dw content; give focus to the view */ - ::fltk::focus(this); + Fl::focus(this); + return true; } - return processed ? true : Group::handle (event); - - case RELEASE: + break; + case FL_RELEASE: processed = - theLayout->buttonRelease (this, event_clicks () + 1, - translateViewXToCanvasX (event_x ()), - translateViewYToCanvasY (event_y ()), - getDwButtonState (), event_button ()); + theLayout->buttonRelease (this, Fl::event_clicks () + 1, + translateViewXToCanvasX (Fl::event_x ()), + translateViewYToCanvasY (Fl::event_y ()), + getDwButtonState (), Fl::event_button ()); _MSG("RELEASE => %s\n", processed ? "true" : "false"); - return processed ? true : Group::handle (event); - - case MOVE: - mouse_x = event_x(); - mouse_y = event_y(); + if (processed) + return true; + break; + case FL_MOVE: + mouse_x = Fl::event_x(); + mouse_y = Fl::event_y(); processed = theLayout->motionNotify (this, translateViewXToCanvasX (mouse_x), translateViewYToCanvasY (mouse_y), getDwButtonState ()); _MSG("MOVE => %s\n", processed ? "true" : "false"); - return processed ? true : Group::handle (event); - - case DRAG: + if (processed) + return true; + break; + case FL_DRAG: processed = theLayout->motionNotify (this, - translateViewXToCanvasX (event_x ()), - translateViewYToCanvasY (event_y ()), + translateViewXToCanvasX (Fl::event_x ()), + translateViewYToCanvasY (Fl::event_y ()), getDwButtonState ()); _MSG("DRAG => %s\n", processed ? "true" : "false"); - return processed ? true : Group::handle (event); - - case ENTER: - theLayout->enterNotify (this, translateViewXToCanvasX (event_x ()), - translateViewYToCanvasY (event_y ()), + if (processed) + return true; + break; + case FL_ENTER: + theLayout->enterNotify (this, + translateViewXToCanvasX (Fl::event_x ()), + translateViewYToCanvasY (Fl::event_y ()), getDwButtonState ()); - return Group::handle (event); - - case LEAVE: + break; + case FL_HIDE: + /* WORKAROUND: strangely, the tooltip window is not automatically hidden + * with its parent. Here we fake a LEAVE to achieve it. */ + case FL_LEAVE: theLayout->leaveNotify (this, getDwButtonState ()); - return Group::handle (event); - + break; + case FL_FOCUS: + if (focused_child && find(focused_child) < children()) { + /* strangely, find() == children() if the child is not found */ + focused_child->take_focus(); + } + return 1; + case FL_UNFOCUS: + focused_child = fl_oldfocus; + return 0; default: - return Group::handle (event); + break; } + return Fl_Group::handle (event); } // ---------------------------------------------------------------------- @@ -269,6 +306,8 @@ int FltkViewBase::handle (int event) void FltkViewBase::setLayout (core::Layout *layout) { theLayout = layout; + if (usesViewport()) + theLayout->viewportSizeChanged(this, w(), h()); } void FltkViewBase::setCanvasSize (int width, int ascent, int descent) @@ -279,55 +318,32 @@ void FltkViewBase::setCanvasSize (int width, int ascent, int descent) void FltkViewBase::setCursor (core::style::Cursor cursor) { - static Cursor *mapDwToFltk[] = { - CURSOR_CROSS, - CURSOR_DEFAULT, - CURSOR_HAND, - CURSOR_MOVE, - CURSOR_WE, - CURSOR_NESW, - CURSOR_NWSE, - CURSOR_NS, - CURSOR_NWSE, - CURSOR_NESW, - CURSOR_NS, - CURSOR_WE, - CURSOR_INSERT, - CURSOR_WAIT, - CURSOR_HELP - }; - - /* - static char *cursorName[] = { - "CURSOR_CROSS", - "CURSOR_DEFAULT", - "CURSOR_HAND", - "CURSOR_MOVE", - "CURSOR_WE", - "CURSOR_NESW", - "CURSOR_NWSE", - "CURSOR_NS", - "CURSOR_NWSE", - "CURSOR_NESW", - "CURSOR_NS", - "CURSOR_WE", - "CURSOR_INSERT", - "CURSOR_WAIT", - "CURSOR_HELP" + static Fl_Cursor mapDwToFltk[] = { + FL_CURSOR_CROSS, + FL_CURSOR_DEFAULT, + FL_CURSOR_HAND, + FL_CURSOR_MOVE, + FL_CURSOR_WE, + FL_CURSOR_NESW, + FL_CURSOR_NWSE, + FL_CURSOR_NS, + FL_CURSOR_NWSE, + FL_CURSOR_NESW, + FL_CURSOR_NS, + FL_CURSOR_WE, + FL_CURSOR_INSERT, + FL_CURSOR_WAIT, + FL_CURSOR_HELP }; - MSG("Cursor changes to '%s'.\n", cursorName[cursor]); - */ - - /** \bug Does not work */ - this->cursor (mapDwToFltk[cursor]); + fl_cursor (mapDwToFltk[cursor]); } void FltkViewBase::setBgColor (core::style::Color *color) { bgColor = color ? ((FltkColor*)color)->colors[dw::core::style::Color::SHADING_NORMAL] : - WHITE; + FL_WHITE; } void FltkViewBase::startDrawing (core::Rectangle *area) @@ -342,12 +358,12 @@ void FltkViewBase::queueDraw (core::Rectangle *area) { drawRegion.addRectangle (area); /** DAMAGE_VALUE is just an arbitrary value other than DAMAGE_EXPOSE here */ - redraw (DAMAGE_VALUE); + damage (FL_DAMAGE_USER1); } void FltkViewBase::queueDrawTotal () { - redraw (DAMAGE_EXPOSE); + damage (FL_DAMAGE_EXPOSE); } void FltkViewBase::cancelQueueDraw () @@ -364,9 +380,16 @@ void FltkViewBase::drawLine (core::style::Color *color, core::style::Color::Shading shading, int x1, int y1, int x2, int y2) { - setcolor(((FltkColor*)color)->colors[shading]); - drawline (translateCanvasXToViewX (x1), translateCanvasYToViewY (y1), - translateCanvasXToViewX (x2), translateCanvasYToViewY (y2)); + fl_color(((FltkColor*)color)->colors[shading]); + // we clip with a large border (5000px), as clipping causes artefacts + // with non-solid line styles. + // However it's still better than no clipping at all. + clipPoint (&x1, &y1, 5000); + clipPoint (&x2, &y2, 5000); + fl_line (translateCanvasXToViewX (x1), + translateCanvasYToViewY (y1), + translateCanvasXToViewX (x2), + translateCanvasYToViewY (y2)); } void FltkViewBase::drawTypedLine (core::style::Color *color, @@ -385,42 +408,42 @@ void FltkViewBase::drawTypedLine (core::style::Color *color, d = len % f*width; gap = ng ? d/ng + (w > 3 ? 2 : 0) : 0; dashes[0] = 1; dashes[1] = f*width-gap; dashes[2] = 0; - line_style(::fltk::DASH + ::fltk::CAP_ROUND, w, dashes); + fl_line_style(FL_DASH + FL_CAP_ROUND, w, dashes); /* These formulas also work, but ain't pretty ;) - * line_style(::fltk::DOT + ::fltk::CAP_ROUND, w); + * fl_line_style(FL_DOT + FL_CAP_ROUND, w); * dashes[0] = 1; dashes[1] = 3*width-2; dashes[2] = 0; */ } else if (type == core::style::LINE_DASHED) { - line_style(::fltk::DASH + ::fltk::CAP_ROUND, w); + fl_line_style(FL_DASH + FL_CAP_ROUND, w); } - setcolor(((FltkColor*)color)->colors[shading]); + fl_color(((FltkColor*)color)->colors[shading]); drawLine (color, shading, x1, y1, x2, y2); if (type != core::style::LINE_NORMAL) - line_style(::fltk::SOLID); + fl_line_style(FL_SOLID); } void FltkViewBase::drawRectangle (core::style::Color *color, core::style::Color::Shading shading, bool filled, - int x, int y, int width, int height) + int X, int Y, int width, int height) { - setcolor(((FltkColor*)color)->colors[shading]); + fl_color(((FltkColor*)color)->colors[shading]); if (width < 0) { - x += width; + X += width; width = -width; } if (height < 0) { - y += height; + Y += height; height = -height; } - int x1 = translateCanvasXToViewX (x); - int y1 = translateCanvasYToViewY (y); - int x2 = translateCanvasXToViewX (x + width); - int y2 = translateCanvasYToViewY (y + height); + int x1 = X; + int y1 = Y; + int x2 = X + width; + int y2 = Y + height; // We only support rectangles with line width 1px, so we clip with // a rectangle 1px wider and higher than what we actually expose. @@ -428,11 +451,15 @@ void FltkViewBase::drawRectangle (core::style::Color *color, clipPoint (&x1, &y1, 1); clipPoint (&x2, &y2, 1); - ::fltk::Rectangle rect (x1, y1, x2 - x1, y2 - y1); + x1 = translateCanvasXToViewX (x1); + y1 = translateCanvasYToViewY (y1); + x2 = translateCanvasXToViewX (x2); + y2 = translateCanvasYToViewY (y2); + if (filled) - fillrect (rect); + fl_rectf (x1, y1, x2 - x1, y2 - y1); else - strokerect (rect); + fl_rect (x1, y1, x2 - x1, y2 - y1); } void FltkViewBase::drawArc (core::style::Color *color, @@ -440,47 +467,55 @@ void FltkViewBase::drawArc (core::style::Color *color, int centerX, int centerY, int width, int height, int angle1, int angle2) { - setcolor(((FltkColor*)color)->colors[shading]); + fl_color(((FltkColor*)color)->colors[shading]); int x = translateCanvasXToViewX (centerX) - width / 2; int y = translateCanvasYToViewY (centerY) - height / 2; - ::fltk::Rectangle rect (x, y, width, height); - addchord(rect, angle1, angle2); - closepath(); + + fl_arc(x, y, width, height, angle1, angle2); if (filled) - fillpath(); - else - strokepath(); + fl_pie(x, y, width, height, angle1, angle2); } void FltkViewBase::drawPolygon (core::style::Color *color, core::style::Color::Shading shading, - bool filled, int points[][2], int npoints) + bool filled, bool convex, core::Point *points, + int npoints) { if (npoints > 0) { + fl_color(((FltkColor*)color)->colors[shading]); + + if (filled) { + if (convex) + fl_begin_polygon(); + else + fl_begin_complex_polygon(); + } else + fl_begin_loop(); + for (int i = 0; i < npoints; i++) { - points[i][0] = translateCanvasXToViewX(points[i][0]); - points[i][1] = translateCanvasYToViewY(points[i][1]); + fl_vertex(translateCanvasXToViewX(points[i].x), + translateCanvasYToViewY(points[i].y)); } - setcolor(((FltkColor*)color)->colors[shading]); - addvertices(npoints, points); - closepath(); - if (filled) - fillpath(); - else - strokepath(); + if (filled) { + if (convex) + fl_end_polygon(); + else + fl_end_complex_polygon(); + } else + fl_end_loop(); } } core::View *FltkViewBase::getClippingView (int x, int y, int width, int height) { - push_clip (translateCanvasXToViewX (x), translateCanvasYToViewY (y), - width, height); + fl_push_clip (translateCanvasXToViewX (x), translateCanvasYToViewY (y), + width, height); return this; } void FltkViewBase::mergeClippingView (core::View *clippingView) { - pop_clip (); + fl_pop_clip (); } // ---------------------------------------------------------------------- @@ -495,80 +530,83 @@ FltkWidgetView::~FltkWidgetView () { } -void FltkWidgetView::layout () { - /** - * pass layout to child widgets. This is needed for complex fltk - * widgets as TextEditor. - * We can't use Group::layout() as that would rearrange the widgets. - */ - for (int i = children () - 1; i >= 0; i--) { - ::fltk::Widget *widget = child (i); - - if (widget->layout_damage ()) { - widget->layout (); - } - } -} - void FltkWidgetView::drawText (core::style::Font *font, core::style::Color *color, core::style::Color::Shading shading, - int x, int y, const char *text, int len) + int X, int Y, const char *text, int len) { FltkFont *ff = (FltkFont*)font; - setfont(ff->font, ff->size); - setcolor(((FltkColor*)color)->colors[shading]); + fl_font(ff->font, ff->size); + fl_color(((FltkColor*)color)->colors[shading]); if (!font->letterSpacing && !font->fontVariant) { - drawtext(text, len, - translateCanvasXToViewX (x), translateCanvasYToViewY (y)); + fl_draw(text, len, + translateCanvasXToViewX (X), translateCanvasYToViewY (Y)); } else { /* Nonzero letter spacing adjustment, draw each glyph individually */ - int viewX = translateCanvasXToViewX (x), - viewY = translateCanvasYToViewY (y); + int viewX = translateCanvasXToViewX (X), + viewY = translateCanvasYToViewY (Y); int curr = 0, next = 0, nb; char chbuf[4]; - wchar_t wc, wcu; + int c, cu; - if (font->fontVariant == 1) { + if (font->fontVariant == core::style::FONT_VARIANT_SMALL_CAPS) { int sc_fontsize = lout::misc::roundInt(ff->size * 0.78); for (curr = 0; next < len; curr = next) { next = theLayout->nextGlyph(text, curr); - wc = utf8decode(text + curr, text + next, &nb); - if ((wcu = towupper(wc)) == wc) { + c = fl_utf8decode(text + curr, text + next, &nb); + if ((cu = fl_toupper(c)) == c) { /* already uppercase, just draw the character */ - setfont(ff->font, ff->size); - drawtext(text + curr, next - curr, viewX, viewY); + fl_font(ff->font, ff->size); + fl_draw(text + curr, next - curr, viewX, viewY); viewX += font->letterSpacing; - viewX += (int)getwidth(text + curr, next - curr); + viewX += (int)fl_width(text + curr, next - curr); } else { /* make utf8 string for converted char */ - nb = utf8encode(wcu, chbuf); - setfont(ff->font, sc_fontsize); - drawtext(chbuf, nb, viewX, viewY); + nb = fl_utf8encode(cu, chbuf); + fl_font(ff->font, sc_fontsize); + fl_draw(chbuf, nb, viewX, viewY); viewX += font->letterSpacing; - viewX += (int)getwidth(chbuf, nb); + viewX += (int)fl_width(chbuf, nb); } } } else { while (next < len) { next = theLayout->nextGlyph(text, curr); - drawtext(text + curr, next - curr, viewX, viewY); + fl_draw(text + curr, next - curr, viewX, viewY); viewX += font->letterSpacing + - (int)getwidth(text + curr,next - curr); + (int)fl_width(text + curr,next - curr); curr = next; } } } } +/* + * "simple" in that it ignores letter-spacing, etc. This was added for image + * alt text where none of that matters. + */ +void FltkWidgetView::drawSimpleWrappedText (core::style::Font *font, + core::style::Color *color, + core::style::Color::Shading shading, + int X, int Y, int W, int H, + const char *text) +{ + FltkFont *ff = (FltkFont*)font; + fl_font(ff->font, ff->size); + fl_color(((FltkColor*)color)->colors[shading]); + fl_draw(text, + translateCanvasXToViewX (X), translateCanvasYToViewY (Y), + W, H, FL_ALIGN_TOP|FL_ALIGN_LEFT|FL_ALIGN_WRAP, NULL, 0); +} + void FltkWidgetView::drawImage (core::Imgbuf *imgbuf, int xRoot, int yRoot, - int x, int y, int width, int height) + int X, int Y, int width, int height) { ((FltkImgbuf*)imgbuf)->draw (this, translateCanvasXToViewX (xRoot), translateCanvasYToViewY (yRoot), - x, y, width, height); + X, Y, width, height); } bool FltkWidgetView::usesFltkWidgets () @@ -576,36 +614,32 @@ bool FltkWidgetView::usesFltkWidgets () return true; } -void FltkWidgetView::addFltkWidget (::fltk::Widget *widget, - core::Allocation *allocation) +void FltkWidgetView::addFltkWidget (Fl_Widget *widget, + core::Allocation *allocation) { allocateFltkWidget (widget, allocation); add (widget); } -void FltkWidgetView::removeFltkWidget (::fltk::Widget *widget) +void FltkWidgetView::removeFltkWidget (Fl_Widget *widget) { remove (widget); } -void FltkWidgetView::allocateFltkWidget (::fltk::Widget *widget, +void FltkWidgetView::allocateFltkWidget (Fl_Widget *widget, core::Allocation *allocation) { - widget->x (translateCanvasXToViewX (allocation->x)); - widget->y (translateCanvasYToViewY (allocation->y)); - widget->w (allocation->width); - widget->h (allocation->ascent + allocation->descent); - - /* widgets created tiny and later resized need this flag to display */ - uchar damage = widget->layout_damage (); - damage |= LAYOUT_XYWH; - widget->layout_damage (damage); + widget->resize (translateCanvasXToViewX (allocation->x), + translateCanvasYToViewY (allocation->y), + allocation->width, + allocation->ascent + allocation->descent); } -void FltkWidgetView::drawFltkWidget (::fltk::Widget *widget, +void FltkWidgetView::drawFltkWidget (Fl_Widget *widget, core::Rectangle *area) { draw_child (*widget); + draw_outside_label(*widget); } } // namespace fltk diff --git a/dw/fltkviewbase.hh b/dw/fltkviewbase.hh index b5c3ab5e..2b248803 100644 --- a/dw/fltkviewbase.hh +++ b/dw/fltkviewbase.hh @@ -4,45 +4,58 @@ #include <time.h> // for time_t #include <sys/time.h> // for time_t in FreeBSD -#include <fltk/Group.h> -#include <fltk/Image.h> -#include <fltk/Scrollbar.h> +#include <FL/Fl_Group.H> +#include <FL/x.H> #include "fltkcore.hh" namespace dw { namespace fltk { -class FltkViewBase: public FltkView, public ::fltk::Group +class FltkViewBase: public FltkView, public Fl_Group { private: + class BackBuffer { + private: + int w; + int h; + bool created; + + public: + Fl_Offscreen offscreen; + + BackBuffer (); + ~BackBuffer (); + void setSize(int w, int h); + }; + typedef enum { DRAW_PLAIN, DRAW_CLIPPED, DRAW_BUFFERED } DrawType; int bgColor; core::Region drawRegion; - ::fltk::Rectangle *exposeArea; - static ::fltk::Image *backBuffer; + core::Rectangle *exposeArea; + static BackBuffer *backBuffer; static bool backBufferInUse; void draw (const core::Rectangle *rect, DrawType type); void drawChildWidgets (); inline void clipPoint (int *x, int *y, int border) { if (exposeArea) { - if (*x < exposeArea->x () - border) - *x = exposeArea->x () - border; - if (*x > exposeArea->r () + border) - *x = exposeArea->r () + border; - if (*y < exposeArea->y () - border) - *y = exposeArea->y () - border; - if (*y > exposeArea->b () + border) - *y = exposeArea->b () + border; + if (*x < exposeArea->x - border) + *x = exposeArea->x - border; + if (*x > exposeArea->x + exposeArea->width + border) + *x = exposeArea->x + exposeArea->width + border; + if (*y < exposeArea->y - border) + *y = exposeArea->y - border; + if (*y > exposeArea->y + exposeArea->height + border) + *y = exposeArea->y + exposeArea->height + border; } } - protected: core::Layout *theLayout; int canvasWidth, canvasHeight; int mouse_x, mouse_y; + Fl_Widget *focused_child; virtual int translateViewXToCanvasX (int x) = 0; virtual int translateViewYToCanvasY (int y) = 0; @@ -85,7 +98,8 @@ public: int angle1, int angle2); void drawPolygon (core::style::Color *color, core::style::Color::Shading shading, - bool filled, int points[][2], int npoints); + bool filled, bool convex, + core::Point *points, int npoints); core::View *getClippingView (int x, int y, int width, int height); void mergeClippingView (core::View *clippingView); @@ -99,21 +113,24 @@ public: FltkWidgetView (int x, int y, int w, int h, const char *label = 0); ~FltkWidgetView (); - void layout(); - void drawText (core::style::Font *font, core::style::Color *color, core::style::Color::Shading shading, int x, int y, const char *text, int len); + void drawSimpleWrappedText (core::style::Font *font, + core::style::Color *color, + core::style::Color::Shading shading, + int x, int y, int w, int h, + const char *text); void drawImage (core::Imgbuf *imgbuf, int xRoot, int yRoot, int x, int y, int width, int height); bool usesFltkWidgets (); - void addFltkWidget (::fltk::Widget *widget, core::Allocation *allocation); - void removeFltkWidget (::fltk::Widget *widget); - void allocateFltkWidget (::fltk::Widget *widget, + void addFltkWidget (Fl_Widget *widget, core::Allocation *allocation); + void removeFltkWidget (Fl_Widget *widget); + void allocateFltkWidget (Fl_Widget *widget, core::Allocation *allocation); - void drawFltkWidget (::fltk::Widget *widget, core::Rectangle *area); + void drawFltkWidget (Fl_Widget *widget, core::Rectangle *area); }; } // namespace fltk diff --git a/dw/fltkviewport.cc b/dw/fltkviewport.cc index a8555c60..19e28854 100644 --- a/dw/fltkviewport.cc +++ b/dw/fltkviewport.cc @@ -21,14 +21,13 @@ #include "fltkviewport.hh" -#include <fltk/draw.h> -#include <fltk/damage.h> -#include <fltk/events.h> +#include <FL/Fl.H> +#include <FL/fl_draw.H> +#include <FL/names.h> #include <stdio.h> #include "../lout/msg.h" -using namespace fltk; using namespace lout; using namespace lout::object; using namespace lout::container::typed; @@ -36,21 +35,39 @@ using namespace lout::container::typed; namespace dw { namespace fltk { -FltkViewport::FltkViewport (int x, int y, int w, int h, const char *label): - FltkWidgetView (x, y, w, h, label) +/* + * Lets SHIFT+{Left,Right} go to the parent + */ +class CustScrollbar : public Fl_Scrollbar { - hscrollbar = new Scrollbar (0, 0, 1, 1); - hscrollbar->set_horizontal(); +public: + CustScrollbar(int x, int y, int w, int h) : Fl_Scrollbar(x,y,w,h) {}; + int handle(int e) { + if (e == FL_SHORTCUT && Fl::event_state() == FL_SHIFT && + (Fl::event_key() == FL_Left || Fl::event_key() == FL_Right)) + return 0; + return Fl_Scrollbar::handle(e); + } +}; + +FltkViewport::FltkViewport (int X, int Y, int W, int H, const char *label): + FltkWidgetView (X, Y, W, H, label) +{ + hscrollbar = new CustScrollbar (x (), y (), 1, 1); + hscrollbar->type(FL_HORIZONTAL); hscrollbar->callback (hscrollbarCallback, this); + hscrollbar->hide(); add (hscrollbar); - vscrollbar = new Scrollbar (0, 0, 1, 1); - vscrollbar->set_vertical(); + vscrollbar = new Fl_Scrollbar (x (), y(), 1, 1); + vscrollbar->type(FL_VERTICAL); vscrollbar->callback (vscrollbarCallback, this); + vscrollbar->hide(); add (vscrollbar); + hasDragScroll = 1; scrollX = scrollY = scrollDX = scrollDY = 0; - dragScrolling = 0; + horScrolling = verScrolling = dragScrolling = 0; gadgetOrientation[0] = GADGET_HORIZONTAL; gadgetOrientation[1] = GADGET_HORIZONTAL; @@ -58,7 +75,7 @@ FltkViewport::FltkViewport (int x, int y, int w, int h, const char *label): gadgetOrientation[3] = GADGET_HORIZONTAL; gadgets = - new container::typed::List <object::TypedPointer < ::fltk::Widget> > + new container::typed::List <object::TypedPointer < Fl_Widget> > (true); } @@ -72,6 +89,7 @@ void FltkViewport::adjustScrollbarsAndGadgetsAllocation () int hdiff = 0, vdiff = 0; int visibility = 0; + _MSG(" >>FltkViewport::adjustScrollbarsAndGadgetsAllocation\n"); if (hscrollbar->visible ()) visibility |= 1; if (vscrollbar->visible ()) @@ -94,32 +112,25 @@ void FltkViewport::adjustScrollbarsAndGadgetsAllocation () vdiff = hscrollbar->visible () ? SCROLLBAR_THICKNESS : 0; } - hscrollbar->x (0); - hscrollbar->y (0 + h () - SCROLLBAR_THICKNESS); - hscrollbar->w (w () - hdiff); - hscrollbar->h (SCROLLBAR_THICKNESS); - - vscrollbar->x (0 + w () - SCROLLBAR_THICKNESS); - vscrollbar->y (0); - vscrollbar->h (h () - vdiff); - vscrollbar->w (SCROLLBAR_THICKNESS); + hscrollbar->resize(x (), y () + h () - SCROLLBAR_THICKNESS, + w () - hdiff, SCROLLBAR_THICKNESS); + vscrollbar->resize(x () + w () - SCROLLBAR_THICKNESS, y (), + SCROLLBAR_THICKNESS, h () - vdiff); - int x = w () - SCROLLBAR_THICKNESS, y = h () - SCROLLBAR_THICKNESS; - for (Iterator <TypedPointer < ::fltk::Widget> > it = gadgets->iterator (); + int X = x () + w () - SCROLLBAR_THICKNESS; + int Y = y () + h () - SCROLLBAR_THICKNESS; + for (Iterator <TypedPointer < Fl_Widget> > it = gadgets->iterator (); it.hasNext (); ) { - ::fltk::Widget *widget = it.getNext()->getTypedValue (); - widget->x (0); - widget->y (0); - widget->w (SCROLLBAR_THICKNESS); - widget->h (SCROLLBAR_THICKNESS); + Fl_Widget *widget = it.getNext()->getTypedValue (); + widget->resize(x (), y (), SCROLLBAR_THICKNESS, SCROLLBAR_THICKNESS); switch (gadgetOrientation [visibility]) { case GADGET_VERTICAL: - y -= SCROLLBAR_THICKNESS; + Y -= SCROLLBAR_THICKNESS; break; case GADGET_HORIZONTAL: - x -= SCROLLBAR_THICKNESS; + X -= SCROLLBAR_THICKNESS; break; } } @@ -141,40 +152,43 @@ void FltkViewport::vscrollbarChanged () scroll (0, vscrollbar->value () - scrollY); } -void FltkViewport::vscrollbarCallback (Widget *vscrollbar, void *viewportPtr) +void FltkViewport::vscrollbarCallback (Fl_Widget *vscrollbar,void *viewportPtr) { ((FltkViewport*)viewportPtr)->vscrollbarChanged (); } -void FltkViewport::hscrollbarCallback (Widget *hscrollbar, void *viewportPtr) +void FltkViewport::hscrollbarCallback (Fl_Widget *hscrollbar,void *viewportPtr) { ((FltkViewport*)viewportPtr)->hscrollbarChanged (); } // ---------------------------------------------------------------------- -void FltkViewport::layout () +void FltkViewport::resize(int X, int Y, int W, int H) { - theLayout->viewportSizeChanged (this, w(), h()); - adjustScrollbarsAndGadgetsAllocation (); + bool dimension_changed = W != w() || H != h(); - FltkWidgetView::layout (); + Fl_Group::resize(X, Y, W, H); + if (dimension_changed) { + theLayout->viewportSizeChanged (this, W, H); + adjustScrollbarsAndGadgetsAllocation (); + } } -void FltkViewport::draw_area (void *data, const Rectangle& cr ) +void FltkViewport::draw_area (void *data, int x, int y, int w, int h) { FltkViewport *vp = (FltkViewport*) data; - push_clip(cr); + fl_push_clip(x, y, w, h); vp->FltkWidgetView::draw (); - for (Iterator <TypedPointer < ::fltk::Widget> > it = vp->gadgets->iterator(); + for (Iterator <TypedPointer < Fl_Widget> > it = vp->gadgets->iterator(); it.hasNext (); ) { - ::fltk::Widget *widget = it.getNext()->getTypedValue (); + Fl_Widget *widget = it.getNext()->getTypedValue (); vp->draw_child (*widget); } - pop_clip(); + fl_pop_clip(); } @@ -182,20 +196,19 @@ void FltkViewport::draw () { int hdiff = vscrollbar->visible () ? SCROLLBAR_THICKNESS : 0; int vdiff = hscrollbar->visible () ? SCROLLBAR_THICKNESS : 0; - Rectangle cr (0, 0, w () - hdiff, h () - vdiff); int d = damage(); - if (d & DAMAGE_SCROLL) { - set_damage (DAMAGE_SCROLL); - scrollrect(cr, -scrollDX, -scrollDY, draw_area, this); - d &= ~DAMAGE_SCROLL; - set_damage (d); + if (d & FL_DAMAGE_SCROLL) { + clear_damage (FL_DAMAGE_SCROLL); + fl_scroll(x(), y(), w() - hdiff, h() - vdiff, + -scrollDX, -scrollDY, draw_area, this); + clear_damage (d & ~FL_DAMAGE_SCROLL); } if (d) { - draw_area(this, cr); + draw_area(this, x(), y(), w () - hdiff, h () - vdiff); - if (d == DAMAGE_CHILD) { + if (d == FL_DAMAGE_CHILD) { if (hscrollbar->damage ()) draw_child (*hscrollbar); if (vscrollbar->damage ()) @@ -212,89 +225,93 @@ void FltkViewport::draw () int FltkViewport::handle (int event) { - _MSG("FltkViewport::handle %d\n", event); - - if (hscrollbar->Rectangle::contains (event_x (), event_y ()) && - !(event_state() & (SHIFT | CTRL | ALT)) && - hscrollbar->send (event)) { - return 1; - } - - if (vscrollbar->Rectangle::contains (event_x (), event_y ()) && - vscrollbar->send (event)) { - return 1; - } + _MSG("FltkViewport::handle %s\n", fl_eventnames[event]); switch(event) { - case ::fltk::KEY: - /* Tell fltk we want to receive KEY events as SHORTCUT. - * As we don't know the exact keybindings set by the user, we ask - * for all of them (except TabKey to keep form navigation). */ - if (::fltk::event_key() != TabKey) + case FL_KEYBOARD: + /* When the viewport has focus (and not one of its children), FLTK + * sends the event here. Returning zero tells FLTK to resend the + * event as SHORTCUT, which we finally route to the parent. */ + + /* As we don't know the exact keybindings set by the user, we ask + * for all of them (except Tab to keep form navigation). */ + if (Fl::event_key() != FL_Tab) return 0; break; - case ::fltk::FOCUS: - /** \bug Draw focus box. */ + case FL_SHORTCUT: + /* send it to the parent (UI) */ + return 0; - /* If the user clicks with the left button we take focus - * and thereby unfocus any form widgets. - * Otherwise we let fltk do the focus handling. - */ - if (::fltk::event_button() == ::fltk::LeftButton || focus_index() < 0) { - focus_index(-1); - return 1; - } + case FL_FOCUS: + /** \bug Draw focus box. */ break; - case ::fltk::UNFOCUS: + case FL_UNFOCUS: /** \bug Undraw focus box. */ break; - case ::fltk::PUSH: - take_focus(); - if (::fltk::event_button() == ::fltk::MiddleButton) { - /* pass event so that middle click can open link in new window */ - if (FltkWidgetView::handle (event) == 0) { + case FL_PUSH: + if (vscrollbar->visible() && Fl::event_inside(vscrollbar)) { + if (vscrollbar->handle(event)) + verScrolling = 1; + } else if (hscrollbar->visible() && Fl::event_inside(hscrollbar)) { + if (hscrollbar->handle(event)) + horScrolling = 1; + } else if (FltkWidgetView::handle(event) == 0 && + Fl::event_button() == FL_MIDDLE_MOUSE) { + if (!hasDragScroll) { + /* let the parent widget handle it... */ + return 0; + } else { + /* receive FL_DRAG and FL_RELEASE */ dragScrolling = 1; - dragX = ::fltk::event_x(); - dragY = ::fltk::event_y(); + dragX = Fl::event_x(); + dragY = Fl::event_y(); setCursor (core::style::CURSOR_MOVE); } - return 1; } + return 1; break; - case ::fltk::DRAG: - if (::fltk::event_button() == ::fltk::MiddleButton) { - if (dragScrolling) { - scroll(dragX - ::fltk::event_x(), dragY - ::fltk::event_y()); - dragX = ::fltk::event_x(); - dragY = ::fltk::event_y(); - return 1; - } + case FL_DRAG: + if (dragScrolling && Fl::event_button() == FL_MIDDLE_MOUSE) { + scroll(dragX - Fl::event_x(), dragY - Fl::event_y()); + dragX = Fl::event_x(); + dragY = Fl::event_y(); + return 1; + } else if (verScrolling) { + vscrollbar->handle(event); + return 1; + } else if (horScrolling) { + hscrollbar->handle(event); + return 1; } break; - case ::fltk:: MOUSEWHEEL: - return (event_dx() ? hscrollbar : vscrollbar)->handle(event); + case FL_MOUSEWHEEL: + return (Fl::event_dx() ? hscrollbar : vscrollbar)->handle(event); break; - case ::fltk::RELEASE: - if (::fltk::event_button() == ::fltk::MiddleButton) { - dragScrolling = 0; + case FL_RELEASE: + if (Fl::event_button() == FL_MIDDLE_MOUSE) { setCursor (core::style::CURSOR_DEFAULT); + } else if (verScrolling) { + vscrollbar->handle(event); + } else if (horScrolling) { + hscrollbar->handle(event); } + horScrolling = verScrolling = dragScrolling = 0; break; - case ::fltk::ENTER: + case FL_ENTER: /* could be the result of, e.g., closing another window. */ - mouse_x = ::fltk::event_x(); - mouse_y = ::fltk::event_y(); + mouse_x = Fl::event_x(); + mouse_y = Fl::event_y(); positionChanged(); break; - case ::fltk::LEAVE: + case FL_LEAVE: mouse_x = mouse_y = -1; break; } @@ -315,7 +332,7 @@ void FltkViewport::setCanvasSize (int width, int ascent, int descent) */ void FltkViewport::positionChanged () { - if (mouse_x != -1) + if (mouse_x != -1 && dragScrolling == false) (void)theLayout->motionNotify (this, translateViewXToCanvasX (mouse_x), translateViewYToCanvasY (mouse_y), @@ -324,7 +341,7 @@ void FltkViewport::positionChanged () /* * For scrollbars, this currently sets the same step to both vertical and - * horizontal. It may me differentiated if necessary. + * horizontal. It may be differentiated if necessary. */ void FltkViewport::setScrollStep(int step) { @@ -373,7 +390,7 @@ void FltkViewport::scrollTo (int x, int y) scrollY = y; adjustScrollbarValues (); - redraw (DAMAGE_SCROLL); + damage(FL_DAMAGE_SCROLL); theLayout->scrollPosChanged (this, scrollX, scrollY); positionChanged(); } @@ -386,9 +403,13 @@ void FltkViewport::scroll (int dx, int dy) void FltkViewport::scroll (core::ScrollCommand cmd) { if (cmd == core::SCREEN_UP_CMD) { - scroll (0, -vscrollbar->pagesize ()); + scroll (0, -h () + vscrollbar->linesize ()); } else if (cmd == core::SCREEN_DOWN_CMD) { - scroll (0, vscrollbar->pagesize ()); + scroll (0, h () - vscrollbar->linesize ()); + } else if (cmd == core::SCREEN_LEFT_CMD) { + scroll (-w() + hscrollbar->linesize (), 0); + } else if (cmd == core::SCREEN_RIGHT_CMD) { + scroll (w() - hscrollbar->linesize (), 0); } else if (cmd == core::LINE_UP_CMD) { scroll (0, (int) -vscrollbar->linesize ()); } else if (cmd == core::LINE_DOWN_CMD) { @@ -408,52 +429,59 @@ void FltkViewport::setViewportSize (int width, int height, int hScrollbarThickness, int vScrollbarThickness) { - if (hScrollbarThickness > 0) - hscrollbar->show (); - else - hscrollbar->hide (); - if (vScrollbarThickness > 0) - vscrollbar->show (); - else - vscrollbar->hide (); + int adjustReq = + (hscrollbar->visible() ? !hScrollbarThickness : hScrollbarThickness) || + (vscrollbar->visible() ? !vScrollbarThickness : vScrollbarThickness); + + _MSG("FltkViewport::setViewportSize old_w,old_h=%dx%d -> w,h=%dx%d\n" + "\t hThick=%d hVis=%d, vThick=%d vVis=%d, adjustReq=%d\n", + w(),h(),width,height, + hScrollbarThickness,hscrollbar->visible(), + vScrollbarThickness,vscrollbar->visible(), adjustReq); + + (hScrollbarThickness > 0) ? hscrollbar->show () : hscrollbar->hide (); + (vScrollbarThickness > 0) ? vscrollbar->show () : vscrollbar->hide (); /* If no scrollbar, go to the beginning */ scroll(hScrollbarThickness ? 0 : -scrollX, vScrollbarThickness ? 0 : -scrollY); + + /* Adjust when scrollbar visibility changes */ + if (adjustReq) + adjustScrollbarsAndGadgetsAllocation (); } void FltkViewport::updateCanvasWidgets (int dx, int dy) { // scroll all child widgets except scroll bars for (int i = children () - 1; i > 0; i--) { - ::fltk::Widget *widget = child (i); + Fl_Widget *widget = child (i); if (widget == hscrollbar || widget == vscrollbar) continue; - widget->x (widget->x () - dx); - widget->y (widget->y () - dy); + widget->position(widget->x () - dx, widget->y () - dy); } } -int FltkViewport::translateViewXToCanvasX (int x) +int FltkViewport::translateViewXToCanvasX (int X) { - return x + scrollX; + return X - x () + scrollX; } -int FltkViewport::translateViewYToCanvasY (int y) +int FltkViewport::translateViewYToCanvasY (int Y) { - return y + scrollY; + return Y - y () + scrollY; } -int FltkViewport::translateCanvasXToViewX (int x) +int FltkViewport::translateCanvasXToViewX (int X) { - return x - scrollX; + return X + x () - scrollX; } -int FltkViewport::translateCanvasYToViewY (int y) +int FltkViewport::translateCanvasYToViewY (int Y) { - return y - scrollY; + return Y + y () - scrollY; } // ---------------------------------------------------------------------- @@ -468,11 +496,11 @@ void FltkViewport::setGadgetOrientation (bool hscrollbarVisible, adjustScrollbarsAndGadgetsAllocation (); } -void FltkViewport::addGadget (::fltk::Widget *gadget) +void FltkViewport::addGadget (Fl_Widget *gadget) { /** \bug Reparent? */ - gadgets->append (new TypedPointer < ::fltk::Widget> (gadget)); + gadgets->append (new TypedPointer < Fl_Widget> (gadget)); adjustScrollbarsAndGadgetsAllocation (); } diff --git a/dw/fltkviewport.hh b/dw/fltkviewport.hh index 1e7f54f6..3df1dccb 100644 --- a/dw/fltkviewport.hh +++ b/dw/fltkviewport.hh @@ -1,8 +1,8 @@ #ifndef __DW_FLTKVIEWPORT_HH__ #define __DW_FLTKVIEWPORT_HH__ -#include <fltk/Group.h> -#include <fltk/Scrollbar.h> +#include <FL/Fl_Group.H> +#include <FL/Fl_Scrollbar.H> #include "core.hh" #include "fltkcore.hh" @@ -21,12 +21,13 @@ private: int scrollX, scrollY; int scrollDX, scrollDY; - int dragScrolling, dragX, dragY; + int hasDragScroll, dragScrolling, dragX, dragY; + int horScrolling, verScrolling; - ::fltk::Scrollbar *vscrollbar, *hscrollbar; + Fl_Scrollbar *vscrollbar, *hscrollbar; GadgetOrientation gadgetOrientation[4]; - lout::container::typed::List <lout::object::TypedPointer < ::fltk::Widget> > + lout::container::typed::List <lout::object::TypedPointer < Fl_Widget> > *gadgets; void adjustScrollbarsAndGadgetsAllocation (); @@ -35,11 +36,11 @@ private: void vscrollbarChanged (); void positionChanged (); - static void hscrollbarCallback (Widget *hscrollbar, void *viewportPtr); - static void vscrollbarCallback (Widget *vscrollbar, void *viewportPtr); + static void hscrollbarCallback (Fl_Widget *hscrollbar, void *viewportPtr); + static void vscrollbarCallback (Fl_Widget *vscrollbar, void *viewportPtr); void updateCanvasWidgets (int oldScrollX, int oldScrollY); - static void draw_area (void *data, const Rectangle& cr); + static void draw_area (void *data, int x, int y, int w, int h); protected: int translateViewXToCanvasX (int x); @@ -51,7 +52,7 @@ public: FltkViewport (int x, int y, int w, int h, const char *label = 0); ~FltkViewport (); - void layout(); + void resize(int x, int y, int w, int h); void draw (); int handle (int event); @@ -69,7 +70,8 @@ public: void setGadgetOrientation (bool hscrollbarVisible, bool vscrollbarVisible, GadgetOrientation gadgetOrientation); - void addGadget (::fltk::Widget *gadget); + void setDragScroll (bool enable) { hasDragScroll = enable ? 1 : 0; } + void addGadget (Fl_Widget *gadget); }; } // namespace fltk diff --git a/dw/image.cc b/dw/image.cc index cab40ed5..1cb9ce39 100644 --- a/dw/image.cc +++ b/dw/image.cc @@ -157,7 +157,7 @@ Image::Image(const char *altText) Image::~Image() { if (altText) - delete altText; + free(altText); if (buffer) buffer->unref (); if (mapKey) @@ -315,8 +315,8 @@ bool Image::buttonPressImpl (core::EventButton *event) { bool ret = false; - currLink = mapList? mapList->link (mapKey, contentX(event),contentY(event)): - getStyle()->x_link; + currLink = mapList ? mapList->link(mapKey,contentX(event),contentY(event)) : + getStyle()->x_link; if (event->button == 3){ (void)layout->emitLinkPress(this, currLink, getStyle()->x_img, -1, -1, event); @@ -330,7 +330,7 @@ bool Image::buttonPressImpl (core::EventButton *event) bool Image::buttonReleaseImpl (core::EventButton *event) { - currLink = mapList ? mapList->link (mapKey, contentX(event),contentY(event)): + currLink = mapList ? mapList->link(mapKey,contentX(event),contentY(event)) : getStyle()->x_link; if (clicking) { int x = isMap ? contentX(event) : -1; @@ -384,12 +384,11 @@ void Image::draw (core::View *view, core::Rectangle *area) getContentHeight()); } - usedView->drawText (getStyle()->font, getStyle()->color, + usedView->drawSimpleWrappedText (getStyle()->font, getStyle()->color, core::style::Color::SHADING_NORMAL, allocation.x + getStyle()->boxOffsetX (), - allocation.y + getStyle()->boxOffsetY () - + getStyle()->font->ascent, - altText, strlen(altText)); + allocation.y + getStyle()->boxOffsetY (), + getContentWidth(), getContentHeight(), altText); if (clippingView) view->mergeClippingView (clippingView); diff --git a/dw/layout.cc b/dw/layout.cc index 8f67e895..d2610687 100644 --- a/dw/layout.cc +++ b/dw/layout.cc @@ -174,7 +174,7 @@ bool Layout::LinkEmitter::emitClick (Widget *widget, int link, int img, Layout::Anchor::~Anchor () { - delete name; + free(name); } // --------------------------------------------------------------------- @@ -194,6 +194,7 @@ Layout::Layout (Platform *platform) canvasWidth = canvasAscent = canvasDescent = 0; usesViewport = false; + drawAfterScrollReq = false; scrollX = scrollY = 0; viewportWidth = viewportHeight = 0; hScrollbarThickness = vScrollbarThickness = 0; @@ -219,14 +220,19 @@ Layout::Layout (Platform *platform) Layout::~Layout () { + widgetAtPoint = NULL; + if (scrollIdleId != -1) platform->removeIdle (scrollIdleId); if (resizeIdleId != -1) platform->removeIdle (resizeIdleId); if (bgColor) bgColor->unref (); - if (topLevel) - delete topLevel; + if (topLevel) { + Widget *w = topLevel; + topLevel = NULL; + delete w; + } delete platform; delete view; delete anchorsTable; @@ -279,9 +285,12 @@ void Layout::removeWidget () void Layout::setWidget (Widget *widget) { - if (topLevel) - delete topLevel; widgetAtPoint = NULL; + if (topLevel) { + Widget *w = topLevel; + topLevel = NULL; + delete w; + } textZone->zoneFree (); addWidget (widget); @@ -449,6 +458,10 @@ void Layout::scrollIdle () if (xChanged || yChanged) { adjustScrollPos (); view->scrollTo (scrollX, scrollY); + if (drawAfterScrollReq) { + drawAfterScrollReq = false; + view->queueDrawTotal (); + } } scrollIdleId = -1; @@ -496,7 +509,11 @@ void Layout::draw (View *view, Rectangle *area) { Rectangle widgetArea, intersection, widgetDrawArea; - if (topLevel) { + if (scrollIdleId != -1) { + /* scroll is pending, defer draw until after scrollIdle() */ + drawAfterScrollReq = true; + + } else if (topLevel) { /* Draw the top level widget. */ widgetArea.x = topLevel->allocation.x; widgetArea.y = topLevel->allocation.y; @@ -527,7 +544,7 @@ void Layout::setAnchor (const char *anchor) _MSG("setAnchor (%s)\n", anchor); if (requestedAnchor) - delete requestedAnchor; + free(requestedAnchor); requestedAnchor = anchor ? strdup (anchor) : NULL; updateAnchor (); } @@ -672,10 +689,9 @@ void Layout::resizeIdle () } // Set viewport sizes. - if (view->usesViewport ()) - view->setViewportSize (viewportWidth, viewportHeight, - actualHScrollbarThickness, - actualVScrollbarThickness); + view->setViewportSize (viewportWidth, viewportHeight, + actualHScrollbarThickness, + actualVScrollbarThickness); } } @@ -691,7 +707,7 @@ void Layout::setSizeHints () if (topLevel) { topLevel->setWidth (viewportWidth - (canvasHeightGreater ? vScrollbarThickness : 0)); - topLevel->setAscent (viewportHeight - vScrollbarThickness); + topLevel->setAscent (viewportHeight - hScrollbarThickness); topLevel->setDescent (0); } } @@ -808,6 +824,7 @@ void Layout::enterNotify (View *view, int x, int y, ButtonState state) */ void Layout::leaveNotify (View *view, ButtonState state) { +#if 0 Widget *lastWidget; EventCrossing event; @@ -820,6 +837,9 @@ void Layout::leaveNotify (View *view, ButtonState state) event.currentWidget = widgetAtPoint; lastWidget->leaveNotify (&event); } +#else + moveOutOfView (state); +#endif } /* @@ -838,15 +858,16 @@ Widget *Layout::getWidgetAtPoint (int x, int y) /* * Emit the necessary crossing events, when the mouse pointer has moved to - * the given widget. + * the given widget (by mouse or scrolling). */ void Layout::moveToWidget (Widget *newWidgetAtPoint, ButtonState state) { Widget *ancestor, *w; Widget **track; - int trackLen, i; + int trackLen, i, i_a; EventCrossing crossingEvent; + _MSG("moveToWidget: wap=%p nwap=%p\n",widgetAtPoint,newWidgetAtPoint); if (newWidgetAtPoint != widgetAtPoint) { // The mouse pointer has been moved into another widget. if (newWidgetAtPoint && widgetAtPoint) @@ -875,6 +896,7 @@ void Layout::moveToWidget (Widget *newWidgetAtPoint, ButtonState state) /* first part */ for (w = widgetAtPoint; w != ancestor; w = w->getParent ()) track[i++] = w; + i_a = i; track[i++] = ancestor; if (newWidgetAtPoint) { /* second part */ @@ -882,17 +904,32 @@ void Layout::moveToWidget (Widget *newWidgetAtPoint, ButtonState state) for (w = newWidgetAtPoint; w != ancestor; w = w->getParent ()) track[i--] = w; } - - /* Send events to all events on the track */ +#if 0 + MSG("Track: %s[ ", widgetAtPoint ? "" : "nil "); + for (i = 0; i < trackLen; i++) + MSG("%s%p ", i == i_a ? ">" : "", track[i]); + MSG("] %s\n", newWidgetAtPoint ? "" : "nil"); +#endif + + /* Send events to the widgets on the track */ for (i = 0; i < trackLen; i++) { crossingEvent.state = state; crossingEvent.currentWidget = widgetAtPoint; // ??? crossingEvent.lastWidget = widgetAtPoint; // ??? - - if (i != 0) - track[i]->enterNotify (&crossingEvent); - if (i != trackLen - 1) + if (i < i_a) { track[i]->leaveNotify (&crossingEvent); + } else if (i == i_a) { /* ancestor */ + /* Don't touch ancestor unless: + * - moving into/from NULL, + * - ancestor becomes the newWidgetAtPoint */ + if (i_a == trackLen-1 && !newWidgetAtPoint) + track[i]->leaveNotify (&crossingEvent); + else if ((i_a == 0 && !widgetAtPoint) || + (i_a == trackLen-1 && newWidgetAtPoint)) + track[i]->enterNotify (&crossingEvent); + } else { + track[i]->enterNotify (&crossingEvent); + } } delete[] track; diff --git a/dw/layout.hh b/dw/layout.hh index dc9bf227..d08eb363 100644 --- a/dw/layout.hh +++ b/dw/layout.hh @@ -138,7 +138,7 @@ private: style::Cursor cursor; int canvasWidth, canvasAscent, canvasDescent; - bool usesViewport; + bool usesViewport, drawAfterScrollReq; int scrollX, scrollY, viewportWidth, viewportHeight; bool canvasHeightGreater; int hScrollbarThickness, vScrollbarThickness; @@ -152,7 +152,8 @@ private: bool scrollIdleNotInterrupted; /* Anchors of the widget tree */ - lout::container::typed::HashTable <lout::object::String, Anchor> *anchorsTable; + lout::container::typed::HashTable <lout::object::String, Anchor> + *anchorsTable; SelectionState selectionState; FindtextState findtextState; @@ -336,6 +337,11 @@ public: return platform->createTooltip (text); } + inline void cancelTooltip () + { + return platform->cancelTooltip (); + } + inline Imgbuf *createImgbuf (Imgbuf::Type type, int width, int height) { return platform->createImgbuf (type, width, height); diff --git a/dw/platform.hh b/dw/platform.hh index 69d1feab..b79b5346 100644 --- a/dw/platform.hh +++ b/dw/platform.hh @@ -131,6 +131,11 @@ public: */ virtual style::Tooltip *createTooltip (const char *text) = 0; + /** + * \brief Cancel a tooltip (either shown or requested) + */ + virtual void cancelTooltip () = 0; + /* * -------------------- * Image Buffers diff --git a/dw/selection.cc b/dw/selection.cc index 275eddaa..1552e80e 100644 --- a/dw/selection.cc +++ b/dw/selection.cc @@ -60,17 +60,6 @@ SelectionState::~SelectionState () reset (); } - -bool SelectionState::DoubleClickEmitter::emitToReceiver (lout::signal::Receiver - *receiver, - int signalNo, - int argc, - Object **argv) -{ - ((DoubleClickReceiver*)receiver)->doubleClick (); - return false; -} - void SelectionState::reset () { resetSelection (); @@ -98,81 +87,64 @@ void SelectionState::resetLink () } bool SelectionState::buttonPress (Iterator *it, int charPos, int linkNo, - EventButton *event, bool withinContent) + EventButton *event) { Widget *itWidget = it->getWidget (); bool ret = false; - if (event && event->button == 1 && - !withinContent && event->numPressed == 2) { - // When the user double-clicks on empty parts, emit the double click - // signal instead of normal processing. Used for full screen - // mode. - doubleClickEmitter.emitDoubleClick (); - // Reset everything, so that dw::core::Selection::buttonRelease will - // ignore the "release" event following soon. - highlight (false, 0); - reset (); + if (!event) return ret; + + if (event->button == 3) { + // menu popup + layout->emitLinkPress (itWidget, linkNo, -1, -1, -1, event); ret = true; - } else { - if (linkNo != -1) { - // link handling - if (event) { - (void) layout->emitLinkPress (itWidget, linkNo, -1, -1, -1, event); - resetLink (); - linkState = LINK_PRESSED; - linkButton = event->button; - DeepIterator *newLink = new DeepIterator (it); - if (newLink->isEmpty ()) { - delete newLink; - resetLink (); - } else { - link = newLink; - // It may be that the user has pressed on something activatable - // (linkNo != -1), but there is no contents, e.g. with images - // without ALTernative text. - if (link) { - linkChar = correctCharPos (link, charPos); - linkNumber = linkNo; - } - } - // We do not return the value of the signal method, - // but we do actually process this event. - ret = true; - } + } else if (linkNo != -1) { + // link handling + (void) layout->emitLinkPress (itWidget, linkNo, -1, -1, -1, event); + resetLink (); + linkState = LINK_PRESSED; + linkButton = event->button; + DeepIterator *newLink = new DeepIterator (it); + if (newLink->isEmpty ()) { + delete newLink; + resetLink (); } else { - // normal selection handling - if (event && event->button == 1) { - highlight (false, 0); - resetSelection (); - - selectionState = SELECTING; - DeepIterator *newFrom = new DeepIterator (it); - if (newFrom->isEmpty ()) { - delete newFrom; - resetSelection (); - } else { - from = newFrom; - fromChar = correctCharPos (from, charPos); - to = from->cloneDeepIterator (); - toChar = correctCharPos (to, charPos); - } - ret = true; - } else { - if (event && event->button == 3) { - // menu popup - layout->emitLinkPress (itWidget, -1, -1, -1, -1, event); - ret = true; - } + link = newLink; + // It may be that the user has pressed on something activatable + // (linkNo != -1), but there is no contents, e.g. with images + // without ALTernative text. + if (link) { + linkChar = correctCharPos (link, charPos); + linkNumber = linkNo; } } + // We do not return the value of the signal method, + // but we do actually process this event. + ret = true; + } else if (event->button == 1) { + // normal selection handling + highlight (false, 0); + resetSelection (); + + selectionState = SELECTING; + DeepIterator *newFrom = new DeepIterator (it); + if (newFrom->isEmpty ()) { + delete newFrom; + resetSelection (); + } else { + from = newFrom; + fromChar = correctCharPos (from, charPos); + to = from->cloneDeepIterator (); + toChar = correctCharPos (to, charPos); + } + ret = true; } return ret; } bool SelectionState::buttonRelease (Iterator *it, int charPos, int linkNo, - EventButton *event, bool withinContent) + EventButton *event) { Widget *itWidget = it->getWidget (); bool ret = false; @@ -214,7 +186,7 @@ bool SelectionState::buttonRelease (Iterator *it, int charPos, int linkNo, } bool SelectionState::buttonMotion (Iterator *it, int charPos, int linkNo, - EventMotion *event, bool withinContent) + EventMotion *event) { if (linkState == LINK_PRESSED) { //link handling @@ -238,21 +210,17 @@ bool SelectionState::buttonMotion (Iterator *it, int charPos, int linkNo, */ bool SelectionState::handleEvent (EventType eventType, Iterator *it, int charPos, int linkNo, - MousePositionEvent *event, - bool withinContent) + MousePositionEvent *event) { switch (eventType) { case BUTTON_PRESS: - return buttonPress (it, charPos, linkNo, (EventButton*)event, - withinContent); + return buttonPress (it, charPos, linkNo, (EventButton*)event); case BUTTON_RELEASE: - return buttonRelease (it, charPos, linkNo, (EventButton*)event, - withinContent); + return buttonRelease (it, charPos, linkNo, (EventButton*)event); case BUTTON_MOTION: - return buttonMotion (it, charPos, linkNo, (EventMotion*)event, - withinContent); + return buttonMotion (it, charPos, linkNo, (EventMotion*)event); default: @@ -334,7 +302,7 @@ void SelectionState::adjustSelection (Iterator *it, int charPos) } } else { if (cmpOld * cmpDiff < 0) { - // The user has reduced the selection. Unighlight the difference. + // The user has reduced the selection. Unhighlight the difference. highlight0 (false, to, 0, newTo, 0, cmpDiff); } diff --git a/dw/selection.hh b/dw/selection.hh index ba03fd18..7f6b1a58 100644 --- a/dw/selection.hh +++ b/dw/selection.hh @@ -44,10 +44,6 @@ namespace core { * otherwise -1 * <tr><td>dw::core::EventButton *event <td>the event itself; only the button * is used - * <tr><td>bool withinContent <td>true, if there is some selectable - * content unter the mouse cursor; if - * set to false, the "full screen" - * feature is used on double click. * </table> * * Look also at dw::core::SelectionState::handleEvent, which may be useful @@ -184,31 +180,7 @@ class SelectionState public: enum { END_OF_WORD = 1 << 30 }; - class DoubleClickReceiver: public lout::signal::Receiver - { - public: - virtual void doubleClick () = 0; - }; - private: - class DoubleClickEmitter: public lout::signal::Emitter - { - private: - enum { DOUBLE_CLICK }; - - protected: - bool emitToReceiver (lout::signal::Receiver *receiver, int signalNo, - int argc, Object **argv); - - public: - inline void connectDoubleClick (DoubleClickReceiver *receiver) - { connect (receiver); } - - inline void emitDoubleClick () { emitVoid (DOUBLE_CLICK, 0, NULL); } - }; - - DoubleClickEmitter doubleClickEmitter; - Layout *layout; // selection @@ -252,19 +224,15 @@ public: inline void setLayout (Layout *layout) { this->layout = layout; } void reset (); - inline void connectDoubleClick (DoubleClickReceiver *receiver) - { doubleClickEmitter.connectDoubleClick (receiver); } - bool buttonPress (Iterator *it, int charPos, int linkNo, - EventButton *event, bool withinContent); + EventButton *event); bool buttonRelease (Iterator *it, int charPos, int linkNo, - EventButton *event, bool withinContent); + EventButton *event); bool buttonMotion (Iterator *it, int charPos, int linkNo, - EventMotion *event, bool withinContent); + EventMotion *event); bool handleEvent (EventType eventType, Iterator *it, int charPos, - int linkNo, MousePositionEvent *event, - bool withinContent); + int linkNo, MousePositionEvent *event); }; } // namespace dw diff --git a/dw/style.cc b/dw/style.cc index ae0f4526..4276862a 100644 --- a/dw/style.cc +++ b/dw/style.cc @@ -431,7 +431,9 @@ static void drawBorderTop(View *view, Style *style, int x1, int y1, int x2, int y2) { - int points[4][2], d, w; + int d, w; + Point points[4]; + const bool filled = true, convex = true; bool ridge = false, inset = false, dotted = false; Color::Shading shading = Color::SHADING_NORMAL; @@ -460,35 +462,38 @@ static void drawBorderTop(View *view, Style *style, if (style->borderWidth.top == 1) { view->drawLine(style->borderColor.top, shading, x1, y1, x2, y2); } else { - points[0][0] = x1; - points[1][0] = x2 + 1; - points[0][1] = points[1][1] = y1; - points[2][0] = points[1][0] - style->borderWidth.right; - points[3][0] = x1 + style->borderWidth.left; - points[2][1] = points[3][1] = points[0][1] + style->borderWidth.top; - view->drawPolygon (style->borderColor.top, shading, true, points, 4); + points[0].x = x1; + points[1].x = x2 + 1; + points[0].y = points[1].y = y1; + points[2].x = points[1].x - style->borderWidth.right; + points[3].x = x1 + style->borderWidth.left; + points[2].y = points[3].y = points[0].y + style->borderWidth.top; + view->drawPolygon (style->borderColor.top, shading, filled, convex, + points, 4); } break; case BORDER_RIDGE: ridge = true; case BORDER_GROOVE: d = style->borderWidth.top & 1; - points[0][0] = x1; - points[1][0] = x2 + 1; - points[0][1] = points[1][1] = y1; - points[2][0] = x2 - style->borderWidth.right / 2; - points[3][0] = x1 + style->borderWidth.left / 2; - points[2][1] = points[3][1] = y1 + style->borderWidth.top / 2 + d; + points[0].x = x1; + points[1].x = x2 + 1; + points[0].y = points[1].y = y1; + points[2].x = x2 - style->borderWidth.right / 2; + points[3].x = x1 + style->borderWidth.left / 2; + points[2].y = points[3].y = y1 + style->borderWidth.top / 2 + d; shading = (ridge) ? Color::SHADING_LIGHT : Color::SHADING_DARK; - view->drawPolygon (style->borderColor.top, shading, true, points, 4); - points[0][0] = x1 + style->borderWidth.left / 2 + d; - points[1][0] = x2 - style->borderWidth.right / 2 + 1 - d; - points[0][1] = points[1][1] = y1 + style->borderWidth.top / 2 + d; - points[2][0] = x2 - style->borderWidth.right + 1 - d; - points[3][0] = x1 + style->borderWidth.left; - points[2][1] = points[3][1] = y1 + style->borderWidth.top; + view->drawPolygon (style->borderColor.top, shading, filled, convex, + points, 4); + points[0].x = x1 + style->borderWidth.left / 2 + d; + points[1].x = x2 - style->borderWidth.right / 2 + 1 - d; + points[0].y = points[1].y = y1 + style->borderWidth.top / 2 + d; + points[2].x = x2 - style->borderWidth.right + 1 - d; + points[3].x = x1 + style->borderWidth.left; + points[2].y = points[3].y = y1 + style->borderWidth.top; shading = (ridge) ? Color::SHADING_DARK : Color::SHADING_LIGHT; - view->drawPolygon (style->borderColor.top, shading, true, points, 4); + view->drawPolygon (style->borderColor.top, shading, filled, convex, + points, 4); break; case BORDER_DOUBLE: w = (int) rint(style->borderWidth.top / 3.0); @@ -499,20 +504,22 @@ static void drawBorderTop(View *view, Style *style, view->drawLine(style->borderColor.top, shading, x1, y1, x2, y2); break; } - points[0][0] = x1; - points[1][0] = x2 + 1; - points[0][1] = points[1][1] = y1; - points[2][0] = points[1][0] - w_r; - points[3][0] = points[0][0] + w_l; - points[2][1] = points[3][1] = points[0][1] + w; - view->drawPolygon (style->borderColor.top, shading, true, points, 4); - points[0][0] = x1 + style->borderWidth.left - w_l; - points[1][0] = x2 + 1 - style->borderWidth.right + w_r; - points[0][1] = points[1][1] = y1 + w + d; - points[2][0] = x2 + 1 - style->borderWidth.right; - points[3][0] = x1 + style->borderWidth.left; - points[2][1] = points[3][1] = y1 + style->borderWidth.top; - view->drawPolygon (style->borderColor.top, shading, true, points, 4); + points[0].x = x1; + points[1].x = x2 + 1; + points[0].y = points[1].y = y1; + points[2].x = points[1].x - w_r; + points[3].x = points[0].x + w_l; + points[2].y = points[3].y = points[0].y + w; + view->drawPolygon (style->borderColor.top, shading, filled, convex, + points, 4); + points[0].x = x1 + style->borderWidth.left - w_l; + points[1].x = x2 + 1 - style->borderWidth.right + w_r; + points[0].y = points[1].y = y1 + w + d; + points[2].x = x2 + 1 - style->borderWidth.right; + points[3].x = x1 + style->borderWidth.left; + points[2].y = points[3].y = y1 + style->borderWidth.top; + view->drawPolygon (style->borderColor.top, shading, filled, convex, + points, 4); break; } } @@ -521,7 +528,9 @@ static void drawBorderBottom(View *view, Style *style, int x1, int y1, int x2, int y2) { - int points[4][2], d, w; + int d, w; + Point points[4]; + const bool filled = true, convex = true; bool ridge = false, inset = false, dotted = false; Color::Shading shading = Color::SHADING_NORMAL; @@ -550,13 +559,14 @@ static void drawBorderBottom(View *view, Style *style, if (style->borderWidth.bottom == 1) { /* 1 pixel line */ view->drawLine(style->borderColor.bottom, shading, x1, y1, x2, y2); } else { - points[0][0] = x1 - 1; - points[1][0] = x2 + 2; - points[0][1] = points[1][1] = y1 + 1; - points[2][0] = points[1][0] - style->borderWidth.right; - points[3][0] = points[0][0] + style->borderWidth.left; - points[2][1] = points[3][1] = points[0][1]-style->borderWidth.bottom; - view->drawPolygon (style->borderColor.bottom, shading, true, points, 4); + points[0].x = x1 - 1; + points[1].x = x2 + 2; + points[0].y = points[1].y = y1 + 1; + points[2].x = points[1].x - style->borderWidth.right; + points[3].x = points[0].x + style->borderWidth.left; + points[2].y = points[3].y = points[0].y-style->borderWidth.bottom; + view->drawPolygon (style->borderColor.bottom, shading, filled, convex, + points, 4); } break; case BORDER_RIDGE: @@ -564,23 +574,25 @@ static void drawBorderBottom(View *view, Style *style, case BORDER_GROOVE: w = style->borderWidth.bottom; d = w & 1; - points[0][0] = x1 - 1; - points[1][0] = x2 + 2 - d; - points[0][1] = points[1][1] = y1 + 1; - points[2][0] = points[1][0] - style->borderWidth.right / 2; - points[3][0] = points[0][0] + style->borderWidth.left / 2 + d; - points[2][1] = points[3][1] = points[0][1] - w/2 - d; + points[0].x = x1 - 1; + points[1].x = x2 + 2 - d; + points[0].y = points[1].y = y1 + 1; + points[2].x = points[1].x - style->borderWidth.right / 2; + points[3].x = points[0].x + style->borderWidth.left / 2 + d; + points[2].y = points[3].y = points[0].y - w/2 - d; shading = (ridge) ? Color::SHADING_DARK : Color::SHADING_LIGHT; - view->drawPolygon (style->borderColor.bottom, shading, true, points, 4); + view->drawPolygon (style->borderColor.bottom, shading, filled, convex, + points, 4); // clockwise - points[0][0] = x1 + style->borderWidth.left - 1; - points[1][0] = x2 + 1 - style->borderWidth.right + 1; - points[0][1] = points[1][1] = y1 - w + 1; - points[2][0] = points[1][0] + style->borderWidth.right / 2; - points[3][0] = points[0][0] - style->borderWidth.left / 2; - points[2][1] = points[3][1] = points[0][1] + w/2; + points[0].x = x1 + style->borderWidth.left - 1; + points[1].x = x2 + 1 - style->borderWidth.right + 1; + points[0].y = points[1].y = y1 - w + 1; + points[2].x = points[1].x + style->borderWidth.right / 2; + points[3].x = points[0].x - style->borderWidth.left / 2; + points[2].y = points[3].y = points[0].y + w/2; shading = (ridge) ? Color::SHADING_LIGHT : Color::SHADING_DARK; - view->drawPolygon (style->borderColor.bottom, shading, true, points, 4); + view->drawPolygon (style->borderColor.bottom, shading, filled, convex, + points, 4); break; case BORDER_DOUBLE: w = (int) rint(style->borderWidth.bottom / 3.0); @@ -591,20 +603,22 @@ static void drawBorderBottom(View *view, Style *style, view->drawLine(style->borderColor.bottom, shading, x1, y1, x2, y2); break; } - points[0][0] = x2 + 2; - points[1][0] = x1 - 1; - points[0][1] = points[1][1] = y1 + 1; - points[2][0] = points[1][0] + w_l; - points[3][0] = points[0][0] - w_r; - points[2][1] = points[3][1] = points[0][1] - w; - view->drawPolygon (style->borderColor.bottom, shading, true, points, 4); - points[0][0] = x2 + 2 - style->borderWidth.right + w_r; - points[1][0] = x1 - 1 + style->borderWidth.left - w_l; - points[0][1] = points[1][1] = y1 + 1 - w - d; - points[2][0] = x1 - 1 + style->borderWidth.left; - points[3][0] = x2 + 2 - style->borderWidth.right; - points[2][1] = points[3][1] = y1 + 1 - style->borderWidth.bottom; - view->drawPolygon (style->borderColor.bottom, shading, true, points, 4); + points[0].x = x2 + 2; + points[1].x = x1 - 1; + points[0].y = points[1].y = y1 + 1; + points[2].x = points[1].x + w_l; + points[3].x = points[0].x - w_r; + points[2].y = points[3].y = points[0].y - w; + view->drawPolygon (style->borderColor.bottom, shading, filled, convex, + points, 4); + points[0].x = x2 + 2 - style->borderWidth.right + w_r; + points[1].x = x1 - 1 + style->borderWidth.left - w_l; + points[0].y = points[1].y = y1 + 1 - w - d; + points[2].x = x1 - 1 + style->borderWidth.left; + points[3].x = x2 + 2 - style->borderWidth.right; + points[2].y = points[3].y = y1 + 1 - style->borderWidth.bottom; + view->drawPolygon (style->borderColor.bottom, shading, filled, convex, + points, 4); break; } } @@ -613,7 +627,9 @@ static void drawBorderLeft(View *view, Style *style, int x1, int y1, int x2, int y2) { - int points[4][2], d, w; + int d, w; + Point points[4]; + bool filled = true, convex = true; bool ridge = false, inset = false, dotted = false; Color::Shading shading = Color::SHADING_NORMAL; @@ -641,13 +657,14 @@ static void drawBorderLeft(View *view, Style *style, if (style->borderWidth.left == 1) { /* 1 pixel line */ view->drawLine(style->borderColor.left, shading, x1, y1, x2, y2); } else { - points[0][0] = points[1][0] = x1; - points[0][1] = y1 - 1; - points[1][1] = y2 + 1; - points[2][0] = points[3][0] = points[0][0] + style->borderWidth.left; - points[2][1] = points[1][1] - style->borderWidth.bottom; - points[3][1] = points[0][1] + style->borderWidth.top; - view->drawPolygon (style->borderColor.left, shading, true, points, 4); + points[0].x = points[1].x = x1; + points[0].y = y1 - 1; + points[1].y = y2 + 1; + points[2].x = points[3].x = points[0].x + style->borderWidth.left; + points[2].y = points[1].y - style->borderWidth.bottom; + points[3].y = points[0].y + style->borderWidth.top; + view->drawPolygon (style->borderColor.left, shading, filled, convex, + points, 4); } break; case BORDER_RIDGE: @@ -655,22 +672,24 @@ static void drawBorderLeft(View *view, Style *style, case BORDER_GROOVE: w = style->borderWidth.left; d = w & 1; - points[0][0] = points[1][0] = x1; - points[0][1] = y1; - points[1][1] = y2; - points[2][0] = points[3][0] = x1 + w / 2 + d; - points[2][1] = y2 - style->borderWidth.bottom / 2; - points[3][1] = y1 + style->borderWidth.top / 2; + points[0].x = points[1].x = x1; + points[0].y = y1; + points[1].y = y2; + points[2].x = points[3].x = x1 + w / 2 + d; + points[2].y = y2 - style->borderWidth.bottom / 2; + points[3].y = y1 + style->borderWidth.top / 2; shading = (ridge) ? Color::SHADING_LIGHT : Color::SHADING_DARK; - view->drawPolygon (style->borderColor.left, shading, true, points, 4); - points[0][0] = points[1][0] = x1 + w / 2 + d; - points[0][1] = y1 + style->borderWidth.top / 2; - points[1][1] = y2 - style->borderWidth.bottom / 2; - points[2][0] = points[3][0] = x1 + w; - points[2][1] = y2 - style->borderWidth.bottom; - points[3][1] = y1 + style->borderWidth.top; + view->drawPolygon (style->borderColor.left, shading, filled, convex, + points, 4); + points[0].x = points[1].x = x1 + w / 2 + d; + points[0].y = y1 + style->borderWidth.top / 2; + points[1].y = y2 - style->borderWidth.bottom / 2; + points[2].x = points[3].x = x1 + w; + points[2].y = y2 - style->borderWidth.bottom; + points[3].y = y1 + style->borderWidth.top; shading = (ridge) ? Color::SHADING_DARK : Color::SHADING_LIGHT; - view->drawPolygon (style->borderColor.left, shading, true, points, 4); + view->drawPolygon (style->borderColor.left, shading, filled, convex, + points, 4); break; case BORDER_DOUBLE: w = (int) rint(style->borderWidth.left / 3.0); @@ -681,20 +700,22 @@ static void drawBorderLeft(View *view, Style *style, view->drawLine(style->borderColor.left, shading, x1, y1, x2, y2-1); break; } - points[0][0] = points[1][0] = x1; - points[0][1] = y1 - 1; - points[1][1] = y2 + 1; - points[2][0] = points[3][0] = points[0][0] + w; - points[2][1] = points[1][1] - w_b; - points[3][1] = points[0][1] + w_t; - view->drawPolygon (style->borderColor.left, shading, true, points, 4); - points[0][0] = points[1][0] = x1 + w + d; - points[0][1] = y1 - 1 + style->borderWidth.top - w_t; - points[1][1] = y2 + 1 - style->borderWidth.bottom + w_b; - points[2][0] = points[3][0] = points[0][0] + w; - points[2][1] = y2 + 1 - style->borderWidth.bottom; - points[3][1] = y1 - 1 + style->borderWidth.top; - view->drawPolygon (style->borderColor.left, shading, true, points, 4); + points[0].x = points[1].x = x1; + points[0].y = y1 - 1; + points[1].y = y2 + 1; + points[2].x = points[3].x = points[0].x + w; + points[2].y = points[1].y - w_b; + points[3].y = points[0].y + w_t; + view->drawPolygon (style->borderColor.left, shading, filled, convex, + points, 4); + points[0].x = points[1].x = x1 + w + d; + points[0].y = y1 - 1 + style->borderWidth.top - w_t; + points[1].y = y2 + 1 - style->borderWidth.bottom + w_b; + points[2].x = points[3].x = points[0].x + w; + points[2].y = y2 + 1 - style->borderWidth.bottom; + points[3].y = y1 - 1 + style->borderWidth.top; + view->drawPolygon (style->borderColor.left, shading, filled, convex, + points, 4); break; } } @@ -703,7 +724,9 @@ static void drawBorderRight(View *view, Style *style, int x1, int y1, int x2, int y2) { - int points[4][2], d, w; + int d, w; + Point points[4]; + const bool filled = true, convex = true; bool ridge = false, inset = false, dotted = false; Color::Shading shading = Color::SHADING_NORMAL; @@ -731,13 +754,14 @@ static void drawBorderRight(View *view, Style *style, if (style->borderWidth.right == 1) { /* 1 pixel line */ view->drawLine(style->borderColor.right, shading, x1, y1, x2, y2); } else { - points[0][0] = points[1][0] = x1 + 1; - points[0][1] = y1 - 1; - points[1][1] = y2 + 1; - points[2][0] = points[3][0] = points[0][0]-style->borderWidth.right; - points[2][1] = points[1][1] - style->borderWidth.bottom; - points[3][1] = points[0][1] + style->borderWidth.top; - view->drawPolygon (style->borderColor.right, shading, true,points,4); + points[0].x = points[1].x = x1 + 1; + points[0].y = y1 - 1; + points[1].y = y2 + 1; + points[2].x = points[3].x = points[0].x-style->borderWidth.right; + points[2].y = points[1].y - style->borderWidth.bottom; + points[3].y = points[0].y + style->borderWidth.top; + view->drawPolygon (style->borderColor.right, shading, filled, convex, + points,4); } break; case BORDER_RIDGE: @@ -745,22 +769,24 @@ static void drawBorderRight(View *view, Style *style, case BORDER_GROOVE: w = style->borderWidth.right; d = w & 1; - points[0][0] = points[1][0] = x1 + 1; - points[0][1] = y1; - points[1][1] = y2; - points[2][0] = points[3][0] = points[0][0] - w / 2 - d; - points[2][1] = y2 - style->borderWidth.bottom / 2; - points[3][1] = points[0][1] + style->borderWidth.top / 2; + points[0].x = points[1].x = x1 + 1; + points[0].y = y1; + points[1].y = y2; + points[2].x = points[3].x = points[0].x - w / 2 - d; + points[2].y = y2 - style->borderWidth.bottom / 2; + points[3].y = points[0].y + style->borderWidth.top / 2; shading = (ridge) ? Color::SHADING_DARK : Color::SHADING_LIGHT; - view->drawPolygon (style->borderColor.right, shading, true, points, 4); - points[0][0] = points[1][0] = x1 + 1 - w / 2 - d; - points[0][1] = y1 + style->borderWidth.top / 2; - points[1][1] = y2 - style->borderWidth.bottom / 2; - points[2][0] = points[3][0] = x1 + 1 - w; - points[2][1] = y2 - style->borderWidth.bottom; - points[3][1] = y1 + style->borderWidth.top; + view->drawPolygon (style->borderColor.right, shading, filled, convex, + points, 4); + points[0].x = points[1].x = x1 + 1 - w / 2 - d; + points[0].y = y1 + style->borderWidth.top / 2; + points[1].y = y2 - style->borderWidth.bottom / 2; + points[2].x = points[3].x = x1 + 1 - w; + points[2].y = y2 - style->borderWidth.bottom; + points[3].y = y1 + style->borderWidth.top; shading = (ridge) ? Color::SHADING_LIGHT: Color::SHADING_DARK; - view->drawPolygon (style->borderColor.right, shading, true, points, 4); + view->drawPolygon (style->borderColor.right, shading, filled, convex, + points, 4); break; case BORDER_DOUBLE: w = (int) rint(style->borderWidth.right / 3.0); @@ -771,20 +797,22 @@ static void drawBorderRight(View *view, Style *style, view->drawLine(style->borderColor.right, shading, x1, y1, x2, y2); break; } - points[0][0] = points[1][0] = x1 + 1; - points[0][1] = y1 - 1; - points[1][1] = y2 + 1; - points[2][0] = points[3][0] = points[0][0] - w; - points[2][1] = points[1][1] - w_b; - points[3][1] = points[0][1] + w_t; - view->drawPolygon (style->borderColor.right, shading, true, points, 4); - points[0][0] = points[1][0] = x1 + 1 - w - d; - points[0][1] = y1 - 1 + style->borderWidth.top - w_t; - points[1][1] = y2 + 1 - style->borderWidth.bottom + w_b; - points[2][0] = points[3][0] = points[0][0] - w; - points[2][1] = y2 + 1 - style->borderWidth.bottom; - points[3][1] = y1 - 1 + style->borderWidth.top; - view->drawPolygon (style->borderColor.right, shading, true, points, 4); + points[0].x = points[1].x = x1 + 1; + points[0].y = y1 - 1; + points[1].y = y2 + 1; + points[2].x = points[3].x = points[0].x - w; + points[2].y = points[1].y - w_b; + points[3].y = points[0].y + w_t; + view->drawPolygon (style->borderColor.right, shading, filled, convex, + points, 4); + points[0].x = points[1].x = x1 + 1 - w - d; + points[0].y = y1 - 1 + style->borderWidth.top - w_t; + points[1].y = y2 + 1 - style->borderWidth.bottom + w_b; + points[2].x = points[3].x = points[0].x - w; + points[2].y = y2 + 1 - style->borderWidth.bottom; + points[3].y = y1 - 1 + style->borderWidth.top; + view->drawPolygon (style->borderColor.right, shading, filled, convex, + points, 4); break; } } @@ -799,8 +827,7 @@ void drawBorder (View *view, Rectangle *area, Style *style, bool inverse) { /** \todo a lot! */ - Color::Shading dark, light, normal; - int xb1, yb1, xb2, yb2, xp1, yp1, xp2, yp2; + int xb1, yb1, xb2, yb2; // top left and bottom right point of outer border boundary xb1 = x + style->margin.left; @@ -808,15 +835,17 @@ void drawBorder (View *view, Rectangle *area, xb2 = x + (width > 0 ? width - 1 : 0) - style->margin.right; yb2 = y + (height > 0 ? height - 1 : 0) - style->margin.bottom; - // top left and bottom right point of inner border boundary - xp1 = xb1 + style->borderWidth.left; - yp1 = yb1 + style->borderWidth.top; - xp2 = xb2 - style->borderWidth.right; - yp2 = yb2 - style->borderWidth.bottom; - - light = inverse ? Color::SHADING_DARK : Color::SHADING_LIGHT; - dark = inverse ? Color::SHADING_LIGHT : Color::SHADING_DARK; - normal = inverse ? Color::SHADING_INVERSE : Color::SHADING_NORMAL; + /* + // top left and bottom right point of inner border boundary + xp1 = xb1 + style->borderWidth.left; + yp1 = yb1 + style->borderWidth.top; + xp2 = xb2 - style->borderWidth.right; + yp2 = yb2 - style->borderWidth.bottom; + + light = inverse ? Color::SHADING_DARK : Color::SHADING_LIGHT; + dark = inverse ? Color::SHADING_LIGHT : Color::SHADING_DARK; + normal = inverse ? Color::SHADING_INVERSE : Color::SHADING_NORMAL; + */ drawBorderRight(view, style, xb2, yb1, xb2, yb2); drawBorderLeft(view, style, xb1, yb1, xb1, yb2); diff --git a/dw/table.cc b/dw/table.cc index 6708b3f0..8a46ce7c 100644 --- a/dw/table.cc +++ b/dw/table.cc @@ -320,11 +320,19 @@ void Table::addCell (Widget *widget, int colspan, int rowspan) for (int col = 0; col < colspanEff; col++) for (int row = 0; row < rowspan; row++) if (!(col == 0 && row == 0)) { + int i = (curRow + row) * numCols + curCol + col; + + child = children->get(i); + if (child) { + MSG("Overlapping spans in table.\n"); + assert(child->type == Child::SPAN_SPACE); + delete child; + } child = new Child (); child->type = Child::SPAN_SPACE; child->spanSpace.startCol = curCol; child->spanSpace.startRow = curRow; - children->set ((curRow + row) * numCols + curCol + col, child); + children->set (i, child); } // Set the "root" cell. diff --git a/dw/textblock.cc b/dw/textblock.cc index fffbac2f..6ded2413 100644 --- a/dw/textblock.cc +++ b/dw/textblock.cc @@ -26,6 +26,15 @@ #include <math.h> // remove again #include <limits.h> +/* + * Local variables + */ + /* The tooltip under mouse pointer in current textblock. No ref. hold. + * (having one per view looks not worth the extra clutter). */ +static dw::core::style::Tooltip *hoverTooltip = NULL; + + + using namespace lout; namespace dw { @@ -81,8 +90,6 @@ Textblock::Textblock (bool limitTextWidth) availAscent = 100; availDescent = 0; - hoverTooltip = NULL; - this->limitTextWidth = limitTextWidth; for (int layer = 0; layer < core::HIGHLIGHT_NUM_LAYERS; layer++) { @@ -96,7 +103,10 @@ Textblock::Textblock (bool limitTextWidth) Textblock::~Textblock () { - //_MSG ("Textblock::~Textblock\n"); + _MSG("Textblock::~Textblock\n"); + + /* make sure not to call a free'd tooltip (very fast overkill) */ + hoverTooltip = NULL; for (int i = 0; i < words->size(); i++) { Word *word = words->getRef (i); @@ -372,13 +382,13 @@ void Textblock::sizeAllocateImpl (core::Allocation *allocation) * http://www.dillo.org/test/img/ */ childAllocation.y = lineYOffsetCanvasAllocation (line, allocation) - + (line->boxAscent - word->size.ascent); - // - word->content.widget->getStyle()->margin.top; + + (line->boxAscent - word->size.ascent) + - word->content.widget->getStyle()->margin.top; childAllocation.width = word->size.width; - childAllocation.ascent = word->size.ascent; - // + word->content.widget->getStyle()->margin.top; - childAllocation.descent = word->size.descent; - // + word->content.widget->getStyle()->margin.bottom; + childAllocation.ascent = word->size.ascent + + word->content.widget->getStyle()->margin.top; + childAllocation.descent = word->size.descent + + word->content.widget->getStyle()->margin.bottom; oldChildAllocation = word->content.widget->getAllocation(); @@ -609,6 +619,11 @@ bool Textblock::buttonReleaseImpl (core::EventButton *event) return sendSelectionEvent (core::SelectionState::BUTTON_RELEASE, event); } +/* + * Handle motion inside the widget + * (special care is necessary when switching from another widget, + * because hoverLink and hoverTooltip are meaningless then). + */ bool Textblock::motionNotifyImpl (core::EventMotion *event) { if (event->state & core::BUTTON1_MASK) @@ -630,6 +645,7 @@ bool Textblock::motionNotifyImpl (core::EventMotion *event) hoverLink = style->x_link; hoverTooltip = style->x_tooltip; } + // Show/hide tooltip if (tooltipOld != hoverTooltip) { if (tooltipOld) @@ -639,21 +655,32 @@ bool Textblock::motionNotifyImpl (core::EventMotion *event) } else if (hoverTooltip) hoverTooltip->onMotion (); - if (hoverLink != linkOld) + _MSG("MN tb=%p tooltipOld=%p hoverTooltip=%p\n", + this, tooltipOld, hoverTooltip); + if (hoverLink != linkOld) { + /* LinkEnter with hoverLink == -1 is the same as LinkLeave */ return layout->emitLinkEnter (this, hoverLink, -1, -1, -1); - else + } else { return hoverLink != -1; + } } } void Textblock::enterNotifyImpl (core::EventCrossing *event) { + _MSG(" tb=%p, ENTER NotifyImpl hoverTooltip=%p\n", this, hoverTooltip); + /* reset hoverLink so linkEnter is detected */ + hoverLink = -2; } void Textblock::leaveNotifyImpl (core::EventCrossing *event) { - hoverLink = -1; - (void) layout->emitLinkEnter (this, hoverLink, -1, -1, -1); + _MSG(" tb=%p, LEAVE NotifyImpl: hoverTooltip=%p\n", this, hoverTooltip); + + /* leaving the viewport can't be handled by motionNotifyImpl() */ + if (hoverLink >= 0) + layout->emitLinkEnter (this, -1, -1, -1, -1); + if (hoverTooltip) { hoverTooltip->onLeave(); hoverTooltip = NULL; @@ -671,10 +698,9 @@ bool Textblock::sendSelectionEvent (core::SelectionState::EventType eventType, int nextWordStartX, wordStartX, wordX, nextWordX, yFirst, yLast; int charPos = 0, link = -1, prevPos, wordIndex, lineIndex; Word *word; - bool found, r, withinContent = true; + bool found, r; if (words->size () == 0) { - withinContent = false; wordIndex = -1; } else { lastLine = lines->getRef (lines->size () - 1); @@ -683,12 +709,10 @@ bool Textblock::sendSelectionEvent (core::SelectionState::EventType eventType, lastLine->boxDescent; if (event->yCanvas < yFirst) { // Above the first line: take the first word. - withinContent = false; wordIndex = 0; charPos = 0; } else if (event->yCanvas >= yLast) { // Below the last line: take the last word. - withinContent = false; wordIndex = words->size () - 1; word = words->getRef (wordIndex); charPos = word->content.type == core::Content::TEXT ? @@ -701,13 +725,11 @@ bool Textblock::sendSelectionEvent (core::SelectionState::EventType eventType, if (event->yWidget > (lineYOffsetWidget (line) + line->boxAscent + line->boxDescent)) { // Choose this break. - withinContent = false; wordIndex = line->lastWord; charPos = 0; } else if (event->xWidget < lineXOffsetWidget (line)) { // Left of the first word in the line. wordIndex = line->firstWord; - withinContent = false; charPos = 0; } else { nextWordStartX = lineXOffsetWidget (line); @@ -761,7 +783,6 @@ bool Textblock::sendSelectionEvent (core::SelectionState::EventType eventType, if (!found) { // No word found in this line (i.e. we are on the right side), // take the last of this line. - withinContent = false; wordIndex = line->lastWord; if (wordIndex >= words->size ()) wordIndex--; @@ -775,8 +796,7 @@ bool Textblock::sendSelectionEvent (core::SelectionState::EventType eventType, } it = new TextblockIterator (this, core::Content::SELECTION_CONTENT, wordIndex); - r = selectionHandleEvent (eventType, it, charPos, link, event, - withinContent); + r = selectionHandleEvent (eventType, it, charPos, link, event); it->unref (); return r; } @@ -1058,29 +1078,29 @@ void Textblock::wordWrap(int wordIndex) // lastLine->boxDescent); if (word->content.type == core::Content::WIDGET) { + int collapseMarginTop = 0; + lastLine->marginDescent = misc::max (lastLine->marginDescent, word->size.descent + word->content.widget->getStyle()->margin.bottom); - //DBG_OBJ_ARRSET_NUM (page, "lines.%d.descent", page->num_lines - 1, - // lastLine->descent); + if (lines->size () == 1 && + word->content.widget->blockLevel () && + getStyle ()->borderWidth.top == 0 && + getStyle ()->padding.top == 0) { + // collapse top margin of parent element with top margin of first child + // see: http://www.w3.org/TR/CSS21/box.html#collapsing-margins + collapseMarginTop = getStyle ()->margin.top; + } - /* If the widget is not in the first line of the paragraph, its top - * margin may make the line higher. - */ - if (lines->size () > 1) { - /* Here, we know already what the break and the bottom margin - * contributed to the space before this line. - */ - lastLine->boxAscent = + lastLine->boxAscent = misc::max (lastLine->boxAscent, + word->size.ascent, word->size.ascent - + word->content.widget->getStyle()->margin.top); + + word->content.widget->getStyle()->margin.top + - collapseMarginTop); - //DBG_OBJ_ARRSET_NUM (page, "lines.%d.ascent", page->num_lines - 1, - // lastLine->boxAscent); - } } else { lastLine->marginDescent = misc::max (lastLine->marginDescent, lastLine->boxDescent); @@ -1197,11 +1217,7 @@ void Textblock::calcWidgetSize (core::Widget *widget, core::Requisition *size) widget->setAscent (availAscent); widget->setDescent (availDescent); widget->sizeRequest (size); -// size->ascent -= wstyle->margin.top; -// size->descent -= wstyle->margin.bottom; } else { - /* TODO: Use margin.{top|bottom} here, like above. - * (No harm for the next future.) */ if (wstyle->width == core::style::LENGTH_AUTO || wstyle->height == core::style::LENGTH_AUTO) widget->sizeRequest (&requisition); @@ -1232,6 +1248,10 @@ void Textblock::calcWidgetSize (core::Widget *widget, core::Requisition *size) size->descent = (int) (len * availDescent); } } + + /* ascent and descent in words do not contain margins. */ + size->ascent -= wstyle->margin.top; + size->descent -= wstyle->margin.bottom; } /** @@ -1499,11 +1519,6 @@ void Textblock::drawLine (Line *line, core::View *view, core::Rectangle *area) word->content.type == core::Content::WIDGET) { if (word->size.width > 0) { - if (word->style->hasBackground ()) { - drawBox (view, word->style, area, xWidget, - yWidgetBase - line->boxAscent, word->size.width, - line->boxAscent + line->boxDescent, false); - } if (word->content.type == core::Content::WIDGET) { core::Widget *child = word->content.widget; core::Rectangle childArea; @@ -1511,6 +1526,11 @@ void Textblock::drawLine (Line *line, core::View *view, core::Rectangle *area) if (child->intersects (area, &childArea)) child->draw (view, &childArea); } else { + if (word->style->hasBackground ()) { + drawBox (view, word->style, area, xWidget, + yWidgetBase - line->boxAscent, word->size.width, + line->boxAscent + line->boxDescent, false); + } drawText(wordIndex, view, area, xWidget, yWidgetBase); } } diff --git a/dw/textblock.hh b/dw/textblock.hh index baa5e29a..ea7795b8 100644 --- a/dw/textblock.hh +++ b/dw/textblock.hh @@ -315,9 +315,7 @@ protected: struct {int index, nChar;} hlStart[core::HIGHLIGHT_NUM_LAYERS], hlEnd[core::HIGHLIGHT_NUM_LAYERS]; - int hoverLink; /* The link under the button. */ - core::style::Tooltip *hoverTooltip; /* The tooltip under the button. No ref - * hold. */ + int hoverLink; /* The link under the mouse pointer */ void queueDrawRange (int index1, int index2); diff --git a/dw/types.cc b/dw/types.cc index 4d94f494..074cb352 100644 --- a/dw/types.cc +++ b/dw/types.cc @@ -140,16 +140,15 @@ void Polygon::draw (core::View *view, core::style::Style *style, int x, int y) { if (points->size()) { int i; - const bool filled = false; - int (*pointArray)[2] = - (int (*)[2]) malloc(points->size() * sizeof(*pointArray)); + const bool filled = false, convex = false; + Point *pointArray = (Point *)malloc(points->size()*sizeof(struct Point)); for (i = 0; i < points->size(); i++) { - pointArray[i][0] = x + points->getRef(i)->x; - pointArray[i][1] = y + points->getRef(i)->y; + pointArray[i].x = x + points->getRef(i)->x; + pointArray[i].y = y + points->getRef(i)->y; } view->drawPolygon(style->color, core::style::Color::SHADING_NORMAL, - filled, pointArray, i); + filled, convex, pointArray, i); free(pointArray); } } diff --git a/dw/types.hh b/dw/types.hh index 420a500f..b5204331 100644 --- a/dw/types.hh +++ b/dw/types.hh @@ -32,7 +32,8 @@ enum VPosition VPOS_NO_CHANGE }; -enum ScrollCommand {SCREEN_UP_CMD, SCREEN_DOWN_CMD, LINE_UP_CMD, LINE_DOWN_CMD, +enum ScrollCommand {SCREEN_UP_CMD, SCREEN_DOWN_CMD, SCREEN_LEFT_CMD, + SCREEN_RIGHT_CMD, LINE_UP_CMD, LINE_DOWN_CMD, LEFT_CMD, RIGHT_CMD, TOP_CMD, BOTTOM_CMD}; /* @@ -266,9 +266,9 @@ void ComplexButtonResource::LayoutReceiver::canvasSizeChanged (int width, int descent) { /** - * \todo The argument to queueResize is not always true. (But this works.) + * \todo Verify that this is correct. */ - resource->queueResize (true); + resource->queueResize (resource->childWidget->extremesChanged ()); } ComplexButtonResource::ComplexButtonResource () @@ -421,12 +421,10 @@ class SelectionResource: public Resource { public: virtual void addItem (const char *str, bool enabled, bool selected) = 0; - virtual void pushGroup (const char *name, bool enabled) = 0; virtual void popGroup () = 0; virtual int getNumberOfItems () = 0; - virtual const char *getItem (int index) = 0; virtual bool isSelected (int index) = 0; }; @@ -92,12 +92,6 @@ public: * This will normally imply a resize of the UI widget. Width and height are * the dimensions of the new size, \em including the scrollbar thicknesses. * - * \bug The rest of this comment needs to be updated. - * - * markerWidthDiff and markerHeightDiff are the respective dimensions of - * the viewport markers (see dw::core::getMarkerWidthDiff and - * dw::core::getMarkerHeightDiff), if they are 0, the respective - * marker should not be shown at all. */ virtual void setViewportSize (int width, int height, int hScrollbarThickness, @@ -179,12 +173,16 @@ public: int angle1, int angle2) = 0; virtual void drawPolygon (style::Color *color, style::Color::Shading shading, - bool filled, int points[][2], int npoints) = 0; + bool filled, bool convex, Point *points, + int npoints) = 0; virtual void drawText (style::Font *font, style::Color *color, style::Color::Shading shading, int x, int y, const char *text, int len) = 0; - + virtual void drawSimpleWrappedText (style::Font *font, style::Color *color, + style::Color::Shading shading, + int x, int y, int w, int h, + const char *text) = 0; virtual void drawImage (Imgbuf *imgbuf, int xRoot, int yRoot, int x, int y, int width, int height) = 0; diff --git a/dw/widget.hh b/dw/widget.hh index 3034b982..e18344c7 100644 --- a/dw/widget.hh +++ b/dw/widget.hh @@ -206,25 +206,21 @@ protected: inline bool selectionButtonPress (Iterator *it, int charPos, int linkNo, EventButton *event, bool withinContent) - { return layout->selectionState.buttonPress (it, charPos, linkNo, event, - withinContent); } + { return layout->selectionState.buttonPress (it, charPos, linkNo, event); } inline bool selectionButtonRelease (Iterator *it, int charPos, int linkNo, EventButton *event, bool withinContent) - { return layout->selectionState.buttonRelease (it, charPos, linkNo, event, - withinContent); } + { return layout->selectionState.buttonRelease (it, charPos, linkNo, event);} inline bool selectionButtonMotion (Iterator *it, int charPos, int linkNo, EventMotion *event, bool withinContent) - { return layout->selectionState.buttonMotion (it, charPos, linkNo, event, - withinContent); } + { return layout->selectionState.buttonMotion (it, charPos, linkNo, event); } inline bool selectionHandleEvent (SelectionState::EventType eventType, Iterator *it, int charPos, int linkNo, - MousePositionEvent *event, - bool withinContent) + MousePositionEvent *event) { return layout->selectionState.handleEvent (eventType, it, charPos, linkNo, - event, withinContent); } + event); } private: void *deleteCallbackData; diff --git a/lout/misc.cc b/lout/misc.cc index 78f758fd..f45a3450 100644 --- a/lout/misc.cc +++ b/lout/misc.cc @@ -144,7 +144,7 @@ void StringBuffer::clear () Node *node, *nextNode; for (node = firstNode; node; node = nextNode) { nextNode = node->next; - delete node->data; + free(node->data); delete node; } firstNode = lastNode = NULL; diff --git a/lout/object.cc b/lout/object.cc index d72b1eec..08ea0452 100644 --- a/lout/object.cc +++ b/lout/object.cc @@ -224,7 +224,7 @@ String::String (const char *str): ConstString (str ? strdup(str) : NULL) String::~String () { if (str) - delete str; + free((char *)str); } // ------------ diff --git a/src/IO/Url.h b/src/IO/Url.h index 95919f11..15934e13 100644 --- a/src/IO/Url.h +++ b/src/IO/Url.h @@ -18,7 +18,8 @@ int a_Http_proxy_auth(void); void a_Http_set_proxy_passwd(const char *str); char *a_Http_make_connect_str(const DilloUrl *url); const char *a_Http_get_proxy_urlstr(); -Dstr *a_Http_make_query_str(const DilloUrl *url, bool_t use_proxy); +Dstr *a_Http_make_query_str(const DilloUrl *url, const DilloUrl *requester, + bool_t use_proxy); void a_Http_ccc (int Op, int Branch, int Dir, ChainLink *Info, void *Data1, void *Data2); diff --git a/src/IO/about.c b/src/IO/about.c index 508bfd11..77af318f 100644 --- a/src/IO/about.c +++ b/src/IO/about.c @@ -61,7 +61,7 @@ const char *const AboutSplash= " <table border='0' cellspacing='0' cellpadding='2'><tr>\n" " <td>\n" " <td>\n" -" <a href='http://www.dillo.org/dillo2-help.html'>\n" +" <a href='http://www.dillo.org/dillo3-help.html'>\n" " Help</a>\n" " <tr>\n" " <td> \n" @@ -153,12 +153,6 @@ const char *const AboutSplash= " <table border='0' cellspacing='0' cellpadding='5'><tr><td>\n" " <table border='0' cellpadding='2'><tr>\n" " <td> \n" -" <td><a href='http://www.google.com/'>Google</a>\n" -" <tr>\n" -" <td> \n" -" <td><a href='http://www.wikipedia.org/'>Wikipedia</a>\n" -" <tr>\n" -" <td> \n" " <td><a href='http://www.gutenberg.org/'>P. Gutenberg</a>\n" " <tr>\n" " <td> \n" @@ -240,20 +234,27 @@ const char *const AboutSplash= "<tr>\n" " <td bgcolor='#CCCCCC'>\n" " <h4>Release overview</h4>\n" -" February 11, 2010\n" +" September 06, 2011\n" "<tr>\n" " <td bgcolor='#FFFFFF'>\n" " <table border='0' cellspacing='0' cellpadding='5'>\n" " <tr>\n" " <td>\n" "<p>\n" -"This release features a major overhaul of the cookies subsystem,\n" -"a reimplementation of the DPI API, a configurable connection limit,\n" -"and various CSS improvements.\n" +"Dillo-3.0 is a port to FLTK-1.3, which is big news because FLTK-1.3.0 was\n" +"<a href='http://fltk.org/articles.php?L1086'>released</a>\n" +"in June, clearing the way for Dillo to return to those distributions\n" +"which had excluded Dillo2 due to FLTK2 never being officially released.\n" +"<p>\n" +"Dillo-3.0 also has plenty of improvements and bugfixes.\n" +"<p>\n" +"After this release, the core team will focus on implementing the CSS\n" +"feature of floating elements. This will <em>greatly</em> improve dillo's\n" +"web page rendering since many sites have adopted floats instead of tables.\n" +"<p>\n" +"The new dillo3 has shown excellent stability in our experience.\n" +"The core team welcomes developers willing to join our workforce.\n" "<p>\n" -"Remember that the dillo project uses a release model where every new\n" -"version shall be better than the last.\n" -"<EM>Keep up with the latest one!</EM>\n" " </table>\n" "</table>\n" "</table>\n" @@ -274,27 +275,39 @@ const char *const AboutSplash= " <tr>\n" " <td>\n" "<ul>\n" -"<li>Added keybindings for scrolling.\n" -"<li>Help button and local help file.\n" -"<li>Add support for multiple class names in CSS.\n" -"<li>Fix X11 coordinate overflows.\n" -"<li>Improve CSS font parsing.\n" -"<li>Enable font face setting via <font> element.\n" -"<li>Ignore XML comment markers in CSS.\n" -"<li>Fix user agent style for nested <ul>.\n" -"<li>Handle signed chars. Added dIsspace() and dIsalnum() to dlib.\n" -"<li>Changed the CCCs to build in one step (for both HTTP and DPI).\n" -"<li>Remove the empty cache entry lingering after connection abort.\n" -"<li>Fixed URL unescaping in the datauri DPI.\n" -"<li>Changed and reimplemented the DPI API.\n" -"<li>Allow linebreaks around Chinese/Japanese characters.\n" -"<li>Fix scrolling for text search.\n" -"<li>Tooltips.\n" -"<li>Enable popup menu below bottom of page content.\n" -"<li>Handle JPEGs with CMYK color space.\n" -"<li>General cookies overhaul.\n" -"<li>Fixed a bug in w3c_mode.\n" -"<li>Limit number of simultaneous connections.\n" +"<li>Ported Dillo to FLTK-1.3.\n" +"<li>Native build on OSX.\n" +"<li>Default binding for close-all changed from Alt-q to Ctrl-q.\n" +"<li>Default binding for close-tab changed from Ctrl-q to Ctrl-w.\n" +"<li>Default binding for left-tab changed to Shift-Ctrl-Tab.\n" +"<li>Rewrote the User Interface: much simpler design and event handling.\n" +"<li>Added on-the-fly panel resize (tiny/small/medium and normal/small icons).\n" +"<li>'hide-panels' key action now hides the findbar if present,\n" +" and toggles display of the control panels otherwise.\n" +"<li>Allow multiple search engines to be set in dillorc, with a menu\n" +" in the web search dialog to select between them.\n" +"<li>Added an optional label to dillorc's search_url.\n" +" Format: \"[<label> ]<url>\"\n" +"<li>Add right_click_closes_tab preference (default is middle click).\n" +"<li>Allow binding to non-ASCII keys and multimedia keys.\n" +"<li>Avoid a certificate dialog storm on some HTTPS sites (BUG#868).\n" +"<li>Enable line wrapping for <textarea>. (BUG#903)\n" +"<li>Avoid double render after going Back or Forward\n" +" (it takes half the time now!)\n" +"<li>Implemented a custom tabs handler (to allow fine control of it).\n" +"<li>Rewrote dw's crossing-events dispatcher (avoids redundant events).\n" +"<li>Fixed a years old bug: stamped tooltips when scrolling with keyboard.\n" +"<li>Fixed a border case in URL resolver: empty path + {query|fragment}\n" +" (BUG#948)\n" +"<li>Cancel the expected URL after offering a download (BUG#982)\n" +"<li>Eliminated a pack of 22 compiler warnings (gcc-4.6.1 amd64)\n" +"<li>Removed 'large' option of panel_size preference.\n" +"<li>Removed --enable-ansi configure option.\n" +"<li>Limit saved cookie size.\n" +"<li>Wrap image alt text.\n" +"<li>Added support for CSS adjacent sibling selectors.\n" +"<li>Fix redraw loops and reenabled limit_text_width dillorc option.\n" +"<li>Collapse parent's and first child's top margin.\n" "</ul>\n" " </table>\n" "</table>\n" diff --git a/src/IO/http.c b/src/IO/http.c index 77a1be43..41ee137a 100644 --- a/src/IO/http.c +++ b/src/IO/http.c @@ -174,7 +174,7 @@ static void Http_connect_queued_sockets(HostConnection_t *hc) MSG_BW(sd->web, 1, "ERROR: %s", dStrerror(sd->Err)); a_Chain_bfcb(OpAbort, sd->Info, NULL, "Both"); dFree(sd->Info); - Http_socket_free((int) sd->Info->LocalKey); + Http_socket_free(VOIDP2INT(sd->Info->LocalKey)); } else { sd->connected_to = hc->host; hc->active_connections++; @@ -271,7 +271,8 @@ static Dstr *Http_make_content_type(const DilloUrl *url) /* * Make the http query string */ -Dstr *a_Http_make_query_str(const DilloUrl *url, bool_t use_proxy) +Dstr *a_Http_make_query_str(const DilloUrl *url, const DilloUrl *requester, + bool_t use_proxy) { const char *auth; char *ptr, *cookies, *referer; @@ -296,7 +297,7 @@ Dstr *a_Http_make_query_str(const DilloUrl *url, bool_t use_proxy) (URL_PATH_(url) || URL_QUERY_(url)) ? "" : "/"); } - cookies = a_Cookies_get_query(url); + cookies = a_Cookies_get_query(url, requester); auth = a_Auth_get_auth_str(url); referer = Http_get_referer(url); if (URL_FLAGS(url) & URL_Post) { @@ -365,7 +366,8 @@ static void Http_send_query(ChainLink *Info, SocketData_t *S) DataBuf *dbuf; /* Create the query */ - query = a_Http_make_query_str(S->web->url, S->flags & HTTP_SOCKET_USE_PROXY); + query = a_Http_make_query_str(S->web->url, S->web->requester, + S->flags & HTTP_SOCKET_USE_PROXY); dbuf = a_Chain_dbuf_new(query->str, query->len, 0); /* actually this message is sent too early. diff --git a/src/IO/iowatch.cc b/src/IO/iowatch.cc index f67b711f..f5243934 100644 --- a/src/IO/iowatch.cc +++ b/src/IO/iowatch.cc @@ -11,19 +11,17 @@ // Simple ADT for watching file descriptor activity -#include <fltk/run.h> +#include <FL/Fl.H> #include "iowatch.hh" -using namespace fltk; - - // // Hook a Callback for a certain activities in a FD // -void a_IOwatch_add_fd(int fd, int when, FileHandler Callback, void *usr_data=0) +void a_IOwatch_add_fd(int fd, int when, Fl_FD_Handler Callback, + void *usr_data = 0) { if (fd >= 0) - add_fd(fd, when, Callback, usr_data); + Fl::add_fd(fd, when, Callback, usr_data); } // @@ -32,6 +30,6 @@ void a_IOwatch_add_fd(int fd, int when, FileHandler Callback, void *usr_data=0) void a_IOwatch_remove_fd(int fd, int when) { if (fd >= 0) - remove_fd(fd, when); + Fl::remove_fd(fd, when); } diff --git a/src/IO/iowatch.hh b/src/IO/iowatch.hh index 681d0080..e2d497f1 100644 --- a/src/IO/iowatch.hh +++ b/src/IO/iowatch.hh @@ -2,7 +2,7 @@ #define __IO_WATCH_H__ /* - * BUG: enum {READ = 1, WRITE = 4, EXCEPT = 8} borrowed from fltk/run.h + * BUG: enum {READ = 1, WRITE = 4, EXCEPT = 8} borrowed from FL/Enumerations.H */ #define DIO_READ 1 #define DIO_WRITE 4 diff --git a/src/Makefile.am b/src/Makefile.am index 0f09b716..9de7eed5 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -18,7 +18,8 @@ dillo_LDADD = \ $(top_builddir)/dw/libDw-fltk.a \ $(top_builddir)/dw/libDw-core.a \ $(top_builddir)/lout/liblout.a \ - @LIBJPEG_LIBS@ @LIBPNG_LIBS@ @LIBFLTK_LIBS@ @LIBZ_LIBS@ @LIBICONV_LIBS@ + @LIBJPEG_LIBS@ @LIBPNG_LIBS@ @LIBFLTK_LIBS@ @LIBZ_LIBS@ \ + @LIBICONV_LIBS@ @LIBPTHREAD_LIBS@ dillo_SOURCES = \ dillo.cc \ @@ -486,8 +486,8 @@ static int Auth_do_auth_dialog(const char *realm, const DilloUrl *url) AuthDialogData_t *data; _MSG("auth.c: Auth_do_auth_dialog: realm = '%s'\n", realm); - message = dStrconcat("Enter a user and password for \"", - realm, "\".", NULL); + message = dStrconcat("The server at ", URL_HOST(url), " requires a username" + " and password for \"", realm, "\".", NULL); data = dNew(AuthDialogData_t, 1); data->realm_name = dStrdup(realm); data->url = a_Url_dup(url); @@ -55,7 +55,6 @@ BrowserWindow *a_Bw_new() bw->nav_stack_ptr = -1; /* Init expect */ - bw->nav_expecting = FALSE; bw->nav_expect_url = NULL; bw->redirect_level = 0; @@ -313,3 +312,27 @@ BrowserWindow *a_Bw_get(int i) return NULL; } +/* expect API ------------------------------------------------------------- */ + +void a_Bw_expect(BrowserWindow *bw, const DilloUrl *url) +{ + a_Url_free(bw->nav_expect_url); + bw->nav_expect_url = a_Url_dup(url); +} + +void a_Bw_cancel_expect(BrowserWindow *bw) +{ + a_Url_free(bw->nav_expect_url); + bw->nav_expect_url = NULL; +} + +bool_t a_Bw_expecting(BrowserWindow *bw) +{ + return (bw->nav_expect_url != NULL); +} + +const DilloUrl *a_Bw_expected_url(BrowserWindow *bw) +{ + return bw->nav_expect_url; +} + @@ -46,12 +46,9 @@ struct _BrowserWindow /* 'nav_stack_ptr' refers to what's being displayed */ int nav_stack_ptr; /* [0 based; -1 = empty] */ /* When the user clicks a link, the URL isn't pushed directly to history; - * nav_expect_url holds it until the first answer-bytes are got. Only then - * it is sent to history and referenced at the top of nav_stack */ + * nav_expect_url holds it until a dw is assigned to it. Only then an entry + * is made in history and referenced at the top of nav_stack */ DilloUrl *nav_expect_url; - /* 'nav_expecting' is true while dillo waits for non-cached URL data, - * until a dw is assigned to it. */ - bool_t nav_expecting; /* Counter for the number of hops on a redirection. Used to stop * redirection loops (accounts for WEB_RootUrl only) */ @@ -88,6 +85,11 @@ void *a_Bw_get_url_doc(BrowserWindow *bw, const DilloUrl *Url); void a_Bw_remove_doc(BrowserWindow *bw, void *vdoc); void a_Bw_add_url(BrowserWindow *bw, const DilloUrl *Url); void a_Bw_cleanup(BrowserWindow *bw); +/* expect API */ +void a_Bw_expect(BrowserWindow *bw, const DilloUrl *Url); +void a_Bw_cancel_expect(BrowserWindow *bw); +bool_t a_Bw_expecting(BrowserWindow *bw); +const DilloUrl *a_Bw_expected_url(BrowserWindow *bw); typedef void (*BwCallback_t)(BrowserWindow *bw, const void *data); diff --git a/src/cache.c b/src/cache.c index d26ae610..6094a8d5 100644 --- a/src/cache.c +++ b/src/cache.c @@ -742,13 +742,29 @@ static void Cache_parse_header(CacheEntry_t *entry) #ifndef DISABLE_COOKIES if ((Cookies = Cache_parse_multiple_fields(header, "Set-Cookie"))) { - char *server_date = Cache_parse_field(header, "Date"); + CacheClient_t *client; + + for (i = 0; (client = dList_nth_data(ClientQueue, i)); ++i) { + if (client->Url == entry->Url) { + DilloWeb *web = client->Web; + + if (!web->requester || + a_Url_same_organization(entry->Url, web->requester)) { + char *server_date = Cache_parse_field(header, "Date"); + + a_Cookies_set(Cookies, entry->Url, server_date); + dFree(server_date); + break; + } + } + } + if (i >= dList_length(ClientQueue)) { + MSG("Cache: cookies not accepted from '%s'\n", URL_STR(entry->Url)); + } - a_Cookies_set(Cookies, entry->Url, server_date); for (i = 0; (data = dList_nth_data(Cookies, i)); ++i) dFree(data); dList_free(Cookies); - dFree(server_date); } #endif /* !DISABLE_COOKIES */ @@ -893,6 +909,16 @@ void a_Cache_process_dbuf(int Op, const char *buf, size_t buf_size, MSG("entry->ExpectedSize = %d, entry->TransferSize = %d\n", entry->ExpectedSize, entry->TransferSize); } + if (!entry->TransferSize && !(entry->Flags & CA_Redirect) && + (entry->Flags & WEB_RootUrl)) { + char *eol = strchr(entry->Header->str, '\n'); + if (eol) { + char *status_line = dStrndup(entry->Header->str, + eol - entry->Header->str); + MSG_HTTP("Body was empty. Server sent status: %s\n", status_line); + dFree(status_line); + } + } entry->Flags |= CA_GotData; entry->Flags &= ~CA_Stopped; /* it may catch up! */ if (entry->TransferDecoder) { @@ -1166,6 +1192,8 @@ static CacheEntry_t *Cache_process_queue(CacheEntry_t *entry) } } if (AbortEntry) { + if (ClientWeb->flags & WEB_RootUrl) + a_Nav_cancel_expect_if_eq(Client_bw, Client->Url); a_Bw_remove_client(Client_bw, Client->Key); Cache_client_dequeue(Client, NULLKey); --i; /* Keep the index value in the next iteration */ @@ -300,17 +300,26 @@ static char *Capi_dpi_build_cmd(DilloWeb *web, char *server) if (strcmp(server, "proto.https") == 0) { /* Let's be kind and make the HTTP query string for the dpi */ char *proxy_connect = a_Http_make_connect_str(web->url); - Dstr *http_query = a_Http_make_query_str(web->url, FALSE); + Dstr *http_query = a_Http_make_query_str(web->url, web->requester,FALSE); /* BUG: embedded NULLs in query data will truncate message */ + + /* BUG: WORKAROUND: request to only check the root URL's certificate. + * This avoids the dialog bombing that stems from loading multiple + * https images/resources in a single page. A proper fix would take + * either to implement the https-dpi as a server (with state), + * or to move back https handling into dillo. */ if (proxy_connect) { const char *proxy_urlstr = a_Http_get_proxy_urlstr(); cmd = a_Dpip_build_cmd("cmd=%s proxy_url=%s proxy_connect=%s " - "url=%s query=%s", "open_url", proxy_urlstr, + "url=%s query=%s check_cert=%s", + "open_url", proxy_urlstr, proxy_connect, URL_STR(web->url), - http_query->str); + http_query->str, + (web->flags & WEB_RootUrl) ? "true" : "false"); } else { - cmd = a_Dpip_build_cmd("cmd=%s url=%s query=%s", - "open_url", URL_STR(web->url),http_query->str); + cmd = a_Dpip_build_cmd("cmd=%s url=%s query=%s check_cert=%s", + "open_url", URL_STR(web->url),http_query->str, + (web->flags & WEB_RootUrl) ? "true" : "false"); } dFree(proxy_connect); dStr_free(http_query, 1); @@ -376,9 +385,7 @@ static bool_t Capi_filters_test(const DilloUrl *wanted, case PREFS_FILTER_SAME_DOMAIN: { const char *req_host = URL_HOST(requester), - *want_host = URL_HOST(wanted), - *req_suffix, - *want_suffix; + *want_host = URL_HOST(wanted); if (want_host[0] == '\0') { ret = (req_host[0] == '\0' || !dStrcasecmp(URL_SCHEME(wanted), "data")) ? TRUE : FALSE; @@ -386,14 +393,12 @@ static bool_t Capi_filters_test(const DilloUrl *wanted, /* This will regard "www.dillo.org" and "www.dillo.org." as * different, but it doesn't seem worth caring about. */ - req_suffix = a_Url_host_find_public_suffix(req_host); - want_suffix = a_Url_host_find_public_suffix(want_host); - - ret = dStrcasecmp(req_suffix, want_suffix) == 0; + ret = a_Url_same_organization(wanted, requester); + } + if (ret == FALSE) { + MSG("Capi_filters_test: deny from '%s' to '%s'\n", req_host, + want_host); } - - MSG("Capi_filters_test: %s from '%s' to '%s'\n", - ret ? "ALLOW" : "DENY", req_host, want_host); break; } case PREFS_FILTER_ALLOW_ALL: diff --git a/src/chain.c b/src/chain.c index d4098a2d..a13b3120 100644 --- a/src/chain.c +++ b/src/chain.c @@ -22,7 +22,7 @@ */ #if VERBOSE static void Chain_debug_msg(char *FuncStr, int Op, int Branch, int Dir, - ChainLink *Info) + ChainLink *Info) { const char *StrOps[] = {"", "OpStart", "OpSend", "OpStop", "OpEnd", "OpAbort"}; @@ -31,7 +31,8 @@ static void Chain_debug_msg(char *FuncStr, int Op, int Branch, int Dir, Info, Info ? Info->Flags : -1); } #else -static void Chain_debug_msg() { } +static void Chain_debug_msg(char *FuncStr, int Op, int Branch, int Dir, + ChainLink *Info) { } #endif /* * Create and initialize a new chain-link diff --git a/src/cookies.c b/src/cookies.c index 7b9062e2..d1451dc1 100644 --- a/src/cookies.c +++ b/src/cookies.c @@ -179,7 +179,7 @@ void a_Cookies_set(Dlist *cookie_strings, const DilloUrl *set_url, /* * Return a string containing cookie data for an HTTP query. */ -char *a_Cookies_get_query(const DilloUrl *request_url) +char *a_Cookies_get_query(const DilloUrl *query_url, const DilloUrl *requester) { char *cmd, *dpip_tag, *query; const char *path; @@ -188,16 +188,25 @@ char *a_Cookies_get_query(const DilloUrl *request_url) if (disabled) return dStrdup(""); - action = Cookies_control_check(request_url); + action = Cookies_control_check(query_url); if (action == COOKIE_DENY) { - _MSG("Cookies: denied GET for %s\n", URL_HOST_(request_url)); + _MSG("Cookies: denied GET for %s\n", URL_HOST_(query_url)); return dStrdup(""); } - path = URL_PATH_(request_url); + + if (requester == NULL) { + /* request made by user */ + } else if (!a_Url_same_organization(query_url, requester)) { + MSG("Cookies: No cookies sent for third-party request by '%s' for " + "'%s'\n", URL_HOST(requester), URL_STR(query_url)); + return dStrdup(""); + } + + path = URL_PATH_(query_url); cmd = a_Dpip_build_cmd("cmd=%s scheme=%s host=%s path=%s", - "get_cookie", URL_SCHEME(request_url), - URL_HOST(request_url), path ? path : "/"); + "get_cookie", URL_SCHEME(query_url), + URL_HOST(query_url), path ? path : "/"); /* Get the answer from cookies.dpi */ _MSG("cookies.c: a_Dpi_send_blocking_cmd cmd = {%s}\n", cmd); diff --git a/src/cookies.h b/src/cookies.h index d6ee1ccd..1cdb82ac 100644 --- a/src/cookies.h +++ b/src/cookies.h @@ -7,12 +7,13 @@ extern "C" { #ifdef DISABLE_COOKIES -# define a_Cookies_get_query(url) dStrdup("") +# define a_Cookies_get_query(url, requester) dStrdup("") # define a_Cookies_set() ; # define a_Cookies_init() ; # define a_Cookies_freeall() ; #else - char *a_Cookies_get_query(const DilloUrl *request_url); + char *a_Cookies_get_query(const DilloUrl *query_url, + const DilloUrl *requester); void a_Cookies_set(Dlist *cookie_string, const DilloUrl *set_url, const char *server_date); void a_Cookies_init( void ); @@ -104,6 +104,7 @@ CssSelector::CssSelector () { cs = selectorList->getRef (selectorList->size () - 1); cs->notMatchingBefore = -1; + cs->combinator = CHILD; cs->selector = new CssSimpleSelector (); }; @@ -133,6 +134,7 @@ bool CssSelector::match (Doctree *docTree, const DoctreeNode *node) { switch (comb) { case CHILD: + case ADJACENT_SIBLING: if (!sel->match (node)) return false; break; @@ -156,7 +158,11 @@ bool CssSelector::match (Doctree *docTree, const DoctreeNode *node) { } comb = cs->combinator; - node = docTree->parent (node); + + if (comb == ADJACENT_SIBLING) + node = docTree->sibling (node); + else + node = docTree->parent (node); } return true; @@ -200,6 +206,9 @@ void CssSelector::print () { case DESCENDANT: fprintf (stderr, "\" \" "); break; + case ADJACENT_SIBLING: + fprintf (stderr, "+ "); + break; default: fprintf (stderr, "? "); break; @@ -489,39 +498,21 @@ void CssStyleSheet::apply (CssPropertyList *props, } } -CssStyleSheet *CssContext::userAgentStyle; -CssStyleSheet *CssContext::userStyle; -CssStyleSheet *CssContext::userImportantStyle; - CssContext::CssContext () { pos = 0; - for (int o = CSS_PRIMARY_USER_AGENT; o < CSS_PRIMARY_LAST; o++) - sheet[o] = NULL; - - if (userAgentStyle == NULL) { - userAgentStyle = new CssStyleSheet (); - userStyle = new CssStyleSheet (); - userImportantStyle = new CssStyleSheet (); + memset (sheet, 0, sizeof(sheet)); + sheet[CSS_PRIMARY_USER_AGENT] = new CssStyleSheet (); + sheet[CSS_PRIMARY_USER] = new CssStyleSheet (); + sheet[CSS_PRIMARY_USER_IMPORTANT] = new CssStyleSheet (); - sheet[CSS_PRIMARY_USER_AGENT] = userAgentStyle; - sheet[CSS_PRIMARY_USER] = userStyle; - sheet[CSS_PRIMARY_USER_IMPORTANT] = userImportantStyle; - - buildUserAgentStyle (); - buildUserStyle (); - } - - sheet[CSS_PRIMARY_USER_AGENT] = userAgentStyle; - sheet[CSS_PRIMARY_USER] = userStyle; - sheet[CSS_PRIMARY_USER_IMPORTANT] = userImportantStyle; + buildUserAgentStyle (); + buildUserStyle (); } CssContext::~CssContext () { for (int o = CSS_PRIMARY_USER_AGENT; o < CSS_PRIMARY_LAST; o++) - if (sheet[o] != userAgentStyle && sheet[o] != userStyle && - sheet[o] != userImportantStyle) - delete sheet[o]; + delete sheet[o]; } /** @@ -535,7 +526,8 @@ CssContext::~CssContext () { */ void CssContext::apply (CssPropertyList *props, Doctree *docTree, DoctreeNode *node, - CssPropertyList *tagStyle, CssPropertyList *nonCssHints) { + CssPropertyList *tagStyle, CssPropertyList *tagStyleImportant, + CssPropertyList *nonCssHints) { if (sheet[CSS_PRIMARY_USER_AGENT]) sheet[CSS_PRIMARY_USER_AGENT]->apply (props, docTree, node); @@ -554,6 +546,9 @@ void CssContext::apply (CssPropertyList *props, Doctree *docTree, if (sheet[CSS_PRIMARY_AUTHOR_IMPORTANT]) sheet[CSS_PRIMARY_AUTHOR_IMPORTANT]->apply (props, docTree, node); + if (tagStyleImportant) + tagStyleImportant->apply (props); + if (sheet[CSS_PRIMARY_USER_IMPORTANT]) sheet[CSS_PRIMARY_USER_IMPORTANT]->apply (props, docTree, node); } @@ -458,9 +458,6 @@ class CssStyleSheet { */ class CssContext { private: - static CssStyleSheet *userAgentStyle; - static CssStyleSheet *userStyle; - static CssStyleSheet *userImportantStyle; CssStyleSheet *sheet[CSS_PRIMARY_USER_IMPORTANT + 1]; int pos; @@ -475,7 +472,8 @@ class CssContext { CssPrimaryOrder order); void apply (CssPropertyList *props, Doctree *docTree, DoctreeNode *node, - CssPropertyList *tagStyle, CssPropertyList *nonCssHints); + CssPropertyList *tagStyle, CssPropertyList *tagStyleImportant, + CssPropertyList *nonCssHints); }; #endif diff --git a/src/cssparser.cc b/src/cssparser.cc index 7b522c8c..f6e60731 100644 --- a/src/cssparser.cc +++ b/src/cssparser.cc @@ -1053,7 +1053,7 @@ void CssParser::parseDeclaration(CssPropertyList * props, CssPropertyList * importantProps) { CssPropertyInfo pi = {NULL, {CSS_TYPE_UNUSED}, NULL}, *pip; - CssShorthandInfo si, *sip; + CssShorthandInfo *sip; CssValueType type = CSS_TYPE_UNUSED; CssPropertyName prop; @@ -1091,7 +1091,6 @@ void CssParser::parseDeclaration(CssPropertyList * props, } } else { /* Try shorthands. */ - si.symbol = tval; sip = (CssShorthandInfo *) bsearch(&pi, Css_shorthand_info, CSS_SHORTHAND_NUM, @@ -1294,6 +1293,9 @@ CssSelector *CssParser::parseSelector() } else if (ttype == CSS_TK_CHAR && tval[0] == '>') { selector->addSimpleSelector (CssSelector::CHILD); nextToken(); + } else if (ttype == CSS_TK_CHAR && tval[0] == '+') { + selector->addSimpleSelector (CssSelector::ADJACENT_SIBLING); + nextToken(); } else if (ttype != CSS_TK_END && spaceSeparated) { selector->addSimpleSelector (CssSelector::DESCENDANT); } else { @@ -1526,7 +1528,7 @@ const char * CssParser::propertyNameString(CssPropertyName name) { return Css_property_info[name].symbol; } - + void CssParser::ignoreBlock() { int depth = 0; @@ -1594,22 +1596,16 @@ void CssParser::parse(DilloHtml *html, DilloUrl *url, CssContext * context, } } -CssPropertyList *CssParser::parseDeclarationBlock(const char *buf, int buflen) +void CssParser::parseDeclarationBlock(const char *buf, int buflen, + CssPropertyList *props, + CssPropertyList *propsImortant) { - CssPropertyList *props = new CssPropertyList (true); CssParser parser (NULL, CSS_ORIGIN_AUTHOR, buf, buflen); parser.withinBlock = true; do - parser.parseDeclaration(props, NULL); + parser.parseDeclaration(props, propsImortant); while (!(parser.ttype == CSS_TK_END || (parser.ttype == CSS_TK_CHAR && parser.tval[0] == '}'))); - - if (props->size () == 0) { - delete props; - props = NULL; - } - - return props; } diff --git a/src/cssparser.hh b/src/cssparser.hh index 1542405d..8609877b 100644 --- a/src/cssparser.hh +++ b/src/cssparser.hh @@ -47,8 +47,9 @@ class CssParser { void ignoreStatement(); public: - static CssPropertyList *parseDeclarationBlock(const char *buf, - int buflen); + static void parseDeclarationBlock(const char *buf, int buflen, + CssPropertyList *props, + CssPropertyList *propsImortant); static void parse(DilloHtml *html, DilloUrl *url, CssContext *context, const char *buf, int buflen, CssOrigin origin); static const char *propertyNameString(CssPropertyName name); diff --git a/src/dialog.cc b/src/dialog.cc index 47af9921..15e5d7a9 100644 --- a/src/dialog.cc +++ b/src/dialog.cc @@ -13,58 +13,192 @@ #include <math.h> // for rint() -#include <fltk/Window.h> -#include <fltk/ask.h> -#include <fltk/file_chooser.h> -#include <fltk/TextBuffer.h> -#include <fltk/ReturnButton.h> -#include <fltk/TextDisplay.h> -#include <fltk/HighlightButton.h> -#include <fltk/WordwrapOutput.h> -#include <fltk/Input.h> -#include <fltk/SecretInput.h> +#include <FL/Fl_Window.H> +#include <FL/Fl_File_Chooser.H> +#include <FL/Fl_Return_Button.H> +#include <FL/Fl_Text_Display.H> +#include <FL/Fl_Button.H> +#include <FL/Fl_Return_Button.H> +#include <FL/Fl_Output.H> +#include <FL/Fl_Input.H> +#include <FL/Fl_Secret_Input.H> +#include <FL/Fl_Choice.H> +#include <FL/Fl_Menu_Item.H> #include "msg.h" #include "dialog.hh" #include "misc.h" #include "prefs.h" -using namespace fltk; +/* + * Local Data + */ +static int input_answer; +static char *input_str = NULL; +static int choice5_answer; + + +/* + * Local sub classes + */ +//---------------------------------------------------------------------------- /* - * Close dialog window. + * Used to enable CTRL+{a,e,d,k} in search dialog (for start,end,del,cut) + * TODO: bind down arrow to a search engine selection list. */ -static void window_close_cb(Widget *, void *vwin) +class CustInput3 : public Fl_Input { +public: + CustInput3 (int x, int y, int w, int h, const char* l=0) : + Fl_Input(x,y,w,h,l) {}; + int handle(int e); +}; + +int CustInput3::handle(int e) { - delete (Window*)vwin; + int k = Fl::event_key(); + + _MSG("CustInput3::handle event=%d\n", e); + + // We're only interested in some flags + unsigned modifier = Fl::event_state() & (FL_SHIFT | FL_CTRL | FL_ALT); + + if (e == FL_KEYBOARD && modifier == FL_CTRL) { + if (k == 'a' || k == 'e') { + position(k == 'a' ? 0 : size()); + return 1; + } else if (k == 'k') { + cut(position(), size()); + return 1; + } else if (k == 'd') { + cut(position(), position()+1); + return 1; + } + } + return Fl_Input::handle(e); } /* + * Used to make the ENTER key activate the CustChoice + */ +class CustChoice : public Fl_Choice { +public: + CustChoice (int x, int y, int w, int h, const char* l=0) : + Fl_Choice(x,y,w,h,l) {}; + int handle(int e) { + if (e == FL_KEYBOARD && + (Fl::event_key() == FL_Enter || Fl::event_key() == FL_Down) && + (Fl::event_state() & (FL_SHIFT|FL_CTRL|FL_ALT|FL_META)) == 0) { + return Fl_Choice::handle(FL_PUSH); + } + return Fl_Choice::handle(e); + }; +}; + +//---------------------------------------------------------------------------- + + +/* * Display a message in a popup window. */ void a_Dialog_msg(const char *msg) { - message("%s", msg); + fl_message("%s", msg); } + /* - * Offer a three choice dialog. - * The option string that begins with "*" is the default. - * - * Return: 0, 1 or 2 (esc = 2, window close = 2) + * Callback for a_Dialog_input() */ -int a_Dialog_choice3(const char *msg, - const char *b0, const char *b1, const char *b2) +static void input_cb(Fl_Widget *button, void *number) { - return choice(msg, b0, b1, b2); + input_answer = VOIDP2INT(number); + button->window()->hide(); } /* * Dialog for one line of Input with a message. + * avoids the sound bell in fl_input(), and allows customization + * + * Return value: string on success, NULL upon Cancel or Close window */ const char *a_Dialog_input(const char *msg) { - return input("%s", "", msg); + static Fl_Menu_Item *pm = 0; + int ww = 450, wh = 130, gap = 10, ih = 60, bw = 80, bh = 30; + + input_answer = 0; + + Fl_Window *window = new Fl_Window(ww,wh,"Ask"); + window->set_modal(); + window->begin(); + Fl_Group* ib = new Fl_Group(0,0,window->w(),window->h()); + ib->begin(); + window->resizable(ib); + + /* '?' Icon */ + Fl_Box* o = new Fl_Box(gap, gap, ih, ih); + o->box(FL_THIN_UP_BOX); + o->labelfont(FL_TIMES_BOLD); + o->labelsize(34); + o->color(FL_WHITE); + o->labelcolor(FL_BLUE); + o->label("?"); + o->show(); + + Fl_Box *box = new Fl_Box(ih+2*gap,gap,ww-(ih+3*gap),ih/2, msg); + box->labelfont(FL_HELVETICA); + box->labelsize(14); + box->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE|FL_ALIGN_CLIP|FL_ALIGN_WRAP); + + CustInput3 *c_inp = new CustInput3(ih+2*gap,gap+ih/2+gap,ww-(ih+3*gap),24); + c_inp->labelsize(14); + c_inp->textsize(14); + + CustChoice *ch = new CustChoice(1*gap,ih+3*gap,180,24); + if (!pm) { + int n_it = dList_length(prefs.search_urls); + pm = new Fl_Menu_Item[n_it+1]; + memset(pm, '\0', sizeof(Fl_Menu_Item[n_it+1])); + for (int i = 0, j = 0; i < n_it; i++) { + char *label, *url, *source; + source = (char *)dList_nth_data(prefs.search_urls, i); + if (!source || a_Misc_parse_search_url(source, &label, &url) < 0) + continue; + pm[j++].label(FL_NORMAL_LABEL, strdup(label)); + } + } + ch->tooltip("Select search engine"); + ch->menu(pm); + ch->value(prefs.search_url_idx); + ch->textcolor(FL_DARK_BLUE); + + int xpos = ww-2*(gap+bw), ypos = ih+3*gap; + Fl_Return_Button *rb = new Fl_Return_Button(xpos, ypos, bw, bh, "OK"); + rb->align(FL_ALIGN_INSIDE|FL_ALIGN_CLIP); + rb->box(FL_UP_BOX); + rb->callback(input_cb, INT2VOIDP(1)); + + xpos = ww-(gap+bw); + Fl_Button *b = new Fl_Button(xpos, ypos, bw, bh, "Cancel"); + b->align(FL_ALIGN_INSIDE|FL_ALIGN_CLIP); + b->box(FL_UP_BOX); + b->callback(input_cb, INT2VOIDP(2)); + + window->end(); + + window->show(); + while (window->shown()) + Fl::wait(); + if (input_answer == 1) { + /* we have a string, save it */ + dFree(input_str); + input_str = dStrdup(c_inp->value()); + prefs.search_url_idx = ch->value(); + } + delete window; + + return (input_answer == 1) ? input_str : NULL; } /* @@ -72,7 +206,7 @@ const char *a_Dialog_input(const char *msg) */ const char *a_Dialog_passwd(const char *msg) { - return password("%s", "", msg); + return fl_password("%s", "", msg); } /* @@ -83,7 +217,7 @@ const char *a_Dialog_passwd(const char *msg) const char *a_Dialog_save_file(const char *msg, const char *pattern, const char *fname) { - return file_chooser(msg, pattern, fname); + return fl_file_chooser(msg, pattern, fname); } /* @@ -101,7 +235,6 @@ const char *a_Dialog_select_file(const char *msg, return a_Dialog_save_file(msg, pattern, fname); } -//#include <fltk/FileIcon.h> /* * Show the open file dialog. * @@ -111,69 +244,66 @@ char *a_Dialog_open_file(const char *msg, const char *pattern, const char *fname) { const char *fc_name; -/* - static int icons_loaded = 0; - if (!icons_loaded) - FileIcon::load_system_icons(); -*/ - fc_name = file_chooser(msg, pattern, fname); + + fc_name = fl_file_chooser(msg, pattern, fname); return (fc_name) ? a_Misc_escape_chars(fc_name, "% ") : NULL; } /* + * Close text window. + */ +static void text_window_close_cb(Fl_Widget *, void *vtd) +{ + Fl_Text_Display *td = (Fl_Text_Display *)vtd; + Fl_Text_Buffer *buf = td->buffer(); + + delete (Fl_Window*)td->window(); + delete buf; +} + +/* * Show a new window with the provided text */ void a_Dialog_text_window(const char *txt, const char *title) { - //int wh = 600, ww = 650, bh = 30; int wh = prefs.height, ww = prefs.width, bh = 30; - int lines, line_num_width; - Font *textfont = font(prefs.font_monospace, 0); - Window *window = new Window(ww, wh, title ? title : "Untitled"); - window->callback(window_close_cb, window); - window->begin(); - - TextDisplay *td = new TextDisplay(0,0,ww, wh-bh); - td->buffer()->text(txt); + Fl_Window *window = new Fl_Window(ww, wh, title ? title : "Dillo text"); + Fl_Group::current(0); - if (textfont) - td->textfont(textfont); - td->textsize((int) rint(13.0 * prefs.font_factor)); - fltk::setfont(td->textfont(), td->textsize()); - lines = td->total_lines(); - line_num_width = 2; - while (lines /= 10) - ++line_num_width; - line_num_width = (int)(line_num_width * fltk::getwidth("0")); - td->linenumber_width(line_num_width); + Fl_Text_Buffer *buf = new Fl_Text_Buffer(); + buf->text(txt); + Fl_Text_Display *td = new Fl_Text_Display(0,0,ww, wh-bh); + td->buffer(buf); + td->textsize((int) rint(14.0 * prefs.font_factor)); /* enable wrapping lines; text uses entire width of window */ td->wrap_mode(true, false); - /* WORKAROUND: FLTK may not display all the lines without this */ - td->resize(ww+1,wh-bh); + window->add(td); - ReturnButton *b = new ReturnButton (0, wh-bh, ww, bh, "Close"); - b->callback(window_close_cb, window); + Fl_Return_Button *b = new Fl_Return_Button (0, wh-bh, ww, bh, "Close"); + b->callback(text_window_close_cb, td); + window->add(b); + window->callback(text_window_close_cb, td); window->resizable(td); - window->end(); window->show(); } /*--------------------------------------------------------------------------*/ -static int choice5_answer; -static void choice5_cb(Widget *button, void *number) +static void choice5_cb(Fl_Widget *button, void *number) { choice5_answer = VOIDP2INT(number); _MSG("choice5_cb: %d\n", choice5_answer); - button->window()->make_exec_return(true); + button->window()->hide(); } /* - * Make a question-dialog with a question and some alternatives. + * Make a question-dialog with a question and up to five alternatives. + * (if less alternatives, non used parameters must be NULL). + * * Return value: 0 = dialog was cancelled, 1-5 = selected alternative. */ int a_Dialog_choice5(const char *QuestionTxt, @@ -182,56 +312,72 @@ int a_Dialog_choice5(const char *QuestionTxt, { choice5_answer = 0; - int ww = 440, wh = 150, bw = 50, bh = 45, nb = 0; + int ww = 440, wh = 120, bw = 50, bh = 45, ih = 50, nb = 0; const char *txt[7]; txt[0] = txt[6] = NULL; txt[1] = alt1; txt[2] = alt2; txt[3] = alt3; txt[4] = alt4; txt[5] = alt5; - for (int i=1; txt[i]; ++i, ++nb) ; + for (int i=1; txt[i]; ++i, ++nb) + ; + + if (!nb) { + MSG_ERR("a_Dialog_choice5: No choices.\n"); + return choice5_answer; + } + ww = 140 + nb*(bw+10); - Window *window = new Window(ww,wh,"Choice5"); + Fl_Window *window = new Fl_Window(ww,wh,"Choice5"); + window->set_modal(); window->begin(); - Group* ib = new Group(0,0,window->w(),window->h()); + Fl_Group* ib = new Fl_Group(0,0,window->w(),window->h()); ib->begin(); window->resizable(ib); - Widget *box = new Widget(0,0,ww,wh-bh, QuestionTxt); - box->box(DOWN_BOX); - box->labelfont(HELVETICA_BOLD_ITALIC); + /* '?' Icon */ + Fl_Box* o = new Fl_Box(10, (wh-bh-ih)/2, ih, ih); + o->box(FL_THIN_UP_BOX); + o->labelfont(FL_TIMES_BOLD); + o->labelsize(34); + o->color(FL_WHITE); + o->labelcolor(FL_BLUE); + o->label("?"); + o->show(); + + Fl_Box *box = new Fl_Box(60,0,ww-60,wh-bh, QuestionTxt); + box->labelfont(FL_HELVETICA); box->labelsize(14); + box->align(FL_ALIGN_WRAP); - HighlightButton *b; + Fl_Button *b; int xpos = 0, gap = 8; bw = (ww - gap)/nb - gap; xpos += gap; for (int i=1; i <= nb; ++i) { - b = new HighlightButton(xpos, wh-bh, bw, bh, txt[i]); - b->align(ALIGN_WRAP|ALIGN_CLIP); - b->box(UP_BOX); + b = new Fl_Button(xpos, wh-bh, bw, bh, txt[i]); + b->align(FL_ALIGN_WRAP|FL_ALIGN_CLIP); + b->box(FL_UP_BOX); b->callback(choice5_cb, INT2VOIDP(i)); xpos += bw + gap; + /* TODO: set focus to the *-prefixed alternative */ } window->end(); - //window->hotspot(box); - window->exec(); + window->show(); + while (window->shown()) + Fl::wait(); + _MSG("a_Dialog_choice5 answer = %d\n", choice5_answer); delete window; - _MSG("Choice5 answer = %d\n", choice5_answer); return choice5_answer; } /*--------------------------------------------------------------------------*/ -/* - * ret: 0 = Cancel, 1 = OK - */ -static void Dialog_user_password_cb(Widget *button, void *vIntPtr) +static void Dialog_user_password_cb(Fl_Widget *button, void *) { - int ret = VOIDP2INT(vIntPtr); - _MSG("Dialog_user_password_cb: %d\n", ret); - button->window()->make_exec_return(ret); + button->window()->user_data(button); + button->window()->hide(); } /* @@ -241,52 +387,70 @@ static void Dialog_user_password_cb(Widget *button, void *vIntPtr) */ int a_Dialog_user_password(const char *message, UserPasswordCB cb, void *vp) { - int ok, - window_w = 300, window_h = 280, - input_x = 80, input_w = 200, input_h = 30, - button_y = 230, button_h = 30; + int ok = 0, window_h = 280, y, msg_w, msg_h; + const int window_w = 300, input_x = 80, input_w = 200, input_h = 30, + button_h = 30; - Window *window = - new Window(window_w,window_h,"User/Password"); - window->begin(); + /* window is resized below */ + Fl_Window *window = new Fl_Window(window_w,window_h,"Dillo User/Password"); + Fl_Group::current(0); + window->user_data(NULL); /* message */ - WordwrapOutput *message_output = - new WordwrapOutput(20,20,window_w-40,100); - message_output->box(DOWN_BOX); - message_output->text(message); - message_output->textfont(HELVETICA_BOLD_ITALIC); - message_output->textsize(14); + y = 20; + msg_w = window_w - 40; + Fl_Box *msg = new Fl_Box(20, y, msg_w, 100); /* resized below */ + msg->label(message); + msg->labelfont(FL_HELVETICA); + msg->labelsize(14); + msg->align(FL_ALIGN_INSIDE | FL_ALIGN_TOP_LEFT | FL_ALIGN_WRAP); + + fl_font(msg->labelfont(), msg->labelsize()); + msg_w -= 6; /* The label doesn't fill the entire box. */ + fl_measure(msg->label(), msg_w, msg_h, 0); /* fl_measure wraps at msg_w */ + msg->size(msg->w(), msg_h); + window->add(msg); /* inputs */ - Input *user_input = - new Input(input_x,140,input_w,input_h,"User"); + y += msg_h + 20; + Fl_Input *user_input = new Fl_Input(input_x, y, input_w, input_h, "User"); user_input->labelsize(14); user_input->textsize(14); - SecretInput *password_input = - new SecretInput(input_x,180,input_w,input_h,"Password"); + window->add(user_input); + y += input_h + 10; + Fl_Secret_Input *password_input = + new Fl_Secret_Input(input_x, y, input_w, input_h, "Password"); password_input->labelsize(14); password_input->textsize(14); + window->add(password_input); /* "OK" button */ - Button *ok_button = - new Button(200,button_y,50,button_h,"OK"); + y += input_h + 20; + Fl_Button *ok_button = new Fl_Button(200, y, 50, button_h, "OK"); ok_button->labelsize(14); ok_button->callback(Dialog_user_password_cb); - ok_button->user_data(INT2VOIDP(1)); + window->add(ok_button); /* "Cancel" button */ - Button *cancel_button = - new Button(50,button_y,100,button_h,"Cancel"); + Fl_Button *cancel_button = + new Fl_Button(50, y, 100, button_h, "Cancel"); cancel_button->labelsize(14); cancel_button->callback(Dialog_user_password_cb); - cancel_button->user_data(INT2VOIDP(0)); + window->add(cancel_button); - window->end(); - window->size_range(window_w,window_h,window_w,window_h); + y += button_h + 20; + window_h = y; + window->size(window_w, window_h); + window->size_range(window_w, window_h, window_w, window_h); window->resizable(window); - if ((ok = window->exec())) { + window->show(); + while (window->shown()) + Fl::wait(); + + ok = ((Fl_Widget *)window->user_data()) == ok_button ? 1 : 0; + + if (ok) { /* call the callback */ const char *user, *password; user = user_input->value(); @@ -294,7 +458,6 @@ int a_Dialog_user_password(const char *message, UserPasswordCB cb, void *vp) _MSG("a_Dialog_user_passwd: ok = %d\n", ok); (*cb)(user, password, vp); } - delete window; return ok; diff --git a/src/dialog.hh b/src/dialog.hh index 440e9bba..57b21849 100644 --- a/src/dialog.hh +++ b/src/dialog.hh @@ -9,8 +9,6 @@ typedef void (*UserPasswordCB)(const char *user, const char *password, void *vp); void a_Dialog_msg(const char *msg); -int a_Dialog_choice3(const char *msg, - const char *b0, const char *b1, const char *b2); int a_Dialog_choice5(const char *QuestionTxt, const char *alt1, const char *alt2, const char *alt3, const char *alt4, const char *alt5); diff --git a/src/dillo.cc b/src/dillo.cc index 3159674e..b05cb16a 100644 --- a/src/dillo.cc +++ b/src/dillo.cc @@ -24,10 +24,9 @@ #include <signal.h> #include <locale.h> -#include <fltk/Window.h> -#include <fltk/TabGroup.h> -#include <fltk/Font.h> -#include <fltk/run.h> +#include <FL/Fl.H> +#include <FL/Fl_Window.H> +#include <FL/fl_draw.H> #include "msg.h" #include "paths.hh" @@ -49,6 +48,8 @@ #include "cookies.h" #include "auth.h" +#include "dw/fltkcore.hh" + /* * Command line options structure */ @@ -171,11 +172,55 @@ static OptID getCmdOption(const CLI_options *options, int argc, char **argv, } /* + * Set FL_NORMAL_LABEL to interpret neither symbols (@) nor shortcuts (&), + * and FL_FREE_LABELTYPE to interpret shortcuts. + */ +static void custLabelDraw(const Fl_Label* o, int X, int Y, int W, int H, + Fl_Align align) +{ + const int interpret_symbols = 0; + + fl_draw_shortcut = 0; + fl_font(o->font, o->size); + fl_color((Fl_Color)o->color); + fl_draw(o->value, X, Y, W, H, align, o->image, interpret_symbols); +} + +static void custLabelMeasure(const Fl_Label* o, int& W, int& H) +{ + const int interpret_symbols = 0; + + fl_draw_shortcut = 0; + fl_font(o->font, o->size); + fl_measure(o->value, W, H, interpret_symbols); +} + +static void custMenuLabelDraw(const Fl_Label* o, int X, int Y, int W, int H, + Fl_Align align) +{ + const int interpret_symbols = 0; + + fl_draw_shortcut = 1; + fl_font(o->font, o->size); + fl_color((Fl_Color)o->color); + fl_draw(o->value, X, Y, W, H, align, o->image, interpret_symbols); +} + +static void custMenuLabelMeasure(const Fl_Label* o, int& W, int& H) +{ + const int interpret_symbols = 0; + + fl_draw_shortcut = 1; + fl_font(o->font, o->size); + fl_measure(o->value, W, H, interpret_symbols); +} + +/* * Tell the user if default/pref fonts can't be found. */ static void checkFont(const char *name, const char *type) { - if (::fltk::font(name) == NULL) + if (! dw::fltk::FltkFont::fontExists(name)) MSG_WARN("preferred %s font \"%s\" not found.\n", type, name); } @@ -318,22 +363,38 @@ int main(int argc, char **argv) } // Sets WM_CLASS hint on X11 - fltk::Window::xclass("dillo"); + Fl_Window::default_xclass("dillo"); + + Fl::scheme(prefs.theme); - // WORKAROUND: sometimes the default pager triggers redraw storms - fltk::TabGroup::default_pager(fltk::PAGER_SHRINK); + if (!prefs.show_tooltip) { + // turn off UI tooltips + Fl::option(Fl::OPTION_SHOW_TOOLTIPS, false); + } + + // Disable '@' and '&' interpretation in normal labels. + Fl::set_labeltype(FL_NORMAL_LABEL, custLabelDraw, custLabelMeasure); + + // Use to permit '&' interpretation. + Fl::set_labeltype(FL_FREE_LABELTYPE,custMenuLabelDraw,custMenuLabelMeasure); checkPreferredFonts(); + /* use preferred font for UI */ - fltk::Font *dfont = fltk::font(prefs.font_sans_serif, 0); - if (dfont) { - fltk::Widget::default_style->textfont(dfont); - fltk::Widget::default_style->labelfont(dfont); - } + Fl_Font defaultFont = dw::fltk::FltkFont::get (prefs.font_sans_serif, 0); + Fl::set_font(FL_HELVETICA, defaultFont); // this seems to be the + // only way to set the + // default font in fltk1.3 // Create a new UI/bw pair BrowserWindow *bw = a_UIcmd_browser_window_new(0, 0, xid, NULL); + /* We need this so that fl_text_extents() in dw/fltkplatform.cc can + * work when FLTK is configured without XFT and Dillo is opening + * immediately-available URLs from the cmdline (e.g. about:splash). + */ + ((Fl_Widget *)bw->ui)->window()->make_current(); + /* Proxy authentication */ if (prefs.http_proxyuser && !a_Http_proxy_auth()) { const char *passwd = a_UIcmd_get_passwd(prefs.http_proxyuser); @@ -349,7 +410,10 @@ int main(int argc, char **argv) if (idx == argc) { /* No URLs/files on cmdline. Send startup screen */ - a_UIcmd_open_url(bw, prefs.start_page); + if (strcmp(URL_STR(prefs.start_page), "about:blank") == 0) + a_UIcmd_open_url(bw, NULL); + else + a_UIcmd_open_url(bw, prefs.start_page); } else { for (int i = idx; i < argc; i++) { DilloUrl *start_url = makeStartUrl(argv[i], local); @@ -369,7 +433,7 @@ int main(int argc, char **argv) } } - fltk::run(); + Fl::run(); /* * Memory deallocating routines @@ -8,7 +8,7 @@ extern "C" { #endif /* __cplusplus */ -typedef void (*DnsCallback_t)(int Status, Dlist *addr_list, void *data); +typedef void (*DnsCallback_t)(int status, Dlist *addr_list, void *data); void a_Dns_init (void); void a_Dns_freeall(void); diff --git a/src/doctree.hh b/src/doctree.hh index ef7faa7c..85c1effd 100644 --- a/src/doctree.hh +++ b/src/doctree.hh @@ -6,6 +6,8 @@ class DoctreeNode { public: DoctreeNode *parent; + DoctreeNode *sibling; + DoctreeNode *lastChild; int num; // unique ascending id int element; lout::misc::SimpleVector<char*> *klass; @@ -14,11 +16,27 @@ class DoctreeNode { DoctreeNode () { parent = NULL; + sibling = NULL; + lastChild = NULL; klass = NULL; pseudo = NULL; id = NULL; element = 0; }; + + ~DoctreeNode () { + dFree ((void*) id); + while (lastChild) { + DoctreeNode *n = lastChild; + lastChild = lastChild->sibling; + delete n; + } + if (klass) { + for (int i = 0; i < klass->size (); i++) + dFree (klass->get(i)); + delete klass; + } + } }; /** @@ -26,46 +44,55 @@ class DoctreeNode { * * The Doctree class defines the interface to the parsed HTML document tree * as it is used for CSS selector matching. - * Currently the Doctree can be represented as stack, however to support - * CSS adjacent siblings or for future JavaScript support it may have to - * be extended to a real tree. */ class Doctree { private: DoctreeNode *topNode; + DoctreeNode *rootNode; int num; public: Doctree () { - topNode = NULL; + rootNode = new DoctreeNode; + topNode = rootNode; num = 0; }; - ~Doctree () { while (top ()) pop (); }; + + ~Doctree () { + delete rootNode; + }; + DoctreeNode *push () { DoctreeNode *dn = new DoctreeNode (); dn->parent = topNode; + dn->sibling = dn->parent->lastChild; + dn->parent->lastChild = dn; dn->num = num++; topNode = dn; return dn; }; + void pop () { - DoctreeNode *dn = topNode; - if (dn) { - dFree ((void*) dn->id); - if (dn->klass) { - for (int i = 0; i < dn->klass->size (); i++) - dFree (dn->klass->get(i)); - delete dn->klass; - } - topNode = dn->parent; - delete dn; - } + assert (topNode != rootNode); // never pop the root node + topNode = topNode->parent; }; + inline DoctreeNode *top () { - return topNode; + if (topNode != rootNode) + return topNode; + else + return NULL; }; + inline DoctreeNode *parent (const DoctreeNode *node) { - return node->parent; + if (node->parent != rootNode) + return node->parent; + else + return NULL; + }; + + inline DoctreeNode *sibling (const DoctreeNode *node) { + return node->sibling; }; }; diff --git a/src/findbar.cc b/src/findbar.cc index 8cca52ba..47363db0 100644 --- a/src/findbar.cc +++ b/src/findbar.cc @@ -9,8 +9,8 @@ * (at your option) any later version. */ -#include <fltk/events.h> -#include <fltk/Window.h> +#include <FL/Fl.H> +#include <FL/Fl_Window.H> #include "findbar.hh" #include "msg.h" @@ -18,49 +18,58 @@ #include "uicmd.hh" #include "bw.h" -using namespace fltk; - /* * Local sub class * (Used to handle escape in the findbar, may also avoid some shortcuts). */ -class MyInput : public Input { +class MyInput : public Fl_Input { public: MyInput (int x, int y, int w, int h, const char* l=0) : - Input(x,y,w,h,l) {}; + Fl_Input(x,y,w,h,l) {}; int handle(int e); }; int MyInput::handle(int e) { _MSG("findbar MyInput::handle()\n"); - int ret = 1, k = event_key(); - unsigned modifier = event_state() & (SHIFT | CTRL | ALT | META); - - if (e == KEY) { - if (k == LeftKey || k == RightKey) { - if (modifier == SHIFT) { - a_UIcmd_send_event_to_tabs_by_wid(e, this); + int ret = 1, k = Fl::event_key(); + unsigned modifier = Fl::event_state() & (FL_SHIFT| FL_CTRL| FL_ALT|FL_META); + + if (e == FL_KEYBOARD) { + if (modifier == FL_SHIFT) { + if (k == FL_Left || k == FL_Right) { + // Let these keys get to the UI + return 0; + } + } else if (modifier == FL_CTRL) { + if (k == 'a' || k == 'e') { + position(k == 'a' ? 0 : size()); + return 1; + } else if (k == 'k') { + cut(position(), size()); + return 1; + } else if (k == 'd') { + cut(position(), position()+1); return 1; } - } else if (k == EscapeKey && modifier == 0) { + } else if (k == FL_Escape && modifier == 0) { // Avoid clearing the text with Esc, just hide the findbar. return 0; } } if (ret) - ret = Input::handle(e); + ret = Fl_Input::handle(e); return ret; }; /* * Find next occurrence of input key */ -void Findbar::search_cb(Widget *, void *vfb) +void Findbar::search_cb(Fl_Widget *, void *vfb) { Findbar *fb = (Findbar *)vfb; - const char *key = fb->i->text(); + const char *key = fb->i->value(); bool case_sens = fb->check_btn->value(); if (key[0] != '\0') @@ -71,10 +80,10 @@ void Findbar::search_cb(Widget *, void *vfb) /* * Find previous occurrence of input key */ -void Findbar::searchBackwards_cb(Widget *, void *vfb) +void Findbar::searchBackwards_cb(Fl_Widget *, void *vfb) { Findbar *fb = (Findbar *)vfb; - const char *key = fb->i->text(); + const char *key = fb->i->value(); bool case_sens = fb->check_btn->value(); if (key[0] != '\0') { @@ -84,86 +93,74 @@ void Findbar::searchBackwards_cb(Widget *, void *vfb) } /* - * Find next occurrence of input key - */ -void Findbar::search_cb2(Widget *widget, void *vfb) -{ - /* - * Somehow fltk even regards the first loss of focus for the - * window as a WHEN_ENTER_KEY_ALWAYS event. - */ - if (event_key() == ReturnKey) - search_cb(widget, vfb); -} - -/* * Hide the search bar */ -void Findbar::hide_cb(Widget *, void *vfb) +void Findbar::hide_cb(Fl_Widget *, void *vfb) { - ((Findbar *)vfb)->hide(); + a_UIcmd_findbar_toggle(a_UIcmd_get_bw_by_widget(vfb), 0); } /* * Construct text search bar */ Findbar::Findbar(int width, int height) : - Group(0, 0, width, height) + Fl_Group(0, 0, width, height) { int button_width = 70; int gap = 2; int border = 2; int input_width = width - (2 * border + 4 * (button_width + gap)); - int x = border; + int x = 0; + + Fl_Group::current(0); + height -= 2 * border; - box(PLASTIC_UP_BOX); - Group::hide(); + box(FL_THIN_UP_BOX); - begin(); - hide_btn = new HighlightButton(x, border, 16, height, 0); - hideImg = new xpmImage(new_s_xpm); + hide_btn = new Fl_Button(x, border, 16, height, 0); + hideImg = new Fl_Pixmap(new_s_xpm); hide_btn->image(hideImg); x += 16 + gap; hide_btn->callback(hide_cb, this); - hide_btn->clear_tab_to_focus(); + hide_btn->clear_visible_focus(); + hide_btn->box(FL_THIN_UP_BOX); + hide_btn->tooltip("Hide"); + add(hide_btn); i = new MyInput(x, border, input_width, height); x += input_width + gap; resizable(i); i->color(206); - i->when(WHEN_ENTER_KEY_ALWAYS); - i->callback(search_cb2, this); - i->clear_tab_to_focus(); - i->set_click_to_focus(); + i->when(FL_WHEN_NEVER); + add(i); - next_btn = new HighlightButton(x, border, button_width, height, "Next"); + next_btn = new Fl_Button(x, border, button_width, height, "Next"); x += button_width + gap; - next_btn->add_shortcut(ReturnKey); - next_btn->add_shortcut(KeypadEnter); + next_btn->shortcut(FL_Enter); next_btn->callback(search_cb, this); - next_btn->clear_tab_to_focus(); + next_btn->clear_visible_focus(); + next_btn->box(FL_THIN_UP_BOX); + next_btn->tooltip("Find next occurrence of the search phrase\n" + "shortcut: Enter"); + add(next_btn); - prev_btn= new HighlightButton(x, border, button_width, height, "Previous"); - prev_btn->add_shortcut(SHIFT+ReturnKey); - prev_btn->callback(searchBackwards_cb, this); - prev_btn->clear_tab_to_focus(); + prev_btn= new Fl_Button(x, border, button_width, height, "Previous"); x += button_width + gap; + prev_btn->shortcut(FL_SHIFT+FL_Enter); + prev_btn->callback(searchBackwards_cb, this); + prev_btn->clear_visible_focus(); + prev_btn->box(FL_THIN_UP_BOX); + prev_btn->tooltip("Find previous occurrence of the search phrase\n" + "shortcut: Shift+Enter"); + add(prev_btn); - check_btn = new CheckButton(x, border, 2*button_width, height, + check_btn = new Fl_Check_Button(x, border, 2*button_width, height, "Case-sensitive"); - check_btn->clear_tab_to_focus(); x += 2 * button_width + gap; + check_btn->clear_visible_focus(); + add(check_btn); - end(); - - if (prefs.show_tooltip) { - hide_btn->tooltip("Hide"); - next_btn->tooltip("Find next occurrence of the search phrase\n" - "shortcut: Enter"); - prev_btn->tooltip("Find previous occurrence of the search phrase\n" - "shortcut: Shift+Enter"); - } } Findbar::~Findbar() @@ -172,23 +169,19 @@ Findbar::~Findbar() } /* - * Handle events. Used to catch EscapeKey events. + * Handle events. Used to catch FL_Escape events. */ int Findbar::handle(int event) { - int ret = 0; - int k = event_key(); - unsigned modifier = event_state() & (SHIFT | CTRL | ALT | META); + int k = Fl::event_key(); + unsigned modifier = Fl::event_state() & (FL_SHIFT| FL_CTRL| FL_ALT|FL_META); - if (event == KEY && modifier == 0 && k == EscapeKey) { - hide(); - ret = 1; + if (event == FL_KEYBOARD && modifier == 0 && k == FL_Escape) { + /* let the UI handle it */ + return 0; } - if (ret == 0) - ret = Group::handle(event); - - return ret; + return Fl_Group::handle(event); } /* @@ -196,21 +189,14 @@ int Findbar::handle(int event) */ void Findbar::show() { - Group::show(); + BrowserWindow *bw = a_UIcmd_get_bw_by_widget(this); + dReturn_if (bw == NULL); + + // It takes more than just calling show() to do the trick + Fl_Group::show(); + /* select text even if already focused */ i->take_focus(); i->position(i->size(), 0); } -/* - * Hide the findbar and reset the search state - */ -void Findbar::hide() -{ - BrowserWindow *bw; - - Group::hide(); - if ((bw = a_UIcmd_get_bw_by_widget(this))) - a_UIcmd_findtext_reset(bw); - a_UIcmd_focus_main_area(bw); -} diff --git a/src/findbar.hh b/src/findbar.hh index ba7ed8ed..72d24c44 100644 --- a/src/findbar.hh +++ b/src/findbar.hh @@ -1,35 +1,32 @@ #ifndef __FINDBAR_HH__ #define __FINDBAR_HH__ -#include <fltk/xpmImage.h> -#include <fltk/Widget.h> -#include <fltk/HighlightButton.h> -#include <fltk/Button.h> -#include <fltk/Input.h> -#include <fltk/Group.h> -#include <fltk/CheckButton.h> +#include <FL/Fl_Pixmap.H> +#include <FL/Fl_Widget.H> +#include <FL/Fl_Button.H> +#include <FL/Fl_Input.H> +#include <FL/Fl_Group.H> +#include <FL/Fl_Check_Button.H> /* * Searchbar to find text in page. */ -class Findbar : public fltk::Group { - fltk::Button *clrb; - fltk::HighlightButton *hide_btn, *next_btn, *prev_btn; - fltk::CheckButton *check_btn; - fltk::xpmImage *hideImg; - fltk::Input *i; +class Findbar : public Fl_Group { + Fl_Button *clrb; + Fl_Button *hide_btn, *next_btn, *prev_btn; + Fl_Check_Button *check_btn; + Fl_Pixmap *hideImg; + Fl_Input *i; - static void search_cb (fltk::Widget *, void *); - static void searchBackwards_cb (fltk::Widget *, void *); - static void search_cb2 (fltk::Widget *, void *); - static void hide_cb (fltk::Widget *, void *); + static void search_cb (Fl_Widget *, void *); + static void searchBackwards_cb (Fl_Widget *, void *); + static void hide_cb (Fl_Widget *, void *); public: Findbar(int width, int height); ~Findbar(); int handle(int event); void show(); - void hide(); }; #endif // __FINDBAR_HH__ diff --git a/src/form.cc b/src/form.cc index 18441fb8..f70bea8c 100644 --- a/src/form.cc +++ b/src/form.cc @@ -249,7 +249,9 @@ static void Html_add_input(DilloHtml *html, DilloHtmlInputType type, html->inputs_outside_form->increase(); html->inputs_outside_form->set(ni, input); - input->setEnabled(false); + if (html->bw->NumPendingStyleSheets > 0) { + input->setEnabled(false); + } } } @@ -609,7 +611,6 @@ void Html_tag_open_isindex(DilloHtml *html, const char *tag, int tagsize) /* * The textarea tag - * (TODO: It doesn't support wrapping). */ void Html_tag_open_textarea(DilloHtml *html, const char *tag, int tagsize) { @@ -850,7 +851,10 @@ void Html_tag_open_button(DilloHtml *html, const char *tag, int tagsize) Embed *embed; char *name, *value; - page = new Textblock (prefs.limit_text_width); + /* We used to have Textblock (prefs.limit_text_width) here, + * but it caused 100% CPU usage. + */ + page = new Textblock (false); page->setStyle (html->styleEngine->backgroundStyle ()); ResourceFactory *factory = HT2LT(html)->getResourceFactory(); @@ -677,7 +677,7 @@ static int Gif_decode(DilloGif *gif, const uchar_t *buf, size_t bsize) case 2: /* End code... consume remaining data chunks..? */ goto error; /* Could clean up better? */ default: - printf("dillo_gif_decode: error!\n"); + MSG("Gif_decode: error!\n"); goto error; } } @@ -810,8 +810,6 @@ static size_t Gif_do_img_desc(DilloGif *gif, void *Buf, return 0; } - gif->linebuf = dMalloc(gif->Width); - a_Dicache_set_parms(gif->url, gif->version, gif->Image, gif->Width, gif->Height, DILLO_IMG_TYPE_INDEXED); @@ -842,6 +840,7 @@ static size_t Gif_do_img_desc(DilloGif *gif, void *Buf, gif->y = 0; Gif_lwz_init(gif); gif->spill_line_index = 0; + gif->linebuf = dMalloc(gif->Width); gif->state = 3; /*Process the lzw data next */ if (gif->Image && gif->ColorMap_ofs) { a_Dicache_set_cmap(gif->url, gif->version, gif->Image, diff --git a/src/html.cc b/src/html.cc index bcefe14b..98fe7b8b 100644 --- a/src/html.cc +++ b/src/html.cc @@ -652,7 +652,7 @@ bool_t DilloHtml::unloadedImages() */ void DilloHtml::loadImages (const DilloUrl *pattern) { - dReturn_if_fail (bw->nav_expecting == FALSE); + dReturn_if (a_Bw_expecting(bw)); /* If the user asked for a specific URL, the user (NULL) is the requester, * but if the user just asked for all URLs, use the page URL as the @@ -693,12 +693,10 @@ bool DilloHtml::HtmlLinkReceiver::enter (Widget *widget, int link, int img, if (link == -1) { _MSG(" Link LEAVE notify...\n"); a_UIcmd_set_msg(bw, ""); - a_UIcmd_set_pointer_on_link(bw, FALSE); } else { _MSG(" Link ENTER notify...\n"); Html_set_link_coordinates(html, link, x, y); a_UIcmd_set_msg(bw, "%s", URL_STR(html->links->get(link))); - a_UIcmd_set_pointer_on_link(bw, TRUE); } return true; } @@ -1723,7 +1721,6 @@ static void Html_tag_close_style(DilloHtml *html, int TagIdx) static void Html_tag_open_body(DilloHtml *html, const char *tag, int tagsize) { const char *attrbuf; - Textblock *textblock; int32_t color; int tag_index_a = a_Html_tag_index ("a"); style::Color *bgColor; @@ -1741,8 +1738,6 @@ static void Html_tag_open_body(DilloHtml *html, const char *tag, int tagsize) BUG_MSG("unclosed HEAD element\n"); } - textblock = HT2TB(html); - if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "bgcolor"))) { color = a_Html_color_parse(html, attrbuf, -1); if (color != -1) @@ -2148,8 +2143,7 @@ static bool Html_load_image(BrowserWindow *bw, DilloUrl *url, DilloWeb *Web; int ClientKey; /* Fill a Web structure for the cache query */ - Web = a_Web_new(url, requester); - Web->bw = bw; + Web = a_Web_new(bw, url, requester); Web->Image = Image; a_Image_ref(Image); Web->flags |= WEB_Image; @@ -2170,7 +2164,6 @@ static void Html_tag_open_img(DilloHtml *html, const char *tag, int tagsize) { DilloImage *Image; DilloUrl *url, *usemap_url; - Textblock *textblock; const char *attrbuf; /* This avoids loading images. Useful for viewing suspicious HTML email. */ @@ -2181,8 +2174,6 @@ static void Html_tag_open_img(DilloHtml *html, const char *tag, int tagsize) !(url = a_Html_url_new(html, attrbuf, NULL, 0))) return; - textblock = HT2TB(html); - usemap_url = NULL; if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "usemap"))) /* TODO: usemap URLs outside of the document are not used. */ @@ -2259,12 +2250,11 @@ static void Html_tag_close_map(DilloHtml *html, int TagIdx) static misc::SimpleVector<int> *Html_read_coords(DilloHtml *html, const char *str) { - int i, coord; + int coord; const char *tail = str; char *newtail = NULL; misc::SimpleVector<int> *coords = new misc::SimpleVector<int> (4); - i = 0; while (1) { coord = strtol(tail, &newtail, 10); if (coord == 0 && newtail == tail) @@ -2461,12 +2451,14 @@ static void Html_tag_open_a(DilloHtml *html, const char *tag, int tagsize) html->InVisitedLink = true; html->styleEngine->setPseudoVisited (); if (html->non_css_visited_color != -1) - html->styleEngine->setNonCssHint(CSS_PROPERTY_COLOR, CSS_TYPE_COLOR, + html->styleEngine->setNonCssHint(CSS_PROPERTY_COLOR, + CSS_TYPE_COLOR, html->non_css_visited_color); } else { html->styleEngine->setPseudoLink (); if (html->non_css_link_color != -1) - html->styleEngine->setNonCssHint(CSS_PROPERTY_COLOR, CSS_TYPE_COLOR, + html->styleEngine->setNonCssHint(CSS_PROPERTY_COLOR, + CSS_TYPE_COLOR, html->non_css_link_color); } @@ -2744,9 +2736,11 @@ static void Html_tag_open_hr(DilloHtml *html, const char *tag, int tagsize) html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_LEFT_WIDTH, CSS_TYPE_LENGTH_PERCENTAGE, size_top); html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_BOTTOM_WIDTH, - CSS_TYPE_LENGTH_PERCENTAGE, size_bottom); + CSS_TYPE_LENGTH_PERCENTAGE, + size_bottom); html->styleEngine->setNonCssHint (CSS_PROPERTY_BORDER_RIGHT_WIDTH, - CSS_TYPE_LENGTH_PERCENTAGE, size_bottom); + CSS_TYPE_LENGTH_PERCENTAGE, + size_bottom); } HT2TB(html)->addParbreak (5, html->styleEngine->wordStyle ()); @@ -2850,6 +2844,7 @@ static void Html_tag_open_meta(DilloHtml *html, const char *tag, int tagsize) const char *p, *equiv, *content, *new_content; char delay_str[64], *mr_url; + DilloUrl *new_url; int delay; /* only valid inside HEAD */ @@ -2871,44 +2866,45 @@ static void Html_tag_open_meta(DilloHtml *html, const char *tag, int tagsize) } /* Skip to anything after "URL=" */ while (*content && *(content++) != '=') ; - if (*content) { - - /* Handle the case of a quoted URL */ - if (*content == '"' || *content == '\'') { - if ((p = strchr(content + 1, *content))) - mr_url = dStrndup(content + 1, p - content - 1); - else - mr_url = dStrdup(content + 1); - } else { - mr_url = dStrdup(content); - } - - if (delay == 0) { - /* zero-delay redirection */ - html->stop_parser = true; - DilloUrl *new_url = a_Url_new(mr_url, URL_STR(html->base_url)); - if (a_Capi_dpi_verify_request(html->bw, new_url)) - a_UIcmd_redirection0((void*)html->bw, new_url); - a_Url_free(new_url); - } else { - /* Send a custom HTML message. - * TODO: This is a hairy hack, - * It'd be much better to build a widget. */ - Dstr *ds_msg = dStr_sized_new(256); - dStr_sprintf(ds_msg, meta_template, mr_url, delay_str); - { - int o_InFlags = html->InFlags; - int o_TagSoup = html->TagSoup; - html->InFlags = IN_BODY; - html->TagSoup = false; - Html_write_raw(html, ds_msg->str, ds_msg->len, 0); - html->TagSoup = o_TagSoup; - html->InFlags = o_InFlags; - } - dStr_free(ds_msg, 1); + /* Handle the case of a quoted URL */ + if (*content == '"' || *content == '\'') { + if ((p = strchr(content + 1, *content))) + mr_url = dStrndup(content + 1, p - content - 1); + else + mr_url = dStrdup(content + 1); + } else { + mr_url = dStrdup(content); + } + new_url = a_Url_new(mr_url, URL_STR(html->base_url)); + + if (a_Url_cmp(html->base_url, new_url) == 0) { + /* redirection loop, or empty url string: ignore */ + BUG_MSG("META refresh: %s\n", + *mr_url ? "redirection loop" : "no target URL"); + } else if (delay == 0) { + /* zero-delay redirection */ + html->stop_parser = true; + if (a_Capi_dpi_verify_request(html->bw, new_url)) + a_UIcmd_redirection0((void*)html->bw, new_url); + } else { + /* Send a custom HTML message. + * TODO: This is a hairy hack, + * It'd be much better to build a widget. */ + Dstr *ds_msg = dStr_sized_new(256); + dStr_sprintf(ds_msg, meta_template, mr_url, delay_str); + { + int o_InFlags = html->InFlags; + int o_TagSoup = html->TagSoup; + html->InFlags = IN_BODY; + html->TagSoup = false; + Html_write_raw(html, ds_msg->str, ds_msg->len, 0); + html->TagSoup = o_TagSoup; + html->InFlags = o_InFlags; } - dFree(mr_url); + dStr_free(ds_msg, 1); } + a_Url_free(new_url); + dFree(mr_url); } else if (!dStrcasecmp(equiv, "content-type") && (content = a_Html_get_attr(html, tag, tagsize, "content"))) { @@ -2958,14 +2954,13 @@ void a_Html_load_stylesheet(DilloHtml *html, DilloUrl *url) if (endq && (endq - data <= 51)) { /* IANA limits charset names to 40 characters */ - const char *ignored; char *content_type; *endq = '\0'; content_type = dStrconcat("text/css; charset=", data+10, NULL); *endq = '"'; a_Capi_unref_buf(url); - ignored = a_Capi_set_content_type(url, content_type, "meta"); + a_Capi_set_content_type(url, content_type, "meta"); dFree(content_type); a_Capi_get_buf(url, &data, &len); } @@ -2976,8 +2971,7 @@ void a_Html_load_stylesheet(DilloHtml *html, DilloUrl *url) } else { /* Fill a Web structure for the cache query */ int ClientKey; - DilloWeb *Web = a_Web_new(url, html->page_url); - Web->bw = html->bw; + DilloWeb *Web = a_Web_new(html->bw, url, html->page_url); if ((ClientKey = a_Capi_open_url(Web, Html_css_load_callback, NULL))) { ++html->bw->NumPendingStyleSheets; a_Bw_add_client(html->bw, ClientKey, 0); @@ -3031,7 +3025,7 @@ static void Html_tag_open_link(DilloHtml *html, const char *tag, int tagsize) !(url = a_Html_url_new(html, attrbuf, NULL, 0))) return; - MSG(" Html_tag_open_link(): addCssUrl %s\n", URL_STR(url)); + _MSG(" Html_tag_open_link(): addCssUrl %s\n", URL_STR(url)); html->addCssUrl(url); a_Url_free(url); diff --git a/src/keys.cc b/src/keys.cc index 1a39f4c8..bd78fd5f 100644 --- a/src/keys.cc +++ b/src/keys.cc @@ -9,7 +9,7 @@ * (at your option) any later version. */ -#include <fltk/events.h> +#include <FL/Fl.H> #include <stdio.h> #include <stdlib.h> /* strtol */ #include <string.h> @@ -17,6 +17,7 @@ #include "dlib/dlib.h" #include "keys.hh" +#include "utf8.hh" #include "msg.h" /* @@ -38,80 +39,99 @@ typedef struct { * Local data */ static const Mapping_t keyNames[] = { - { "Backspace", fltk::BackSpaceKey }, - { "Delete", fltk::DeleteKey }, - { "Down", fltk::DownKey }, - { "End", fltk::EndKey }, - { "Esc", fltk::EscapeKey }, - { "F1", fltk::F1Key }, - { "F2", fltk::F2Key }, - { "F3", fltk::F3Key }, - { "F4", fltk::F4Key }, - { "F5", fltk::F5Key }, - { "F6", fltk::F6Key }, - { "F7", fltk::F7Key }, - { "F8", fltk::F8Key }, - { "F9", fltk::F9Key }, - { "F10", fltk::F10Key }, - { "F11", fltk::F11Key }, - { "F12", fltk::F12Key }, - { "Home", fltk::HomeKey }, - { "Insert", fltk::InsertKey }, - { "Left", fltk::LeftKey }, - { "PageDown", fltk::PageDownKey }, - { "PageUp", fltk::PageUpKey }, - { "Print", fltk::PrintKey }, - { "Return", fltk::ReturnKey }, - { "Right", fltk::RightKey }, - { "Space", fltk::SpaceKey }, - { "Tab", fltk::TabKey }, - { "Up", fltk::UpKey } + { "Backspace", FL_BackSpace }, + { "Delete", FL_Delete }, + { "Down", FL_Down }, + { "End", FL_End }, + { "Esc", FL_Escape }, + { "F1", FL_F + 1 }, + { "F2", FL_F + 2 }, + { "F3", FL_F + 3 }, + { "F4", FL_F + 4 }, + { "F5", FL_F + 5 }, + { "F6", FL_F + 6 }, + { "F7", FL_F + 7 }, + { "F8", FL_F + 8 }, + { "F9", FL_F + 9 }, + { "F10", FL_F + 10 }, + { "F11", FL_F + 11 }, + { "F12", FL_F + 12 }, + { "Home", FL_Home }, + { "Insert", FL_Insert }, + { "Left", FL_Left }, + { "PageDown", FL_Page_Down }, + { "PageUp", FL_Page_Up }, + { "Print", FL_Print }, + { "Return", FL_Enter }, + { "Right", FL_Right }, + { "Space", ' ' }, + { "Tab", FL_Tab }, + { "Up", FL_Up }, + /* multimedia keys */ + { "Back", FL_Back }, + { "Favorites", FL_Favorites }, + { "Forward", FL_Forward }, + { "HomePage", FL_Home_Page }, + { "Mail", FL_Mail }, + { "MediaNext", FL_Media_Next }, + { "MediaPlay", FL_Media_Play }, + { "MediaPrev", FL_Media_Prev }, + { "MediaStop", FL_Media_Stop }, + { "Refresh", FL_Refresh }, + { "Search", FL_Search }, + { "Sleep", FL_Sleep }, + { "Stop", FL_Stop }, + { "VolumeDown", FL_Volume_Down }, + { "VolumeMute", FL_Volume_Mute }, + { "VolumeUp", FL_Volume_Up }, }; static const Mapping_t modifierNames[] = { - { "Shift", fltk::SHIFT }, - { "Ctrl", fltk::CTRL }, - { "Alt", fltk::ALT }, - { "Meta", fltk::META }, - { "Button1", fltk::BUTTON1 }, - { "Button2", fltk::BUTTON2 }, - { "Button3", fltk::BUTTON3 } + { "Shift", FL_SHIFT }, + { "Ctrl", FL_CTRL }, + { "Alt", FL_ALT }, + { "Meta", FL_META }, + { "Button1", FL_BUTTON1 }, + { "Button2", FL_BUTTON2 }, + { "Button3", FL_BUTTON3 } }; static const KeyBinding_t default_keys[] = { - { "nop" , KEYS_NOP , 0 , 0 }, - { "open" , KEYS_OPEN , fltk::CTRL , 'o' }, - { "new-window" , KEYS_NEW_WINDOW , fltk::CTRL , 'n' }, - { "new-tab" , KEYS_NEW_TAB , fltk::CTRL , 't' }, - { "left-tab" , KEYS_LEFT_TAB , fltk::SHIFT , fltk::TabKey }, - { "right-tab" , KEYS_RIGHT_TAB , fltk::CTRL , fltk::TabKey }, - { "close-tab" , KEYS_CLOSE_TAB , fltk::CTRL , 'q' }, - { "find" , KEYS_FIND , fltk::CTRL , 'f' }, - { "websearch" , KEYS_WEBSEARCH , fltk::CTRL , 's' }, - { "bookmarks" , KEYS_BOOKMARKS , fltk::CTRL , 'b' }, - { "fullscreen" , KEYS_FULLSCREEN , fltk::CTRL , fltk::SpaceKey }, - { "reload" , KEYS_RELOAD , fltk::CTRL , 'r' }, - { "stop" , KEYS_STOP , 0 , 0 }, - { "save" , KEYS_SAVE , 0 , 0 }, - { "hide-panels" , KEYS_HIDE_PANELS , 0 , fltk::EscapeKey }, - { "file-menu" , KEYS_FILE_MENU , fltk::ALT , 'f' }, - { "close-all" , KEYS_CLOSE_ALL , fltk::ALT , 'q' }, - { "back" , KEYS_BACK , 0 , fltk::BackSpaceKey }, - { "back" , KEYS_BACK , 0 , ',' }, - { "forward" , KEYS_FORWARD , fltk::SHIFT , fltk::BackSpaceKey }, - { "forward" , KEYS_FORWARD , 0 , '.' }, - { "goto" , KEYS_GOTO , fltk::CTRL , 'l' }, - { "home" , KEYS_HOME , fltk::CTRL , 'h' }, - { "screen-up" , KEYS_SCREEN_UP , 0 , fltk::PageUpKey }, - { "screen-up" , KEYS_SCREEN_UP , 0 , 'b' }, - { "screen-down" , KEYS_SCREEN_DOWN , 0 , fltk::PageDownKey }, - { "screen-down" , KEYS_SCREEN_DOWN , 0 , fltk::SpaceKey }, - { "line-up" , KEYS_LINE_UP , 0 , fltk::UpKey }, - { "line-down" , KEYS_LINE_DOWN , 0 , fltk::DownKey }, - { "left" , KEYS_LEFT , 0 , fltk::LeftKey }, - { "right" , KEYS_RIGHT , 0 , fltk::RightKey }, - { "top" , KEYS_TOP , 0 , fltk::HomeKey }, - { "bottom" , KEYS_BOTTOM , 0 , fltk::EndKey }, + { "nop" , KEYS_NOP , 0 , 0 }, + { "open" , KEYS_OPEN , FL_CTRL , 'o' }, + { "new-window" , KEYS_NEW_WINDOW , FL_CTRL , 'n' }, + { "new-tab" , KEYS_NEW_TAB , FL_CTRL , 't' }, + { "left-tab" , KEYS_LEFT_TAB , FL_CTRL | + FL_SHIFT , FL_Tab }, + { "right-tab" , KEYS_RIGHT_TAB , FL_CTRL , FL_Tab }, + { "close-tab" , KEYS_CLOSE_TAB , FL_CTRL , 'w' }, + { "find" , KEYS_FIND , FL_CTRL , 'f' }, + { "websearch" , KEYS_WEBSEARCH , FL_CTRL , 's' }, + { "bookmarks" , KEYS_BOOKMARKS , FL_CTRL , 'b' }, + { "reload" , KEYS_RELOAD , FL_CTRL , 'r' }, + { "stop" , KEYS_STOP , 0 , 0 }, + { "save" , KEYS_SAVE , 0 , 0 }, + { "hide-panels" , KEYS_HIDE_PANELS , 0 , FL_Escape }, + { "file-menu" , KEYS_FILE_MENU , FL_ALT , 'f' }, + { "close-all" , KEYS_CLOSE_ALL , FL_CTRL , 'q' }, + { "back" , KEYS_BACK , 0 , FL_BackSpace }, + { "back" , KEYS_BACK , 0 , ',' }, + { "forward" , KEYS_FORWARD , FL_SHIFT , FL_BackSpace }, + { "forward" , KEYS_FORWARD , 0 , '.' }, + { "goto" , KEYS_GOTO , FL_CTRL , 'l' }, + { "home" , KEYS_HOME , FL_CTRL , 'h' }, + { "screen-up" , KEYS_SCREEN_UP , 0 , FL_Page_Up }, + { "screen-up" , KEYS_SCREEN_UP , 0 , 'b' }, + { "screen-down" , KEYS_SCREEN_DOWN , 0 , FL_Page_Down }, + { "screen-down" , KEYS_SCREEN_DOWN , 0 , ' ' }, + { "screen-left" , KEYS_SCREEN_LEFT , 0 , 0 }, + { "screen-right" , KEYS_SCREEN_RIGHT , 0 , 0 }, + { "line-up" , KEYS_LINE_UP , 0 , FL_Up }, + { "line-down" , KEYS_LINE_DOWN , 0 , FL_Down }, + { "left" , KEYS_LEFT , 0 , FL_Left }, + { "right" , KEYS_RIGHT , 0 , FL_Right }, + { "top" , KEYS_TOP , 0 , FL_Home }, + { "bottom" , KEYS_BOTTOM , 0 , FL_End }, }; static Dlist *bindings; @@ -172,20 +192,25 @@ KeysCommand_t Keys::getKeyCmd() { KeysCommand_t ret = KEYS_NOP; KeyBinding_t keyNode; - // We're only interested in some flags - keyNode.modifier = fltk::event_state() & - (fltk::SHIFT | fltk::CTRL | fltk::ALT | fltk::META); - - if (keyNode.modifier == fltk::SHIFT && - ispunct(fltk::event_text()[0])) { - // Get key code for a shifted character - keyNode.key = fltk::event_text()[0]; - keyNode.modifier = 0; + + keyNode.modifier = Fl::event_state() & (FL_SHIFT | FL_CTRL |FL_ALT|FL_META); + if (iscntrl(Fl::event_text()[0])) { + keyNode.key = Fl::event_key(); } else { - keyNode.key = fltk::event_key(); + const char *beyond = Fl::event_text() + Fl::event_length(); + keyNode.key = a_Utf8_decode(Fl::event_text(), beyond, NULL); + + /* BUG: The idea is to drop the modifiers if their use results in a + * different character (e.g., if shift-8 gives '*', drop the shift, + * but if ctrl-6 gives '6', keep the ctrl), but we have to compare a + * keysym with a Unicode codepoint, which only works for characters + * below U+0100 (those known to latin-1). + */ + if (keyNode.key != Fl::event_key()) + keyNode.modifier = 0; } - - _MSG("getKeyCmd: key=%d, mod=%d\n", keyNode.key, keyNode.modifier); + _MSG("getKeyCmd: evkey=0x%x evtext=\'%s\' key=0x%x, mod=0x%x\n", + Fl::event_key(), Fl::event_text(), keyNode.key, keyNode.modifier); void *data = dList_find_sorted(bindings, &keyNode, nodeByKeyCmp); if (data) ret = ((KeyBinding_t*)data)->cmd; @@ -311,8 +336,11 @@ void Keys::parseKey(char *key, char *commandName) // Get key code if (!key[1]) { keycode = *key; + } else if (a_Utf8_char_count(keystr, strlen(keystr)) == 1) { + const char *beyond = keystr + strlen(keystr); + keycode = a_Utf8_decode(keystr, beyond, NULL); } else if (key[0] == '0' && key[1] == 'x') { - /* keysym. For details on values reported, see fltk's fltk/events.h */ + /* keysym */ keycode = strtol(key, NULL, 0x10); } else if ((st = getKeyCode(keystr)) == -1) { MSG("Keys::parseKey unknown keyname: %s\n", keystr); diff --git a/src/keys.hh b/src/keys.hh index d234838c..d3a5d586 100644 --- a/src/keys.hh +++ b/src/keys.hh @@ -27,7 +27,6 @@ typedef enum { KEYS_FIND, KEYS_WEBSEARCH, KEYS_BOOKMARKS, - KEYS_FULLSCREEN, KEYS_RELOAD, KEYS_STOP, KEYS_SAVE, @@ -40,6 +39,8 @@ typedef enum { KEYS_HOME, KEYS_SCREEN_UP, KEYS_SCREEN_DOWN, + KEYS_SCREEN_LEFT, + KEYS_SCREEN_RIGHT, KEYS_LINE_UP, KEYS_LINE_DOWN, KEYS_LEFT, @@ -6,10 +6,16 @@ # The commented-out bindings below show the defaults built into Dillo. # # Modifiers recognized: "Shift", "Ctrl", "Alt", "Meta". +# (OS X: Use "Meta" for Command) +# # Key names recognized: "Backspace", "Delete", "Down", "End", "Esc", # "F1" through "F12", "Home", "Insert", "Left", "PageDown", "PageUp", # "Print", "Return", "Right", "Space", "Tab", "Up". # +# Multimedia keys: "Back", "Favorites", "Forward", "HomePage", "Mail", +# "MediaNext", "MediaPlay", "MediaPrev", "MediaStop", "Refresh", "Search", +# "Sleep", "Stop", "VolumeDown", "VolumeMute", VolumeUp". +# # If Dillo is running under X11, keys whose names are not recognized can # be specified using their keysym value in hexadecimal. Use xev to get # the keysym. Example rule: "0x1008ff27 = forward". @@ -27,14 +33,13 @@ # "close-tab" closes the current tab. # Note that this closes the browser window if there is only one tab. -#<ctrl>q = close-tab +#<ctrl>w = close-tab # "close-all" closes all tabs/windows and exits. -#<alt>q = close-all +#<ctrl>q = close-all # "left-tab" and "right-tab" switch to the left/right of the current tab. -# *** NOT HOOKED UP YET *** -# <shift>tab = left-tab +# <ctrl><shift>tab = left-tab # <ctrl>tab = right-tab # "back" and "forward" move back/forward through the browser history. @@ -52,7 +57,7 @@ # "find" lets you search for a text string on the current page. #<ctrl>f = find -# "hide-panels" hides the findbar. +# "hide-panels" hides the findbar if present, control panels if not. #esc = hide-panels # "websearch" lets you send a text string to the search engine that you @@ -62,9 +67,6 @@ # go to your "bookmarks". #<ctrl>b = bookmarks -# "fullscreen" hides/shows the panels at the top and bottom of a dillo window. -#<ctrl>space = fullscreen - # "file-menu" pops up the file menu. #<alt>f = file-menu @@ -87,6 +89,10 @@ #pagedown = screen-down #space = screen-down +#(screen-left has no default binding) + +#(screen-right has no default binding) + #up = line-up #down = line-down diff --git a/src/menu.cc b/src/menu.cc index d802bddb..658b89bc 100644 --- a/src/menu.cc +++ b/src/menu.cc @@ -11,11 +11,8 @@ // Functions/Methods for menus -#include <fltk/events.h> -#include <fltk/PopupMenu.h> -#include <fltk/Item.h> -#include <fltk/ToggleItem.h> -#include <fltk/Divider.h> +#include <FL/Fl.H> +#include <FL/Fl_Menu_Item.H> #include "lout/misc.hh" /* SimpleVector */ #include "msg.h" @@ -27,8 +24,6 @@ #include "keys.hh" #include "timeout.hh" -using namespace fltk; - /* * Local data */ @@ -38,54 +33,27 @@ using namespace fltk; static DilloUrl *popup_url = NULL; // Weak reference to the popup's bw static BrowserWindow *popup_bw = NULL; -// Where to place the filemenu popup +static void *popup_form = NULL; +// Where to place the popup static int popup_x, popup_y; // History popup direction (-1 = back, 1 = forward). static int history_direction = -1; // History popup, list of URL-indexes. static int *history_list = NULL; -/* - * Local sub class. - * Used to add the hint for history popup menus, and to remember - * the mouse button pressed over a menu item. - */ -class CustItem : public Item { - int EventButton; -public: - CustItem (const char* label) : Item(label) { EventButton = 0; }; - int button () { return EventButton; }; - void draw(); - int handle(int e) { - EventButton = event_button(); - return Item::handle(e); - } -}; - -/* - * This adds a call to a_UIcmd_set_msg() to show the URL in the status bar - * TODO: erase the URL on popup close. - */ -void CustItem::draw() { - const DilloUrl *url; - if (flags() & SELECTED) { - url = a_History_get_url(history_list[(VOIDP2INT(user_data()))-1]); - a_UIcmd_set_msg(popup_bw, "%s", URL_STR(url)); - } - Item::draw(); +//-------------------------------------------------------------------------- +static void Menu_nop_cb(Fl_Widget*, void*) +{ } - -//-------------------------------------------------------------------------- /* * Static function for File menu callbacks. */ -static void filemenu_cb(Widget *wid, void *data) +static void filemenu_cb(Fl_Widget*, void *data) { if (strcmp((char*)data, "nw") == 0) { - UI *ui = (UI*)popup_bw->ui; - a_UIcmd_browser_window_new(ui->w(), ui->h(), 0, popup_bw); + a_UIcmd_open_url_nw(popup_bw, NULL); } else if (strcmp((char*)data, "nt") == 0) { a_UIcmd_open_url_nt(popup_bw, NULL, 1); } else if (strcmp((char*)data, "of") == 0) { @@ -100,13 +68,13 @@ static void filemenu_cb(Widget *wid, void *data) } -static void Menu_copy_urlstr_cb(Widget *) +static void Menu_copy_urlstr_cb(Fl_Widget*, void*) { if (popup_url) a_UIcmd_copy_urlstr(popup_bw, URL_STR(popup_url)); } -static void Menu_link_cb(Widget*, void *user_data) +static void Menu_link_cb(Fl_Widget*, void *user_data) { DilloUrl *url = (DilloUrl *) user_data ; _MSG("Menu_link_cb: click! :-)\n"); @@ -118,7 +86,7 @@ static void Menu_link_cb(Widget*, void *user_data) /* * Open URL */ -static void Menu_open_url_cb(Widget* ) +static void Menu_open_url_cb(Fl_Widget*, void*) { _MSG("Open URL cb: click! :-)\n"); a_UIcmd_open_url(popup_bw, popup_url); @@ -127,7 +95,7 @@ static void Menu_open_url_cb(Widget* ) /* * Open URL in new window */ -static void Menu_open_url_nw_cb(Widget* ) +static void Menu_open_url_nw_cb(Fl_Widget*, void*) { _MSG("Open URL in new window cb: click! :-)\n"); a_UIcmd_open_url_nw(popup_bw, popup_url); @@ -136,17 +104,17 @@ static void Menu_open_url_nw_cb(Widget* ) /* * Open URL in new Tab */ -static void Menu_open_url_nt_cb(Widget* ) +static void Menu_open_url_nt_cb(Fl_Widget*, void*) { int focus = prefs.focus_new_tab ? 1 : 0; - if (event_state(SHIFT)) focus = !focus; + if (Fl::event_state(FL_SHIFT)) focus = !focus; a_UIcmd_open_url_nt(popup_bw, popup_url, focus); } /* * Add bookmark */ -static void Menu_add_bookmark_cb(Widget* ) +static void Menu_add_bookmark_cb(Fl_Widget*, void*) { a_UIcmd_add_bookmark(popup_bw, popup_url); } @@ -154,15 +122,15 @@ static void Menu_add_bookmark_cb(Widget* ) /* * Find text */ -static void Menu_find_text_cb(Widget* ) +static void Menu_find_text_cb(Fl_Widget*, void*) { - ((UI *)popup_bw->ui)->set_findbar_visibility(1); + ((UI *)popup_bw->ui)->findbar_toggle(1); } /* * Save link */ -static void Menu_save_link_cb(Widget* ) +static void Menu_save_link_cb(Fl_Widget*, void*) { a_UIcmd_save_link(popup_bw, popup_url); } @@ -170,7 +138,7 @@ static void Menu_save_link_cb(Widget* ) /* * Save current page */ -static void Menu_save_page_cb(Widget* ) +static void Menu_save_page_cb(Fl_Widget*, void*) { a_UIcmd_save(popup_bw); } @@ -178,7 +146,7 @@ static void Menu_save_page_cb(Widget* ) /* * View current page source */ -static void Menu_view_page_source_cb(Widget* ) +static void Menu_view_page_source_cb(Fl_Widget*, void*) { a_UIcmd_view_page_source(popup_bw, popup_url); } @@ -186,7 +154,7 @@ static void Menu_view_page_source_cb(Widget* ) /* * View current page's bugs */ -static void Menu_view_page_bugs_cb(Widget* ) +static void Menu_view_page_bugs_cb(Fl_Widget*, void*) { a_UIcmd_view_page_bugs(popup_bw); } @@ -194,7 +162,7 @@ static void Menu_view_page_bugs_cb(Widget* ) /* * Load images on current page that match URL pattern */ -static void Menu_load_images_cb(Widget*, void *user_data) +static void Menu_load_images_cb(Fl_Widget*, void *user_data) { DilloUrl *page_url = (DilloUrl *) user_data; void *doc = a_Bw_get_url_doc(popup_bw, page_url); @@ -206,39 +174,38 @@ static void Menu_load_images_cb(Widget*, void *user_data) /* * Submit form */ -static void Menu_form_submit_cb(Widget*, void *v_form) +static void Menu_form_submit_cb(Fl_Widget*, void*) { void *doc = a_Bw_get_url_doc(popup_bw, popup_url); if (doc) - a_Html_form_submit(doc, v_form); + a_Html_form_submit(doc, popup_form); } /* * Reset form */ -static void Menu_form_reset_cb(Widget*, void *v_form) +static void Menu_form_reset_cb(Fl_Widget*, void*) { void *doc = a_Bw_get_url_doc(popup_bw, popup_url); if (doc) - a_Html_form_reset(doc, v_form); + a_Html_form_reset(doc, popup_form); } /* * Toggle display of 'hidden' form controls. */ -static void Menu_form_hiddens_cb(Widget *w, void *user_data) +static void Menu_form_hiddens_cb(Fl_Widget*, void *user_data) { - void *v_form = w->parent()->user_data(); bool visible = *((bool *) user_data); void *doc = a_Bw_get_url_doc(popup_bw, popup_url); if (doc) - a_Html_form_display_hiddens(doc, v_form, !visible); + a_Html_form_display_hiddens(doc, popup_form, !visible); } -static void Menu_stylesheet_cb(Widget *w, void *vUrl) +static void Menu_stylesheet_cb(Fl_Widget*, void *vUrl) { const DilloUrl *url = (const DilloUrl *) vUrl; a_UIcmd_open_url(popup_bw, url); @@ -247,7 +214,7 @@ static void Menu_stylesheet_cb(Widget *w, void *vUrl) /* * Validate URL with the W3C */ -static void Menu_bugmeter_validate_w3c_cb(Widget* ) +static void Menu_bugmeter_validate_w3c_cb(Fl_Widget*, void*) { Dstr *dstr = dStr_sized_new(128); @@ -260,7 +227,7 @@ static void Menu_bugmeter_validate_w3c_cb(Widget* ) /* * Validate URL with the WDG */ -static void Menu_bugmeter_validate_wdg_cb(Widget* ) +static void Menu_bugmeter_validate_wdg_cb(Fl_Widget*, void*) { Dstr *dstr = dStr_sized_new(128); @@ -274,7 +241,7 @@ static void Menu_bugmeter_validate_wdg_cb(Widget* ) /* * Show info page for the bug meter */ -static void Menu_bugmeter_about_cb(Widget* ) +static void Menu_bugmeter_about_cb(Fl_Widget*, void*) { a_UIcmd_open_urlstr(popup_bw, "http://www.dillo.org/help/bug_meter.html"); } @@ -283,23 +250,23 @@ static void Menu_bugmeter_about_cb(Widget* ) * Navigation History callback. * Go to selected URL. */ -static void Menu_history_cb(Widget *wid, void *data) +static void Menu_history_cb(Fl_Widget*, void *data) { - int mb = ((CustItem*)wid)->button(); + int mb = Fl::event_button(); int offset = history_direction * VOIDP2INT(data); const DilloUrl *url = a_History_get_url(history_list[VOIDP2INT(data)-1]); - if (mb == 2) { + if (mb == 1) { + a_UIcmd_nav_jump(popup_bw, offset, 0); + } else if (mb == 2) { // Middle button, open in a new window/tab if (prefs.middle_click_opens_new_tab) { int focus = prefs.focus_new_tab ? 1 : 0; - if (event_state(SHIFT)) focus = !focus; + if (Fl::event_state(FL_SHIFT)) focus = !focus; a_UIcmd_open_url_nt(popup_bw, url, focus); } else { a_UIcmd_open_url_nw(popup_bw, url); } - } else { - a_UIcmd_nav_jump(popup_bw, offset, 0); } } @@ -311,18 +278,10 @@ static void Menu_history_cb(Widget *wid, void *data) */ static void Menu_popup_cb(void *data) { - ((PopupMenu *)data)->popup(); - a_Timeout_remove(); -} + const Fl_Menu_Item *m = ((Fl_Menu_Item *)data)->popup(popup_x, popup_y); -/* - * Same as above but with coordinates. - */ -static void Menu_popup_cb2(void *data) -{ - Menu *m = (Menu *)data; - m->value(-1); - m->popup(Rectangle(popup_x,popup_y,m->w(),m->h()), m->label()); + if (m && m->callback()) + m->do_callback((Fl_Widget *)data); a_Timeout_remove(); } @@ -334,65 +293,49 @@ void a_Menu_page_popup(BrowserWindow *bw, const DilloUrl *url, { lout::misc::SimpleVector <DilloUrl*> *cssUrls = (lout::misc::SimpleVector <DilloUrl*> *) v_cssUrls; - Item *i; - int j; - // One menu for every browser window - static PopupMenu *pm = 0; - // Active/inactive control. - static Item *view_page_bugs_item = 0, *view_source_item = 0; - static ItemGroup *stylesheets = 0; - + int j = 0; + + static Fl_Menu_Item *stylesheets = NULL; + static Fl_Menu_Item pm[] = { + {"View page source", 0, Menu_view_page_source_cb,0,0,0,0,0,0}, + {"View page bugs", 0, Menu_view_page_bugs_cb,0,0,0,0,0,0}, + {"View stylesheets", 0, Menu_nop_cb,0,FL_SUBMENU_POINTER|FL_MENU_DIVIDER, + 0,0,0,0}, + {"Bookmark this page", 0,Menu_add_bookmark_cb,0,FL_MENU_DIVIDER,0,0,0,0}, + {"Find text", 0, Menu_find_text_cb,0,0,0,0,0,0}, + {"Save page as...", 0, Menu_save_page_cb,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0} + }; + + popup_x = Fl::event_x(); + popup_y = Fl::event_y(); popup_bw = bw; a_Url_free(popup_url); popup_url = a_Url_dup(url); - if (!pm) { - pm = new PopupMenu(0,0,0,0,"&PAGE OPTIONS"); - pm->begin(); - i = view_source_item = new Item("View page Source"); - i->callback(Menu_view_page_source_cb); - i = view_page_bugs_item = new Item("View page Bugs"); - i->callback(Menu_view_page_bugs_cb); - stylesheets = new ItemGroup("View Stylesheets"); - new Divider(); - i = new Item("Bookmark this page"); - i->callback(Menu_add_bookmark_cb); - new Divider(); - i = new Item("Find Text"); - i->callback(Menu_find_text_cb); - //i->shortcut(CTRL+'f'); - i = new Item("Jump to..."); - i->deactivate(); - new Divider(); - i = new Item("Save page As..."); - i->callback(Menu_save_page_cb); - - pm->type(PopupMenu::POPUP123); - pm->end(); - } - - if (has_bugs == TRUE) - view_page_bugs_item->activate(); - else - view_page_bugs_item->deactivate(); + has_bugs == TRUE ? pm[1].activate() : pm[1].deactivate(); if (strncmp(URL_STR(url), "dpi:/vsource/", 13) == 0) - view_source_item->deactivate(); + pm[0].deactivate(); else - view_source_item->activate(); - - int n = stylesheets->children(); - for (j = 0; j < n; j++) { - /* get rid of the old ones */ - Widget *child = stylesheets->child(0); - dFree((char *)child->label()); - a_Url_free((DilloUrl *)child->user_data()); - delete child; + pm[0].activate(); + + if (stylesheets) { + while (stylesheets[j].text) { + dFree((char *) stylesheets[j].label()); + a_Url_free((DilloUrl *) stylesheets[j].user_data()); + j++; + } + delete [] stylesheets; + stylesheets = NULL; } if (cssUrls && cssUrls->size () > 0) { - stylesheets->activate(); + stylesheets = new Fl_Menu_Item[cssUrls->size() + 1]; + memset(stylesheets, '\0', sizeof(Fl_Menu_Item[cssUrls->size() + 1])); + for (j = 0; j < cssUrls->size(); j++) { + /* may want ability to Load individual unloaded stylesheets as well */ const char *action = "View "; DilloUrl *url = cssUrls->get(j); @@ -411,17 +354,17 @@ void a_Menu_page_popup(BrowserWindow *bw, const DilloUrl *url, label = dStrconcat(action, url_str, NULL); } - i = new Item(label); - i->set_flag(RAW_LABEL); - i->user_data(a_Url_dup(url)); - i->callback(Menu_stylesheet_cb); - stylesheets->add(i); + stylesheets[j].label(FL_NORMAL_LABEL, label); + stylesheets[j].callback(Menu_stylesheet_cb, a_Url_dup(url)); } + + pm[2].user_data(stylesheets); + pm[2].activate(); } else { - stylesheets->deactivate(); + pm[2].deactivate(); } - a_Timeout_add(0.0, Menu_popup_cb, (void *)pm); + a_Timeout_add(0.0, Menu_popup_cb, (void*)pm); } /* @@ -429,35 +372,23 @@ void a_Menu_page_popup(BrowserWindow *bw, const DilloUrl *url, */ void a_Menu_link_popup(BrowserWindow *bw, const DilloUrl *url) { - // One menu for every browser window - static PopupMenu *pm = 0; - + static Fl_Menu_Item pm[] = { + {"Open link in new tab", 0, Menu_open_url_nt_cb,0,0,0,0,0,0}, + {"Open link in new window", 0, Menu_open_url_nw_cb,0,FL_MENU_DIVIDER,0,0, + 0,0}, + {"Bookmark this link", 0, Menu_add_bookmark_cb,0,0,0,0,0,0}, + {"Copy link location", 0, Menu_copy_urlstr_cb,0,FL_MENU_DIVIDER,0,0,0,0}, + {"Save link as...", 0, Menu_save_link_cb,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0} + }; + + popup_x = Fl::event_x(); + popup_y = Fl::event_y(); popup_bw = bw; a_Url_free(popup_url); popup_url = a_Url_dup(url); - if (!pm) { - Item *i; - pm = new PopupMenu(0,0,0,0,"&LINK OPTIONS"); - //pm->callback(Menu_link_cb, url); - pm->begin(); - i = new Item("Open Link in New Window"); - i->callback(Menu_open_url_nw_cb); - i = new Item("Open Link in New Tab"); - i->callback(Menu_open_url_nt_cb); - new Divider(); - i = new Item("Bookmark this Link"); - i->callback(Menu_add_bookmark_cb); - i = new Item("Copy Link location"); - i->callback(Menu_copy_urlstr_cb); - new Divider(); - i = new Item("Save Link As..."); - i->callback(Menu_save_link_cb); - - pm->type(PopupMenu::POPUP123); - pm->end(); - } - a_Timeout_add(0.0, Menu_popup_cb, (void *)pm); + a_Timeout_add(0.0, Menu_popup_cb, (void*)pm); } /* @@ -467,14 +398,23 @@ void a_Menu_image_popup(BrowserWindow *bw, const DilloUrl *url, bool_t loaded_img, DilloUrl *page_url, DilloUrl *link_url) { - // One menu for every browser window - static PopupMenu *pm = 0; - // Active/inactive control. - static Item *link_menuitem = 0; - static Item *load_img_menuitem = 0; static DilloUrl *popup_page_url = NULL; static DilloUrl *popup_link_url = NULL; - + static Fl_Menu_Item pm[] = { + {"Isolate image", 0, Menu_open_url_cb,0,0,0,0,0,0}, + {"Open image in new tab", 0, Menu_open_url_nt_cb,0,0,0,0,0,0}, + {"Open image in new window", 0, Menu_open_url_nw_cb, 0, FL_MENU_DIVIDER, + 0,0,0,0}, + {"Load image", 0, Menu_load_images_cb,0,0,0,0,0,0}, + {"Bookmark this image", 0, Menu_add_bookmark_cb,0,0,0,0,0,0}, + {"Copy image location", 0,Menu_copy_urlstr_cb,0,FL_MENU_DIVIDER,0,0,0,0}, + {"Save image as...", 0, Menu_save_link_cb, 0, FL_MENU_DIVIDER,0,0,0,0}, + {"Link menu", 0, Menu_link_cb,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0} + }; + + popup_x = Fl::event_x(); + popup_y = Fl::event_y(); popup_bw = bw; a_Url_free(popup_url); popup_url = a_Url_dup(url); @@ -483,49 +423,22 @@ void a_Menu_image_popup(BrowserWindow *bw, const DilloUrl *url, a_Url_free(popup_link_url); popup_link_url = a_Url_dup(link_url); - if (!pm) { - Item *i; - pm = new PopupMenu(0,0,0,0,"&IMAGE OPTIONS"); - pm->begin(); - i = new Item("Isolate Image"); - i->callback(Menu_open_url_cb); - i = new Item("Open Image in New Window"); - i->callback(Menu_open_url_nw_cb); - i = new Item("Open Image in New Tab"); - i->callback(Menu_open_url_nt_cb); - new Divider(); - i = load_img_menuitem = new Item("Load image"); - i->callback(Menu_load_images_cb); - i = new Item("Bookmark this Image"); - i->callback(Menu_add_bookmark_cb); - i = new Item("Copy Image location"); - i->callback(Menu_copy_urlstr_cb); - new Divider(); - i = new Item("Save Image As..."); - i->callback(Menu_save_link_cb); - new Divider(); - i = link_menuitem = new Item("Link menu"); - i->callback(Menu_link_cb); - - pm->type(PopupMenu::POPUP123); - pm->end(); - } if (loaded_img) { - load_img_menuitem->deactivate(); + pm[3].deactivate(); } else { - load_img_menuitem->activate(); - load_img_menuitem->user_data(popup_page_url); + pm[3].activate(); + pm[3].user_data(popup_page_url); } if (link_url) { - link_menuitem->user_data(popup_link_url); - link_menuitem->activate(); + pm[7].activate(); + pm[7].user_data(popup_link_url); } else { - link_menuitem->deactivate(); + pm[7].deactivate(); } - a_Timeout_add(0.0, Menu_popup_cb, (void *)pm); + a_Timeout_add(0.0, Menu_popup_cb, (void*)pm); } /* @@ -534,31 +447,25 @@ void a_Menu_image_popup(BrowserWindow *bw, const DilloUrl *url, void a_Menu_form_popup(BrowserWindow *bw, const DilloUrl *page_url, void *formptr, bool_t hidvis) { - static PopupMenu *pm = 0; - static Item *hiddens_item = 0; static bool hiddens_visible; - + static Fl_Menu_Item pm[] = { + {"Submit form", 0, Menu_form_submit_cb,0,0,0,0,0,0}, + {"Reset form", 0, Menu_form_reset_cb,0,0,0,0,0,0}, + {0, 0, Menu_form_hiddens_cb, &hiddens_visible, 0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0} + }; + + popup_x = Fl::event_x(); + popup_y = Fl::event_y(); popup_bw = bw; a_Url_free(popup_url); popup_url = a_Url_dup(page_url); - if (!pm) { - Item *i; - pm = new PopupMenu(0,0,0,0,"FORM OPTIONS"); - pm->add(i = new Item("Submit form")); - i->callback(Menu_form_submit_cb); - pm->add(i = new Item("Reset form")); - i->callback(Menu_form_reset_cb); - pm->add(hiddens_item = new Item("")); - hiddens_item->callback(Menu_form_hiddens_cb); - hiddens_item->user_data(&hiddens_visible); - pm->type(PopupMenu::POPUP123); - } - pm->user_data(formptr); + popup_form = formptr; hiddens_visible = hidvis; - hiddens_item->label(hiddens_visible ? "Hide hiddens": "Show hiddens"); + pm[2].label(hiddens_visible ? "Hide hiddens": "Show hiddens"); - a_Timeout_add(0.0, Menu_popup_cb, (void *)pm); + a_Timeout_add(0.0, Menu_popup_cb, (void*)pm); } /* @@ -566,44 +473,32 @@ void a_Menu_form_popup(BrowserWindow *bw, const DilloUrl *page_url, */ void a_Menu_file_popup(BrowserWindow *bw, void *v_wid) { - UI *ui = (UI *)bw->ui; - Widget *wid = (Widget*)v_wid; - // One menu for every browser window - static PopupMenu *pm = 0; + Fl_Widget *wid = (Fl_Widget*)v_wid; + + static Fl_Menu_Item pm[] = { + {"New tab", Keys::getShortcut(KEYS_NEW_TAB), filemenu_cb, + (void*)"nt",0,0,0,0,0}, + {"New window", Keys::getShortcut(KEYS_NEW_WINDOW), filemenu_cb, + (void*)"nw", FL_MENU_DIVIDER,0,0,0,0}, + {"Open file...", Keys::getShortcut(KEYS_OPEN), filemenu_cb, + (void*)"of",0,0,0,0,0}, + {"Open URL...", Keys::getShortcut(KEYS_GOTO), filemenu_cb, + (void*)"ou",0,0,0,0,0}, + {"Close", Keys::getShortcut(KEYS_CLOSE_TAB), filemenu_cb, + (void*)"cw", FL_MENU_DIVIDER,0,0,0,0}, + {"Exit Dillo", Keys::getShortcut(KEYS_CLOSE_ALL), filemenu_cb, + (void*)"ed",0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0} + }; popup_bw = bw; popup_x = wid->x(); - popup_y = wid->y() + wid->h() + - // WORKAROUND: ?? wid->y() doesn't count tabs ?? - (((Group*)ui->tabs())->children() > 1 ? 20 : 0); + popup_y = wid->y() + wid->h(); a_Url_free(popup_url); popup_url = NULL; - if (!pm) { - int shortcut; - Item *i; - pm = new PopupMenu(0,0,0,0,"File"); - pm->begin(); - shortcut = Keys::getShortcut(KEYS_NEW_WINDOW); - i = new Item("New Window", shortcut, filemenu_cb, (void*)"nw"); - shortcut = Keys::getShortcut(KEYS_NEW_TAB); - i = new Item("New Tab", shortcut, filemenu_cb, (void*)"nt"); - new Divider(); - shortcut = Keys::getShortcut(KEYS_OPEN); - i = new Item("Open File...", shortcut, filemenu_cb, (void*)"of"); - shortcut = Keys::getShortcut(KEYS_GOTO); - i = new Item("Open URL...", shortcut, filemenu_cb, (void*)"ou"); - shortcut = Keys::getShortcut(KEYS_CLOSE_TAB); - i = new Item("Close", shortcut, filemenu_cb, (void*)"cw"); - new Divider(); - shortcut = Keys::getShortcut(KEYS_CLOSE_ALL); - i = new Item("Exit Dillo", shortcut, filemenu_cb, (void*)"ed"); - pm->type(PopupMenu::POPUP123); - pm->end(); - } - - pm->label(wid->visible() ? NULL : "File"); - a_Timeout_add(0.0, Menu_popup_cb2, (void *)pm); + //pm->label(wid->visible() ? NULL : "File"); + a_Timeout_add(0.0, Menu_popup_cb, (void*)pm); } /* @@ -611,28 +506,21 @@ void a_Menu_file_popup(BrowserWindow *bw, void *v_wid) */ void a_Menu_bugmeter_popup(BrowserWindow *bw, const DilloUrl *url) { - // One menu for every browser window - static PopupMenu *pm = 0; + static Fl_Menu_Item pm[] = { + {"Validate URL with W3C", 0, Menu_bugmeter_validate_w3c_cb,0,0,0,0,0,0}, + {"Validate URL with WDG", 0, Menu_bugmeter_validate_wdg_cb, 0, + FL_MENU_DIVIDER,0,0,0,0}, + {"About bug meter", 0, Menu_bugmeter_about_cb,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0} + }; + popup_x = Fl::event_x(); + popup_y = Fl::event_y(); popup_bw = bw; a_Url_free(popup_url); popup_url = a_Url_dup(url); - if (!pm) { - Item *i; - pm = new PopupMenu(0,0,0,0,"&BUG METER OPTIONS"); - pm->begin(); - i = new Item("Validate URL with W3C"); - i->callback(Menu_bugmeter_validate_w3c_cb); - i = new Item("Validate URL with WDG"); - i->callback(Menu_bugmeter_validate_wdg_cb); - new Divider(); - i = new Item("About Bug Meter..."); - i->callback(Menu_bugmeter_about_cb); - pm->type(PopupMenu::POPUP123); - pm->end(); - } - pm->popup(); + a_Timeout_add(0.0, Menu_popup_cb, (void*)pm); } /* @@ -640,67 +528,82 @@ void a_Menu_bugmeter_popup(BrowserWindow *bw, const DilloUrl *url) * * direction: {backward = -1, forward = 1} */ -void a_Menu_history_popup(BrowserWindow *bw, int direction) +void a_Menu_history_popup(BrowserWindow *bw, int x, int y, int direction) { - static PopupMenu *pm = 0; - Item *it; - int i; + static Fl_Menu_Item *pm = 0; + int i, n; popup_bw = bw; + popup_x = x; + popup_y = y; history_direction = direction; // TODO: hook popdown event with delete or similar. if (pm) - delete(pm); + delete [] pm; if (history_list) dFree(history_list); - if (direction == -1) { - pm = new PopupMenu(0,0,0,0, "&PREVIOUS PAGES"); - } else { - pm = new PopupMenu(0,0,0,0, "&FOLLOWING PAGES"); - } - // Get a list of URLs for this popup history_list = a_UIcmd_get_history(bw, direction); - pm->begin(); - for (i = 0; history_list[i] != -1; i += 1) { - // TODO: restrict title size - it = new CustItem(a_History_get_title(history_list[i], 1)); - it->callback(Menu_history_cb, INT2VOIDP(i+1)); - } - pm->type(PopupMenu::POPUP123); - pm->end(); + for (n = 0; history_list[n] != -1; n++) + ; - pm->popup(); + pm = new Fl_Menu_Item[n + 1]; + memset(pm, '\0', sizeof(Fl_Menu_Item[n + 1])); + + for (i = 0; i < n; i++) { + pm[i].label(FL_NORMAL_LABEL, a_History_get_title(history_list[i], 1)); + pm[i].callback(Menu_history_cb, INT2VOIDP(i+1)); + } + a_Timeout_add(0.0, Menu_popup_cb, (void*)pm); } /* * Toggle use of remote stylesheets */ -static void Menu_remote_css_cb(Widget *wid) +static void Menu_remote_css_cb(Fl_Widget *wid, void*) { - _MSG("Menu_remote_css_cb\n"); - prefs.load_stylesheets = wid->state() ? 1 : 0; + Fl_Menu_Item *item = (Fl_Menu_Item*) wid; + + item->flags ^= FL_MENU_VALUE; + prefs.load_stylesheets = item->flags & FL_MENU_VALUE ? 1 : 0; a_UIcmd_repush(popup_bw); } /* * Toggle use of embedded CSS style */ -static void Menu_embedded_css_cb(Widget *wid) +static void Menu_embedded_css_cb(Fl_Widget *wid, void*) { - prefs.parse_embedded_css = wid->state() ? 1 : 0; + Fl_Menu_Item *item = (Fl_Menu_Item*) wid; + + item->flags ^= FL_MENU_VALUE; + prefs.parse_embedded_css = item->flags & FL_MENU_VALUE ? 1 : 0; a_UIcmd_repush(popup_bw); } +static void Menu_panel_change_cb(Fl_Widget*, void *user_data) +{ + UI *ui = (UI*)popup_bw->ui; + + if (VOIDP2INT(user_data) == 10) /* small icons */ + ui->change_panel(ui->get_panelsize(), !ui->get_smallicons()); + else + ui->change_panel(VOIDP2INT(user_data), ui->get_smallicons()); +} + /* * Toggle loading of images -- and load them if enabling. */ -static void Menu_imgload_toggle_cb(Widget *wid) +static void Menu_imgload_toggle_cb(Fl_Widget *wid, void*) { - if ((prefs.load_images = wid->state() ? 1 : 0)) { + Fl_Menu_Item *item = (Fl_Menu_Item*) wid; + + item->flags ^= FL_MENU_VALUE; + + if ((prefs.load_images = item->flags & FL_MENU_VALUE ? 1 : 0)) { void *doc = a_Bw_get_current_doc(popup_bw); if (doc) { @@ -713,33 +616,44 @@ static void Menu_imgload_toggle_cb(Widget *wid) /* * Tools popup menu (construction & popup) */ -void a_Menu_tools_popup(BrowserWindow *bw, void *v_wid) -{ - // One menu shared by every browser window - static PopupMenu *pm = NULL; - Widget *wid = (Widget*)v_wid; - Item *it; +void a_Menu_tools_popup(BrowserWindow *bw, int x, int y) +{ + const Fl_Menu_Item *item; + UI *ui = (UI*)bw->ui; + + static Fl_Menu_Item pm[] = { + {"Use remote CSS", 0, Menu_remote_css_cb, 0, FL_MENU_TOGGLE,0,0,0,0}, + {"Use embedded CSS", 0, Menu_embedded_css_cb, 0, + FL_MENU_TOGGLE|FL_MENU_DIVIDER,0,0,0,0}, + {"Load images", 0, Menu_imgload_toggle_cb, 0, + FL_MENU_TOGGLE|FL_MENU_DIVIDER,0,0,0,0}, + {"Panel size", 0, Menu_nop_cb, (void*)"Submenu1", FL_SUBMENU,0,0,0,0}, + {"tiny", 0,Menu_panel_change_cb,(void*)0,FL_MENU_RADIO,0,0,0,0}, + {"small", 0,Menu_panel_change_cb,(void*)1,FL_MENU_RADIO,0,0,0,0}, + {"medium",0,Menu_panel_change_cb,(void*)2, + FL_MENU_RADIO|FL_MENU_DIVIDER,0,0,0,0}, + {"small icons", 0,Menu_panel_change_cb,(void*)10, + FL_MENU_TOGGLE,0,0,0,0}, + {0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0} + }; popup_bw = bw; - - if (!pm) { - pm = new PopupMenu(0,0,0,0, "TOOLS"); - pm->begin(); - it = new ToggleItem("Use remote CSS"); - it->callback(Menu_remote_css_cb); - it->state(prefs.load_stylesheets); - it = new ToggleItem("Use embedded CSS"); - it->callback(Menu_embedded_css_cb); - it->state(prefs.parse_embedded_css); - new Divider(); - it = new ToggleItem("Load images"); - it->callback(Menu_imgload_toggle_cb); - it->state(prefs.load_images); - pm->type(PopupMenu::POPUP13); - pm->end(); + int cur_panelsize = ui->get_panelsize(); + int cur_smallicons = ui->get_smallicons(); + + if (prefs.load_stylesheets) + pm[0].set(); + if (prefs.parse_embedded_css) + pm[1].set(); + if (prefs.load_images) + pm[2].set(); + pm[4+cur_panelsize].setonly(); + cur_smallicons ? pm[7].set() : pm[7].clear(); + + item = pm->popup(x, y); + if (item) { + ((Fl_Widget *)item)->do_callback(); } - //pm->popup(); - pm->value(-1); - ((Menu*)pm)->popup(Rectangle(0,wid->h(),pm->w(),pm->h())); } diff --git a/src/menu.hh b/src/menu.hh index 668de001..a8170e89 100644 --- a/src/menu.hh +++ b/src/menu.hh @@ -17,8 +17,8 @@ void a_Menu_form_popup(BrowserWindow *bw, const DilloUrl *page_url, void *vform, bool_t showing_hiddens); void a_Menu_file_popup(BrowserWindow *bw, void *v_wid); void a_Menu_bugmeter_popup(BrowserWindow *bw, const DilloUrl *url); -void a_Menu_history_popup(BrowserWindow *bw, int direction); -void a_Menu_tools_popup(BrowserWindow *bw, void *v_wid); +void a_Menu_history_popup(BrowserWindow *bw, int x, int y, int direction); +void a_Menu_tools_popup(BrowserWindow *bw, int x, int y); #ifdef __cplusplus @@ -383,6 +383,40 @@ int a_Misc_parse_geometry(char *str, int *x, int *y, int *w, int *h) } /* + * Parse dillorc's search_url string ("[<label> ]<url>") + * Return value: -1 on error, 0 on success (and label and urlstr pointers) + */ +int a_Misc_parse_search_url(char *source, char **label, char **urlstr) +{ + static char buf[32]; + char *p, *q; + int ret = -1; + + if ((p = strrchr(source, ' '))) { + /* label and url pair */ + strncpy(buf,source,MIN(p-source,31)); + buf[MIN(p-source,31)] = 0; + source = p+1; + if ((p = strchr(source, '/')) && p[1] && (q = strchr(p+2,'/'))) { + *urlstr = source; + ret = 0; + } + } else { + /* url only, make a custom label */ + if ((p = strchr(source, '/')) && p[1] && (q = strchr(p+2,'/'))) { + strncpy(buf,p+2,MIN(q-p-2,31)); + buf[MIN(q-p-2,31)] = 0; + *urlstr = source; + ret = 0; + } + } + *label = buf; + if (ret == -1) + MSG("Invalid search_url: \"%s\"\n", source); + return ret; +} + +/* * Encodes string using base64 encoding. * Return value: new string or NULL if input string is empty. */ @@ -17,6 +17,7 @@ void a_Misc_parse_content_type(const char *str, char **major, char **minor, char **charset); int a_Misc_content_type_cmp(const char* ct1, const char *ct2); int a_Misc_parse_geometry(char *geom, int *x, int *y, int *w, int *h); +int a_Misc_parse_search_url(char *source, char **label, char **urlstr); char *a_Misc_encode_base64(const char *in); Dstr *a_Misc_file2dstr(const char *filename); @@ -195,13 +195,12 @@ static void Nav_open_url(BrowserWindow *bw, const DilloUrl *url, const DilloUrl *requester, int offset) { const DilloUrl *old_url; - bool_t MustLoad, ForceReload, Repush, IgnoreScroll; + bool_t MustLoad, ForceReload, IgnoreScroll; int x, y, idx, ClientKey; DilloWeb *Web; MSG("Nav_open_url: new url='%s'\n", URL_STR_(url)); - Repush = (URL_FLAGS(url) & URL_ReloadFromCache) != 0; ForceReload = (URL_FLAGS(url) & (URL_E2EQuery + URL_ReloadFromCache)) != 0; IgnoreScroll = (URL_FLAGS(url) & URL_IgnoreScroll) != 0; @@ -233,8 +232,7 @@ static void Nav_open_url(BrowserWindow *bw, const DilloUrl *url, // a_Menu_pagemarks_new(bw); - Web = a_Web_new(url, requester); - Web->bw = bw; + Web = a_Web_new(bw, url, requester); Web->flags |= WEB_RootUrl; if ((ClientKey = a_Capi_open_url(Web, NULL, NULL)) != 0) { a_Bw_add_client(bw, ClientKey, 1); @@ -249,10 +247,9 @@ static void Nav_open_url(BrowserWindow *bw, const DilloUrl *url, */ void a_Nav_cancel_expect(BrowserWindow *bw) { - if (bw->nav_expecting) { - a_Url_free(bw->nav_expect_url); - bw->nav_expect_url = NULL; - bw->nav_expecting = FALSE; + if (a_Bw_expecting(bw)) { + a_Bw_cancel_expect(bw); + a_UIcmd_set_buttons_sens(bw); } if (bw->meta_refresh_status > 0) --bw->meta_refresh_status; @@ -263,7 +260,7 @@ void a_Nav_cancel_expect(BrowserWindow *bw) */ void a_Nav_cancel_expect_if_eq(BrowserWindow *bw, const DilloUrl *url) { - if (bw->nav_expecting && a_Url_cmp(url, bw->nav_expect_url) == 0) + if (a_Url_cmp(url, a_Bw_expected_url(bw)) == 0) a_Nav_cancel_expect(bw); } @@ -281,8 +278,8 @@ void a_Nav_expect_done(BrowserWindow *bw) dReturn_if_fail(bw != NULL); - if (bw->nav_expecting) { - url = bw->nav_expect_url; + if (a_Bw_expecting(bw)) { + url = a_Url_dup(a_Bw_expected_url(bw)); reload = (URL_FLAGS(url) & URL_ReloadPage); repush = (URL_FLAGS(url) & URL_ReloadFromCache); e2equery = (URL_FLAGS(url) & URL_E2EQuery); @@ -293,6 +290,7 @@ void a_Nav_expect_done(BrowserWindow *bw) m = URL_E2EQuery|URL_ReloadPage|URL_ReloadFromCache|URL_IgnoreScroll; a_Url_set_flags(url, URL_FLAGS(url) & ~m); url_idx = a_History_add_url(url); + a_Url_free(url); if (repush) { MSG("a_Nav_expect_done: repush!\n"); @@ -345,16 +343,17 @@ void a_Nav_expect_done(BrowserWindow *bw) void a_Nav_push(BrowserWindow *bw, const DilloUrl *url, const DilloUrl *requester) { + const DilloUrl *e_url; dReturn_if_fail (bw != NULL); - if (bw->nav_expecting && !a_Url_cmp(bw->nav_expect_url, url) && - !strcmp(URL_FRAGMENT(bw->nav_expect_url),URL_FRAGMENT(url))) { + e_url = a_Bw_expected_url(bw); + if (e_url && !a_Url_cmp(e_url, url) && + !strcmp(URL_FRAGMENT(e_url),URL_FRAGMENT(url))) { /* we're already expecting that url (most probably a double-click) */ return; } a_Nav_cancel_expect(bw); - bw->nav_expect_url = a_Url_dup(url); - bw->nav_expecting = TRUE; + a_Bw_expect(bw, url); Nav_open_url(bw, url, requester, 0); } @@ -370,8 +369,7 @@ static void Nav_repush(BrowserWindow *bw) url = a_Url_dup(a_History_get_url(NAV_TOP_UIDX(bw))); /* Let's make reload be from Cache */ a_Url_set_flags(url, URL_FLAGS(url) | URL_ReloadFromCache); - bw->nav_expect_url = a_Url_dup(url); - bw->nav_expecting = TRUE; + a_Bw_expect(bw, url); Nav_open_url(bw, url, NULL, 0); a_Url_free(url); } @@ -488,9 +486,9 @@ static void Nav_reload_callback(void *data) confirmed = 0; } else if (URL_FLAGS(h_url) & URL_Post) { /* Attempt to repost data, let's confirm... */ - choice = a_Dialog_choice3("Repost form data?", - "Yes", "*No", "Cancel"); - confirmed = (choice == 0); /* "Yes" */ + choice = a_Dialog_choice5("Repost form data?", + "No", "Yes", "Cancel", NULL, NULL); + confirmed = (choice == 2); /* "Yes" */ } if (confirmed) { @@ -501,9 +499,9 @@ static void Nav_reload_callback(void *data) a_Url_set_flags(r_url, URL_FLAGS(r_url) | URL_E2EQuery); /* This is an explicit reload, so clear the SpamSafe flag */ a_Url_set_flags(r_url, URL_FLAGS(r_url) & ~URL_SpamSafe); - bw->nav_expect_url = r_url; - bw->nav_expecting = TRUE; + a_Bw_expect(bw, r_url); Nav_open_url(bw, r_url, NULL, 0); + a_Url_free(r_url); } } } @@ -567,8 +565,7 @@ static void Nav_save_cb(int Op, CacheClient_t *Client) void a_Nav_save_url(BrowserWindow *bw, const DilloUrl *url, const char *filename) { - DilloWeb *Web = a_Web_new(url, NULL); - Web->bw = bw; + DilloWeb *Web = a_Web_new(bw, url, NULL); Web->filename = dStrdup(filename); Web->flags |= WEB_Download; /* TODO: keep track of this client */ diff --git a/src/pixmaps.h b/src/pixmaps.h index 83235dd2..9d3c4f28 100644 --- a/src/pixmaps.h +++ b/src/pixmaps.h @@ -819,11 +819,11 @@ static const char *const tools_xpm[] = { " ", " ", " .XXo. ", -" oO $$+. ", +" oO$$$+. ", " oo@$$$@# ", " #o@$$$O# ", " #X$$$$%X ", -" &#% #X$$$@o ", +" &# #X$$$@o ", " #*o =-@$$$# ", " oO*o #$@$$$$# ", " oOOOX oO@;$$$$X ", @@ -1426,11 +1426,11 @@ static const char *const tools_s_xpm[] = { " p*45<Xg ", " h.>885oa ", " p.3883Xg ", -" i$O s$488;s ", +" $O s$488;s ", " O>1p e;588;a ", " O331sr;7778:s ", " O343,**3678;a ", -" f,643;#%368:s ", +" O,643;#%368:s ", " t<64>= &374f ", " t244>= &379ih", " d@:;=& &475u", @@ -1539,22 +1539,22 @@ static const char *const help_xpm[] = { "D c #000000", "E c #000000", "F c #000000", -" 5555555 ", -" 544433355 ", -" 54555438455 ", -" 44555542835 ", -" 44445548245 ", -" 4444554274 ", -" 544554274 ", -" 55474 ", -" 5474 ", -" 544 ", +" ", +" 444333 ", +" 4 4384 ", +" 44 4283 ", +" 4444 4824 ", +" 4444 4274 ", +" 44 4274 ", +" 474 ", +" 474 ", +" 44 ", " 44 ", " ", -" 5445 ", +" 44 ", " 4764 ", " 4674 ", -" 5445 "}; +" 44 "}; /* XPM */ static const char *const full_screen_on_xpm[] = { diff --git a/src/prefs.c b/src/prefs.c index f968710a..f243205a 100644 --- a/src/prefs.c +++ b/src/prefs.c @@ -18,11 +18,12 @@ #define PREFS_FONT_CURSIVE "URW Chancery L" #define PREFS_FONT_FANTASY "DejaVu Sans" /* TODO: find good default */ #define PREFS_FONT_MONOSPACE "DejaVu Sans Mono" -#define PREFS_SEARCH_URL "http://www.google.com/search?ie=UTF-8&oe=UTF-8&q=%s" +#define PREFS_SEARCH_URL "http://duckduckgo.com/lite/?kp=-1&q=%s" #define PREFS_NO_PROXY "localhost 127.0.0.1" #define PREFS_SAVE_DIR "/tmp/" #define PREFS_HTTP_REFERER "host" #define PREFS_HTTP_USER_AGENT "Dillo/" VERSION +#define PREFS_THEME "none" /*----------------------------------------------------------------------------- * Global Data @@ -70,11 +71,15 @@ void a_Prefs_init(void) prefs.load_stylesheets=TRUE; prefs.middle_click_drags_page = TRUE; prefs.middle_click_opens_new_tab = TRUE; + prefs.right_click_closes_tab = FALSE; prefs.no_proxy = dStrdup(PREFS_NO_PROXY); prefs.panel_size = P_medium; prefs.parse_embedded_css=TRUE; prefs.save_dir = dStrdup(PREFS_SAVE_DIR); - prefs.search_url = dStrdup(PREFS_SEARCH_URL); + prefs.search_urls = dList_new(16); + dList_append(prefs.search_urls, dStrdup(PREFS_SEARCH_URL)); + dList_append(prefs.search_urls, NULL); /* flags a default search URL */ + prefs.search_url_idx = 0; prefs.show_back = TRUE; prefs.show_bookmarks = TRUE; prefs.show_clear_url = TRUE; @@ -85,6 +90,7 @@ void a_Prefs_init(void) prefs.show_home = TRUE; prefs.show_msg = TRUE; prefs.show_progress_box = TRUE; + prefs.show_quit_dialog = TRUE; prefs.show_reload = TRUE; prefs.show_save = TRUE; prefs.show_search = TRUE; @@ -94,6 +100,7 @@ void a_Prefs_init(void) prefs.show_url = TRUE; prefs.small_icons = FALSE; prefs.start_page = a_Url_new(PREFS_START_PAGE, NULL); + prefs.theme = dStrdup(PREFS_THEME); prefs.w3c_plus_heuristics = TRUE; } @@ -103,6 +110,8 @@ void a_Prefs_init(void) */ void a_Prefs_freeall(void) { + int i; + dFree(prefs.font_cursive); dFree(prefs.font_fantasy); dFree(prefs.font_monospace); @@ -116,6 +125,9 @@ void a_Prefs_freeall(void) dFree(prefs.http_user_agent); dFree(prefs.no_proxy); dFree(prefs.save_dir); - dFree(prefs.search_url); + for (i = 0; i < dList_length(prefs.search_urls); ++i) + dFree(dList_nth_data(prefs.search_urls, i)); + dList_free(prefs.search_urls); a_Url_free(prefs.start_page); + dFree(prefs.theme); } diff --git a/src/prefs.h b/src/prefs.h index 4009925c..f1a3d538 100644 --- a/src/prefs.h +++ b/src/prefs.h @@ -24,7 +24,7 @@ extern "C" { #define PREFS_GEOMETRY_DEFAULT_YPOS -9999 /* Panel sizes */ -enum { P_tiny = 0, P_small, P_medium, P_large }; +enum { P_tiny = 0, P_small, P_medium }; enum {PREFS_FILTER_ALLOW_ALL, PREFS_FILTER_SAME_DOMAIN}; @@ -49,6 +49,7 @@ struct _DilloPrefs { int32_t bg_color; bool_t contrast_visited_color; bool_t show_tooltip; + char *theme; int panel_size; bool_t small_icons; bool_t limit_text_width; @@ -71,6 +72,7 @@ struct _DilloPrefs { bool_t show_search; bool_t show_help; bool_t show_progress_box; + bool_t show_quit_dialog; bool_t fullwindow_start; bool_t load_images; bool_t load_stylesheets; @@ -84,7 +86,9 @@ struct _DilloPrefs { char *font_monospace; bool_t enterpress_forces_submit; bool_t middle_click_opens_new_tab; - char *search_url; + bool_t right_click_closes_tab; + bool_t search_url_idx; + Dlist *search_urls; char *save_dir; bool_t show_msg; bool_t show_extra_warnings; diff --git a/src/prefsparser.cc b/src/prefsparser.cc index 95f98c16..efe64a0e 100644 --- a/src/prefsparser.cc +++ b/src/prefsparser.cc @@ -24,6 +24,7 @@ typedef enum { PREFS_BOOL, PREFS_COLOR, PREFS_STRING, + PREFS_STRINGS, PREFS_URL, PREFS_INT32, PREFS_DOUBLE, @@ -81,11 +82,12 @@ int PrefsParser::parseOption(char *name, char *value) PREFS_BOOL }, { "middle_click_opens_new_tab", &prefs.middle_click_opens_new_tab, PREFS_BOOL }, + { "right_click_closes_tab", &prefs.right_click_closes_tab, PREFS_BOOL }, { "no_proxy", &prefs.no_proxy, PREFS_STRING }, { "panel_size", &prefs.panel_size, PREFS_PANEL_SIZE }, { "parse_embedded_css", &prefs.parse_embedded_css, PREFS_BOOL }, { "save_dir", &prefs.save_dir, PREFS_STRING }, - { "search_url", &prefs.search_url, PREFS_STRING }, + { "search_url", &prefs.search_urls, PREFS_STRINGS }, { "show_back", &prefs.show_back, PREFS_BOOL }, { "show_bookmarks", &prefs.show_bookmarks, PREFS_BOOL }, { "show_clear_url", &prefs.show_clear_url, PREFS_BOOL }, @@ -96,6 +98,7 @@ int PrefsParser::parseOption(char *name, char *value) { "show_home", &prefs.show_home, PREFS_BOOL }, { "show_msg", &prefs.show_msg, PREFS_BOOL }, { "show_progress_box", &prefs.show_progress_box, PREFS_BOOL }, + { "show_quit_dialog", &prefs.show_quit_dialog, PREFS_BOOL }, { "show_reload", &prefs.show_reload, PREFS_BOOL }, { "show_save", &prefs.show_save, PREFS_BOOL }, { "show_search", &prefs.show_search, PREFS_BOOL }, @@ -105,6 +108,7 @@ int PrefsParser::parseOption(char *name, char *value) { "show_url", &prefs.show_url, PREFS_BOOL }, { "small_icons", &prefs.small_icons, PREFS_BOOL }, { "start_page", &prefs.start_page, PREFS_URL }, + { "theme", &prefs.theme, PREFS_STRING }, { "w3c_plus_heuristics", &prefs.w3c_plus_heuristics, PREFS_BOOL } }; @@ -128,11 +132,26 @@ int PrefsParser::parseOption(char *name, char *value) break; case PREFS_COLOR: *(int32_t *)node->pref = a_Color_parse(value, *(int32_t*)node->pref,&st); + if (st) + MSG("prefs: Color '%s' not recognized.\n", value); break; case PREFS_STRING: dFree(*(char **)node->pref); *(char **)node->pref = dStrdup(value); break; + case PREFS_STRINGS: + { + Dlist *lp = *(Dlist **)node->pref; + if (dList_length(lp) == 2 && !dList_nth_data(lp, 1)) { + /* override the default */ + void *data = dList_nth_data(lp, 0); + dList_remove(lp, data); + dList_remove(lp, NULL); + dFree(data); + } + dList_append(lp, dStrdup(value)); + break; + } case PREFS_URL: a_Url_free(*(DilloUrl **)node->pref); *(DilloUrl **)node->pref = a_Url_new(value, NULL); @@ -161,8 +180,6 @@ int PrefsParser::parseOption(char *name, char *value) prefs.panel_size = P_tiny; else if (!dStrcasecmp(value, "small")) prefs.panel_size = P_small; - else if (!dStrcasecmp(value, "large")) - prefs.panel_size = P_large; else /* default to "medium" */ prefs.panel_size = P_medium; break; @@ -170,13 +187,6 @@ int PrefsParser::parseOption(char *name, char *value) MSG_WARN("prefs: {%s} IS recognized but not handled!\n", name); break; /* Not reached */ } - - if (prefs.limit_text_width) { - /* BUG: causes 100% CPU usage with <button> or <input type="image"> */ - MSG_WARN("Disabling limit_text_width preference (currently broken).\n"); - prefs.limit_text_width = FALSE; - } - return 0; } diff --git a/src/styleengine.cc b/src/styleengine.cc index 776c1694..a4c31ccb 100644 --- a/src/styleengine.cc +++ b/src/styleengine.cc @@ -52,6 +52,7 @@ StyleEngine::StyleEngine (dw::core::Layout *layout) { n->wordStyle = NULL; n->backgroundStyle = NULL; n->styleAttrProperties = NULL; + n->styleAttrPropertiesImportant = NULL; n->nonCssProperties = NULL; n->inheritBackgroundColor = false; } @@ -82,6 +83,7 @@ void StyleEngine::startElement (int element) { stack->increase (); Node *n = stack->getRef (stack->size () - 1); n->styleAttrProperties = NULL; + n->styleAttrPropertiesImportant = NULL; n->nonCssProperties = NULL; n->style = NULL; n->wordStyle = NULL; @@ -138,10 +140,14 @@ void StyleEngine::setStyle (const char *styleAttr) { Node *n = stack->getRef (stack->size () - 1); assert (n->styleAttrProperties == NULL); // parse style information from style="" attribute, if it exists - if (styleAttr && prefs.parse_embedded_css) - n->styleAttrProperties = - CssParser::parseDeclarationBlock (styleAttr, - strlen (styleAttr)); + if (styleAttr && prefs.parse_embedded_css) { + n->styleAttrProperties = new CssPropertyList (true); + n->styleAttrPropertiesImportant = new CssPropertyList (true); + + CssParser::parseDeclarationBlock (styleAttr, strlen (styleAttr), + n->styleAttrProperties, + n->styleAttrPropertiesImportant); + } }; /** @@ -213,6 +219,8 @@ void StyleEngine::endElement (int element) { if (n->styleAttrProperties) delete n->styleAttrProperties; + if (n->styleAttrPropertiesImportant) + delete n->styleAttrPropertiesImportant; if (n->nonCssProperties) delete n->nonCssProperties; if (n->style) @@ -709,7 +717,8 @@ Style * StyleEngine::backgroundStyle () { * This method is private. Call style() to get a current style object. */ Style * StyleEngine::style0 (int i) { - CssPropertyList props, *styleAttrProperties, *nonCssProperties; + CssPropertyList props, *styleAttrProperties, *styleAttrPropertiesImportant; + CssPropertyList *nonCssProperties; // get previous style from the stack StyleAttrs attrs = *stack->getRef (i - 1)->style; @@ -726,11 +735,13 @@ Style * StyleEngine::style0 (int i) { preprocessAttrs (&attrs); styleAttrProperties = stack->getRef (i)->styleAttrProperties; + styleAttrPropertiesImportant = stack->getRef(i)->styleAttrPropertiesImportant; nonCssProperties = stack->getRef (i)->nonCssProperties; // merge style information cssContext->apply (&props, doctree, stack->getRef(i)->doctreeNode, - styleAttrProperties, nonCssProperties); + styleAttrProperties, styleAttrPropertiesImportant, + nonCssProperties); // apply style apply (i, &attrs, &props); diff --git a/src/styleengine.hh b/src/styleengine.hh index e37aeed1..b73a8b5f 100644 --- a/src/styleengine.hh +++ b/src/styleengine.hh @@ -21,6 +21,7 @@ class StyleEngine { private: struct Node { CssPropertyList *styleAttrProperties; + CssPropertyList *styleAttrPropertiesImportant; CssPropertyList *nonCssProperties; dw::core::style::Style *style; dw::core::style::Style *wordStyle; diff --git a/src/table.cc b/src/table.cc index 58cdf22e..d48a0c45 100644 --- a/src/table.cc +++ b/src/table.cc @@ -151,7 +151,6 @@ void Html_tag_open_tr(DilloHtml *html, const char *tag, int tagsize) { const char *attrbuf; int32_t bgcolor = -1; - bool new_style = false; html->styleEngine->inheritNonCssHints (); @@ -183,10 +182,8 @@ void Html_tag_open_tr(DilloHtml *html, const char *tag, int tagsize) if (bgcolor != -1) { html->styleEngine->setNonCssHint(CSS_PROPERTY_BACKGROUND_COLOR, CSS_TYPE_COLOR, bgcolor); - new_style = true; } - if (a_Html_tag_set_valign_attr (html, tag, tagsize)) - new_style = true; + a_Html_tag_set_valign_attr (html, tag, tagsize); break; default: break; @@ -318,7 +315,6 @@ static void Html_tag_open_table_cell(DilloHtml *html, int colspan = 1, rowspan = 1; const char *attrbuf; int32_t bgcolor; - bool_t new_style; html->styleEngine->inheritNonCssHints (); @@ -363,8 +359,7 @@ static void Html_tag_open_table_cell(DilloHtml *html, a_Html_parse_length (html, attrbuf)); } - if (a_Html_tag_set_valign_attr (html, tag, tagsize)) - new_style = TRUE; + a_Html_tag_set_valign_attr (html, tag, tagsize); if ((attrbuf = a_Html_get_attr(html, tag, tagsize, "bgcolor"))) { bgcolor = a_Html_color_parse(html, attrbuf, -1); diff --git a/src/timeout.cc b/src/timeout.cc index 80eb6425..1ddcd5e1 100644 --- a/src/timeout.cc +++ b/src/timeout.cc @@ -11,12 +11,9 @@ // Simple ADT for timeout functions -#include <fltk/run.h> +#include <FL/Fl.H> #include "timeout.hh" -using namespace fltk; - - // C++ functions with C linkage ---------------------------------------------- /* @@ -25,7 +22,7 @@ using namespace fltk; */ void a_Timeout_add(float t, TimeoutCb_t cb, void *cbdata) { - add_timeout(t, cb, cbdata); + Fl::add_timeout(t, cb, cbdata); } /* @@ -33,7 +30,7 @@ void a_Timeout_add(float t, TimeoutCb_t cb, void *cbdata) */ void a_Timeout_repeat(float t, TimeoutCb_t cb, void *cbdata) { - add_timeout(t, cb, cbdata); + Fl::add_timeout(t, cb, cbdata); } /* @@ -14,73 +14,64 @@ #include <unistd.h> #include <stdio.h> -#include <fltk/HighlightButton.h> -#include <fltk/run.h> -#include <fltk/damage.h> -#include <fltk/xpmImage.h> -#include <fltk/events.h> // for mouse buttons and keys -#include <fltk/Font.h> // UI label font for tabs -#include <fltk/InvisibleBox.h> -#include <fltk/PopupMenu.h> -#include <fltk/Item.h> -#include <fltk/Divider.h> - #include "keys.hh" #include "ui.hh" #include "msg.h" #include "timeout.hh" #include "utf8.hh" -using namespace fltk; - +#include <FL/Fl.H> +#include <FL/Fl_Pixmap.H> +#include <FL/Fl_Box.H> +#include <FL/names.h> // Include image data #include "pixmaps.h" #include "uicmd.hh" struct iconset { - Image *ImgMeterOK, *ImgMeterBug, - *ImgHome, *ImgReload, *ImgSave, *ImgBook, *ImgTools, - *ImgClear,*ImgSearch, *ImgHelp; - MultiImage *ImgLeftMulti, *ImgRightMulti, *ImgStopMulti; + Fl_Image *ImgMeterOK, *ImgMeterBug, + *ImgHome, *ImgReload, *ImgSave, *ImgBook, *ImgTools, + *ImgClear,*ImgSearch, *ImgHelp, *ImgLeft, *ImgLeftIn, + *ImgRight, *ImgRightIn, *ImgStop, *ImgStopIn; }; static struct iconset standard_icons = { - new xpmImage(mini_ok_xpm), - new xpmImage(mini_bug_xpm), - new xpmImage(home_xpm), - new xpmImage(reload_xpm), - new xpmImage(save_xpm), - new xpmImage(bm_xpm), - new xpmImage(tools_xpm), - new xpmImage(new_s_xpm), - new xpmImage(search_xpm), - new xpmImage(help_xpm), - new MultiImage(*new xpmImage(left_xpm), INACTIVE_R, - *new xpmImage(left_i_xpm)), - new MultiImage(*new xpmImage(right_xpm), INACTIVE_R, - *new xpmImage(right_i_xpm)), - new MultiImage(*new xpmImage(stop_xpm), INACTIVE_R, - *new xpmImage(stop_i_xpm)), + new Fl_Pixmap(mini_ok_xpm), + new Fl_Pixmap(mini_bug_xpm), + new Fl_Pixmap(home_xpm), + new Fl_Pixmap(reload_xpm), + new Fl_Pixmap(save_xpm), + new Fl_Pixmap(bm_xpm), + new Fl_Pixmap(tools_xpm), + new Fl_Pixmap(new_s_xpm), + new Fl_Pixmap(search_xpm), + new Fl_Pixmap(help_xpm), + new Fl_Pixmap(left_xpm), + new Fl_Pixmap(left_i_xpm), + new Fl_Pixmap(right_xpm), + new Fl_Pixmap(right_i_xpm), + new Fl_Pixmap(stop_xpm), + new Fl_Pixmap(stop_i_xpm), }; static struct iconset small_icons = { standard_icons.ImgMeterOK, standard_icons.ImgMeterBug, - new xpmImage(home_s_xpm), - new xpmImage(reload_s_xpm), - new xpmImage(save_s_xpm), - new xpmImage(bm_s_xpm), - new xpmImage(tools_s_xpm), - new xpmImage(new_s_xpm), + new Fl_Pixmap(home_s_xpm), + new Fl_Pixmap(reload_s_xpm), + new Fl_Pixmap(save_s_xpm), + new Fl_Pixmap(bm_s_xpm), + new Fl_Pixmap(tools_s_xpm), + new Fl_Pixmap(new_s_xpm), standard_icons.ImgSearch, standard_icons.ImgHelp, - new MultiImage(*new xpmImage(left_s_xpm), INACTIVE_R, - *new xpmImage(left_si_xpm)), - new MultiImage(*new xpmImage(right_s_xpm), INACTIVE_R, - *new xpmImage(right_si_xpm)), - new MultiImage(*new xpmImage(stop_s_xpm), INACTIVE_R, - *new xpmImage(stop_si_xpm)), + new Fl_Pixmap(left_s_xpm), + new Fl_Pixmap(left_si_xpm), + new Fl_Pixmap(right_s_xpm), + new Fl_Pixmap(right_si_xpm), + new Fl_Pixmap(stop_s_xpm), + new Fl_Pixmap(stop_si_xpm), }; @@ -95,49 +86,69 @@ static struct iconset *icons = &standard_icons; /* * (Used to avoid certain shortcuts in the location bar) */ -class CustInput : public Input { +class CustInput : public Fl_Input { public: CustInput (int x, int y, int w, int h, const char* l=0) : - Input(x,y,w,h,l) {}; + Fl_Input(x,y,w,h,l) {}; int handle(int e); }; /* - * Disable: UpKey, DownKey, PageUpKey, PageDownKey and - * CTRL+{o,r,HomeKey,EndKey} + * Disable keys: Up, Down, Page_Up, Page_Down, Tab and + * CTRL+{o,r,Home,End} SHIFT+{Left,Right}. */ int CustInput::handle(int e) { - int k = event_key(); + int k = Fl::event_key(); _MSG("CustInput::handle event=%d\n", e); // We're only interested in some flags - unsigned modifier = event_state() & (SHIFT | CTRL | ALT); + unsigned modifier = Fl::event_state() & (FL_SHIFT | FL_CTRL | FL_ALT); // Don't focus with arrow keys - if (e == FOCUS && - (k == UpKey || k == DownKey || k == LeftKey || k == RightKey)) { + if (e == FL_FOCUS && + (k == FL_Up || k == FL_Down || k == FL_Left || k == FL_Right)) { return 0; - } else if (e == KEY) { - if (modifier == CTRL) { - if (k == 'l') { + } else if (e == FL_KEYBOARD) { + if (k == FL_Escape && modifier == 0) { + // Let the parent group handle this Esc key + return 0; + } else if (modifier == FL_SHIFT) { + if (k == FL_Left || k == FL_Right) { + // Let these keys get to the UI + return 0; + } + } else if (modifier == FL_CTRL) { + if (k == 'a' || k == 'e') { + position(k == 'a' ? 0 : size()); + return 1; + } else if (k == 'k') { + cut(position(), size()); + return 1; + } else if (k == 'd') { + cut(position(), position()+1); + return 1; + } else if (k == 'l') { // Make text selected when already focused. position(size(), 0); return 1; - } else if (k == 'o' || k == 'r' || k == HomeKey || k == EndKey) + } else if (k == 'h' || k == 'o' || k == 'r' || + k == FL_Home || k == FL_End) { + // Let these keys get to the UI + return 0; + } + } else if (modifier == 0) { + if (k == FL_Down || k == FL_Up || + k == FL_Page_Down || k == FL_Page_Up || k == FL_Tab) { + // Give up focus and honor the key + a_UIcmd_focus_main_area(a_UIcmd_get_bw_by_widget(this)); return 0; - } else if (modifier == SHIFT) { - if (k == LeftKey || k == RightKey) { - _MSG(" CustInput::handle > SHIFT+RightKey\n"); - a_UIcmd_send_event_to_tabs_by_wid(e, this); - return 1; } } } - _MSG("\n"); - return Input::handle(e); + return Fl_Input::handle(e); } //---------------------------------------------------------------------------- @@ -145,24 +156,24 @@ int CustInput::handle(int e) /* * Used to handle "paste" within the toolbar's Clear button. */ -class CustHighlightButton : public HighlightButton { +class CustPasteButton : public CustLightButton { public: - CustHighlightButton(int x, int y, int w, int h, const char *l=0) : - HighlightButton(x,y,w,h,l) {}; + CustPasteButton(int x, int y, int w, int h, const char *l=0) : + CustLightButton(x,y,w,h,l) {}; int handle(int e); }; -int CustHighlightButton::handle(int e) +int CustPasteButton::handle(int e) { - if (e == PASTE) { - const char* t = event_text(); + if (e == FL_PASTE) { + const char* t = Fl::event_text(); if (t && *t) { a_UIcmd_set_location_text(a_UIcmd_get_bw_by_widget(this), t); a_UIcmd_open_urlstr(a_UIcmd_get_bw_by_widget(this), t); return 1; } } - return HighlightButton::handle(e); + return CustLightButton::handle(e); } //---------------------------------------------------------------------------- @@ -170,22 +181,19 @@ int CustHighlightButton::handle(int e) /* * Used to resize the progress boxes automatically. */ -class CustProgressBox : public InvisibleBox { +class CustProgressBox : public Fl_Box { int padding; public: CustProgressBox(int x, int y, int w, int h, const char *l=0) : - InvisibleBox(x,y,w,h,l) { padding = 0; }; + Fl_Box(x,y,w,h,l) { padding = 0; }; void update_label(const char *lbl) { - int w,h; + int w = 0, h = 0; if (!padding) { copy_label("W"); measure_label(w, h); padding = w > 2 ? w/2 : 1; } copy_label(lbl); - measure_label(w,h); - resize(w+padding,h); - redraw_label(); } }; @@ -205,23 +213,23 @@ public: /* * Callback for the search button. */ -static void search_cb(Widget *wid, void *data) +static void search_cb(Fl_Widget *wid, void *data) { - int k = event_key(); + int b = Fl::event_button(); - if (k == 1) { + if (b == FL_LEFT_MOUSE) { a_UIcmd_search_dialog(a_UIcmd_get_bw_by_widget(wid)); - } else if (k == 2) { + } else if (b == FL_MIDDLE_MOUSE) { ((UI*)data)->color_change_cb_i(); - } else if (k == 3) { - ((UI*)data)->panel_cb_i(); + } else if (b == FL_RIGHT_MOUSE) { + // nothing ATM } } /* * Callback for the help button. */ -static void help_cb(Widget *w, void *) +static void help_cb(Fl_Widget *w, void *) { char *path = dStrconcat(DILLO_DOCDIR, "user_help.html", NULL); BrowserWindow *bw = a_UIcmd_get_bw_by_widget(w); @@ -233,7 +241,7 @@ static void help_cb(Widget *w, void *) } else { MSG("Can't read local help file at \"%s\"." " Getting remote help...\n", path); - a_UIcmd_open_urlstr(bw, "http://www.dillo.org/dillo2-help.html"); + a_UIcmd_open_urlstr(bw, "http://www.dillo.org/dillo3-help.html"); } dFree(path); } @@ -241,10 +249,10 @@ static void help_cb(Widget *w, void *) /* * Callback for the File menu button. */ -static void filemenu_cb(Widget *wid, void *) +static void filemenu_cb(Fl_Widget *wid, void *) { - int k = event_key(); - if (k == 1 || k == 3) { + int b = Fl::event_button(); + if (b == FL_LEFT_MOUSE || b == FL_RIGHT_MOUSE) { a_UIcmd_file_popup(a_UIcmd_get_bw_by_widget(wid), wid); } } @@ -252,105 +260,92 @@ static void filemenu_cb(Widget *wid, void *) /* * Callback for the location's clear-button. */ -static void clear_cb(Widget *w, void *data) +static void clear_cb(Fl_Widget *w, void *data) { UI *ui = (UI*)data; - int k = event_key(); - if (k == 1) { + int b = Fl::event_button(); + if (b == FL_LEFT_MOUSE) { ui->set_location(""); ui->focus_location(); - } if (k == 2) { + } if (b == FL_MIDDLE_MOUSE) { ui->paste_url(); } } /* - * Change the color of the location bar. - * -static void color_change_cb(Widget *wid, void *data) -{ - ((UI*)data)->color_change_cb_i(); -} - */ - - -/* * Send the browser to the new URL in the location. */ -static void location_cb(Widget *wid, void *data) +static void location_cb(Fl_Widget *wid, void *data) { - Input *i = (Input*)wid; + Fl_Input *i = (Fl_Input*)wid; UI *ui = (UI*)data; _MSG("location_cb()\n"); - /* This test is necessary because WHEN_ENTER_KEY also includes - * other events we're not interested in. For instance pressing - * The Back or Forward, buttons, or the first click on a rendered - * page. BUG: this must be investigated and reported to FLTK2 team */ - if (event_key() == ReturnKey) { - a_UIcmd_open_urlstr(a_UIcmd_get_bw_by_widget(i), i->value()); - } - if (ui->get_panelmode() == UI_TEMPORARILY_SHOW_PANELS) { - ui->set_panelmode(UI_HIDDEN); - } + a_UIcmd_open_urlstr(a_UIcmd_get_bw_by_widget(i), i->value()); + + if (ui->temporaryPanels()) + ui->panels_toggle(); } /* * Callback handler for button press on the panel */ -static void b1_cb(Widget *wid, void *cb_data) +static void b1_cb(Fl_Widget *wid, void *cb_data) { int bn = VOIDP2INT(cb_data); - int k = event_key(); - if (k && k <= 7) { - _MSG("[%s], mouse button %d was pressed\n", button_names[bn], k); - _MSG("mouse button %d was pressed\n", k); + int b = Fl::event_button(); + if (b >= FL_LEFT_MOUSE && b <= FL_RIGHT_MOUSE) { + _MSG("[%s], mouse button %d was pressed\n", button_names[bn], b); + _MSG("mouse button %d was pressed\n", b); } switch (bn) { case UI_BACK: - if (k == 1) { + if (b == FL_LEFT_MOUSE) { a_UIcmd_back(a_UIcmd_get_bw_by_widget(wid)); - } else if (k == 3) { - a_UIcmd_back_popup(a_UIcmd_get_bw_by_widget(wid)); + } else if (b == FL_RIGHT_MOUSE) { + a_UIcmd_back_popup(a_UIcmd_get_bw_by_widget(wid), wid->x(), + wid->y() + wid->h()); } break; case UI_FORW: - if (k == 1) { + if (b == FL_LEFT_MOUSE) { a_UIcmd_forw(a_UIcmd_get_bw_by_widget(wid)); - } else if (k == 3) { - a_UIcmd_forw_popup(a_UIcmd_get_bw_by_widget(wid)); + } else if (b == FL_RIGHT_MOUSE) { + a_UIcmd_forw_popup(a_UIcmd_get_bw_by_widget(wid), wid->x(), + wid->y() + wid->h()); } break; case UI_HOME: - if (k == 1) { + if (b == FL_LEFT_MOUSE) { a_UIcmd_home(a_UIcmd_get_bw_by_widget(wid)); } break; case UI_RELOAD: - if (k == 1) { + if (b == FL_LEFT_MOUSE) { a_UIcmd_reload(a_UIcmd_get_bw_by_widget(wid)); } break; case UI_SAVE: - if (k == 1) { + if (b == FL_LEFT_MOUSE) { a_UIcmd_save(a_UIcmd_get_bw_by_widget(wid)); } break; case UI_STOP: - if (k == 1) { + if (b == FL_LEFT_MOUSE) { a_UIcmd_stop(a_UIcmd_get_bw_by_widget(wid)); } break; case UI_BOOK: - if (k == 1) { + if (b == FL_LEFT_MOUSE) { a_UIcmd_book(a_UIcmd_get_bw_by_widget(wid)); } break; case UI_TOOLS: - if (k == 1 || k == 3) { - a_UIcmd_tools(a_UIcmd_get_bw_by_widget(wid), wid); + if (b == FL_LEFT_MOUSE || b == FL_RIGHT_MOUSE) { + a_UIcmd_tools(a_UIcmd_get_bw_by_widget(wid), wid->x(), + wid->y() + wid->h()); } break; default: @@ -359,24 +354,14 @@ static void b1_cb(Widget *wid, void *cb_data) } /* - * Callback handler for fullscreen button press - */ -//static void fullscreen_cb(Widget *wid, void *data) -//{ -// /* TODO: do we want to toggle fullscreen or panelmode? -// maybe we need to add another button?*/ -// ((UI*)data)->panelmode_cb_i(); -//} - -/* * Callback for the bug meter button. */ -static void bugmeter_cb(Widget *wid, void *data) +static void bugmeter_cb(Fl_Widget *wid, void *data) { - int k = event_key(); - if (k == 1) { + int b = Fl::event_button(); + if (b == FL_LEFT_MOUSE) { a_UIcmd_view_page_bugs(a_UIcmd_get_bw_by_widget(wid)); - } else if (k == 3) { + } else if (b == FL_RIGHT_MOUSE) { a_UIcmd_bugmeter_popup(a_UIcmd_get_bw_by_widget(wid)); } } @@ -390,159 +375,136 @@ static void bugmeter_cb(Widget *wid, void *data) //---------------------------- /* + * Make a generic navigation button + */ +Fl_Button *UI::make_button(const char *label, Fl_Image *img, Fl_Image *deimg, + int b_n, int start) +{ + if (start) + p_xpos = 0; + + Fl_Button *b = new CustLightButton(p_xpos, 0, bw, bh, (lbl) ? label : NULL); + if (img) + b->image(img); + if (deimg) + b->deimage(deimg); + b->callback(b1_cb, INT2VOIDP(b_n)); + b->clear_visible_focus(); + b->labelsize(12); + b->box(FL_FLAT_BOX); + b->down_box(FL_THIN_DOWN_FRAME); + p_xpos += bw; + return b; +} + +/* * Create the archetipic browser buttons */ -PackedGroup *UI::make_toolbar(int tw, int th) +void UI::make_toolbar(int tw, int th) { - HighlightButton *b; - PackedGroup *p1=new PackedGroup(0,0,tw,th); - p1->begin(); - Back = b = new HighlightButton(xpos, 0, bw, bh, (lbl) ? "Back" : 0); - b->image(icons->ImgLeftMulti); - b->callback(b1_cb, (void *)UI_BACK); - b->clear_tab_to_focus(); - HighlightButton::default_style->highlight_color(CuteColor); - - Forw = b = new HighlightButton(xpos, 0, bw, bh, (lbl) ? "Forw" : 0); - b->image(icons->ImgRightMulti); - b->callback(b1_cb, (void *)UI_FORW); - b->clear_tab_to_focus(); - - Home = b = new HighlightButton(xpos, 0, bw, bh, (lbl) ? "Home" : 0); - b->image(icons->ImgHome); - b->callback(b1_cb, (void *)UI_HOME); - b->clear_tab_to_focus(); - - Reload = b = new HighlightButton(xpos, 0, bw, bh, (lbl) ? "Reload" : 0); - b->image(icons->ImgReload); - b->callback(b1_cb, (void *)UI_RELOAD); - b->clear_tab_to_focus(); - - Save = b = new HighlightButton(xpos, 0, bw, bh, (lbl) ? "Save" : 0); - b->image(icons->ImgSave); - b->callback(b1_cb, (void *)UI_SAVE); - b->clear_tab_to_focus(); - - Stop = b = new HighlightButton(xpos, 0, bw, bh, (lbl) ? "Stop" : 0); - b->image(icons->ImgStopMulti); - b->callback(b1_cb, (void *)UI_STOP); - b->clear_tab_to_focus(); - - Bookmarks = b = new HighlightButton(xpos, 0, bw, bh, (lbl) ? "Book" : 0); - b->image(icons->ImgBook); - b->callback(b1_cb, (void *)UI_BOOK); - b->clear_tab_to_focus(); - - Tools = b = new HighlightButton(xpos, 0, bw, bh, (lbl) ? "Tools" : 0); - b->image(icons->ImgTools); - b->callback(b1_cb, (void *)UI_TOOLS); - b->clear_tab_to_focus(); - - p1->type(PackedGroup::ALL_CHILDREN_VERTICAL); - p1->end(); - - if (prefs.show_tooltip) { - Back->tooltip("Previous page"); - Forw->tooltip("Next page"); - Home->tooltip("Go to the Home page"); - Reload->tooltip("Reload"); - Save->tooltip("Save this page"); - Stop->tooltip("Stop loading"); - Bookmarks->tooltip("View bookmarks"); - Tools->tooltip("Settings"); - } - return p1; + Back = make_button("Back", icons->ImgLeft, icons->ImgLeftIn, UI_BACK, 1); + Forw = make_button("Forw", icons->ImgRight, icons->ImgRightIn, UI_FORW); + Home = make_button("Home", icons->ImgHome, NULL, UI_HOME); + Reload = make_button("Reload", icons->ImgReload, NULL, UI_RELOAD); + Save = make_button("Save", icons->ImgSave, NULL, UI_SAVE); + Stop = make_button("Stop", icons->ImgStop, icons->ImgStopIn, UI_STOP); + Bookmarks = make_button("Book", icons->ImgBook, NULL, UI_BOOK); + Tools = make_button("Tools", icons->ImgTools, NULL, UI_TOOLS); + + Back->tooltip("Previous page"); + Forw->tooltip("Next page"); + Home->tooltip("Go to the Home page"); + Reload->tooltip("Reload"); + Save->tooltip("Save this page"); + Stop->tooltip("Stop loading"); + Bookmarks->tooltip("View bookmarks"); + Tools->tooltip("Settings"); } /* * Create the location box (Clear/Input/Search) */ -PackedGroup *UI::make_location() +void UI::make_location(int ww) { - Button *b; - PackedGroup *pg = new PackedGroup(0,0,0,0); - pg->begin(); - Clear = b = new CustHighlightButton(2,2,16,22,0); + Fl_Button *b; + + Clear = b = new CustPasteButton(p_xpos,0,16,lh,0); b->image(icons->ImgClear); b->callback(clear_cb, this); - b->clear_tab_to_focus(); + b->clear_visible_focus(); + b->box(FL_THIN_UP_BOX); + b->tooltip("Clear the URL box.\nMiddle-click to paste a URL."); + p_xpos += b->w(); - Input *i = Location = new CustInput(0,0,0,0,0); + Fl_Input *i = Location = new CustInput(p_xpos,0,ww-p_xpos-32,lh,0); i->color(CuteColor); - i->when(WHEN_ENTER_KEY); + i->when(FL_WHEN_ENTER_KEY); i->callback(location_cb, this); - i->set_click_to_focus(); + i->tooltip("Location"); + p_xpos += i->w(); - Search = b = new HighlightButton(0,0,16,22,0); + Search = b = new CustLightButton(p_xpos,0,16,lh,0); b->image(icons->ImgSearch); b->callback(search_cb, this); - b->clear_tab_to_focus(); + b->clear_visible_focus(); + b->box(FL_THIN_UP_BOX); + b->tooltip("Search the Web"); + p_xpos += b->w(); - Help = b = new HighlightButton(0,0,16,22,0); + Help = b = new CustLightButton(p_xpos,0,16,lh,0); b->image(icons->ImgHelp); b->callback(help_cb, this); - b->clear_tab_to_focus(); + b->clear_visible_focus(); + b->box(FL_THIN_UP_BOX); + b->tooltip("Help"); + p_xpos += b->w(); - pg->type(PackedGroup::ALL_CHILDREN_VERTICAL); - pg->resizable(i); - pg->end(); - - if (prefs.show_tooltip) { - Clear->tooltip("Clear the URL box.\nMiddle-click to paste a URL."); - Location->tooltip("Location"); - Search->tooltip("Search the Web"); - Help->tooltip("Help"); - } - return pg; } /* * Create the progress bars */ -PackedGroup *UI::make_progress_bars(int wide, int thin_up) +void UI::make_progress_bars(int wide, int thin_up) { - ProgBox = new PackedGroup(0,0,0,0); - ProgBox->begin(); // Images - IProg = new CustProgressBox(0,0,0,0); - IProg->box(thin_up ? THIN_UP_BOX : EMBOSSED_BOX); - IProg->labelcolor(GRAY10); + IProg = new CustProgressBox(p_xpos,p_ypos,pw,bh); + IProg->labelsize(12); + IProg->box(thin_up ? FL_THIN_UP_BOX : FL_EMBOSSED_BOX); + IProg->labelcolor(FL_GRAY_RAMP + 2); IProg->update_label(wide ? "Images\n0 of 0" : "0 of 0"); + p_xpos += pw; // Page - PProg = new CustProgressBox(0,0,0,0); - PProg->box(thin_up ? THIN_UP_BOX : EMBOSSED_BOX); - PProg->labelcolor(GRAY10); + PProg = new CustProgressBox(p_xpos,p_ypos,pw,bh); + PProg->labelsize(12); + PProg->box(thin_up ? FL_THIN_UP_BOX : FL_EMBOSSED_BOX); + PProg->labelcolor(FL_GRAY_RAMP + 2); PProg->update_label(wide ? "Page\n0.0KB" : "0.0KB"); - ProgBox->type(PackedGroup::ALL_CHILDREN_VERTICAL); - ProgBox->end(); - - return ProgBox; } /* * Create the "File" menu * Static function for File menu callbacks. */ -Widget *UI::make_filemenu_button() +Fl_Widget *UI::make_filemenu_button() { - HighlightButton *btn; - int w,h, padding; + Fl_Button *btn; + int w = 0, h = 0, padding; - FileButton = btn = new HighlightButton(0,0,0,0,"W"); + FileButton = btn = new Fl_Button(p_xpos,0,bw,bh,"W"); + btn->labeltype(FL_FREE_LABELTYPE); btn->measure_label(w, h); padding = w; btn->copy_label(PanelSize == P_tiny ? "&F" : "&File"); btn->measure_label(w,h); - if (PanelSize == P_large) - h = fh; - btn->resize(w+padding,h); + h = (PanelSize == P_tiny) ? bh : lh; + btn->size(w+padding, h); + p_xpos += btn->w(); _MSG("UI::make_filemenu_button w=%d h=%d padding=%d\n", w, h, padding); - btn->box(PanelSize == P_large ? FLAT_BOX : THIN_UP_BOX); + btn->box(FL_THIN_UP_BOX); btn->callback(filemenu_cb, this); - if (prefs.show_tooltip) - btn->tooltip("File menu"); - btn->clear_tab_to_focus(); - if (!prefs.show_filemenu && PanelSize != P_large) + btn->tooltip("File menu"); + btn->clear_visible_focus(); + if (!prefs.show_filemenu) btn->hide(); return btn; } @@ -551,216 +513,173 @@ Widget *UI::make_filemenu_button() /* * Create the control panel */ -Group *UI::make_panel(int ww) +void UI::make_panel(int ww) { - Widget *w; - Group *g1, *g2, *g3; - PackedGroup *pg; - - if (PanelSize > P_large) { - PanelSize = P_tiny; - Small_Icons = !Small_Icons; - } + Fl_Widget *w; if (Small_Icons) icons = &small_icons; else icons = &standard_icons; + pw = 70; + p_xpos = p_ypos = 0; if (PanelSize == P_tiny) { if (Small_Icons) - xpos = 0, bw = 22, bh = 22, fh = 0, lh = 22, lbl = 0; + bw = 22, bh = 22, mh = 0, lh = 22, lbl = 0; else - xpos = 0, bw = 28, bh = 28, fh = 0, lh = 28, lbl = 0; + bw = 28, bh = 28, mh = 0, lh = 28, lbl = 0; } else if (PanelSize == P_small) { if (Small_Icons) - xpos = 0, bw = 20, bh = 20, fh = 0, lh = 20, lbl = 0; + bw = 20, bh = 20, mh = 0, lh = 20, lbl = 0; else - xpos = 0, bw = 28, bh = 28, fh = 0, lh = 28, lbl = 0; + bw = 28, bh = 28, mh = 0, lh = 28, lbl = 0; } else if (PanelSize == P_medium) { if (Small_Icons) - xpos = 0, bw = 42, bh = 36, fh = 0, lh = 22, lbl = 1; - else - xpos = 0, bw = 45, bh = 45, fh = 0, lh = 28, lbl = 1; - } else { // P_large - if (Small_Icons) - xpos = 0, bw = 42, bh = 36, fh = 22, lh = 22, lbl = 1; + bw = 42, bh = 36, mh = 0, lh = 22, lbl = 1; else - xpos = 0, bw = 45, bh = 45, fh = 24, lh = 28, lbl = 1; + bw = 45, bh = 45, mh = 0, lh = 28, lbl = 1; } + nh = bh, fh = 28; sh = 20; + current(0); if (PanelSize == P_tiny) { - g1 = new Group(0,0,ww,bh); - // Toolbar - pg = make_toolbar(ww,bh); - pg->box(EMBOSSED_BOX); - g1->add(pg); - w = make_filemenu_button(); - pg->add(w); - w = make_location(); - pg->add(w); - pg->resizable(w); - w = make_progress_bars(0,1); - pg->add(w); - - g1->resizable(pg); - + NavBar = new CustGroupHorizontal(0,0,ww,nh); + NavBar->box(FL_NO_BOX); + NavBar->begin(); + make_toolbar(ww,bh); + make_filemenu_button(); + make_location(ww); + NavBar->resizable(Location); + make_progress_bars(0,1); + NavBar->box(FL_THIN_UP_FRAME); + NavBar->end(); + NavBar->rearrange(); + TopGroup->insert(*NavBar,0); } else { - g1 = new Group(0,0,ww,fh+lh+bh); - g1->begin(); - // File menu - if (PanelSize == P_large) { - g3 = new Group(0,0,ww,lh); - g3->box(FLAT_BOX); - Widget *bn = make_filemenu_button(); - g3->add(bn); - g3->add_resizable(*new InvisibleBox(bn->w(),0,ww - bn->w(),lh)); - - g2 = new Group(0,fh,ww,lh); - g2->begin(); - pg = make_location(); - pg->resize(ww,lh); - } else { - g2 = new PackedGroup(0,fh,ww,lh); - g2->type(PackedGroup::ALL_CHILDREN_VERTICAL); - g2->begin(); - make_filemenu_button(); - pg = make_location(); - } - - g2->resizable(pg); - g2->end(); + // Location + LocBar = new CustGroupHorizontal(0,0,ww,lh); + LocBar->box(FL_NO_BOX); + LocBar->begin(); + p_xpos = 0; + make_filemenu_button(); + make_location(ww); + LocBar->resizable(Location); + LocBar->end(); + LocBar->rearrange(); + TopGroup->insert(*LocBar,0); // Toolbar - g3 = new Group(0,fh+lh,ww,bh); - g3->begin(); - pg = make_toolbar(ww,bh); - //w = new InvisibleBox(0,0,0,0,"i n v i s i b l e"); - w = new InvisibleBox(0,0,0,0,0); - pg->add(w); - pg->resizable(w); - + p_ypos = 0; + NavBar = new CustGroupHorizontal(0,0,ww,bh); + NavBar->box(FL_NO_BOX); + NavBar->begin(); + make_toolbar(ww,bh); + w = new Fl_Box(p_xpos,0,ww-p_xpos-2*pw,bh); + w->box(FL_FLAT_BOX); + NavBar->resizable(w); + p_xpos = ww - 2*pw; if (PanelSize == P_small) { - w = make_progress_bars(0,0); + make_progress_bars(0,0); } else { - w = make_progress_bars(1,0); + make_progress_bars(1,0); } - pg->add(w); - - g3->resizable(pg); // Better than 'w3' and it also works - pg->box(BORDER_FRAME); - //g3->box(EMBOSSED_BOX); - g3->end(); - - g1->resizable(g3); - g1->end(); + NavBar->end(); + NavBar->rearrange(); + TopGroup->insert(*NavBar,1); } - - return g1; } /* * Create the status panel */ -Group *UI::make_status_panel(int ww) +void UI::make_status_bar(int ww, int wh) { - const int s_h = 20, bm_w = 16; - Group *g = new Group(0, 0, ww, s_h, 0); - - // Status box - Status = new Output(0, 0, ww-bm_w, s_h, 0); - Status->value(""); - Status->box(THIN_DOWN_BOX); - Status->clear_click_to_focus(); - Status->clear_tab_to_focus(); - Status->color(GRAY80); - g->add(Status); - //Status->throw_focus(); - - // Bug Meter - BugMeter = new HighlightButton(ww-bm_w,0,bm_w,s_h,0); - BugMeter->image(icons->ImgMeterOK); - BugMeter->box(THIN_DOWN_BOX); - BugMeter->align(ALIGN_INSIDE|ALIGN_CLIP|ALIGN_LEFT); - if (prefs.show_tooltip) - BugMeter->tooltip("Show HTML bugs\n(right-click for menu)"); - BugMeter->callback(bugmeter_cb, this); - BugMeter->clear_tab_to_focus(); - g->add(BugMeter); - - g->resizable(Status); - return g; + const int bm_w = 20; + StatusBar = new CustGroupHorizontal(0, wh-sh, ww, sh); + StatusBar->box(FL_NO_BOX); + + // Status box + StatusOutput = new Fl_Output(0, wh-sh, ww-bm_w, sh); + StatusOutput->value("http://www.dillo.org"); + StatusOutput->labelsize(8); + StatusOutput->box(FL_THIN_DOWN_BOX); + StatusOutput->clear_visible_focus(); + StatusOutput->color(FL_GRAY_RAMP + 18); + + // Bug Meter + BugMeter = new CustLightButton(ww-bm_w,wh-sh,bm_w,sh); + BugMeter->image(icons->ImgMeterOK); + BugMeter->box(FL_THIN_DOWN_BOX); + BugMeter->align(FL_ALIGN_INSIDE | FL_ALIGN_TEXT_NEXT_TO_IMAGE); + BugMeter->tooltip("Show HTML bugs\n(right-click for menu)"); + BugMeter->callback(bugmeter_cb, this); + BugMeter->clear_visible_focus(); + + StatusBar->end(); + StatusBar->resizable(StatusOutput); + StatusBar->rearrange(); } /* * User Interface constructor */ -UI::UI(int x, int y, int ww, int wh, const char* label, const UI *cur_ui) : - Group(x, y, ww, wh, label) +UI::UI(int x, int y, int ui_w, int ui_h, const char* label, const UI *cur_ui) : + CustGroupVertical(x, y, ui_w, ui_h, label) { - PointerOnLink = FALSE; + LocBar = NavBar = StatusBar = NULL; Tabs = NULL; TabTooltip = NULL; - TopGroup = new PackedGroup(0, 0, ww, wh); - add(TopGroup); - resizable(TopGroup); - set_flag(RAW_LABEL); + TopGroup = this; + TopGroup->box(FL_NO_BOX); + clear_flag(SHORTCUT_LABEL); + PanelTemporary = false; if (cur_ui) { PanelSize = cur_ui->PanelSize; CuteColor = cur_ui->CuteColor; Small_Icons = cur_ui->Small_Icons; - if (cur_ui->Panelmode == UI_HIDDEN || - cur_ui->Panelmode == UI_TEMPORARILY_SHOW_PANELS) - Panelmode = UI_HIDDEN; - else - Panelmode = UI_NORMAL; + Panelmode = cur_ui->Panelmode; } else { // Set some default values - //PanelSize = P_tiny, CuteColor = 26, Small_Icons = 0; PanelSize = prefs.panel_size; Small_Icons = prefs.small_icons; CuteColor = 206; - Panelmode = (UIPanelmode) prefs.fullwindow_start; + Panelmode = (prefs.fullwindow_start) ? UI_HIDDEN : UI_NORMAL; } // Control panel - Panel = make_panel(ww); - TopGroup->add(Panel); - - // Render area - Main = new Widget(0,0,1,1,"Welcome..."); - Main->box(FLAT_BOX); - Main->color(GRAY15); - Main->labelfont(HELVETICA_BOLD_ITALIC); - Main->labelsize(36); - Main->labeltype(SHADOW_LABEL); - Main->labelcolor(WHITE); - TopGroup->add(Main); - TopGroup->resizable(Main); - MainIdx = TopGroup->find(Main); - - // Find text bar - findbar = new Findbar(ww, 28); - TopGroup->add(findbar); - - // Status Panel - StatusPanel = make_status_panel(ww); - TopGroup->add(StatusPanel); - - // Make the full screen button (to be attached to the viewport later) - // TODO: attach to the viewport - //FullScreen = new HighlightButton(0,0,15,15); - //FullScreen->image(ImgFullScreenOn); - //FullScreen->tooltip("Hide Controls"); - //FullScreen->callback(fullscreen_cb, this); + TopGroup->begin(); + make_panel(ui_w); + + // Render area + Main = new Fl_Group(0,0,0,0,"Welcome..."); // size is set by rearrange() + Main->align(FL_ALIGN_CENTER|FL_ALIGN_INSIDE); + Main->box(FL_FLAT_BOX); + Main->color(FL_GRAY_RAMP + 3); + Main->labelfont(FL_HELVETICA_BOLD_ITALIC); + Main->labelsize(36); + Main->labeltype(FL_SHADOW_LABEL); + Main->labelcolor(FL_WHITE); + TopGroup->add(Main); + TopGroup->resizable(Main); + MainIdx = TopGroup->find(Main); + + // Find text bar + FindBar = new Findbar(ui_w, fh); + TopGroup->add(FindBar); + + // Status Panel + make_status_bar(ui_w, ui_h); + TopGroup->add(StatusBar); + TopGroup->end(); + TopGroup->rearrange(); customize(0); - if (Panelmode) { - Panel->hide(); - StatusPanel->hide(); + if (Panelmode == UI_HIDDEN) { + panels_toggle(); } } @@ -778,18 +697,27 @@ UI::~UI() */ int UI::handle(int event) { - _MSG("UI::handle event=%d (%d,%d)\n", event, event_x(), event_y()); - _MSG("Panel->h()=%d Main->h()=%d\n", Panel->h() , Main->h()); + _MSG("UI::handle event=%s\n", fl_eventnames[event]); int ret = 0; + if (event == FL_KEYBOARD) { + /* WORKAROUND: remove the Panel's fltk-tooltip. + * Although the expose event is delivered, it has an offset. This + * extra call avoids the lingering tooltip. */ + if (!Fl::event_inside(Main) && + (Fl::event_inside((Fl_Widget*)tabs()) || + Fl::event_inside(NavBar) || + (LocBar && Fl::event_inside(LocBar)) || + (StatusBar && Fl::event_inside(StatusBar)))) + window()->damage(FL_DAMAGE_EXPOSE,0,0,1,1); - if (event == KEY) { return 0; // Receive as shortcut - } else if (event == SHORTCUT) { + } else if (event == FL_SHORTCUT) { KeysCommand_t cmd = Keys::getKeyCmd(); if (cmd == KEYS_NOP) { // Do nothing } else if (cmd == KEYS_SCREEN_UP || cmd == KEYS_SCREEN_DOWN || + cmd == KEYS_SCREEN_LEFT || cmd == KEYS_SCREEN_RIGHT || cmd == KEYS_LINE_UP || cmd == KEYS_LINE_DOWN || cmd == KEYS_LEFT || cmd == KEYS_RIGHT || cmd == KEYS_TOP || cmd == KEYS_BOTTOM) { @@ -805,26 +733,22 @@ int UI::handle(int event) a_UIcmd_book(a_UIcmd_get_bw_by_widget(this)); ret = 1; } else if (cmd == KEYS_FIND) { - set_findbar_visibility(1); + findbar_toggle(1); ret = 1; } else if (cmd == KEYS_WEBSEARCH) { a_UIcmd_search_dialog(a_UIcmd_get_bw_by_widget(this)); ret = 1; } else if (cmd == KEYS_GOTO) { + if (Panelmode == UI_HIDDEN) { + panels_toggle(); + temporaryPanels(true); + } focus_location(); ret = 1; - } else if (cmd == KEYS_NEW_TAB) { - a_UIcmd_open_url_nt(a_UIcmd_get_bw_by_widget(this), NULL, 1); - ret = 1; - } else if (cmd == KEYS_CLOSE_TAB) { - a_UIcmd_close_bw(a_UIcmd_get_bw_by_widget(this)); - ret = 1; - } else if (cmd == KEYS_HIDE_PANELS && - get_panelmode() == UI_TEMPORARILY_SHOW_PANELS) { - set_panelmode(UI_HIDDEN); - ret = 1; - } else if (cmd == KEYS_NEW_WINDOW) { - a_UIcmd_browser_window_new(w(),h(),0,a_UIcmd_get_bw_by_widget(this)); + } else if (cmd == KEYS_HIDE_PANELS) { + /* Hide findbar if present, hide panels if not */ + (FindBar->visible()) ? findbar_toggle(0) : panels_toggle(); + temporaryPanels(false); ret = 1; } else if (cmd == KEYS_OPEN) { a_UIcmd_open_file(a_UIcmd_get_bw_by_widget(this)); @@ -841,40 +765,26 @@ int UI::handle(int event) } else if (cmd == KEYS_SAVE) { a_UIcmd_save(a_UIcmd_get_bw_by_widget(this)); ret = 1; - } else if (cmd == KEYS_FULLSCREEN) { - panelmode_cb_i(); - ret = 1; } else if (cmd == KEYS_FILE_MENU) { a_UIcmd_file_popup(a_UIcmd_get_bw_by_widget(this), FileButton); ret = 1; - } else if (cmd == KEYS_CLOSE_ALL) { - a_Timeout_add(0.0, a_UIcmd_close_all_bw, NULL); - ret = 1; } - } else if (event == PUSH) { - if (prefs.middle_click_drags_page == 0 && - event_button() == MiddleButton && - !a_UIcmd_pointer_on_link(a_UIcmd_get_bw_by_widget(this))) { - if (Main->Rectangle::contains (event_x (), event_y ())) { - /* Offer the event to Main's children (form widgets) */ - int save_x = e_x, save_y = e_y; - - e_x -= Main->x(); - e_y -= Main->y(); - ret = ((Group *)Main)->Group::handle(event); - e_x = save_x; - e_y = save_y; - } - if (!ret) { - /* middle click was not on a link or a form widget */ - paste_url(); - ret = 1; - } + } else if (event == FL_RELEASE) { + if (Fl::event_button() == FL_MIDDLE_MOUSE && + prefs.middle_click_drags_page == 0) { + /* nobody claimed the event; try paste */ + paste_url(); + ret = 1; } } if (!ret) { - ret = Group::handle(event); + ret = Fl_Group::handle(event); + } + if (!ret && event == FL_PUSH && !prefs.middle_click_drags_page) { + /* nobody claimed FL_PUSH: ask for FL_RELEASE, + * which is necessary for middle-click paste URL) */ + ret = 1; } return ret; @@ -899,9 +809,7 @@ const char *UI::get_location() void UI::set_location(const char *str) { if (!str) str = ""; - // This text() call clears fl_pending_callback, avoiding - // an extra location_cb() call. - Location->text(str); + Location->value(str); Location->position(strlen(str)); } @@ -911,9 +819,6 @@ void UI::set_location(const char *str) */ void UI::focus_location() { - if (get_panelmode() == UI_HIDDEN) { - set_panelmode(UI_TEMPORARILY_SHOW_PANELS); - } Location->take_focus(); // Make text selected when already focused. Location->position(Location->size(), 0); @@ -932,7 +837,7 @@ void UI::focus_main() */ void UI::set_status(const char *str) { - Status->value(str); + StatusOutput->value(str); } /* @@ -985,7 +890,7 @@ void UI::set_img_prog(int n_img, int t_img, int cmd) void UI::set_bug_prog(int n_bug) { char str[32]; - int new_w = 16; + int new_w = 20; if (n_bug == 0) { BugMeter->image(icons->ImgMeterOK); @@ -995,12 +900,10 @@ void UI::set_bug_prog(int n_bug) BugMeter->image(icons->ImgMeterBug); snprintf(str, 32, "%d", n_bug); BugMeter->copy_label(str); - BugMeter->redraw_label(); - new_w = strlen(str)*8 + 20; + new_w = strlen(str)*9 + 20; } - Status->resize(0,0,StatusPanel->w()-new_w,Status->h()); - BugMeter->resize(StatusPanel->w()-new_w, 0, new_w, BugMeter->h()); - StatusPanel->init_sizes(); + BugMeter->size(new_w, BugMeter->h()); + StatusBar->rearrange(); } /* @@ -1034,25 +937,40 @@ void UI::customize(int flags) Search->hide(); if ( !prefs.show_help ) Help->hide(); - if ( !prefs.show_progress_box ) - ProgBox->hide(); + if ( !prefs.show_progress_box ) { + IProg->hide(); + PProg->hide(); + } + + if (NavBar) + NavBar->rearrange(); + if (LocBar) + LocBar->rearrange(); } /* * On-the-fly panel style change */ -void UI::panel_cb_i() +void UI::change_panel(int new_size, int small_icons) { - Group *NewPanel; - - // Create a new Panel - ++PanelSize; - NewPanel = make_panel(TopGroup->w()); - TopGroup->replace(*Panel, *NewPanel); - delete(Panel); - Panel = NewPanel; + // Remove current panel's bars + init_sizes(); + TopGroup->remove(LocBar); + Fl::delete_widget(LocBar); + TopGroup->remove(NavBar); + Fl::delete_widget(NavBar); + LocBar = NavBar = NULL; + + // Set internal vars for panel size + PanelSize = new_size; + Small_Icons = small_icons; + + // make a new panel + make_panel(TopGroup->w()); customize(0); + a_UIcmd_set_buttons_sens(a_UIcmd_get_bw_by_widget(this)); + TopGroup->rearrange(); Location->take_focus(); } @@ -1069,88 +987,21 @@ void UI::color_change_cb_i() MSG("Location color %d\n", CuteColor); Location->color(CuteColor); Location->redraw(); - HighlightButton::default_style->highlight_color(CuteColor); -} - -/* - * Set or remove the Panelmode flag and update the UI accordingly - */ -void UI::set_panelmode(UIPanelmode mode) -{ - if (mode == UI_HIDDEN) { - Panel->hide(); - StatusPanel->hide(); - } else { - /* UI_NORMAL or UI_TEMPORARILY_SHOW_PANELS */ - Panel->show(); - StatusPanel->show(); - } - Panelmode = mode; -} - -/* - * Get the value of the panelmode flag - */ -UIPanelmode UI::get_panelmode() -{ - return Panelmode; -} - -/* - * Toggle the Control Panel out of the way - */ -void UI::panelmode_cb_i() -{ - set_panelmode((UIPanelmode) !Panelmode); } /* * Set 'nw' as the main render area widget */ -void UI::set_render_layout(Widget &nw) +void UI::set_render_layout(Fl_Group *nw) { - // BUG: replace() is not working as it should. - // In our case, replacing the rendering area leaves the vertical - // scrollbar without events. - // - // We'll use a workaround in a_UIcmd_browser_window_new() instead. - TopGroup->replace(MainIdx, nw); - delete(Main); - Main = &nw; - //TopGroup->box(DOWN_BOX); - //TopGroup->box(BORDER_FRAME); - TopGroup->resizable(TopGroup->child(MainIdx)); -} + // Resize layout widget to current height + nw->resize(0,Main->y(),Main->w(),Main->h()); -/* - * Set the tab title - */ -void UI::set_tab_title(const char *label) -{ - char title[128]; - - dReturn_if_fail(label != NULL); - - if (*label) { - // Make a label for this tab - size_t tab_chars = 18, label_len = strlen(label); - - if (label_len > tab_chars) - tab_chars = a_Utf8_end_of_char(label, tab_chars - 1) + 1; - snprintf(title, tab_chars + 1, "%s", label); - if (label_len > tab_chars) - snprintf(title + tab_chars, 4, "..."); - // Avoid unnecessary redraws - if (strcmp(this->label(), title)) { - this->copy_label(title); - this->redraw_label(); - } - - // Disabled because of a bug in fltk::Tabgroup - //dFree(TabTooltip); - //TabTooltip = dStrdup(label); - //this->tooltip(TabTooltip); - } + TopGroup->insert(*nw, Main); + remove(Main); + delete(Main); + Main = nw; + TopGroup->resizable(Main); } /* @@ -1161,15 +1012,12 @@ void UI::button_set_sens(UIButton btn, int sens) switch (btn) { case UI_BACK: (sens) ? Back->activate() : Back->deactivate(); - Back->redraw(DAMAGE_HIGHLIGHT); break; case UI_FORW: (sens) ? Forw->activate() : Forw->deactivate(); - Forw->redraw(DAMAGE_HIGHLIGHT); break; case UI_STOP: (sens) ? Stop->activate() : Stop->deactivate(); - Stop->redraw(DAMAGE_HIGHLIGHT); break; default: break; @@ -1181,17 +1029,63 @@ void UI::button_set_sens(UIButton btn, int sens) */ void UI::paste_url() { - paste(*Clear, false); + Fl::paste(*Clear, false); } /* - * Shows or hides the findbar of this window + * Adjust space for the findbar (if necessary) and show or remove it */ -void UI::set_findbar_visibility(bool visible) +void UI::findbar_toggle(bool add) { - if (visible) { - findbar->show(); + /* WORKAROUND: + * This is tricky: As fltk-1.3 resizes hidden widgets (which it + * doesn't resize when visible!). We need to set the size to (0,0) to + * get the desired behaviour. + * (STR#2639 in FLTK bug tracker). + */ + + if (add) { + if (!FindBar->visible()) + FindBar->size(w(), fh); + FindBar->show(); } else { - findbar->hide(); + // hide + FindBar->size(0,0); + FindBar->hide(); + // reset state + a_UIcmd_findtext_reset(a_UIcmd_get_bw_by_widget(this)); + // focus main area + focus_main(); + } + TopGroup->rearrange(); +} + +/* + * Make panels disappear growing the render area. + * WORKAROUND: here we avoid hidden widgets resize by setting their + * size to (0,0) while hidden. + * (Already reported to FLTK team) + */ +void UI::panels_toggle() +{ + int hide = StatusBar->visible(); + + // hide/show panels + init_sizes(); + if (LocBar) { + hide ? LocBar->size(0,0) : LocBar->size(w(),lh); + hide ? LocBar->hide() : LocBar->show(); } + if (NavBar) { + hide ? NavBar->size(0,0) : NavBar->size(w(),nh); + hide ? NavBar->hide() : NavBar->show(); + } + if (StatusBar) { + hide ? StatusBar->size(0,0) : StatusBar->size(w(),sh);; + hide ? StatusBar->hide() : StatusBar->show();; + StatusBar->rearrange(); + } + + TopGroup->rearrange(); + Panelmode = (hide) ? UI_HIDDEN : UI_NORMAL; } @@ -3,16 +3,13 @@ // UI for dillo -------------------------------------------------------------- -#include <fltk/Window.h> -#include <fltk/Widget.h> -#include <fltk/Button.h> -#include <fltk/Input.h> -#include <fltk/PackedGroup.h> -#include <fltk/Output.h> -#include <fltk/Image.h> -#include <fltk/MultiImage.h> -#include <fltk/MenuBuild.h> -#include <fltk/TabGroup.h> +#include <FL/Fl_Window.H> +#include <FL/Fl_Widget.H> +#include <FL/Fl_Button.H> +#include <FL/Fl_Input.H> +#include <FL/Fl_Output.H> +#include <FL/Fl_Image.H> +#include <FL/Fl_Tabs.H> #include "findbar.hh" @@ -31,47 +28,153 @@ typedef enum { typedef enum { UI_NORMAL = 0, /* make sure it's compatible with bool */ - UI_HIDDEN = 1, - UI_TEMPORARILY_SHOW_PANELS + UI_HIDDEN = 1 } UIPanelmode; + +// Min size to fit the full UI +#define UI_MIN_W 600 +#define UI_MIN_H 200 + // Private classes class CustProgressBox; -class CustTabGroup; +class CustTabs; + + +// Class definitions --------------------------------------------------------- +/* + * Used to reposition group's widgets when some of them are hidden. + * All children get the height of the group but retain their original width. + * The resizable child get's the remaining space. + */ +class CustGroupHorizontal : public Fl_Group { + Fl_Widget *rsz; +public: + CustGroupHorizontal(int x,int y,int w ,int h,const char *l = 0) : + Fl_Group(x,y,w,h,l) { }; + + void rearrange() { + Fl_Widget*const* a = array(); + int sum = 0, _x = x(); + int children_ = children(); + + if (resizable()) + rsz = resizable(); + + for (int i=0; i < children_; i++) + if (a[i] != resizable() && a[i]->visible()) + sum += a[i]->w(); + + for (int i=0; i < children_; i++) { + if (a[i] == rsz) { + if (w() > sum) { + a[i]->resize(_x, y(), w()-sum, h()); + if (!resizable()) + resizable(rsz); + } else { + /* widgets overflow width */ + a[i]->resize(_x, y(), 0, h()); + resizable(NULL); + } + } else { + a[i]->resize(_x, y(), a[i]->w(), h()); + } + if (a[i]->visible()) + _x += a[i]->w(); + } + init_sizes(); + redraw(); + } +}; + +class CustGroupVertical : public Fl_Group { +public: + CustGroupVertical(int x,int y,int w ,int h,const char *l = 0) : + Fl_Group(x,y,w,h,l) { }; + + void rearrange() { + Fl_Widget*const* a = array(); + int sum = 0, _y = y(); + int children_ = children(); + + for (int i=0; i < children_; i++) + if (a[i] != resizable() && a[i]->visible()) + sum += a[i]->h(); + + for (int i=0; i < children_; i++) { + if (a[i] == resizable()) { + a[i]->resize(x(), _y, w(), h() - sum); + } else { + a[i]->resize(x(), _y, w(), a[i]->h()); + } + if (a[i]->visible()) + _y += a[i]->h(); + } + init_sizes(); + redraw(); + } +}; + +/* + * A button that highlights on mouse over + */ +class CustLightButton : public Fl_Button { + Fl_Color norm_color, light_color; +public: + CustLightButton(int x, int y, int w, int h, const char *l=0) : + Fl_Button(x,y,w,h,l) { norm_color = color(); light_color = 51; }; + virtual int handle(int e) + { + if (active()) { + if (e == FL_ENTER) { + color(light_color); // {17,26,51} + redraw(); + } else if (e == FL_LEAVE || e == FL_RELEASE || e == FL_HIDE) { + color(norm_color); + redraw(); + } + } else if (e == FL_DEACTIVATE && color() != norm_color) { + color(norm_color); + redraw(); + } + return Fl_Button::handle(e); + } + void hl_color(Fl_Color col) { light_color = col; }; +}; // // UI class definition ------------------------------------------------------- // -class UI : public fltk::Group { - CustTabGroup *Tabs; +class UI : public CustGroupVertical { + CustTabs *Tabs; char *TabTooltip; - fltk::Group *TopGroup; - fltk::Button *Back, *Forw, *Home, *Reload, *Save, *Stop, *Bookmarks, *Tools, - *Clear, *Search, *Help, *FullScreen, *BugMeter, *FileButton; - fltk::Input *Location; - fltk::PackedGroup *ProgBox; + CustGroupVertical *TopGroup; + Fl_Button *Back, *Forw, *Home, *Reload, *Save, *Stop, *Bookmarks, *Tools, + *Clear, *Search, *Help, *BugMeter, *FileButton; + CustGroupHorizontal *LocBar, *NavBar, *StatusBar; + Fl_Input *Location; CustProgressBox *PProg, *IProg; - fltk::Group *Panel, *StatusPanel; - fltk::Widget *Main; - fltk::Output *Status; + Fl_Group *Panel, *Main; + Fl_Output *StatusOutput; + Findbar *FindBar; int MainIdx; // Panel customization variables int PanelSize, CuteColor, Small_Icons; - int xpos, bw, bh, fh, lh, lbl; + int p_xpos, p_ypos, bw, bh, mh, lh, nh, fh, sh, pw, lbl; + bool PanelTemporary; UIPanelmode Panelmode; - Findbar *findbar; - int PointerOnLink; - - fltk::PackedGroup *make_toolbar(int tw, int th); - fltk::PackedGroup *make_location(); - fltk::PackedGroup *make_progress_bars(int wide, int thin_up); + Fl_Button *make_button(const char *label, Fl_Image *img, + Fl_Image*deimg, int b_n, int start = 0); + void make_toolbar(int tw, int th); + void make_location(int ww); + void make_progress_bars(int wide, int thin_up); void make_menubar(int x, int y, int w, int h); - fltk::Widget *make_filemenu_button(); - fltk::Group *make_panel(int ww); - fltk::Group *make_status_panel(int ww); + Fl_Widget *make_filemenu_button(); + void make_panel(int ww); + void make_status_bar(int ww, int wh); public: @@ -89,27 +192,24 @@ public: void set_page_prog(size_t nbytes, int cmd); void set_img_prog(int n_img, int t_img, int cmd); void set_bug_prog(int n_bug); - void set_render_layout(Widget &nw); - void set_tab_title(const char *label); + void set_render_layout(Fl_Group *nw); void customize(int flags); void button_set_sens(UIButton btn, int sens); void paste_url(); - void set_panelmode(UIPanelmode mode); - UIPanelmode get_panelmode(); - void set_findbar_visibility(bool visible); - Widget *fullscreen_button() { return FullScreen; } - void fullscreen_toggle() { FullScreen->do_callback(); } + int get_panelsize() { return PanelSize; } + int get_smallicons() { return Small_Icons; } + void change_panel(int new_size, int small_icons); + void findbar_toggle(bool add); + void panels_toggle(); - CustTabGroup *tabs() { return Tabs; } - void tabs(CustTabGroup *tabs) { Tabs = tabs; } - int pointerOnLink() { return PointerOnLink; } - void pointerOnLink(int flag) { PointerOnLink = flag; } + CustTabs *tabs() { return Tabs; } + void tabs(CustTabs *tabs) { Tabs = tabs; } + bool temporaryPanels() { return PanelTemporary; } + void temporaryPanels(bool val) { PanelTemporary = val; } // Hooks to method callbacks - void panel_cb_i(); void color_change_cb_i(); void toggle_cb_i(); - void panelmode_cb_i(); }; #endif // __UI_HH__ diff --git a/src/uicmd.cc b/src/uicmd.cc index 5573db11..38225047 100644 --- a/src/uicmd.cc +++ b/src/uicmd.cc @@ -1,7 +1,7 @@ /* * File: uicmd.cc * - * Copyright (C) 2005-2007 Jorge Arellano Cid <jcid@dillo.org> + * Copyright (C) 2005-2011 Jorge Arellano Cid <jcid@dillo.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,11 +16,14 @@ #include <stdarg.h> #include <math.h> /* for rint */ -#include <fltk/draw.h> -#include <fltk/damage.h> -#include <fltk/Widget.h> -#include <fltk/TabGroup.h> -#include <fltk/Tooltip.h> +#include <FL/Fl.H> +#include <FL/Fl_Widget.H> +#include <FL/Fl_Double_Window.H> +#include <FL/Fl_Wizard.H> +#include <FL/Fl_Box.H> +#include <FL/Fl_Pack.H> +#include <FL/Fl_Scroll.H> +#include <FL/names.h> #include "paths.hh" #include "keys.hh" @@ -35,12 +38,14 @@ #include "history.h" #include "msg.h" #include "prefs.h" +#include "misc.h" #include "dw/fltkviewport.hh" #include "nav.h" -#define DEFAULT_TAB_LABEL "Dillo" +//#define DEFAULT_TAB_LABEL "-.untitled.-" +#define DEFAULT_TAB_LABEL "-.new.-" // Handy macro #define BW2UI(bw) ((UI*)((bw)->ui)) @@ -56,316 +61,384 @@ using namespace dw::fltk; */ static char *save_dir = NULL; -using namespace fltk; - +/* + * Forward declarations + */ +static BrowserWindow *UIcmd_tab_new(CustTabs *tabs, UI *old_ui, int focus); +static void close_tab_btn_cb (Fl_Widget *w, void *cb_data); //---------------------------------------------------------------------------- -#define BTN_W 25 -#define BTN_H 20 -static int btn_x; +/* + * CustTabs --------------------------------------------------------------- + */ /* - * Adds a tab-close button at the rightmost part + * stores the respective UI pointer */ -class CustShrinkTabPager : public TabGroupPager { - bool btn_hl; - TabGroup *tg; +class CustTabButton : public Fl_Button { + UI *ui_; public: - int update_positions( - TabGroup *g, int numchildren, int &selected, - int &cumulated_width, int &available_width, - int *tab_pos, int *tab_width); - virtual int which(TabGroup* g, int m_x,int m_y); - virtual TabGroupPager* clone() const; - virtual const char * mode_name() const {return "Shrink";} - virtual int id() const {return PAGER_SHRINK;} - virtual int available_width(TabGroup *g) const; - virtual bool draw_tabs(TabGroup* g, int selected, int* tab_pos, - int* tab_width) { - if (!tg) tg = g; - if (g->children() > 1) { - fltk::Rectangle r(btn_x,0,BTN_W,BTN_H); - setcolor(btn_hl ? 206 : GRAY75); - fillrect(r); - if (btn_hl) { - setcolor(WHITE); - strokerect(r); - } - setcolor(GRAY10); - //fltk::setfont(fltk::getfont()->bold(), fltk::getsize()); - r.h(r.h()-2); - drawtext("X", r, ALIGN_CENTER); - return false; - } else { - // WORKAROUND: for http://fltk.org/str.php?L2062 - // By returning true we avoid a call to TabGroup::draw_tab() - // in TabGroup::draw() in case we don't show the tabs. - return true; - } - } + CustTabButton (int x,int y,int w,int h, const char* label = 0) : + Fl_Button (x,y,w,h,label) { ui_ = NULL; }; + void ui(UI *pui) { ui_ = pui; } + UI *ui(void) { return ui_; } +}; - void btn_highlight(bool flag) { - if (btn_hl != flag) { - btn_hl = flag; - if (tg) - tg->redraw(DAMAGE_VALUE); - } - }; - bool btn_highlight() { return btn_hl; }; +/* + * Allows fine control of the tabbed interface + */ +class CustTabs : public Fl_Group { + int tab_w, tab_h, ctab_h, btn_w, ctl_w; + Fl_Wizard *Wizard; + Fl_Scroll *Scroll; + Fl_Pack *Pack; + Fl_Group *Control; + CustLightButton *CloseBtn; + int tabcolor_inactive, tabcolor_active; - CustShrinkTabPager() : TabGroupPager() { - noclip(true); - btn_hl = false; - tg = NULL; - } + void update_pack_offset(void); + void resize(int x, int y, int w, int h) + { Fl_Group::resize(x,y,w,h); update_pack_offset(); } + int get_btn_idx(UI *ui); + +public: + CustTabs (int ww, int wh, int th, const char *lbl=0) : + Fl_Group(0,0,ww,th,lbl) { + Pack = NULL; + tab_w = 50, tab_h = th, ctab_h = 1, btn_w = 20, ctl_w = 1*btn_w+2; + tabcolor_active = 0x87aca700; tabcolor_inactive = 0xb7beb700; + resize(0,0,ww,ctab_h); + /* tab buttons go inside a pack within a scroll */ + Scroll = new Fl_Scroll(0,0,ww-ctl_w,ctab_h); + Scroll->type(0); /* no scrollbars */ + Scroll->box(FL_NO_BOX); + Pack = new Fl_Pack(0,0,ww-ctl_w,tab_h); + Pack->type(Fl_Pack::HORIZONTAL); + Pack->box(FL_NO_BOX); //FL_THIN_DOWN_FRAME + Pack->end(); + Scroll->end(); + resizable(Scroll); + + /* control buttons go inside a group */ + Control = new Fl_Group(ww-ctl_w,0,ctl_w,ctab_h); + CloseBtn = new CustLightButton(ww-ctl_w+2,0,btn_w,ctab_h, "X"); + CloseBtn->box(FL_THIN_UP_BOX); + CloseBtn->labelcolor(0x00641000); + CloseBtn->hl_color(FL_WHITE); + CloseBtn->clear_visible_focus(); + CloseBtn->tooltip(prefs.right_click_closes_tab ? + "Close current tab.\nor Right-click tab label to close." : + "Close current tab.\nor Middle-click tab label to close."); + CloseBtn->callback(close_tab_btn_cb, this); + CloseBtn->hide(); + Control->end(); + + box(FL_FLAT_BOX); + end(); + + Wizard = new Fl_Wizard(0,ctab_h,ww,wh-ctab_h); + Wizard->box(FL_NO_BOX); + Wizard->end(); + }; + int handle(int e); + UI *add_new_tab(UI *old_ui, int focus); + void remove_tab(UI *ui); + Fl_Wizard *wizard(void) { return Wizard; } + int num_tabs() { return (Pack ? Pack->children() : 0); } + void switch_tab(CustTabButton *cbtn); + void prev_tab(void); + void next_tab(void); + void set_tab_label(UI *ui, const char *title); }; -int CustShrinkTabPager::available_width(TabGroup *g) const +/* + * Callback for mouse click + */ +static void tab_btn_cb (Fl_Widget *w, void *cb_data) { - _MSG("CustShrinkTabPager::available_width\n"); - int w = MAX (g->w() - this->slope()-1 - BTN_W, 0); - btn_x = w + 6; - return w; + CustTabButton *btn = (CustTabButton*) w; + CustTabs *tabs = (CustTabs*) cb_data; + int b = Fl::event_button(); + + if (b == FL_LEFT_MOUSE) { + tabs->switch_tab(btn); + } else if ((b == FL_RIGHT_MOUSE && prefs.right_click_closes_tab) || + (b == FL_MIDDLE_MOUSE && !prefs.right_click_closes_tab)) { + // TODO: just an example, not necessarily final + a_UIcmd_close_bw(a_UIcmd_get_bw_by_widget(btn->ui())); + } } -int CustShrinkTabPager::which(TabGroup* g, int event_x,int event_y) +/* + * Callback for the close-tab button + */ +static void close_tab_btn_cb (Fl_Widget *, void *cb_data) { - int H = g->tab_height(); - if (!H) return -1; - if (H < 0) { - if (event_y > g->h() || event_y < g->h()+H) return -1; - } else { - if (event_y > H || event_y < 0) return -1; + CustTabs *tabs = (CustTabs*) cb_data; + int b = Fl::event_button(); + + if (b == FL_LEFT_MOUSE) { + a_UIcmd_close_bw(a_UIcmd_get_bw_by_widget(tabs->wizard()->value())); } - if (event_x < 0) return -1; - int p[128], w[128]; - int selected = g->tab_positions(p, w); - int d = (event_y-(H>=0?0:g->h()))*slope()/H; - for (int i=0; i<g->children(); i++) { - if (event_x < p[i+1]+(i<selected ? slope() - d : d)) return i; +} + +int CustTabs::handle(int e) +{ + int ret = 0; + + _MSG("CustTabs::handle e=%s\n", fl_eventnames[e]); + if (e == FL_KEYBOARD) { + return 0; // Receive as shortcut + } else if (e == FL_SHORTCUT) { + UI *ui = (UI*)wizard()->value(); + BrowserWindow *bw = a_UIcmd_get_bw_by_widget(ui); + KeysCommand_t cmd = Keys::getKeyCmd(); + if (cmd == KEYS_NOP) { + // Do nothing + _MSG("CustTabs::handle KEYS_NOP\n"); + } else if (cmd == KEYS_NEW_TAB) { + a_UIcmd_open_url_nt(bw, NULL, 1); + ret = 1; + } else if (cmd == KEYS_CLOSE_TAB) { + a_UIcmd_close_bw(bw); + ret = 1; + } else if (cmd == KEYS_LEFT_TAB) { + prev_tab(); + ret = 1; + } else if (cmd == KEYS_RIGHT_TAB) { + next_tab(); + ret = 1; + } else if (cmd == KEYS_NEW_WINDOW) { + a_UIcmd_open_url_nw(bw, NULL); + ret = 1; + } else if (cmd == KEYS_CLOSE_ALL) { + a_Timeout_add(0.0, a_UIcmd_close_all_bw, NULL); + ret = 1; + } } - return -1; + + return (ret) ? ret : Fl_Group::handle(e); } /* - * Prevents tabs from going over the close-tab button. - * Modified from fltk-2.0.x-r6525. + * Create a new tab with its own UI */ -int CustShrinkTabPager::update_positions( - TabGroup *g, int numchildren, int &selected, - int &cumulated_width, int &available_width, - int *tab_pos, int *tab_width) +UI *CustTabs::add_new_tab(UI *old_ui, int focus) { - available_width-=BTN_W; - - // uh oh, they are too big, we must move them: - // special case when the selected tab itself is too big, make it fill - // cumulated_width: - int i; + if (num_tabs() == 1) { + // Show tabbar + ctab_h = tab_h; + Wizard->resize(0,ctab_h,Wizard->w(),window()->h()-ctab_h); + resize(0,0,window()->w(),ctab_h); // tabbar + CloseBtn->show(); + {int w = 0, h; Pack->child(0)->measure_label(w, h); + Pack->child(0)->size(w+14,ctab_h);} + Pack->child(0)->show(); // first tab button + window()->init_sizes(); + } - if (tab_width[selected] >= available_width) { - tab_width[selected] = available_width; - for (i = 0; i <= selected; i++) - tab_pos[i] = 0; - for (i = selected + 1; i <= numchildren; i++) - tab_pos[i] = available_width; - return selected; + /* The UI is constructed in a comfortable fitting size, and then resized + * so FLTK doesn't get confused later with even smaller dimensions! */ + current(0); + UI *new_ui = new UI(0,0,UI_MIN_W,UI_MIN_H,"Dillo:",old_ui); + new_ui->resize(0,ctab_h,Wizard->w(),Wizard->h()); + new_ui->tabs(this); + Wizard->add(new_ui); + new_ui->show(); + + CustTabButton *btn = new CustTabButton(num_tabs()*tab_w,0,tab_w,ctab_h); + btn->align(FL_ALIGN_INSIDE); + btn->labelsize(btn->labelsize()-2); + btn->copy_label(DEFAULT_TAB_LABEL); + btn->clear_visible_focus(); + btn->box(FL_GTK_THIN_UP_BOX); + btn->color(focus ? tabcolor_active : tabcolor_inactive); + btn->ui(new_ui); + btn->callback(tab_btn_cb, this); + Pack->add(btn); // append + + if (focus) { + switch_tab(btn); + } else if (num_tabs() == 2) { + // no focus and tabbar added: redraw current page + Wizard->redraw(); } + if (num_tabs() == 1) + btn->hide(); + update_pack_offset(); - int w2[128]; + return new_ui; +} - for (i = 0; i < numchildren; i++) - w2[i] = tab_width[i]; - i = numchildren - 1; - int j = 0; +/* + * Remove tab by UI + */ +void CustTabs::remove_tab(UI *ui) +{ + CustTabButton *btn; - int minsize = 5; + // get active tab idx + int act_idx = get_btn_idx((UI*)Wizard->value()); + // get to-be-removed tab idx + int rm_idx = get_btn_idx(ui); + btn = (CustTabButton*)Pack->child(rm_idx); - bool right = true; + if (act_idx == rm_idx) { + // Active tab is being closed, switch to another one + rm_idx > 0 ? prev_tab() : next_tab(); + } + Pack->remove(rm_idx); + update_pack_offset(); + delete btn; - while (cumulated_width > available_width) { - int n; // which one to shrink + Wizard->remove(ui); + delete(ui); - if (j < selected && (!right || i <= selected)) { // shrink a left one - n = j++; - right = true; - } else if (i > selected) { // shrink a right one - n = i--; - right = false; - } else { // no more space, start making them zero - minsize = 0; - i = numchildren - 1; - j = 0; - right = true; - continue; - } - cumulated_width -= w2[n] - minsize; - w2[n] = minsize; - if (cumulated_width < available_width) { - w2[n] = available_width - cumulated_width + minsize; - cumulated_width = available_width; - break; - } + if (num_tabs() == 1) { + // hide tabbar + ctab_h = 1; + CloseBtn->hide(); + Pack->child(0)->size(0,0); + Pack->child(0)->hide(); // first tab button + resize(0,0,window()->w(),ctab_h); // tabbar + Wizard->resize(0,ctab_h,Wizard->w(),window()->h()-ctab_h); + window()->init_sizes(); + window()->redraw(); } - // re-sum the positions: - cumulated_width = 0; - for (i = 0; i < numchildren; i++) { - cumulated_width += w2[i]; - tab_pos[i+1] = cumulated_width; - } - return selected; } -TabGroupPager* CustShrinkTabPager::clone() const { - return new CustShrinkTabPager(*this); +int CustTabs::get_btn_idx(UI *ui) +{ + for (int i = 0; i < num_tabs(); ++i) { + CustTabButton *btn = (CustTabButton*)Pack->child(i); + if (btn->ui() == ui) + return i; + } + return -1; } -//---------------------------------------------------------------------------- +/* + * Keep active tab visible + * (Pack children have unusable x() coordinate) + */ +void CustTabs::update_pack_offset() +{ + dReturn_if (num_tabs() == 0); + + // get active tab button + int act_idx = get_btn_idx((UI*)Wizard->value()); + CustTabButton *cbtn = (CustTabButton*)Pack->child(act_idx); + + // calculate tab button's x() coordinates + int x_i = 0, x_f; + for (int j=0; j < act_idx; ++j) + x_i += Pack->child(j)->w(); + x_f = x_i + cbtn->w(); + + int scr_x = Scroll->xposition(), scr_y = Scroll->yposition(); + int px_i = x_i - scr_x; + int px_f = px_i + cbtn->w(); + int pw = Scroll->window()->w() - ctl_w; + _MSG(" scr_x=%d btn_x=%d px_i=%d btn_w=%d px_f=%d pw=%d", + Scroll->xposition(),cbtn->x(),px_i,cbtn->w(),px_f,pw); + if (px_i < 0) { + Scroll->scroll_to(x_i, scr_y); + } else if (px_i > pw || (px_i > 0 && px_f > pw)) { + Scroll->scroll_to(MIN(x_i, x_f-pw), scr_y); + } + Scroll->redraw(); + _MSG(" >>scr_x=%d btn0_x=%d\n", scr_x, Pack->child(0)->x()); +} /* - * For custom handling of keyboard + * Make cbtn's tab the active one */ -class CustTabGroup : public fltk::TabGroup { - Tooltip *toolTip; - bool tooltipEnabled; - bool buttonPushed; -public: - CustTabGroup (int x, int y, int ww, int wh, const char *lbl=0) : - TabGroup(x,y,ww,wh,lbl) { - // The parameter pager is cloned, so free it. - CustShrinkTabPager *cp = new CustShrinkTabPager(); - this->pager(cp); - delete cp; - toolTip = new Tooltip; - tooltipEnabled = false; - buttonPushed = false; - }; - ~CustTabGroup() { delete toolTip; } - int handle(int e) { - // Don't focus with arrow keys - _MSG("CustTabGroup::handle %d\n", e); - fltk::Rectangle r(btn_x,0,BTN_W,BTN_H); - if (e == KEY) { - int k = event_key(); - // We're only interested in some flags - unsigned modifier = event_state() & (SHIFT | CTRL | ALT); - if (k == UpKey || k == DownKey || k == TabKey) { - return 0; - } else if (k == LeftKey || k == RightKey) { - if (modifier == SHIFT) { - int i = value(); - if (k == LeftKey) {i = i ? i-1 : children()-1;} - else {i++; if (i >= children()) i = 0;} - selected_child(child(i)); - return 1; - } - // Avoid focus change. - return 0; - } - } else if (e == FOCUS_CHANGE) { - // Update the window title - BrowserWindow *bw = a_UIcmd_get_bw_by_widget(selected_child()); - const char *title = a_History_get_title(NAV_TOP_UIDX(bw), 1); - a_UIcmd_set_page_title(bw, title ? title : ""); - } else if (e == MOVE) { - CustShrinkTabPager *cstp = (CustShrinkTabPager *) pager(); - if (event_inside(r) && children() > 1) { - /* We're inside the button area */ - cstp->btn_highlight(true); - if (prefs.show_tooltip) { - /* Prepare the tooltip for pop-up */ - tooltipEnabled = true; - /* We use parent() if available because we are returning 0. - * Returning without having TabGroup processing makes the - * popup event never reach 'this', but it reaches parent() */ - toolTip->enter(parent() ?parent():this, r, "Close current Tab"); - } - return 0; // Change focus - } else { - cstp->btn_highlight(false); - - if (prefs.show_tooltip) { - /* Hide the tooltip or enable it again.*/ - if (tooltipEnabled) { - tooltipEnabled = false; - toolTip->exit(); - } else { - toolTip->enable(); - } - } - } - } else if (e == PUSH && event_inside(r) && - event_button() == 1 && children() > 1) { - buttonPushed = true; - return 1; /* non-zero */ - } else if (e == RELEASE) { - if (event_inside(r) && event_button() == 1 && - children() > 1 && buttonPushed) { - a_UIcmd_close_bw(a_UIcmd_get_bw_by_widget(selected_child())); - } else { - CustShrinkTabPager *cstp = (CustShrinkTabPager *) pager(); - cstp->btn_highlight(false); - } - buttonPushed = false; - } else if (e == DRAG) { - /* Ignore this event */ - return 1; +void CustTabs::switch_tab(CustTabButton *cbtn) +{ + int idx; + CustTabButton *btn; + BrowserWindow *bw; + UI *old_ui = (UI*)Wizard->value(); + + if (cbtn->ui() != old_ui) { + // Set old tab label to normal color + if ((idx = get_btn_idx(old_ui)) != -1) { + btn = (CustTabButton*)Pack->child(idx); + btn->color(tabcolor_inactive); + btn->redraw(); } - int ret = TabGroup::handle(e); - - if (e == PUSH) { - /* WORKAROUND: FLTK raises the window on unhandled clicks, - * which we do not want. - */ - ret = 1; + Wizard->value(cbtn->ui()); + cbtn->color(tabcolor_active); + cbtn->redraw(); + update_pack_offset(); + + // Update window title + if ((bw = a_UIcmd_get_bw_by_widget(cbtn->ui()))) { + const char *title = (cbtn->ui())->label(); + cbtn->window()->copy_label(title ? title : ""); } - return ret; } +} - void remove (Widget *w) { - TabGroup::remove (w); - /* fixup resizable in case we just removed it */ - if (resizable () == w) { - if (children () > 0) - resizable (child (children () - 1)); - else - resizable (NULL); - } +void CustTabs::prev_tab() +{ + int idx; - if (children () < 2) - hideLabels (); - } + if ((idx = get_btn_idx((UI*)Wizard->value())) != -1) + switch_tab((CustTabButton*)Pack->child(idx>0 ? idx-1 : num_tabs()-1)); +} - void add (Widget *w) { - TabGroup::add (w); - if (children () > 1) - showLabels (); - } +void CustTabs::next_tab() +{ + int idx; - void hideLabels() { - for (int i = children () - 1; i >= 0; i--) - child(i)->resize(x(), y(), w(), h()); - } + if ((idx = get_btn_idx((UI*)Wizard->value())) != -1) + switch_tab((CustTabButton*)Pack->child((idx+1<num_tabs()) ? idx+1 : 0)); +} + +/* + * Set this UI's tab button label + */ +void CustTabs::set_tab_label(UI *ui, const char *label) +{ + char title[128]; + int idx = get_btn_idx(ui); + + if (idx != -1) { + // Make a label for this tab + size_t tab_chars = 15, label_len = strlen(label); - void showLabels() { - for (int i = children () - 1; i >= 0; i--) - child(i)->resize(x(), y() + 20, w(), h() - 20); + if (label_len > tab_chars) + tab_chars = a_Utf8_end_of_char(label, tab_chars - 1) + 1; + snprintf(title, tab_chars + 1, "%s", label); + if (label_len > tab_chars) + snprintf(title + tab_chars, 4, "..."); + + // Avoid unnecessary redraws + if (strcmp(Pack->child(idx)->label(), title)) { + int w = 0, h; + Pack->child(idx)->copy_label(title); + Pack->child(idx)->measure_label(w, h); + Pack->child(idx)->size(w+14,ctab_h); + update_pack_offset(); + } } -}; +} + //---------------------------------------------------------------------------- -static void win_cb (fltk::Widget *w, void *cb_data) { - int choice = 0; - CustTabGroup *tabs = (CustTabGroup*) cb_data; +static void win_cb (Fl_Widget *w, void *cb_data) { + CustTabs *tabs = (CustTabs*) cb_data; + int choice = 1, ntabs = tabs->num_tabs(); - if (tabs->children () > 1) - choice = a_Dialog_choice3 ("Window contains more than one tab.", - "Close all tabs", "Cancel", NULL); - if (choice == 0) - while (tabs->children()) - a_UIcmd_close_bw(a_UIcmd_get_bw_by_widget(tabs->child(0))); + if (prefs.show_quit_dialog && ntabs > 1) + choice = a_Dialog_choice5("Window contains more than one tab.", + "Close", "Cancel", NULL, NULL, NULL); + if (choice == 1) + while (ntabs-- > 0) + a_UIcmd_close_bw(a_UIcmd_get_bw_by_widget(tabs->wizard()->value())); } /* @@ -376,27 +449,14 @@ BrowserWindow *a_UIcmd_get_bw_by_widget(void *v_wid) BrowserWindow *bw; for (int i = 0; i < a_Bw_num(); ++i) { bw = a_Bw_get(i); - if (((fltk::Widget*)bw->ui)->contains((fltk::Widget*)v_wid)) + if (((UI*)bw->ui)->contains((Fl_Widget*)v_wid)) { return bw; + } } return NULL; } /* - * FLTK regards SHIFT + {LeftKey, Right} as navigation keys. - * Special handling is required to override it. Here we route - * these events directly to the recipient. - * TODO: focus is not remembered correctly. - */ -void a_UIcmd_send_event_to_tabs_by_wid(int e, void *v_wid) -{ - BrowserWindow *bw = a_UIcmd_get_bw_by_widget(v_wid); - UI *ui = (UI*)bw->ui; - if (ui->tabs()) - ui->tabs()->handle(e); -} - -/* * Create a new UI and its associated BrowserWindow data structure. * Use style from v_ui. If non-NULL it must be of type UI*. */ @@ -405,7 +465,8 @@ BrowserWindow *a_UIcmd_browser_window_new(int ww, int wh, { BrowserWindow *old_bw = (BrowserWindow*)vbw; BrowserWindow *new_bw = NULL; - Window *win; + UI *old_ui = old_bw ? BW2UI(old_bw) : NULL; + Fl_Window *win; if (ww <= 0 || wh <= 0) { // Set default geometry from dillorc. @@ -415,96 +476,40 @@ BrowserWindow *a_UIcmd_browser_window_new(int ww, int wh, if (xid) win = new Xembed(xid, ww, wh); + else if (prefs.buffered_drawing != 2) + win = new Fl_Window(ww, wh); else - win = new Window(ww, wh); + win = new Fl_Double_Window(ww, wh); - win->shortcut(0); // Ignore Escape - if (prefs.buffered_drawing != 2) - win->clear_double_buffer(); - win->set_flag(RAW_LABEL); - CustTabGroup *DilloTabs = new CustTabGroup(0, 0, ww, wh); - DilloTabs->clear_tab_to_focus(); - DilloTabs->selection_color(156); - win->add(DilloTabs); + win->box(FL_NO_BOX); + CustTabs *DilloTabs = new CustTabs(ww, wh, 16); + win->end(); - // Create and set the UI - UI *new_ui = new UI(0, 0, ww, wh, DEFAULT_TAB_LABEL, - old_bw ? BW2UI(old_bw) : NULL); - new_ui->set_status("http://www.dillo.org/"); - new_ui->tabs(DilloTabs); - - DilloTabs->add(new_ui); - DilloTabs->resizable(new_ui); - DilloTabs->window()->resizable(new_ui); - DilloTabs->window()->show(); + int focus = 1; + new_bw = UIcmd_tab_new(DilloTabs, old_ui, focus); + win->resizable(DilloTabs->wizard()); + win->show(); if (old_bw == NULL && prefs.xpos >= 0 && prefs.ypos >= 0) { // position the first window according to preferences - fltk::Rectangle r; - new_ui->window()->borders(&r); - // borders() gives x and y border sizes as negative values - new_ui->window()->position(prefs.xpos - r.x(), prefs.ypos - r.y()); + DilloTabs->window()->position(prefs.xpos, prefs.ypos); } - // Now create the Dw render layout and viewport - FltkPlatform *platform = new FltkPlatform (); - Layout *layout = new Layout (platform); - style::Color *bgColor = style::Color::create (layout, prefs.bg_color); - layout->setBgColor (bgColor); - - FltkViewport *viewport = new FltkViewport (0, 0, 1, 1); - if (prefs.buffered_drawing == 1) - viewport->setBufferedDrawing (true); - else - viewport->setBufferedDrawing (false); - - layout->attachView (viewport); - new_ui->set_render_layout(*viewport); - - viewport->setScrollStep((int) rint(14.0 * prefs.font_factor)); - - // Now, create a new browser window structure - new_bw = a_Bw_new(); - - // Reference the UI from the bw - new_bw->ui = (void *)new_ui; - // Copy the layout pointer into the bw data - new_bw->render_layout = (void*)layout; - win->callback(win_cb, DilloTabs); - new_ui->focus_location(); - return new_bw; } /* - * Create a new Tab. - * i.e the new UI and its associated BrowserWindow data structure. + * Create a new Tab button, UI and its associated BrowserWindow data + * structure. */ -static BrowserWindow *UIcmd_tab_new(const void *vbw) +static BrowserWindow *UIcmd_tab_new(CustTabs *tabs, UI *old_ui, int focus) { - _MSG(" UIcmd_tab_new vbw=%p\n", vbw); - - dReturn_val_if_fail (vbw != NULL, NULL); - - BrowserWindow *new_bw = NULL; - BrowserWindow *old_bw = (BrowserWindow*)vbw; - UI *ui = BW2UI(old_bw); - - // WORKAROUND: limit the number of tabs because of a fltk bug - if (ui->tabs()->children() >= 127) - return a_UIcmd_browser_window_new(ui->window()->w(), ui->window()->h(), - 0, vbw); + _MSG(" UIcmd_tab_new\n"); // Create and set the UI - UI *new_ui = new UI(0, 0, ui->w(), ui->h(), DEFAULT_TAB_LABEL, ui); - new_ui->tabs(ui->tabs()); - - new_ui->tabs()->add(new_ui); - new_ui->tabs()->resizable(new_ui); - new_ui->tabs()->window()->resizable(new_ui); - new_ui->tabs()->window()->show(); + UI *new_ui = tabs->add_new_tab(old_ui, focus); // Now create the Dw render layout and viewport FltkPlatform *platform = new FltkPlatform (); @@ -512,21 +517,30 @@ static BrowserWindow *UIcmd_tab_new(const void *vbw) style::Color *bgColor = style::Color::create (layout, prefs.bg_color); layout->setBgColor (bgColor); - FltkViewport *viewport = new FltkViewport (0, 0, 1, 1); - + // set_render_layout() sets the proper viewport size + FltkViewport *viewport = new FltkViewport (0, 0, 0, 1); + viewport->box(FL_NO_BOX); + viewport->setBufferedDrawing (prefs.buffered_drawing ? true : false); + viewport->setDragScroll (prefs.middle_click_drags_page ? true : false); layout->attachView (viewport); - new_ui->set_render_layout(*viewport); - - viewport->setScrollStep((int) rint(14.0 * prefs.font_factor)); + new_ui->set_render_layout(viewport); + viewport->setScrollStep((int) rint(28.0 * prefs.font_factor)); // Now, create a new browser window structure - new_bw = a_Bw_new(); + BrowserWindow *new_bw = a_Bw_new(); // Reference the UI from the bw new_bw->ui = (void *)new_ui; // Copy the layout pointer into the bw data new_bw->render_layout = (void*)layout; + // Clear the window title + if (focus) + new_ui->window()->copy_label(new_ui->label()); + + // WORKAROUND: see findbar_toggle() + new_ui->findbar_toggle(0); + return new_bw; } @@ -537,21 +551,17 @@ void a_UIcmd_close_bw(void *vbw) { BrowserWindow *bw = (BrowserWindow *)vbw; UI *ui = BW2UI(bw); + CustTabs *tabs = ui->tabs(); Layout *layout = (Layout*)bw->render_layout; - MSG("a_UIcmd_close_bw\n"); + _MSG("a_UIcmd_close_bw\n"); a_Bw_stop_clients(bw, BW_Root + BW_Img + BW_Force); delete(layout); - if (ui->tabs()) { - ui->tabs()->remove(ui); - ui->tabs()->value(ui->tabs()->children() - 1); - if (ui->tabs()->value() != -1) - ui->tabs()->selected_child()->take_focus(); - else - ui->tabs()->window()->hide(); + if (tabs) { + tabs->remove_tab(ui); + if (tabs->num_tabs() == 0) + delete tabs->window(); } - delete(ui); - a_Bw_free(bw); } @@ -561,12 +571,12 @@ void a_UIcmd_close_bw(void *vbw) void a_UIcmd_close_all_bw(void *) { BrowserWindow *bw; - int choice = 0; + int choice = 1; - if (a_Bw_num() > 1) - choice = a_Dialog_choice3 ("More than one open tab or Window.", - "Close all tabs and windows", "Cancel", NULL); - if (choice == 0) + if (prefs.show_quit_dialog && a_Bw_num() > 1) + choice = a_Dialog_choice5("More than one open tab or window.", + "Quit", "Cancel", NULL, NULL, NULL); + if (choice == 1) while ((bw = a_Bw_get(0))) a_UIcmd_close_bw((void*)bw); } @@ -616,10 +626,14 @@ void a_UIcmd_open_urlstr(void *vbw, const char *urlstr) */ void a_UIcmd_open_url(BrowserWindow *bw, const DilloUrl *url) { - a_Nav_push(bw, url, NULL); - if (BW2UI(bw)->get_panelmode() == UI_TEMPORARILY_SHOW_PANELS) - BW2UI(bw)->set_panelmode(UI_HIDDEN); - a_UIcmd_focus_main_area(bw); + if (url) { + a_Nav_push(bw, url, NULL); + BW2UI(bw)->focus_main(); + } else { + // Used to start a bw with a blank screen + BW2UI(bw)->focus_location(); + a_UIcmd_set_buttons_sens(bw); + } } static void UIcmd_open_url_nbw(BrowserWindow *new_bw, const DilloUrl *url) @@ -632,6 +646,7 @@ static void UIcmd_open_url_nbw(BrowserWindow *new_bw, const DilloUrl *url) BW2UI(new_bw)->focus_main(); } else { BW2UI(new_bw)->focus_location(); + a_UIcmd_set_buttons_sens(new_bw); } } @@ -654,11 +669,9 @@ void a_UIcmd_open_url_nw(BrowserWindow *bw, const DilloUrl *url) */ void a_UIcmd_open_url_nt(void *vbw, const DilloUrl *url, int focus) { - BrowserWindow *new_bw = UIcmd_tab_new(vbw); - - if (focus) - BW2UI(new_bw)->tabs()->selected_child(BW2UI(new_bw)); - + BrowserWindow *bw = (BrowserWindow *)vbw; + BrowserWindow *new_bw = UIcmd_tab_new(BW2UI(bw)->tabs(), + bw ? BW2UI(bw) : NULL, focus); UIcmd_open_url_nbw(new_bw, url); } @@ -673,9 +686,9 @@ void a_UIcmd_back(void *vbw) /* * Popup the navigation menu of the Back button */ -void a_UIcmd_back_popup(void *vbw) +void a_UIcmd_back_popup(void *vbw, int x, int y) { - a_Menu_history_popup((BrowserWindow*)vbw, -1); + a_Menu_history_popup((BrowserWindow*)vbw, x, y, -1); } /* @@ -689,9 +702,9 @@ void a_UIcmd_forw(void *vbw) /* * Popup the navigation menu of the Forward button */ -void a_UIcmd_forw_popup(void *vbw) +void a_UIcmd_forw_popup(void *vbw, int x, int y) { - a_Menu_history_popup((BrowserWindow*)vbw, 1); + a_Menu_history_popup((BrowserWindow*)vbw, x, y, 1); } /* @@ -825,9 +838,9 @@ void a_UIcmd_stop(void *vbw) /* * Popup the tools menu */ -void a_UIcmd_tools(void *vbw, void *v_wid) +void a_UIcmd_tools(void *vbw, int x, int y) { - a_Menu_tools_popup((BrowserWindow*)vbw, v_wid); + a_Menu_tools_popup((BrowserWindow*)vbw, x, y); } /* @@ -850,29 +863,33 @@ void a_UIcmd_open_file(void *vbw) /* * Returns a newly allocated string holding a search url generated from - * a string of keywords (separarated by blanks) and prefs.search_url. + * a string of keywords (separated by blanks) and the current search_url. * The search string is urlencoded. */ static char *UIcmd_make_search_str(const char *str) { - char *keys = a_Url_encode_hex_str(str), *c = prefs.search_url; + char *search_url, *l, *u, *c; + char *keys = a_Url_encode_hex_str(str), + *src = (char*)dList_nth_data(prefs.search_urls, prefs.search_url_idx); Dstr *ds = dStr_sized_new(128); - char *search_url; - - for (; *c; c++) { - if (*c == '%') - switch(*++c) { - case 's': - dStr_append(ds, keys); break;; - case '%': - dStr_append_c(ds, '%'); break;; - case 0: - MSG_WARN("search_url ends with '%%'\n"); c--; break;; - default: - MSG_WARN("illegal specifier '%%%c' in search_url\n", *c); - } - else - dStr_append_c(ds, *c); + + /* parse search_url into label and url */ + if (a_Misc_parse_search_url(src, &l, &u) == 0) { + for (c = u; *c; c++) { + if (*c == '%') + switch(*++c) { + case 's': + dStr_append(ds, keys); break;; + case '%': + dStr_append_c(ds, '%'); break;; + case 0: + MSG_WARN("search_url ends with '%%'\n"); c--; break;; + default: + MSG_WARN("illegal specifier '%%%c' in search_url\n", *c); + } + else + dStr_append_c(ds, *c); + } } dFree(keys); @@ -918,13 +935,11 @@ void a_UIcmd_save_link(BrowserWindow *bw, const DilloUrl *url) a_UIcmd_set_save_dir(prefs.save_dir); SuggestedName = UIcmd_make_save_filename(URL_STR(url)); - name = a_Dialog_save_file("Save Link as File", NULL, SuggestedName); - MSG("a_UIcmd_save_link: %s\n", name); - dFree(SuggestedName); - - if (name) { + if ((name = a_Dialog_save_file("Save Link as File", NULL, SuggestedName))) { + MSG("a_UIcmd_save_link: %s\n", name); a_Nav_save_url(bw, url, name); } + dFree(SuggestedName); } /* @@ -1030,7 +1045,7 @@ void a_UIcmd_view_page_source(BrowserWindow *bw, const DilloUrl *url) } /* - * Show a text window with the URL's source + * Show the browser window's HTML errors in a text window */ void a_UIcmd_view_page_bugs(void *vbw) { @@ -1151,6 +1166,8 @@ void a_UIcmd_scroll(BrowserWindow *bw, int icmd) const mapping_t map[] = { {KEYS_SCREEN_UP, SCREEN_UP_CMD}, {KEYS_SCREEN_DOWN, SCREEN_DOWN_CMD}, + {KEYS_SCREEN_LEFT, SCREEN_LEFT_CMD}, + {KEYS_SCREEN_RIGHT, SCREEN_RIGHT_CMD}, {KEYS_LINE_UP, LINE_UP_CMD}, {KEYS_LINE_DOWN, LINE_DOWN_CMD}, {KEYS_LEFT, LEFT_CMD}, @@ -1217,7 +1234,7 @@ void a_UIcmd_set_bug_prog(BrowserWindow *bw, int n_bug) } /* - * Set the page title in the window titlebar and tab label. + * Set the page title in the tab label and window titlebar. * (Update window titlebar for the current tab only) */ void a_UIcmd_set_page_title(BrowserWindow *bw, const char *label) @@ -1225,16 +1242,17 @@ void a_UIcmd_set_page_title(BrowserWindow *bw, const char *label) const int size = 128; char title[size]; - if (a_UIcmd_get_bw_by_widget(BW2UI(bw)->tabs()->selected_child()) == bw) { + if (snprintf(title, size, "Dillo: %s", label ? label : "") >= size) { + uint_t i = MIN(size - 4, 1 + a_Utf8_end_of_char(title, size - 8)); + snprintf(title + i, 4, "..."); + } + BW2UI(bw)->copy_label(title); + BW2UI(bw)->tabs()->set_tab_label(BW2UI(bw), label ? label : ""); + + if (a_UIcmd_get_bw_by_widget(BW2UI(bw)->tabs()->wizard()->value()) == bw) { // This is the focused bw, set window title - if (snprintf(title, size, "Dillo: %s", label) >= size) { - uint_t i = MIN(size - 4, 1 + a_Utf8_end_of_char(title, size - 8)); - snprintf(title + i, 4, "..."); - } BW2UI(bw)->window()->copy_label(title); - BW2UI(bw)->window()->redraw_label(); } - BW2UI(bw)->set_tab_title(label); } /* @@ -1268,32 +1286,16 @@ void a_UIcmd_set_buttons_sens(BrowserWindow *bw) BW2UI(bw)->button_set_sens(UI_BACK, sens); // Forward sens = (a_Nav_stack_ptr(bw) < a_Nav_stack_size(bw) - 1 && - !bw->nav_expecting); + !a_Bw_expecting(bw)); BW2UI(bw)->button_set_sens(UI_FORW, sens); } /* - * Keep track of mouse pointer over a link. - */ -void a_UIcmd_set_pointer_on_link(BrowserWindow *bw, int flag) -{ - BW2UI(bw)->pointerOnLink(flag); -} - -/* - * Is the mouse pointer over a link? + * Toggle control panel */ -int a_UIcmd_pointer_on_link(BrowserWindow *bw) +void a_UIcmd_panels_toggle(BrowserWindow *bw) { - return BW2UI(bw)->pointerOnLink(); -} - -/* - * Toggle control panel (aka. fullscreen) - */ -void a_UIcmd_fullscreen_toggle(BrowserWindow *bw) -{ - BW2UI(bw)->fullscreen_toggle(); + BW2UI(bw)->panels_toggle(); } /* @@ -1330,6 +1332,14 @@ void a_UIcmd_findtext_reset(BrowserWindow *bw) } /* + * Tell the UI to hide/show the findbar + */ +void a_UIcmd_findbar_toggle(BrowserWindow *bw, int on) +{ + BW2UI(bw)->findbar_toggle(on); +} + +/* * Focus the rendered area. */ void a_UIcmd_focus_main_area(BrowserWindow *bw) diff --git a/src/uicmd.hh b/src/uicmd.hh index c8fea9e7..c859ba9c 100644 --- a/src/uicmd.hh +++ b/src/uicmd.hh @@ -17,16 +17,16 @@ void a_UIcmd_open_url(BrowserWindow *bw, const DilloUrl *url); void a_UIcmd_open_url_nw(BrowserWindow *bw, const DilloUrl *url); void a_UIcmd_open_url_nt(void *vbw, const DilloUrl *url, int focus); void a_UIcmd_back(void *vbw); -void a_UIcmd_back_popup(void *vbw); +void a_UIcmd_back_popup(void *vbw, int x, int y); void a_UIcmd_forw(void *vbw); -void a_UIcmd_forw_popup(void *vbw); +void a_UIcmd_forw_popup(void *vbw, int x, int y); void a_UIcmd_home(void *vbw); void a_UIcmd_reload(void *vbw); void a_UIcmd_repush(void *vbw); void a_UIcmd_redirection0(void *vbw, const DilloUrl *url); void a_UIcmd_save(void *vbw); void a_UIcmd_stop(void *vbw); -void a_UIcmd_tools(void *vbw, void *v_wid); +void a_UIcmd_tools(void *vbw, int x, int y); void a_UIcmd_save_link(BrowserWindow *bw, const DilloUrl *url); void a_UIcmd_open_file(void *vbw); const char *a_UIcmd_select_file(); @@ -34,11 +34,12 @@ void a_UIcmd_search_dialog(void *vbw); const char *a_UIcmd_get_passwd(const char *user); void a_UIcmd_book(void *vbw); void a_UIcmd_add_bookmark(BrowserWindow *bw, const DilloUrl *url); -void a_UIcmd_fullscreen_toggle(BrowserWindow *bw); +void a_UIcmd_panels_toggle(BrowserWindow *bw); void a_UIcmd_findtext_dialog(BrowserWindow *bw); void a_UIcmd_findtext_search(BrowserWindow *bw,const char *key,int case_sens, int backwards); void a_UIcmd_findtext_reset(BrowserWindow *bw); +void a_UIcmd_findbar_toggle(BrowserWindow *bw, int on); void a_UIcmd_focus_main_area(BrowserWindow *bw); void a_UIcmd_focus_location(void *vbw); void a_UIcmd_page_popup(void *vbw, bool_t has_bugs, void *v_cssUrls); @@ -77,9 +78,6 @@ void a_UIcmd_set_bug_prog(BrowserWindow *bw, int n_bug); void a_UIcmd_set_page_title(BrowserWindow *bw, const char *label); void a_UIcmd_set_msg(BrowserWindow *bw, const char *format, ...); void a_UIcmd_set_buttons_sens(BrowserWindow *bw); -void a_UIcmd_fullscreen_toggle(BrowserWindow *bw); -void a_UIcmd_set_pointer_on_link(BrowserWindow *bw, int flag); -int a_UIcmd_pointer_on_link(BrowserWindow *bw); #ifdef __cplusplus } @@ -233,6 +233,8 @@ static Dstr *Url_resolve_relative(const char *RelStr, dStr_append(SolvedUrl, BaseStr); if ((p = strchr(SolvedUrl->str, '#'))) dStr_truncate(SolvedUrl, p - SolvedUrl->str); + if (!BaseUrl->path) + dStr_append_c(SolvedUrl, '/'); if (RelUrl->query) { /* query */ if (BaseUrl->query) @@ -687,11 +689,11 @@ static uint_t Url_host_public_internal_dots(const char *host) if (tld_len > 0) { /* These TLDs were chosen by examining the current publicsuffix list - * in January 2010 and picking out those where it was simplest for + * in September 2011 and picking out those where it was simplest for * them to describe the situation by beginning with a "*.[tld]" rule. */ - const char *const tlds[] = {"ar","au","bd","bn","bt","ck","cy","do", - "eg","er","et","fj","fk","gt","gu","id", + const char *const tlds[] = {"ar","au","bd","bn","bt","ck","cy", + "er","et","fj","fk","gt","gu","id", "il","jm","ke","kh","kw","ml","mm","mt", "mz","ni","np","nz","om","pg","py","qa", "sv","tr","uk","uy","ve","ye","yu","za", @@ -716,7 +718,7 @@ static uint_t Url_host_public_internal_dots(const char *host) * domain that is in a registry outside the organization. * For 'www.dillo.org', that would be 'dillo.org'. */ -const char *a_Url_host_find_public_suffix(const char *host) +static const char *Url_host_find_public_suffix(const char *host) { const char *s; uint_t dots; @@ -751,3 +753,12 @@ const char *a_Url_host_find_public_suffix(const char *host) _MSG("public suffix of %s is %s\n", host, s); return s; } + +bool_t a_Url_same_organization(const DilloUrl *u1, const DilloUrl *u2) +{ + if (!u1 || !u2) + return FALSE; + + return dStrcasecmp(Url_host_find_public_suffix(URL_HOST(u1)), + Url_host_find_public_suffix(URL_HOST(u2))) ? FALSE :TRUE; +} @@ -47,21 +47,21 @@ * (non '_'-ended macros MUST use these for initialization sake) */ /* these MAY return NULL: */ -#define URL_SCHEME_(u) u->scheme -#define URL_AUTHORITY_(u) u->authority -#define URL_PATH_(u) u->path -#define URL_QUERY_(u) u->query -#define URL_FRAGMENT_(u) u->fragment +#define URL_SCHEME_(u) (u)->scheme +#define URL_AUTHORITY_(u) (u)->authority +#define URL_PATH_(u) (u)->path +#define URL_QUERY_(u) (u)->query +#define URL_FRAGMENT_(u) (u)->fragment #define URL_HOST_(u) a_Url_hostname(u) -#define URL_ALT_(u) u->alt +#define URL_ALT_(u) (u)->alt #define URL_STR_(u) a_Url_str(u) /* this returns a Dstr* */ -#define URL_DATA_(u) u->data +#define URL_DATA_(u) (u)->data /* these return an integer */ -#define URL_PORT_(u) (URL_HOST(u), u->port) -#define URL_FLAGS_(u) u->flags -#define URL_ILLEGAL_CHARS_(u) url->illegal_chars -#define URL_ILLEGAL_CHARS_SPC_(u) url->illegal_chars_spc +#define URL_PORT_(u) (URL_HOST(u), (u)->port) +#define URL_FLAGS_(u) (u)->flags +#define URL_ILLEGAL_CHARS_(u) (u)->illegal_chars +#define URL_ILLEGAL_CHARS_SPC_(u) (u)->illegal_chars_spc /* * Access methods that never return NULL. @@ -122,7 +122,7 @@ void a_Url_set_ismap_coords(DilloUrl *u, char *coord_str); char *a_Url_decode_hex_str(const char *str); char *a_Url_encode_hex_str(const char *str); char *a_Url_string_strip_delimiters(const char *str); -const char *a_Url_host_find_public_suffix(const char *host); +bool_t a_Url_same_organization(const DilloUrl *u1, const DilloUrl *u2); #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/src/utf8.cc b/src/utf8.cc index 0138c616..3d25f4f5 100644 --- a/src/utf8.cc +++ b/src/utf8.cc @@ -9,7 +9,7 @@ * (at your option) any later version. */ -#include <fltk/utf.h> +#include <FL/fl_utf8.h> #include "../dlib/dlib.h" /* TRUE/FALSE */ #include "utf8.hh" @@ -45,7 +45,7 @@ uint_t a_Utf8_end_of_char(const char *str, uint_t i) */ uint_t a_Utf8_decode(const char* str, const char* end, int* len) { - return utf8decode(str, end, len); + return fl_utf8decode(str, end, len); } /* @@ -53,7 +53,7 @@ uint_t a_Utf8_decode(const char* str, const char* end, int* len) */ int a_Utf8_encode(unsigned int ucs, char *buf) { - return utf8encode(ucs, buf); + return fl_utf8encode(ucs, buf); } /* @@ -63,7 +63,7 @@ int a_Utf8_encode(unsigned int ucs, char *buf) */ int a_Utf8_test(const char* src, unsigned int srclen) { - return utf8test(src, srclen); + return fl_utf8test(src, srclen); } /* @@ -100,3 +100,8 @@ bool_t a_Utf8_combining_char(int unicode) (unicode >= 0x20d0 && unicode <= 0x20ff) || (unicode >= 0xfe20 && unicode <= 0xfe2f)); } + +int a_Utf8_char_count(const char *str, int len) +{ + return fl_utf_nb_char((const uchar_t*)str, len); +} diff --git a/src/utf8.hh b/src/utf8.hh index 4ded50b8..ce575118 100644 --- a/src/utf8.hh +++ b/src/utf8.hh @@ -24,6 +24,7 @@ int a_Utf8_encode(unsigned int ucs, char *buf); int a_Utf8_test(const char* src, unsigned int srclen); bool_t a_Utf8_ideographic(const char *s, const char *end, int *len); bool_t a_Utf8_combining_char(int unicode); +int a_Utf8_char_count(const char *str, int len); #ifdef __cplusplus } @@ -78,8 +78,11 @@ int a_Web_dispatch_by_type (const char *Type, DilloWeb *Web, /* This method frees the old dw if any */ layout->setWidget(dw); - /* Clear the title bar for pages without a <TITLE> tag */ - a_UIcmd_set_page_title(Web->bw, ""); + /* Set the page title with the bare filename (e.g. for images), + * HTML pages with a <TITLE> tag will overwrite it later */ + const char *p = strrchr(URL_STR(Web->url), '/'); + a_UIcmd_set_page_title(Web->bw, p ? p+1 : ""); + a_UIcmd_set_location_text(Web->bw, URL_STR(Web->url)); /* Reset both progress bars */ a_UIcmd_set_page_prog(Web->bw, 0, 2); @@ -106,14 +109,15 @@ int a_Web_dispatch_by_type (const char *Type, DilloWeb *Web, /* * Allocate and set safe values for a DilloWeb structure */ -DilloWeb* a_Web_new(const DilloUrl *url, const DilloUrl *requester) +DilloWeb* a_Web_new(BrowserWindow *bw, const DilloUrl *url, + const DilloUrl *requester) { DilloWeb *web= dNew(DilloWeb, 1); _MSG(" a_Web_new: ValidWebs ==> %d\n", dList_length(ValidWebs)); web->url = a_Url_dup(url); web->requester = a_Url_dup(requester); - web->bw = NULL; + web->bw = bw; web->flags = 0; web->Image = NULL; web->filename = NULL; @@ -36,7 +36,8 @@ struct _DilloWeb { }; void a_Web_init(void); -DilloWeb* a_Web_new (const DilloUrl* url, const DilloUrl *requester); +DilloWeb* a_Web_new (BrowserWindow *bw, const DilloUrl* url, + const DilloUrl *requester); int a_Web_valid(DilloWeb *web); void a_Web_free (DilloWeb*); int a_Web_dispatch_by_type (const char *Type, DilloWeb *web, diff --git a/src/xembed.cc b/src/xembed.cc index 04a4362a..f180d81d 100644 --- a/src/xembed.cc +++ b/src/xembed.cc @@ -12,14 +12,14 @@ #include <string.h> #include <ctype.h> -#include <fltk/Window.h> -#include <fltk/run.h> -#include <fltk/events.h> -#include <fltk/x.h> +#define FL_INTERNALS +#include <FL/Fl_Window.H> +#include <FL/Fl.H> +#include <FL/x.H> #include "xembed.hh" -#if USE_X11 +#ifdef X_PROTOCOL typedef enum { XEMBED_EMBEDDED_NOTIFY = 0, @@ -41,12 +41,12 @@ Xembed::setXembedInfo(unsigned long flags) { unsigned long buffer[2]; - Atom xembed_info_atom = XInternAtom (fltk::xdisplay, "_XEMBED_INFO", false); + Atom xembed_info_atom = XInternAtom (fl_display, "_XEMBED_INFO", false); buffer[0] = 1; buffer[1] = flags; - XChangeProperty (fltk::xdisplay, + XChangeProperty (fl_display, xid, xembed_info_atom, xembed_info_atom, 32, PropModeReplace, @@ -60,35 +60,36 @@ Xembed::sendXembedEvent(uint32_t message) { memset (&xclient, 0, sizeof (xclient)); xclient.window = xid; xclient.type = ClientMessage; - xclient.message_type = XInternAtom (fltk::xdisplay, "_XEMBED", false); + xclient.message_type = XInternAtom (fl_display, "_XEMBED", false); xclient.format = 32; - xclient.data.l[0] = fltk::event_time; + xclient.data.l[0] = fl_event_time; xclient.data.l[1] = message; - XSendEvent(fltk::xdisplay, xid, False, NoEventMask, (XEvent *)&xclient); - XSync(fltk::xdisplay, False); + XSendEvent(fl_display, xid, False, NoEventMask, (XEvent *)&xclient); + XSync(fl_display, False); } int Xembed::handle(int e) { - if (e == fltk::PUSH) + if (e == FL_PUSH) sendXembedEvent(XEMBED_REQUEST_FOCUS); - return Window::handle(e); + return Fl_Window::handle(e); } -static int event_handler(int e, fltk::Window *w) { - Atom xembed_atom = XInternAtom (fltk::xdisplay, "_XEMBED", false); +static int event_handler(int e, Fl_Window *w) { + Atom xembed_atom = XInternAtom (fl_display, "_XEMBED", false); - if (fltk::xevent.type == ClientMessage) { - if (fltk::xevent.xclient.message_type == xembed_atom) { - long message = fltk::xevent.xclient.data.l[1]; + if (fl_xevent->type == ClientMessage) { + if (fl_xevent->xclient.message_type == xembed_atom) { + long message = fl_xevent->xclient.data.l[1]; switch (message) { case XEMBED_WINDOW_ACTIVATE: // Force a ConfigureNotify message so fltk can get the new // coordinates after a move of the embedder window. - w->resize(0, 0, w->w(), w->h()); + if (w) + w->resize(0,0, w->w(), w->h()); break; case XEMBED_WINDOW_DEACTIVATE: break; @@ -98,20 +99,20 @@ static int event_handler(int e, fltk::Window *w) { } } - return 0; + return Fl::handle_(e, w); } // TODO: Implement more XEMBED support; -void Xembed::create() { +void Xembed::show() { createInternal(xid); setXembedInfo(1); - fltk::add_event_handler(event_handler); + Fl::event_dispatch(event_handler); } void Xembed::createInternal(uint32_t parent) { - fltk::Window *window = this; - Colormap colormap = fltk::xcolormap; + Fl_Window *window = this; + Colormap colormap = fl_colormap; XSetWindowAttributes attr; attr.border_pixel = 0; @@ -133,18 +134,18 @@ void Xembed::createInternal(uint32_t parent) { | EnterWindowMask | LeaveWindowMask | PointerMotionMask; - fltk::CreatedWindow::set_xid(window, - XCreateWindow(fltk::xdisplay, + Fl_X::set_xid(window, + XCreateWindow(fl_display, parent, X, Y, W, H, 0, // borderwidth - fltk::xvisual->depth, + fl_visual->depth, InputOutput, - fltk::xvisual->visual, + fl_visual->visual, mask, &attr)); } -#else // USE_X11 +#else // X_PROTOCOL void Xembed::setXembedInfo(unsigned long flags) {}; @@ -154,12 +155,12 @@ Xembed::sendXembedEvent(uint32_t message) {}; int Xembed::handle(int e) { - return Window::handle(e); + return Fl_Window::handle(e); } void -Xembed::create() { - Window::create(); +Xembed::show() { + Fl_Window::show(); } #endif diff --git a/src/xembed.hh b/src/xembed.hh index 70d79c5f..d7663c8e 100644 --- a/src/xembed.hh +++ b/src/xembed.hh @@ -1,11 +1,11 @@ #ifndef __XEMBED_HH__ #define __XEMBED_HH__ -#include <fltk/Window.h> +#include <FL/Fl_Window.H> #include "d_size.h" -class Xembed : public fltk::Window { +class Xembed : public Fl_Window { private: uint32_t xid; void createInternal(uint32_t parent); @@ -13,10 +13,10 @@ class Xembed : public fltk::Window { void sendXembedEvent(uint32_t message); public: - Xembed(uint32_t xid, int _w, int _h) : fltk::Window(_w, _h) { + Xembed(uint32_t xid, int _w, int _h) : Fl_Window(_w, _h) { this->xid = xid; }; - void create(); + void show(); int handle(int event); }; diff --git a/test/dw_anchors_test.cc b/test/dw_anchors_test.cc index 977d724a..10525f1a 100644 --- a/test/dw_anchors_test.cc +++ b/test/dw_anchors_test.cc @@ -20,8 +20,8 @@ #include <ctype.h> -#include <fltk/Window.h> -#include <fltk/run.h> +#include <FL/Fl_Window.H> +#include <FL/Fl.H> #include "../dw/core.hh" #include "../dw/fltkcore.hh" @@ -36,7 +36,7 @@ using namespace dw::fltk; static FltkPlatform *platform; static Layout *layout; -static ::fltk::Window *window; +static Fl_Window *window; static FltkViewport *viewport; static Style *topWidgetStyle, *widgetStyle, *wordStyle, *headingStyle; static Textblock *topTextblock = NULL; @@ -47,7 +47,7 @@ static const char *numbers[10] = { "six", "seven", "eight", "nine", "ten" }; -static void anchorCallback (::fltk::Widget *widget, void *data) +static void anchorCallback (Fl_Widget *widget, void *data) { layout->setAnchor (numbers[(long)data]); } @@ -87,7 +87,7 @@ static void textTimeout (void *data) textblockNo++; if (textblockNo < 10) - ::fltk::repeat_timeout (1, textTimeout, NULL); + Fl::repeat_timeout (1, textTimeout, NULL); } @@ -98,10 +98,12 @@ int main(int argc, char **argv) platform = new FltkPlatform (); layout = new Layout (platform); - window = new ::fltk::Window(250, 200, "Dw Anchors Test"); + window = new Fl_Window(250, 200, "Dw Anchors Test"); + window->box(FL_NO_BOX); window->begin(); viewport = new FltkViewport (50, 0, 200, 200); + viewport->end(); layout->attachView (viewport); for (int i = 0; i < 10; i++) { @@ -109,10 +111,9 @@ int main(int argc, char **argv) strcpy (buf, numbers[i]); buf[0] = toupper (buf[0]); buttonLabel[i] = strdup(buf); - ::fltk::Button *button = - new ::fltk::Button(0, 20 * i, 50, 20, buttonLabel[i]); - button->callback (anchorCallback, (void*)i); - button->when (::fltk::WHEN_RELEASE); + Fl_Button *button = new Fl_Button(0, 20 * i, 50, 20, buttonLabel[i]); + button->callback (anchorCallback, (void*)(long)i); + button->when (FL_WHEN_RELEASE); } FontAttrs fontAttrs; @@ -121,10 +122,11 @@ int main(int argc, char **argv) fontAttrs.weight = 400; fontAttrs.style = FONT_STYLE_NORMAL; fontAttrs.letterSpacing = 0; + fontAttrs.fontVariant = FONT_VARIANT_NORMAL; StyleAttrs styleAttrs; styleAttrs.initValues (); - styleAttrs.font = Font::create (layout, &fontAttrs); + styleAttrs.font = dw::core::style::Font::create (layout, &fontAttrs); styleAttrs.margin.setVal (5); styleAttrs.color = Color::create (layout, 0x000000); styleAttrs.backgroundColor = Color::create (layout, 0xffffff); @@ -140,22 +142,22 @@ int main(int argc, char **argv) fontAttrs.size = 28; fontAttrs.weight = 700; - styleAttrs.font = Font::create (layout, &fontAttrs); + styleAttrs.font = dw::core::style::Font::create (layout, &fontAttrs); headingStyle = Style::create (layout, &styleAttrs); - ::fltk::add_timeout (0, textTimeout, NULL); + Fl::add_timeout (0, textTimeout, NULL); window->resizable(viewport); window->show(); - int errorCode = ::fltk::run(); + int errorCode = Fl::run(); topWidgetStyle->unref (); widgetStyle->unref (); wordStyle->unref (); headingStyle->unref (); for (int i = 0; i < 10; i++) - delete buttonLabel[i]; + free(buttonLabel[i]); delete layout; return errorCode; diff --git a/test/dw_border_test.cc b/test/dw_border_test.cc index b7586608..988abc33 100644 --- a/test/dw_border_test.cc +++ b/test/dw_border_test.cc @@ -19,8 +19,8 @@ -#include <fltk/Window.h> -#include <fltk/run.h> +#include <FL/Fl_Window.H> +#include <FL/Fl.H> #include "../dw/core.hh" #include "../dw/fltkcore.hh" @@ -38,7 +38,8 @@ int main(int argc, char **argv) FltkPlatform *platform = new FltkPlatform (); Layout *layout = new Layout (platform); - ::fltk::Window *window = new ::fltk::Window(200, 300, "Dw Border Test"); + Fl_Window *window = new Fl_Window(200, 300, "Dw Border Test"); + window->box(FL_NO_BOX); window->begin(); FltkViewport *viewport = new FltkViewport (0, 0, 200, 300); @@ -58,7 +59,8 @@ int main(int argc, char **argv) fontAttrs.weight = 400; fontAttrs.style = FONT_STYLE_NORMAL; fontAttrs.letterSpacing = 0; - styleAttrs.font = Font::create (layout, &fontAttrs); + fontAttrs.fontVariant = FONT_VARIANT_NORMAL; + styleAttrs.font = dw::core::style::Font::create (layout, &fontAttrs); styleAttrs.color = Color::create (layout, 0x000000); styleAttrs.backgroundColor = Color::create (layout, 0xffffff); @@ -115,7 +117,7 @@ int main(int argc, char **argv) window->resizable(viewport); window->show(); - int errorCode = ::fltk::run(); + int errorCode = Fl::run(); widgetStyle2->unref(); wordStyle->unref(); diff --git a/test/dw_example.cc b/test/dw_example.cc index 1ce643f8..52aa2440 100644 --- a/test/dw_example.cc +++ b/test/dw_example.cc @@ -19,8 +19,8 @@ -#include <fltk/Window.h> -#include <fltk/run.h> +#include <FL/Fl_Window.H> +#include <FL/Fl.H> #include "../dw/core.hh" #include "../dw/fltkcore.hh" @@ -33,7 +33,8 @@ int main(int argc, char **argv) dw::fltk::FltkPlatform *platform = new dw::fltk::FltkPlatform (); dw::core::Layout *layout = new dw::core::Layout (platform); - fltk::Window *window = new fltk::Window(200, 300, "Dw Example"); + Fl_Window *window = new Fl_Window(200, 300, "Dw Example"); + window->box(FL_NO_BOX); window->begin(); dw::fltk::FltkViewport *viewport = @@ -50,6 +51,7 @@ int main(int argc, char **argv) fontAttrs.weight = 400; fontAttrs.style = dw::core::style::FONT_STYLE_NORMAL; fontAttrs.letterSpacing = 0; + fontAttrs.fontVariant = dw::core::style::FONT_VARIANT_NORMAL; styleAttrs.font = dw::core::style::Font::create (layout, &fontAttrs); styleAttrs.color = @@ -95,7 +97,7 @@ int main(int argc, char **argv) window->resizable(viewport); window->show(); - int errorCode = fltk::run(); + int errorCode = Fl::run(); delete layout; diff --git a/test/dw_find_test.cc b/test/dw_find_test.cc index a0743754..e5c79fd3 100644 --- a/test/dw_find_test.cc +++ b/test/dw_find_test.cc @@ -19,9 +19,9 @@ -#include <fltk/Window.h> -#include <fltk/run.h> - +#include <FL/Fl.H> +#include <FL/Fl_Window.H> +#include <FL/Fl_Box.H> #include "../dw/core.hh" #include "../dw/fltkcore.hh" #include "../dw/fltkviewport.hh" @@ -35,12 +35,12 @@ using namespace dw::fltk; static FltkPlatform *platform; static Layout *layout; -static ::fltk::Window *window; +static Fl_Window *window; static FltkViewport *viewport; -static ::fltk::Button *findButton, *resetButton; -static ::fltk::Widget *resultLabel; +static Fl_Button *findButton, *resetButton; +static Fl_Widget *resultLabel; -static void findCallback (::fltk::Widget *widget, void *data) +static void findCallback (Fl_Widget *widget, void *data) { //switch(layout->search ("worm", true)) { switch(layout->search ("WORM", false, false)) { @@ -60,7 +60,7 @@ static void findCallback (::fltk::Widget *widget, void *data) resultLabel->redraw (); } -static void resetCallback (::fltk::Widget *widget, void *data) +static void resetCallback (Fl_Widget *widget, void *data) { layout->resetSearch (); resultLabel->label("---"); @@ -72,21 +72,26 @@ int main(int argc, char **argv) platform = new FltkPlatform (); layout = new Layout (platform); - window = new ::fltk::Window(200, 300, "Dw Find Test"); + window = new Fl_Window(200, 300, "Dw Find Test"); + window->box(FL_NO_BOX); window->begin(); viewport = new FltkViewport (0, 0, 200, 280); + viewport->end(); layout->attachView (viewport); - findButton = new ::fltk::Button(0, 280, 50, 20, "Find"); + findButton = new Fl_Button(0, 280, 50, 20, "Find"); findButton->callback (findCallback, NULL); - findButton->when (::fltk::WHEN_RELEASE); + findButton->when (FL_WHEN_RELEASE); + findButton->clear_visible_focus (); - resetButton = new ::fltk::Button(50, 280, 50, 20, "Reset"); + resetButton = new Fl_Button(50, 280, 50, 20, "Reset"); resetButton->callback (resetCallback, NULL); - resetButton->when (::fltk::WHEN_RELEASE); + resetButton->when (FL_WHEN_RELEASE); + resetButton->clear_visible_focus (); - resultLabel = new ::fltk::Widget(100, 280, 100, 20, "---"); + resultLabel = new Fl_Box(100, 280, 100, 20, "---"); + resultLabel->box(FL_FLAT_BOX); FontAttrs fontAttrs; fontAttrs.name = "Bitstream Charter"; @@ -94,10 +99,11 @@ int main(int argc, char **argv) fontAttrs.weight = 400; fontAttrs.style = FONT_STYLE_NORMAL; fontAttrs.letterSpacing = 0; + fontAttrs.fontVariant = FONT_VARIANT_NORMAL; StyleAttrs styleAttrs; styleAttrs.initValues (); - styleAttrs.font = Font::create (layout, &fontAttrs); + styleAttrs.font = dw::core::style::Font::create (layout, &fontAttrs); styleAttrs.margin.setVal (10); styleAttrs.color = Color::create (layout, 0x000000); styleAttrs.backgroundColor = Color::create (layout, 0xffffff); @@ -143,7 +149,7 @@ int main(int argc, char **argv) window->resizable(viewport); window->show(); - int errorCode = ::fltk::run(); + int errorCode = Fl::run(); delete layout; diff --git a/test/dw_float_test.cc b/test/dw_float_test.cc index 1da4c5aa..acafeafa 100644 --- a/test/dw_float_test.cc +++ b/test/dw_float_test.cc @@ -1,5 +1,5 @@ -#include <fltk/Window.h> -#include <fltk/run.h> +#include <FL/Fl.H> +#include <FL/Fl_Window.H> #include "../dw/core.hh" #include "../dw/fltkcore.hh" @@ -18,9 +18,9 @@ static void addTextToFloatTimeout (void *data) { printf("addTextToFloatTimeout\n"); - char *fWords[] = { "This", "is", "a", "float,", "which", "is", - "set", "aside", "from", "the", "main", - "text.", NULL }; + const char *fWords[] = { "This", "is", "a", "float,", "which", "is", + "set", "aside", "from", "the", "main", + "text.", NULL }; for(int k = 0; fWords[k]; k++) { firstFloat->addText(fWords[k], wordStyle); @@ -29,7 +29,7 @@ static void addTextToFloatTimeout (void *data) firstFloat->flush(); - ::fltk::repeat_timeout (2, addTextToFloatTimeout, NULL); + Fl::repeat_timeout (2, addTextToFloatTimeout, NULL); } int main(int argc, char **argv) @@ -37,7 +37,7 @@ int main(int argc, char **argv) FltkPlatform *platform = new FltkPlatform (); Layout *layout = new Layout (platform); - ::fltk::Window *window = new ::fltk::Window(400, 600, "Dw Floats Example"); + Fl_Window *window = new Fl_Window(400, 600, "Dw Floats Example"); window->begin(); FltkViewport *viewport = new FltkViewport (0, 0, 400, 600); @@ -53,7 +53,7 @@ int main(int argc, char **argv) fontAttrs.weight = 400; fontAttrs.style = FONT_STYLE_NORMAL; fontAttrs.letterSpacing = 0; - styleAttrs.font = Font::create (layout, &fontAttrs); + styleAttrs.font = core::style::Font::create (layout, &fontAttrs); styleAttrs.color = Color::create (layout, 0x000000); styleAttrs.backgroundColor = Color::create (layout, 0xffffff); @@ -90,10 +90,10 @@ int main(int argc, char **argv) snprintf(buf, sizeof(buf), "%d%s", i, (i == 1 ? "st" : (i == 2 ? "nd" : (i == 3 ? "rd" : "th")))); - char *words[] = { "This", "is", "the", buf, "paragraph.", - "Here", "comes", "some", "more", "text", - "to", "demonstrate", "word", "wrapping.", - NULL }; + const char *words[] = { "This", "is", "the", buf, "paragraph.", + "Here", "comes", "some", "more", "text", + "to", "demonstrate", "word", "wrapping.", + NULL }; for(int j = 0; words[j]; j++) { textblock->addText(words[j], wordStyle); @@ -106,9 +106,9 @@ int main(int argc, char **argv) Textblock *vloat = new Textblock (false); textblock->addFloatIntoGenerator(vloat, i == 3 ? leftFloatStyle : rightFloatStyle); - char *fWords[] = { "This", "is", "a", "float,", "which", "is", - "set", "aside", "from", "the", "main", - "text.", NULL }; + const char *fWords[] = { "This", "is", "a", "float,", "which", "is", + "set", "aside", "from", "the", "main", + "text.", NULL }; for(int k = 0; fWords[k]; k++) { vloat->addText(fWords[k], wordStyle); @@ -132,8 +132,8 @@ int main(int argc, char **argv) window->resizable(viewport); window->show(); - ::fltk::add_timeout (2, addTextToFloatTimeout, NULL); - int errorCode = ::fltk::run(); + Fl::add_timeout (2, addTextToFloatTimeout, NULL); + int errorCode = Fl::run(); wordStyle->unref(); delete layout; diff --git a/test/dw_images_scaled.cc b/test/dw_images_scaled.cc index c9f6e76e..2f8896e6 100644 --- a/test/dw_images_scaled.cc +++ b/test/dw_images_scaled.cc @@ -19,8 +19,8 @@ -#include <fltk/Window.h> -#include <fltk/run.h> +#include <FL/Fl.H> +#include <FL/Fl_Window.H> #include "../dw/core.hh" #include "../dw/fltkcore.hh" @@ -87,7 +87,7 @@ static void imageDrawTimeout (void *data) } if(imgRow < 200) - ::fltk::repeat_timeout (0.5, imageDrawTimeout, NULL); + Fl::repeat_timeout (0.5, imageDrawTimeout, NULL); } int main(int argc, char **argv) @@ -95,7 +95,8 @@ int main(int argc, char **argv) FltkPlatform *platform = new FltkPlatform (); layout = new Layout (platform); - ::fltk::Window *window = new ::fltk::Window(410, 210, "Dw Scaled Image"); + Fl_Window *window = new Fl_Window(410, 210, "Dw Scaled Image"); + window->box(FL_NO_BOX); window->begin(); FltkViewport *viewport = new FltkViewport (0, 0, 410, 210); @@ -113,7 +114,8 @@ int main(int argc, char **argv) fontAttrs.weight = 400; fontAttrs.style = FONT_STYLE_NORMAL; fontAttrs.letterSpacing = 0; - styleAttrs.font = Font::create (layout, &fontAttrs); + fontAttrs.fontVariant = FONT_VARIANT_NORMAL; + styleAttrs.font = dw::core::style::Font::create (layout, &fontAttrs); styleAttrs.color = Color::create (layout, 0x000000); styleAttrs.backgroundColor = Color::create (layout, 0xffffff); @@ -142,10 +144,10 @@ int main(int argc, char **argv) window->resizable(viewport); window->show(); - ::fltk::add_timeout (2.0, imageInitTimeout, NULL); - ::fltk::add_timeout (0.1, imageDrawTimeout, NULL); + Fl::add_timeout (2.0, imageInitTimeout, NULL); + Fl::add_timeout (0.1, imageDrawTimeout, NULL); - int errorCode = ::fltk::run(); + int errorCode = Fl::run(); delete layout; diff --git a/test/dw_images_scaled2.cc b/test/dw_images_scaled2.cc index 175ef414..2adb1770 100644 --- a/test/dw_images_scaled2.cc +++ b/test/dw_images_scaled2.cc @@ -19,8 +19,8 @@ -#include <fltk/Window.h> -#include <fltk/run.h> +#include <FL/Fl.H> +#include <FL/Fl_Window.H> #include "../dw/core.hh" #include "../dw/fltkcore.hh" @@ -64,7 +64,7 @@ static void imageDrawTimeout (void *data) } if(imgRow < 200) - ::fltk::repeat_timeout (0.5, imageDrawTimeout, NULL); + Fl::repeat_timeout (0.5, imageDrawTimeout, NULL); } int main(int argc, char **argv) @@ -72,7 +72,8 @@ int main(int argc, char **argv) FltkPlatform *platform = new FltkPlatform (); layout = new Layout (platform); - ::fltk::Window *window = new ::fltk::Window(410, 210, "Dw Scaled Image 2"); + Fl_Window *window = new Fl_Window(410, 210, "Dw Scaled Image 2"); + window->box(FL_NO_BOX); window->begin(); FltkViewport *viewport = new FltkViewport (0, 0, 410, 210); @@ -88,7 +89,8 @@ int main(int argc, char **argv) fontAttrs.weight = 400; fontAttrs.style = FONT_STYLE_NORMAL; fontAttrs.letterSpacing = 0; - styleAttrs.font = Font::create (layout, &fontAttrs); + fontAttrs.fontVariant = FONT_VARIANT_NORMAL; + styleAttrs.font = dw::core::style::Font::create (layout, &fontAttrs); styleAttrs.color = Color::create (layout, 0x000000); styleAttrs.backgroundColor = Color::create (layout, 0xffffff); @@ -113,8 +115,8 @@ int main(int argc, char **argv) styleAttrs.setBorderStyle (BORDER_SOLID); styleAttrs.padding.setVal (1); styleAttrs.backgroundColor = NULL; - styleAttrs.width = createPerLength (0.5); - styleAttrs.height = createPerLength (0.5); + styleAttrs.width = createPerLength (0.25); + styleAttrs.height = createPerLength (0.25); Style *imageStyle1 = Style::create (layout, &styleAttrs); image1 = new dw::Image ("A longer ALT Text to demonstrate clipping."); @@ -137,10 +139,10 @@ int main(int argc, char **argv) window->resizable(viewport); window->show(); - ::fltk::add_timeout (3.0, imageInitTimeout, NULL); - ::fltk::add_timeout (0.1, imageDrawTimeout, NULL); + Fl::add_timeout (3.0, imageInitTimeout, NULL); + Fl::add_timeout (0.1, imageDrawTimeout, NULL); - int errorCode = ::fltk::run(); + int errorCode = Fl::run(); delete layout; diff --git a/test/dw_images_simple.cc b/test/dw_images_simple.cc index 39b7ed90..8f00f847 100644 --- a/test/dw_images_simple.cc +++ b/test/dw_images_simple.cc @@ -19,8 +19,8 @@ -#include <fltk/Window.h> -#include <fltk/run.h> +#include <FL/Fl.H> +#include <FL/Fl_Window.H> #include "../dw/core.hh" #include "../dw/fltkcore.hh" @@ -66,7 +66,7 @@ static void imageDrawTimeout (void *data) } if(imgRow < 200) - ::fltk::repeat_timeout (0.5, imageDrawTimeout, NULL); + Fl::repeat_timeout (0.5, imageDrawTimeout, NULL); } */ @@ -88,7 +88,7 @@ static void imageDrawTimeout (void *data) } if(imgRow < 200) - ::fltk::repeat_timeout (0.5, imageDrawTimeout, NULL); + Fl::repeat_timeout (0.5, imageDrawTimeout, NULL); } int main(int argc, char **argv) @@ -96,7 +96,8 @@ int main(int argc, char **argv) FltkPlatform *platform = new FltkPlatform (); layout = new Layout (platform); - ::fltk::Window *window = new ::fltk::Window(410, 210, "Dw Simple Image"); + Fl_Window *window = new Fl_Window(410, 210, "Dw Simple Image"); + window->box(FL_NO_BOX); window->begin(); FltkViewport *viewport = new FltkViewport (0, 0, 410, 210); @@ -112,7 +113,8 @@ int main(int argc, char **argv) fontAttrs.weight = 400; fontAttrs.style = FONT_STYLE_NORMAL; fontAttrs.letterSpacing = 0; - styleAttrs.font = Font::create (layout, &fontAttrs); + fontAttrs.fontVariant = FONT_VARIANT_NORMAL; + styleAttrs.font = dw::core::style::Font::create (layout, &fontAttrs); styleAttrs.color = Color::create (layout, 0x000000); styleAttrs.backgroundColor = Color::create (layout, 0xffffff); @@ -141,10 +143,10 @@ int main(int argc, char **argv) window->resizable(viewport); window->show(); - ::fltk::add_timeout (2.0, imageInitTimeout, NULL); - ::fltk::add_timeout (0.1, imageDrawTimeout, NULL); + Fl::add_timeout (2.0, imageInitTimeout, NULL); + Fl::add_timeout (0.1, imageDrawTimeout, NULL); - int errorCode = ::fltk::run(); + int errorCode = Fl::run(); delete layout; diff --git a/test/dw_imgbuf_mem_test.cc b/test/dw_imgbuf_mem_test.cc index 33131134..45beef8b 100644 --- a/test/dw_imgbuf_mem_test.cc +++ b/test/dw_imgbuf_mem_test.cc @@ -17,11 +17,6 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ - - -#include <fltk/Window.h> -#include <fltk/run.h> - #include "../dw/core.hh" #include "../dw/fltkcore.hh" diff --git a/test/dw_links.cc b/test/dw_links.cc index 44628b28..5622cbd5 100644 --- a/test/dw_links.cc +++ b/test/dw_links.cc @@ -19,8 +19,8 @@ -#include <fltk/Window.h> -#include <fltk/run.h> +#include <FL/Fl.H> +#include <FL/Fl_Window.H> #include "../dw/core.hh" #include "../dw/fltkcore.hh" @@ -76,7 +76,8 @@ int main(int argc, char **argv) FltkPlatform *platform = new FltkPlatform (); Layout *layout = new Layout (platform); - ::fltk::Window *window = new ::fltk::Window(200, 300, "Dw Links"); + Fl_Window *window = new Fl_Window(200, 300, "Dw Links"); + window->box(FL_NO_BOX); window->begin(); FltkViewport *viewport = new FltkViewport (0, 0, 200, 300); @@ -92,7 +93,8 @@ int main(int argc, char **argv) fontAttrs.weight = 400; fontAttrs.style = FONT_STYLE_NORMAL; fontAttrs.letterSpacing = 0; - styleAttrs.font = Font::create (layout, &fontAttrs); + fontAttrs.fontVariant = FONT_VARIANT_NORMAL; + styleAttrs.font = dw::core::style::Font::create (layout, &fontAttrs); styleAttrs.color = Color::create (layout, 0x000000); styleAttrs.backgroundColor = Color::create (layout, 0xffffff); @@ -153,7 +155,7 @@ int main(int argc, char **argv) window->resizable(viewport); window->show(); - int errorCode = ::fltk::run(); + int errorCode = Fl::run(); delete layout; diff --git a/test/dw_links2.cc b/test/dw_links2.cc index 294950af..b8e8c55b 100644 --- a/test/dw_links2.cc +++ b/test/dw_links2.cc @@ -19,8 +19,9 @@ -#include <fltk/Window.h> -#include <fltk/run.h> +#include <FL/Fl.H> +#include <FL/Fl_Window.H> +#include <FL/Fl_Box.H> #include "../dw/core.hh" #include "../dw/fltkcore.hh" @@ -78,22 +79,23 @@ int main(int argc, char **argv) FltkPlatform *platform = new FltkPlatform (); Layout *layout = new Layout (platform); - ::fltk::Window *window = new ::fltk::Window(200, 300, "Dw Links2"); + Fl_Window *window = new Fl_Window(200, 300, "Dw Links2"); + window->box(FL_NO_BOX); window->begin(); - ::fltk::Widget *Panel = new ::fltk::Widget(0, 0, ww, lh, "CONTROL PANEL"); - - Panel->color(::fltk::GRAY15); - Panel->labelcolor(::fltk::WHITE); - ::fltk::Widget *Main = - new ::fltk::Widget(0, lh, ww, wh - 2*lh, "MAIN RENDERING AREA"); - Main->color(::fltk::GRAY20); - Main->labelcolor(::fltk::WHITE); + Fl_Widget *Panel = new Fl_Box(0, 0, ww, lh, "CONTROL PANEL"); + + Panel->color(FL_GRAY_RAMP + 3); + Panel->labelcolor(FL_WHITE); + Panel->box(FL_FLAT_BOX); + Fl_Widget *Main = new Fl_Box(0, lh, ww, wh - 2*lh, "MAIN RENDERING AREA"); + Main->color(FL_GRAY_RAMP + 4); + Main->labelcolor(FL_WHITE); MainIdx = window->find(Main); /* status bar */ - ::fltk::Widget *Bar = - new ::fltk::Widget(0, wh - lh, 200, lh, "STATUS BAR..."); - Bar->color(::fltk::GRAY15); - Bar->labelcolor(::fltk::WHITE); + Fl_Widget *Bar = new Fl_Box(0, wh - lh, 200, lh, "STATUS BAR..."); + Bar->color(FL_GRAY_RAMP + 3); + Bar->labelcolor(FL_WHITE); + Bar->box(FL_FLAT_BOX); window->resizable(Main); window->end(); @@ -120,7 +122,8 @@ int main(int argc, char **argv) fontAttrs.weight = 400; fontAttrs.style = FONT_STYLE_NORMAL; fontAttrs.letterSpacing = 0; - styleAttrs.font = Font::create (layout, &fontAttrs); + fontAttrs.fontVariant = FONT_VARIANT_NORMAL; + styleAttrs.font = dw::core::style::Font::create (layout, &fontAttrs); styleAttrs.color = Color::create (layout, 0x000000); styleAttrs.backgroundColor = Color::create (layout, 0xffffff); @@ -181,7 +184,7 @@ int main(int argc, char **argv) window->resizable(viewport); window->show(); - int errorCode = ::fltk::run(); + int errorCode = Fl::run(); delete layout; diff --git a/test/dw_lists.cc b/test/dw_lists.cc index 2725c34d..12fa1627 100644 --- a/test/dw_lists.cc +++ b/test/dw_lists.cc @@ -19,8 +19,8 @@ -#include <fltk/Window.h> -#include <fltk/run.h> +#include <FL/Fl.H> +#include <FL/Fl_Window.H> #include "../dw/core.hh" #include "../dw/fltkcore.hh" @@ -38,7 +38,8 @@ int main(int argc, char **argv) FltkPlatform *platform = new FltkPlatform (); Layout *layout = new Layout (platform); - ::fltk::Window *window = new ::fltk::Window(200, 300, "Dw Lists"); + Fl_Window *window = new Fl_Window(200, 300, "Dw Lists"); + window->box(FL_NO_BOX); window->begin(); FltkViewport *viewport = new FltkViewport (0, 0, 200, 300); @@ -54,7 +55,8 @@ int main(int argc, char **argv) fontAttrs.weight = 400; fontAttrs.style = FONT_STYLE_NORMAL; fontAttrs.letterSpacing = 0; - styleAttrs.font = Font::create (layout, &fontAttrs); + fontAttrs.fontVariant = FONT_VARIANT_NORMAL; + styleAttrs.font = dw::core::style::Font::create (layout, &fontAttrs); styleAttrs.color = Color::create (layout, 0x000000); styleAttrs.backgroundColor = Color::create (layout, 0xffffff); @@ -126,7 +128,7 @@ int main(int argc, char **argv) window->resizable(viewport); window->show(); - int errorCode = ::fltk::run(); + int errorCode = Fl::run(); delete layout; diff --git a/test/dw_resource_test.cc b/test/dw_resource_test.cc index 28611bb0..a2a26c62 100644 --- a/test/dw_resource_test.cc +++ b/test/dw_resource_test.cc @@ -19,8 +19,8 @@ -#include <fltk/Window.h> -#include <fltk/run.h> +#include <FL/Fl.H> +#include <FL/Fl_Window.H> #include "../dw/core.hh" #include "../dw/fltkcore.hh" @@ -39,7 +39,8 @@ int main(int argc, char **argv) FltkPlatform *platform = new FltkPlatform (); Layout *layout = new Layout (platform); - ::fltk::Window *window = new ::fltk::Window(410, 210, "Dw Resource test"); + Fl_Window *window = new Fl_Window(410, 210, "Dw Resource test"); + window->box(FL_NO_BOX); window->begin(); FltkViewport *viewport = new FltkViewport (0, 0, 410, 210); @@ -55,7 +56,8 @@ int main(int argc, char **argv) fontAttrs.weight = 400; fontAttrs.style = FONT_STYLE_NORMAL; fontAttrs.letterSpacing = 0; - styleAttrs.font = Font::create (layout, &fontAttrs); + fontAttrs.fontVariant = FONT_VARIANT_NORMAL; + styleAttrs.font = dw::core::style::Font::create (layout, &fontAttrs); styleAttrs.color = Color::create (layout, 0x000000); styleAttrs.backgroundColor = Color::create (layout, 0xffffff); @@ -71,6 +73,8 @@ int main(int argc, char **argv) styleAttrs.margin.setVal (0); styleAttrs.backgroundColor = NULL; + widgetStyle = Style::create (layout, &styleAttrs); + SelectionResource *res = layout->getResourceFactory()->createListResource (ListResource::SELECTION_AT_MOST_ONE, 4); //SelectionResource *res = @@ -83,14 +87,14 @@ int main(int argc, char **argv) widgetStyle->unref(); for(int i = 0; i < 50; i++) - res->addItem ("Hello, world!", true, false); + res->addItem ("Hello, world!", true, i == 0 ? true : false); textblock->flush (); window->resizable(viewport); window->show(); - int errorCode = ::fltk::run(); + int errorCode = Fl::run(); delete layout; diff --git a/test/dw_table.cc b/test/dw_table.cc index b0e9c4db..75842e60 100644 --- a/test/dw_table.cc +++ b/test/dw_table.cc @@ -19,8 +19,8 @@ -#include <fltk/Window.h> -#include <fltk/run.h> +#include <FL/Fl.H> +#include <FL/Fl_Window.H> #include "../dw/core.hh" #include "../dw/fltkcore.hh" @@ -38,7 +38,8 @@ int main(int argc, char **argv) FltkPlatform *platform = new FltkPlatform (); Layout *layout = new Layout (platform); - ::fltk::Window *window = new ::fltk::Window(300, 300, "Dw Table"); + Fl_Window *window = new Fl_Window(300, 300, "Dw Table"); + window->box(FL_NO_BOX); window->begin(); FltkViewport *viewport = new FltkViewport (0, 0, 300, 300); @@ -62,7 +63,8 @@ int main(int argc, char **argv) fontAttrs.weight = 400; fontAttrs.style = FONT_STYLE_NORMAL; fontAttrs.letterSpacing = 0; - styleAttrs.font = Font::create (layout, &fontAttrs); + fontAttrs.fontVariant = FONT_VARIANT_NORMAL; + styleAttrs.font = dw::core::style::Font::create (layout, &fontAttrs); Style *tableStyle = Style::create (layout, &styleAttrs); @@ -107,7 +109,7 @@ int main(int argc, char **argv) window->resizable(viewport); window->show(); - int errorCode = ::fltk::run(); + int errorCode = Fl::run(); delete layout; diff --git a/test/dw_table_aligned.cc b/test/dw_table_aligned.cc index 67cf21f3..022e7026 100644 --- a/test/dw_table_aligned.cc +++ b/test/dw_table_aligned.cc @@ -19,8 +19,8 @@ -#include <fltk/Window.h> -#include <fltk/run.h> +#include <FL/Fl.H> +#include <FL/Fl_Window.H> #include "../dw/core.hh" #include "../dw/fltkcore.hh" @@ -38,7 +38,8 @@ int main(int argc, char **argv) FltkPlatform *platform = new FltkPlatform (); Layout *layout = new Layout (platform); - ::fltk::Window *window = new ::fltk::Window(200, 300, "Dw Table Aligned"); + Fl_Window *window = new Fl_Window(200, 300, "Dw Table Aligned"); + window->box(FL_NO_BOX); window->begin(); FltkViewport *viewport = new FltkViewport (0, 0, 200, 300); @@ -57,7 +58,8 @@ int main(int argc, char **argv) fontAttrs.weight = 400; fontAttrs.style = FONT_STYLE_NORMAL; fontAttrs.letterSpacing = 0; - styleAttrs.font = Font::create (layout, &fontAttrs); + fontAttrs.fontVariant = FONT_VARIANT_NORMAL; + styleAttrs.font = dw::core::style::Font::create (layout, &fontAttrs); styleAttrs.color = Color::create (layout, 0x000000); styleAttrs.backgroundColor = Color::create (layout, 0xa0a0a0); @@ -111,7 +113,7 @@ int main(int argc, char **argv) window->resizable(viewport); window->show(); - int errorCode = ::fltk::run(); + int errorCode = Fl::run(); delete layout; diff --git a/test/dw_ui_test.cc b/test/dw_ui_test.cc index 2bc35893..60893f06 100644 --- a/test/dw_ui_test.cc +++ b/test/dw_ui_test.cc @@ -19,8 +19,8 @@ -#include <fltk/Window.h> -#include <fltk/run.h> +#include <FL/Fl.H> +#include <FL/Fl_Window.H> #include "../dw/core.hh" #include "../dw/fltkcore.hh" @@ -43,7 +43,8 @@ int main(int argc, char **argv) FltkPlatform *platform = new FltkPlatform (); Layout *layout = new Layout (platform); - ::fltk::Window *window = new ::fltk::Window(400, 400, "Dw UI Test"); + Fl_Window *window = new Fl_Window(400, 400, "Dw UI Test"); + window->box(FL_NO_BOX); window->begin(); FltkViewport *viewport = new FltkViewport (0, 0, 400, 400); @@ -61,7 +62,8 @@ int main(int argc, char **argv) fontAttrs.weight = 400; fontAttrs.style = FONT_STYLE_NORMAL; fontAttrs.letterSpacing = 0; - styleAttrs.font = Font::create (layout, &fontAttrs); + fontAttrs.fontVariant = FONT_VARIANT_NORMAL; + styleAttrs.font = dw::core::style::Font::create (layout, &fontAttrs); Style *tableStyle = Style::create (layout, &styleAttrs); @@ -119,7 +121,7 @@ int main(int argc, char **argv) const char *radiovalues[] = { "radio1", "radio2", NULL }; form->addRadioButtonResource ("val3", radiores1, radiovalues); form->addCheckButtonResource ("check", checkres); - const char *selvalues[] = { "i1", "i11", "i12", "i13", "i2", + const char *selvalues[] = { "i1", "g1", "i11", "i12", "i13", "i2", "g2", "i21", "i22", "i23", "i3", NULL }; form->addSelectionResource ("val4", selres[0], selvalues); form->addSelectionResource ("val5", selres[1], selvalues); @@ -207,9 +209,9 @@ int main(int argc, char **argv) selres[i]->addItem("item 1/3", false, false); selres[i]->popGroup(); - selres[i]->addItem("item 2", true, i == 1); + selres[i]->addItem("item 2", false, i == 1); - selres[i]->pushGroup("group 2", false); + selres[i]->pushGroup("group 2", true); selres[i]->addItem("item 2/1", true, false); selres[i]->addItem("item 2/2", true, false); selres[i]->addItem("item 2/3", false, false); @@ -232,7 +234,7 @@ int main(int argc, char **argv) window->resizable(viewport); window->show(); - int errorCode = ::fltk::run(); + int errorCode = Fl::run(); delete form; delete layout; diff --git a/test/fltk_browser.cc b/test/fltk_browser.cc index 11dfcbeb..bdbec72c 100644 --- a/test/fltk_browser.cc +++ b/test/fltk_browser.cc @@ -19,28 +19,25 @@ -#include <fltk/Window.h> -#include <fltk/Browser.h> -#include <fltk/MultiBrowser.h> -#include <fltk/Item.h> -#include <fltk/run.h> - -using namespace fltk; +#include <FL/Fl_Window.H> +#include <FL/Fl_Multi_Browser.H> +#include <FL/Fl.H> int main (int argc, char *argv[]) { - Window *window = new Window (300, 300, "FLTK Browser"); + Fl_Window *window = new Fl_Window (300, 300, "FLTK Browser"); + window->box(FL_NO_BOX); window->begin (); - Browser *browser = new MultiBrowser (0, 0, 300, 300); + Fl_Multi_Browser *browser = new Fl_Multi_Browser (0, 0, 300, 300); browser->begin (); for (int i = 0; i < 10; i++) { - new Item ("first"); - new Item ("second"); - new Item ("third"); + browser->add("first"); + browser->add("second"); + browser->add("third"); } window->resizable(browser); window->show(); - return run(); + return Fl::run(); } diff --git a/test/form.cc b/test/form.cc index 4bebd520..82938a16 100644 --- a/test/form.cc +++ b/test/form.cc @@ -32,7 +32,7 @@ Form::ResourceDecorator::ResourceDecorator (const char *name) Form::ResourceDecorator::~ResourceDecorator () { - delete name; + free((char *)name); } Form::TextResourceDecorator::TextResourceDecorator (const char *name, @@ -57,15 +57,15 @@ Form::RadioButtonResourceDecorator::RadioButtonResourceDecorator while (values[n]) n++; this->values = new const char*[n + 1]; - for(int i = 0; i < n; i++) + for (int i = 0; i < n; i++) this->values[i] = strdup (values[i]); this->values[n] = 0; } Form::RadioButtonResourceDecorator::~RadioButtonResourceDecorator () { - for(int i = 0; values[i]; i++) - delete values[i]; + for (int i = 0; values[i]; i++) + free((char *)values[i]); delete[] values; } @@ -115,7 +115,7 @@ Form::SelectionResourceDecorator::SelectionResourceDecorator Form::SelectionResourceDecorator::~SelectionResourceDecorator () { for(int i = 0; values[i]; i++) - delete values[i]; + free((char *)values[i]); delete[] values; } @@ -159,8 +159,8 @@ Form::FormClickedReceiver::FormClickedReceiver (Form *form, const char *name, Form::FormClickedReceiver::~FormClickedReceiver () { - delete name; - delete[] value; + free((char *)name); + free((char *)value); } void Form::FormClickedReceiver::clicked (Resource *resource, |