Subversion Repositories Kolibri OS

Rev

Rev 4364 | Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright 2008 Vincent Sanders <vince@simtec.co.uk>
  3.  *
  4.  * This file is part of NetSurf, http://www.netsurf-browser.org/
  5.  *
  6.  * NetSurf is free software; you can redistribute it and/or modify
  7.  * it under the terms of the GNU General Public License as published by
  8.  * the Free Software Foundation; version 2 of the License.
  9.  *
  10.  * NetSurf is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License
  16.  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  17.  */
  18.  
  19. #include <sys/types.h>
  20. #include <sys/stat.h>
  21. #include <fcntl.h>
  22. #include <sys/ioctl.h>
  23. #include <limits.h>
  24. #include <unistd.h>
  25. #include <assert.h>
  26. #include <string.h>
  27. #include <stdbool.h>
  28. #include <stdlib.h>
  29.  
  30. #include <libnsfb.h>
  31. #include <libnsfb_plot.h>
  32. #include <libnsfb_event.h>
  33.  
  34. #include "desktop/browser_private.h"
  35. #include "desktop/gui.h"
  36. #include "desktop/mouse.h"
  37. #include "desktop/plotters.h"
  38. #include "desktop/netsurf.h"
  39. #include "desktop/options.h"
  40. #include "utils/filepath.h"
  41. #include "utils/log.h"
  42. #include "utils/messages.h"
  43. #include "utils/schedule.h"
  44. #include "utils/types.h"
  45. #include "utils/url.h"
  46. #include "utils/utils.h"
  47. #include "desktop/textinput.h"
  48. #include "render/form.h"
  49.  
  50. #include "framebuffer/gui.h"
  51. #include "framebuffer/fbtk.h"
  52. #include "framebuffer/framebuffer.h"
  53. #include "framebuffer/schedule.h"
  54. #include "framebuffer/findfile.h"
  55. #include "framebuffer/image_data.h"
  56. #include "framebuffer/font.h"
  57.  
  58.  
  59.  
  60.  
  61. #include "content/urldb.h"
  62. #include "desktop/history_core.h"
  63. #include "content/fetch.h"
  64.  
  65. #define NSFB_TOOLBAR_DEFAULT_LAYOUT "blfsrut"
  66.  
  67. #ifdef DBG
  68. #undef DBG
  69. #endif
  70. #define DBG(s) __menuet__debug_out(s) /* For the debug messages in BOARD */
  71. //#define DBG(s) LOG((s))            /* So that we see debug in Netsurf's LOG files */
  72.  
  73. fbtk_widget_t *fbtk;
  74.  
  75. struct gui_window *input_window = NULL;
  76. struct gui_window *search_current_window;
  77. struct gui_window *window_list = NULL;
  78.  
  79. /* private data for browser user widget */
  80. struct browser_widget_s {
  81.         struct browser_window *bw; /**< The browser window connected to this gui window */
  82.         int scrollx, scrolly; /**< scroll offsets. */
  83.  
  84.         /* Pending window redraw state. */
  85.         bool redraw_required; /**< flag indicating the foreground loop
  86.                                * needs to redraw the browser widget.
  87.                                */
  88.         bbox_t redraw_box; /**< Area requiring redraw. */
  89.         bool pan_required; /**< flag indicating the foreground loop
  90.                             * needs to pan the window.
  91.                             */
  92.         int panx, pany; /**< Panning required. */
  93. };
  94.  
  95. static struct gui_drag {
  96.         enum state {
  97.                 GUI_DRAG_NONE,
  98.                 GUI_DRAG_PRESSED,
  99.                 GUI_DRAG_DRAG
  100.         } state;
  101.         int button;
  102.         int x;
  103.         int y;
  104.         bool grabbed_pointer;
  105. } gui_drag;
  106.  
  107.  
  108. /* queue a redraw operation, co-ordinates are relative to the window */
  109. static void
  110. fb_queue_redraw(struct fbtk_widget_s *widget, int x0, int y0, int x1, int y1)
  111. {
  112.         struct browser_widget_s *bwidget = fbtk_get_userpw(widget);
  113.  
  114.         bwidget->redraw_box.x0 = min(bwidget->redraw_box.x0, x0);
  115.         bwidget->redraw_box.y0 = min(bwidget->redraw_box.y0, y0);
  116.         bwidget->redraw_box.x1 = max(bwidget->redraw_box.x1, x1);
  117.         bwidget->redraw_box.y1 = max(bwidget->redraw_box.y1, y1);
  118.  
  119.         if (fbtk_clip_to_widget(widget, &bwidget->redraw_box)) {
  120.                 bwidget->redraw_required = true;
  121.                 fbtk_request_redraw(widget);
  122.         } else {
  123.                 bwidget->redraw_box.y0 = bwidget->redraw_box.x0 = INT_MAX;
  124.                 bwidget->redraw_box.y1 = bwidget->redraw_box.x1 = -(INT_MAX);
  125.                 bwidget->redraw_required = false;
  126.         }
  127. }
  128.  
  129. /* queue a window scroll */
  130. static void
  131. widget_scroll_y(struct gui_window *gw, int y, bool abs)
  132. {
  133.         struct browser_widget_s *bwidget = fbtk_get_userpw(gw->browser);
  134.         int content_height;
  135.         int height;
  136.         float scale = gw->bw->scale;
  137.  
  138.         LOG(("window scroll"));
  139.         if (abs) {
  140.                 bwidget->pany = y - bwidget->scrolly;
  141.         } else {
  142.                 bwidget->pany += y;
  143.         }
  144.  
  145.         content_height = content_get_height(gw->bw->current_content) * scale;
  146.  
  147.         height = fbtk_get_height(gw->browser);
  148.  
  149.         /* dont pan off the top */
  150.         if ((bwidget->scrolly + bwidget->pany) < 0)
  151.                 bwidget->pany = -bwidget->scrolly;
  152.  
  153.         /* do not pan off the bottom of the content */
  154.         if ((bwidget->scrolly + bwidget->pany) > (content_height - height))
  155.                 bwidget->pany = (content_height - height) - bwidget->scrolly;
  156.  
  157.         if (bwidget->pany == 0)
  158.                 return;
  159.  
  160.         bwidget->pan_required = true;
  161.  
  162.         fbtk_request_redraw(gw->browser);
  163.  
  164.         fbtk_set_scroll_position(gw->vscroll, bwidget->scrolly + bwidget->pany);
  165. }
  166.  
  167. /* queue a window scroll */
  168. static void
  169. widget_scroll_x(struct gui_window *gw, int x, bool abs)
  170. {
  171.         struct browser_widget_s *bwidget = fbtk_get_userpw(gw->browser);
  172.         int content_width;
  173.         int width;
  174.         float scale = gw->bw->scale;
  175.  
  176.         if (abs) {
  177.                 bwidget->panx = x - bwidget->scrollx;
  178.         } else {
  179.                 bwidget->panx += x;
  180.         }
  181.  
  182.         content_width = content_get_width(gw->bw->current_content) * scale;
  183.  
  184.         width = fbtk_get_width(gw->browser);
  185.  
  186.         /* dont pan off the left */
  187.         if ((bwidget->scrollx + bwidget->panx) < 0)
  188.                 bwidget->panx = - bwidget->scrollx;
  189.  
  190.         /* do not pan off the right of the content */
  191.         if ((bwidget->scrollx + bwidget->panx) > (content_width - width))
  192.                 bwidget->panx = (content_width - width) - bwidget->scrollx;
  193.  
  194.         if (bwidget->panx == 0)
  195.                 return;
  196.  
  197.         bwidget->pan_required = true;
  198.  
  199.         fbtk_request_redraw(gw->browser);
  200.  
  201.         fbtk_set_scroll_position(gw->hscroll, bwidget->scrollx + bwidget->panx);
  202. }
  203.  
  204. static void
  205. fb_pan(fbtk_widget_t *widget,
  206.        struct browser_widget_s *bwidget,
  207.        struct browser_window *bw)
  208. {
  209.         int x;
  210.         int y;
  211.         int width;
  212.         int height;
  213.         nsfb_bbox_t srcbox;
  214.         nsfb_bbox_t dstbox;
  215.  
  216.         nsfb_t *nsfb = fbtk_get_nsfb(widget);
  217.  
  218.         height = fbtk_get_height(widget);
  219.         width = fbtk_get_width(widget);
  220.  
  221.         LOG(("panning %d, %d", bwidget->panx, bwidget->pany));
  222.  
  223.         x = fbtk_get_absx(widget);
  224.         y = fbtk_get_absy(widget);
  225.  
  226.         /* if the pan exceeds the viewport size just redraw the whole area */
  227.         if (bwidget->pany >= height || bwidget->pany <= -height ||
  228.             bwidget->panx >= width || bwidget->panx <= -width) {
  229.  
  230.                 bwidget->scrolly += bwidget->pany;
  231.                 bwidget->scrollx += bwidget->panx;
  232.                 fb_queue_redraw(widget, 0, 0, width, height);
  233.  
  234.                 /* ensure we don't try to scroll again */
  235.                 bwidget->panx = 0;
  236.                 bwidget->pany = 0;
  237.                 bwidget->pan_required = false;
  238.                 return;
  239.         }
  240.  
  241.         if (bwidget->pany < 0) {
  242.                 /* pan up by less then viewport height */
  243.                 srcbox.x0 = x;
  244.                 srcbox.y0 = y;
  245.                 srcbox.x1 = srcbox.x0 + width;
  246.                 srcbox.y1 = srcbox.y0 + height + bwidget->pany;
  247.  
  248.                 dstbox.x0 = x;
  249.                 dstbox.y0 = y - bwidget->pany;
  250.                 dstbox.x1 = dstbox.x0 + width;
  251.                 dstbox.y1 = dstbox.y0 + height + bwidget->pany;
  252.  
  253.                 /* move part that remains visible up */
  254.                 nsfb_plot_copy(nsfb, &srcbox, nsfb, &dstbox);
  255.  
  256.                 /* redraw newly exposed area */
  257.                 bwidget->scrolly += bwidget->pany;
  258.                 fb_queue_redraw(widget, 0, 0, width, - bwidget->pany);
  259.  
  260.         } else if (bwidget->pany > 0) {
  261.                 /* pan down by less then viewport height */
  262.                 srcbox.x0 = x;
  263.                 srcbox.y0 = y + bwidget->pany;
  264.                 srcbox.x1 = srcbox.x0 + width;
  265.                 srcbox.y1 = srcbox.y0 + height - bwidget->pany;
  266.  
  267.                 dstbox.x0 = x;
  268.                 dstbox.y0 = y;
  269.                 dstbox.x1 = dstbox.x0 + width;
  270.                 dstbox.y1 = dstbox.y0 + height - bwidget->pany;
  271.  
  272.                 /* move part that remains visible down */
  273.                 nsfb_plot_copy(nsfb, &srcbox, nsfb, &dstbox);
  274.  
  275.                 /* redraw newly exposed area */
  276.                 bwidget->scrolly += bwidget->pany;
  277.                 fb_queue_redraw(widget, 0, height - bwidget->pany,
  278.                                 width, height);
  279.         }
  280.  
  281.         if (bwidget->panx < 0) {
  282.                 /* pan left by less then viewport width */
  283.                 srcbox.x0 = x;
  284.                 srcbox.y0 = y;
  285.                 srcbox.x1 = srcbox.x0 + width + bwidget->panx;
  286.                 srcbox.y1 = srcbox.y0 + height;
  287.  
  288.                 dstbox.x0 = x - bwidget->panx;
  289.                 dstbox.y0 = y;
  290.                 dstbox.x1 = dstbox.x0 + width + bwidget->panx;
  291.                 dstbox.y1 = dstbox.y0 + height;
  292.  
  293.                 /* move part that remains visible left */
  294.                 nsfb_plot_copy(nsfb, &srcbox, nsfb, &dstbox);
  295.  
  296.                 /* redraw newly exposed area */
  297.                 bwidget->scrollx += bwidget->panx;
  298.                 fb_queue_redraw(widget, 0, 0, -bwidget->panx, height);
  299.  
  300.         } else if (bwidget->panx > 0) {
  301.                 /* pan right by less then viewport width */
  302.                 srcbox.x0 = x + bwidget->panx;
  303.                 srcbox.y0 = y;
  304.                 srcbox.x1 = srcbox.x0 + width - bwidget->panx;
  305.                 srcbox.y1 = srcbox.y0 + height;
  306.  
  307.                 dstbox.x0 = x;
  308.                 dstbox.y0 = y;
  309.                 dstbox.x1 = dstbox.x0 + width - bwidget->panx;
  310.                 dstbox.y1 = dstbox.y0 + height;
  311.  
  312.                 /* move part that remains visible right */
  313.                 nsfb_plot_copy(nsfb, &srcbox, nsfb, &dstbox);
  314.  
  315.                 /* redraw newly exposed area */
  316.                 bwidget->scrollx += bwidget->panx;
  317.                 fb_queue_redraw(widget, width - bwidget->panx, 0,
  318.                                 width, height);
  319.         }
  320.  
  321.         bwidget->pan_required = false;
  322.         bwidget->panx = 0;
  323.         bwidget->pany = 0;
  324. }
  325.  
  326. static void
  327. fb_redraw(fbtk_widget_t *widget,
  328.           struct browser_widget_s *bwidget,
  329.           struct browser_window *bw)
  330. {
  331.         int x;
  332.         int y;
  333.         int caret_x, caret_y, caret_h;
  334.         struct rect clip;
  335.         struct redraw_context ctx = {
  336.                 .interactive = true,
  337.                 .background_images = true,
  338.                 .plot = &fb_plotters
  339.         };
  340.         nsfb_t *nsfb = fbtk_get_nsfb(widget);
  341.  
  342.         LOG(("%d,%d to %d,%d",
  343.              bwidget->redraw_box.x0,
  344.              bwidget->redraw_box.y0,
  345.              bwidget->redraw_box.x1,
  346.              bwidget->redraw_box.y1));
  347.  
  348.         x = fbtk_get_absx(widget);
  349.         y = fbtk_get_absy(widget);
  350.  
  351.         /* adjust clipping co-ordinates according to window location */
  352.         bwidget->redraw_box.y0 += y;
  353.         bwidget->redraw_box.y1 += y;
  354.         bwidget->redraw_box.x0 += x;
  355.         bwidget->redraw_box.x1 += x;
  356.  
  357.         nsfb_claim(nsfb, &bwidget->redraw_box);
  358.  
  359.         /* redraw bounding box is relative to window */
  360.         clip.x0 = bwidget->redraw_box.x0;
  361.         clip.y0 = bwidget->redraw_box.y0;
  362.         clip.x1 = bwidget->redraw_box.x1;
  363.         clip.y1 = bwidget->redraw_box.y1;
  364.  
  365.         browser_window_redraw(bw,
  366.                         (x - bwidget->scrollx) / bw->scale,
  367.                         (y - bwidget->scrolly) / bw->scale,
  368.                         &clip, &ctx);
  369.  
  370.         if (fbtk_get_caret(widget, &caret_x, &caret_y, &caret_h)) {
  371.                 /* This widget has caret, so render it */
  372.                 nsfb_bbox_t line;
  373.                 nsfb_plot_pen_t pen;
  374.  
  375.                 line.x0 = x - bwidget->scrollx + caret_x;
  376.                 line.y0 = y - bwidget->scrolly + caret_y;
  377.                 line.x1 = x - bwidget->scrollx + caret_x;
  378.                 line.y1 = y - bwidget->scrolly + caret_y + caret_h;
  379.  
  380.                 pen.stroke_type = NFSB_PLOT_OPTYPE_SOLID;
  381.                 pen.stroke_width = 1;
  382.                 pen.stroke_colour = 0xFF0000FF;
  383.  
  384.                 nsfb_plot_line(nsfb, &line, &pen);
  385.         }
  386.         ///STUB???
  387.         nsfb_update(fbtk_get_nsfb(widget), &bwidget->redraw_box);
  388.  
  389.         bwidget->redraw_box.y0 = bwidget->redraw_box.x0 = INT_MAX;
  390.         bwidget->redraw_box.y1 = bwidget->redraw_box.x1 = INT_MIN;
  391.         bwidget->redraw_required = false;
  392. }
  393.  
  394. static int
  395. fb_browser_window_redraw(fbtk_widget_t *widget, fbtk_callback_info *cbi)
  396. {
  397.         struct gui_window *gw = cbi->context;
  398.         struct browser_widget_s *bwidget;
  399.  
  400.         bwidget = fbtk_get_userpw(widget);
  401.         if (bwidget == NULL) {
  402.                 LOG(("browser widget from widget %p was null", widget));
  403.                 return -1;
  404.         }
  405.  
  406.         if (bwidget->pan_required) {
  407.                 fb_pan(widget, bwidget, gw->bw);
  408.         }
  409.  
  410.         if (bwidget->redraw_required) {
  411.                 fb_redraw(widget, bwidget, gw->bw);
  412.         } else {
  413.                 bwidget->redraw_box.x0 = 0;
  414.                 bwidget->redraw_box.y0 = 0;
  415.                 bwidget->redraw_box.x1 = fbtk_get_width(widget);
  416.                 bwidget->redraw_box.y1 = fbtk_get_height(widget);
  417.                 fb_redraw(widget, bwidget, gw->bw);
  418.         }
  419.         return 0;
  420. }
  421.  
  422.  
  423. static const char *fename;
  424. static int febpp;
  425. static int fewidth;
  426. static int feheight;
  427. static const char *feurl;
  428.  
  429. static bool
  430. process_cmdline(int argc, char** argv)
  431. {
  432.         int opt;
  433.  
  434.         LOG(("argc %d, argv %p", argc, argv));
  435.  
  436.         fename = "kolibri";
  437.         febpp = 32;
  438.  
  439.         if ((nsoption_int(window_width) != 0) &&
  440.             (nsoption_int(window_height) != 0)) {
  441.                 fewidth = nsoption_int(window_width);
  442.                 feheight = nsoption_int(window_height);
  443.         } else {
  444.                 fewidth = 790; //640;
  445.                 feheight = 560; //400;
  446.         }
  447.  
  448.         if ((nsoption_charp(homepage_url) != NULL) &&
  449.             (nsoption_charp(homepage_url)[0] != '\0')) {
  450.                 feurl = nsoption_charp(homepage_url);
  451.         } else {
  452.                 feurl = "about:about";
  453.         }
  454.  
  455.         while((opt = getopt(argc, argv, "f:b:w:h:")) != -1) {
  456.                 switch (opt) {
  457.                 case 'f':
  458.                         fename = optarg;
  459.                         break;
  460.  
  461.                 case 'b':
  462.                         febpp = atoi(optarg);
  463.                         break;
  464.  
  465.                 case 'w':
  466.                         fewidth = atoi(optarg);
  467.                         break;
  468.  
  469.                 case 'h':
  470.                         feheight = atoi(optarg);
  471.                         break;
  472.  
  473.                 default:
  474.                         fprintf(stderr,
  475.                                 "Usage: %s [-f frontend] [-b bpp] url\n",
  476.                                 argv[0]);
  477.                         return false;
  478.                 }
  479.         }
  480.  
  481.         if (optind < argc) {
  482.                 feurl = argv[optind];
  483.         }
  484.  
  485.         return true;
  486. }
  487.  
  488. /* Documented in desktop/options.h */
  489. void gui_options_init_defaults(void)
  490. {
  491.         /* Set defaults for absent option strings */
  492.         nsoption_setnull_charp(cookie_file, strdup("~/.netsurf/Cookies"));
  493.         nsoption_setnull_charp(cookie_jar, strdup("~/.netsurf/Cookies"));
  494.  
  495.         if (nsoption_charp(cookie_file) == NULL ||
  496.                         nsoption_charp(cookie_jar == NULL)) {
  497.                 die("Failed initialising cookie options");
  498.         }
  499. }
  500.  
  501. static void
  502. gui_init(int argc, char** argv)
  503. {
  504.         nsfb_t *nsfb;
  505.  
  506.         /* Override, since we have no support for non-core SELECT menu */
  507.         nsoption_set_bool(core_select_menu, true);
  508.  
  509.         if (process_cmdline(argc,argv) != true)
  510.                 die("unable to process command line.\n");
  511.  
  512.         nsfb = framebuffer_initialise(fename, fewidth, feheight, febpp);
  513.         if (nsfb == NULL)
  514.                 die("Unable to initialise framebuffer");
  515.  
  516.         framebuffer_set_cursor(&pointer_image);
  517.  
  518.         if (fb_font_init() == false)
  519.                 die("Unable to initialise the font system");
  520.  
  521.         fbtk = fbtk_init(nsfb);
  522.  
  523.         fbtk_enable_oskb(fbtk);
  524.  
  525.         urldb_load_cookies(nsoption_charp(cookie_file));
  526. }
  527.  
  528. /** Entry point from OS.
  529.  *
  530.  * /param argc The number of arguments in the string vector.
  531.  * /param argv The argument string vector.
  532.  * /return The return code to the OS
  533.  */
  534.  
  535. #include <surface.h>
  536.  
  537. int
  538. main(int argc, char** argv)
  539. {
  540.         struct browser_window *bw;
  541.         char *options;
  542.         char *messages;
  543.  
  544.         setbuf(stderr, NULL);
  545.  
  546.         freopen( "stderr.log", "w", stderr );
  547.         freopen( "stdout.log", "w", stdout );
  548.        
  549.  
  550.         char p[256];
  551.         char **z;
  552.         z=0x20;
  553.         strcpy(p, *z);
  554.        
  555.         DBG("PATH1...\n");
  556.         DBG(p);
  557.         DBG("PATH1...\n");
  558.        
  559.         *(strrchr(p, '/')+1)='\0';
  560.        
  561.         strcpy(strrchr(p, '/')+1, "res/");
  562.        
  563.         DBG("PATH1...\n");
  564.         DBG(p);
  565.         DBG("PATH1...\n");
  566.  
  567.         asm volatile ("int $0x40"::"a"(30), "b"(1), "c"(p));
  568.        
  569.         LOG(("Registering surfaces for SDL and RAM.."));
  570.        
  571.         //extern nsfb_surface_rtns_t sdl_rtns;
  572.         extern nsfb_surface_rtns_t ram_rtns;
  573.         extern nsfb_surface_rtns_t able_rtns;
  574.         extern nsfb_surface_rtns_t kolibri_rtns;
  575.        
  576.         //_nsfb_register_surface(NSFB_SURFACE_SDL, &sdl_rtns, "sdl");
  577.         _nsfb_register_surface(NSFB_SURFACE_RAM, &ram_rtns, "ram");
  578.         _nsfb_register_surface(NSFB_SURFACE_ABLE, &able_rtns, "able");
  579.         _nsfb_register_surface(NSFB_SURFACE_KOLIBRI, &kolibri_rtns, "kolibri");
  580.        
  581.        
  582.         //respaths = fb_init_resource("/kolibrios/:/hd0/1/res/:/bd0/1/res/:/tmp9/1/netsurf/res/:res/:fonts/:");
  583.         respaths = fb_init_resource(p);
  584.  
  585.         options = filepath_find(respaths, "Choices");
  586.         messages = filepath_find(respaths, "messages");
  587.         LOG(("gui.c : printing kolibri DEBUG messages for BOARD"));
  588.         DBG("====================START\n");
  589.         DBG(messages);
  590.         DBG("====================END\n");
  591.        
  592.         //netsurf_init(&argc, &argv, options, "res/messages");
  593.         LOG(("Calling netsurf_init"));
  594.         netsurf_init(&argc, &argv, options, messages); 
  595.         extern HTTP_INIT();
  596.         DBG("Calling HTTP_INIT() for KolibriOS http lib..");
  597.         HTTP_INIT();
  598.         DBG(("NS HTTP_INIT okay"));
  599.         LOG(("NS init okay"));
  600.        
  601.         free(messages);
  602.         free(options);
  603.  
  604.         LOG(("freed opts and msgs, start gui init"));
  605.        
  606.  
  607.         gui_init(argc, argv);
  608.  
  609.         LOG(("calling browser_window_create in MAIN()"));
  610.         bw = browser_window_create(feurl, 0, 0, true, false);
  611.  
  612.  
  613.         LOG(("NS main loop..."));
  614.        
  615.         netsurf_main_loop();
  616.  
  617.         browser_window_destroy(bw);
  618.  
  619.         netsurf_exit();
  620.  
  621.         return 0;
  622. }
  623.  
  624. void
  625. gui_poll(bool active)
  626. {
  627.         /* LOG(("GUI poll in")); */
  628.         nsfb_event_t event;
  629.         int timeout; /* timeout in miliseconds */
  630.  
  631. /* LOG(("schedule run")); */
  632.         /* run the scheduler and discover how long to wait for the next event */
  633.         timeout = schedule_run();
  634.  
  635.         /* if active do not wait for event, return immediately */
  636.         if (active)
  637.                 timeout = 0;
  638.  
  639. /* LOG(("redraw pending")); */
  640.         /* if redraws are pending do not wait for event, return immediately */
  641.         if (fbtk_get_redraw_pending(fbtk))
  642.                 timeout = 0;
  643.  
  644.         if (fbtk_event(fbtk, &event, timeout)) {
  645.                 if ((event.type == NSFB_EVENT_CONTROL) &&
  646.                     (event.value.controlcode ==  NSFB_CONTROL_QUIT))
  647.                         netsurf_quit = true;
  648.         }
  649.  
  650. /* LOG(("fbtk redraw")); */
  651.         fbtk_redraw(fbtk);
  652.  
  653. /* LOG(("GUI poll out success")); */
  654. }
  655.  
  656. void
  657. gui_quit(void)
  658. {
  659.         LOG(("gui_quit"));
  660.  
  661.         urldb_save_cookies(nsoption_charp(cookie_jar));
  662.  
  663.         framebuffer_finalise();
  664. }
  665.  
  666. /* called back when click in browser window */
  667. static int
  668. fb_browser_window_click(fbtk_widget_t *widget, fbtk_callback_info *cbi)
  669. {
  670.         struct gui_window *gw = cbi->context;
  671.         struct browser_widget_s *bwidget = fbtk_get_userpw(widget);
  672.         float scale = gw->bw->scale;
  673.         int x = (cbi->x + bwidget->scrollx) / scale;
  674.         int y = (cbi->y + bwidget->scrolly) / scale;
  675.  
  676.         if (cbi->event->type != NSFB_EVENT_KEY_DOWN &&
  677.             cbi->event->type != NSFB_EVENT_KEY_UP)
  678.                 return 0;
  679.  
  680.         LOG(("browser window clicked at %d,%d", cbi->x, cbi->y));
  681.  
  682.         switch (cbi->event->type) {
  683.         case NSFB_EVENT_KEY_DOWN:
  684.                 switch (cbi->event->value.keycode) {
  685.                 case NSFB_KEY_MOUSE_1:
  686.                         browser_window_mouse_click(gw->bw,
  687.                                         BROWSER_MOUSE_PRESS_1, x, y);
  688.                         gui_drag.state = GUI_DRAG_PRESSED;
  689.                         gui_drag.button = 1;
  690.                         gui_drag.x = x;
  691.                         gui_drag.y = y;
  692.                         break;
  693.  
  694.                 case NSFB_KEY_MOUSE_3:
  695.                         browser_window_mouse_click(gw->bw,
  696.                                         BROWSER_MOUSE_PRESS_2, x, y);
  697.                         gui_drag.state = GUI_DRAG_PRESSED;
  698.                         gui_drag.button = 2;
  699.                         gui_drag.x = x;
  700.                         gui_drag.y = y;
  701.                         break;
  702.  
  703.                 case NSFB_KEY_MOUSE_4:
  704.                         /* scroll up */
  705.                         if (browser_window_scroll_at_point(gw->bw, x, y,
  706.                                         0, -100) == false)
  707.                                 widget_scroll_y(gw, -100, false);
  708.                         break;
  709.  
  710.                 case NSFB_KEY_MOUSE_5:
  711.                         /* scroll down */
  712.                         if (browser_window_scroll_at_point(gw->bw, x, y,
  713.                                         0, 100) == false)
  714.                                 widget_scroll_y(gw, 100, false);
  715.                         break;
  716.  
  717.                 default:
  718.                         break;
  719.  
  720.                 }
  721.  
  722.                 break;
  723.         case NSFB_EVENT_KEY_UP:
  724.                 switch (cbi->event->value.keycode) {
  725.                 case NSFB_KEY_MOUSE_1:
  726.                         if (gui_drag.state == GUI_DRAG_DRAG) {
  727.                                 /* End of a drag, rather than click */
  728.  
  729.                                 if (gui_drag.grabbed_pointer) {
  730.                                         /* need to ungrab pointer */
  731.                                         fbtk_tgrab_pointer(widget);
  732.                                         gui_drag.grabbed_pointer = false;
  733.                                 }
  734.  
  735.                                 gui_drag.state = GUI_DRAG_NONE;
  736.  
  737.                                 /* Tell core */
  738.                                 browser_window_mouse_track(gw->bw, 0, x, y);
  739.                                 break;
  740.                         }
  741.                         /* This is a click;
  742.                          * clear PRESSED state and pass to core */
  743.                         gui_drag.state = GUI_DRAG_NONE;
  744.                         browser_window_mouse_click(gw->bw,
  745.                                         BROWSER_MOUSE_CLICK_1, x, y);
  746.                         break;
  747.  
  748.                 case NSFB_KEY_MOUSE_3:
  749.                         if (gui_drag.state == GUI_DRAG_DRAG) {
  750.                                 /* End of a drag, rather than click */
  751.                                 gui_drag.state = GUI_DRAG_NONE;
  752.  
  753.                                 if (gui_drag.grabbed_pointer) {
  754.                                         /* need to ungrab pointer */
  755.                                         fbtk_tgrab_pointer(widget);
  756.                                         gui_drag.grabbed_pointer = false;
  757.                                 }
  758.  
  759.                                 /* Tell core */
  760.                                 browser_window_mouse_track(gw->bw, 0, x, y);
  761.                                 break;
  762.                         }
  763.                         /* This is a click;
  764.                          * clear PRESSED state and pass to core */
  765.                         gui_drag.state = GUI_DRAG_NONE;
  766.                         browser_window_mouse_click(gw->bw,
  767.                                         BROWSER_MOUSE_CLICK_2, x, y);
  768.                         break;
  769.  
  770.                 default:
  771.                         break;
  772.  
  773.                 }
  774.  
  775.                 break;
  776.         default:
  777.                 break;
  778.  
  779.         }
  780.         return 1;
  781. }
  782.  
  783. /* called back when movement in browser window */
  784. static int
  785. fb_browser_window_move(fbtk_widget_t *widget, fbtk_callback_info *cbi)
  786. {
  787.         browser_mouse_state mouse = 0;
  788.         struct gui_window *gw = cbi->context;
  789.         struct browser_widget_s *bwidget = fbtk_get_userpw(widget);
  790.         int x = (cbi->x + bwidget->scrollx) / gw->bw->scale;
  791.         int y = (cbi->y + bwidget->scrolly) / gw->bw->scale;
  792.  
  793.         if (gui_drag.state == GUI_DRAG_PRESSED &&
  794.                         (abs(x - gui_drag.x) > 5 ||
  795.                          abs(y - gui_drag.y) > 5)) {
  796.                 /* Drag started */
  797.                 if (gui_drag.button == 1) {
  798.                         browser_window_mouse_click(gw->bw,
  799.                                         BROWSER_MOUSE_DRAG_1,
  800.                                         gui_drag.x, gui_drag.y);
  801.                 } else {
  802.                         browser_window_mouse_click(gw->bw,
  803.                                         BROWSER_MOUSE_DRAG_2,
  804.                                         gui_drag.x, gui_drag.y);
  805.                 }
  806.                 gui_drag.grabbed_pointer = fbtk_tgrab_pointer(widget);
  807.                 gui_drag.state = GUI_DRAG_DRAG;
  808.         }
  809.  
  810.         if (gui_drag.state == GUI_DRAG_DRAG) {
  811.                 /* set up mouse state */
  812.                 mouse |= BROWSER_MOUSE_DRAG_ON;
  813.  
  814.                 if (gui_drag.button == 1)
  815.                         mouse |= BROWSER_MOUSE_HOLDING_1;
  816.                 else
  817.                         mouse |= BROWSER_MOUSE_HOLDING_2;
  818.         }
  819.  
  820.         browser_window_mouse_track(gw->bw, mouse, x, y);
  821.  
  822.         return 0;
  823. }
  824.  
  825.  
  826. static int
  827. fb_browser_window_input(fbtk_widget_t *widget, fbtk_callback_info *cbi)
  828. {
  829.         struct gui_window *gw = cbi->context;
  830.         static fbtk_modifier_type modifier = FBTK_MOD_CLEAR;
  831.         int ucs4 = -1;
  832.  
  833.         LOG(("got value %d", cbi->event->value.keycode));
  834.  
  835.         switch (cbi->event->type) {
  836.         case NSFB_EVENT_KEY_DOWN:
  837.                 switch (cbi->event->value.keycode) {
  838.  
  839.                 case NSFB_KEY_PAGEUP:
  840.                         if (browser_window_key_press(gw->bw,
  841.                                         KEY_PAGE_UP) == false)
  842.                                 widget_scroll_y(gw, -fbtk_get_height(
  843.                                                 gw->browser), false);
  844.                         break;
  845.  
  846.                 case NSFB_KEY_PAGEDOWN:
  847.                         if (browser_window_key_press(gw->bw,
  848.                                         KEY_PAGE_DOWN) == false)
  849.                                 widget_scroll_y(gw, fbtk_get_height(
  850.                                                 gw->browser), false);
  851.                         break;
  852.  
  853.                 case NSFB_KEY_RIGHT:
  854.                         if (modifier & FBTK_MOD_RCTRL ||
  855.                                         modifier & FBTK_MOD_LCTRL) {
  856.                                 /* CTRL held */
  857.                                 if (browser_window_key_press(gw->bw,
  858.                                                 KEY_LINE_END) == false)
  859.                                         widget_scroll_x(gw, INT_MAX, true);
  860.  
  861.                         } else if (modifier & FBTK_MOD_RSHIFT ||
  862.                                         modifier & FBTK_MOD_LSHIFT) {
  863.                                 /* SHIFT held */
  864.                                 if (browser_window_key_press(gw->bw,
  865.                                                 KEY_WORD_RIGHT) == false)
  866.                                         widget_scroll_x(gw, fbtk_get_width(
  867.                                                 gw->browser), false);
  868.  
  869.                         } else {
  870.                                 /* no modifier */
  871.                                 if (browser_window_key_press(gw->bw,
  872.                                                 KEY_RIGHT) == false)
  873.                                         widget_scroll_x(gw, 100, false);
  874.                         }
  875.                         break;
  876.  
  877.                 case NSFB_KEY_LEFT:
  878.                         if (modifier & FBTK_MOD_RCTRL ||
  879.                                         modifier & FBTK_MOD_LCTRL) {
  880.                                 /* CTRL held */
  881.                                 if (browser_window_key_press(gw->bw,
  882.                                                 KEY_LINE_START) == false)
  883.                                         widget_scroll_x(gw, 0, true);
  884.  
  885.                         } else if (modifier & FBTK_MOD_RSHIFT ||
  886.                                         modifier & FBTK_MOD_LSHIFT) {
  887.                                 /* SHIFT held */
  888.                                 if (browser_window_key_press(gw->bw,
  889.                                                 KEY_WORD_LEFT) == false)
  890.                                         widget_scroll_x(gw, -fbtk_get_width(
  891.                                                 gw->browser), false);
  892.  
  893.                         } else {
  894.                                 /* no modifier */
  895.                                 if (browser_window_key_press(gw->bw,
  896.                                                 KEY_LEFT) == false)
  897.                                         widget_scroll_x(gw, -100, false);
  898.                         }
  899.                         break;
  900.  
  901.                 case NSFB_KEY_UP:
  902.                         if (browser_window_key_press(gw->bw,
  903.                                         KEY_UP) == false)
  904.                                 widget_scroll_y(gw, -100, false);
  905.                         break;
  906.  
  907.                 case NSFB_KEY_DOWN:
  908.                         if (browser_window_key_press(gw->bw,
  909.                                         KEY_DOWN) == false)
  910.                                 widget_scroll_y(gw, 100, false);
  911.                         break;
  912.  
  913.                 case NSFB_KEY_RSHIFT:
  914.                         modifier |= FBTK_MOD_RSHIFT;
  915.                         break;
  916.  
  917.                 case NSFB_KEY_LSHIFT:
  918.                         modifier |= FBTK_MOD_LSHIFT;
  919.                         break;
  920.  
  921.                 case NSFB_KEY_RCTRL:
  922.                         modifier |= FBTK_MOD_RCTRL;
  923.                         break;
  924.  
  925.                 case NSFB_KEY_LCTRL:
  926.                         modifier |= FBTK_MOD_LCTRL;
  927.                         break;
  928.  
  929.                 default:
  930.                         ucs4 = fbtk_keycode_to_ucs4(cbi->event->value.keycode,
  931.                                                     modifier);
  932.                         if (ucs4 != -1)
  933.                                 browser_window_key_press(gw->bw, ucs4);
  934.                         break;
  935.                 }
  936.                 break;
  937.  
  938.         case NSFB_EVENT_KEY_UP:
  939.                 switch (cbi->event->value.keycode) {
  940.                 case NSFB_KEY_RSHIFT:
  941.                         modifier &= ~FBTK_MOD_RSHIFT;
  942.                         break;
  943.  
  944.                 case NSFB_KEY_LSHIFT:
  945.                         modifier &= ~FBTK_MOD_LSHIFT;
  946.                         break;
  947.  
  948.                 case NSFB_KEY_RCTRL:
  949.                         modifier &= ~FBTK_MOD_RCTRL;
  950.                         break;
  951.  
  952.                 case NSFB_KEY_LCTRL:
  953.                         modifier &= ~FBTK_MOD_LCTRL;
  954.                         break;
  955.  
  956.                 default:
  957.                         break;
  958.                 }
  959.                 break;
  960.  
  961.         default:
  962.                 break;
  963.         }
  964.  
  965.         return 0;
  966. }
  967.  
  968. static void
  969. fb_update_back_forward(struct gui_window *gw)
  970. {
  971.         struct browser_window *bw = gw->bw;
  972.  
  973.         fbtk_set_bitmap(gw->back,
  974.                         (browser_window_back_available(bw)) ?
  975.                         &left_arrow : &left_arrow_g);
  976.         fbtk_set_bitmap(gw->forward,
  977.                         (browser_window_forward_available(bw)) ?
  978.                         &right_arrow : &right_arrow_g);
  979. }
  980.  
  981. /* left icon click routine */
  982. static int
  983. fb_leftarrow_click(fbtk_widget_t *widget, fbtk_callback_info *cbi)
  984. {
  985.         struct gui_window *gw = cbi->context;
  986.         struct browser_window *bw = gw->bw;
  987.  
  988.         if (cbi->event->type != NSFB_EVENT_KEY_UP)
  989.                 return 0;
  990.  
  991.         if (history_back_available(bw->history))
  992.                 history_back(bw, bw->history);
  993.  
  994.         fb_update_back_forward(gw);
  995.  
  996.         return 1;
  997. }
  998.  
  999. /* right arrow icon click routine */
  1000. static int
  1001. fb_rightarrow_click(fbtk_widget_t *widget, fbtk_callback_info *cbi)
  1002. {
  1003.         struct gui_window *gw = cbi->context;
  1004.         struct browser_window *bw = gw->bw;
  1005.  
  1006.         if (cbi->event->type != NSFB_EVENT_KEY_UP)
  1007.                 return 0;
  1008.  
  1009.         if (history_forward_available(bw->history))
  1010.                 history_forward(bw, bw->history);
  1011.  
  1012.         fb_update_back_forward(gw);
  1013.         return 1;
  1014.  
  1015. }
  1016.  
  1017. /* reload icon click routine */
  1018. static int
  1019. fb_reload_click(fbtk_widget_t *widget, fbtk_callback_info *cbi)
  1020. {
  1021.         struct browser_window *bw = cbi->context;
  1022.  
  1023.         if (cbi->event->type != NSFB_EVENT_KEY_UP)
  1024.                 return 0;
  1025.  
  1026.         browser_window_reload(bw, true);
  1027.         return 1;
  1028. }
  1029.  
  1030. /* stop icon click routine */
  1031. static int
  1032. fb_stop_click(fbtk_widget_t *widget, fbtk_callback_info *cbi)
  1033. {
  1034.         struct browser_window *bw = cbi->context;
  1035.  
  1036.         if (cbi->event->type != NSFB_EVENT_KEY_UP)
  1037.                 return 0;
  1038.  
  1039.         browser_window_stop(bw);
  1040.         return 0;
  1041. }
  1042.  
  1043. static int
  1044. fb_osk_click(fbtk_widget_t *widget, fbtk_callback_info *cbi)
  1045. {
  1046.  
  1047.         if (cbi->event->type != NSFB_EVENT_KEY_UP)
  1048.                 return 0;
  1049.  
  1050.         map_osk();
  1051.  
  1052.         return 0;
  1053. }
  1054.  
  1055. /* close browser window icon click routine */
  1056. static int
  1057. fb_close_click(fbtk_widget_t *widget, fbtk_callback_info *cbi)
  1058. {
  1059.         if (cbi->event->type != NSFB_EVENT_KEY_UP)
  1060.                 return 0;
  1061.  
  1062.         netsurf_quit = true;
  1063.         return 0;
  1064. }
  1065.  
  1066. static int
  1067. fb_scroll_callback(fbtk_widget_t *widget, fbtk_callback_info *cbi)
  1068. {
  1069.         struct gui_window *gw = cbi->context;
  1070.  
  1071.         switch (cbi->type) {
  1072.         case FBTK_CBT_SCROLLY:
  1073.                 widget_scroll_y(gw, cbi->y, true);
  1074.                 break;
  1075.  
  1076.         case FBTK_CBT_SCROLLX:
  1077.                 widget_scroll_x(gw, cbi->x, true);
  1078.                 break;
  1079.  
  1080.         default:
  1081.                 break;
  1082.         }
  1083.         return 0;
  1084. }
  1085.  
  1086. static int
  1087. fb_url_enter(void *pw, char *text)
  1088. {
  1089.         struct browser_window *bw = pw;
  1090.         browser_window_go(bw, text, 0, true);
  1091.         return 0;
  1092. }
  1093.  
  1094. static int
  1095. fb_url_move(fbtk_widget_t *widget, fbtk_callback_info *cbi)
  1096. {
  1097.         framebuffer_set_cursor(&caret_image);
  1098.         return 0;
  1099. }
  1100.  
  1101. static int
  1102. set_ptr_default_move(fbtk_widget_t *widget, fbtk_callback_info *cbi)
  1103. {
  1104.         framebuffer_set_cursor(&pointer_image);
  1105.         return 0;
  1106. }
  1107.  
  1108. static int
  1109. fb_localhistory_btn_clik(fbtk_widget_t *widget, fbtk_callback_info *cbi)
  1110. {
  1111.         struct gui_window *gw = cbi->context;
  1112.  
  1113.         if (cbi->event->type != NSFB_EVENT_KEY_UP)
  1114.                 return 0;
  1115.  
  1116.         fb_localhistory_map(gw->localhistory);
  1117.  
  1118.         return 0;
  1119. }
  1120.  
  1121.  
  1122. /** Create a toolbar window and populate it with buttons.
  1123.  *
  1124.  * The toolbar layout uses a character to define buttons type and position:
  1125.  * b - back
  1126.  * l - local history
  1127.  * f - forward
  1128.  * s - stop
  1129.  * r - refresh
  1130.  * u - url bar expands to fit remaining space
  1131.  * t - throbber/activity indicator
  1132.  * c - close the current window
  1133.  *
  1134.  * The default layout is "blfsrut" there should be no more than a
  1135.  * single url bar entry or behaviour will be undefined.
  1136.  *
  1137.  * @param gw Parent window
  1138.  * @param toolbar_height The height in pixels of the toolbar
  1139.  * @param padding The padding in pixels round each element of the toolbar
  1140.  * @param frame_col Frame colour.
  1141.  * @param toolbar_layout A string defining which buttons and controls
  1142.  *                       should be added to the toolbar. May be empty
  1143.  *                       string to disable the bar..
  1144.  *
  1145.  */
  1146. static fbtk_widget_t *
  1147. create_toolbar(struct gui_window *gw,
  1148.                int toolbar_height,
  1149.                int padding,
  1150.                colour frame_col,
  1151.                const char *toolbar_layout)
  1152. {
  1153.         fbtk_widget_t *toolbar;
  1154.         fbtk_widget_t *widget;
  1155.  
  1156.         int xpos; /* The position of the next widget. */
  1157.         int xlhs = 0; /* extent of the left hand side widgets */
  1158.         int xdir = 1; /* the direction of movement + or - 1 */
  1159.         const char *itmtype; /* type of the next item */
  1160.  
  1161.         if (toolbar_layout == NULL) {
  1162.                 toolbar_layout = NSFB_TOOLBAR_DEFAULT_LAYOUT;
  1163.         }
  1164.  
  1165.         LOG(("Using toolbar layout %s", toolbar_layout));
  1166.  
  1167.         itmtype = toolbar_layout;
  1168.  
  1169.         if (*itmtype == 0) {
  1170.                 return NULL;
  1171.         }
  1172.  
  1173.         toolbar = fbtk_create_window(gw->window, 0, 0, 0,
  1174.                                      toolbar_height,
  1175.                                      frame_col);
  1176.  
  1177.         if (toolbar == NULL) {
  1178.                 return NULL;
  1179.         }
  1180.  
  1181.         fbtk_set_handler(toolbar,
  1182.                          FBTK_CBT_POINTERENTER,
  1183.                          set_ptr_default_move,
  1184.                          NULL);
  1185.  
  1186.  
  1187.         xpos = padding;
  1188.  
  1189.         /* loop proceeds creating widget on the left hand side until
  1190.          * it runs out of layout or encounters a url bar declaration
  1191.          * wherupon it works backwards from the end of the layout
  1192.          * untill the space left is for the url bar
  1193.          */
  1194.         while ((itmtype >= toolbar_layout) &&
  1195.                (*itmtype != 0) &&
  1196.                (xdir !=0)) {
  1197.  
  1198.                 LOG(("toolbar adding %c", *itmtype));
  1199.  
  1200.  
  1201.                 switch (*itmtype) {
  1202.  
  1203.                 case 'b': /* back */
  1204.                         widget = fbtk_create_button(toolbar,
  1205.                                                     (xdir == 1) ? xpos :
  1206.                                                      xpos - left_arrow.width,
  1207.                                                     padding,
  1208.                                                     left_arrow.width,
  1209.                                                     -padding,
  1210.                                                     frame_col,
  1211.                                                     &left_arrow,
  1212.                                                     fb_leftarrow_click,
  1213.                                                     gw);
  1214.                         gw->back = widget; /* keep reference */
  1215.                         break;
  1216.  
  1217.                 case 'l': /* local history */
  1218.                         widget = fbtk_create_button(toolbar,
  1219.                                                     (xdir == 1) ? xpos :
  1220.                                                      xpos - history_image.width,
  1221.                                                     padding,
  1222.                                                     history_image.width,
  1223.                                                     -padding,
  1224.                                                     frame_col,
  1225.                                                     &history_image,
  1226.                                                     fb_localhistory_btn_clik,
  1227.                                                     gw);
  1228.                         break;
  1229.  
  1230.                 case 'f': /* forward */
  1231.                         widget = fbtk_create_button(toolbar,
  1232.                                                     (xdir == 1)?xpos :
  1233.                                                      xpos - right_arrow.width,
  1234.                                                     padding,
  1235.                                                     right_arrow.width,
  1236.                                                     -padding,
  1237.                                                     frame_col,
  1238.                                                     &right_arrow,
  1239.                                                     fb_rightarrow_click,
  1240.                                                     gw);
  1241.                         gw->forward = widget;
  1242.                         break;
  1243.  
  1244.                 case 'c': /* close the current window */
  1245.                         widget = fbtk_create_button(toolbar,
  1246.                                                     (xdir == 1)?xpos :
  1247.                                                      xpos - stop_image_g.width,
  1248.                                                     padding,
  1249.                                                     stop_image_g.width,
  1250.                                                     -padding,
  1251.                                                     frame_col,
  1252.                                                     &stop_image_g,
  1253.                                                     fb_close_click,
  1254.                                                     gw->bw);
  1255.                         break;
  1256.  
  1257.                 case 's': /* stop  */
  1258.                         widget = fbtk_create_button(toolbar,
  1259.                                                     (xdir == 1)?xpos :
  1260.                                                      xpos - stop_image.width,
  1261.                                                     padding,
  1262.                                                     stop_image.width,
  1263.                                                     -padding,
  1264.                                                     frame_col,
  1265.                                                     &stop_image,
  1266.                                                     fb_stop_click,
  1267.                                                     gw->bw);
  1268.                         break;
  1269.  
  1270.                 case 'r': /* reload */
  1271.                         widget = fbtk_create_button(toolbar,
  1272.                                                     (xdir == 1)?xpos :
  1273.                                                      xpos - reload.width,
  1274.                                                     padding,
  1275.                                                     reload.width,
  1276.                                                     -padding,
  1277.                                                     frame_col,
  1278.                                                     &reload,
  1279.                                                     fb_reload_click,
  1280.                                                     gw->bw);
  1281.                         break;
  1282.  
  1283.                 case 't': /* throbber/activity indicator */
  1284.                         widget = fbtk_create_bitmap(toolbar,
  1285.                                                     (xdir == 1)?xpos :
  1286.                                                      xpos - throbber0.width,
  1287.                                                     padding,
  1288.                                                     throbber0.width,
  1289.                                                     -padding,
  1290.                                                     frame_col,
  1291.                                                     &throbber0);
  1292.                         gw->throbber = widget;
  1293.                         break;
  1294.  
  1295.  
  1296.                 case 'u': /* url bar*/
  1297.                         if (xdir == -1) {
  1298.                                 /* met the u going backwards add url
  1299.                                  * now we know available extent
  1300.                                  */
  1301.  
  1302.                                 widget = fbtk_create_writable_text(toolbar,
  1303.                                                    xlhs,
  1304.                                                    padding,
  1305.                                                    xpos - xlhs,
  1306.                                                    -padding,
  1307.                                                    FB_COLOUR_WHITE,
  1308.                                                    FB_COLOUR_BLACK,
  1309.                                                    true,
  1310.                                                    fb_url_enter,
  1311.                                                    gw->bw);
  1312.  
  1313.                                 fbtk_set_handler(widget,
  1314.                                                  FBTK_CBT_POINTERENTER,
  1315.                                                  fb_url_move, gw->bw);
  1316.  
  1317.                                 gw->url = widget; /* keep reference */
  1318.  
  1319.                                 /* toolbar is complete */
  1320.                                 xdir = 0;
  1321.                                 break;
  1322.                         }
  1323.                         /* met url going forwards, note position and
  1324.                          * reverse direction
  1325.                          */
  1326.                         itmtype = toolbar_layout + strlen(toolbar_layout);
  1327.                         xdir = -1;
  1328.                         xlhs = xpos;
  1329.                         xpos = (2 * fbtk_get_width(toolbar));
  1330.                         widget = toolbar;
  1331.                         break;
  1332.  
  1333.                 default:
  1334.                         widget = NULL;
  1335.                         xdir = 0;
  1336.                         LOG(("Unknown element %c in toolbar layout", *itmtype));
  1337.                         break;
  1338.  
  1339.                 }
  1340.  
  1341.                 if (widget != NULL) {
  1342.                         xpos += (xdir * (fbtk_get_width(widget) + padding));
  1343.                 }
  1344.  
  1345.                 LOG(("xpos is %d",xpos));
  1346.  
  1347.                 itmtype += xdir;
  1348.         }
  1349.  
  1350.         fbtk_set_mapping(toolbar, true);
  1351.  
  1352.         return toolbar;
  1353. }
  1354.  
  1355. /** Routine called when "stripped of focus" event occours for browser widget.
  1356.  *
  1357.  * @param widget The widget reciving "stripped of focus" event.
  1358.  * @param cbi The callback parameters.
  1359.  * @return The callback result.
  1360.  */
  1361. static int
  1362. fb_browser_window_strip_focus(fbtk_widget_t *widget, fbtk_callback_info *cbi)
  1363. {
  1364.         fbtk_set_caret(widget, false, 0, 0, 0, NULL);
  1365.  
  1366.         return 0;
  1367. }
  1368.  
  1369. static void
  1370. create_browser_widget(struct gui_window *gw, int toolbar_height, int furniture_width)
  1371. {
  1372.         struct browser_widget_s *browser_widget;
  1373.         browser_widget = calloc(1, sizeof(struct browser_widget_s));
  1374.  
  1375.         gw->browser = fbtk_create_user(gw->window,
  1376.                                        0,
  1377.                                        toolbar_height,
  1378.                                        -furniture_width,
  1379.                                        -furniture_width,
  1380.                                        browser_widget);
  1381.  
  1382.         fbtk_set_handler(gw->browser, FBTK_CBT_REDRAW, fb_browser_window_redraw, gw);
  1383.         fbtk_set_handler(gw->browser, FBTK_CBT_INPUT, fb_browser_window_input, gw);
  1384.         fbtk_set_handler(gw->browser, FBTK_CBT_CLICK, fb_browser_window_click, gw);
  1385.         fbtk_set_handler(gw->browser, FBTK_CBT_STRIP_FOCUS, fb_browser_window_strip_focus, gw);
  1386.         fbtk_set_handler(gw->browser, FBTK_CBT_POINTERMOVE, fb_browser_window_move, gw);
  1387. }
  1388.  
  1389. static void
  1390. create_normal_browser_window(struct gui_window *gw, int furniture_width)
  1391. {
  1392.         LOG(("enter norm win"));
  1393.         fbtk_widget_t *widget;
  1394.         fbtk_widget_t *toolbar;
  1395.         int statusbar_width = 0;
  1396.         int toolbar_height = 30; //nsoption_int(fb_toolbar_size);
  1397.  
  1398.         LOG(("Normal window"));
  1399.  
  1400.         gw->window = fbtk_create_window(fbtk, 0, 0, 0, 0, 0);
  1401.  
  1402.         statusbar_width = nsoption_int(toolbar_status_width) *
  1403.                 fbtk_get_width(gw->window) / 10000;
  1404.  
  1405. LOG(("STUB options"));
  1406.  
  1407.                  
  1408.                          
  1409.         nsoptions.fb_depth = 16;                                       
  1410.         nsoptions.fb_refresh = 70;                             
  1411.         nsoptions.fb_device = NULL;                            
  1412.         nsoptions.fb_input_devpath = NULL;                     
  1413.         nsoptions.fb_input_glob = NULL;                        
  1414.         nsoptions.fb_furniture_size = 18;                      
  1415.         nsoptions.fb_toolbar_size = 30;                        
  1416.         nsoptions.fb_toolbar_layout = NULL;                            
  1417.         nsoptions.fb_osk = false;                              
  1418.  
  1419.  
  1420.  
  1421.         /* toolbar */
  1422.         LOG(("toolbar"));
  1423.        
  1424.        
  1425.        
  1426.         toolbar = create_toolbar(gw,
  1427.                                  toolbar_height,
  1428.                                  2,
  1429.                                  FB_FRAME_COLOUR,
  1430.                                  nsoption_charp(fb_toolbar_layout));
  1431.  
  1432.         /* set the actually created toolbar height */
  1433.         if (toolbar != NULL) {
  1434.                 toolbar_height = fbtk_get_height(toolbar);
  1435.         } else {
  1436.                 toolbar_height = 0;
  1437.         }
  1438.  
  1439.         LOG(("statbar"));
  1440.         /* status bar */
  1441.         gw->status = fbtk_create_text(gw->window,
  1442.                                       0,
  1443.                                       fbtk_get_height(gw->window) - furniture_width,
  1444.                                       statusbar_width, furniture_width,
  1445.                                       FB_FRAME_COLOUR, FB_COLOUR_BLACK,
  1446.                                       false);
  1447.        
  1448.         LOG(("handler"));
  1449.         fbtk_set_handler(gw->status, FBTK_CBT_POINTERENTER, set_ptr_default_move, NULL);
  1450.  
  1451.         LOG(("status bar %p at %d,%d", gw->status, fbtk_get_absx(gw->status), fbtk_get_absy(gw->status)));
  1452.  
  1453.         /* create horizontal scrollbar */
  1454.         LOG(("hor sb"));
  1455.        
  1456.         gw->hscroll = fbtk_create_hscroll(gw->window,
  1457.                                           statusbar_width,
  1458.                                           fbtk_get_height(gw->window) - furniture_width,
  1459.                                           fbtk_get_width(gw->window) - statusbar_width - furniture_width,
  1460.                                           furniture_width,
  1461.                                           FB_SCROLL_COLOUR,
  1462.                                           FB_FRAME_COLOUR,
  1463.                                           fb_scroll_callback,
  1464.                                           gw);
  1465.  
  1466.         /* fill bottom right area */
  1467.         LOG(("fill bottom"));
  1468.  
  1469.         if (nsoption_bool(fb_osk) == true) {
  1470.                 widget = fbtk_create_text_button(gw->window,
  1471.                                                  fbtk_get_width(gw->window) - furniture_width,
  1472.                                                  fbtk_get_height(gw->window) - furniture_width,
  1473.                                                  furniture_width,
  1474.                                                  furniture_width,
  1475.                                                  FB_FRAME_COLOUR, FB_COLOUR_BLACK,
  1476.                                                  fb_osk_click,
  1477.                                                  NULL);
  1478.                 widget = fbtk_create_button(gw->window,
  1479.                                 fbtk_get_width(gw->window) - furniture_width,
  1480.                                 fbtk_get_height(gw->window) - furniture_width,
  1481.                                 furniture_width,
  1482.                                 furniture_width,
  1483.                                 FB_FRAME_COLOUR,
  1484.                                 &osk_image,
  1485.                                 fb_osk_click,
  1486.                                 NULL);
  1487.         } else {
  1488.                 widget = fbtk_create_fill(gw->window,
  1489.                                           fbtk_get_width(gw->window) - furniture_width,
  1490.                                           fbtk_get_height(gw->window) - furniture_width,
  1491.                                           furniture_width,
  1492.                                           furniture_width,
  1493.                                           FB_FRAME_COLOUR);
  1494.  
  1495.                 fbtk_set_handler(widget, FBTK_CBT_POINTERENTER, set_ptr_default_move, NULL);
  1496.         }
  1497.  
  1498.         LOG(("vsb GUI"));
  1499.         /* create vertical scrollbar */
  1500.         gw->vscroll = fbtk_create_vscroll(gw->window,
  1501.                                           fbtk_get_width(gw->window) - furniture_width,
  1502.                                           toolbar_height,
  1503.                                           furniture_width,
  1504.                                           fbtk_get_height(gw->window) - toolbar_height - furniture_width,
  1505.                                           FB_SCROLL_COLOUR,
  1506.                                           FB_FRAME_COLOUR,
  1507.                                           fb_scroll_callback,
  1508.                                           gw);
  1509.  
  1510.         LOG(("BRO widget"));
  1511.         /* browser widget */
  1512.         create_browser_widget(gw, toolbar_height, nsoption_int(fb_furniture_size));
  1513.  
  1514.         LOG(("set focus"));
  1515.         /* Give browser_window's user widget input focus */
  1516.         fbtk_set_focus(gw->browser);
  1517.         LOG(("GUI OK"));
  1518. }
  1519.  
  1520.  
  1521. struct gui_window *
  1522. gui_create_browser_window(struct browser_window *bw,
  1523.                           struct browser_window *clone,
  1524.                           bool new_tab)
  1525. {
  1526.         struct gui_window *gw;
  1527.         LOG(("GCBW calloc"));
  1528.        
  1529.         gw = calloc(1, sizeof(struct gui_window));
  1530.  
  1531.         if (gw == NULL)
  1532.                 return NULL;
  1533.  
  1534.         /* seems we need to associate the gui window with the underlying
  1535.          * browser window
  1536.          */
  1537.         LOG(("GCBW next.."));
  1538.        
  1539.        
  1540.         gw->bw = bw;
  1541.  
  1542.         LOG(("fb_furn_size is STUB now!..."));
  1543.        
  1544.          //nsoption_int(fb_furniture_size);
  1545.         LOG(("GCBW create normal window..."));
  1546.        
  1547.        
  1548.         create_normal_browser_window(gw, 18); //nsoption_int(fb_furniture_size));
  1549.         LOG(("GCBW create local history..."));
  1550.        
  1551.         gw->localhistory = fb_create_localhistory(bw, fbtk, nsoption_int(fb_furniture_size));
  1552.  
  1553.         /* map and request redraw of gui window */
  1554.         LOG(("GCBW set mapping"));
  1555.        
  1556.         fbtk_set_mapping(gw->window, true);
  1557.         LOG(("GCBW OK!"));
  1558.        
  1559.  
  1560.         return gw;
  1561. }
  1562.  
  1563. void
  1564. gui_window_destroy(struct gui_window *gw)
  1565. {
  1566.         fbtk_destroy_widget(gw->window);
  1567.  
  1568.         free(gw);
  1569.  
  1570.  
  1571. }
  1572.  
  1573. void
  1574. gui_window_set_title(struct gui_window *g, const char *title)
  1575. {
  1576.         LOG(("%p, %s", g, title));
  1577. }
  1578.  
  1579. void
  1580. gui_window_redraw_window(struct gui_window *g)
  1581. {
  1582.         fb_queue_redraw(g->browser, 0, 0, fbtk_get_width(g->browser), fbtk_get_height(g->browser) );
  1583. }
  1584.  
  1585. void
  1586. gui_window_update_box(struct gui_window *g, const struct rect *rect)
  1587. {
  1588.         struct browser_widget_s *bwidget = fbtk_get_userpw(g->browser);
  1589.         fb_queue_redraw(g->browser,
  1590.                         rect->x0 - bwidget->scrollx,
  1591.                         rect->y0 - bwidget->scrolly,
  1592.                         rect->x1 - bwidget->scrollx,
  1593.                         rect->y1 - bwidget->scrolly);
  1594. }
  1595.  
  1596. bool
  1597. gui_window_get_scroll(struct gui_window *g, int *sx, int *sy)
  1598. {
  1599.         struct browser_widget_s *bwidget = fbtk_get_userpw(g->browser);
  1600.  
  1601.         *sx = bwidget->scrollx / g->bw->scale;
  1602.         *sy = bwidget->scrolly / g->bw->scale;
  1603.  
  1604.         return true;
  1605. }
  1606.  
  1607. void
  1608. gui_window_set_scroll(struct gui_window *gw, int sx, int sy)
  1609. {
  1610.         struct browser_widget_s *bwidget = fbtk_get_userpw(gw->browser);
  1611.  
  1612.         assert(bwidget);
  1613.  
  1614.         widget_scroll_x(gw, sx * gw->bw->scale, true);
  1615.         widget_scroll_y(gw, sy * gw->bw->scale, true);
  1616. }
  1617.  
  1618. void
  1619. gui_window_scroll_visible(struct gui_window *g, int x0, int y0,
  1620.                           int x1, int y1)
  1621. {
  1622.         LOG(("%s:(%p, %d, %d, %d, %d)", __func__, g, x0, y0, x1, y1));
  1623. }
  1624.  
  1625. void
  1626. gui_window_get_dimensions(struct gui_window *g,
  1627.                           int *width,
  1628.                           int *height,
  1629.                           bool scaled)
  1630. {
  1631.         *width = fbtk_get_width(g->browser);
  1632.         *height = fbtk_get_height(g->browser);
  1633.  
  1634.         if (scaled) {
  1635.                 *width /= g->bw->scale;
  1636.                 *height /= g->bw->scale;
  1637.         }
  1638. }
  1639.  
  1640. void
  1641. gui_window_update_extent(struct gui_window *gw)
  1642. {
  1643.         float scale = gw->bw->scale;
  1644.  
  1645.         fbtk_set_scroll_parameters(gw->hscroll, 0,
  1646.                         content_get_width(gw->bw->current_content) * scale,
  1647.                         fbtk_get_width(gw->browser), 100);
  1648.  
  1649.         fbtk_set_scroll_parameters(gw->vscroll, 0,
  1650.                         content_get_height(gw->bw->current_content) * scale,
  1651.                         fbtk_get_height(gw->browser), 100);
  1652. }
  1653.  
  1654. void
  1655. gui_window_set_status(struct gui_window *g, const char *text)
  1656. {
  1657.         fbtk_set_text(g->status, text);
  1658. }
  1659.  
  1660. void
  1661. gui_window_set_pointer(struct gui_window *g, gui_pointer_shape shape)
  1662. {
  1663.         switch (shape) {
  1664.         case GUI_POINTER_POINT:
  1665.                 framebuffer_set_cursor(&hand_image);
  1666.                 break;
  1667.  
  1668.         case GUI_POINTER_CARET:
  1669.                 framebuffer_set_cursor(&caret_image);
  1670.                 break;
  1671.  
  1672.         case GUI_POINTER_MENU:
  1673.                 framebuffer_set_cursor(&menu_image);
  1674.                 break;
  1675.  
  1676.         case GUI_POINTER_PROGRESS:
  1677.                 framebuffer_set_cursor(&progress_image);
  1678.                 break;
  1679.  
  1680.         case GUI_POINTER_MOVE:
  1681.                 framebuffer_set_cursor(&move_image);
  1682.                 break;
  1683.  
  1684.         default:
  1685.                 framebuffer_set_cursor(&pointer_image);
  1686.                 break;
  1687.         }
  1688. }
  1689.  
  1690. void
  1691. gui_window_hide_pointer(struct gui_window *g)
  1692. {
  1693. }
  1694.  
  1695. void
  1696. gui_window_set_url(struct gui_window *g, const char *url)
  1697. {
  1698.         fbtk_set_text(g->url, url);
  1699. }
  1700.  
  1701. static void
  1702. throbber_advance(void *pw)
  1703. {
  1704.         struct gui_window *g = pw;
  1705.         struct fbtk_bitmap *image;
  1706.  
  1707.         switch (g->throbber_index) {
  1708.         case 0:
  1709.                 image = &throbber1;
  1710.                 g->throbber_index = 1;
  1711.                 break;
  1712.  
  1713.         case 1:
  1714.                 image = &throbber2;
  1715.                 g->throbber_index = 2;
  1716.                 break;
  1717.  
  1718.         case 2:
  1719.                 image = &throbber3;
  1720.                 g->throbber_index = 3;
  1721.                 break;
  1722.  
  1723.         case 3:
  1724.                 image = &throbber4;
  1725.                 g->throbber_index = 4;
  1726.                 break;
  1727.  
  1728.         case 4:
  1729.                 image = &throbber5;
  1730.                 g->throbber_index = 5;
  1731.                 break;
  1732.  
  1733.         case 5:
  1734.                 image = &throbber6;
  1735.                 g->throbber_index = 6;
  1736.                 break;
  1737.  
  1738.         case 6:
  1739.                 image = &throbber7;
  1740.                 g->throbber_index = 7;
  1741.                 break;
  1742.  
  1743.         case 7:
  1744.                 image = &throbber8;
  1745.                 g->throbber_index = 0;
  1746.                 break;
  1747.  
  1748.         default:
  1749.                 return;
  1750.         }
  1751.  
  1752.         if (g->throbber_index >= 0) {
  1753.                 fbtk_set_bitmap(g->throbber, image);
  1754.                 schedule(10, throbber_advance, g);
  1755.         }
  1756. }
  1757.  
  1758. void
  1759. gui_window_start_throbber(struct gui_window *g)
  1760. {
  1761.         g->throbber_index = 0;
  1762.         schedule(10, throbber_advance, g);
  1763. }
  1764.  
  1765. void
  1766. gui_window_stop_throbber(struct gui_window *gw)
  1767. {
  1768.         gw->throbber_index = -1;
  1769.         fbtk_set_bitmap(gw->throbber, &throbber0);
  1770.  
  1771.         fb_update_back_forward(gw);
  1772.  
  1773. }
  1774.  
  1775. static void
  1776. gui_window_remove_caret_cb(fbtk_widget_t *widget)
  1777. {
  1778.         struct browser_widget_s *bwidget = fbtk_get_userpw(widget);
  1779.         int c_x, c_y, c_h;
  1780.  
  1781.         if (fbtk_get_caret(widget, &c_x, &c_y, &c_h)) {
  1782.                 /* browser window already had caret:
  1783.                  * redraw its area to remove it first */
  1784.                 fb_queue_redraw(widget,
  1785.                                 c_x - bwidget->scrollx,
  1786.                                 c_y - bwidget->scrolly,
  1787.                                 c_x + 1 - bwidget->scrollx,
  1788.                                 c_y + c_h - bwidget->scrolly);
  1789.         }
  1790. }
  1791.  
  1792. void
  1793. gui_window_place_caret(struct gui_window *g, int x, int y, int height)
  1794. {
  1795.         struct browser_widget_s *bwidget = fbtk_get_userpw(g->browser);
  1796.  
  1797.         /* set new pos */
  1798.         fbtk_set_caret(g->browser, true, x, y, height,
  1799.                         gui_window_remove_caret_cb);
  1800.  
  1801.         /* redraw new caret pos */
  1802.         fb_queue_redraw(g->browser,
  1803.                         x - bwidget->scrollx,
  1804.                         y - bwidget->scrolly,
  1805.                         x + 1 - bwidget->scrollx,
  1806.                         y + height - bwidget->scrolly);
  1807. }
  1808.  
  1809. void
  1810. gui_window_remove_caret(struct gui_window *g)
  1811. {
  1812.         int c_x, c_y, c_h;
  1813.  
  1814.         if (fbtk_get_caret(g->browser, &c_x, &c_y, &c_h)) {
  1815.                 /* browser window owns the caret, so can remove it */
  1816.                 fbtk_set_caret(g->browser, false, 0, 0, 0, NULL);
  1817.         }
  1818. }
  1819.  
  1820. void
  1821. gui_window_new_content(struct gui_window *g)
  1822. {
  1823. }
  1824.  
  1825. bool
  1826. gui_window_scroll_start(struct gui_window *g)
  1827. {
  1828.         return true;
  1829. }
  1830.  
  1831. bool
  1832. gui_window_drag_start(struct gui_window *g, gui_drag_type type,
  1833.                       const struct rect *rect)
  1834. {
  1835.         return true;
  1836. }
  1837.  
  1838. void
  1839. gui_window_save_link(struct gui_window *g, const char *url, const char *title)
  1840. {
  1841. }
  1842.  
  1843. /**
  1844.  * set favicon
  1845.  */
  1846. void
  1847. gui_window_set_icon(struct gui_window *g, hlcache_handle *icon)
  1848. {
  1849. }
  1850.  
  1851. /**
  1852.  * set gui display of a retrieved favicon representing the search provider
  1853.  * \param ico may be NULL for local calls; then access current cache from
  1854.  * search_web_ico()
  1855.  */
  1856. void
  1857. gui_window_set_search_ico(hlcache_handle *ico)
  1858. {
  1859. }
  1860.  
  1861. struct gui_download_window *
  1862. gui_download_window_create(download_context *ctx, struct gui_window *parent)
  1863. {
  1864.         return NULL;
  1865. }
  1866.  
  1867. nserror
  1868. gui_download_window_data(struct gui_download_window *dw,
  1869.                          const char *data,
  1870.                          unsigned int size)
  1871. {
  1872.         return NSERROR_OK;
  1873. }
  1874.  
  1875. void
  1876. gui_download_window_error(struct gui_download_window *dw,
  1877.                           const char *error_msg)
  1878. {
  1879. }
  1880.  
  1881. void
  1882. gui_download_window_done(struct gui_download_window *dw)
  1883. {
  1884. }
  1885.  
  1886. void
  1887. gui_drag_save_object(gui_save_type type,
  1888.                      hlcache_handle *c,
  1889.                      struct gui_window *w)
  1890. {
  1891. }
  1892.  
  1893. void
  1894. gui_drag_save_selection(struct selection *s, struct gui_window *g)
  1895. {
  1896. }
  1897.  
  1898. void
  1899. gui_start_selection(struct gui_window *g)
  1900. {
  1901. }
  1902.  
  1903. void
  1904. gui_clear_selection(struct gui_window *g)
  1905. {
  1906. }
  1907.  
  1908. void
  1909. gui_create_form_select_menu(struct browser_window *bw,
  1910.                             struct form_control *control)
  1911. {
  1912. }
  1913.  
  1914. void
  1915. gui_launch_url(const char *url)
  1916. {
  1917. }
  1918.  
  1919. void
  1920. gui_cert_verify(nsurl *url,
  1921.                 const struct ssl_cert_info *certs,
  1922.                 unsigned long num,
  1923.                 nserror (*cb)(bool proceed, void *pw),
  1924.                 void *cbpw)
  1925. {
  1926.         cb(false, cbpw);
  1927. }
  1928.  
  1929. /*
  1930.  * Local Variables:
  1931.  * c-basic-offset:8
  1932.  * End:
  1933.  */
  1934.