Codebase list dillo / 6642af7
Merge branch 'upstream' Axel Beckert 12 years ago
54 changed file(s) with 969 addition(s) and 695 deletion(s). Raw diff Collapse all Expand all
11 Dillo project
22 =============================================================================
33
4 dillo-3.0 [not released yet]
4 dillo-3.0 [September ??, 2011]
55
66 +- Ported Dillo to FLTK-1.3.
77 Patch: corvid, Johannes Hofmann, Jorge Arellano Cid
8 +- Default binding for close-all changed from Alt-q to Ctrl-q.
8 +- Rewrote the User Interface: much simpler design and event handling.
9 - Avoid double render after going Back or Forward (takes half the time now!).
10 - Added on-the-fly panel resize (tiny/small/medium and normal/small icons).
11 - Implemented a custom tabs handler (to allow fine control of it).
12 - Rewrote dw's crossing-events dispatcher (avoids redundant events).
13 - Fixed a years old bug: stamped tooltips when scrolling with keyboard.
14 - Allow multiple search engines to be set in dillorc, with a menu in the web
15 search dialog to select between them.
16 - Added an optional label to dillorc's search_url. Format: "[<label> ]<url>"
17 - Fixed a border case in URL resolver: empty path + {query|fragment} (BUG#948)
18 - Avoid a certificate dialog storm on some HTTPS sites (BUG#868).
19 - Cancel the expected URL after offering a download (BUG#982)
20 - Default binding for close-all changed from Alt-q to Ctrl-q.
921 - Default binding for close-tab changed from Ctrl-q to Ctrl-w.
1022 - Add right_click_closes_tab preference (default is middle click).
1123 - 'hide-panels' key action now hides the findbar if present, and toggles
1224 display of the control panels otherwise.
25 - Removed 'large' option of panel_size preference.
1326 - Remove 'fullscreen' key action.
27 - Eliminated a pack of 22 compiler warnings (gcc-4.6.1 amd64)
28 - Lots of minor bug-fixes.
1429 Patches: Jorge Arellano Cid
1530 +- Remove --enable-ansi configure option.
1631 - Limit saved cookie size.
1732 - Allow binding to non-ASCII keys and multimedia keys.
1833 - Enable line wrapping for <textarea>. (BUG#903)
34 - Wrap image alt text.
1935 Patches: corvid
36 +- Add support for CSS adjacent sibling selectors.
37 - Collapse parent's and first child's top margin.
38 Patch: Johannes Hofmann
39 +- Default binding for left-tab changed to Shift-Ctrl-Tab.
40 Patch: Jeremy Henty
41
42 Note: these are user-visible changes. The full Changelog is kept
43 in our Mercurial repository at http://hg.dillo.org/dillo
44
2045
2146 -----------------------------------------------------------------------------
2247
23 dillo-2.2.1 [not released yet]
24
25 +- Implemented "View source" as a dpi.
48 dillo-2.2.1 [July 18, 2011]
49
50 +- Fix fullwindow start.
51 - Implemented "View source" as a dpi.
52 - Fix: vsource html, fix entities display, indentation.
2653 - Accept application/xhtml+xml.
2754 - Small caps support.
2855 - Border-collapse, border-style properties.
56 - Removed gcc warnings for 64bit
2957 Patches: Jorge Arellano Cid
3058 +- Configurable User-Agent HTTP header.
3159 Patch: Alexander Voigt, corvid
2626
2727 The new FLTK2-based dillo code is released! (under GPL3)
2828
29 Jul 2011
30
31 Dillo switches to fltk-1.3.0.
32 dillo-2.2.1, the last of the 2.x series is released.
33
34 Sep 2011
35
36 dillo-3.0, the first of the 3.x series is released.
37
38
2939 Jorge.-
3040 jcid@dillo.org
3141 Project maintainer, core developer, patcher, you name it! :-)
11 Dillo web browser
22 ===================
33
4 Dillo 2.2 features a major overhaul of the cookies subsystem,
5 a reimplementation of the Dillo Plugin (DPI) API, a configurable
6 connection limit, and various CSS improvements.
4 Dillo-3.0 is the first release of the newest branch, which is
5 based on the already released fltk-1.3 toolkit. This is big news
6 because it clears the way for Dillo to return to those
7 distributions which had excluded Dillo2 due to FLTK2 never
8 being officially released.
79
8 This release is part of the Dillo2 series. In Dillo2, significant
9 parts of the codebase were ported to C++, and the rendering engine was
10 modified to use the FLTK2 library rather than GTK1.
10 The development effort shifted to the dillo-3.x branch long ago,
11 and it became the active one; dillo-2.x received less and less
12 attention, and dillo-2.2.1 became the last of its series.
1113
12 Here's a list of some well-known problems:
14 The core team will focus on implementing the CSS feature of
15 floating elements. This will greatly improve dillo's web page
16 rendering since many sites have adopted floats instead of tables.
17
18 The new dillo3 has shown excellent stability.
19
20 The core team welcomes developers willing to join our workforce.
21
22
23 Here's a list of some old well-known problems of dillo:
1324
1425 * no FRAMES rendering
1526 * no https (there's a barebones prototype).
1627
17 -----
18 FLTK2
19 -----
2028
21 The FLTK2 library is statically linked into Dillo2.
22 You can get it from fltk.org.
23 The recommended version is >= r6916. e.g. in:
29 -------
30 FLTK1.3
31 -------
2432
25 http://fltk.org/software.php?VERSION=2.0.x-r6916
33 You can get FLTK-1.3 here:
34
35 http://fltk.org/software.php?VERSION=1.3.0
36
37
38 ---------------------------
39 Building dillo from sources
40 ---------------------------
41
42 1.- Install fltk:
43
44 tar jxvf fltk-1.3.0-source.tar.gz
45 cd fltk-1.3.0
46 less README.unix
47 make
48 sudo make install
49 cd ..
50
51 (don't configure fltk with --enable-cairo)
52
53 2.- Then dillo3:
54
55 tar jxvf dillo-3.0.tar.bz2
56 cd dillo-3.0
57 ./autogen.sh; ./configure; make
58 sudo make install-strip
2659
2760
2861 ------------
6699
67100 Jorge.-
68101 (jcid@dillo.org)
69 June, 2009
102 August, 2011
7777 /* Define to the one symbol short name of this package. */
7878 #undef PACKAGE_TARNAME
7979
80 /* Define to the home page for this package. */
81 #undef PACKAGE_URL
82
8083 /* Define to the version of this package. */
8184 #undef PACKAGE_VERSION
8285
102105 #undef VERSION
103106
104107 /* Define for Solaris 2.5.1 so the uint32_t typedef from <sys/synch.h>,
105 <pthread.h>, or <semaphore.h> is not used. If the typedef was allowed, the
108 <pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
106109 #define below would cause a syntax error. */
107110 #undef _UINT32_T
108111
111111 # Set the URLs used by the web search dialog.
112112 # "%s" is replaced with the search keywords separated by '+'.
113113 # Format: search_url="[<label> ]<url>"
114 # You can have several search engines, with the first being the default.
115 # e.g.
116 # search_url="DuckDuckGo http://duckduckgo.com/html?q=%s"
117 # search_url="Wikipedia http://www.wikipedia.org/wiki/Special:Search?search=%s"
118 # search_url="Lycos http://search.lycos.com/?query=%s"
119 #search_url="http://www.google.com/search?ie=UTF-8&oe=UTF-8&q=%s"
114 # You can enable multiple search_url strings at once and select from among
115 # them at runtime, with the first being the default.
116 search_url="http://duckduckgo.com/lite/?kp=-1&q=%s"
117 search_url="Scroogle https://ssl.scroogle.org/cgi-bin/nbbwssl.cgi?Gw=%s"
118 search_url="Wikipedia http://www.wikipedia.org/w/index.php?search=%s&go=Go"
119 search_url="Free Dictionary http://www.thefreedictionary.com/%s"
120 search_url="Google http://www.google.com/search?ie=UTF-8&oe=UTF-8&q=%s"
120121
121122 # If set, dillo will ask web servers to send pages in this language.
122123 # This setting does NOT change dillo's user interface.
190191 # USER INTERFACE SECTION
191192 #-------------------------------------------------------------------------
192193
193 # Size of dillo panel (used to enlarge the browsing area)
194 # tiny : recommended for iPAQ (with small_icons)
195 # small : very nice! (it's "medium" without icon titles)
196 # medium : nice!
197 # large : Traditional
194 # Size of dillo panel
195 # tiny : buttons, location, and progress boxes in one row
196 # small : location in one row, buttons + progress boxes in another
197 # medium : adds text labels to buttons and boxes
198198 # panel_size=tiny
199199 # panel_size=small
200200 #panel_size=medium
201 # panel_size=large
202201
203202 #small_icons=NO
204203
876876
877877 dstr = dStr_sized_new(64);
878878 while ((ch = fgetc(stream)) != EOF) {
879 if (ch == '\\') {
880 /* continue with the next line */
881 while ((ch = fgetc(stream)) != EOF && ch != '\n') ;
882 continue;
883 }
884879 dStr_append_c(dstr, ch);
885880 if (ch == '\n')
886881 break;
308308 <tr><td>Shift-Back or "<b>.</b>" <td>> <td>next page
309309 <tr><td>Alt-F <td>File <td>file menu
310310 <tr><td>Ctrl-TabKey <td>TabKey <td>Next tab
311 <tr><td>Shift-TabKey <td>TabKey <td>Previous tab
311 <tr><td>Ctrl-Shift-TabKey <td>TabKey <td>Previous tab
312312 <tr><td>Esc <td>escape <td>close dialog,
313313 close findbar,<br>
314314 Hide/show control panels
107107 int LogPipe[2];
108108 char *shortname, *fullname;
109109 char *target_dir;
110 int log_len, log_max, log_state;
110 size_t log_len, log_max;
111 int log_state;
111112 char *log_text;
112113 time_t init_time;
113114 char **dl_argv;
189190 DLAction check_filename(char **p_dl_dest);
190191 };
191192
193 /*
194 * FLTK cannot be dissuaded from interpreting '@' in a tooltip
195 * as indicating a symbol unless we escape it.
196 */
197 static char *escape_tooltip(const char *buf, ssize_t len)
198 {
199 if (len < 0)
200 len = 0;
201
202 char *ret = (char *) malloc(2 * len + 1);
203 char *dest = ret;
204
205 while (len-- > 0) {
206 if (*buf == '@')
207 *dest++ = *buf;
208 *dest++ = *buf++;
209 }
210 *dest = '\0';
211
212 return ret;
213 }
214
192215
193216 /*
194217 * Global variables
475498 void DLItem::log_text_add(const char *buf, ssize_t st)
476499 {
477500 const char *p;
478 char *q, *d, num[64];
501 char *esc_str, *q, *d, num[64];
502 size_t esc_len;
503
504 // WORKAROUND: We have to escape '@' in FLTK tooltips.
505 esc_str = escape_tooltip(buf, st);
506 esc_len = strlen(esc_str);
479507
480508 // Make room...
481 if (log_len + st >= log_max) {
482 log_max = log_len + st + 1024;
509 if (log_len + esc_len >= log_max) {
510 log_max = log_len + esc_len + 1024;
483511 log_text = (char *) realloc (log_text, log_max);
484512 log_text[log_len] = 0;
485513 prTitle->tooltip(log_text);
487515
488516 // FSM to remove wget's "dot-progress" (i.e. "^ " || "^[0-9]+K")
489517 q = log_text + log_len;
490 for (p = buf; (p - buf) < st; ++p) {
518 for (p = esc_str; (size_t)(p - esc_str) < esc_len; ++p) {
491519 switch (log_state) {
492520 case ST_newline:
493521 if (*p == ' ') {
522550 *q = 0;
523551 log_len = strlen(log_text);
524552
553 free(esc_str);
554
525555 // Now scan for the length of the file
526556 if (total_bytesize == -1) {
527557 p = strstr(log_text, "\nLength: ");
10911121
10921122 // ---------------------------------------------------------------------------
10931123
1124 /*
1125 * Set FL_NORMAL_LABEL to interpret neither symbols (@) nor shortcuts (&)
1126 */
1127 static void custLabelDraw(const Fl_Label* o, int X, int Y, int W, int H,
1128 Fl_Align align)
1129 {
1130 const int interpret_symbols = 0;
1131
1132 fl_draw_shortcut = 0;
1133 fl_font(o->font, o->size);
1134 fl_color((Fl_Color)o->color);
1135 fl_draw(o->value, X, Y, W, H, align, o->image, interpret_symbols);
1136 }
1137
1138 static void custLabelMeasure(const Fl_Label* o, int& W, int& H)
1139 {
1140 const int interpret_symbols = 0;
1141
1142 fl_draw_shortcut = 0;
1143 fl_font(o->font, o->size);
1144 fl_measure(o->value, W, H, interpret_symbols);
1145 }
1146
10941147
10951148
10961149 //int main(int argc, char **argv)
11001153
11011154 Fl::lock();
11021155
1156 // Disable '@' and '&' interpretation in normal labels.
1157 Fl::set_labeltype(FL_NORMAL_LABEL, custLabelDraw, custLabelMeasure);
1158
11031159 // Create the download window
11041160 dl_win = new DLWin(ww, wh);
11051161
129129 SSL * ssl_connection = NULL;
130130
131131 char *dpip_tag = NULL, *cmd = NULL, *url = NULL, *http_query = NULL,
132 *proxy_url = NULL, *proxy_connect = NULL;
132 *proxy_url = NULL, *proxy_connect = NULL, *check_cert = NULL;
133133 char buf[4096];
134134 int ret = 0;
135135 int network_socket = -1;
199199 a_Dpip_get_attr(dpip_tag, "proxy_connect");
200200 url = a_Dpip_get_attr(dpip_tag, "url");
201201 http_query = a_Dpip_get_attr(dpip_tag, "query");
202
203 if (cmd == NULL || url == NULL || http_query == NULL){
202 if (!(check_cert = a_Dpip_get_attr(dpip_tag, "check_cert"))) {
203 /* allow older dillo versions use this dpi */
204 check_cert = dStrdup("true");
205 }
206
207 if (!cmd || !url || !http_query) {
204208 MSG("***Value of cmd, url or http_query is NULL"
205209 " - cannot continue\n");
206210 exit_error = 1;
287291
288292 /*Use handle error function to decide what to do*/
289293 if (exit_error == 0){
290 if (handle_certificate_problem(ssl_connection) < 0){
294 if (strcmp(check_cert, "true") == 0 &&
295 handle_certificate_problem(ssl_connection) < 0){
291296 MSG("Certificate verification error\n");
292297 exit_error = 1;
293298 }
321326 dFree(http_query);
322327 dFree(proxy_url);
323328 dFree(proxy_connect);
329 dFree(check_cert);
324330
325331 if (network_socket != -1){
326332 close(network_socket);
145145 fl_draw(text, len, translateCanvasXToViewX (x), translateCanvasYToViewY(y));
146146 }
147147
148 void FltkPreview::drawSimpleWrappedText (core::style::Font *font,
149 core::style::Color *color,
150 core::style::Color::Shading shading,
151 int x, int y, int w, int h,
152 const char *text)
153 {
154 }
155
148156 void FltkPreview::drawImage (core::Imgbuf *imgbuf, int xRoot, int yRoot,
149157 int x, int y, int width, int height)
150158 {
4141 core::style::Color *color,
4242 core::style::Color::Shading shading,
4343 int x, int y, const char *text, int len);
44 void drawSimpleWrappedText (core::style::Font *font,
45 core::style::Color *color,
46 core::style::Color::Shading shading,
47 int x, int y, int w, int h,
48 const char *text);
4449 void drawImage (core::Imgbuf *imgbuf, int xRoot, int yRoot,
4550 int x, int y, int width, int height);
4651
354354
355355 void FltkLabelButtonResource::setLabel (const char *label)
356356 {
357 delete this->label;
357 free((char *)this->label);
358358 this->label = strdup (label);
359359
360360 widget->label (this->label);
604604 FltkSpecificResource <dw::core::ui::MultiLineTextResource> (platform)
605605 {
606606 buffer = new Fl_Text_Buffer;
607 text_copy = NULL;
607608 editable = false;
608609
609610 numCols = cols;
627628 /* Free memory avoiding a double-free of text buffers */
628629 ((Fl_Text_Editor *) widget)->buffer (0);
629630 delete buffer;
631 if (text_copy)
632 free(text_copy);
630633 }
631634
632635 Fl_Widget *FltkMultiLineTextResource::createNewWidget (core::Allocation
677680
678681 const char *FltkMultiLineTextResource::getText ()
679682 {
680 return buffer->text ();
683 /* FLTK-1.3 insists upon returning a new copy of the buffer text, so
684 * we have to keep track of it.
685 */
686 if (text_copy)
687 free(text_copy);
688 text_copy = buffer->text();
689 return text_copy;
681690 }
682691
683692 void FltkMultiLineTextResource::setText (const char *text)
315315 {
316316 private:
317317 Fl_Text_Buffer *buffer;
318 char *text_copy;
318319 bool editable;
319320 int numCols, numRows;
320321
470470 int x = translateCanvasXToViewX (centerX) - width / 2;
471471 int y = translateCanvasYToViewY (centerY) - height / 2;
472472
473 fl_arc(x, y, width, height, 0.0, 360.0);
473 fl_arc(x, y, width, height, angle1, angle2);
474474 if (filled)
475 fl_pie(x, y, width, height, 0.0, 360.0);
475 fl_pie(x, y, width, height, angle1, angle2);
476476 }
477477
478478 void FltkViewBase::drawPolygon (core::style::Color *color,
479479 core::style::Color::Shading shading,
480 bool filled, bool convex, int points[][2],
480 bool filled, bool convex, core::Point *points,
481481 int npoints)
482482 {
483483 if (npoints > 0) {
492492 fl_begin_loop();
493493
494494 for (int i = 0; i < npoints; i++) {
495 fl_vertex(translateCanvasXToViewX(points[i][0]),
496 translateCanvasYToViewY(points[i][1]));
495 fl_vertex(translateCanvasXToViewX(points[i].x),
496 translateCanvasYToViewY(points[i].y));
497497 }
498498 if (filled) {
499499 if (convex)
581581 }
582582 }
583583
584 /*
585 * "simple" in that it ignores letter-spacing, etc. This was added for image
586 * alt text where none of that matters.
587 */
588 void FltkWidgetView::drawSimpleWrappedText (core::style::Font *font,
589 core::style::Color *color,
590 core::style::Color::Shading shading,
591 int X, int Y, int W, int H,
592 const char *text)
593 {
594 FltkFont *ff = (FltkFont*)font;
595 fl_font(ff->font, ff->size);
596 fl_color(((FltkColor*)color)->colors[shading]);
597 fl_draw(text,
598 translateCanvasXToViewX (X), translateCanvasYToViewY (Y),
599 W, H, FL_ALIGN_TOP|FL_ALIGN_LEFT|FL_ALIGN_WRAP, NULL, 0);
600 }
601
584602 void FltkWidgetView::drawImage (core::Imgbuf *imgbuf, int xRoot, int yRoot,
585603 int X, int Y, int width, int height)
586604 {
9797 int angle1, int angle2);
9898 void drawPolygon (core::style::Color *color,
9999 core::style::Color::Shading shading,
100 bool filled, bool convex, int points[][2], int npoints);
100 bool filled, bool convex,
101 core::Point *points, int npoints);
101102
102103 core::View *getClippingView (int x, int y, int width, int height);
103104 void mergeClippingView (core::View *clippingView);
115116 core::style::Color *color,
116117 core::style::Color::Shading shading,
117118 int x, int y, const char *text, int len);
119 void drawSimpleWrappedText (core::style::Font *font,
120 core::style::Color *color,
121 core::style::Color::Shading shading,
122 int x, int y, int w, int h,
123 const char *text);
118124 void drawImage (core::Imgbuf *imgbuf, int xRoot, int yRoot,
119125 int x, int y, int width, int height);
120126
342342
343343 /*
344344 * For scrollbars, this currently sets the same step to both vertical and
345 * horizontal. It may me differentiated if necessary.
345 * horizontal. It may be differentiated if necessary.
346346 */
347347 void FltkViewport::setScrollStep(int step)
348348 {
383383 getContentHeight());
384384 }
385385
386 usedView->drawText (getStyle()->font, getStyle()->color,
386 usedView->drawSimpleWrappedText (getStyle()->font, getStyle()->color,
387387 core::style::Color::SHADING_NORMAL,
388388 allocation.x + getStyle()->boxOffsetX (),
389 allocation.y + getStyle()->boxOffsetY ()
390 + getStyle()->font->ascent,
391 altText, strlen(altText));
389 allocation.y + getStyle()->boxOffsetY (),
390 getContentWidth(), getContentHeight(), altText);
392391
393392 if (clippingView)
394393 view->mergeClippingView (clippingView);
193193 canvasWidth = canvasAscent = canvasDescent = 0;
194194
195195 usesViewport = false;
196 drawAfterScrollReq = false;
196197 scrollX = scrollY = 0;
197198 viewportWidth = viewportHeight = 0;
198199 hScrollbarThickness = vScrollbarThickness = 0;
455456 if (xChanged || yChanged) {
456457 adjustScrollPos ();
457458 view->scrollTo (scrollX, scrollY);
459 if (drawAfterScrollReq) {
460 drawAfterScrollReq = false;
461 view->queueDrawTotal ();
462 }
458463 }
459464
460465 scrollIdleId = -1;
502507 {
503508 Rectangle widgetArea, intersection, widgetDrawArea;
504509
505 if (topLevel) {
510 if (scrollIdleId != -1) {
511 /* scroll is pending, defer draw until after scrollIdle() */
512 drawAfterScrollReq = true;
513
514 } else if (topLevel) {
506515 /* Draw the top level widget. */
507516 widgetArea.x = topLevel->allocation.x;
508517 widgetArea.y = topLevel->allocation.y;
813822 */
814823 void Layout::leaveNotify (View *view, ButtonState state)
815824 {
825 #if 0
816826 Widget *lastWidget;
817827 EventCrossing event;
818828
825835 event.currentWidget = widgetAtPoint;
826836 lastWidget->leaveNotify (&event);
827837 }
838 #else
839 moveOutOfView (state);
840 #endif
828841 }
829842
830843 /*
843856
844857 /*
845858 * Emit the necessary crossing events, when the mouse pointer has moved to
846 * the given widget.
859 * the given widget (by mouse or scrolling).
847860 */
848861 void Layout::moveToWidget (Widget *newWidgetAtPoint, ButtonState state)
849862 {
889902 for (w = newWidgetAtPoint; w != ancestor; w = w->getParent ())
890903 track[i--] = w;
891904 }
905 #if 0
906 MSG("Track: %s[ ", widgetAtPoint ? "" : "nil ");
907 for (i = 0; i < trackLen; i++)
908 MSG("%s%p ", i == i_a ? ">" : "", track[i]);
909 MSG("] %s\n", newWidgetAtPoint ? "" : "nil");
910 #endif
892911
893912 /* Send events to the widgets on the track */
894913 for (i = 0; i < trackLen; i++) {
898917 if (i < i_a) {
899918 track[i]->leaveNotify (&crossingEvent);
900919 } else if (i == i_a) { /* ancestor */
901 if (!widgetAtPoint)
920 /* Don't touch ancestor unless:
921 * - moving into/from NULL,
922 * - ancestor becomes the newWidgetAtPoint */
923 if (i_a == trackLen-1 && !newWidgetAtPoint)
924 track[i]->leaveNotify (&crossingEvent);
925 else if ((i_a == 0 && !widgetAtPoint) ||
926 (i_a == trackLen-1 && newWidgetAtPoint))
902927 track[i]->enterNotify (&crossingEvent);
903 else if (!newWidgetAtPoint)
904 track[i]->leaveNotify (&crossingEvent);
905928 } else {
906929 track[i]->enterNotify (&crossingEvent);
907930 }
137137 style::Cursor cursor;
138138 int canvasWidth, canvasAscent, canvasDescent;
139139
140 bool usesViewport;
140 bool usesViewport, drawAfterScrollReq;
141141 int scrollX, scrollY, viewportWidth, viewportHeight;
142142 bool canvasHeightGreater;
143143 int hScrollbarThickness, vScrollbarThickness;
422422 int x1, int y1, int x2, int y2)
423423
424424 {
425 int points[4][2], d, w;
425 int d, w;
426 Point points[4];
426427 const bool filled = true, convex = true;
427428 bool ridge = false, inset = false, dotted = false;
428429 Color::Shading shading = Color::SHADING_NORMAL;
452453 if (style->borderWidth.top == 1) {
453454 view->drawLine(style->borderColor.top, shading, x1, y1, x2, y2);
454455 } else {
455 points[0][0] = x1;
456 points[1][0] = x2 + 1;
457 points[0][1] = points[1][1] = y1;
458 points[2][0] = points[1][0] - style->borderWidth.right;
459 points[3][0] = x1 + style->borderWidth.left;
460 points[2][1] = points[3][1] = points[0][1] + style->borderWidth.top;
456 points[0].x = x1;
457 points[1].x = x2 + 1;
458 points[0].y = points[1].y = y1;
459 points[2].x = points[1].x - style->borderWidth.right;
460 points[3].x = x1 + style->borderWidth.left;
461 points[2].y = points[3].y = points[0].y + style->borderWidth.top;
461462 view->drawPolygon (style->borderColor.top, shading, filled, convex,
462463 points, 4);
463464 }
466467 ridge = true;
467468 case BORDER_GROOVE:
468469 d = style->borderWidth.top & 1;
469 points[0][0] = x1;
470 points[1][0] = x2 + 1;
471 points[0][1] = points[1][1] = y1;
472 points[2][0] = x2 - style->borderWidth.right / 2;
473 points[3][0] = x1 + style->borderWidth.left / 2;
474 points[2][1] = points[3][1] = y1 + style->borderWidth.top / 2 + d;
470 points[0].x = x1;
471 points[1].x = x2 + 1;
472 points[0].y = points[1].y = y1;
473 points[2].x = x2 - style->borderWidth.right / 2;
474 points[3].x = x1 + style->borderWidth.left / 2;
475 points[2].y = points[3].y = y1 + style->borderWidth.top / 2 + d;
475476 shading = (ridge) ? Color::SHADING_LIGHT : Color::SHADING_DARK;
476477 view->drawPolygon (style->borderColor.top, shading, filled, convex,
477478 points, 4);
478 points[0][0] = x1 + style->borderWidth.left / 2 + d;
479 points[1][0] = x2 - style->borderWidth.right / 2 + 1 - d;
480 points[0][1] = points[1][1] = y1 + style->borderWidth.top / 2 + d;
481 points[2][0] = x2 - style->borderWidth.right + 1 - d;
482 points[3][0] = x1 + style->borderWidth.left;
483 points[2][1] = points[3][1] = y1 + style->borderWidth.top;
479 points[0].x = x1 + style->borderWidth.left / 2 + d;
480 points[1].x = x2 - style->borderWidth.right / 2 + 1 - d;
481 points[0].y = points[1].y = y1 + style->borderWidth.top / 2 + d;
482 points[2].x = x2 - style->borderWidth.right + 1 - d;
483 points[3].x = x1 + style->borderWidth.left;
484 points[2].y = points[3].y = y1 + style->borderWidth.top;
484485 shading = (ridge) ? Color::SHADING_DARK : Color::SHADING_LIGHT;
485486 view->drawPolygon (style->borderColor.top, shading, filled, convex,
486487 points, 4);
494495 view->drawLine(style->borderColor.top, shading, x1, y1, x2, y2);
495496 break;
496497 }
497 points[0][0] = x1;
498 points[1][0] = x2 + 1;
499 points[0][1] = points[1][1] = y1;
500 points[2][0] = points[1][0] - w_r;
501 points[3][0] = points[0][0] + w_l;
502 points[2][1] = points[3][1] = points[0][1] + w;
498 points[0].x = x1;
499 points[1].x = x2 + 1;
500 points[0].y = points[1].y = y1;
501 points[2].x = points[1].x - w_r;
502 points[3].x = points[0].x + w_l;
503 points[2].y = points[3].y = points[0].y + w;
503504 view->drawPolygon (style->borderColor.top, shading, filled, convex,
504505 points, 4);
505 points[0][0] = x1 + style->borderWidth.left - w_l;
506 points[1][0] = x2 + 1 - style->borderWidth.right + w_r;
507 points[0][1] = points[1][1] = y1 + w + d;
508 points[2][0] = x2 + 1 - style->borderWidth.right;
509 points[3][0] = x1 + style->borderWidth.left;
510 points[2][1] = points[3][1] = y1 + style->borderWidth.top;
506 points[0].x = x1 + style->borderWidth.left - w_l;
507 points[1].x = x2 + 1 - style->borderWidth.right + w_r;
508 points[0].y = points[1].y = y1 + w + d;
509 points[2].x = x2 + 1 - style->borderWidth.right;
510 points[3].x = x1 + style->borderWidth.left;
511 points[2].y = points[3].y = y1 + style->borderWidth.top;
511512 view->drawPolygon (style->borderColor.top, shading, filled, convex,
512513 points, 4);
513514 break;
518519 int x1, int y1, int x2, int y2)
519520
520521 {
521 int points[4][2], d, w;
522 int d, w;
523 Point points[4];
522524 const bool filled = true, convex = true;
523525 bool ridge = false, inset = false, dotted = false;
524526 Color::Shading shading = Color::SHADING_NORMAL;
548550 if (style->borderWidth.bottom == 1) { /* 1 pixel line */
549551 view->drawLine(style->borderColor.bottom, shading, x1, y1, x2, y2);
550552 } else {
551 points[0][0] = x1 - 1;
552 points[1][0] = x2 + 2;
553 points[0][1] = points[1][1] = y1 + 1;
554 points[2][0] = points[1][0] - style->borderWidth.right;
555 points[3][0] = points[0][0] + style->borderWidth.left;
556 points[2][1] = points[3][1] = points[0][1]-style->borderWidth.bottom;
553 points[0].x = x1 - 1;
554 points[1].x = x2 + 2;
555 points[0].y = points[1].y = y1 + 1;
556 points[2].x = points[1].x - style->borderWidth.right;
557 points[3].x = points[0].x + style->borderWidth.left;
558 points[2].y = points[3].y = points[0].y-style->borderWidth.bottom;
557559 view->drawPolygon (style->borderColor.bottom, shading, filled, convex,
558560 points, 4);
559561 }
563565 case BORDER_GROOVE:
564566 w = style->borderWidth.bottom;
565567 d = w & 1;
566 points[0][0] = x1 - 1;
567 points[1][0] = x2 + 2 - d;
568 points[0][1] = points[1][1] = y1 + 1;
569 points[2][0] = points[1][0] - style->borderWidth.right / 2;
570 points[3][0] = points[0][0] + style->borderWidth.left / 2 + d;
571 points[2][1] = points[3][1] = points[0][1] - w/2 - d;
568 points[0].x = x1 - 1;
569 points[1].x = x2 + 2 - d;
570 points[0].y = points[1].y = y1 + 1;
571 points[2].x = points[1].x - style->borderWidth.right / 2;
572 points[3].x = points[0].x + style->borderWidth.left / 2 + d;
573 points[2].y = points[3].y = points[0].y - w/2 - d;
572574 shading = (ridge) ? Color::SHADING_DARK : Color::SHADING_LIGHT;
573575 view->drawPolygon (style->borderColor.bottom, shading, filled, convex,
574576 points, 4);
575577 // clockwise
576 points[0][0] = x1 + style->borderWidth.left - 1;
577 points[1][0] = x2 + 1 - style->borderWidth.right + 1;
578 points[0][1] = points[1][1] = y1 - w + 1;
579 points[2][0] = points[1][0] + style->borderWidth.right / 2;
580 points[3][0] = points[0][0] - style->borderWidth.left / 2;
581 points[2][1] = points[3][1] = points[0][1] + w/2;
578 points[0].x = x1 + style->borderWidth.left - 1;
579 points[1].x = x2 + 1 - style->borderWidth.right + 1;
580 points[0].y = points[1].y = y1 - w + 1;
581 points[2].x = points[1].x + style->borderWidth.right / 2;
582 points[3].x = points[0].x - style->borderWidth.left / 2;
583 points[2].y = points[3].y = points[0].y + w/2;
582584 shading = (ridge) ? Color::SHADING_LIGHT : Color::SHADING_DARK;
583585 view->drawPolygon (style->borderColor.bottom, shading, filled, convex,
584586 points, 4);
592594 view->drawLine(style->borderColor.bottom, shading, x1, y1, x2, y2);
593595 break;
594596 }
595 points[0][0] = x2 + 2;
596 points[1][0] = x1 - 1;
597 points[0][1] = points[1][1] = y1 + 1;
598 points[2][0] = points[1][0] + w_l;
599 points[3][0] = points[0][0] - w_r;
600 points[2][1] = points[3][1] = points[0][1] - w;
597 points[0].x = x2 + 2;
598 points[1].x = x1 - 1;
599 points[0].y = points[1].y = y1 + 1;
600 points[2].x = points[1].x + w_l;
601 points[3].x = points[0].x - w_r;
602 points[2].y = points[3].y = points[0].y - w;
601603 view->drawPolygon (style->borderColor.bottom, shading, filled, convex,
602604 points, 4);
603 points[0][0] = x2 + 2 - style->borderWidth.right + w_r;
604 points[1][0] = x1 - 1 + style->borderWidth.left - w_l;
605 points[0][1] = points[1][1] = y1 + 1 - w - d;
606 points[2][0] = x1 - 1 + style->borderWidth.left;
607 points[3][0] = x2 + 2 - style->borderWidth.right;
608 points[2][1] = points[3][1] = y1 + 1 - style->borderWidth.bottom;
605 points[0].x = x2 + 2 - style->borderWidth.right + w_r;
606 points[1].x = x1 - 1 + style->borderWidth.left - w_l;
607 points[0].y = points[1].y = y1 + 1 - w - d;
608 points[2].x = x1 - 1 + style->borderWidth.left;
609 points[3].x = x2 + 2 - style->borderWidth.right;
610 points[2].y = points[3].y = y1 + 1 - style->borderWidth.bottom;
609611 view->drawPolygon (style->borderColor.bottom, shading, filled, convex,
610612 points, 4);
611613 break;
616618 int x1, int y1, int x2, int y2)
617619
618620 {
619 int points[4][2], d, w;
621 int d, w;
622 Point points[4];
620623 bool filled = true, convex = true;
621624 bool ridge = false, inset = false, dotted = false;
622625 Color::Shading shading = Color::SHADING_NORMAL;
645648 if (style->borderWidth.left == 1) { /* 1 pixel line */
646649 view->drawLine(style->borderColor.left, shading, x1, y1, x2, y2);
647650 } else {
648 points[0][0] = points[1][0] = x1;
649 points[0][1] = y1 - 1;
650 points[1][1] = y2 + 1;
651 points[2][0] = points[3][0] = points[0][0] + style->borderWidth.left;
652 points[2][1] = points[1][1] - style->borderWidth.bottom;
653 points[3][1] = points[0][1] + style->borderWidth.top;
651 points[0].x = points[1].x = x1;
652 points[0].y = y1 - 1;
653 points[1].y = y2 + 1;
654 points[2].x = points[3].x = points[0].x + style->borderWidth.left;
655 points[2].y = points[1].y - style->borderWidth.bottom;
656 points[3].y = points[0].y + style->borderWidth.top;
654657 view->drawPolygon (style->borderColor.left, shading, filled, convex,
655658 points, 4);
656659 }
660663 case BORDER_GROOVE:
661664 w = style->borderWidth.left;
662665 d = w & 1;
663 points[0][0] = points[1][0] = x1;
664 points[0][1] = y1;
665 points[1][1] = y2;
666 points[2][0] = points[3][0] = x1 + w / 2 + d;
667 points[2][1] = y2 - style->borderWidth.bottom / 2;
668 points[3][1] = y1 + style->borderWidth.top / 2;
666 points[0].x = points[1].x = x1;
667 points[0].y = y1;
668 points[1].y = y2;
669 points[2].x = points[3].x = x1 + w / 2 + d;
670 points[2].y = y2 - style->borderWidth.bottom / 2;
671 points[3].y = y1 + style->borderWidth.top / 2;
669672 shading = (ridge) ? Color::SHADING_LIGHT : Color::SHADING_DARK;
670673 view->drawPolygon (style->borderColor.left, shading, filled, convex,
671674 points, 4);
672 points[0][0] = points[1][0] = x1 + w / 2 + d;
673 points[0][1] = y1 + style->borderWidth.top / 2;
674 points[1][1] = y2 - style->borderWidth.bottom / 2;
675 points[2][0] = points[3][0] = x1 + w;
676 points[2][1] = y2 - style->borderWidth.bottom;
677 points[3][1] = y1 + style->borderWidth.top;
675 points[0].x = points[1].x = x1 + w / 2 + d;
676 points[0].y = y1 + style->borderWidth.top / 2;
677 points[1].y = y2 - style->borderWidth.bottom / 2;
678 points[2].x = points[3].x = x1 + w;
679 points[2].y = y2 - style->borderWidth.bottom;
680 points[3].y = y1 + style->borderWidth.top;
678681 shading = (ridge) ? Color::SHADING_DARK : Color::SHADING_LIGHT;
679682 view->drawPolygon (style->borderColor.left, shading, filled, convex,
680683 points, 4);
688691 view->drawLine(style->borderColor.left, shading, x1, y1, x2, y2-1);
689692 break;
690693 }
691 points[0][0] = points[1][0] = x1;
692 points[0][1] = y1 - 1;
693 points[1][1] = y2 + 1;
694 points[2][0] = points[3][0] = points[0][0] + w;
695 points[2][1] = points[1][1] - w_b;
696 points[3][1] = points[0][1] + w_t;
694 points[0].x = points[1].x = x1;
695 points[0].y = y1 - 1;
696 points[1].y = y2 + 1;
697 points[2].x = points[3].x = points[0].x + w;
698 points[2].y = points[1].y - w_b;
699 points[3].y = points[0].y + w_t;
697700 view->drawPolygon (style->borderColor.left, shading, filled, convex,
698701 points, 4);
699 points[0][0] = points[1][0] = x1 + w + d;
700 points[0][1] = y1 - 1 + style->borderWidth.top - w_t;
701 points[1][1] = y2 + 1 - style->borderWidth.bottom + w_b;
702 points[2][0] = points[3][0] = points[0][0] + w;
703 points[2][1] = y2 + 1 - style->borderWidth.bottom;
704 points[3][1] = y1 - 1 + style->borderWidth.top;
702 points[0].x = points[1].x = x1 + w + d;
703 points[0].y = y1 - 1 + style->borderWidth.top - w_t;
704 points[1].y = y2 + 1 - style->borderWidth.bottom + w_b;
705 points[2].x = points[3].x = points[0].x + w;
706 points[2].y = y2 + 1 - style->borderWidth.bottom;
707 points[3].y = y1 - 1 + style->borderWidth.top;
705708 view->drawPolygon (style->borderColor.left, shading, filled, convex,
706709 points, 4);
707710 break;
712715 int x1, int y1, int x2, int y2)
713716
714717 {
715 int points[4][2], d, w;
718 int d, w;
719 Point points[4];
716720 const bool filled = true, convex = true;
717721 bool ridge = false, inset = false, dotted = false;
718722 Color::Shading shading = Color::SHADING_NORMAL;
741745 if (style->borderWidth.right == 1) { /* 1 pixel line */
742746 view->drawLine(style->borderColor.right, shading, x1, y1, x2, y2);
743747 } else {
744 points[0][0] = points[1][0] = x1 + 1;
745 points[0][1] = y1 - 1;
746 points[1][1] = y2 + 1;
747 points[2][0] = points[3][0] = points[0][0]-style->borderWidth.right;
748 points[2][1] = points[1][1] - style->borderWidth.bottom;
749 points[3][1] = points[0][1] + style->borderWidth.top;
748 points[0].x = points[1].x = x1 + 1;
749 points[0].y = y1 - 1;
750 points[1].y = y2 + 1;
751 points[2].x = points[3].x = points[0].x-style->borderWidth.right;
752 points[2].y = points[1].y - style->borderWidth.bottom;
753 points[3].y = points[0].y + style->borderWidth.top;
750754 view->drawPolygon (style->borderColor.right, shading, filled, convex,
751755 points,4);
752756 }
756760 case BORDER_GROOVE:
757761 w = style->borderWidth.right;
758762 d = w & 1;
759 points[0][0] = points[1][0] = x1 + 1;
760 points[0][1] = y1;
761 points[1][1] = y2;
762 points[2][0] = points[3][0] = points[0][0] - w / 2 - d;
763 points[2][1] = y2 - style->borderWidth.bottom / 2;
764 points[3][1] = points[0][1] + style->borderWidth.top / 2;
763 points[0].x = points[1].x = x1 + 1;
764 points[0].y = y1;
765 points[1].y = y2;
766 points[2].x = points[3].x = points[0].x - w / 2 - d;
767 points[2].y = y2 - style->borderWidth.bottom / 2;
768 points[3].y = points[0].y + style->borderWidth.top / 2;
765769 shading = (ridge) ? Color::SHADING_DARK : Color::SHADING_LIGHT;
766770 view->drawPolygon (style->borderColor.right, shading, filled, convex,
767771 points, 4);
768 points[0][0] = points[1][0] = x1 + 1 - w / 2 - d;
769 points[0][1] = y1 + style->borderWidth.top / 2;
770 points[1][1] = y2 - style->borderWidth.bottom / 2;
771 points[2][0] = points[3][0] = x1 + 1 - w;
772 points[2][1] = y2 - style->borderWidth.bottom;
773 points[3][1] = y1 + style->borderWidth.top;
772 points[0].x = points[1].x = x1 + 1 - w / 2 - d;
773 points[0].y = y1 + style->borderWidth.top / 2;
774 points[1].y = y2 - style->borderWidth.bottom / 2;
775 points[2].x = points[3].x = x1 + 1 - w;
776 points[2].y = y2 - style->borderWidth.bottom;
777 points[3].y = y1 + style->borderWidth.top;
774778 shading = (ridge) ? Color::SHADING_LIGHT: Color::SHADING_DARK;
775779 view->drawPolygon (style->borderColor.right, shading, filled, convex,
776780 points, 4);
784788 view->drawLine(style->borderColor.right, shading, x1, y1, x2, y2);
785789 break;
786790 }
787 points[0][0] = points[1][0] = x1 + 1;
788 points[0][1] = y1 - 1;
789 points[1][1] = y2 + 1;
790 points[2][0] = points[3][0] = points[0][0] - w;
791 points[2][1] = points[1][1] - w_b;
792 points[3][1] = points[0][1] + w_t;
791 points[0].x = points[1].x = x1 + 1;
792 points[0].y = y1 - 1;
793 points[1].y = y2 + 1;
794 points[2].x = points[3].x = points[0].x - w;
795 points[2].y = points[1].y - w_b;
796 points[3].y = points[0].y + w_t;
793797 view->drawPolygon (style->borderColor.right, shading, filled, convex,
794798 points, 4);
795 points[0][0] = points[1][0] = x1 + 1 - w - d;
796 points[0][1] = y1 - 1 + style->borderWidth.top - w_t;
797 points[1][1] = y2 + 1 - style->borderWidth.bottom + w_b;
798 points[2][0] = points[3][0] = points[0][0] - w;
799 points[2][1] = y2 + 1 - style->borderWidth.bottom;
800 points[3][1] = y1 - 1 + style->borderWidth.top;
799 points[0].x = points[1].x = x1 + 1 - w - d;
800 points[0].y = y1 - 1 + style->borderWidth.top - w_t;
801 points[1].y = y2 + 1 - style->borderWidth.bottom + w_b;
802 points[2].x = points[3].x = points[0].x - w;
803 points[2].y = y2 + 1 - style->borderWidth.bottom;
804 points[3].y = y1 - 1 + style->borderWidth.top;
801805 view->drawPolygon (style->borderColor.right, shading, filled, convex,
802806 points, 4);
803807 break;
2525 #include <stdio.h>
2626 #include <limits.h>
2727
28 /*
29 * Local variables
30 */
31 /* The tooltip under mouse pointer in current textblock. No ref. hold.
32 * (having one per view looks not worth the extra clutter). */
33 static dw::core::style::Tooltip *hoverTooltip = NULL;
34
35
36
2837 using namespace lout;
2938
3039 namespace dw {
7988 availAscent = 100;
8089 availDescent = 0;
8190
82 hoverTooltip = NULL;
83
8491 this->limitTextWidth = limitTextWidth;
8592
8693 for (int layer = 0; layer < core::HIGHLIGHT_NUM_LAYERS; layer++) {
94101
95102 Textblock::~Textblock ()
96103 {
97 //_MSG ("Textblock::~Textblock\n");
104 _MSG("Textblock::~Textblock\n");
105
106 /* make sure not to call a free'd tooltip (very fast overkill) */
107 hoverTooltip = NULL;
98108
99109 for (int i = 0; i < words->size(); i++) {
100110 Word *word = words->getRef (i);
365375 * http://www.dillo.org/test/img/ */
366376 childAllocation.y =
367377 lineYOffsetCanvasAllocation (line, allocation)
368 + (line->boxAscent - word->size.ascent);
369 // - word->content.widget->getStyle()->margin.top;
378 + (line->boxAscent - word->size.ascent)
379 - word->content.widget->getStyle()->margin.top;
370380 childAllocation.width = word->size.width;
371 childAllocation.ascent = word->size.ascent;
372 // + word->content.widget->getStyle()->margin.top;
373 childAllocation.descent = word->size.descent;
374 // + word->content.widget->getStyle()->margin.bottom;
381 childAllocation.ascent = word->size.ascent
382 + word->content.widget->getStyle()->margin.top;
383 childAllocation.descent = word->size.descent
384 + word->content.widget->getStyle()->margin.bottom;
375385
376386 oldChildAllocation = word->content.widget->getAllocation();
377387
535545 return sendSelectionEvent (core::SelectionState::BUTTON_RELEASE, event);
536546 }
537547
548 /*
549 * Handle motion inside the widget
550 * (special care is necessary when switching from another widget,
551 * because hoverLink and hoverTooltip are meaningless then).
552 */
538553 bool Textblock::motionNotifyImpl (core::EventMotion *event)
539554 {
540555 if (event->state & core::BUTTON1_MASK)
556571 hoverLink = style->x_link;
557572 hoverTooltip = style->x_tooltip;
558573 }
574
559575 // Show/hide tooltip
560576 if (tooltipOld != hoverTooltip) {
561577 if (tooltipOld)
565581 } else if (hoverTooltip)
566582 hoverTooltip->onMotion ();
567583
568 if (hoverLink != linkOld)
584 _MSG("MN tb=%p tooltipOld=%p hoverTooltip=%p\n",
585 this, tooltipOld, hoverTooltip);
586 if (hoverLink != linkOld) {
587 /* LinkEnter with hoverLink == -1 is the same as LinkLeave */
569588 return layout->emitLinkEnter (this, hoverLink, -1, -1, -1);
570 else
589 } else {
571590 return hoverLink != -1;
591 }
572592 }
573593 }
574594
575595 void Textblock::enterNotifyImpl (core::EventCrossing *event)
576596 {
597 _MSG(" tb=%p, ENTER NotifyImpl hoverTooltip=%p\n", this, hoverTooltip);
598 /* reset hoverLink so linkEnter is detected */
599 hoverLink = -2;
577600 }
578601
579602 void Textblock::leaveNotifyImpl (core::EventCrossing *event)
580603 {
581 hoverLink = -1;
582 (void) layout->emitLinkEnter (this, hoverLink, -1, -1, -1);
604 _MSG(" tb=%p, LEAVE NotifyImpl: hoverTooltip=%p\n", this, hoverTooltip);
605
606 /* leaving the viewport can't be handled by motionNotifyImpl() */
607 if (hoverLink >= 0)
608 layout->emitLinkEnter (this, -1, -1, -1, -1);
609
583610 if (hoverTooltip) {
584611 hoverTooltip->onLeave();
585612 hoverTooltip = NULL;
962989 // lastLine->boxDescent);
963990
964991 if (word->content.type == core::Content::WIDGET) {
992 int collapseMarginTop = 0;
993
965994 lastLine->marginDescent =
966995 misc::max (lastLine->marginDescent,
967996 word->size.descent +
968997 word->content.widget->getStyle()->margin.bottom);
969998
970 //DBG_OBJ_ARRSET_NUM (page, "lines.%d.descent", page->num_lines - 1,
971 // lastLine->descent);
972
973 /* If the widget is not in the first line of the paragraph, its top
974 * margin may make the line higher.
975 */
976 if (lines->size () > 1) {
977 /* Here, we know already what the break and the bottom margin
978 * contributed to the space before this line.
979 */
980 lastLine->boxAscent =
999 if (lines->size () == 1 &&
1000 word->content.widget->blockLevel () &&
1001 getStyle ()->borderWidth.top == 0 &&
1002 getStyle ()->padding.top == 0) {
1003 // collapse top margin of parent element with top margin of first child
1004 // see: http://www.w3.org/TR/CSS21/box.html#collapsing-margins
1005 collapseMarginTop = getStyle ()->margin.top;
1006 }
1007
1008 lastLine->boxAscent =
9811009 misc::max (lastLine->boxAscent,
1010 word->size.ascent,
9821011 word->size.ascent
983 + word->content.widget->getStyle()->margin.top);
984
985 //DBG_OBJ_ARRSET_NUM (page, "lines.%d.ascent", page->num_lines - 1,
986 // lastLine->boxAscent);
987 }
1012 + word->content.widget->getStyle()->margin.top
1013 - collapseMarginTop);
1014
9881015 } else {
9891016 lastLine->marginDescent =
9901017 misc::max (lastLine->marginDescent, lastLine->boxDescent);
10951122 widget->setAscent (availAscent);
10961123 widget->setDescent (availDescent);
10971124 widget->sizeRequest (size);
1098 // size->ascent -= wstyle->margin.top;
1099 // size->descent -= wstyle->margin.bottom;
11001125 } else {
1101 /* TODO: Use margin.{top|bottom} here, like above.
1102 * (No harm for the next future.) */
11031126 if (wstyle->width == core::style::LENGTH_AUTO ||
11041127 wstyle->height == core::style::LENGTH_AUTO)
11051128 widget->sizeRequest (&requisition);
11301153 size->descent = (int) (len * availDescent);
11311154 }
11321155 }
1156
1157 /* ascent and descent in words do not contain margins. */
1158 size->ascent -= wstyle->margin.top;
1159 size->descent -= wstyle->margin.bottom;
11331160 }
11341161
11351162 /**
250250 struct {int index, nChar;}
251251 hlStart[core::HIGHLIGHT_NUM_LAYERS], hlEnd[core::HIGHLIGHT_NUM_LAYERS];
252252
253 int hoverLink; /* The link under the button. */
254 core::style::Tooltip *hoverTooltip; /* The tooltip under the button. No ref
255 * hold. */
253 int hoverLink; /* The link under the mouse pointer */
256254
257255
258256 void queueDrawRange (int index1, int index2);
140140 if (points->size()) {
141141 int i;
142142 const bool filled = false, convex = false;
143 int (*pointArray)[2] =
144 (int (*)[2]) malloc(points->size() * sizeof(*pointArray));
143 Point *pointArray = (Point *)malloc(points->size()*sizeof(struct Point));
145144
146145 for (i = 0; i < points->size(); i++) {
147 pointArray[i][0] = x + points->getRef(i)->x;
148 pointArray[i][1] = y + points->getRef(i)->y;
146 pointArray[i].x = x + points->getRef(i)->x;
147 pointArray[i].y = y + points->getRef(i)->y;
149148 }
150149 view->drawPolygon(style->color, core::style::Color::SHADING_NORMAL,
151150 filled, convex, pointArray, i);
172172 int angle1, int angle2) = 0;
173173 virtual void drawPolygon (style::Color *color,
174174 style::Color::Shading shading,
175 bool filled, bool convex, int points[][2],
175 bool filled, bool convex, Point *points,
176176 int npoints) = 0;
177177 virtual void drawText (style::Font *font,
178178 style::Color *color,
179179 style::Color::Shading shading,
180180 int x, int y, const char *text, int len) = 0;
181
181 virtual void drawSimpleWrappedText (style::Font *font, style::Color *color,
182 style::Color::Shading shading,
183 int x, int y, int w, int h,
184 const char *text) = 0;
182185 virtual void drawImage (Imgbuf *imgbuf, int xRoot, int yRoot,
183186 int x, int y, int width, int height) = 0;
184187
6060 " <table border='0' cellspacing='0' cellpadding='2'><tr>\n"
6161 " <td>\n"
6262 " <td>\n"
63 " <a href='http://www.dillo.org/dillo2-help.html'>\n"
63 " <a href='http://www.dillo.org/dillo3-help.html'>\n"
6464 " Help</a>\n"
6565 " <tr>\n"
6666 " <td>&nbsp;&nbsp;\n"
116116 " <tr>\n"
117117 " <td>&nbsp;&nbsp;\n"
118118 " <td>\n"
119 " <a href='http://slashdot.org/'>Slashdot</a>\n"
120 " <tr>\n"
121 " <td>&nbsp;&nbsp;\n"
122 " <td>\n"
123119 " <a href='http://www.linux.org.uk/Portaloo.cs'>Linux.org.uk</a>\n"
120 " <tr>\n"
121 " <td>&nbsp;&nbsp;\n"
122 " <td>\n"
123 " <a href='http://www.mathaba.net/'>Mathaba</a>\n"
124 " <tr>\n"
124125 " <tr>\n"
125126 " <td>&nbsp;&nbsp;\n"
126127 " <td>\n"
151152 " <td bgcolor='#FFFFFF'>\n"
152153 " <table border='0' cellspacing='0' cellpadding='5'><tr><td>\n"
153154 " <table border='0' cellpadding='2'><tr>\n"
154 " <td>&nbsp;&nbsp;\n"
155 " <td><a href='http://www.google.com/'>Google</a>\n"
156 " <tr>\n"
157 " <td>&nbsp;&nbsp;\n"
158 " <td><a href='http://www.wikipedia.org/'>Wikipedia</a>\n"
159 " <tr>\n"
160155 " <td>&nbsp;&nbsp;\n"
161156 " <td><a href='http://www.gutenberg.org/'>P.&nbsp;Gutenberg</a>\n"
162157 " <tr>\n"
239234 "<tr>\n"
240235 " <td bgcolor='#CCCCCC'>\n"
241236 " <h4>Release overview</h4>\n"
242 " February 11, 2010\n"
237 " August ??, 2011\n"
243238 "<tr>\n"
244239 " <td bgcolor='#FFFFFF'>\n"
245240 " <table border='0' cellspacing='0' cellpadding='5'>\n"
246241 " <tr>\n"
247242 " <td>\n"
248243 "<p>\n"
249 "This release features a major overhaul of the cookies subsystem,\n"
250 "a reimplementation of the DPI API, a configurable connection limit,\n"
251 "and various CSS improvements.\n"
252 "<p>\n"
253 "Remember that the dillo project uses a release model where every new\n"
254 "version shall be better than the last.\n"
255 "<EM>Keep up with the latest one!</EM>\n"
244 "Dillo-3.0 is a port to FLTK-1.3, which is big news because FLTK-1.3.0 was\n"
245 "<a href='http://fltk.org/articles.php?L1086'>released</a>\n"
246 "in June, clearing the way for Dillo to return to those distributions\n"
247 "which had excluded Dillo2 due to FLTK2 never being officially released.\n"
248 "<p>\n"
249 "Dillo-3.0 also has plenty of improvements and bugfixes.\n"
250 "<p>\n"
251 "After this release, the core team will focus on implementing the CSS\n"
252 "feature of floating elements. This will <em>greatly</em> improve dillo's\n"
253 "web page rendering since many sites have adopted floats instead of tables.\n"
254 "<p>\n"
255 "The new dillo3 has shown excellent stability in our experience.\n"
256 "The core team welcomes developers willing to join our workforce.\n"
257 "<p>\n"
256258 " </table>\n"
257259 "</table>\n"
258260 "</table>\n"
273275 " <tr>\n"
274276 " <td>\n"
275277 "<ul>\n"
276 "<li>Added keybindings for scrolling.\n"
277 "<li>Help button and local help file.\n"
278 "<li>Add support for multiple class names in CSS.\n"
279 "<li>Fix X11 coordinate overflows.\n"
280 "<li>Improve CSS font parsing.\n"
281 "<li>Enable font face setting via &lt;font&gt; element.\n"
282 "<li>Ignore XML comment markers in CSS.\n"
283 "<li>Fix user agent style for nested &lt;ul&gt;.\n"
284 "<li>Handle signed chars. Added dIsspace() and dIsalnum() to dlib.\n"
285 "<li>Changed the CCCs to build in one step (for both HTTP and DPI).\n"
286 "<li>Remove the empty cache entry lingering after connection abort.\n"
287 "<li>Fixed URL unescaping in the datauri DPI.\n"
288 "<li>Changed and reimplemented the DPI API.\n"
289 "<li>Allow linebreaks around Chinese/Japanese characters.\n"
290 "<li>Fix scrolling for text search.\n"
291 "<li>Tooltips.\n"
292 "<li>Enable popup menu below bottom of page content.\n"
293 "<li>Handle JPEGs with CMYK color space.\n"
294 "<li>General cookies overhaul.\n"
295 "<li>Fixed a bug in w3c_mode.\n"
296 "<li>Limit number of simultaneous connections.\n"
278 "<li>Ported Dillo to FLTK-1.3.\n"
279 "<li>Native build on OSX.\n"
280 "<li>Default binding for close-all changed from Alt-q to Ctrl-q.\n"
281 "<li>Default binding for close-tab changed from Ctrl-q to Ctrl-w.\n"
282 "<li>Default binding for left-tab changed to Shift-Ctrl-Tab.\n"
283 "<li>'hide-panels' key action now hides the findbar if present,\n"
284 " and toggles display of the control panels otherwise.\n"
285 "<li>Allow multiple search engines to be set in dillorc, with a menu\n"
286 " in the web search dialog to select between them.\n"
287 "<li>Added an optional label to dillorc's search_url.\n"
288 " Format: \"[&lt;label&gt; ]&lt;url&gt;\"\n"
289 "<li>Removed 'large' option of panel_size preference.\n"
290 "<li>Add right_click_closes_tab preference (default is middle click).\n"
291 "<li>Allow binding to non-ASCII keys and multimedia keys.\n"
292 "<li>Removed --enable-ansi configure option.\n"
293 "<li>Avoid a certificate dialog storm on some HTTPS sites (BUG#868).\n"
294 "<li>Enable line wrapping for &lt;textarea&gt;. (BUG#903)\n"
295 "<li>Rewrote the User Interface: much simpler design and event handling.\n"
296 "<li>Avoid double render after going Back or Forward\n"
297 " (it takes half the time now!)\n"
298 "<li>Added on-the-fly panel resize (tiny/small/medium and normal/small icons).\n"
299 "<li>Implemented a custom tabs handler (to allow fine control of it).\n"
300 "<li>Rewrote dw's crossing-events dispatcher (avoids redundant events).\n"
301 "<li>Fixed a years old bug: stamped tooltips when scrolling with keyboard.\n"
302 "<li>Fixed a border case in URL resolver: empty path + {query|fragment}\n"
303 " (BUG#948)\n"
304 "<li>Cancel the expected URL after offering a download (BUG#982)\n"
305 "<li>Eliminated a pack of 22 compiler warnings (gcc-4.6.1 amd64)\n"
306 "<li>Limit saved cookie size.\n"
307 "<li>Wrap image alt text.\n"
308 "<li>Added support for CSS adjacent sibling selectors.\n"
309 "<li>Collapse parent's and first child's top margin.\n"
297310 "</ul>\n"
298311 " </table>\n"
299312 "</table>\n"
364364 DataBuf *dbuf;
365365
366366 /* Create the query */
367 query = a_Http_make_query_str(S->web->url, S->flags & HTTP_SOCKET_USE_PROXY);
367 query = a_Http_make_query_str(S->web->url,S->flags & HTTP_SOCKET_USE_PROXY);
368368 dbuf = a_Chain_dbuf_new(query->str, query->len, 0);
369369
370370 /* actually this message is sent too early.
5454 bw->nav_stack_ptr = -1;
5555
5656 /* Init expect */
57 bw->nav_expecting = FALSE;
5857 bw->nav_expect_url = NULL;
5958
6059 bw->redirect_level = 0;
312311 return NULL;
313312 }
314313
314 /* expect API ------------------------------------------------------------- */
315
316 void a_Bw_expect(BrowserWindow *bw, const DilloUrl *url)
317 {
318 a_Url_free(bw->nav_expect_url);
319 bw->nav_expect_url = a_Url_dup(url);
320 }
321
322 void a_Bw_cancel_expect(BrowserWindow *bw)
323 {
324 a_Url_free(bw->nav_expect_url);
325 bw->nav_expect_url = NULL;
326 }
327
328 bool_t a_Bw_expecting(BrowserWindow *bw)
329 {
330 return (bw->nav_expect_url != NULL);
331 }
332
333 const DilloUrl *a_Bw_expected_url(BrowserWindow *bw)
334 {
335 return bw->nav_expect_url;
336 }
337
4545 /* 'nav_stack_ptr' refers to what's being displayed */
4646 int nav_stack_ptr; /* [0 based; -1 = empty] */
4747 /* When the user clicks a link, the URL isn't pushed directly to history;
48 * nav_expect_url holds it until the first answer-bytes are got. Only then
49 * it is sent to history and referenced at the top of nav_stack */
48 * nav_expect_url holds it until a dw is assigned to it. Only then an entry
49 * is made in history and referenced at the top of nav_stack */
5050 DilloUrl *nav_expect_url;
51 /* 'nav_expecting' is true while dillo waits for non-cached URL data,
52 * until a dw is assigned to it. */
53 bool_t nav_expecting;
5451
5552 /* Counter for the number of hops on a redirection. Used to stop
5653 * redirection loops (accounts for WEB_RootUrl only) */
8784 void a_Bw_remove_doc(BrowserWindow *bw, void *vdoc);
8885 void a_Bw_add_url(BrowserWindow *bw, const DilloUrl *Url);
8986 void a_Bw_cleanup(BrowserWindow *bw);
87 /* expect API */
88 void a_Bw_expect(BrowserWindow *bw, const DilloUrl *Url);
89 void a_Bw_cancel_expect(BrowserWindow *bw);
90 bool_t a_Bw_expecting(BrowserWindow *bw);
91 const DilloUrl *a_Bw_expected_url(BrowserWindow *bw);
9092
9193 typedef void (*BwCallback_t)(BrowserWindow *bw, const void *data);
9294
891891 " at: %s\n", URL_STR_(entry->Url));
892892 MSG("entry->ExpectedSize = %d, entry->TransferSize = %d\n",
893893 entry->ExpectedSize, entry->TransferSize);
894 }
895 if (!entry->TransferSize && !(entry->Flags & CA_Redirect) &&
896 (entry->Flags & WEB_RootUrl)) {
897 char *eol = strchr(entry->Header->str, '\n');
898 if (eol) {
899 char *status_line = dStrndup(entry->Header->str,
900 eol - entry->Header->str);
901 MSG_HTTP("Body was empty. Server sent status: %s\n", status_line);
902 dFree(status_line);
903 }
894904 }
895905 entry->Flags |= CA_GotData;
896906 entry->Flags &= ~CA_Stopped; /* it may catch up! */
301301 char *proxy_connect = a_Http_make_connect_str(web->url);
302302 Dstr *http_query = a_Http_make_query_str(web->url, FALSE);
303303 /* BUG: embedded NULLs in query data will truncate message */
304
305 /* BUG: WORKAROUND: request to only check the root URL's certificate.
306 * This avoids the dialog bombing that stems from loading multiple
307 * https images/resources in a single page. A proper fix would take
308 * either to implement the https-dpi as a server (with state),
309 * or to move back https handling into dillo. */
304310 if (proxy_connect) {
305311 const char *proxy_urlstr = a_Http_get_proxy_urlstr();
306312 cmd = a_Dpip_build_cmd("cmd=%s proxy_url=%s proxy_connect=%s "
307 "url=%s query=%s", "open_url", proxy_urlstr,
313 "url=%s query=%s check_cert=%s",
314 "open_url", proxy_urlstr,
308315 proxy_connect, URL_STR(web->url),
309 http_query->str);
316 http_query->str,
317 (web->flags & WEB_RootUrl) ? "true" : "false");
310318 } else {
311 cmd = a_Dpip_build_cmd("cmd=%s url=%s query=%s",
312 "open_url", URL_STR(web->url),http_query->str);
319 cmd = a_Dpip_build_cmd("cmd=%s url=%s query=%s check_cert=%s",
320 "open_url", URL_STR(web->url),http_query->str,
321 (web->flags & WEB_RootUrl) ? "true" : "false");
313322 }
314323 dFree(proxy_connect);
315324 dStr_free(http_query, 1);
103103 cs = selectorList->getRef (selectorList->size () - 1);
104104
105105 cs->notMatchingBefore = -1;
106 cs->combinator = CHILD;
106107 cs->selector = new CssSimpleSelector ();
107108 };
108109
132133
133134 switch (comb) {
134135 case CHILD:
136 case ADJACENT_SIBLING:
135137 if (!sel->match (node))
136138 return false;
137139 break;
155157 }
156158
157159 comb = cs->combinator;
158 node = docTree->parent (node);
160
161 if (comb == ADJACENT_SIBLING)
162 node = docTree->sibling (node);
163 else
164 node = docTree->parent (node);
159165 }
160166
161167 return true;
198204 break;
199205 case DESCENDANT:
200206 fprintf (stderr, "\" \" ");
207 break;
208 case ADJACENT_SIBLING:
209 fprintf (stderr, "+ ");
201210 break;
202211 default:
203212 fprintf (stderr, "? ");
488497 }
489498 }
490499
491 CssStyleSheet *CssContext::userAgentStyle;
492 CssStyleSheet *CssContext::userStyle;
493 CssStyleSheet *CssContext::userImportantStyle;
494
495500 CssContext::CssContext () {
496501 pos = 0;
497502
498 for (int o = CSS_PRIMARY_USER_AGENT; o < CSS_PRIMARY_LAST; o++)
499 sheet[o] = NULL;
500
501 if (userAgentStyle == NULL) {
502 userAgentStyle = new CssStyleSheet ();
503 userStyle = new CssStyleSheet ();
504 userImportantStyle = new CssStyleSheet ();
505
506 sheet[CSS_PRIMARY_USER_AGENT] = userAgentStyle;
507 sheet[CSS_PRIMARY_USER] = userStyle;
508 sheet[CSS_PRIMARY_USER_IMPORTANT] = userImportantStyle;
509
510 buildUserAgentStyle ();
511 buildUserStyle ();
512 }
513
514 sheet[CSS_PRIMARY_USER_AGENT] = userAgentStyle;
515 sheet[CSS_PRIMARY_USER] = userStyle;
516 sheet[CSS_PRIMARY_USER_IMPORTANT] = userImportantStyle;
503 memset (sheet, 0, sizeof(sheet));
504 sheet[CSS_PRIMARY_USER_AGENT] = new CssStyleSheet ();
505 sheet[CSS_PRIMARY_USER] = new CssStyleSheet ();
506 sheet[CSS_PRIMARY_USER_IMPORTANT] = new CssStyleSheet ();
507
508 buildUserAgentStyle ();
509 buildUserStyle ();
517510 }
518511
519512 CssContext::~CssContext () {
520513 for (int o = CSS_PRIMARY_USER_AGENT; o < CSS_PRIMARY_LAST; o++)
521 if (sheet[o] != userAgentStyle && sheet[o] != userStyle &&
522 sheet[o] != userImportantStyle)
523 delete sheet[o];
514 delete sheet[o];
524515 }
525516
526517 /**
457457 */
458458 class CssContext {
459459 private:
460 static CssStyleSheet *userAgentStyle;
461 static CssStyleSheet *userStyle;
462 static CssStyleSheet *userImportantStyle;
463460 CssStyleSheet *sheet[CSS_PRIMARY_USER_IMPORTANT + 1];
464461 int pos;
465462
12881288 } else if (ttype == CSS_TK_CHAR && tval[0] == '>') {
12891289 selector->addSimpleSelector (CssSelector::CHILD);
12901290 nextToken();
1291 } else if (ttype == CSS_TK_CHAR && tval[0] == '+') {
1292 selector->addSimpleSelector (CssSelector::ADJACENT_SIBLING);
1293 nextToken();
12911294 } else if (ttype != CSS_TK_END && spaceSeparated) {
12921295 selector->addSimpleSelector (CssSelector::DESCENDANT);
12931296 } else {
8888 if (e == FL_KEYBOARD &&
8989 (Fl::event_key() == FL_Enter || Fl::event_key() == FL_Down) &&
9090 (Fl::event_state() & (FL_SHIFT|FL_CTRL|FL_ALT|FL_META)) == 0) {
91 MSG("CustChoice: ENTER\n");
9291 return Fl_Choice::handle(FL_PUSH);
9392 }
9493 return Fl_Choice::handle(e);
163162 for (int i = 0, j = 0; i < n_it; i++) {
164163 char *label, *url, *source;
165164 source = (char *)dList_nth_data(prefs.search_urls, i);
166 if (a_Misc_parse_search_url(source, &label, &url) < 0)
165 if (!source || a_Misc_parse_search_url(source, &label, &url) < 0)
167166 continue;
168167 pm[j++].label(FL_NORMAL_LABEL, strdup(label));
169168 }
190189 window->show();
191190 while (window->shown())
192191 Fl::wait();
193 _MSG("a_Dialog_input answer = %d\n", input_answer);
194192 if (input_answer == 1) {
195193 /* we have a string, save it */
196194 dFree(input_str);
197195 input_str = dStrdup(c_inp->value());
198 MSG("a_Dialog_input value() = %d\n", ch->value());
199196 prefs.search_url_idx = ch->value();
200197 }
201198 delete window;
55 class DoctreeNode {
66 public:
77 DoctreeNode *parent;
8 DoctreeNode *sibling;
9 DoctreeNode *lastChild;
810 int num; // unique ascending id
911 int element;
1012 lout::misc::SimpleVector<char*> *klass;
1315
1416 DoctreeNode () {
1517 parent = NULL;
18 sibling = NULL;
19 lastChild = NULL;
1620 klass = NULL;
1721 pseudo = NULL;
1822 id = NULL;
1923 element = 0;
2024 };
25
26 ~DoctreeNode () {
27 dFree ((void*) id);
28 while (lastChild) {
29 DoctreeNode *n = lastChild;
30 lastChild = lastChild->sibling;
31 delete n;
32 }
33 if (klass) {
34 for (int i = 0; i < klass->size (); i++)
35 dFree (klass->get(i));
36 delete klass;
37 }
38 }
2139 };
2240
2341 /**
2543 *
2644 * The Doctree class defines the interface to the parsed HTML document tree
2745 * as it is used for CSS selector matching.
28 * Currently the Doctree can be represented as stack, however to support
29 * CSS adjacent siblings or for future JavaScript support it may have to
30 * be extended to a real tree.
3146 */
3247 class Doctree {
3348 private:
3449 DoctreeNode *topNode;
50 DoctreeNode *rootNode;
3551 int num;
3652
3753 public:
3854 Doctree () {
39 topNode = NULL;
55 rootNode = new DoctreeNode;
56 topNode = rootNode;
4057 num = 0;
4158 };
42 ~Doctree () { while (top ()) pop (); };
59
60 ~Doctree () {
61 delete rootNode;
62 };
63
4364 DoctreeNode *push () {
4465 DoctreeNode *dn = new DoctreeNode ();
4566 dn->parent = topNode;
67 dn->sibling = dn->parent->lastChild;
68 dn->parent->lastChild = dn;
4669 dn->num = num++;
4770 topNode = dn;
4871 return dn;
4972 };
73
5074 void pop () {
51 DoctreeNode *dn = topNode;
52 if (dn) {
53 dFree ((void*) dn->id);
54 if (dn->klass) {
55 for (int i = 0; i < dn->klass->size (); i++)
56 dFree (dn->klass->get(i));
57 delete dn->klass;
58 }
59 topNode = dn->parent;
60 delete dn;
61 }
75 assert (topNode != rootNode); // never pop the root node
76 topNode = topNode->parent;
6277 };
78
6379 inline DoctreeNode *top () {
64 return topNode;
80 if (topNode != rootNode)
81 return topNode;
82 else
83 return NULL;
6584 };
85
6686 inline DoctreeNode *parent (const DoctreeNode *node) {
67 return node->parent;
87 if (node->parent != rootNode)
88 return node->parent;
89 else
90 return NULL;
91 };
92
93 inline DoctreeNode *sibling (const DoctreeNode *node) {
94 return node->sibling;
6895 };
6996 };
7097
4040 // Let these keys get to the UI
4141 return 0;
4242 }
43 } else if (modifier == FL_CTRL) {
44 if (k == 'a' || k == 'e') {
45 position(k == 'a' ? 0 : size());
46 return 1;
47 } else if (k == 'k') {
48 cut(position(), size());
49 return 1;
50 } else if (k == 'd') {
51 cut(position(), position()+1);
52 return 1;
53 }
4354 } else if (k == FL_Escape && modifier == 0) {
4455 // Avoid clearing the text with Esc, just hide the findbar.
4556 return 0;
8596 */
8697 void Findbar::hide_cb(Fl_Widget *, void *vfb)
8798 {
88 ((Findbar *)vfb)->hide();
99 a_UIcmd_findbar_toggle(a_UIcmd_get_bw_by_widget(vfb), 0);
89100 }
90101
91102 /*
163174 */
164175 int Findbar::handle(int event)
165176 {
166 int ret = 0;
167177 int k = Fl::event_key();
168178 unsigned modifier = Fl::event_state() & (FL_SHIFT| FL_CTRL| FL_ALT|FL_META);
169179
170180 if (event == FL_KEYBOARD && modifier == 0 && k == FL_Escape) {
171 hide();
172 ret = 1;
173 }
174
175 if (ret == 0)
176 ret = Fl_Group::handle(event);
177
178 return ret;
181 /* let the UI handle it */
182 return 0;
183 }
184
185 return Fl_Group::handle(event);
179186 }
180187
181188 /*
187194 dReturn_if (bw == NULL);
188195
189196 // It takes more than just calling show() to do the trick
190 //a_UIcmd_findbar_toggle(bw, 1);
191197 Fl_Group::show();
192198
193199 /* select text even if already focused */
195201 i->position(i->size(), 0);
196202 }
197203
198 /*
199 * Hide the findbar and reset the search state
200 */
201 void Findbar::hide()
202 {
203 BrowserWindow *bw = a_UIcmd_get_bw_by_widget(this);
204 dReturn_if (bw == NULL);
205
206 // It takes more than just calling hide() to do the trick
207 Fl_Group::hide();
208 a_UIcmd_findbar_toggle(bw, 0);
209
210 a_UIcmd_findtext_reset(bw);
211 a_UIcmd_focus_main_area(bw);
212 }
2626 ~Findbar();
2727 int handle(int event);
2828 void show();
29 void hide();
3029 };
3130
3231 #endif // __FINDBAR_HH__
676676 case 2: /* End code... consume remaining data chunks..? */
677677 goto error; /* Could clean up better? */
678678 default:
679 printf("dillo_gif_decode: error!\n");
679 MSG("Gif_decode: error!\n");
680680 goto error;
681681 }
682682 }
646646 */
647647 void DilloHtml::loadImages (const DilloUrl *pattern)
648648 {
649 dReturn_if_fail (bw->nav_expecting == FALSE);
649 dReturn_if (a_Bw_expecting(bw));
650650
651651 /* If the user asked for a specific URL, the user (NULL) is the requester,
652652 * but if the user just asked for all URLs, use the page URL as the
687687 if (link == -1) {
688688 _MSG(" Link LEAVE notify...\n");
689689 a_UIcmd_set_msg(bw, "");
690 a_UIcmd_set_pointer_on_link(bw, FALSE);
691690 } else {
692691 _MSG(" Link ENTER notify...\n");
693692 Html_set_link_coordinates(html, link, x, y);
694693 a_UIcmd_set_msg(bw, "%s", URL_STR(html->links->get(link)));
695 a_UIcmd_set_pointer_on_link(bw, TRUE);
696694 }
697695 return true;
698696 }
100100 { "open" , KEYS_OPEN , FL_CTRL , 'o' },
101101 { "new-window" , KEYS_NEW_WINDOW , FL_CTRL , 'n' },
102102 { "new-tab" , KEYS_NEW_TAB , FL_CTRL , 't' },
103 { "left-tab" , KEYS_LEFT_TAB , FL_SHIFT , FL_Tab },
103 { "left-tab" , KEYS_LEFT_TAB , FL_CTRL |
104 FL_SHIFT , FL_Tab },
104105 { "right-tab" , KEYS_RIGHT_TAB , FL_CTRL , FL_Tab },
105106 { "close-tab" , KEYS_CLOSE_TAB , FL_CTRL , 'w' },
106107 { "find" , KEYS_FIND , FL_CTRL , 'f' },
55 # The commented-out bindings below show the defaults built into Dillo.
66 #
77 # Modifiers recognized: "Shift", "Ctrl", "Alt", "Meta".
8 # (OS X: Use "Meta" for Command)
89 #
910 # Key names recognized: "Backspace", "Delete", "Down", "End", "Esc",
1011 # "F1" through "F12", "Home", "Insert", "Left", "PageDown", "PageUp",
3738 #<ctrl>q = close-all
3839
3940 # "left-tab" and "right-tab" switch to the left/right of the current tab.
40 # <shift>tab = left-tab
41 # <ctrl><shift>tab = left-tab
4142 # <ctrl>tab = right-tab
4243
4344 # "back" and "forward" move back/forward through the browser history.
630630 {"Panel size", 0, Menu_nop_cb, (void*)"Submenu1", FL_SUBMENU,0,0,0,0},
631631 {"tiny", 0,Menu_panel_change_cb,(void*)0,FL_MENU_RADIO,0,0,0,0},
632632 {"small", 0,Menu_panel_change_cb,(void*)1,FL_MENU_RADIO,0,0,0,0},
633 {"medium",0,Menu_panel_change_cb,(void*)2,FL_MENU_RADIO,0,0,0,0},
634 {"large", 0,Menu_panel_change_cb,(void*)3,
633 {"medium",0,Menu_panel_change_cb,(void*)2,
635634 FL_MENU_RADIO|FL_MENU_DIVIDER,0,0,0,0},
636635 {"small icons", 0,Menu_panel_change_cb,(void*)10,
637636 FL_MENU_TOGGLE,0,0,0,0},
650649 if (prefs.load_images)
651650 pm[2].set();
652651 pm[4+cur_panelsize].setonly();
653 cur_smallicons ? pm[8].set() : pm[8].clear();
652 cur_smallicons ? pm[7].set() : pm[7].clear();
654653
655654 item = pm->popup(wid->x(), wid->y() + wid->h());
656655 if (item) {
410410 }
411411 }
412412 *label = buf;
413 if (ret == -1)
414 MSG("Invalid search_url: \"%s\"\n", source);
413415 return ret;
414416 }
415417
247247 */
248248 void a_Nav_cancel_expect(BrowserWindow *bw)
249249 {
250 if (bw->nav_expecting) {
251 a_Url_free(bw->nav_expect_url);
252 bw->nav_expect_url = NULL;
253 bw->nav_expecting = FALSE;
250 if (a_Bw_expecting(bw)) {
251 a_Bw_cancel_expect(bw);
254252 a_UIcmd_set_buttons_sens(bw);
255253 }
256254 if (bw->meta_refresh_status > 0)
262260 */
263261 void a_Nav_cancel_expect_if_eq(BrowserWindow *bw, const DilloUrl *url)
264262 {
265 if (bw->nav_expecting && a_Url_cmp(url, bw->nav_expect_url) == 0)
263 if (a_Url_cmp(url, a_Bw_expected_url(bw)) == 0)
266264 a_Nav_cancel_expect(bw);
267265 }
268266
280278
281279 dReturn_if_fail(bw != NULL);
282280
283 if (bw->nav_expecting) {
284 url = bw->nav_expect_url;
281 if (a_Bw_expecting(bw)) {
282 url = a_Url_dup(a_Bw_expected_url(bw));
285283 reload = (URL_FLAGS(url) & URL_ReloadPage);
286284 repush = (URL_FLAGS(url) & URL_ReloadFromCache);
287285 e2equery = (URL_FLAGS(url) & URL_E2EQuery);
292290 m = URL_E2EQuery|URL_ReloadPage|URL_ReloadFromCache|URL_IgnoreScroll;
293291 a_Url_set_flags(url, URL_FLAGS(url) & ~m);
294292 url_idx = a_History_add_url(url);
293 a_Url_free(url);
295294
296295 if (repush) {
297296 MSG("a_Nav_expect_done: repush!\n");
344343 void a_Nav_push(BrowserWindow *bw, const DilloUrl *url,
345344 const DilloUrl *requester)
346345 {
347 dReturn_if_fail (bw != NULL);
348
349 if (bw->nav_expecting && !a_Url_cmp(bw->nav_expect_url, url) &&
350 !strcmp(URL_FRAGMENT(bw->nav_expect_url),URL_FRAGMENT(url))) {
346 const DilloUrl *e_url;
347 dReturn_if_fail (bw != NULL);
348
349 e_url = a_Bw_expected_url(bw);
350 if (e_url && !a_Url_cmp(e_url, url) &&
351 !strcmp(URL_FRAGMENT(e_url),URL_FRAGMENT(url))) {
351352 /* we're already expecting that url (most probably a double-click) */
352353 return;
353354 }
354355 a_Nav_cancel_expect(bw);
355 bw->nav_expect_url = a_Url_dup(url);
356 bw->nav_expecting = TRUE;
356 a_Bw_expect(bw, url);
357357 Nav_open_url(bw, url, requester, 0);
358358 }
359359
369369 url = a_Url_dup(a_History_get_url(NAV_TOP_UIDX(bw)));
370370 /* Let's make reload be from Cache */
371371 a_Url_set_flags(url, URL_FLAGS(url) | URL_ReloadFromCache);
372 bw->nav_expect_url = a_Url_dup(url);
373 bw->nav_expecting = TRUE;
372 a_Bw_expect(bw, url);
374373 Nav_open_url(bw, url, NULL, 0);
375374 a_Url_free(url);
376375 }
500499 a_Url_set_flags(r_url, URL_FLAGS(r_url) | URL_E2EQuery);
501500 /* This is an explicit reload, so clear the SpamSafe flag */
502501 a_Url_set_flags(r_url, URL_FLAGS(r_url) & ~URL_SpamSafe);
503 bw->nav_expect_url = r_url;
504 bw->nav_expecting = TRUE;
502 a_Bw_expect(bw, r_url);
505503 Nav_open_url(bw, r_url, NULL, 0);
504 a_Url_free(r_url);
506505 }
507506 }
508507 }
1717 #define PREFS_FONT_CURSIVE "URW Chancery L"
1818 #define PREFS_FONT_FANTASY "DejaVu Sans" /* TODO: find good default */
1919 #define PREFS_FONT_MONOSPACE "DejaVu Sans Mono"
20 #define PREFS_SEARCH_URL "http://www.google.com/search?ie=UTF-8&oe=UTF-8&q=%s"
20 #define PREFS_SEARCH_URL "http://duckduckgo.com/lite/?kp=-1&q=%s"
2121 #define PREFS_NO_PROXY "localhost 127.0.0.1"
2222 #define PREFS_SAVE_DIR "/tmp/"
2323 #define PREFS_HTTP_REFERER "host"
2323 #define PREFS_GEOMETRY_DEFAULT_YPOS -9999
2424
2525 /* Panel sizes */
26 enum { P_tiny = 0, P_small, P_medium, P_large };
26 enum { P_tiny = 0, P_small, P_medium };
2727
2828 enum {PREFS_FILTER_ALLOW_ALL,
2929 PREFS_FILTER_SAME_DOMAIN};
175175 prefs.panel_size = P_tiny;
176176 else if (!dStrcasecmp(value, "small"))
177177 prefs.panel_size = P_small;
178 else if (!dStrcasecmp(value, "large"))
179 prefs.panel_size = P_large;
180178 else /* default to "medium" */
181179 prefs.panel_size = P_medium;
182180 break;
153153 //----------------------------------------------------------------------------
154154
155155 /*
156 * A button that highlights on mouse over
157 */
158 class CustLightButton : public Fl_Button {
159 Fl_Color norm_color;
160 public:
161 CustLightButton(int x, int y, int w, int h, const char *l=0) :
162 Fl_Button(x,y,w,h,l) { norm_color = color(); };
163 virtual int handle(int e);
164 };
165
166 int CustLightButton::handle(int e)
167 {
168 if (active()) {
169 if (e == FL_ENTER) {
170 color(51); // {17,26,51}
171 redraw();
172 } else if (e == FL_LEAVE || e == FL_RELEASE) {
173 color(norm_color);
174 redraw();
175 }
176 }
177 return Fl_Button::handle(e);
178 }
179
180 //----------------------------------------------------------------------------
181
182 /*
183156 * Used to handle "paste" within the toolbar's Clear button.
184157 */
185158 class CustPasteButton : public CustLightButton {
220193 padding = w > 2 ? w/2 : 1;
221194 }
222195 copy_label(lbl);
223 //measure_label(w,h);
224 //size(w+padding,this->h());
225196 }
226197 };
227198
302273 }
303274
304275 /*
305 * Change the color of the location bar.
306 *
307 static void color_change_cb(Fl_Widget *wid, void *data)
308 {
309 ((UI*)data)->color_change_cb_i();
310 }
311 */
312
313
314 /*
315276 * Send the browser to the new URL in the location.
316277 */
317278 static void location_cb(Fl_Widget *wid, void *data)
322283 _MSG("location_cb()\n");
323284 a_UIcmd_open_urlstr(a_UIcmd_get_bw_by_widget(i), i->value());
324285
325 if (ui->get_panelmode() == UI_TEMPORARILY_SHOW_PANELS) {
326 ui->set_panelmode(UI_HIDDEN);
327 }
286 if (ui->temporaryPanels())
287 ui->panels_toggle();
328288 }
329289
330290
536496 padding = w;
537497 btn->copy_label(PanelSize == P_tiny ? "&F" : "&File");
538498 btn->measure_label(w,h);
539 h = (PanelSize == P_large) ? mh : (PanelSize == P_tiny) ? bh : lh;
499 h = (PanelSize == P_tiny) ? bh : lh;
540500 btn->size(w+padding, h);
541501 p_xpos += btn->w();
542502 _MSG("UI::make_filemenu_button w=%d h=%d padding=%d\n", w, h, padding);
543 btn->box(PanelSize == P_large ? FL_THIN_UP_BOX : FL_THIN_UP_BOX);
503 btn->box(FL_THIN_UP_BOX);
544504 btn->callback(filemenu_cb, this);
545505 if (prefs.show_tooltip)
546506 btn->tooltip("File menu");
580540 bw = 42, bh = 36, mh = 0, lh = 22, lbl = 1;
581541 else
582542 bw = 45, bh = 45, mh = 0, lh = 28, lbl = 1;
583 } else { // P_large
584 if (Small_Icons)
585 bw = 42, bh = 36, mh = 22, lh = 22, lbl = 1;
586 else
587 bw = 45, bh = 45, mh = 24, lh = 28, lbl = 1;
588543 }
589544 nh = bh, fh = 28; sh = 20;
590545
603558 NavBar->rearrange();
604559 TopGroup->insert(*NavBar,0);
605560 } else {
606 if (PanelSize == P_large) {
607 MenuBar = new CustGroupHorizontal(0,0,ww,mh);
608 MenuBar->begin();
609 MenuBar->box(FL_THIN_UP_BOX);
610 Fl_Widget *bn = make_filemenu_button();
611 MenuBar->add_resizable(*new Fl_Box(bn->w(),0,ww - bn->w(),mh));
612 MenuBar->end();
613 MenuBar->rearrange();
614 TopGroup->insert(*MenuBar,0);
615
616 p_xpos = 0;
617 LocBar = new CustGroupHorizontal(0,0,ww,lh);
618 LocBar->begin();
619 make_location(ww);
620 LocBar->resizable(Location);
621 LocBar->end();
622 LocBar->rearrange();
623 TopGroup->insert(*LocBar,1);
624 } else {
625 LocBar = new CustGroupHorizontal(0,0,ww,lh);
626 LocBar->box(FL_NO_BOX);
627 LocBar->begin();
628 p_xpos = 0;
629 make_filemenu_button();
630 make_location(ww);
631 LocBar->resizable(Location);
632 LocBar->end();
633 LocBar->rearrange();
634 TopGroup->insert(*LocBar,0);
635 }
561 // Location
562 LocBar = new CustGroupHorizontal(0,0,ww,lh);
563 LocBar->box(FL_NO_BOX);
564 LocBar->begin();
565 p_xpos = 0;
566 make_filemenu_button();
567 make_location(ww);
568 LocBar->resizable(Location);
569 LocBar->end();
570 LocBar->rearrange();
571 TopGroup->insert(*LocBar,0);
636572
637573 // Toolbar
638574 p_ypos = 0;
651587 }
652588 NavBar->end();
653589 NavBar->rearrange();
654 TopGroup->insert(*NavBar,(MenuBar ? 2 : 1));
590 TopGroup->insert(*NavBar,1);
655591 }
656592 }
657593
693629 UI::UI(int x, int y, int ui_w, int ui_h, const char* label, const UI *cur_ui) :
694630 CustGroupVertical(x, y, ui_w, ui_h, label)
695631 {
696 PointerOnLink = FALSE;
697
698 MenuBar = LocBar = NavBar = StatusBar = NULL;
632 LocBar = NavBar = StatusBar = NULL;
699633
700634 Tabs = NULL;
701635 TabTooltip = NULL;
703637 TopGroup->box(FL_NO_BOX);
704638 clear_flag(SHORTCUT_LABEL);
705639
640 PanelTemporary = false;
706641 if (cur_ui) {
707642 PanelSize = cur_ui->PanelSize;
708643 CuteColor = cur_ui->CuteColor;
709644 Small_Icons = cur_ui->Small_Icons;
710 if (cur_ui->Panelmode == UI_HIDDEN ||
711 cur_ui->Panelmode == UI_TEMPORARILY_SHOW_PANELS)
712 Panelmode = UI_HIDDEN;
713 else
714 Panelmode = UI_NORMAL;
645 Panelmode = cur_ui->Panelmode;
715646 } else {
716647 // Set some default values
717 //PanelSize = P_tiny, CuteColor = 26, Small_Icons = 0;
718648 PanelSize = prefs.panel_size;
719649 Small_Icons = prefs.small_icons;
720650 CuteColor = 206;
739669 MainIdx = TopGroup->find(Main);
740670
741671 // Find text bar
742 FindBarSpace = 1;
743672 FindBar = new Findbar(ui_w, fh);
744673 TopGroup->add(FindBar);
745674
749678 TopGroup->end();
750679 TopGroup->rearrange();
751680
752 // Make the full screen button (to be attached to the viewport later)
753 // TODO: attach to the viewport
754 //FullScreen = new Fl_Button(0,0,15,15);
755 //FullScreen->image(ImgFullScreenOn);
756 //FullScreen->tooltip("Hide Controls");
757 //FullScreen->callback(fullscreen_cb, this);
758
759681 customize(0);
760682
761683 if (Panelmode == UI_HIDDEN) {
770692 {
771693 _MSG("UI::~UI()\n");
772694 dFree(TabTooltip);
773
774 if (!FindBarSpace)
775 delete FindBar;
776695 }
777696
778697 /*
787706 /* WORKAROUND: remove the Panel's fltk-tooltip.
788707 * Although the expose event is delivered, it has an offset. This
789708 * extra call avoids the lingering tooltip. */
790 if (Fl::event_inside(NavBar) ||
791 (LocBar && Fl::event_inside(LocBar)) ||
792 (MenuBar && Fl::event_inside(MenuBar)) ||
793 (StatusBar && Fl::event_inside(StatusBar)))
709 if (!Fl::event_inside(Main) &&
710 (Fl::event_inside((Fl_Widget*)tabs()) ||
711 Fl::event_inside(NavBar) ||
712 (LocBar && Fl::event_inside(LocBar)) ||
713 (StatusBar && Fl::event_inside(StatusBar))))
794714 window()->damage(FL_DAMAGE_EXPOSE,0,0,1,1);
795715
796716 return 0; // Receive as shortcut
820740 a_UIcmd_search_dialog(a_UIcmd_get_bw_by_widget(this));
821741 ret = 1;
822742 } else if (cmd == KEYS_GOTO) {
743 if (Panelmode == UI_HIDDEN) {
744 panels_toggle();
745 temporaryPanels(true);
746 }
823747 focus_location();
824748 ret = 1;
825749 } else if (cmd == KEYS_HIDE_PANELS) {
826750 /* Hide findbar if present, hide panels if not */
827 (FindBarSpace) ? findbar_toggle(0) : panels_toggle();
828 ret = 1;
829 //if (get_panelmode() == UI_TEMPORARILY_SHOW_PANELS)
830 // set_panelmode(UI_HIDDEN);
751 (FindBar->visible()) ? findbar_toggle(0) : panels_toggle();
752 temporaryPanels(false);
753 ret = 1;
831754 } else if (cmd == KEYS_OPEN) {
832755 a_UIcmd_open_file(a_UIcmd_get_bw_by_widget(this));
833756 ret = 1;
897820 */
898821 void UI::focus_location()
899822 {
900 if (get_panelmode() == UI_HIDDEN) {
901 // Temporary panel handling is disabled now.
902 //set_panelmode(UI_TEMPORARILY_SHOW_PANELS);
903 }
904823 Location->take_focus();
905824 // Make text selected when already focused.
906825 Location->position(Location->size(), 0);
1037956 {
1038957 // Remove current panel's bars
1039958 init_sizes();
1040 TopGroup->remove(MenuBar);
1041 Fl::delete_widget(MenuBar);
1042959 TopGroup->remove(LocBar);
1043960 Fl::delete_widget(LocBar);
1044961 TopGroup->remove(NavBar);
1045962 Fl::delete_widget(NavBar);
1046 MenuBar = LocBar = NavBar = NULL;
963 LocBar = NavBar = NULL;
1047964
1048965 // Set internal vars for panel size
1049966 PanelSize = new_size;
1074991 }
1075992
1076993 /*
1077 * Set or remove the Panelmode flag and update the UI accordingly
1078 */
1079 void UI::set_panelmode(UIPanelmode mode)
1080 {
1081 if (mode == UI_HIDDEN) {
1082 //Panel->hide();
1083 StatusBar->hide();
1084 } else {
1085 /* UI_NORMAL or UI_TEMPORARILY_SHOW_PANELS */
1086 //Panel->show();
1087 StatusBar->show();
1088 }
1089 Panelmode = mode;
1090 TopGroup->rearrange();
1091 }
1092
1093 /*
1094 * Get the value of the panelmode flag
1095 */
1096 UIPanelmode UI::get_panelmode()
1097 {
1098 return Panelmode;
1099 }
1100
1101 /*
1102 * Toggle the Control Panel out of the way
1103 */
1104 void UI::panelmode_cb_i()
1105 {
1106 set_panelmode((UIPanelmode) !Panelmode);
1107 }
1108
1109 /*
1110994 * Set 'nw' as the main render area widget
1111995 */
1112996 void UI::set_render_layout(Fl_Group *nw)
11291013 switch (btn) {
11301014 case UI_BACK:
11311015 (sens) ? Back->activate() : Back->deactivate();
1132 // Back->redraw(DAMAGE_HIGHLIGHT);
11331016 break;
11341017 case UI_FORW:
11351018 (sens) ? Forw->activate() : Forw->deactivate();
1136 // Forw->redraw(DAMAGE_HIGHLIGHT);
11371019 break;
11381020 case UI_STOP:
11391021 (sens) ? Stop->activate() : Stop->deactivate();
1140 // Stop->redraw(DAMAGE_HIGHLIGHT);
11411022 break;
11421023 default:
11431024 break;
11591040 {
11601041 /* WORKAROUND:
11611042 * This is tricky: As fltk-1.3 resizes hidden widgets (which it
1162 * doesn't resize when visible!). We need to go through hoops to
1043 * doesn't resize when visible!). We need to set the size to (0,0) to
11631044 * get the desired behaviour.
11641045 * (STR#2639 in FLTK bug tracker).
11651046 */
11661047
11671048 if (add) {
1168 if (!FindBarSpace) {
1169 // show
1170 Main->size(Main->w(), Main->h()-FindBar->h());
1171 insert(*FindBar, StatusBar);
1172 FindBar->show();
1173 FindBarSpace = 1;
1174 } else {
1175 // select text
1176 FindBar->show();
1177 }
1178 } else if (!add && FindBarSpace) {
1049 if (!FindBar->visible())
1050 FindBar->size(w(), fh);
1051 FindBar->show();
1052 } else {
11791053 // hide
1180 Main->size(Main->w(), Main->h()+FindBar->h());
1181 remove(FindBar);
1182 FindBarSpace = 0;
1054 FindBar->size(0,0);
1055 FindBar->hide();
1056 // reset state
1057 a_UIcmd_findtext_reset(a_UIcmd_get_bw_by_widget(this));
1058 // focus main area
1059 focus_main();
11831060 }
11841061 TopGroup->rearrange();
11851062 }
11961073
11971074 // hide/show panels
11981075 init_sizes();
1199 if (MenuBar) {
1200 hide ? MenuBar->size(0,0) : MenuBar->size(w(),mh);
1201 hide ? MenuBar->hide() : MenuBar->show();
1202 }
12031076 if (LocBar) {
12041077 hide ? LocBar->size(0,0) : LocBar->size(w(),lh);
12051078 hide ? LocBar->hide() : LocBar->show();
12151088 }
12161089
12171090 TopGroup->rearrange();
1218 }
1091 Panelmode = (hide) ? UI_HIDDEN : UI_NORMAL;
1092 }
2727
2828 typedef enum {
2929 UI_NORMAL = 0, /* make sure it's compatible with bool */
30 UI_HIDDEN = 1,
31 UI_TEMPORARILY_SHOW_PANELS
30 UI_HIDDEN = 1
3231 } UIPanelmode;
32
33
34 // Min size to fit the full UI
35 #define UI_MIN_W 600
36 #define UI_MIN_H 200
3337
3438 // Private classes
3539 class CustProgressBox;
3640 class CustTabs;
3741
3842
39 // Class definition ----------------------------------------------------------
43 // Class definitions ---------------------------------------------------------
4044 /*
4145 * Used to reposition group's widgets when some of them are hidden.
4246 * All children get the height of the group but retain their original width.
4347 * The resizable child get's the remaining space.
4448 */
4549 class CustGroupHorizontal : public Fl_Group {
50 Fl_Widget *rsz;
4651 public:
4752 CustGroupHorizontal(int x,int y,int w ,int h,const char *l = 0) :
4853 Fl_Group(x,y,w,h,l) { };
5257 int sum = 0, _x = x();
5358 int children_ = children();
5459
60 if (resizable())
61 rsz = resizable();
62
5563 for (int i=0; i < children_; i++)
5664 if (a[i] != resizable() && a[i]->visible())
5765 sum += a[i]->w();
5866
5967 for (int i=0; i < children_; i++) {
60 if (a[i] == resizable()) {
61 a[i]->resize(_x, y(), w() - sum, h());
68 if (a[i] == rsz) {
69 if (w() > sum) {
70 a[i]->resize(_x, y(), w()-sum, h());
71 if (!resizable())
72 resizable(rsz);
73 } else {
74 /* widgets overflow width */
75 a[i]->resize(_x, y(), 0, h());
76 resizable(NULL);
77 }
6278 } else {
6379 a[i]->resize(_x, y(), a[i]->w(), h());
6480 }
98114 }
99115 };
100116
117 /*
118 * A button that highlights on mouse over
119 */
120 class CustLightButton : public Fl_Button {
121 Fl_Color norm_color, light_color;
122 public:
123 CustLightButton(int x, int y, int w, int h, const char *l=0) :
124 Fl_Button(x,y,w,h,l) { norm_color = color(); light_color = 51; };
125 virtual int handle(int e)
126 {
127 if (active()) {
128 if (e == FL_ENTER) {
129 color(light_color); // {17,26,51}
130 redraw();
131 } else if (e == FL_LEAVE || e == FL_RELEASE || e == FL_HIDE) {
132 color(norm_color);
133 redraw();
134 }
135 } else if (e == FL_DEACTIVATE && color() != norm_color) {
136 color(norm_color);
137 redraw();
138 }
139 return Fl_Button::handle(e);
140 }
141 void hl_color(Fl_Color col) { light_color = col; };
142 };
101143
102144 //
103145 // UI class definition -------------------------------------------------------
108150
109151 CustGroupVertical *TopGroup;
110152 Fl_Button *Back, *Forw, *Home, *Reload, *Save, *Stop, *Bookmarks, *Tools,
111 *Clear, *Search, *Help, *FullScreen, *BugMeter, *FileButton;
112 CustGroupHorizontal *MenuBar, *LocBar, *NavBar, *StatusBar;
153 *Clear, *Search, *Help, *BugMeter, *FileButton;
154 CustGroupHorizontal *LocBar, *NavBar, *StatusBar;
113155 Fl_Input *Location;
114156 CustProgressBox *PProg, *IProg;
115157 Fl_Group *Panel, *Main;
116158 Fl_Output *StatusOutput;
117159 Findbar *FindBar;
118160
119 int FindBarSpace, MainIdx;
161 int MainIdx;
120162 // Panel customization variables
121163 int PanelSize, CuteColor, Small_Icons;
122164 int p_xpos, p_ypos, bw, bh, mh, lh, nh, fh, sh, pw, lbl;
165 bool PanelTemporary;
123166
124167 UIPanelmode Panelmode;
125 int PointerOnLink;
126168 Fl_Button *make_button(const char *label, Fl_Image *img,
127169 Fl_Image*deimg, int b_n, int start = 0);
128170 void make_toolbar(int tw, int th);
153195 void customize(int flags);
154196 void button_set_sens(UIButton btn, int sens);
155197 void paste_url();
156 void set_panelmode(UIPanelmode mode);
157 UIPanelmode get_panelmode();
158198 int get_panelsize() { return PanelSize; }
159199 int get_smallicons() { return Small_Icons; }
160200 void change_panel(int new_size, int small_icons);
163203
164204 CustTabs *tabs() { return Tabs; }
165205 void tabs(CustTabs *tabs) { Tabs = tabs; }
166 int pointerOnLink() { return PointerOnLink; }
167 void pointerOnLink(int flag) { PointerOnLink = flag; }
206 bool temporaryPanels() { return PanelTemporary; }
207 void temporaryPanels(bool val) { PanelTemporary = val; }
168208
169209 // Hooks to method callbacks
170210 void color_change_cb_i();
171211 void toggle_cb_i();
172 void panelmode_cb_i();
173212 };
174213
175214 #endif // __UI_HH__
00 /*
11 * File: uicmd.cc
22 *
3 * Copyright (C) 2005-2007 Jorge Arellano Cid <jcid@dillo.org>
3 * Copyright (C) 2005-2011 Jorge Arellano Cid <jcid@dillo.org>
44 *
55 * This program is free software; you can redistribute it and/or modify
66 * it under the terms of the GNU General Public License as published by
2020 #include <FL/Fl_Double_Window.H>
2121 #include <FL/Fl_Wizard.H>
2222 #include <FL/Fl_Box.H>
23 #include <FL/Fl_Pack.H>
24 #include <FL/Fl_Scroll.H>
2325 #include <FL/names.h>
2426
2527 #include "paths.hh"
4143
4244 #include "nav.h"
4345
44 #define DEFAULT_TAB_LABEL "Dillo"
46 //#define DEFAULT_TAB_LABEL "-.untitled.-"
47 #define DEFAULT_TAB_LABEL "-.new.-"
4548
4649 // Handy macro
4750 #define BW2UI(bw) ((UI*)((bw)->ui))
6164 * Forward declarations
6265 */
6366 static BrowserWindow *UIcmd_tab_new(CustTabs *tabs, UI *old_ui, int focus);
67 static void close_tab_btn_cb (Fl_Widget *w, void *cb_data);
6468
6569 //----------------------------------------------------------------------------
6670
8387 /*
8488 * Allows fine control of the tabbed interface
8589 */
86 class CustTabs : public CustGroupHorizontal {
87 int tab_w, tab_h, ctab_h, tab_n;
90 class CustTabs : public Fl_Group {
91 int tab_w, tab_h, ctab_h, btn_w, ctl_w;
8892 Fl_Wizard *Wizard;
89 int tabcolor_inactive, tabcolor_active, curtab_idx;
93 Fl_Scroll *Scroll;
94 Fl_Pack *Pack;
95 Fl_Group *Control;
96 CustLightButton *CloseBtn;
97 int tabcolor_inactive, tabcolor_active;
98
99 void update_pack_offset(void);
100 void resize(int x, int y, int w, int h)
101 { Fl_Group::resize(x,y,w,h); update_pack_offset(); }
102 int get_btn_idx(UI *ui);
103
90104 public:
91105 CustTabs (int ww, int wh, int th, const char *lbl=0) :
92 CustGroupHorizontal(0,0,ww,th,lbl) {
93 tab_w = 80, tab_h = th, ctab_h = 1, tab_n = 0, curtab_idx = -1;
106 Fl_Group(0,0,ww,th,lbl) {
107 Pack = NULL;
108 tab_w = 50, tab_h = th, ctab_h = 1, btn_w = 20, ctl_w = 1*btn_w+2;
94109 tabcolor_active = FL_DARK_CYAN; tabcolor_inactive = 206;
95110 resize(0,0,ww,ctab_h);
96 resizable(NULL);
111 /* tab buttons go inside a pack within a scroll */
112 Scroll = new Fl_Scroll(0,0,ww-ctl_w,ctab_h);
113 Scroll->type(0); /* no scrollbars */
114 Scroll->box(FL_NO_BOX);
115 Pack = new Fl_Pack(0,0,ww-ctl_w,tab_h);
116 Pack->type(Fl_Pack::HORIZONTAL);
117 Pack->box(FL_NO_BOX); //FL_THIN_DOWN_FRAME
118 Pack->end();
119 Scroll->end();
120 resizable(Scroll);
121
122 /* control buttons go inside a group */
123 Control = new Fl_Group(ww-ctl_w,0,ctl_w,ctab_h);
124 CloseBtn = new CustLightButton(ww-ctl_w+2,0,btn_w,ctab_h, "X");
125 CloseBtn->box(FL_PLASTIC_ROUND_UP_BOX);
126 CloseBtn->labelcolor(0x00641000);
127 CloseBtn->hl_color(FL_WHITE);
128 CloseBtn->clear_visible_focus();
129 CloseBtn->tooltip(prefs.right_click_closes_tab ?
130 "Close current tab.\nor Right-click tab label to close." :
131 "Close current tab.\nor Middle-click tab label to close.");
132 CloseBtn->callback(close_tab_btn_cb, this);
133 CloseBtn->hide();
134 Control->end();
135
97136 box(FL_FLAT_BOX);
98137 end();
99138
105144 UI *add_new_tab(UI *old_ui, int focus);
106145 void remove_tab(UI *ui);
107146 Fl_Wizard *wizard(void) { return Wizard; }
108 int get_btn_idx(UI *ui);
109 int num_tabs() { return children(); }
147 int num_tabs() { return (Pack ? Pack->children() : 0); }
110148 void switch_tab(CustTabButton *cbtn);
111149 void prev_tab(void);
112150 void next_tab(void);
113
114151 void set_tab_label(UI *ui, const char *title);
115152 };
116153
129166 (b == FL_MIDDLE_MOUSE && !prefs.right_click_closes_tab)) {
130167 // TODO: just an example, not necessarily final
131168 a_UIcmd_close_bw(a_UIcmd_get_bw_by_widget(btn->ui()));
169 }
170 }
171
172 /*
173 * Callback for the close-tab button
174 */
175 static void close_tab_btn_cb (Fl_Widget *, void *cb_data)
176 {
177 CustTabs *tabs = (CustTabs*) cb_data;
178 int b = Fl::event_button();
179
180 if (b == FL_LEFT_MOUSE) {
181 a_UIcmd_close_bw(a_UIcmd_get_bw_by_widget(tabs->wizard()->value()));
132182 }
133183 }
134184
143193 UI *ui = (UI*)wizard()->value();
144194 BrowserWindow *bw = a_UIcmd_get_bw_by_widget(ui);
145195 KeysCommand_t cmd = Keys::getKeyCmd();
146 if (Fl::event_key() == FL_Escape) {
147 // Hide findbar if present
148 ui->findbar_toggle(0);
149 ret = 1;
150 } else if (cmd == KEYS_NOP) {
196 if (cmd == KEYS_NOP) {
151197 // Do nothing
152198 _MSG("CustTabs::handle KEYS_NOP\n");
153199 } else if (cmd == KEYS_NEW_TAB) {
171217 }
172218 }
173219
174 return (ret) ? ret : CustGroupHorizontal::handle(e);
220 return (ret) ? ret : Fl_Group::handle(e);
175221 }
176222
177223 /*
179225 */
180226 UI *CustTabs::add_new_tab(UI *old_ui, int focus)
181227 {
182 char tab_label[64];
183
184228 if (num_tabs() == 1) {
185229 // Show tabbar
186230 ctab_h = tab_h;
187231 Wizard->resize(0,ctab_h,Wizard->w(),window()->h()-ctab_h);
188232 resize(0,0,window()->w(),ctab_h); // tabbar
189 child(0)->show(); // first tab button
233 CloseBtn->show();
234 {int w = 0, h; Pack->child(0)->measure_label(w, h);
235 Pack->child(0)->size(w+14,ctab_h);}
236 Pack->child(0)->show(); // first tab button
190237 window()->init_sizes();
191238 }
192239
240 /* The UI is constructed in a comfortable fitting size, and then resized
241 * so FLTK doesn't get confused later with even smaller dimensions! */
193242 current(0);
194 UI *new_ui = new UI(0,ctab_h,Wizard->w(),Wizard->h(),0,old_ui);
243 UI *new_ui = new UI(0,0,UI_MIN_W,UI_MIN_H,"Dillo:",old_ui);
244 new_ui->resize(0,ctab_h,Wizard->w(),Wizard->h());
195245 new_ui->tabs(this);
196246 Wizard->add(new_ui);
197247 new_ui->show();
198248
199 snprintf(tab_label, 64,"ctab%d", ++tab_n);
200249 CustTabButton *btn = new CustTabButton(num_tabs()*tab_w,0,tab_w,ctab_h);
201 btn->align(FL_ALIGN_INSIDE|FL_ALIGN_CLIP);
202 btn->copy_label(tab_label);
250 btn->align(FL_ALIGN_INSIDE);
251 btn->labelsize(btn->labelsize()-2);
252 btn->copy_label(DEFAULT_TAB_LABEL);
203253 btn->clear_visible_focus();
204254 btn->box(FL_PLASTIC_ROUND_UP_BOX);
205255 btn->color(focus ? tabcolor_active : tabcolor_inactive);
206256 btn->ui(new_ui);
207 add(btn);
208257 btn->callback(tab_btn_cb, this);
258 Pack->add(btn); // append
209259
210260 if (focus) {
211261 switch_tab(btn);
215265 }
216266 if (num_tabs() == 1)
217267 btn->hide();
218 rearrange();
268 update_pack_offset();
219269
220270 return new_ui;
221271 }
231281 int act_idx = get_btn_idx((UI*)Wizard->value());
232282 // get to-be-removed tab idx
233283 int rm_idx = get_btn_idx(ui);
234 btn = (CustTabButton*)child(rm_idx);
284 btn = (CustTabButton*)Pack->child(rm_idx);
235285
236286 if (act_idx == rm_idx) {
237287 // Active tab is being closed, switch to another one
238288 rm_idx > 0 ? prev_tab() : next_tab();
239289 }
240 remove(rm_idx);
290 Pack->remove(rm_idx);
291 update_pack_offset();
241292 delete btn;
242 rearrange();
243293
244294 Wizard->remove(ui);
245295 delete(ui);
246296
247 if (num_tabs() == 0) {
248 window()->hide();
249 // TODO: free memory
250 //delete window();
251
252 } else if (num_tabs() == 1) {
297 if (num_tabs() == 1) {
253298 // hide tabbar
254299 ctab_h = 1;
255 child(0)->hide(); // first tab button
300 CloseBtn->hide();
301 Pack->child(0)->size(0,0);
302 Pack->child(0)->hide(); // first tab button
256303 resize(0,0,window()->w(),ctab_h); // tabbar
257304 Wizard->resize(0,ctab_h,Wizard->w(),window()->h()-ctab_h);
258305 window()->init_sizes();
263310 int CustTabs::get_btn_idx(UI *ui)
264311 {
265312 for (int i = 0; i < num_tabs(); ++i) {
266 CustTabButton *btn = (CustTabButton*)child(i);
313 CustTabButton *btn = (CustTabButton*)Pack->child(i);
267314 if (btn->ui() == ui)
268315 return i;
269316 }
270317 return -1;
318 }
319
320 /*
321 * Keep active tab visible
322 * (Pack children have unusable x() coordinate)
323 */
324 void CustTabs::update_pack_offset()
325 {
326 dReturn_if (num_tabs() == 0);
327
328 // get active tab button
329 int act_idx = get_btn_idx((UI*)Wizard->value());
330 CustTabButton *cbtn = (CustTabButton*)Pack->child(act_idx);
331
332 // calculate tab button's x() coordinates
333 int x_i = 0, x_f;
334 for (int j=0; j < act_idx; ++j)
335 x_i += Pack->child(j)->w();
336 x_f = x_i + cbtn->w();
337
338 int scr_x = Scroll->xposition(), scr_y = Scroll->yposition();
339 int px_i = x_i - scr_x;
340 int px_f = px_i + cbtn->w();
341 int pw = Scroll->window()->w() - ctl_w;
342 _MSG(" scr_x=%d btn_x=%d px_i=%d btn_w=%d px_f=%d pw=%d",
343 Scroll->xposition(),cbtn->x(),px_i,cbtn->w(),px_f,pw);
344 if (px_i < 0) {
345 Scroll->scroll_to(x_i, scr_y);
346 } else if (px_i > pw || (px_i > 0 && px_f > pw)) {
347 Scroll->scroll_to(MIN(x_i, x_f-pw), scr_y);
348 }
349 Scroll->redraw();
350 _MSG(" >>scr_x=%d btn0_x=%d\n", scr_x, Pack->child(0)->x());
271351 }
272352
273353 /*
283363 if (cbtn->ui() != old_ui) {
284364 // Set old tab label to normal color
285365 if ((idx = get_btn_idx(old_ui)) != -1) {
286 btn = (CustTabButton*)child(idx);
366 btn = (CustTabButton*)Pack->child(idx);
287367 btn->color(tabcolor_inactive);
288368 btn->redraw();
289369 }
290370 Wizard->value(cbtn->ui());
291371 cbtn->color(tabcolor_active);
292372 cbtn->redraw();
373 update_pack_offset();
293374
294375 // Update window title
295376 if ((bw = a_UIcmd_get_bw_by_widget(cbtn->ui()))) {
304385 int idx;
305386
306387 if ((idx = get_btn_idx((UI*)Wizard->value())) != -1)
307 switch_tab( (CustTabButton*)child(idx > 0 ? idx-1 : num_tabs()-1) );
388 switch_tab((CustTabButton*)Pack->child(idx>0 ? idx-1 : num_tabs()-1));
308389 }
309390
310391 void CustTabs::next_tab()
312393 int idx;
313394
314395 if ((idx = get_btn_idx((UI*)Wizard->value())) != -1)
315 switch_tab( (CustTabButton*)child((idx+1 < num_tabs()) ? idx+1 : 0) );
396 switch_tab((CustTabButton*)Pack->child((idx+1<num_tabs()) ? idx+1 : 0));
316397 }
317398
318399 /*
325406
326407 if (idx != -1) {
327408 // Make a label for this tab
328 size_t tab_chars = 7, label_len = strlen(label);
409 size_t tab_chars = 15, label_len = strlen(label);
329410
330411 if (label_len > tab_chars)
331412 tab_chars = a_Utf8_end_of_char(label, tab_chars - 1) + 1;
334415 snprintf(title + tab_chars, 4, "...");
335416
336417 // Avoid unnecessary redraws
337 if (strcmp(child(idx)->label(), title)) {
338 child(idx)->copy_label(title);
418 if (strcmp(Pack->child(idx)->label(), title)) {
419 int w = 0, h;
420 Pack->child(idx)->copy_label(title);
421 Pack->child(idx)->measure_label(w, h);
422 Pack->child(idx)->size(w+14,ctab_h);
423 update_pack_offset();
339424 }
340425 }
341426 }
344429 //----------------------------------------------------------------------------
345430
346431 static void win_cb (Fl_Widget *w, void *cb_data) {
347 int choice = 1;
348432 CustTabs *tabs = (CustTabs*) cb_data;
349
350 if (tabs->num_tabs() > 1)
433 int choice = 1, ntabs = tabs->num_tabs();
434
435 if (ntabs > 1)
351436 choice = a_Dialog_choice5("Window contains more than one tab.",
352437 "Close", "Cancel", NULL, NULL, NULL);
353438 if (choice == 1)
354 while (tabs->num_tabs())
439 while (ntabs-- > 0)
355440 a_UIcmd_close_bw(a_UIcmd_get_bw_by_widget(tabs->wizard()->value()));
356441 }
357442
401486
402487 int focus = 1;
403488 new_bw = UIcmd_tab_new(DilloTabs, old_ui, focus);
404 win->resizable(BW2UI(new_bw));
489 win->resizable(DilloTabs->wizard());
405490 win->show();
406491
407492 if (old_bw == NULL && prefs.xpos >= 0 && prefs.ypos >= 0) {
448533 // Copy the layout pointer into the bw data
449534 new_bw->render_layout = (void*)layout;
450535
536 // Clear the window title
537 if (focus)
538 new_ui->window()->copy_label(new_ui->label());
539
451540 // WORKAROUND: see findbar_toggle()
452541 new_ui->findbar_toggle(0);
453542
461550 {
462551 BrowserWindow *bw = (BrowserWindow *)vbw;
463552 UI *ui = BW2UI(bw);
553 CustTabs *tabs = ui->tabs();
464554 Layout *layout = (Layout*)bw->render_layout;
465555
466 MSG("a_UIcmd_close_bw\n");
556 _MSG("a_UIcmd_close_bw\n");
467557 a_Bw_stop_clients(bw, BW_Root + BW_Img + BW_Force);
468558 delete(layout);
469 if (ui->tabs()) {
470 ui->tabs()->remove_tab(ui);
559 if (tabs) {
560 tabs->remove_tab(ui);
561 if (tabs->num_tabs() == 0)
562 delete tabs->window();
471563 }
472564 a_Bw_free(bw);
473565 }
535627 {
536628 if (url) {
537629 a_Nav_push(bw, url, NULL);
630 BW2UI(bw)->focus_main();
538631 } else {
539632 // Used to start a bw with a blank screen
540633 BW2UI(bw)->focus_location();
541634 a_UIcmd_set_buttons_sens(bw);
542635 }
543 #if 0
544 if (BW2UI(bw)->get_panelmode() == UI_TEMPORARILY_SHOW_PANELS)
545 BW2UI(bw)->set_panelmode(UI_HIDDEN);
546 a_UIcmd_focus_main_area(bw);
547 #endif
548636 }
549637
550638 static void UIcmd_open_url_nbw(BrowserWindow *new_bw, const DilloUrl *url)
785873 Dstr *ds = dStr_sized_new(128);
786874
787875 /* parse search_url into label and url */
788 a_Misc_parse_search_url(src, &l, &u);
789
790 for (c = u; *c; c++) {
791 if (*c == '%')
792 switch(*++c) {
793 case 's':
794 dStr_append(ds, keys); break;;
795 case '%':
796 dStr_append_c(ds, '%'); break;;
797 case 0:
798 MSG_WARN("search_url ends with '%%'\n"); c--; break;;
799 default:
800 MSG_WARN("illegal specifier '%%%c' in search_url\n", *c);
801 }
802 else
803 dStr_append_c(ds, *c);
876 if (a_Misc_parse_search_url(src, &l, &u) == 0) {
877 for (c = u; *c; c++) {
878 if (*c == '%')
879 switch(*++c) {
880 case 's':
881 dStr_append(ds, keys); break;;
882 case '%':
883 dStr_append_c(ds, '%'); break;;
884 case 0:
885 MSG_WARN("search_url ends with '%%'\n"); c--; break;;
886 default:
887 MSG_WARN("illegal specifier '%%%c' in search_url\n", *c);
888 }
889 else
890 dStr_append_c(ds, *c);
891 }
804892 }
805893 dFree(keys);
806894
846934 a_UIcmd_set_save_dir(prefs.save_dir);
847935
848936 SuggestedName = UIcmd_make_save_filename(URL_STR(url));
849 name = a_Dialog_save_file("Save Link as File", NULL, SuggestedName);
850 MSG("a_UIcmd_save_link: %s\n", name);
937 if ((name = a_Dialog_save_file("Save Link as File", NULL, SuggestedName))) {
938 MSG("a_UIcmd_save_link: %s\n", name);
939 a_Nav_save_url(bw, url, name);
940 }
851941 dFree(SuggestedName);
852
853 if (name) {
854 a_Nav_save_url(bw, url, name);
855 }
856942 }
857943
858944 /*
11451231 }
11461232
11471233 /*
1148 * Set the page title in the window titlebar and tab label.
1234 * Set the page title in the tab label and window titlebar.
11491235 * (Update window titlebar for the current tab only)
11501236 */
11511237 void a_UIcmd_set_page_title(BrowserWindow *bw, const char *label)
11531239 const int size = 128;
11541240 char title[size];
11551241
1242 if (snprintf(title, size, "Dillo: %s", label ? label : "") >= size) {
1243 uint_t i = MIN(size - 4, 1 + a_Utf8_end_of_char(title, size - 8));
1244 snprintf(title + i, 4, "...");
1245 }
1246 BW2UI(bw)->copy_label(title);
1247 BW2UI(bw)->tabs()->set_tab_label(BW2UI(bw), label ? label : "");
1248
11561249 if (a_UIcmd_get_bw_by_widget(BW2UI(bw)->tabs()->wizard()->value()) == bw) {
11571250 // This is the focused bw, set window title
1158 if (snprintf(title, size, "Dillo: %s", label) >= size) {
1159 uint_t i = MIN(size - 4, 1 + a_Utf8_end_of_char(title, size - 8));
1160 snprintf(title + i, 4, "...");
1161 }
1162 BW2UI(bw)->copy_label(title);
11631251 BW2UI(bw)->window()->copy_label(title);
11641252 }
1165 BW2UI(bw)->tabs()->set_tab_label(BW2UI(bw), label);
11661253 }
11671254
11681255 /*
11961283 BW2UI(bw)->button_set_sens(UI_BACK, sens);
11971284 // Forward
11981285 sens = (a_Nav_stack_ptr(bw) < a_Nav_stack_size(bw) - 1 &&
1199 !bw->nav_expecting);
1286 !a_Bw_expecting(bw));
12001287 BW2UI(bw)->button_set_sens(UI_FORW, sens);
1201 }
1202
1203 /*
1204 * Keep track of mouse pointer over a link.
1205 */
1206 void a_UIcmd_set_pointer_on_link(BrowserWindow *bw, int flag)
1207 {
1208 BW2UI(bw)->pointerOnLink(flag);
1209 }
1210
1211 /*
1212 * Is the mouse pointer over a link?
1213 */
1214 int a_UIcmd_pointer_on_link(BrowserWindow *bw)
1215 {
1216 return BW2UI(bw)->pointerOnLink();
12171288 }
12181289
12191290 /*
7777 void a_UIcmd_set_page_title(BrowserWindow *bw, const char *label);
7878 void a_UIcmd_set_msg(BrowserWindow *bw, const char *format, ...);
7979 void a_UIcmd_set_buttons_sens(BrowserWindow *bw);
80 void a_UIcmd_set_pointer_on_link(BrowserWindow *bw, int flag);
81 int a_UIcmd_pointer_on_link(BrowserWindow *bw);
8280
8381 #ifdef __cplusplus
8482 }
232232 dStr_append(SolvedUrl, BaseStr);
233233 if ((p = strchr(SolvedUrl->str, '#')))
234234 dStr_truncate(SolvedUrl, p - SolvedUrl->str);
235 if (!BaseUrl->path)
236 dStr_append_c(SolvedUrl, '/');
235237
236238 if (RelUrl->query) { /* query */
237239 if (BaseUrl->query)
4646 * (non '_'-ended macros MUST use these for initialization sake)
4747 */
4848 /* these MAY return NULL: */
49 #define URL_SCHEME_(u) u->scheme
50 #define URL_AUTHORITY_(u) u->authority
51 #define URL_PATH_(u) u->path
52 #define URL_QUERY_(u) u->query
53 #define URL_FRAGMENT_(u) u->fragment
49 #define URL_SCHEME_(u) (u)->scheme
50 #define URL_AUTHORITY_(u) (u)->authority
51 #define URL_PATH_(u) (u)->path
52 #define URL_QUERY_(u) (u)->query
53 #define URL_FRAGMENT_(u) (u)->fragment
5454 #define URL_HOST_(u) a_Url_hostname(u)
55 #define URL_ALT_(u) u->alt
55 #define URL_ALT_(u) (u)->alt
5656 #define URL_STR_(u) a_Url_str(u)
5757 /* this returns a Dstr* */
58 #define URL_DATA_(u) u->data
58 #define URL_DATA_(u) (u)->data
5959 /* these return an integer */
60 #define URL_PORT_(u) (URL_HOST(u), u->port)
61 #define URL_FLAGS_(u) u->flags
62 #define URL_ILLEGAL_CHARS_(u) url->illegal_chars
63 #define URL_ILLEGAL_CHARS_SPC_(u) url->illegal_chars_spc
60 #define URL_PORT_(u) (URL_HOST(u), (u)->port)
61 #define URL_FLAGS_(u) (u)->flags
62 #define URL_ILLEGAL_CHARS_(u) (u)->illegal_chars
63 #define URL_ILLEGAL_CHARS_SPC_(u) (u)->illegal_chars_spc
6464
6565 /*
6666 * Access methods that never return NULL.
114114 styleAttrs.setBorderStyle (BORDER_SOLID);
115115 styleAttrs.padding.setVal (1);
116116 styleAttrs.backgroundColor = NULL;
117 styleAttrs.width = createPerLength (0.5);
118 styleAttrs.height = createPerLength (0.5);
117 styleAttrs.width = createPerLength (0.25);
118 styleAttrs.height = createPerLength (0.25);
119119
120120 Style *imageStyle1 = Style::create (layout, &styleAttrs);
121121 image1 = new dw::Image ("A longer ALT Text to demonstrate clipping.");