Dillo v3.1.1-119-g140d9ebd
Loading...
Searching...
No Matches
uicmd.cc
Go to the documentation of this file.
1/*
2 * File: uicmd.cc
3 *
4 * Copyright (C) 2005-2011 Jorge Arellano Cid <jcid@dillo.org>
5 * Copyright (C) 2024 Rodrigo Arias Mallo <rodarima@gmail.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 */
12
18#include <string.h>
19#include <stdio.h>
20#include <stdarg.h>
21#include <stdlib.h> /* for qsort */
22#include <math.h> /* for rint */
23#include <limits.h> /* for UINT_MAX */
24#include <sys/stat.h>
25
26#include <FL/Fl.H>
27#include <FL/Fl_Widget.H>
28#include <FL/Fl_Double_Window.H>
29#include <FL/Fl_Wizard.H>
30#include <FL/Fl_Box.H>
31#include <FL/Fl_Pack.H>
32#include <FL/Fl_Scroll.H>
33#include <FL/names.h>
34
35#include "paths.hh"
36#include "keys.hh"
37#include "ui.hh"
38#include "uicmd.hh"
39#include "timeout.hh"
40#include "utf8.hh"
41#include "menu.hh"
42#include "dialog.hh"
43#include "xembed.hh"
44#include "bookmark.h"
45#include "history.h"
46#include "msg.h"
47#include "prefs.h"
48#include "misc.h"
49#include "dlib/dlib.h"
50
51#include "dw/fltkviewport.hh"
52
53#include "nav.h"
54
55//#define DEFAULT_TAB_LABEL "-.untitled.-"
56#define DEFAULT_TAB_LABEL "-.new.-"
57
58// Handy macro
59#define BW2UI(bw) ((UI*)((bw)->ui))
60
61// Platform idependent part
62using namespace dw::core;
63// FLTK related
64using namespace dw::fltk;
65
66
67/*
68 * Local data
69 */
70static const char *save_dir = "";
71
72struct Tabgroup {
73 CustTabs *tabs;
74 struct Tabgroup *next;
75};
76
77/* An stack of CustTabs groups, each maps to one FLTK window. Points to
78 * the last one created. */
79static struct Tabgroup *tabgroups = NULL;
80
81/*
82 * Forward declarations
83 */
84static BrowserWindow *UIcmd_tab_new(CustTabs *tabs, UI *old_ui, int focus);
85static void close_tab_btn_cb (Fl_Widget *w, void *cb_data);
86static char *UIcmd_make_search_str(const char *str);
87static void UIcmd_set_window_labels(Fl_Window *win, const char *str);
88
89//----------------------------------------------------------------------------
90
91/*
92 * CustTabs ---------------------------------------------------------------
93 */
94
98class CustTabButton : public Fl_Button {
99 UI *ui_;
100 uint_t focus_num_; // Used to choose which tab to focus when closing the
101 // active one (the highest numbered gets focus).
102public:
103 CustTabButton (int x,int y,int w,int h, const char* label = 0) :
104 Fl_Button (x,y,w,h,label) { ui_ = NULL; focus_num_ = 0; };
105 void ui(UI *pui) { ui_ = pui; }
106 UI *ui(void) { return ui_; }
107 void focus_num(uint_t fn) { focus_num_ = fn; }
108 uint_t focus_num(void) { return focus_num_; }
109};
110
111static int btn_cmp(const void *p1, const void *p2)
112{
113 return ((*(CustTabButton * const *)p1)->focus_num() -
114 (*(CustTabButton * const *)p2)->focus_num() );
115}
116
120class CustTabs : public Fl_Group {
121 uint_t focus_counter; // An increasing counter
122 int tab_w, tab_h, ctab_h, btn_w, ctl_w;
123 Fl_Wizard *Wizard;
124 Fl_Scroll *Scroll;
125 Fl_Pack *Pack;
126 Fl_Group *Control;
127 CustButton *CloseBtn;
128
129 void update_pack_offset(void);
130 void resize(int x, int y, int w, int h)
131 { Fl_Group::resize(x,y,w,h); update_pack_offset(); }
132 int get_btn_idx(UI *ui);
133 void increase_focus_counter() {
134 if (focus_counter < UINT_MAX) /* check for overflow */
135 ++focus_counter;
136 else {
137 /* wrap & normalize old numbers here */
138 CustTabButton **btns = dNew(CustTabButton*, num_tabs());
139 for (int i = 0; i < num_tabs(); ++i)
140 btns[i] = (CustTabButton*)Pack->child(i);
141 qsort(btns, num_tabs(), sizeof(CustTabButton *), btn_cmp);
142 focus_counter = 0;
143 for (int i = 0; i < num_tabs(); ++i)
144 btns[i]->focus_num(focus_counter++);
145 dFree(btns);
146 }
147 }
148
149public:
150 CustTabs (int ww, int wh, int th, const char *lbl=0) :
151 Fl_Group(0,0,ww,th,lbl) {
152 Pack = NULL;
153 focus_counter = 0;
154 tab_w = 50, tab_h = th, ctab_h = 1, btn_w = 20, ctl_w = 1*btn_w+2;
155 resize(0,0,ww,ctab_h);
156 /* tab buttons go inside a pack within a scroll */
157 Scroll = new Fl_Scroll(0,0,ww-ctl_w,ctab_h);
158 Scroll->type(0); /* no scrollbars */
159 Scroll->box(FL_NO_BOX);
160 Pack = new Fl_Pack(0,0,ww-ctl_w,tab_h);
161 Pack->type(Fl_Pack::HORIZONTAL);
162 Pack->box(FL_NO_BOX); //FL_THIN_DOWN_FRAME
163 Pack->end();
164 Scroll->end();
165 resizable(Scroll);
166
167 /* control buttons go inside a group */
168 Control = new Fl_Group(ww-ctl_w,0,ctl_w,ctab_h);
169 CloseBtn = new CustButton(ww-ctl_w+2,0,btn_w,ctab_h, "X");
170 CloseBtn->box(FL_THIN_UP_BOX);
171 CloseBtn->clear_visible_focus();
173 "Close current tab.\nor Right-click tab label to close." :
174 "Close current tab.\nor Middle-click tab label to close.");
175 CloseBtn->callback(close_tab_btn_cb, this);
176 CloseBtn->hide();
177 Control->end();
178
179 box(FL_FLAT_BOX);
180 end();
181
182 Wizard = new Fl_Wizard(0,ctab_h,ww,wh-ctab_h);
183 Wizard->box(FL_NO_BOX);
184 Wizard->end();
185 };
186 int handle(int e);
187 UI *add_new_tab(UI *old_ui, int focus);
188 void remove_tab(UI *ui);
189 Fl_Wizard *wizard(void) { return Wizard; }
190 int num_tabs() { return (Pack ? Pack->children() : 0); }
191 void switch_tab(CustTabButton *cbtn);
192 void prev_tab(void);
193 void next_tab(void);
194 void set_tab_label(UI *ui, const char *title);
195};
196
200static void tab_btn_cb (Fl_Widget *w, void *cb_data)
201{
202 CustTabButton *btn = (CustTabButton*) w;
203 CustTabs *tabs = (CustTabs*) cb_data;
204 int b = Fl::event_button();
205
206 if (b == FL_LEFT_MOUSE) {
207 tabs->switch_tab(btn);
208 } else if ((b == FL_RIGHT_MOUSE && prefs.right_click_closes_tab) ||
209 (b == FL_MIDDLE_MOUSE && !prefs.right_click_closes_tab)) {
210 // TODO: just an example, not necessarily final
212 }
213}
214
218static void close_tab_btn_cb (Fl_Widget *, void *cb_data)
219{
220 CustTabs *tabs = (CustTabs*) cb_data;
221 int b = Fl::event_button();
222
223 if (b == FL_LEFT_MOUSE) {
224 a_UIcmd_close_bw(a_UIcmd_get_bw_by_widget(tabs->wizard()->value()));
225 }
226}
227
228int CustTabs::handle(int e)
229{
230 int ret = 0;
231
232 _MSG("CustTabs::handle e=%s\n", fl_eventnames[e]);
233 if (e == FL_KEYBOARD) {
234 return 0; // Receive as shortcut
235 } else if (e == FL_SHORTCUT) {
236 UI *ui = (UI*)wizard()->value();
239 if (cmd == KEYS_NOP) {
240 // Do nothing
241 _MSG("CustTabs::handle KEYS_NOP\n");
242 } else if (cmd == KEYS_NEW_TAB) {
243 a_UIcmd_open_url_nt(bw, NULL, 1);
244 ret = 1;
245 } else if (cmd == KEYS_CLOSE_TAB) {
247 ret = 1;
248 } else if (cmd == KEYS_LEFT_TAB) {
249 prev_tab();
250 ret = 1;
251 } else if (cmd == KEYS_RIGHT_TAB) {
252 next_tab();
253 ret = 1;
254 } else if (cmd == KEYS_NEW_WINDOW) {
255 a_UIcmd_open_url_nw(bw, NULL);
256 ret = 1;
257 } else if (cmd == KEYS_CLOSE_ALL) {
259 ret = 1;
260 }
261 } else if (e == FL_MOUSEWHEEL && prefs.scroll_switches_tabs) {
262 /* Move to the next or previous tab using the mouse wheel */
263 int dx = Fl::event_dx();
264 int dy = Fl::event_dy();
265 int dir = dy ? dy : dx;
266
268 dir = -dir;
269
270 if (dir > 0)
271 next_tab();
272 else if (dir < 0)
273 prev_tab();
274
275 ret = 1;
276 }
277
278 return (ret) ? ret : Fl_Group::handle(e);
279}
280
284UI *CustTabs::add_new_tab(UI *old_ui, int focus)
285{
286 if (num_tabs() == 1) {
287 // Show tabbar
288 ctab_h = tab_h;
289 Wizard->resize(0,ctab_h,Wizard->w(),window()->h()-ctab_h);
290 resize(0,0,window()->w(),ctab_h); // tabbar
291 CloseBtn->show();
292 {int w = 0, h; Pack->child(0)->measure_label(w, h);
293 Pack->child(0)->size(w+14,ctab_h);}
294 Pack->child(0)->show(); // first tab button
295 window()->init_sizes();
296 }
297
298 /* The UI is constructed in a comfortable fitting size, and then resized
299 * so FLTK doesn't get confused later with even smaller dimensions! */
300 current(0);
301 UI *new_ui = new UI(0,0,UI_MIN_W,UI_MIN_H,"Dillo:",old_ui);
302 new_ui->resize(0,ctab_h,Wizard->w(),Wizard->h());
303 new_ui->tabs(this);
304 Wizard->add(new_ui);
305 new_ui->show();
306
307 CustTabButton *btn = new CustTabButton(num_tabs()*tab_w,0,tab_w,ctab_h);
308 btn->align(FL_ALIGN_INSIDE);
309 btn->labelsize(btn->labelsize()-2);
310 btn->copy_label(DEFAULT_TAB_LABEL);
311 btn->clear_visible_focus();
312 btn->box(FL_GTK_THIN_UP_BOX);
315 btn->ui(new_ui);
316 btn->callback(tab_btn_cb, this);
317 Pack->add(btn); // append
318
319 if (focus) {
320 switch_tab(btn);
321 } else { // no focus
322 // set focus counter
323 increase_focus_counter();
324 btn->focus_num(focus_counter);
325
326 if (num_tabs() == 2) {
327 // tabbar added: redraw current page
328 Wizard->redraw();
329 }
330 }
331 if (num_tabs() == 1)
332 btn->hide();
333 update_pack_offset();
334
335 return new_ui;
336}
337
341void CustTabs::remove_tab(UI *ui)
342{
343 CustTabButton *btn;
344
345 // get active tab idx
346 int act_idx = get_btn_idx((UI*)Wizard->value());
347 // get to-be-removed tab idx
348 int rm_idx = get_btn_idx(ui);
349 btn = (CustTabButton*)Pack->child(rm_idx);
350
351 if (act_idx == rm_idx) {
352 // Active tab is being closed, switch to the "previous" one
353 CustTabButton *fbtn = NULL;
354 for (int i = 0; i < num_tabs(); ++i) {
355 if (i != rm_idx) {
356 if (!fbtn)
357 fbtn = (CustTabButton*)Pack->child(i);
358 CustTabButton *btn = (CustTabButton*)Pack->child(i);
359 if (btn->focus_num() > fbtn->focus_num())
360 fbtn = btn;
361 }
362 }
363 switch_tab(fbtn);
364 }
365 Pack->remove(rm_idx);
366 update_pack_offset();
367 delete btn;
368
369 Wizard->remove(ui);
370 delete(ui);
371
372 if (num_tabs() == 1) {
373 // hide tabbar
374 ctab_h = 1;
375 CloseBtn->hide();
376 Pack->child(0)->size(0,0);
377 Pack->child(0)->hide(); // first tab button
378 resize(0,0,window()->w(),ctab_h); // tabbar
379 Wizard->resize(0,ctab_h,Wizard->w(),window()->h()-ctab_h);
380 window()->init_sizes();
381 window()->redraw();
382 }
383}
384
385int CustTabs::get_btn_idx(UI *ui)
386{
387 for (int i = 0; i < num_tabs(); ++i) {
388 CustTabButton *btn = (CustTabButton*)Pack->child(i);
389 if (btn->ui() == ui)
390 return i;
391 }
392 return -1;
393}
394
399void CustTabs::update_pack_offset()
400{
401 dReturn_if (num_tabs() == 0);
402
403 // get active tab button
404 int act_idx = get_btn_idx((UI*)Wizard->value());
405 CustTabButton *cbtn = (CustTabButton*)Pack->child(act_idx);
406
407 // calculate tab button's x() coordinates
408 int x_i = 0, x_f;
409 for (int j=0; j < act_idx; ++j)
410 x_i += Pack->child(j)->w();
411 x_f = x_i + cbtn->w();
412
413 int scr_x = Scroll->xposition(), scr_y = Scroll->yposition();
414 int px_i = x_i - scr_x;
415 int px_f = px_i + cbtn->w();
416 int pw = Scroll->window()->w() - ctl_w;
417 _MSG(" scr_x=%d btn_x=%d px_i=%d btn_w=%d px_f=%d pw=%d",
418 Scroll->xposition(),cbtn->x(),px_i,cbtn->w(),px_f,pw);
419 if (px_i < 0) {
420 Scroll->scroll_to(x_i, scr_y);
421 } else if (px_i > pw || (px_i > 0 && px_f > pw)) {
422 Scroll->scroll_to(MIN(x_i, x_f-pw), scr_y);
423 }
424 Scroll->redraw();
425 _MSG(" >>scr_x=%d btn0_x=%d\n", scr_x, Pack->child(0)->x());
426}
427
431void CustTabs::switch_tab(CustTabButton *cbtn)
432{
433 int idx;
434 CustTabButton *btn;
435 BrowserWindow *bw;
436 UI *old_ui = (UI*)Wizard->value();
437
438 if (cbtn && cbtn->ui() != old_ui) {
439 // Set old tab label to normal color
440 if ((idx = get_btn_idx(old_ui)) != -1) {
441 btn = (CustTabButton*)Pack->child(idx);
442 btn->color(PREFS_UI_TAB_BG_COLOR);
443 btn->labelcolor(PREFS_UI_TAB_FG_COLOR);
444 btn->redraw();
445 }
446 /* We make a point of calling show() before value() is changed because
447 * the wizard may hide the old one before showing the new one. In that
448 * case, the new UI gets focus with Fl::e_keysym set to whatever
449 * triggered the switch, and this is a problem when it's Tab/Left/Right/
450 * Up/Down because some widgets (notably Fl_Group and Fl_Input) exhibit
451 * unwelcome behaviour in that case. If the new widgets are already
452 * shown, fl_fix_focus will fix everything with Fl::e_keysym temporarily
453 * cleared.
454 */
455 cbtn->ui()->show();
456 Wizard->value(cbtn->ui());
457 cbtn->color(PREFS_UI_TAB_ACTIVE_BG_COLOR);
458 cbtn->labelcolor(PREFS_UI_TAB_ACTIVE_FG_COLOR);
459 cbtn->redraw();
460 update_pack_offset();
461
462 // Update window title
463 if ((bw = a_UIcmd_get_bw_by_widget(cbtn->ui()))) {
464 const char *title = (cbtn->ui())->label();
465 UIcmd_set_window_labels(cbtn->window(), title ? title : "");
466 }
467 // Update focus priority
468 increase_focus_counter();
469 cbtn->focus_num(focus_counter);
470 }
471}
472
473void CustTabs::prev_tab()
474{
475 int idx;
476
477 if ((idx = get_btn_idx((UI*)Wizard->value())) != -1)
478 switch_tab((CustTabButton*)Pack->child(idx>0 ? idx-1 : num_tabs()-1));
479}
480
481void CustTabs::next_tab()
482{
483 int idx;
484
485 if ((idx = get_btn_idx((UI*)Wizard->value())) != -1)
486 switch_tab((CustTabButton*)Pack->child((idx+1<num_tabs()) ? idx+1 : 0));
487}
488
492void CustTabs::set_tab_label(UI *ui, const char *label)
493{
494 char title[128];
495 int idx = get_btn_idx(ui);
496
497 if (idx != -1) {
498 // Make a label for this tab
499 size_t tab_chars = 15, label_len = strlen(label);
500
501 if (label_len > tab_chars)
502 tab_chars = a_Utf8_end_of_char(label, tab_chars - 1) + 1;
503 snprintf(title, tab_chars + 1, "%s", label);
504 if (label_len > tab_chars)
505 snprintf(title + tab_chars, 4, "...");
506
507 // Avoid unnecessary redraws
508 if (strcmp(Pack->child(idx)->label(), title)) {
509 int w = 0, h;
510 Pack->child(idx)->copy_label(title);
511 Pack->child(idx)->measure_label(w, h);
512 Pack->child(idx)->size(w+14,ctab_h);
513 update_pack_offset();
514 }
515 }
516}
517
518
519//----------------------------------------------------------------------------
520
521static void win_cb (Fl_Widget *w, void *cb_data) {
522 CustTabs *tabs = (CustTabs*) cb_data;
523 int choice = 1, ntabs = tabs->num_tabs();
524
525 if (Fl::event_key() == FL_Escape) {
526 // Don't let FLTK close a browser window due to unhandled Escape
527 // (most likely with modifiers).
528 return;
529 }
530
531 if (prefs.show_quit_dialog && ntabs > 1)
532 choice = a_Dialog_choice("Dillo: Close window?",
533 "Window contains more than one tab.",
534 "Close", "Cancel", NULL);
535 if (choice == 1)
536 while (ntabs-- > 0)
537 a_UIcmd_close_bw(a_UIcmd_get_bw_by_widget(tabs->wizard()->value()));
538}
539
540/*
541 * Given a UI or UI child widget, return its bw.
542 */
544{
545 BrowserWindow *bw;
546 for (int i = 0; i < a_Bw_num(); ++i) {
547 bw = a_Bw_get(i);
548 if (((UI*)bw->ui)->contains((Fl_Widget*)v_wid)) {
549 return bw;
550 }
551 }
552 return NULL;
553}
554
555/*
556 * Create a new UI and its associated BrowserWindow data structure.
557 * Use style from v_ui. If non-NULL it must be of type UI*.
558 */
560 uint32_t xid, const void *vbw)
561{
562 BrowserWindow *old_bw = (BrowserWindow*)vbw;
563 BrowserWindow *new_bw = NULL;
564 UI *old_ui = old_bw ? BW2UI(old_bw) : NULL;
565 Fl_Window *win;
566
567 if (ww <= 0 || wh <= 0) {
568 // Set default geometry from dillorc.
569 ww = prefs.width;
570 wh = prefs.height;
571 }
572
573 if (xid)
574 win = new Xembed(xid, ww, wh);
575 else if (prefs.buffered_drawing != 2)
576 win = new Fl_Window(ww, wh);
577 else
578 win = new Fl_Double_Window(ww, wh);
579
580 win->box(FL_NO_BOX);
581 CustTabs *DilloTabs = new CustTabs(ww, wh, prefs.ui_tab_height);
582
583 struct Tabgroup *tg = new Tabgroup;
584 tg->tabs = DilloTabs;
585 tg->next = tabgroups;
586 tabgroups = tg;
587 _MSG("new: tabgroups=%p\n", (void *) tg);
588
589 win->end();
590 win->resizable(DilloTabs->wizard());
591
592 int focus = 1;
593 new_bw = UIcmd_tab_new(DilloTabs, old_ui, focus);
594 win->show();
595
596 if (old_bw == NULL) {
597 new_bw->zoom = prefs.zoom_factor;
598
599 if (prefs.xpos >= 0 && prefs.ypos >= 0) {
600 // position the first window according to preferences
601 DilloTabs->window()->position(prefs.xpos, prefs.ypos);
602 }
603 }
604
605 win->callback(win_cb, DilloTabs);
606
607 return new_bw;
608}
609
610/*
611 * Set the window name and icon name.
612 */
613static void UIcmd_set_window_labels(Fl_Window *win, const char *str)
614{
615 const char *copy;
616
617 win->Fl_Widget::copy_label(str);
618 copy = win->label();
619 win->label(copy, copy);
620}
621
622/*
623 * Create a new Tab button, UI and its associated BrowserWindow data
624 * structure.
625 */
626static BrowserWindow *UIcmd_tab_new(CustTabs *tabs, UI *old_ui, int focus)
627{
628 _MSG(" UIcmd_tab_new\n");
629
630 // Create and set the UI
631 UI *new_ui = tabs->add_new_tab(old_ui, focus);
632
633 // Now create the Dw render layout and viewport
635 Layout *layout = new Layout (platform);
637 layout->setBgColor (bgColor);
641
642 // set_render_layout() sets the proper viewport size
643 FltkViewport *viewport = new FltkViewport (0, 0, 0, 1);
644 viewport->box(FL_NO_BOX);
653
654 // Now, create a new browser window structure
655 BrowserWindow *new_bw = a_Bw_new();
656
657 // Reference the UI from the bw
658 new_bw->ui = (void *)new_ui;
659 // Copy the layout pointer into the bw data
660 new_bw->render_layout = (void*)layout;
661
662 // Clear the window title
663 if (focus)
664 UIcmd_set_window_labels(new_ui->window(), new_ui->label());
665
666 // WORKAROUND: see findbar_toggle()
667 new_ui->findbar_toggle(0);
668
669 return new_bw;
670}
671
672/*
673 * Close one browser window
674 */
675void a_UIcmd_close_bw(void *vbw)
676{
677 BrowserWindow *bw = (BrowserWindow *)vbw;
678 UI *ui = BW2UI(bw);
679 CustTabs *tabs = ui->tabs();
681
682 _MSG("a_UIcmd_close_bw\n");
684 delete(layout);
685 if (tabs) {
686 tabs->remove_tab(ui);
687 if (tabs->num_tabs() == 0) {
688 /* No more tabs, remove tabgroup */
689 struct Tabgroup *tmp = tabgroups;
690 struct Tabgroup *prev = NULL;
691 for (tmp = tabgroups; tmp; tmp = tmp->next) {
692 if (tmp->tabs == tabs) {
693 if (prev)
694 prev->next = tmp->next;
695 else
696 tabgroups = tmp->next;
697 break;
698 }
699 prev = tmp;
700 }
701 if (tmp) {
702 _MSG("gone: tmp=%p tabgroups=%p\n", (void *) tmp, (void *) tabgroups);
703 delete tmp;
704 }
705 delete tabs->window();
706 }
707 }
708 a_Bw_free(bw);
709}
710
711/*
712 * Close all the browser windows
713 */
715{
716 BrowserWindow *bw;
717 int choice = 1;
718
719 if (prefs.show_quit_dialog && a_Bw_num() > 1)
720 choice = a_Dialog_choice("Dillo: Quit?",
721 "More than one open tab or window.",
722 "Quit", "Cancel", NULL);
723 if (choice == 1)
724 while ((bw = a_Bw_get(0)))
725 a_UIcmd_close_bw((void*)bw);
726}
727
728/*
729 * Return a search string of the suffix if str starts with a
730 * prefix of a search engine name and a blank
731 */
732static char *UIcmd_find_search_str(const char *str)
733{
734 int p;
735 char *url = NULL;
736 int len = strcspn(str, " ");
737
738 if (len > 0 && str[len] != '\0') {
739 /* we found a ' ' in str, check whether the first part of str
740 * is a prefix of a search_url label
741 */
742 for (p = 0; p < dList_length(prefs.search_urls); p++) {
743 const char *search =
744 (const char *)dList_nth_data(prefs.search_urls, p);
745 if (search && dStrnAsciiCasecmp(str, search, len) == 0) {
747 url = UIcmd_make_search_str(str + len + 1);
748 break;
749 }
750 }
751 }
752 return url;
753}
754
755/*
756 * Open a new URL in the given browser window.
757 *
758 * our custom "file:" URIs are normalized here too.
759 */
760void a_UIcmd_open_urlstr(void *vbw, const char *urlstr)
761{
762 char *new_urlstr;
763 char *search_urlstr = NULL;
764 DilloUrl *url;
765 int ch;
766 BrowserWindow *bw = (BrowserWindow*)vbw;
767
768 if ((search_urlstr = UIcmd_find_search_str(urlstr))) {
769 urlstr = search_urlstr;
770 }
771 if (urlstr && *urlstr) {
772 /* Filter URL string */
773 new_urlstr = a_Url_string_strip_delimiters(urlstr);
774
775 if (!dStrnAsciiCasecmp(new_urlstr, "file:", 5)) {
776 /* file URI */
777 ch = new_urlstr[5];
778 if (!ch || ch == '.') {
779 url = a_Url_new(Paths::getOldWorkingDir(), "file:");
780 } else {
781 url = a_Url_new(new_urlstr, "file:");
782 }
783
784 } else {
785 /* common case */
786 url = a_Url_new(new_urlstr, NULL);
787 }
788 dFree(new_urlstr);
789
790 if (url) {
791 a_UIcmd_open_url(bw, url);
792 a_Url_free(url);
793 }
794 }
795 dFree(search_urlstr);
796}
797
798/*
799 * Open a new URL in the given browser window
800 */
802{
803 if (url) {
804 a_Nav_push(bw, url, NULL);
805 BW2UI(bw)->focus_main();
806 } else {
807 // Used to start a bw with a blank screen
808 BW2UI(bw)->focus_location();
810 }
811}
812
813static void UIcmd_open_url_nbw(BrowserWindow *new_bw, const DilloUrl *url)
814{
815 if (!url && prefs.new_tab_page) {
816 if (strcmp(URL_STR(prefs.new_tab_page), "about:blank") != 0)
817 url = prefs.new_tab_page;
818 }
819
820 /* When opening a new BrowserWindow (tab or real window) we focus
821 * Location if we don't yet have an URL, main otherwise.
822 */
823 if (url) {
824 a_Nav_push(new_bw, url, NULL);
826 BW2UI(new_bw)->focus_main();
827 } else {
828 BW2UI(new_bw)->focus_location();
830 }
831}
832
833/*
834 * Open a new URL in a new browser window
835 */
837{
838 int w, h;
839 BrowserWindow *new_bw;
840
841 a_UIcmd_get_wh(bw, &w, &h);
842 new_bw = a_UIcmd_browser_window_new(w, h, 0, bw);
843
844 /* Preserve same zoom factor in new window */
845 new_bw->zoom = bw->zoom;
846 UIcmd_open_url_nbw(new_bw, url);
847}
848
849/*
850 * Open a new URL in a new tab in the same browser window
851 */
852void a_UIcmd_open_url_nt(void *vbw, const DilloUrl *url, int focus)
853{
854 BrowserWindow *bw = (BrowserWindow *)vbw;
855 BrowserWindow *new_bw = UIcmd_tab_new(BW2UI(bw)->tabs(),
856 bw ? BW2UI(bw) : NULL, focus);
857 /* Preserve same zoom factor in new tab */
858 new_bw->zoom = bw->zoom;
859 UIcmd_open_url_nbw(new_bw, url);
860}
861
862/*
863 * Send the browser back to previous page
864 */
865void a_UIcmd_back(void *vbw)
866{
868}
869
870/*
871 * Popup the navigation menu of the Back button
872 */
873void a_UIcmd_back_popup(void *vbw, int x, int y)
874{
875 a_Menu_history_popup((BrowserWindow*)vbw, x, y, -1);
876}
877
878/*
879 * Send the browser to next page in the history list
880 */
881void a_UIcmd_forw(void *vbw)
882{
884}
885
886/*
887 * Popup the navigation menu of the Forward button
888 */
889void a_UIcmd_forw_popup(void *vbw, int x, int y)
890{
891 a_Menu_history_popup((BrowserWindow*)vbw, x, y, 1);
892}
893
894/*
895 * Send the browser to home URL
896 */
897void a_UIcmd_home(void *vbw)
898{
900}
901
902/*
903 * Reload current URL
904 */
905void a_UIcmd_reload(void *vbw)
906{
908}
909
910/*
911 * Reload all active tabs
912 */
914{
915 struct Tabgroup *tg = tabgroups;
916 for (tg = tabgroups; tg; tg = tg->next) {
917 BrowserWindow *bw = a_UIcmd_get_bw_by_widget(tg->tabs->wizard()->value());
918 if (bw)
919 a_UIcmd_reload(bw);
920 }
921}
922
923/*
924 * Repush current URL
925 */
926void a_UIcmd_repush(void *vbw)
927{
929}
930
931/*
932 * Zero-delay URL redirection.
933 */
934void a_UIcmd_redirection0(void *vbw, const DilloUrl *url)
935{
937}
938
939/*
940 * Zoom in
941 */
942void a_UIcmd_zoom_in(void *vbw)
943{
944 BrowserWindow *bw = (BrowserWindow*) vbw;
945 bw->zoom += 0.10;
946
947 if (bw->zoom > 10.0)
948 bw->zoom = 10.0;
949
950 a_UIcmd_set_msg(bw, "Zoom set to %.0f%%", bw->zoom * 100.0);
951
953}
954
955/*
956 * Zoom out
957 */
958void a_UIcmd_zoom_out(void *vbw)
959{
960 BrowserWindow *bw = (BrowserWindow*) vbw;
961 bw->zoom -= 0.10;
962
963 if (bw->zoom < 0.10)
964 bw->zoom = 0.10;
965
966 a_UIcmd_set_msg(bw, "Zoom set to %.0f%%", bw->zoom * 100.0);
967
969}
970
971/*
972 * Zoom reset
973 */
974void a_UIcmd_zoom_reset(void *vbw)
975{
976 BrowserWindow *bw = (BrowserWindow*) vbw;
977 bw->zoom = 1.0;
978
979 a_UIcmd_set_msg(bw, "Zoom set to %.0f%%", bw->zoom * 100.0);
980
982}
983
984/*
985 * Return a suitable filename for a given URL path.
986 */
987static char *UIcmd_make_save_filename(const DilloUrl *url)
988{
989 size_t MaxLen = 64;
990 const char *dir = save_dir, *path, *path2, *query;
991 char *name, *free1, *free2, *n1, *n2;
992
993 free1 = free2 = NULL;
994
995 /* get the last component of the path */
996 path = URL_PATH(url);
997 path2 = strrchr(path, '/');
998 path = path2 ? path2 + 1 : path;
999
1000 /* truncate the path if necessary */
1001 if (strlen(path) > MaxLen) {
1002 path = free1 = dStrndup(path, MaxLen);
1003 }
1004
1005 /* is there a query? */
1006 query = URL_QUERY(url);
1007 if (*query) {
1008 /* truncate the query if necessary */
1009 if (strlen(query) > MaxLen) {
1010 query = free2 = dStrndup(query, MaxLen);
1011 }
1012 name = dStrconcat(dir, path, "?", query, NULL);
1013 } else {
1014 name = dStrconcat(dir, path, NULL);
1015 }
1016
1017 dFree(free1);
1018 dFree(free2);
1019
1020 /* Replace %20 and ' ' with '_' */
1021 for (n1 = n2 = name; *n1; n1++, n2++) {
1022 *n2 =
1023 (n1[0] == ' ')
1024 ? '_' :
1025 (n1[0] == '%' && n1[1] == '2' && n1[2] == '0')
1026 ? (n1 += 2, '_') :
1027 n1[0];
1028 }
1029 *n2 = 0;
1030
1031 return name;
1032}
1033
1034/*
1035 * Set the default directory for saving files.
1036 */
1038{
1039 const char *dir = prefs.save_dir;
1040
1041 if (dir && *dir) {
1042 // assert a trailing '/'
1043 save_dir =
1044 (dir[strlen(dir)-1] == '/')
1045 ? dStrdup(dir)
1046 : dStrconcat(dir, "/", NULL);
1047 }
1048}
1049
1050/*
1051 * Check a file to save to.
1052 */
1053static int UIcmd_save_file_check(const char *name)
1054{
1055 struct stat ss;
1056 if (stat(name, &ss) == 0) {
1057 Dstr *ds;
1058 int ch;
1059 ds = dStr_sized_new(128);
1060 dStr_sprintf(ds,
1061 "The file: %s (%d Bytes) already exists. What do we do?",
1062 name, (int)ss.st_size);
1063 ch = a_Dialog_choice("Dillo Save: File exists!", ds->str,
1064 "Abort", "Continue", "Rename", NULL);
1065 dStr_free(ds, 1);
1066 return ch;
1067 } else {
1068 return 2; /* assume the file does not exist, so Continue */
1069 }
1070}
1071
1072/*
1073 * Save a URL
1074 */
1075static void UIcmd_save(BrowserWindow *bw, const DilloUrl *url,
1076 const char *title)
1077{
1078 char *SuggestedName = UIcmd_make_save_filename(url);
1079
1080 while (1) {
1081 const char *name = a_Dialog_save_file(title, NULL, SuggestedName);
1082 dFree(SuggestedName);
1083
1084 if (name) {
1085 switch (UIcmd_save_file_check(name)) {
1086 case 0:
1087 case 1:
1088 /* Abort */
1089 return;
1090 case 2:
1091 /* Continue */
1092 MSG("UIcmd_save: %s\n", name);
1093 a_Nav_save_url(bw, url, name);
1094 return;
1095 default:
1096 /* Rename */
1097 break; /* prompt again */
1098 }
1099 } else {
1100 return; /* no name, so Abort */
1101 }
1102
1103 SuggestedName = dStrdup(name);
1104 }
1105}
1106
1107/*
1108 * Save current URL
1109 */
1110void a_UIcmd_save(void *vbw)
1111{
1112 BrowserWindow *bw = (BrowserWindow *)vbw;
1113 const DilloUrl *url = a_History_get_url(NAV_TOP_UIDX(bw));
1114
1115 if (url) {
1116 UIcmd_save(bw, url, "Save Page as File");
1117 }
1118}
1119
1120/*
1121 * Select a file
1122 */
1124{
1125 return a_Dialog_select_file("Dillo: Select a File", NULL, NULL);
1126}
1127
1128/*
1129 * Stop network activity on this bw.
1130 * The stop button was pressed: stop page (and images) downloads.
1131 */
1132void a_UIcmd_stop(void *vbw)
1133{
1134 BrowserWindow *bw = (BrowserWindow *)vbw;
1135
1136 MSG("a_UIcmd_stop()\n");
1140}
1141
1142/*
1143 * Popup the tools menu
1144 */
1145void a_UIcmd_tools(void *vbw, int x, int y)
1146{
1147 a_Menu_tools_popup((BrowserWindow*)vbw, x, y);
1148}
1149
1150/*
1151 * Open URL with dialog chooser
1152 */
1153void a_UIcmd_open_file(void *vbw)
1154{
1155 char *name;
1156 DilloUrl *url;
1157
1158 name = a_Dialog_open_file("Dillo: Open File", NULL, "");
1159
1160 if (name) {
1161 url = a_Url_new(name, "file:");
1162 a_UIcmd_open_url((BrowserWindow*)vbw, url);
1163 a_Url_free(url);
1164 dFree(name);
1165 }
1166}
1167
1168/*
1169 * Returns a newly allocated string holding a search url generated from
1170 * a string of keywords (separated by blanks) and the current search_url.
1171 * The search string is urlencoded.
1172 */
1173static char *UIcmd_make_search_str(const char *str)
1174{
1175 char *search_url, *l, *u, *c;
1176 char *keys = a_Url_encode_hex_str(str),
1178 Dstr *ds = dStr_sized_new(128);
1179
1180 /* parse search_url into label and url */
1181 if (a_Misc_parse_search_url(src, &l, &u) == 0) {
1182 for (c = u; *c; c++) {
1183 if (*c == '%')
1184 switch(*++c) {
1185 case 's':
1186 dStr_append(ds, keys); break;
1187 case '%':
1188 dStr_append_c(ds, '%'); break;
1189 case 0:
1190 MSG_WARN("search_url ends with '%%'\n"); c--; break;
1191 default:
1192 MSG_WARN("illegal specifier '%%%c' in search_url\n", *c);
1193 }
1194 else
1195 dStr_append_c(ds, *c);
1196 }
1197 }
1198 dFree(keys);
1199
1200 search_url = ds->str;
1201 dStr_free(ds, 0);
1202 return search_url;
1203}
1204
1205/*
1206 * Get a query from a dialog and open it
1207 */
1209{
1210 const char *query;
1211
1212 if ((query = a_Dialog_input("Dillo: Search", "Search the Web:"))) {
1213 char *url_str = UIcmd_make_search_str(query);
1214 a_UIcmd_open_urlstr(vbw, url_str);
1215 dFree(url_str);
1216 }
1217}
1218
1219/*
1220 * Get password for user
1221 */
1222const char *a_UIcmd_get_passwd(const char *user)
1223{
1224 const char *passwd;
1225 const char *title = "Dillo: Password";
1226 char *msg = dStrconcat("Password for user \"", user, "\"", NULL);
1227 passwd = a_Dialog_passwd(title, msg);
1228 dFree(msg);
1229 return passwd;
1230}
1231
1232/*
1233 * Save link URL
1234 */
1236{
1237 UIcmd_save(bw, url, "Dillo: Save Link as File");
1238}
1239
1240/*
1241 * Request the bookmarks page
1242 */
1243void a_UIcmd_book(void *vbw)
1244{
1245 DilloUrl *url = a_Url_new("dpi:/bm/", NULL);
1246 a_UIcmd_open_url((BrowserWindow*)vbw, url);
1247 a_Url_free(url);
1248}
1249
1250/*
1251 * Add a bookmark for a certain URL
1252 */
1254{
1255 a_Bookmarks_add(bw, url);
1256}
1257
1258
1259/*
1260 * Popup the page menu
1261 */
1262void a_UIcmd_page_popup(void *vbw, bool_t has_bugs, void *v_cssUrls)
1263{
1264 BrowserWindow *bw = (BrowserWindow*)vbw;
1265 const DilloUrl *url = a_History_get_url(NAV_TOP_UIDX(bw));
1266 a_Menu_page_popup(bw, url, has_bugs, v_cssUrls);
1267}
1268
1269/*
1270 * Popup the link menu
1271 */
1272void a_UIcmd_link_popup(void *vbw, const DilloUrl *url, const DilloUrl *page_url)
1273{
1274 a_Menu_link_popup((BrowserWindow*)vbw, url, page_url);
1275}
1276
1277/*
1278 * Pop up the image menu
1279 */
1280void a_UIcmd_image_popup(void *vbw, const DilloUrl *url, bool_t loaded_img,
1281 DilloUrl *page_url, DilloUrl *link_url)
1282{
1283 a_Menu_image_popup((BrowserWindow*)vbw, url, loaded_img, page_url,link_url);
1284}
1285
1286/*
1287 * Pop up the form menu
1288 */
1289void a_UIcmd_form_popup(void *vbw, const DilloUrl *url, void *vform,
1290 bool_t showing_hiddens)
1291{
1292 a_Menu_form_popup((BrowserWindow*)vbw, url, vform, showing_hiddens);
1293}
1294
1295/*
1296 * Pop up the file menu
1297 */
1298void a_UIcmd_file_popup(void *vbw, void *v_wid)
1299{
1300 a_Menu_file_popup((BrowserWindow*)vbw, v_wid);
1301}
1302
1303/*
1304 * Copy url string to paste buffer
1305 */
1306void a_UIcmd_copy_urlstr(BrowserWindow *bw, const char *urlstr)
1307{
1309 layout->copySelection(urlstr);
1310}
1311
1312/*
1313 * Ask the vsource dpi to show this URL's source
1314 */
1316{
1317 char *buf, *major;
1318 int buf_size;
1319 Dstr *dstr_url;
1320 DilloUrl *vs_url;
1321 static int post_id = 0;
1322 char tag[16];
1323 const char *content_type = a_Nav_get_content_type(url);
1324
1325 a_Misc_parse_content_type(content_type, &major, NULL, NULL);
1326
1327 if (major && dStrAsciiCasecmp(major, "image") &&
1328 a_Nav_get_buf(url, &buf, &buf_size)) {
1330 dstr_url = dStr_new("dpi:/vsource/:");
1331 dStr_append(dstr_url, URL_STR(url));
1332 if (URL_FLAGS(url) & URL_Post) {
1333 /* append a custom string to differentiate POST URLs */
1334 post_id = (post_id < 9999) ? post_id + 1 : 0;
1335 snprintf(tag, 16, "_%.4d", post_id);
1336 dStr_append(dstr_url, tag);
1337 }
1338 vs_url = a_Url_new(dstr_url->str, NULL);
1339 a_UIcmd_open_url_nt(bw, vs_url, 1);
1340 a_Url_free(vs_url);
1341 dStr_free(dstr_url, 1);
1342 a_Nav_unref_buf(url);
1343 }
1344 dFree(major);
1345}
1346
1347/*
1348 * Show the browser window's HTML errors in a text window
1349 */
1351{
1352 BrowserWindow *bw = (BrowserWindow*)vbw;
1353
1354 if (bw->num_page_bugs > 0) {
1355 a_Dialog_text_window("Dillo: Detected HTML errors", bw->page_bugs->str);
1356 } else {
1357 a_Dialog_msg("Dillo: Good HTML!", "No HTML errors found while parsing!");
1358 }
1359}
1360
1361/*
1362 * Popup the bug meter menu
1363 */
1365{
1366 BrowserWindow *bw = (BrowserWindow*)vbw;
1367
1369}
1370
1371/*
1372 * Make a list of URL indexes for the history popup
1373 * based on direction (-1 = back, 1 = forward)
1374 */
1375int *a_UIcmd_get_history(BrowserWindow *bw, int direction)
1376{
1377 int i, j, n;
1378 int *hlist;
1379
1380 // Count the number of URLs
1381 i = a_Nav_stack_ptr(bw) + direction;
1382 for (n = 0 ; i >= 0 && i < a_Nav_stack_size(bw); i+=direction)
1383 ++n;
1384 hlist = dNew(int, n + 1);
1385
1386 // Fill the list
1387 i = a_Nav_stack_ptr(bw) + direction;
1388 for (j = 0 ; i >= 0 && i < a_Nav_stack_size(bw); i+=direction, j += 1) {
1389 hlist[j] = NAV_UIDX(bw,i);
1390 }
1391 hlist[j] = -1;
1392
1393 return hlist;
1394}
1395
1396/*
1397 * Jump to a certain URL in the navigation stack.
1398 */
1399void a_UIcmd_nav_jump(BrowserWindow *bw, int offset, int new_bw)
1400{
1401 a_Nav_jump(bw, offset, new_bw);
1402}
1403
1404// UI binding functions -------------------------------------------------------
1405
1406/*
1407 * Return browser window width and height
1408 */
1409void a_UIcmd_get_wh(BrowserWindow *bw, int *w, int *h)
1410{
1411 *w = BW2UI(bw)->w();
1412 *h = BW2UI(bw)->h();
1413 _MSG("a_UIcmd_wh: w=%d, h=%d\n", *w, *h);
1414}
1415
1416/*
1417 * Get the scroll position (x, y offset pair)
1418 */
1419void a_UIcmd_get_scroll_xy(BrowserWindow *bw, int *x, int *y)
1420{
1422
1423 if (layout) {
1424 *x = layout->getScrollPosX();
1425 *y = layout->getScrollPosY();
1426 }
1427}
1428
1429/*
1430 * Set the scroll position ({x, y} offset pair)
1431 */
1433{
1435
1436 if (layout) {
1437 layout->scrollTo(HPOS_LEFT, VPOS_TOP, x, y, 0, 0);
1438 }
1439}
1440
1441/*
1442 * Set the scroll position by fragment (from URL)
1443 */
1445{
1447
1448 if (layout && f) {
1449 layout->setAnchor(f);
1450 }
1451}
1452
1453/*
1454 * Pass scrolling command to dw.
1455 */
1457{
1459
1460 if (layout) {
1461 typedef struct {
1462 KeysCommand_t keys_cmd;
1463 ScrollCommand dw_cmd;
1464 } mapping_t;
1465
1466 const mapping_t map[] = {
1475 {KEYS_TOP, TOP_CMD},
1477 };
1478 KeysCommand_t keycmd = (KeysCommand_t)icmd;
1479
1480 for (uint_t i = 0; i < sizeof(map) / sizeof(map[0]); i++) {
1481 if (keycmd == map[i].keys_cmd) {
1482 layout->scroll(map[i].dw_cmd);
1483 break;
1484 }
1485 }
1486 }
1487}
1488
1489/*
1490 * Get location's text
1491 */
1493{
1494 return dStrdup(BW2UI(bw)->get_location());
1495}
1496
1497/*
1498 * Set location's text
1499 */
1500void a_UIcmd_set_location_text(void *vbw, const char *text)
1501{
1502 BrowserWindow *bw = (BrowserWindow*)vbw;
1503 BW2UI(bw)->set_location(text);
1504}
1505
1506/*
1507 * Set the page progress bar
1508 * cmd: 0 Deactivate, 1 Update, 2 Clear
1509 */
1510void a_UIcmd_set_page_prog(BrowserWindow *bw, size_t nbytes, int cmd)
1511{
1512 BW2UI(bw)->set_page_prog(nbytes, cmd);
1513}
1514
1515/*
1516 * Set the images progress bar
1517 * cmd: 0 Deactivate, 1 Update, 2 Clear
1518 */
1519void a_UIcmd_set_img_prog(BrowserWindow *bw, int n_img, int t_img, int cmd)
1520{
1521 BW2UI(bw)->set_img_prog(n_img, t_img, cmd);
1522#if 0
1523 if (!cmd)
1524 a_UIcmd_close_bw(bw);
1525#endif
1526}
1527
1528/*
1529 * Set the bug meter progress label
1530 */
1532{
1533 BW2UI(bw)->set_bug_prog(n_bug);
1534}
1535
1536/*
1537 * Set the page title in the tab label and window titlebar.
1538 * (Update window titlebar for the current tab only)
1539 */
1540void a_UIcmd_set_page_title(BrowserWindow *bw, const char *label)
1541{
1542 const int size = 128;
1543 char title[size];
1544
1545 if (snprintf(title, size, "Dillo: %s", label ? label : "") >= size) {
1546 uint_t i = MIN(size - 4, 1 + a_Utf8_end_of_char(title, size - 8));
1547 snprintf(title + i, 4, "...");
1548 }
1549 BW2UI(bw)->copy_label(title);
1550 BW2UI(bw)->tabs()->set_tab_label(BW2UI(bw), label ? label : "");
1551
1552 if (a_UIcmd_get_bw_by_widget(BW2UI(bw)->tabs()->wizard()->value()) == bw) {
1553 // This is the focused bw, set window title
1554 UIcmd_set_window_labels(BW2UI(bw)->window(), title);
1555 }
1556}
1557
1558/*
1559 * Set a printf-like status string on the bottom of the dillo window.
1560 * Beware: The safe way to set an arbitrary string is
1561 * a_UIcmd_set_msg(bw, "%s", str)
1562 */
1563void a_UIcmd_set_msg(BrowserWindow *bw, const char *format, ...)
1564{
1565 va_list argp;
1566 Dstr *ds = dStr_sized_new(128);
1567 va_start(argp, format);
1568 dStr_vsprintf(ds, format, argp);
1569 va_end(argp);
1570 BW2UI(bw)->set_status(ds->str);
1571 dStr_free(ds, 1);
1572}
1573
1574/*
1575 * Set the sensitivity of back/forw/stop buttons.
1576 */
1578{
1579 int sens;
1580
1581 // Stop
1582 sens = (dList_length(bw->ImageClients) || dList_length(bw->RootClients));
1583 BW2UI(bw)->button_set_sens(UI_STOP, sens);
1584 // Back
1585 sens = (a_Nav_stack_ptr(bw) > 0);
1586 BW2UI(bw)->button_set_sens(UI_BACK, sens);
1587 // Forward
1588 sens = (a_Nav_stack_ptr(bw) < a_Nav_stack_size(bw) - 1 &&
1589 !a_Bw_expecting(bw));
1590 BW2UI(bw)->button_set_sens(UI_FORW, sens);
1591}
1592
1593/*
1594 * Toggle control panel
1595 */
1597{
1598 BW2UI(bw)->panels_toggle();
1599}
1600
1601/*
1602 * Search for next/previous occurrence of key.
1603 */
1604void a_UIcmd_findtext_search(BrowserWindow *bw, const char *key,
1605 int case_sens, int backward)
1606{
1607 Layout *l = (Layout *)bw->render_layout;
1608
1609 switch (l->search(key, case_sens, backward)) {
1611 a_UIcmd_set_msg(bw, backward?"Top reached; restarting from the bottom."
1612 :"Bottom reached; restarting from the top.");
1613 break;
1615 a_UIcmd_set_msg(bw, "\"%s\" not found.", key);
1616 break;
1618 default:
1619 a_UIcmd_set_msg(bw, "");
1620 }
1621}
1622
1623/*
1624 * Reset text search state.
1625 */
1627{
1628 Layout *l = (Layout *)bw->render_layout;
1629 l->resetSearch();
1630
1631 a_UIcmd_set_msg(bw, "");
1632}
1633
1634/*
1635 * Tell the UI to hide/show the findbar
1636 */
1638{
1639 BW2UI(bw)->findbar_toggle(on);
1640}
1641
1642/*
1643 * Focus the rendered area.
1644 */
1646{
1647 BW2UI(bw)->focus_main();
1648}
1649
1650/*
1651 * Focus the location bar.
1652 */
1654{
1655 BrowserWindow *bw = (BrowserWindow*)vbw;
1656 BW2UI(bw)->focus_location();
1657}
1658
void a_Bookmarks_add(BrowserWindow *bw, const DilloUrl *url)
Add the new bookmark through the bookmarks server.
Definition bookmark.c:71
#define _MSG(...)
Definition bookmarks.c:45
#define MSG(...)
Definition bookmarks.c:46
bool_t a_Bw_expecting(BrowserWindow *bw)
Definition bw.c:334
void a_Bw_free(BrowserWindow *bw)
Free resources associated to a bw.
Definition bw.c:89
BrowserWindow * a_Bw_get(int i)
Return a bw by index.
Definition bw.c:313
void a_Bw_stop_clients(BrowserWindow *bw, int flags)
Stop the active clients of this bw's top page.
Definition bw.c:182
int a_Bw_num(void)
Definition bw.c:305
BrowserWindow * a_Bw_new(void)
Create a new browser window and return it.
Definition bw.c:47
#define BW_Img
Definition bw.h:22
#define BW_Force
Definition bw.h:23
#define BW_Root
Definition bw.h:21
A button that highlights on mouse over.
Definition tipwin.hh:49
static KeysCommand_t getKeyCmd(void)
Look if the just pressed key is bound to a command.
Definition keys.cc:200
static char * getOldWorkingDir(void)
Return the initial current working directory in a string.
Definition paths.cc:64
void set_tooltip(const char *s)
Definition tipwin.cc:162
Definition ui.hh:123
void findbar_toggle(bool add)
Adjust space for the findbar (if necessary) and show or remove it.
Definition ui.cc:1059
void set_render_layout(Fl_Group *nw)
Set 'nw' as the main render area widget.
Definition ui.cc:1016
CustTabs * tabs()
Definition ui.hh:179
@ SUCCESS
The next occurrence of the pattern has been found.
Definition findtext.hh:18
@ NOT_FOUND
The patten does not at all occur in the text.
Definition findtext.hh:27
@ RESTART
There is no further occurrence of the pattern, instead, the first occurrence has been selected.
Definition findtext.hh:24
The central class for managing and drawing a widget tree.
Definition layout.hh:17
void attachView(View *view)
Attach a view to the layout.
Definition layout.cc:459
int getScrollPosY()
Definition layout.hh:289
FindtextState::Result search(const char *str, bool caseSens, int backwards)
See dw::core::FindtextState::search.
Definition layout.hh:430
void resetSearch()
See dw::core::FindtextState::resetSearch.
Definition layout.hh:435
void setBgColor(style::Color *color)
Definition layout.cc:826
void setBgImage(style::StyleImage *bgImage, style::BackgroundRepeat bgRepeat, style::BackgroundAttachment bgAttachment, style::Length bgPositionX, style::Length bgPositionY)
Definition layout.cc:839
void copySelection(const char *text)
Definition layout.hh:416
int getScrollPosX()
Definition layout.hh:288
void scrollTo(HPosition hpos, VPosition vpos, int x, int y, int width, int height)
Scrolls all viewports, so that the region [x, y, width, height] is seen, according to hpos and vpos.
Definition layout.cc:539
void scroll(ScrollCommand)
Definition layout.cc:529
void setAnchor(const char *anchor)
Sets the anchor to scroll to.
Definition layout.cc:738
static Color * create(Layout *layout, int color)
Definition style.cc:529
void setBufferedDrawing(bool b)
void setPageOverlap(int overlap)
void setScrollbarPageMode(bool enable)
void setDragScroll(bool enable)
void setScrollStep(int step)
void setScrollbarOnLeft(bool enable)
unsigned int uint_t
Definition d_size.h:20
unsigned char bool_t
Definition d_size.h:21
char * a_Dialog_open_file(const char *title, const char *pattern, const char *fname)
Show the open file dialog.
Definition dialog.cc:272
int a_Dialog_choice(const char *title, const char *msg,...)
Make a question-dialog with a question and alternatives.
Definition dialog.cc:342
void a_Dialog_msg(const char *title, const char *msg)
Display a message in a popup window.
Definition dialog.cc:127
const char * a_Dialog_save_file(const char *title, const char *pattern, const char *fname)
Show the save file dialog.
Definition dialog.cc:246
const char * a_Dialog_passwd(const char *title, const char *msg)
Dialog for password.
Definition dialog.cc:233
void a_Dialog_text_window(const char *title, const char *txt)
Show a new window with the provided text.
Definition dialog.cc:296
const char * a_Dialog_select_file(const char *title, const char *pattern, const char *fname)
Show the select file dialog.
Definition dialog.cc:257
const char * a_Dialog_input(const char *title, const char *msg)
Dialog for one line of Input with a message.
Definition dialog.cc:151
char * dStrconcat(const char *s1,...)
Concatenate a NULL-terminated list of strings.
Definition dlib.c:102
void dFree(void *mem)
Definition dlib.c:68
int dStrAsciiCasecmp(const char *s1, const char *s2)
Definition dlib.c:203
void dStr_append(Dstr *ds, const char *s)
Append a C string to a Dstr.
Definition dlib.c:316
char * dStrdup(const char *s)
Definition dlib.c:77
Dstr * dStr_sized_new(int sz)
Create a new string with a given size.
Definition dlib.c:254
int dStrnAsciiCasecmp(const char *s1, const char *s2, size_t n)
Definition dlib.c:215
int dList_length(Dlist *lp)
For completing the ADT.
Definition dlib.c:613
void * dList_nth_data(Dlist *lp, int n0)
Return the nth data item, NULL when not found or 'n0' is out of range.
Definition dlib.c:662
void dStr_free(Dstr *ds, int all)
Free a dillo string.
Definition dlib.c:337
void dStr_append_c(Dstr *ds, int c)
Append one character.
Definition dlib.c:349
char * dStrndup(const char *s, size_t sz)
Definition dlib.c:88
void dStr_sprintf(Dstr *ds, const char *format,...)
Printf-like function.
Definition dlib.c:450
Dstr * dStr_new(const char *s)
Create a new string.
Definition dlib.c:325
void dStr_vsprintf(Dstr *ds, const char *format, va_list argp)
vsprintf-like function.
Definition dlib.c:439
#define MIN(a, b)
Definition dlib.h:30
#define dReturn_if(expr)
Definition dlib.h:64
#define dNew(type, count)
Definition dlib.h:49
static Fl_Window * window
static Layout * layout
static FltkPlatform * platform
static FltkViewport * viewport
const DilloUrl * a_History_get_url(int idx)
Return the DilloUrl field (by index)
Definition history.c:80
KeysCommand_t
Definition keys.hh:17
@ KEYS_SCREEN_RIGHT
Definition keys.hh:45
@ KEYS_BOTTOM
Definition keys.hh:51
@ KEYS_LEFT
Definition keys.hh:48
@ KEYS_RIGHT
Definition keys.hh:49
@ KEYS_NOP
Definition keys.hh:19
@ KEYS_LEFT_TAB
Definition keys.hh:23
@ KEYS_RIGHT_TAB
Definition keys.hh:24
@ KEYS_CLOSE_ALL
Definition keys.hh:36
@ KEYS_LINE_UP
Definition keys.hh:46
@ KEYS_SCREEN_DOWN
Definition keys.hh:43
@ KEYS_TOP
Definition keys.hh:50
@ KEYS_LINE_DOWN
Definition keys.hh:47
@ KEYS_NEW_WINDOW
Definition keys.hh:21
@ KEYS_NEW_TAB
Definition keys.hh:22
@ KEYS_SCREEN_LEFT
Definition keys.hh:44
@ KEYS_SCREEN_UP
Definition keys.hh:42
@ KEYS_CLOSE_TAB
Definition keys.hh:25
#define MSG_WARN(...)
Definition msg.h:26
void a_Menu_page_popup(BrowserWindow *bw, const DilloUrl *url, bool_t has_bugs, void *v_cssUrls)
Page popup menu (construction & popup)
Definition menu.cc:355
void a_Menu_file_popup(BrowserWindow *bw, void *v_wid)
File popup menu (construction & popup)
Definition menu.cc:658
void a_Menu_tools_popup(BrowserWindow *bw, int x, int y)
Tools popup menu (construction & popup).
Definition menu.cc:830
void a_Menu_link_popup(BrowserWindow *bw, const DilloUrl *url, const DilloUrl *page_url)
Link popup menu (construction & popup)
Definition menu.cc:550
void a_Menu_image_popup(BrowserWindow *bw, const DilloUrl *url, bool_t loaded_img, DilloUrl *page_url, DilloUrl *link_url)
Image popup menu (construction & popup)
Definition menu.cc:571
void a_Menu_bugmeter_popup(BrowserWindow *bw, const DilloUrl *url)
Bugmeter popup menu (construction & popup)
Definition menu.cc:691
void a_Menu_history_popup(BrowserWindow *bw, int x, int y, int direction)
Navigation History popup menu (construction & popup).
Definition menu.cc:717
void a_Menu_form_popup(BrowserWindow *bw, const DilloUrl *page_url, void *formptr, bool_t hidvis)
Form popup menu (construction & popup)
Definition menu.cc:630
int a_Misc_parse_search_url(char *source, char **label, char **urlstr)
Parse dillorc's search_url string ([<label> ]<url>) Return value: -1 on error, 0 on success (and labe...
Definition misc.c:391
void a_Misc_parse_content_type(const char *type, char **major, char **minor, char **charset)
Parse Content-Type string, e.g., "text/html; charset=utf-8".
Definition misc.c:210
@ BACKGROUND_ATTACHMENT_SCROLL
Definition style.hh:245
Length createPerLength(double v)
Returns a percentage, v is relative to 1, not to 100.
Definition style.hh:435
The core of Dw is defined in this namespace.
Definition core.hh:23
@ VPOS_TOP
Definition types.hh:27
@ HPOS_LEFT
Definition types.hh:17
ScrollCommand
Definition types.hh:35
@ LINE_UP_CMD
Definition types.hh:36
@ BOTTOM_CMD
Definition types.hh:37
@ RIGHT_CMD
Definition types.hh:37
@ SCREEN_LEFT_CMD
Definition types.hh:35
@ LEFT_CMD
Definition types.hh:37
@ SCREEN_DOWN_CMD
Definition types.hh:35
@ LINE_DOWN_CMD
Definition types.hh:36
@ SCREEN_UP_CMD
Definition types.hh:35
@ SCREEN_RIGHT_CMD
Definition types.hh:36
@ TOP_CMD
Definition types.hh:37
This namespace contains FLTK implementations of Dw interfaces.
int a_Nav_stack_ptr(BrowserWindow *bw)
Definition nav.c:55
void a_Nav_redirection0(BrowserWindow *bw, const DilloUrl *new_url)
Definition nav.c:422
void a_Nav_forw(BrowserWindow *bw)
Definition nav.c:452
const char * a_Nav_get_content_type(const DilloUrl *url)
Definition nav.c:596
void a_Nav_cancel_expect(BrowserWindow *bw)
Definition nav.c:247
void a_Nav_jump(BrowserWindow *bw, int offset, int new_bw)
Definition nav.c:525
void a_Nav_back(BrowserWindow *bw)
Definition nav.c:438
void a_Nav_reload(BrowserWindow *bw)
Definition nav.c:516
void a_Nav_repush(BrowserWindow *bw)
Definition nav.c:393
void a_Nav_unref_buf(const DilloUrl *Url)
Definition nav.c:588
int a_Nav_stack_size(BrowserWindow *bw)
Definition nav.c:98
void a_Nav_set_vsource_url(const DilloUrl *Url)
Definition nav.c:604
void a_Nav_save_url(BrowserWindow *bw, const DilloUrl *url, const char *filename)
Definition nav.c:567
int a_Nav_get_buf(const DilloUrl *Url, char **PBuf, int *BufSize)
Definition nav.c:580
void a_Nav_push(BrowserWindow *bw, const DilloUrl *url, const DilloUrl *requester)
Definition nav.c:342
#define NAV_UIDX(bw, i)
Definition nav.h:9
#define NAV_TOP_UIDX(bw)
Definition nav.h:10
DilloPrefs prefs
Global Data.
Definition prefs.c:33
#define PREFS_UI_TAB_ACTIVE_BG_COLOR
Definition prefs.h:29
#define PREFS_UI_TAB_ACTIVE_FG_COLOR
Definition prefs.h:30
#define PREFS_UI_TAB_FG_COLOR
Definition prefs.h:32
#define PREFS_UI_TAB_BG_COLOR
Definition prefs.h:31
#define UI_MIN_H
Definition ui.hh:38
@ UI_FORW
Definition ui.hh:19
@ UI_BACK
Definition ui.hh:18
@ UI_STOP
Definition ui.hh:23
#define UI_MIN_W
Definition ui.hh:37
Contains the specific data for a single window.
Definition bw.h:27
Dlist * ImageClients
Image Keys for all active connections in the window.
Definition bw.h:42
Dstr * page_bugs
Definition bw.h:71
Dlist * RootClients
A list of active cache clients in the window (The primary Key)
Definition bw.h:40
void * render_layout
All the rendering is done by this.
Definition bw.h:34
float zoom
Definition bw.h:74
void * ui
Pointer to the UI object this bw belongs to.
Definition bw.h:29
int num_page_bugs
HTML-bugs detected at parse time.
Definition bw.h:70
int xpos
Definition prefs.h:40
int width
Definition prefs.h:38
int ypos
Definition prefs.h:41
int32_t bg_color
Definition prefs.h:54
int32_t buffered_drawing
Definition prefs.h:107
bool_t middle_click_drags_page
Definition prefs.h:123
bool_t right_click_closes_tab
Definition prefs.h:115
bool_t show_quit_dialog
Definition prefs.h:97
bool_t scrollbar_on_left
Definition prefs.h:81
bool_t scrollbar_page_mode
Definition prefs.h:82
int32_t scroll_page_overlap
Definition prefs.h:80
int32_t scroll_step
Definition prefs.h:79
DilloUrl * new_tab_page
Definition prefs.h:51
bool_t scroll_switches_tabs
Definition prefs.h:116
bool_t scroll_switches_tabs_reverse
Definition prefs.h:117
double zoom_factor
Definition prefs.h:76
Dlist * search_urls
Definition prefs.h:119
char * save_dir
Definition prefs.h:120
int32_t ui_tab_height
Definition prefs.h:63
int height
Definition prefs.h:39
DilloUrl * home
Definition prefs.h:50
bool_t search_url_idx
Definition prefs.h:118
Definition url.h:88
Definition dlib.h:102
Dstr_char_t * str
Definition dlib.h:105
static void path()
Definition cookies.c:859
void a_Timeout_add(float t, TimeoutCb_t cb, void *cbdata)
Hook a one-time timeout function 'cb' after 't' seconds with 'cbdata" as its data.
Definition timeout.cc:25
void a_UIcmd_tools(void *vbw, int x, int y)
Definition uicmd.cc:1145
void a_UIcmd_link_popup(void *vbw, const DilloUrl *url, const DilloUrl *page_url)
Definition uicmd.cc:1272
const char * a_UIcmd_get_passwd(const char *user)
Definition uicmd.cc:1222
static void UIcmd_open_url_nbw(BrowserWindow *new_bw, const DilloUrl *url)
Definition uicmd.cc:813
#define BW2UI(bw)
Definition uicmd.cc:59
static BrowserWindow * UIcmd_tab_new(CustTabs *tabs, UI *old_ui, int focus)
Definition uicmd.cc:626
void a_UIcmd_set_bug_prog(BrowserWindow *bw, int n_bug)
Definition uicmd.cc:1531
void a_UIcmd_set_scroll_xy(BrowserWindow *bw, int x, int y)
Definition uicmd.cc:1432
void a_UIcmd_page_popup(void *vbw, bool_t has_bugs, void *v_cssUrls)
Definition uicmd.cc:1262
void a_UIcmd_bugmeter_popup(void *vbw)
Definition uicmd.cc:1364
void a_UIcmd_set_msg(BrowserWindow *bw, const char *format,...)
Definition uicmd.cc:1563
static char * UIcmd_find_search_str(const char *str)
Definition uicmd.cc:732
void a_UIcmd_home(void *vbw)
Definition uicmd.cc:897
void a_UIcmd_copy_urlstr(BrowserWindow *bw, const char *urlstr)
Definition uicmd.cc:1306
void a_UIcmd_form_popup(void *vbw, const DilloUrl *url, void *vform, bool_t showing_hiddens)
Definition uicmd.cc:1289
void a_UIcmd_close_bw(void *vbw)
Definition uicmd.cc:675
static char * UIcmd_make_search_str(const char *str)
Definition uicmd.cc:1173
void a_UIcmd_image_popup(void *vbw, const DilloUrl *url, bool_t loaded_img, DilloUrl *page_url, DilloUrl *link_url)
Definition uicmd.cc:1280
int * a_UIcmd_get_history(BrowserWindow *bw, int direction)
Definition uicmd.cc:1375
static void win_cb(Fl_Widget *w, void *cb_data)
Definition uicmd.cc:521
void a_UIcmd_reload_all_active()
Definition uicmd.cc:913
void a_UIcmd_open_file(void *vbw)
Definition uicmd.cc:1153
BrowserWindow * a_UIcmd_browser_window_new(int ww, int wh, uint32_t xid, const void *vbw)
Definition uicmd.cc:559
void a_UIcmd_focus_location(void *vbw)
Definition uicmd.cc:1653
void a_UIcmd_zoom_reset(void *vbw)
Definition uicmd.cc:974
void a_UIcmd_zoom_in(void *vbw)
Definition uicmd.cc:942
void a_UIcmd_zoom_out(void *vbw)
Definition uicmd.cc:958
void a_UIcmd_set_page_title(BrowserWindow *bw, const char *label)
Definition uicmd.cc:1540
void a_UIcmd_focus_main_area(BrowserWindow *bw)
Definition uicmd.cc:1645
void a_UIcmd_findtext_search(BrowserWindow *bw, const char *key, int case_sens, int backward)
Definition uicmd.cc:1604
void a_UIcmd_reload(void *vbw)
Definition uicmd.cc:905
static void tab_btn_cb(Fl_Widget *w, void *cb_data)
Callback for mouse click.
Definition uicmd.cc:200
#define DEFAULT_TAB_LABEL
Definition uicmd.cc:56
BrowserWindow * a_UIcmd_get_bw_by_widget(void *v_wid)
Definition uicmd.cc:543
void a_UIcmd_file_popup(void *vbw, void *v_wid)
Definition uicmd.cc:1298
void a_UIcmd_open_url_nw(BrowserWindow *bw, const DilloUrl *url)
Definition uicmd.cc:836
static void close_tab_btn_cb(Fl_Widget *w, void *cb_data)
Callback for the close-tab button.
Definition uicmd.cc:218
void a_UIcmd_view_page_source(BrowserWindow *bw, const DilloUrl *url)
Definition uicmd.cc:1315
void a_UIcmd_book(void *vbw)
Definition uicmd.cc:1243
void a_UIcmd_search_dialog(void *vbw)
Definition uicmd.cc:1208
void a_UIcmd_view_page_bugs(void *vbw)
Definition uicmd.cc:1350
void a_UIcmd_nav_jump(BrowserWindow *bw, int offset, int new_bw)
Definition uicmd.cc:1399
static char * UIcmd_make_save_filename(const DilloUrl *url)
Definition uicmd.cc:987
void a_UIcmd_findbar_toggle(BrowserWindow *bw, int on)
Definition uicmd.cc:1637
static int btn_cmp(const void *p1, const void *p2)
Definition uicmd.cc:111
void a_UIcmd_get_wh(BrowserWindow *bw, int *w, int *h)
Definition uicmd.cc:1409
void a_UIcmd_open_urlstr(void *vbw, const char *urlstr)
Definition uicmd.cc:760
void a_UIcmd_set_buttons_sens(BrowserWindow *bw)
Definition uicmd.cc:1577
static struct Tabgroup * tabgroups
Definition uicmd.cc:79
void a_UIcmd_panels_toggle(BrowserWindow *bw)
Definition uicmd.cc:1596
const char * a_UIcmd_select_file()
Definition uicmd.cc:1123
void a_UIcmd_forw_popup(void *vbw, int x, int y)
Definition uicmd.cc:889
void a_UIcmd_save(void *vbw)
Definition uicmd.cc:1110
void a_UIcmd_back(void *vbw)
Definition uicmd.cc:865
void a_UIcmd_get_scroll_xy(BrowserWindow *bw, int *x, int *y)
Definition uicmd.cc:1419
void a_UIcmd_forw(void *vbw)
Definition uicmd.cc:881
void a_UIcmd_save_link(BrowserWindow *bw, const DilloUrl *url)
Definition uicmd.cc:1235
static void UIcmd_save(BrowserWindow *bw, const DilloUrl *url, const char *title)
Definition uicmd.cc:1075
void a_UIcmd_repush(void *vbw)
Definition uicmd.cc:926
void a_UIcmd_back_popup(void *vbw, int x, int y)
Definition uicmd.cc:873
char * a_UIcmd_get_location_text(BrowserWindow *bw)
Definition uicmd.cc:1492
void a_UIcmd_close_all_bw(void *)
Definition uicmd.cc:714
static const char * save_dir
Definition uicmd.cc:70
void a_UIcmd_add_bookmark(BrowserWindow *bw, const DilloUrl *url)
Definition uicmd.cc:1253
void a_UIcmd_open_url(BrowserWindow *bw, const DilloUrl *url)
Definition uicmd.cc:801
void a_UIcmd_set_page_prog(BrowserWindow *bw, size_t nbytes, int cmd)
Definition uicmd.cc:1510
void a_UIcmd_stop(void *vbw)
Definition uicmd.cc:1132
void a_UIcmd_findtext_reset(BrowserWindow *bw)
Definition uicmd.cc:1626
void a_UIcmd_scroll(BrowserWindow *bw, int icmd)
Definition uicmd.cc:1456
static void UIcmd_set_window_labels(Fl_Window *win, const char *str)
Definition uicmd.cc:613
void a_UIcmd_set_scroll_by_fragment(BrowserWindow *bw, const char *f)
Definition uicmd.cc:1444
void a_UIcmd_set_img_prog(BrowserWindow *bw, int n_img, int t_img, int cmd)
Definition uicmd.cc:1519
static int UIcmd_save_file_check(const char *name)
Definition uicmd.cc:1053
void a_UIcmd_redirection0(void *vbw, const DilloUrl *url)
Definition uicmd.cc:934
void a_UIcmd_set_location_text(void *vbw, const char *text)
Definition uicmd.cc:1500
void a_UIcmd_open_url_nt(void *vbw, const DilloUrl *url, int focus)
Definition uicmd.cc:852
void a_UIcmd_init(void)
Definition uicmd.cc:1037
char * a_Url_string_strip_delimiters(const char *str)
RFC-3986 suggests this stripping when "importing" URLs from other media.
Definition url.c:658
char * a_Url_encode_hex_str(const char *str)
Urlencode 'str'.
Definition url.c:620
void a_Url_free(DilloUrl *url)
Free a DilloUrl.
Definition url.c:208
DilloUrl * a_Url_new(const char *url_str, const char *base_url)
Transform (and resolve) an URL string into the respective DilloURL.
Definition url.c:371
#define URL_PATH(u)
Definition url.h:72
#define URL_FLAGS(u)
Definition url.h:79
#define URL_STR(u)
Definition url.h:76
#define URL_QUERY(u)
Definition url.h:73
#define URL_Post
Definition url.h:33
uint_t a_Utf8_end_of_char(const char *str, uint_t i)
Return index of the last byte of the UTF-8-encoded character that str + i points to or into.
Definition utf8.cc:23