home *** CD-ROM | disk | FTP | other *** search
/ vim.ftp.fu-berlin.de / 2015-02-03.vim.ftp.fu-berlin.de.tar / vim.ftp.fu-berlin.de / unreleased / patches / 5.6a.018 < prev    next >
Encoding:
Internet Message Format  |  2000-01-07  |  180.2 KB

  1. To: vim-dev@vim.org
  2. Subject: Patch 5.6a.018
  3. Fcc: outbox
  4. From: Bram Moolenaar <Bram@moolenaar.net>
  5. ------------
  6.  
  7. Note: I received a number of fixes for the GTK version from Marcin Dalecki.  I
  8. found these important enough to include.  But since this is more than a small
  9. change, I'll give this another week before releasing 5.6.  A few functions
  10. were moved, which made patch quite big, even though not that much really
  11. changed.
  12.  
  13.  
  14. Patch 5.6a.018
  15. Problem:    GTK GUI: submenu priority doesn't work.
  16.         Help dialog could be destroyed too soon.
  17.         When closing a dialog window (e.g. the "ATTENTION" one), Vim would
  18.         just hang.
  19.         When GTK theme is changed, Vim doesn't adjust to the new colors.
  20.         Argument for ":promptfind" isn't used.
  21. Solution:   Fixed the mentioned problems.
  22.         Made the dialogs look&feel nicer.
  23.         Moved functions to avoid the need for a forward declaration.
  24.         Fixed reentrancy of the file browser dialog.
  25.         Added drag&drop support for GNOME.
  26.         Init the text for the Find/replace dialog from the last used
  27.         search string.  Set "match whole word" toggle button correctly.
  28.         Made repeat rate for drag outside of window depend on the
  29.         distance from the window.  (Marcin Dalecki)
  30.         Made the drag in Visual mode actually work.
  31.         Removed recursiveness protection from gui_mch_get_rgb(), it might
  32.         cause more trouble than it solves.
  33. Files:        src/ex_docmd.c, src/gui_gtk.c, src/gui_gtk_x11.c, src/ui.c,
  34.         src/proto/ui.pro, src/misc2.c
  35.  
  36.  
  37. *** ../vim-5.6a.17/src/ex_docmd.c    Wed Dec 29 12:11:01 1999
  38. --- src/ex_docmd.c    Sat Jan  8 13:45:47 2000
  39. ***************
  40. *** 5941,5947 ****
  41.       }
  42.   }
  43.   
  44. ! #if defined(USE_GUI_MSWIN) || defined(USE_GUI_BEOS) || defined(macintosh) || defined(PROTO)
  45.   /*
  46.    * Handle a file drop. The code is here because a drop is *nearly* like an
  47.    * :args command, but not quite (we have a list of exact filenames, so we
  48. --- 5941,5948 ----
  49.       }
  50.   }
  51.   
  52. ! #if defined(USE_GUI_MSWIN) || defined(USE_GUI_BEOS) || defined(macintosh) \
  53. !     || defined(USE_GUI_GTK) || defined(PROTO)
  54.   /*
  55.    * Handle a file drop. The code is here because a drop is *nearly* like an
  56.    * :args command, but not quite (we have a list of exact filenames, so we
  57. ***************
  58. *** 5949,5958 ****
  59.    * code is very similar to :args and hence needs access to a lot of the static
  60.    * functions in this file.
  61.    *
  62. -  * Arguments:
  63. -  *    FILEC => the number of files dropped
  64. -  *    FILEV => the list of files dropped
  65. -  *
  66.    * The list should be allocated using vim_alloc(), as should each item in the
  67.    * list. This function takes over responsibility for freeing the list.
  68.    *
  69. --- 5950,5955 ----
  70. ***************
  71. *** 5966,5973 ****
  72.   
  73.       void
  74.   handle_drop(filec, filev, split)
  75. !     int        filec;
  76. !     char_u    **filev;
  77.       int        split;        /* force splitting the window */
  78.   {
  79.       EXARG    ea;
  80. --- 5963,5970 ----
  81.   
  82.       void
  83.   handle_drop(filec, filev, split)
  84. !     int        filec;        /* the number of files dropped */
  85. !     char_u    **filev;    /* the list of files dropped */
  86.       int        split;        /* force splitting the window */
  87.   {
  88.       EXARG    ea;
  89. *** ../vim-5.6a.17/src/gui_gtk.c    Mon Dec 20 09:59:10 1999
  90. --- src/gui_gtk.c    Sat Jan  8 21:11:02 2000
  91. ***************
  92. *** 19,24 ****
  93. --- 19,29 ----
  94.    *    :-) <dalecki@cs.net.pl> (My native language is polish and I speak
  95.    *    native grade german too. I'm living in GĂ·ttingen.de.)
  96.    *    --mdcki"
  97. +  *
  98. +  *
  99. +  * Although some #ifdefs suggest that GTK 1.0 is supported, it isn't.  The
  100. +  * code requires GTK version 1.1.16 or later.  Stuff for older versions will
  101. +  * be removed some time.
  102.    */
  103.   
  104.   #include "gui_gtk_f.h"
  105. ***************
  106. *** 92,115 ****
  107.   #define FR_REPLACE    4
  108.   #define FR_REPLACEALL    5
  109.   
  110. - #if defined(USE_BROWSE) || defined(PROTO)
  111. - static void browse_ok_cb(GtkWidget * widget, gpointer cbdata);
  112. - static void browse_cancel_cb(GtkWidget * widget, gpointer cbdata);
  113. - static gboolean browse_destroy_cb(GtkWidget * widget);
  114. - #endif
  115. - #ifdef GUI_DIALOG
  116. - static void butproc(GtkWidget * widget, gpointer data);
  117. - #endif
  118.   static void entry_activate_cb(GtkWidget *widget, GtkWidget *with);
  119.   static void entry_changed_cb(GtkWidget *entry, GtkWidget *dialog);
  120.   static void find_direction_cb(GtkWidget *widget, gpointer data);
  121. ! static void find_replace_cb(GtkWidget *widget, gint flags);
  122.   static void exact_match_cb(GtkWidget *widget, gpointer data);
  123.   static void repl_dir_cb(GtkWidget * widget, gpointer data);
  124. - static void find_replace_dialog_create(int do_replace);
  125.   
  126.   #ifdef USE_TOOLBAR
  127.   static void get_pixmap(char *menuname, GdkPixmap **pixmap, GdkBitmap **mask);
  128. --- 97,108 ----
  129.   #define FR_REPLACE    4
  130.   #define FR_REPLACEALL    5
  131.   
  132.   static void entry_activate_cb(GtkWidget *widget, GtkWidget *with);
  133.   static void entry_changed_cb(GtkWidget *entry, GtkWidget *dialog);
  134.   static void find_direction_cb(GtkWidget *widget, gpointer data);
  135. ! static void find_replace_cb(GtkWidget *widget, unsigned int flags);
  136.   static void exact_match_cb(GtkWidget *widget, gpointer data);
  137.   static void repl_dir_cb(GtkWidget * widget, gpointer data);
  138.   
  139.   #ifdef USE_TOOLBAR
  140.   static void get_pixmap(char *menuname, GdkPixmap **pixmap, GdkBitmap **mask);
  141. ***************
  142. *** 120,127 ****
  143.   #endif
  144.   
  145.   #if defined(WANT_MENU) || defined(PROTO)
  146. - static void gui_mch_recurse_tearoffs(VimMenu *menu, int val);
  147. - static void menu_item_cb(GtkWidget *widget, gpointer data);
  148.   
  149.   /*
  150.    * Only use accelerators when gtk_menu_ensure_uline_accel_group() is
  151. --- 113,118 ----
  152. ***************
  153. *** 133,138 ****
  154. --- 124,130 ----
  155.   #  define GTK_USE_ACCEL
  156.   # endif
  157.   #endif
  158.   /*
  159.    * Create a highly customized menu item by hand instead of by using:
  160.    *
  161. ***************
  162. *** 192,198 ****
  163.        * additional underscores.
  164.        */
  165.       name = g_new(char, strlen((char *)menu->name) + num + 1);
  166. !     for (num = 0, tmp = (char *)menu->name; *tmp; tmp++) {
  167.       /* actext has been added above, stop at the TAB */
  168.       if (*tmp == TAB)
  169.           break;
  170. --- 184,190 ----
  171.        * additional underscores.
  172.        */
  173.       name = g_new(char, strlen((char *)menu->name) + num + 1);
  174. !     for (num = 0, tmp = (char *)menu->name; *tmp; ++tmp) {
  175.       /* actext has been added above, stop at the TAB */
  176.       if (*tmp == TAB)
  177.           break;
  178. ***************
  179. *** 285,294 ****
  180.       if (parent == NULL)
  181.       gtk_menu_bar_insert(GTK_MENU_BAR(gui.menubar), menu->id, idx);
  182.       else {
  183. - #ifdef GTK_HAVE_FEATURES_1_1_0
  184.       /* since the tearoff should always appear first, increment idx */
  185.       ++idx;
  186. - #endif
  187.       gtk_menu_insert(GTK_MENU(parent->submenu_id), menu->id, idx);
  188.       }
  189.   
  190. --- 277,284 ----
  191. ***************
  192. *** 314,319 ****
  193. --- 304,319 ----
  194.   #endif
  195.   }
  196.   
  197. + /*ARGSUSED*/
  198. + static void
  199. + menu_item_activate(GtkWidget * widget, gpointer data)
  200. + {
  201. +     gui_menu_cb((VimMenu *) data);
  202. +     /* make sure the menu action is taken immediately */
  203. +     if (gtk_main_level() > 0)
  204. +     gtk_main_quit();
  205. + }
  206.   
  207.   /*ARGSUSED*/
  208.   void
  209. ***************
  210. *** 337,343 ****
  211.                       (char *)(menu->strings[MENU_INDEX_TIP]),
  212.                       (char *)(menu->dname),
  213.                       gtk_pixmap_new(pixmap, mask),
  214. !                     GTK_SIGNAL_FUNC(menu_item_cb),
  215.                       (gpointer)menu,
  216.                       idx);
  217.       }
  218. --- 337,343 ----
  219.                       (char *)(menu->strings[MENU_INDEX_TIP]),
  220.                       (char *)(menu->dname),
  221.                       gtk_pixmap_new(pixmap, mask),
  222. !                     GTK_SIGNAL_FUNC(menu_item_activate),
  223.                       (gpointer)menu,
  224.                       idx);
  225.       }
  226. ***************
  227. *** 351,372 ****
  228.       if (parent->submenu_id == 0)
  229.       return;
  230.   
  231.       if (is_menu_separator(menu->name)) {
  232. !     /* just add it */
  233.       menu->id = gtk_menu_item_new();
  234.       gtk_widget_show(menu->id);
  235. !     gtk_menu_append(GTK_MENU(parent->submenu_id), menu->id);
  236.   
  237. !     return; /* that's all */
  238.       }
  239.   
  240.       menu_item_new(menu, parent->submenu_id, FALSE);
  241.       gtk_widget_show(menu->id);
  242. !     gtk_menu_append(GTK_MENU(parent->submenu_id), menu->id);
  243.   
  244.       if (menu->id != 0)
  245.       gtk_signal_connect(GTK_OBJECT(menu->id), "activate",
  246. !         GTK_SIGNAL_FUNC(menu_item_cb), (gpointer) menu);
  247.   }
  248.   #endif
  249.   
  250. --- 351,375 ----
  251.       if (parent->submenu_id == 0)
  252.       return;
  253.   
  254. +     /* make place for the possible tearoff handle item */
  255. +     ++idx;
  256.       if (is_menu_separator(menu->name)) {
  257. !     /* Separator: Just add it */
  258.       menu->id = gtk_menu_item_new();
  259.       gtk_widget_show(menu->id);
  260. !     gtk_menu_insert(GTK_MENU(parent->submenu_id), menu->id, idx);
  261.   
  262. !     return;
  263.       }
  264.   
  265. +     /* Add textual menu item. */
  266.       menu_item_new(menu, parent->submenu_id, FALSE);
  267.       gtk_widget_show(menu->id);
  268. !     gtk_menu_insert(GTK_MENU(parent->submenu_id), menu->id, idx);
  269.   
  270.       if (menu->id != 0)
  271.       gtk_signal_connect(GTK_OBJECT(menu->id), "activate",
  272. !         GTK_SIGNAL_FUNC(menu_item_activate), (gpointer) menu);
  273.   }
  274.   #endif
  275.   
  276. ***************
  277. *** 426,432 ****
  278.   
  279.       *pixmap = NULL;
  280.       *mask = NULL;
  281. !     if (strncmp(menuname, "BuiltIn", 7) == 0) {
  282.       if (isdigit((int)menuname[7]) && isdigit((int)menuname[8])) {
  283.           builtin_num = atoi(menuname + 7);
  284.           pixmap_create_by_num(builtin_num, pixmap, mask);
  285. --- 429,435 ----
  286.   
  287.       *pixmap = NULL;
  288.       *mask = NULL;
  289. !     if (strncmp(menuname, "BuiltIn", (size_t)7) == 0) {
  290.       if (isdigit((int)menuname[7]) && isdigit((int)menuname[8])) {
  291.           builtin_num = atoi(menuname + 7);
  292.           pixmap_create_by_num(builtin_num, pixmap, mask);
  293. ***************
  294. *** 549,565 ****
  295.       gtk_form_move_resize(GTK_FORM(gui.formwin), gui.drawarea, x, y, w, h);
  296.   }
  297.   
  298. - #if 0
  299. - /*
  300. -  * Nothing to be done here, since we have started to manage our windows with
  301. -  * abstract management widgets, which is much better in fact.
  302. -  */
  303. - /*ARGSUSED*/
  304. - void
  305. - gui_mch_set_menu_pos(int x, int y, int w, int h)
  306. - {
  307. - }
  308. - #endif
  309.   
  310.   #if defined(WANT_MENU) || defined(PROTO)
  311.   /*
  312. --- 552,557 ----
  313. ***************
  314. *** 571,577 ****
  315.   {
  316.   #if 0
  317.       VimMenu *menu;
  318. !     /*  FIXME: imeplemnt this later */
  319.       for (menu = root_menu; menu != NULL; menu = menu->next)
  320.       if (menu->id != 0)
  321.           XtVaSetValues(menu->id,
  322. --- 563,569 ----
  323.   {
  324.   #if 0
  325.       VimMenu *menu;
  326. !     /*  FIXME: implement this later */
  327.       for (menu = root_menu; menu != NULL; menu = menu->next)
  328.       if (menu->id != 0)
  329.           XtVaSetValues(menu->id,
  330. ***************
  331. *** 580,600 ****
  332.   #endif
  333.   }
  334.   
  335.   void
  336.   gui_mch_toggle_tearoffs(int enable)
  337.   {
  338. !     gui_mch_recurse_tearoffs(root_menu, enable);
  339.   }
  340.   #endif
  341.   
  342.   
  343.   #ifdef USE_TOOLBAR
  344.   /*
  345. !  * seems like there's a hole in the GTK Toolbar API: there's no provision for
  346. !  * removing an item from the toolbar!
  347.    */
  348.   static void
  349. ! gui_gtk_toolbar_remove_item_by_text(GtkToolbar *tb, const char *text)
  350.   {
  351.       GtkContainer *container;
  352.       GList *childl;
  353. --- 572,615 ----
  354.   #endif
  355.   }
  356.   
  357. + static void
  358. + recurse_tearoffs(VimMenu * menu, int val)
  359. + {
  360. + #ifdef GTK_HAVE_FEATURES_1_1_0
  361. +     while (menu != NULL) {
  362. +     if (!popup_menu(menu->name)) {
  363. +         if (menu->submenu_id != 0) {
  364. +         if (val)
  365. +             gtk_widget_show(menu->tearoff_handle);
  366. +         else
  367. +             gtk_widget_hide(menu->tearoff_handle);
  368. +         }
  369. +         recurse_tearoffs(menu->children, val);
  370. +     }
  371. +     menu = menu->next;
  372. +     }
  373. + #endif
  374. + }
  375.   void
  376.   gui_mch_toggle_tearoffs(int enable)
  377.   {
  378. !     recurse_tearoffs(root_menu, enable);
  379.   }
  380.   #endif
  381.   
  382.   
  383.   #ifdef USE_TOOLBAR
  384.   /*
  385. !  * Seems like there's a hole in the GTK Toolbar API: there's no provision for
  386. !  * removing an item from the toolbar.  Therefore I need to resort to going
  387. !  * really deeply into the internal widget structures.
  388.    */
  389.   static void
  390. ! toolbar_remove_item_by_text(GtkToolbar *tb, const char *text)
  391.   {
  392.       GtkContainer *container;
  393.       GList *childl;
  394. ***************
  395. *** 637,648 ****
  396.   {
  397.   #ifdef USE_TOOLBAR
  398.       if (menu->parent && toolbar_menu(menu->parent->name)) {
  399. ! #if 0
  400. !     /* FIXME: this isn't in GTK yet, but will be.  for now, use the alternative */
  401. !     gtk_toolbar_remove_item(GTK_TOOLBAR(gui.toolbar),
  402. !                 GTK_TOOLBAR_DATA_TEXT, menu->dname);
  403. ! #endif
  404. !     gui_gtk_toolbar_remove_item_by_text(GTK_TOOLBAR(gui.toolbar),
  405.                           (const char *)menu->dname);
  406.       return;
  407.       }
  408. --- 652,658 ----
  409.   {
  410.   #ifdef USE_TOOLBAR
  411.       if (menu->parent && toolbar_menu(menu->parent->name)) {
  412. !     toolbar_remove_item_by_text(GTK_TOOLBAR(gui.toolbar),
  413.                           (const char *)menu->dname);
  414.       return;
  415.       }
  416. ***************
  417. *** 716,724 ****
  418.       value = adjustment->value;
  419.   
  420.       /*
  421. !      * We just ignore the dragging argument, since otherwise
  422. !      * the scrollbar size will not be adjusted properly in
  423. !      * synthetic scrolls.
  424.        */
  425.       gui_drag_scrollbar(sb, value, FALSE);
  426.       if (gtk_main_level() > 0)
  427. --- 726,733 ----
  428.       value = adjustment->value;
  429.   
  430.       /*
  431. !      * We just ignore the dragging argument, since otherwise the scrollbar
  432. !      * size will not be adjusted properly in synthetic scrolls.
  433.        */
  434.       gui_drag_scrollbar(sb, value, FALSE);
  435.       if (gtk_main_level() > 0)
  436. ***************
  437. *** 768,773 ****
  438. --- 777,831 ----
  439.    * Implementation of the file selector related stuff
  440.    */
  441.   
  442. + /*ARGSUSED*/
  443. + static void
  444. + browse_ok_cb(GtkWidget *widget, gpointer cbdata)
  445. + {
  446. +     Gui *vw = (Gui *)cbdata;
  447. +     if (vw->browse_fname != NULL)
  448. +     g_free(vw->browse_fname);
  449. +     vw->browse_fname = (char_u *)g_strdup(gtk_file_selection_get_filename(
  450. +                     GTK_FILE_SELECTION(vw->filedlg)));
  451. +     gtk_widget_hide(vw->filedlg);
  452. +     if (gtk_main_level() > 0)
  453. +     gtk_main_quit();
  454. + }
  455. + /*ARGSUSED*/
  456. + static void
  457. + browse_cancel_cb(GtkWidget *widget, gpointer cbdata)
  458. + {
  459. +     Gui *vw = (Gui *)cbdata;
  460. +     if (vw->browse_fname != NULL)
  461. +     {
  462. +     g_free(vw->browse_fname);
  463. +     vw->browse_fname = NULL;
  464. +     }
  465. +     gtk_widget_hide(vw->filedlg);
  466. +     if (gtk_main_level() > 0)
  467. +     gtk_main_quit();
  468. + }
  469. + /*ARGSUSED*/
  470. + static gboolean
  471. + browse_destroy_cb(GtkWidget * widget)
  472. + {
  473. +     if (gui.browse_fname != NULL)
  474. +     {
  475. +     g_free(gui.browse_fname);
  476. +     gui.browse_fname = NULL;
  477. +     }
  478. +     gui.filedlg = NULL;
  479. +     if (gtk_main_level() > 0)
  480. +     gtk_main_quit();
  481. +     return FALSE;
  482. + }
  483.   /*
  484.    * Put up a file requester.
  485.    * Returns the selected name in allocated memory, or NULL for Cancel.
  486. ***************
  487. *** 793,804 ****
  488.       if (!gui.filedlg)
  489.       {
  490.       gui.filedlg = gtk_file_selection_new((const gchar *)title);
  491. -     fs = GTK_FILE_SELECTION(gui.filedlg);
  492.   #ifdef GTK_HAVE_FEATURES_1_1_4
  493.       gtk_window_set_modal(GTK_WINDOW(gui.filedlg), TRUE);
  494.       gtk_window_set_transient_for(GTK_WINDOW(gui.filedlg),
  495.           GTK_WINDOW(gui.mainwin));
  496.   #endif
  497.       gtk_container_border_width(GTK_CONTAINER(fs), 4);
  498.       gtk_file_selection_hide_fileop_buttons(fs);
  499.   
  500. --- 851,863 ----
  501.       if (!gui.filedlg)
  502.       {
  503.       gui.filedlg = gtk_file_selection_new((const gchar *)title);
  504.   #ifdef GTK_HAVE_FEATURES_1_1_4
  505.       gtk_window_set_modal(GTK_WINDOW(gui.filedlg), TRUE);
  506.       gtk_window_set_transient_for(GTK_WINDOW(gui.filedlg),
  507.           GTK_WINDOW(gui.mainwin));
  508.   #endif
  509. +     fs = GTK_FILE_SELECTION(gui.filedlg);
  510.       gtk_container_border_width(GTK_CONTAINER(fs), 4);
  511.       gtk_file_selection_hide_fileop_buttons(fs);
  512.   
  513. ***************
  514. *** 834,926 ****
  515.       if (gui.browse_fname == NULL)
  516.       return NULL;
  517.       return vim_strsave(gui.browse_fname);
  518. ! } /* gui_mch_browse */
  519.   
  520. ! /*ARGSUSED*/
  521. ! static void
  522. ! browse_ok_cb(GtkWidget *widget, gpointer cbdata)
  523. ! {
  524. !     Gui *vw = (Gui *)cbdata;
  525.   
  526. !     if (vw->browse_fname != NULL)
  527. !     g_free(vw->browse_fname);
  528.   
  529. !     vw->browse_fname = (char_u *)g_strdup(gtk_file_selection_get_filename(
  530. !                     GTK_FILE_SELECTION(vw->filedlg)));
  531. !     gtk_widget_hide(vw->filedlg);
  532. !     if (gtk_main_level() > 0)
  533. !     gtk_main_quit();
  534. ! }
  535.   
  536. ! /*ARGSUSED*/
  537.   static void
  538. ! browse_cancel_cb(GtkWidget *widget, gpointer cbdata)
  539.   {
  540. !     Gui *vw = (Gui *)cbdata;
  541. !     if (vw->browse_fname != NULL)
  542. !     {
  543. !     g_free(vw->browse_fname);
  544. !     vw->browse_fname = NULL;
  545. !     }
  546. !     gtk_widget_hide(vw->filedlg);
  547. !     if (gtk_main_level() > 0)
  548. !     gtk_main_quit();
  549.   }
  550.   
  551.   /*ARGSUSED*/
  552. ! static gboolean
  553. ! browse_destroy_cb(GtkWidget * widget)
  554.   {
  555. !     if (gui.browse_fname != NULL)
  556. !     {
  557. !     g_free(gui.browse_fname);
  558. !     gui.browse_fname = NULL;
  559. !     }
  560. !     gui.filedlg = NULL;
  561.   
  562. !     /* This is needed to get out of gtk_main? */
  563. !     if (gtk_main_level() > 0)
  564. !     gtk_main_quit();
  565.   
  566. !     return FALSE;
  567.   }
  568.   
  569. - #endif    /* USE_BROWSE */
  570. - #ifdef GUI_DIALOG
  571. - static int dialogStatus;
  572. - static GtkWidget *dialogbb = NULL;
  573.   /* ARGSUSED */
  574.   int
  575. ! gui_mch_dialog(int type,
  576. !            char_u * title,
  577. !            char_u * message,
  578. !            char_u * buttons,
  579. !            int dfltbutton)
  580.   {
  581. !     char_u *buts;
  582. !     char_u *p, *next;
  583.       int butcount;
  584.   
  585. !     GtkWidget *vbox = NULL;
  586. !     GtkWidget *table = NULL;
  587.       GtkWidget *pixmap;
  588. !     GtkWidget *dialogmessage = NULL;
  589. !     GtkWidget *action_area = NULL;
  590. !     GtkWidget *separator = NULL;
  591.   
  592.       GdkPixmap *icon = NULL;
  593.       GdkBitmap *mask = NULL;
  594.       char **icon_data = NULL;
  595.   
  596.   #define MAXBUT 10
  597. !     GtkWidget *dialogButton[MAXBUT];
  598.   
  599.       if (title == NULL)
  600. !     title = (char_u *) "Vim dialog";
  601.   
  602.       if ((type < 0) || (type > VIM_LAST_TYPE))
  603.       type = VIM_GENERIC;
  604. --- 893,975 ----
  605.       if (gui.browse_fname == NULL)
  606.       return NULL;
  607.       return vim_strsave(gui.browse_fname);
  608. ! }
  609.   
  610. ! #endif    /* USE_BROWSE */
  611.   
  612. ! #ifdef GUI_DIALOG
  613.   
  614. ! typedef struct _ButtonData {
  615. !     int           *status;
  616. !     int           index;
  617. !     GtkWidget  *dialog;
  618. ! } ButtonData;
  619. ! typedef struct _CancelData {
  620. !     int          *status;
  621. !     GtkWidget *dialog;
  622. ! } CancelData;
  623.   
  624. ! /* ARGSUSED */
  625.   static void
  626. ! dlg_button_clicked(GtkWidget * widget, ButtonData *data)
  627.   {
  628. !     *(data->status) = data->index + 1;
  629. !     gtk_widget_destroy(data->dialog);
  630.   }
  631.   
  632. + /*
  633. +  * This makes the Escape key equivalent to the cancel button.
  634. +  */
  635.   /*ARGSUSED*/
  636. ! static int
  637. ! dlg_key_press_event(GtkWidget * widget, GdkEventKey * event, CancelData *data)
  638.   {
  639. !     if (event->keyval != GDK_Escape)
  640. !     return FALSE;
  641.   
  642. !     /* The result value of 0 from a dialog is signaling cancelation. */
  643. !     *(data->status) = 0;
  644. !     gtk_widget_destroy(data->dialog);
  645.   
  646. !     return TRUE;
  647.   }
  648.   
  649.   /* ARGSUSED */
  650.   int
  651. ! gui_mch_dialog(int type,        /* type of dialog */
  652. !            char_u * title,        /* title of dialog */
  653. !            char_u * message,    /* message text */
  654. !            char_u * buttons,    /* names of buttons */
  655. !            int def_but)        /* default button */
  656.   {
  657. !     char_u *names;
  658. !     char_u *p;
  659.       int butcount;
  660. +     int dialog_status = -1;
  661.   
  662. !     GtkWidget *dialog;
  663. !     GtkWidget *frame;
  664. !     GtkWidget *vbox;
  665. !     GtkWidget *table;
  666.       GtkWidget *pixmap;
  667. !     GtkWidget *dialogmessage;
  668. !     GtkWidget *action_area;
  669. !     GtkWidget *sub_area;
  670. !     GtkWidget *separator;
  671.   
  672.       GdkPixmap *icon = NULL;
  673.       GdkBitmap *mask = NULL;
  674.       char **icon_data = NULL;
  675.   
  676.   #define MAXBUT 10
  677. !     GtkWidget *button[MAXBUT];
  678. !     ButtonData data[MAXBUT];
  679. !     CancelData cancel_data;
  680.   
  681.       if (title == NULL)
  682. !     title = (char_u *) "Vim dialog...";
  683.   
  684.       if ((type < 0) || (type > VIM_LAST_TYPE))
  685.       type = VIM_GENERIC;
  686. ***************
  687. *** 928,943 ****
  688.       /* if our pointer is currently hidden, then we should show it. */
  689.       gui_mch_mousehide(FALSE);
  690.   
  691. !     dialogbb = gtk_window_new(GTK_WINDOW_DIALOG);
  692. !     gtk_window_set_title(GTK_WINDOW(dialogbb), (const gchar *)title);
  693. !     gtk_window_position(GTK_WINDOW(dialogbb), GTK_WIN_POS_MOUSE);
  694.   #ifdef GTK_HAVE_FEATURES_1_1_4
  695. !     gtk_window_set_transient_for(GTK_WINDOW(dialogbb), GTK_WINDOW(gui.mainwin));
  696.   #endif
  697. !     gtk_grab_add(dialogbb);
  698.   
  699.       vbox = gtk_vbox_new(FALSE, 0);
  700. !     gtk_container_add(GTK_CONTAINER(dialogbb), vbox);
  701.       gtk_widget_show(vbox);
  702.   
  703.       table = gtk_table_new(1, 3, FALSE);
  704. --- 977,1007 ----
  705.       /* if our pointer is currently hidden, then we should show it. */
  706.       gui_mch_mousehide(FALSE);
  707.   
  708. !     dialog = gtk_window_new(GTK_WINDOW_DIALOG);
  709. !     gtk_window_set_title(GTK_WINDOW(dialog), (const gchar *)title);
  710. !     gtk_window_position(GTK_WINDOW(dialog), GTK_WIN_POS_MOUSE);
  711.   #ifdef GTK_HAVE_FEATURES_1_1_4
  712. !     gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(gui.mainwin));
  713.   #endif
  714. !     gtk_widget_realize(dialog);
  715. !     gdk_window_set_decorations(dialog->window, GDK_DECOR_BORDER);
  716. !     gdk_window_set_functions(dialog->window, GDK_FUNC_MOVE);
  717. !     cancel_data.status = &dialog_status;
  718. !     cancel_data.dialog = dialog;
  719. !     gtk_signal_connect_after(GTK_OBJECT(dialog), "key_press_event",
  720. !             GTK_SIGNAL_FUNC(dlg_key_press_event),
  721. !             (gpointer) &cancel_data);
  722. !     gtk_grab_add(dialog);
  723. !     /* this makes it look beter on Motif style window managers */
  724. !     frame = gtk_frame_new(NULL);
  725. !     gtk_container_add(GTK_CONTAINER(dialog), frame);
  726. !     gtk_widget_show(frame);
  727.   
  728.       vbox = gtk_vbox_new(FALSE, 0);
  729. !     gtk_container_add(GTK_CONTAINER(frame), vbox);
  730.       gtk_widget_show(vbox);
  731.   
  732.       table = gtk_table_new(1, 3, FALSE);
  733. ***************
  734. *** 968,974 ****
  735.       icon_data = generic_xpm;
  736.       };
  737.       icon = gdk_pixmap_colormap_create_from_xpm_d(NULL,
  738. !                      gtk_widget_get_colormap(dialogbb),
  739.                        &mask, NULL, icon_data);
  740.       if (icon) {
  741.       pixmap = gtk_pixmap_new(icon, mask);
  742. --- 1032,1038 ----
  743.       icon_data = generic_xpm;
  744.       };
  745.       icon = gdk_pixmap_colormap_create_from_xpm_d(NULL,
  746. !                      gtk_widget_get_colormap(dialog),
  747.                        &mask, NULL, icon_data);
  748.       if (icon) {
  749.       pixmap = gtk_pixmap_new(icon, mask);
  750. ***************
  751. *** 976,1006 ****
  752.       gtk_table_attach_defaults(GTK_TABLE(table), pixmap, 0, 1, 0, 1);
  753.       gtk_widget_show(pixmap);
  754.       }
  755.       /* Add label */
  756.       dialogmessage = gtk_label_new((const gchar *)message);
  757.       gtk_table_attach_defaults(GTK_TABLE(table), dialogmessage, 1, 2, 0, 1);
  758.       gtk_widget_show(dialogmessage);
  759.   
  760. -     /* for some reason this doesn't work properly under kwm */
  761. -     /* gdk_window_set_decorations(dialogbb->window, GDK_DECOR_BORDER);
  762. -      * gdk_window_set_functions(dialogbb->window, 0);
  763. -      */
  764.       action_area = gtk_hbox_new(FALSE, 0);
  765.       gtk_container_border_width(GTK_CONTAINER(action_area), 4);
  766.       gtk_box_pack_end(GTK_BOX(vbox), action_area, FALSE, TRUE, 0);
  767.       gtk_widget_show(action_area);
  768.   
  769.       /* make a copy, so that we can insert NULs */
  770. !     buts = vim_strsave(buttons);
  771. !     if (buts == NULL)
  772.       return -1;
  773.   
  774.       /*
  775.        * Create the buttons.
  776.        */
  777. !     p = buts;
  778.       for (butcount = 0; butcount < MAXBUT; ++butcount) {
  779.       for (next = p; *next; ++next) {
  780.           if (*next == DLG_HOTKEY_CHAR)
  781.           mch_memmove(next, next + 1, STRLEN(next));
  782. --- 1040,1073 ----
  783.       gtk_table_attach_defaults(GTK_TABLE(table), pixmap, 0, 1, 0, 1);
  784.       gtk_widget_show(pixmap);
  785.       }
  786.       /* Add label */
  787.       dialogmessage = gtk_label_new((const gchar *)message);
  788.       gtk_table_attach_defaults(GTK_TABLE(table), dialogmessage, 1, 2, 0, 1);
  789.       gtk_widget_show(dialogmessage);
  790.   
  791.       action_area = gtk_hbox_new(FALSE, 0);
  792.       gtk_container_border_width(GTK_CONTAINER(action_area), 4);
  793.       gtk_box_pack_end(GTK_BOX(vbox), action_area, FALSE, TRUE, 0);
  794.       gtk_widget_show(action_area);
  795.   
  796. +     sub_area = gtk_hbox_new(TRUE, 0);
  797. +     gtk_container_set_border_width(GTK_CONTAINER(sub_area), 0);
  798. +     gtk_box_pack_start(GTK_BOX(action_area), sub_area, FALSE, TRUE, 0);
  799. +     gtk_widget_show(sub_area);
  800.       /* make a copy, so that we can insert NULs */
  801. !     names = vim_strsave(buttons);
  802. !     if (names == NULL)
  803.       return -1;
  804.   
  805.       /*
  806.        * Create the buttons.
  807.        */
  808. !     p = names;
  809.       for (butcount = 0; butcount < MAXBUT; ++butcount) {
  810. +     char_u *next;
  811.       for (next = p; *next; ++next) {
  812.           if (*next == DLG_HOTKEY_CHAR)
  813.           mch_memmove(next, next + 1, STRLEN(next));
  814. ***************
  815. *** 1010,1066 ****
  816.           }
  817.       }
  818.   
  819. !     dialogButton[butcount] = gtk_button_new_with_label((const gchar *)p);
  820. !     GTK_WIDGET_SET_FLAGS(dialogButton[butcount], GTK_CAN_DEFAULT);
  821. !     gtk_widget_show(dialogButton[butcount]);
  822. !     gtk_signal_connect(GTK_OBJECT(dialogButton[butcount]),
  823.                  (const char *)"clicked",
  824. !                GTK_SIGNAL_FUNC(butproc), GINT_TO_POINTER(butcount));
  825.   
  826.       if (*next == NUL) {
  827. !         gtk_box_pack_end(GTK_BOX(action_area), dialogButton[butcount],
  828. !                  FALSE, FALSE, 0);
  829.           break;
  830.       } else {
  831. !         gtk_box_pack_start(GTK_BOX(action_area), dialogButton[butcount],
  832. !                    FALSE, FALSE, 0);
  833.       }
  834.       p = next;
  835.       }
  836. !     ++butcount;
  837. !     vim_free(buts);
  838. !     if (dfltbutton < 1)
  839. !     dfltbutton = 1;
  840. !     if (dfltbutton > butcount)
  841. !     dfltbutton = butcount;
  842. !     /* XtVaSetValues(dialogbb, XmNdefaultButton, dialogButton[dfltbutton - 1], NULL); */
  843.   
  844. !     gtk_widget_grab_focus(dialogButton[dfltbutton - 1]);
  845. !     gtk_widget_grab_default(dialogButton[dfltbutton - 1]);
  846.   
  847.       separator = gtk_hseparator_new();
  848.       gtk_box_pack_end(GTK_BOX(vbox), separator, FALSE, TRUE, 0);
  849.       gtk_widget_show(separator);
  850.   
  851. !     dialogStatus = -1;
  852. !     gtk_widget_show(dialogbb);
  853. !     while (dialogbb)    /* stay here until dialog goes away */
  854.       gtk_main_iteration_do(TRUE);
  855.   
  856. !     return dialogStatus;
  857.   }
  858.   
  859. - /* ARGSUSED */
  860. - static void
  861. - butproc(GtkWidget * widget, gpointer data)
  862. - {
  863. -     dialogStatus = (GPOINTER_TO_INT(data)) + 1;
  864. -     gtk_widget_destroy(dialogbb);
  865. -     dialogbb = NULL;
  866. -     if (gtk_main_level() > 0)
  867. -     gtk_main_quit();
  868. - }
  869.   
  870.   #endif    /* GUI_DIALOG */
  871.   
  872. --- 1077,1131 ----
  873.           }
  874.       }
  875.   
  876. !     button[butcount] = gtk_button_new_with_label((const gchar *)p);
  877. !     GTK_WIDGET_SET_FLAGS(button[butcount], GTK_CAN_DEFAULT);
  878. !     gtk_widget_show(button[butcount]);
  879. !     data[butcount].status = &dialog_status;
  880. !     data[butcount].index = butcount;
  881. !     data[butcount].dialog = dialog;
  882. !     gtk_signal_connect(GTK_OBJECT(button[butcount]),
  883.                  (const char *)"clicked",
  884. !                GTK_SIGNAL_FUNC(dlg_button_clicked),
  885. !                (gpointer) &data[butcount]);
  886.   
  887.       if (*next == NUL) {
  888. !         gtk_box_pack_end(GTK_BOX(action_area), button[butcount],
  889. !                  FALSE, TRUE, 0);
  890.           break;
  891.       } else {
  892. !         gtk_box_pack_start(GTK_BOX(sub_area), button[butcount],
  893. !                    TRUE, TRUE, 0);
  894.       }
  895.       p = next;
  896.       }
  897. !     vim_free(names);
  898. !     --def_but;        /* 1 is first button */
  899. !     if (def_but < 0)
  900. !     def_but = 0;
  901. !     if (def_but > butcount)
  902. !     def_but = butcount;
  903.   
  904. !     gtk_widget_grab_focus(button[def_but]);
  905. !     gtk_widget_grab_default(button[def_but]);
  906.   
  907.       separator = gtk_hseparator_new();
  908.       gtk_box_pack_end(GTK_BOX(vbox), separator, FALSE, TRUE, 0);
  909.       gtk_widget_show(separator);
  910.   
  911. !     dialog_status = -1;
  912. !     gtk_widget_show(dialog);
  913. !     /* loop here until the dialog goes away */
  914. !     while (dialog_status == -1 && GTK_WIDGET_VISIBLE(dialog))
  915.       gtk_main_iteration_do(TRUE);
  916.   
  917. !     if (dialog_status < 0)
  918. !     dialog_status = 0;
  919. !     return dialog_status;
  920.   }
  921.   
  922.   
  923.   #endif    /* GUI_DIALOG */
  924.   
  925. ***************
  926. *** 1069,1081 ****
  927.   gui_mch_show_popupmenu(VimMenu * menu)
  928.   {
  929.       gtk_menu_popup(GTK_MENU(menu->submenu_id),
  930. !            NULL, NULL, NULL, NULL, 3, GDK_CURRENT_TIME);
  931.   }
  932.   #endif
  933.   
  934.   
  935.   /*
  936. !  * Don't create it twice!
  937.    */
  938.   
  939.   typedef struct _SharedFindReplace {
  940. --- 1134,1146 ----
  941.   gui_mch_show_popupmenu(VimMenu * menu)
  942.   {
  943.       gtk_menu_popup(GTK_MENU(menu->submenu_id),
  944. !            NULL, NULL, NULL, NULL, 3, (guint32)GDK_CURRENT_TIME);
  945.   }
  946.   #endif
  947.   
  948.   
  949.   /*
  950. !  * We don't create it twice.
  951.    */
  952.   
  953.   typedef struct _SharedFindReplace {
  954. ***************
  955. *** 1090,1165 ****
  956.       GtkWidget *all;    /* 'Replace All' action button */
  957.   } SharedFindReplace;
  958.   
  959. ! static SharedFindReplace find_widgets;
  960. ! static SharedFindReplace repl_widgets;
  961.   
  962. ! /*ARGSUSED*/
  963. ! void
  964. ! gui_mch_find_dialog(char_u * arg)
  965.   {
  966. !     find_replace_dialog_create(FALSE);
  967. ! }
  968.   
  969. ! /*ARGSUSED*/
  970. ! void
  971. ! gui_mch_replace_dialog(char_u * arg)
  972. ! {
  973. !     find_replace_dialog_create(TRUE);
  974. ! }
  975.   
  976.   
  977. ! /*
  978. !  * Synchronize all gui elements, which are dependant upon the
  979. !  * main text font used. Those are in esp. the find/replace dialogs.
  980. !  * If You don't understand why this should be needed, please try to
  981. !  * search for "piΩ╢µ" in iso8859-2.
  982. !  */
  983. ! void gui_gtk_synch_fonts(void)
  984. ! {
  985. !     SharedFindReplace *frdp;
  986. !     int do_replace;
  987.   
  988. !     /* OK this loop is a bit tricky... */
  989. !     for (do_replace = 0; do_replace <= 1; ++do_replace) {
  990. !     frdp = (do_replace) ? (&repl_widgets) : (&find_widgets);
  991. !     if (frdp->dialog) {
  992. !         GtkStyle *style;
  993.   
  994. !         /* synch the font with whats used by the text itself */
  995. !         style = gtk_style_copy(gtk_widget_get_style(frdp->what));
  996. !         gdk_font_unref(style->font);
  997. !         style->font = gui.norm_font;
  998. !         gdk_font_ref(style->font);
  999. !         gtk_widget_set_style(frdp->what, style);
  1000. !         gtk_style_unref(style);
  1001. !         if (do_replace) {
  1002. !         style = gtk_style_copy(gtk_widget_get_style(frdp->with));
  1003. !         gdk_font_unref(style->font);
  1004. !         style->font = gui.norm_font;
  1005. !         gdk_font_ref(style->font);
  1006. !         gtk_widget_set_style(frdp->with, style);
  1007. !         gtk_style_unref(style);
  1008. !         }
  1009. !     }
  1010. !     }
  1011.   }
  1012.   
  1013.   static void
  1014. ! find_replace_dialog_create(int do_replace)
  1015.   {
  1016. !     GtkWidget *hbox;        /* main top down box */
  1017. !     GtkWidget *actionarea;
  1018. !     GtkWidget *table;
  1019. !     GtkWidget *tmp;
  1020. !     GtkWidget *vbox;
  1021. !     gboolean sensitive;
  1022.       SharedFindReplace *frdp;
  1023. !     char *entry_text;
  1024.   
  1025.       frdp = (do_replace) ? (&repl_widgets) : (&find_widgets);
  1026.   
  1027.       if (frdp->dialog) {
  1028.       gui_gtk_synch_fonts();
  1029.       if (!GTK_WIDGET_VISIBLE(frdp->dialog)) {
  1030. --- 1155,1238 ----
  1031.       GtkWidget *all;    /* 'Replace All' action button */
  1032.   } SharedFindReplace;
  1033.   
  1034. ! static SharedFindReplace find_widgets = { NULL };
  1035. ! static SharedFindReplace repl_widgets = { NULL };
  1036.   
  1037. ! /* ARGSUSED */
  1038. ! static int
  1039. ! find_key_press_event(GtkWidget * widget,
  1040. !     GdkEventKey * event,
  1041. !     SharedFindReplace * frdp)
  1042.   {
  1043. !     /* If the user is holding one of the key modifiers we will just bail out,
  1044. !      * thus preserving the possibility of normal focus traversal.
  1045. !      */
  1046. !     if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK))
  1047. !     return FALSE;
  1048.   
  1049. !     /* the scape key synthesizes a cancellation action */
  1050. !     if (event->keyval == GDK_Escape) {
  1051. !     find_replace_cb(widget, FR_DIALOGTERM);
  1052. !     gtk_widget_hide(frdp->dialog);
  1053.   
  1054. +     return TRUE;
  1055. +     }
  1056.   
  1057. !     /* block traversal resulting from those keys */
  1058. !     if (event->keyval == GDK_Left || event->keyval == GDK_Right)
  1059. !     return TRUE;
  1060.   
  1061. !     /* It would be delightfull if it where possible to do search history
  1062. !      * operations on the K_UP and K_DOWN keys here.
  1063. !      */
  1064.   
  1065. !     return FALSE;
  1066.   }
  1067.   
  1068.   static void
  1069. ! find_replace_dialog_create(char_u *arg, int do_replace)
  1070.   {
  1071. !     GtkWidget    *frame;
  1072. !     GtkWidget    *hbox;        /* main top down box */
  1073. !     GtkWidget    *actionarea;
  1074. !     GtkWidget    *table;
  1075. !     GtkWidget    *tmp;
  1076. !     GtkWidget    *vbox;
  1077. !     gboolean    sensitive;
  1078.       SharedFindReplace *frdp;
  1079. !     char_u    *entry_text = arg;
  1080. !     gboolean    exact_word = FALSE;
  1081.   
  1082.       frdp = (do_replace) ? (&repl_widgets) : (&find_widgets);
  1083.   
  1084. +     /*
  1085. +      * If the argument is emtpy, get the last used search pattern.  If it is
  1086. +      * surrounded by "\<..\>" remove that and set the "exact_word" toggle
  1087. +      * button.
  1088. +      */
  1089. +     if (*entry_text == NUL)
  1090. +     entry_text = last_search_pat();
  1091. +     if (entry_text != NULL)
  1092. +     {
  1093. +     entry_text = vim_strsave(entry_text);
  1094. +     if (entry_text != NULL)
  1095. +     {
  1096. +         int len = STRLEN(entry_text);
  1097. +         if (len >= 4
  1098. +             && STRNCMP(entry_text, "\\<", 2) == 0
  1099. +             && STRNCMP(entry_text + len - 2, "\\>", 2) == 0)
  1100. +         {
  1101. +         exact_word = TRUE;
  1102. +         mch_memmove(entry_text, entry_text + 2, (size_t)(len - 4));
  1103. +         entry_text[len - 4] = NUL;
  1104. +         }
  1105. +     }
  1106. +     }
  1107. +     /*
  1108. +      * If the dialog already exists, just raise it.
  1109. +      */
  1110.       if (frdp->dialog) {
  1111.       gui_gtk_synch_fonts();
  1112.       if (!GTK_WIDGET_VISIBLE(frdp->dialog)) {
  1113. ***************
  1114. *** 1167,1174 ****
  1115. --- 1240,1254 ----
  1116.           gtk_widget_show(frdp->dialog);
  1117.       }
  1118.   
  1119. +     if (entry_text != NULL)
  1120. +     {
  1121. +         gtk_entry_set_text(GTK_ENTRY(frdp->what), (char *)entry_text);
  1122. +         gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(frdp->exact),
  1123. +                                   exact_word);
  1124. +     }
  1125.       gdk_window_raise(frdp->dialog->window);
  1126.   
  1127. +     vim_free(entry_text);
  1128.       return;
  1129.       }
  1130.   
  1131. ***************
  1132. *** 1182,1190 ****
  1133.       }
  1134.   
  1135.       gtk_window_position(GTK_WINDOW(frdp->dialog), GTK_WIN_POS_MOUSE);
  1136.   
  1137.       hbox = gtk_hbox_new(FALSE, 0);
  1138. !     gtk_container_add(GTK_CONTAINER(frdp->dialog), hbox);
  1139.   
  1140.       if (do_replace)
  1141.       table = gtk_table_new(1024, 4, FALSE);
  1142. --- 1262,1279 ----
  1143.       }
  1144.   
  1145.       gtk_window_position(GTK_WINDOW(frdp->dialog), GTK_WIN_POS_MOUSE);
  1146. +     gtk_widget_realize(frdp->dialog);
  1147. +     gdk_window_set_decorations(frdp->dialog->window,
  1148. +         GDK_DECOR_TITLE | GDK_DECOR_BORDER | GDK_DECOR_RESIZEH);
  1149. +     gdk_window_set_functions(frdp->dialog->window,
  1150. +         GDK_FUNC_RESIZE | GDK_FUNC_MOVE);
  1151. +     /* this makes it look beter on Motif style window managers */
  1152. +     frame = gtk_frame_new(NULL);
  1153. +     gtk_container_add(GTK_CONTAINER(frdp->dialog), frame);
  1154.   
  1155.       hbox = gtk_hbox_new(FALSE, 0);
  1156. !     gtk_container_add(GTK_CONTAINER(frame), hbox);
  1157.   
  1158.       if (do_replace)
  1159.       table = gtk_table_new(1024, 4, FALSE);
  1160. ***************
  1161. *** 1198,1208 ****
  1162.       gtk_table_attach(GTK_TABLE(table), tmp, 0, 1, 0, 1,
  1163.                GTK_FILL, GTK_EXPAND, 2, 2);
  1164.       frdp->what = gtk_entry_new();
  1165. !     entry_text = gtk_entry_get_text(GTK_ENTRY(frdp->what));
  1166. !     sensitive = (strlen(entry_text) != 0);
  1167. !     gtk_entry_set_text(GTK_ENTRY(frdp->what), entry_text);
  1168.       gtk_signal_connect(GTK_OBJECT(frdp->what), "changed",
  1169.                  GTK_SIGNAL_FUNC(entry_changed_cb), frdp->dialog);
  1170.       gtk_table_attach(GTK_TABLE(table), frdp->what, 1, 1024, 0, 1,
  1171.                GTK_EXPAND | GTK_FILL, GTK_EXPAND, 2, 2);
  1172.   
  1173. --- 1287,1300 ----
  1174.       gtk_table_attach(GTK_TABLE(table), tmp, 0, 1, 0, 1,
  1175.                GTK_FILL, GTK_EXPAND, 2, 2);
  1176.       frdp->what = gtk_entry_new();
  1177. !     sensitive = (entry_text != NULL && STRLEN(entry_text) != 0);
  1178. !     if (entry_text != NULL)
  1179. !     gtk_entry_set_text(GTK_ENTRY(frdp->what), (char *)entry_text);
  1180.       gtk_signal_connect(GTK_OBJECT(frdp->what), "changed",
  1181.                  GTK_SIGNAL_FUNC(entry_changed_cb), frdp->dialog);
  1182. +     gtk_signal_connect_after(GTK_OBJECT(frdp->what), "key_press_event",
  1183. +                  GTK_SIGNAL_FUNC(find_key_press_event),
  1184. +                  (gpointer) frdp);
  1185.       gtk_table_attach(GTK_TABLE(table), frdp->what, 1, 1024, 0, 1,
  1186.                GTK_EXPAND | GTK_FILL, GTK_EXPAND, 2, 2);
  1187.   
  1188. ***************
  1189. *** 1215,1220 ****
  1190. --- 1307,1315 ----
  1191.       gtk_signal_connect(GTK_OBJECT(frdp->with), "activate",
  1192.                  GTK_SIGNAL_FUNC(find_replace_cb),
  1193.                  (gpointer) FR_R_FINDNEXT);
  1194. +     gtk_signal_connect_after(GTK_OBJECT(frdp->with), "key_press_event",
  1195. +                  GTK_SIGNAL_FUNC(find_key_press_event),
  1196. +                  (gpointer) frdp);
  1197.       gtk_table_attach(GTK_TABLE(table), frdp->with, 1, 1024, 1, 2,
  1198.                GTK_EXPAND | GTK_FILL, GTK_EXPAND, 2, 2);
  1199.   
  1200. ***************
  1201. *** 1235,1241 ****
  1202.   
  1203.       /* exact match only button */
  1204.       frdp->exact = gtk_check_button_new_with_label("Match exact word only");
  1205. !     gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(frdp->exact), FALSE);
  1206.       gtk_signal_connect(GTK_OBJECT(frdp->exact), "clicked",
  1207.                  GTK_SIGNAL_FUNC(exact_match_cb), NULL);
  1208.       if (do_replace)
  1209. --- 1330,1336 ----
  1210.   
  1211.       /* exact match only button */
  1212.       frdp->exact = gtk_check_button_new_with_label("Match exact word only");
  1213. !     gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(frdp->exact), exact_word);
  1214.       gtk_signal_connect(GTK_OBJECT(frdp->exact), "clicked",
  1215.                  GTK_SIGNAL_FUNC(exact_match_cb), NULL);
  1216.       if (do_replace)
  1217. ***************
  1218. *** 1256,1262 ****
  1219.       gtk_container_border_width(GTK_CONTAINER(vbox), 0);
  1220.       gtk_container_add(GTK_CONTAINER(tmp), vbox);
  1221.   
  1222. !     /* 'up' and 'down' buttons */
  1223.       frdp->up = gtk_radio_button_new_with_label(NULL, "Up");
  1224.       gtk_box_pack_start(GTK_BOX(vbox), frdp->up, TRUE, TRUE, 0);
  1225.       frdp->down = gtk_radio_button_new_with_label(
  1226. --- 1351,1357 ----
  1227.       gtk_container_border_width(GTK_CONTAINER(vbox), 0);
  1228.       gtk_container_add(GTK_CONTAINER(tmp), vbox);
  1229.   
  1230. !     /* 'Up' and 'Down' buttons */
  1231.       frdp->up = gtk_radio_button_new_with_label(NULL, "Up");
  1232.       gtk_box_pack_start(GTK_BOX(vbox), frdp->up, TRUE, TRUE, 0);
  1233.       frdp->down = gtk_radio_button_new_with_label(
  1234. ***************
  1235. *** 1281,1287 ****
  1236.       }
  1237.       gtk_box_pack_end(GTK_BOX(hbox), actionarea, FALSE, FALSE, 0);
  1238.   
  1239. !     /* 'find next' button */
  1240.       frdp->find = gtk_button_new_with_label("Find Next");
  1241.       gtk_widget_set_sensitive(frdp->find, sensitive);
  1242.       if (do_replace)
  1243. --- 1376,1382 ----
  1244.       }
  1245.       gtk_box_pack_end(GTK_BOX(hbox), actionarea, FALSE, FALSE, 0);
  1246.   
  1247. !     /* 'Find Next' button */
  1248.       frdp->find = gtk_button_new_with_label("Find Next");
  1249.       gtk_widget_set_sensitive(frdp->find, sensitive);
  1250.       if (do_replace)
  1251. ***************
  1252. *** 1297,1303 ****
  1253.       gtk_widget_grab_default(frdp->find);
  1254.   
  1255.       if (do_replace) {
  1256. !     /* 'replace' button */
  1257.       frdp->replace = gtk_button_new_with_label("Replace");
  1258.       gtk_widget_set_sensitive(frdp->replace, sensitive);
  1259.       GTK_WIDGET_SET_FLAGS(frdp->replace, GTK_CAN_DEFAULT);
  1260. --- 1392,1398 ----
  1261.       gtk_widget_grab_default(frdp->find);
  1262.   
  1263.       if (do_replace) {
  1264. !     /* 'Replace' button */
  1265.       frdp->replace = gtk_button_new_with_label("Replace");
  1266.       gtk_widget_set_sensitive(frdp->replace, sensitive);
  1267.       GTK_WIDGET_SET_FLAGS(frdp->replace, GTK_CAN_DEFAULT);
  1268. ***************
  1269. *** 1306,1312 ****
  1270.                  GTK_SIGNAL_FUNC(find_replace_cb),
  1271.                  (gpointer) FR_REPLACE);
  1272.   
  1273. !     /* 'replace all' button */
  1274.       frdp->all = gtk_button_new_with_label("Replace All");
  1275.       gtk_widget_set_sensitive(frdp->all, sensitive);
  1276.       GTK_WIDGET_SET_FLAGS(frdp->all, GTK_CAN_DEFAULT);
  1277. --- 1401,1407 ----
  1278.                  GTK_SIGNAL_FUNC(find_replace_cb),
  1279.                  (gpointer) FR_REPLACE);
  1280.   
  1281. !     /* 'Replace All' button */
  1282.       frdp->all = gtk_button_new_with_label("Replace All");
  1283.       gtk_widget_set_sensitive(frdp->all, sensitive);
  1284.       GTK_WIDGET_SET_FLAGS(frdp->all, GTK_CAN_DEFAULT);
  1285. ***************
  1286. *** 1316,1322 ****
  1287.                  (gpointer) FR_REPLACEALL);
  1288.       }
  1289.   
  1290. !     /* 'cancel' button */
  1291.       tmp = gtk_button_new_with_label("Cancel");
  1292.       GTK_WIDGET_SET_FLAGS(tmp, GTK_CAN_DEFAULT);
  1293.       gtk_box_pack_end(GTK_BOX(actionarea), tmp, FALSE, FALSE, 0);
  1294. --- 1411,1417 ----
  1295.                  (gpointer) FR_REPLACEALL);
  1296.       }
  1297.   
  1298. !     /* 'Cancel' button */
  1299.       tmp = gtk_button_new_with_label("Cancel");
  1300.       GTK_WIDGET_SET_FLAGS(tmp, GTK_CAN_DEFAULT);
  1301.       gtk_box_pack_end(GTK_BOX(actionarea), tmp, FALSE, FALSE, 0);
  1302. ***************
  1303. *** 1340,1350 ****
  1304.       gui_gtk_synch_fonts();
  1305.   
  1306.       gtk_widget_show_all(frdp->dialog);
  1307.   }
  1308.   
  1309.   /*
  1310.    * Convenience function.
  1311. !  * creates a button with a label, and packs it into the box specified by the
  1312.    * parameter 'parent'.
  1313.    */
  1314.   GtkWidget *
  1315. --- 1435,1499 ----
  1316.       gui_gtk_synch_fonts();
  1317.   
  1318.       gtk_widget_show_all(frdp->dialog);
  1319. +     vim_free(entry_text);
  1320. + }
  1321. + void
  1322. + gui_mch_find_dialog(char_u * arg)
  1323. + {
  1324. +     find_replace_dialog_create(arg, FALSE);
  1325. + }
  1326. + void
  1327. + gui_mch_replace_dialog(char_u * arg)
  1328. + {
  1329. +     find_replace_dialog_create(arg, TRUE);
  1330. + }
  1331. + /*
  1332. +  * Synchronize all gui elements, which are dependant upon the
  1333. +  * main text font used. Those are in esp. the find/replace dialogs.
  1334. +  * If You don't understand why this should be needed, please try to
  1335. +  * search for "piΩ╢µ" in iso8859-2.
  1336. +  */
  1337. + void
  1338. + gui_gtk_synch_fonts(void)
  1339. + {
  1340. +     SharedFindReplace *frdp;
  1341. +     int do_replace;
  1342. +     /* OK this loop is a bit tricky... */
  1343. +     for (do_replace = 0; do_replace <= 1; ++do_replace) {
  1344. +     frdp = (do_replace) ? (&repl_widgets) : (&find_widgets);
  1345. +     if (frdp->dialog) {
  1346. +         GtkStyle *style;
  1347. +         /* synch the font with whats used by the text itself */
  1348. +         style = gtk_style_copy(gtk_widget_get_style(frdp->what));
  1349. +         gdk_font_unref(style->font);
  1350. +         style->font = gui.norm_font;
  1351. +         gdk_font_ref(style->font);
  1352. +         gtk_widget_set_style(frdp->what, style);
  1353. +         gtk_style_unref(style);
  1354. +         if (do_replace) {
  1355. +         style = gtk_style_copy(gtk_widget_get_style(frdp->with));
  1356. +         gdk_font_unref(style->font);
  1357. +         style->font = gui.norm_font;
  1358. +         gdk_font_ref(style->font);
  1359. +         gtk_widget_set_style(frdp->with, style);
  1360. +         gtk_style_unref(style);
  1361. +         }
  1362. +     }
  1363. +     }
  1364.   }
  1365.   
  1366.   /*
  1367.    * Convenience function.
  1368. !  * Creates a button with a label, and packs it into the box specified by the
  1369.    * parameter 'parent'.
  1370.    */
  1371.   GtkWidget *
  1372. ***************
  1373. *** 1355,1362 ****
  1374.       GtkWidget *parent,
  1375.       int connect_object,
  1376.       gboolean expand,
  1377. !     gboolean fill
  1378. !     )
  1379.   {
  1380.       GtkWidget *tmp;
  1381.   
  1382. --- 1504,1510 ----
  1383.       GtkWidget *parent,
  1384.       int connect_object,
  1385.       gboolean expand,
  1386. !     gboolean fill)
  1387.   {
  1388.       GtkWidget *tmp;
  1389.   
  1390. ***************
  1391. *** 1374,1418 ****
  1392.   
  1393.   /*** private function definitions ***/
  1394.   
  1395. - #ifdef WANT_MENU
  1396. - static void
  1397. - gui_mch_recurse_tearoffs(VimMenu * menu, int val)
  1398. - {
  1399. - #ifdef GTK_HAVE_FEATURES_1_1_0
  1400. -     while (menu != NULL) {
  1401. -     if (!popup_menu(menu->name)) {
  1402. -         if (menu->submenu_id != 0) {
  1403. -         if (val)
  1404. -             gtk_widget_show(menu->tearoff_handle);
  1405. -         else
  1406. -             gtk_widget_hide(menu->tearoff_handle);
  1407. -         }
  1408. -         gui_mch_recurse_tearoffs(menu->children, val);
  1409. -     }
  1410. -     menu = menu->next;
  1411. -     }
  1412. - #endif
  1413. - }
  1414. - /*ARGSUSED*/
  1415. - static void
  1416. - menu_item_cb(GtkWidget * widget, gpointer data)
  1417. - {
  1418. -     gui_menu_cb((VimMenu *) data);
  1419. -     /* make sure the menu action is taken immediately */
  1420. -     if (gtk_main_level() > 0)
  1421. -     gtk_main_quit();
  1422. - }
  1423. - #endif
  1424.   /*
  1425.    * Callback for actions of the find and replace dialogs
  1426.    */
  1427.   /*ARGSUSED*/
  1428.   static void
  1429. ! find_replace_cb(GtkWidget * widget, gint flags)
  1430.   {
  1431.       char *find_text, *repl_text, *cmd;
  1432.       gboolean direction_down = TRUE;
  1433. --- 1522,1533 ----
  1434.   
  1435.   /*** private function definitions ***/
  1436.   
  1437.   /*
  1438.    * Callback for actions of the find and replace dialogs
  1439.    */
  1440.   /*ARGSUSED*/
  1441.   static void
  1442. ! find_replace_cb(GtkWidget * widget, unsigned int flags)
  1443.   {
  1444.       char *find_text, *repl_text, *cmd;
  1445.       gboolean direction_down = TRUE;
  1446. ***************
  1447. *** 1519,1525 ****
  1448.       }
  1449.   
  1450.       g_free(cmd);
  1451. ! } /* find_replace_cb */
  1452.   
  1453.   /* our usual callback function */
  1454.   /*ARGSUSED*/
  1455. --- 1634,1640 ----
  1456.       }
  1457.   
  1458.       g_free(cmd);
  1459. ! }
  1460.   
  1461.   /* our usual callback function */
  1462.   /*ARGSUSED*/
  1463. ***************
  1464. *** 1615,1631 ****
  1465.       }
  1466.   }
  1467.   
  1468. ! static void helpfind_ok(GtkWidget *wgt, gpointer cbdata);
  1469. ! static void helpfind_entry_changed(GtkWidget *entry, gpointer cbdata);
  1470.   
  1471.   static GtkWidget *helpfind = NULL;
  1472.   static GtkWidget *help_entry = NULL;
  1473.   
  1474. !     void
  1475. ! do_helpfind()
  1476.   {
  1477. !     GtkWidget *vbox, *hbox, *tmp;
  1478.   
  1479.       if (!gui.in_use)
  1480.       {
  1481. --- 1730,1808 ----
  1482.       }
  1483.   }
  1484.   
  1485. ! /*
  1486. !  * Handling of the nice additional asynchronous little help topic requester.
  1487. !  */
  1488.   
  1489.   static GtkWidget *helpfind = NULL;
  1490.   static GtkWidget *help_entry = NULL;
  1491. + static int     help_ok_sensitive = FALSE;
  1492.   
  1493. !     static void
  1494. ! helpfind_entry_changed(GtkWidget *entry, gpointer cbdata)
  1495.   {
  1496. !     GtkWidget *ok = (GtkWidget *)cbdata;
  1497. !     char *txt = gtk_entry_get_text(GTK_ENTRY(entry));
  1498. !     if (txt == NULL || *txt == NUL)
  1499. !     return;
  1500. !     gtk_widget_set_sensitive(ok, strlen(txt));
  1501. !     gtk_widget_grab_default(ok);
  1502. !     help_ok_sensitive = TRUE;
  1503. ! }
  1504. ! /*ARGSUSED*/
  1505. !     static void
  1506. ! helpfind_ok(GtkWidget *wgt, gpointer cbdata)
  1507. ! {
  1508. !     char *txt, *cmd;
  1509. !     GtkEntry *entry = GTK_ENTRY(cbdata);
  1510. !     if ((txt = gtk_entry_get_text(entry)) == NULL)
  1511. !     return;
  1512. !     /* When the OK button isn't sensitive, hitting CR means cancel. */
  1513. !     if (help_ok_sensitive)
  1514. !     {
  1515. !     if ((cmd = (char *)alloc(strlen(txt) + 8)) == NULL)
  1516. !         return;
  1517. !     /* use CTRL-\ CTRL-N to get Vim into Normal mode first */
  1518. !     g_snprintf(cmd, (gulong)(strlen(txt) + 7), "\034\016:h %s\r", txt);
  1519. !     add_to_input_buf((char_u *)cmd, STRLEN(cmd));
  1520. !     vim_free(cmd);
  1521. !     }
  1522. !     /* Don't destroy this dialogue just hide it from the users view.
  1523. !      * Reuse it later */
  1524. !     gtk_widget_hide(helpfind);
  1525. !     if (gtk_main_level() > 0)
  1526. !     gtk_main_quit();
  1527. ! }
  1528. ! /*ARGSUSED*/
  1529. !     static void
  1530. ! helpfind_cancel(GtkWidget *wgt, gpointer cbdata)
  1531. ! {
  1532. !     /* Don't destroy this dialogue just hide it from the users view.
  1533. !      * Reuse it later */
  1534. !     gtk_widget_hide(helpfind);
  1535. !     if (gtk_main_level() > 0)
  1536. !     gtk_main_quit();
  1537. ! }
  1538. ! void
  1539. ! do_helpfind(void)
  1540. ! {
  1541. !     GtkWidget *frame;
  1542. !     GtkWidget *vbox;
  1543. !     GtkWidget *hbox;
  1544. !     GtkWidget *tmp;
  1545. !     GtkWidget *action_area;
  1546. !     GtkWidget *sub_area;
  1547.   
  1548.       if (!gui.in_use)
  1549.       {
  1550. ***************
  1551. *** 1650,1735 ****
  1552.       gtk_window_set_transient_for(GTK_WINDOW(helpfind), GTK_WINDOW(gui.mainwin));
  1553.   #endif
  1554.       gtk_window_position(GTK_WINDOW(helpfind), GTK_WIN_POS_MOUSE);
  1555. !     gtk_window_set_title(GTK_WINDOW(helpfind), "VIM - Help on what?");
  1556.       gtk_signal_connect(GTK_OBJECT(helpfind), "destroy",
  1557.                  GTK_SIGNAL_FUNC(gtk_widget_destroyed), &helpfind);
  1558.   
  1559. !     vbox = gtk_vbox_new(FALSE, 6);
  1560. !     gtk_container_add(GTK_CONTAINER(helpfind), vbox);
  1561. !     gtk_container_border_width(GTK_CONTAINER(helpfind), 6);
  1562.   
  1563.       hbox = gtk_hbox_new(FALSE, 6);
  1564.       gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
  1565.   
  1566. !     tmp = gtk_label_new("Topic: ");
  1567.       gtk_box_pack_start(GTK_BOX(hbox), tmp, TRUE, TRUE, 0);
  1568.   
  1569.       help_entry = gtk_entry_new();
  1570.       gtk_box_pack_start(GTK_BOX(hbox), help_entry, TRUE, TRUE, 0);
  1571.   
  1572. !     tmp = gtk_hseparator_new();
  1573. !     gtk_box_pack_start(GTK_BOX(vbox), tmp,  FALSE, TRUE, 0);
  1574.   
  1575. !     hbox = gtk_hbutton_box_new();
  1576. !     gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_EDGE);
  1577. !     gtk_button_box_set_spacing(GTK_BUTTON_BOX(hbox), 0);
  1578. !     gtk_container_border_width(GTK_CONTAINER(hbox), 0);
  1579. !     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
  1580. !     tmp = gui_gtk_button_new_with_label("Ok",
  1581. !                     GTK_SIGNAL_FUNC(helpfind_ok),
  1582. !                     help_entry, hbox, FALSE, FALSE, FALSE);
  1583.       gtk_signal_connect(GTK_OBJECT(help_entry), "changed",
  1584.                  GTK_SIGNAL_FUNC(helpfind_entry_changed), tmp);
  1585.       gtk_signal_connect(GTK_OBJECT(help_entry), "activate",
  1586.                  GTK_SIGNAL_FUNC(helpfind_ok), help_entry);
  1587.       gtk_widget_set_sensitive(tmp, FALSE);
  1588.       GTK_WIDGET_SET_FLAGS(tmp, GTK_CAN_DEFAULT);
  1589.   
  1590. !     tmp = gui_gtk_button_new_with_label("Cancel",
  1591. !                     GTK_SIGNAL_FUNC(gtk_widget_destroy),
  1592. !                     helpfind, hbox, TRUE, FALSE, FALSE);
  1593. !     GTK_WIDGET_SET_FLAGS(tmp, GTK_CAN_DEFAULT);
  1594. !     gtk_widget_grab_default(tmp);
  1595.   
  1596.       gtk_widget_grab_focus(help_entry);
  1597.       gtk_widget_show_all(helpfind);
  1598. - }
  1599. -     static void
  1600. - helpfind_entry_changed(GtkWidget *entry, gpointer cbdata)
  1601. - {
  1602. -     GtkWidget *ok = (GtkWidget *)cbdata;
  1603. -     char *txt = gtk_entry_get_text(GTK_ENTRY(entry));
  1604. -     if (txt == NULL)
  1605. -     return;
  1606. -     gtk_widget_set_sensitive(ok, strlen(txt));
  1607. - }
  1608. - /*ARGSUSED*/
  1609. -     static void
  1610. - helpfind_ok(GtkWidget *wgt, gpointer cbdata)
  1611. - {
  1612. -     char *txt, *cmd;
  1613. -     GtkEntry *entry = GTK_ENTRY(cbdata);
  1614. -     if ((txt = gtk_entry_get_text(entry)) == NULL)
  1615. -     return;
  1616. -     if ((cmd = (char *)alloc(strlen(txt) + 8)) == NULL)
  1617. -     return;
  1618. -     /* use CTRL-\ CTRL-N to get Vim into Normal mode first */
  1619. -     g_snprintf(cmd, (gulong)(strlen(txt) + 7), "\034\016:h %s\r", txt);
  1620. -     add_to_input_buf((char_u *)cmd, STRLEN(cmd));
  1621. -     gtk_widget_destroy(helpfind);
  1622. -     vim_free(cmd);
  1623. -     if (gtk_main_level() > 0)
  1624. -     gtk_main_quit();
  1625.   }
  1626. --- 1827,1888 ----
  1627.       gtk_window_set_transient_for(GTK_WINDOW(helpfind), GTK_WINDOW(gui.mainwin));
  1628.   #endif
  1629.       gtk_window_position(GTK_WINDOW(helpfind), GTK_WIN_POS_MOUSE);
  1630. !     gtk_window_set_title(GTK_WINDOW(helpfind), "VIM - Help on...");
  1631. !     gtk_widget_realize(helpfind);
  1632. !     gdk_window_set_decorations(helpfind->window,
  1633. !             GDK_DECOR_BORDER | GDK_DECOR_TITLE);
  1634. !     gdk_window_set_functions(helpfind->window, GDK_FUNC_MOVE);
  1635.       gtk_signal_connect(GTK_OBJECT(helpfind), "destroy",
  1636.                  GTK_SIGNAL_FUNC(gtk_widget_destroyed), &helpfind);
  1637.   
  1638. !     /* this makes it look beter on Motif style window managers */
  1639. !     frame = gtk_frame_new(NULL);
  1640. !     gtk_container_add(GTK_CONTAINER(helpfind), frame);
  1641. !     gtk_widget_show(frame);
  1642. !     vbox = gtk_vbox_new(FALSE, 0);
  1643. !     gtk_container_add(GTK_CONTAINER(frame), vbox);
  1644.   
  1645.       hbox = gtk_hbox_new(FALSE, 6);
  1646.       gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
  1647. +     gtk_container_border_width(GTK_CONTAINER(hbox), 6);
  1648.   
  1649. !     tmp = gtk_label_new("Topic:");
  1650.       gtk_box_pack_start(GTK_BOX(hbox), tmp, TRUE, TRUE, 0);
  1651.   
  1652.       help_entry = gtk_entry_new();
  1653.       gtk_box_pack_start(GTK_BOX(hbox), help_entry, TRUE, TRUE, 0);
  1654.   
  1655. !     action_area = gtk_hbox_new(FALSE, 0);
  1656. !     gtk_container_set_border_width(GTK_CONTAINER(action_area), 4);
  1657. !     gtk_box_pack_end(GTK_BOX(vbox), action_area, FALSE, TRUE, 0);
  1658.   
  1659. !     sub_area = gtk_hbox_new(TRUE, 0);
  1660. !     gtk_container_set_border_width(GTK_CONTAINER(sub_area), 0);
  1661. !     gtk_box_pack_end(GTK_BOX(action_area), sub_area, FALSE, TRUE, 0);
  1662. !     tmp = gui_gtk_button_new_with_label("Cancel",
  1663. !         GTK_SIGNAL_FUNC(helpfind_cancel),
  1664. !         help_entry, sub_area, TRUE, TRUE, TRUE);
  1665. !     GTK_WIDGET_SET_FLAGS(tmp, GTK_CAN_DEFAULT);
  1666. !     gtk_widget_grab_default(tmp);
  1667. !     tmp = gui_gtk_button_new_with_label("OK",
  1668. !         GTK_SIGNAL_FUNC(helpfind_ok),
  1669. !         help_entry, sub_area, FALSE, TRUE, TRUE);
  1670.       gtk_signal_connect(GTK_OBJECT(help_entry), "changed",
  1671.                  GTK_SIGNAL_FUNC(helpfind_entry_changed), tmp);
  1672.       gtk_signal_connect(GTK_OBJECT(help_entry), "activate",
  1673.                  GTK_SIGNAL_FUNC(helpfind_ok), help_entry);
  1674.       gtk_widget_set_sensitive(tmp, FALSE);
  1675. +     help_ok_sensitive = FALSE;
  1676.       GTK_WIDGET_SET_FLAGS(tmp, GTK_CAN_DEFAULT);
  1677.   
  1678. !     tmp = gtk_hseparator_new();
  1679. !     gtk_box_pack_end(GTK_BOX(vbox), tmp, FALSE, TRUE, 0);
  1680.   
  1681.       gtk_widget_grab_focus(help_entry);
  1682.       gtk_widget_show_all(helpfind);
  1683.   }
  1684. *** ../vim-5.6a.17/src/gui_gtk_x11.c    Wed Dec 29 12:11:01 1999
  1685. --- src/gui_gtk_x11.c    Sat Jan  8 21:15:25 2000
  1686. ***************
  1687. *** 19,24 ****
  1688. --- 19,29 ----
  1689.    *    :-) <dalecki@cs.net.pl> (My native language is polish and I speak
  1690.    *    native grade german too. I'm living in GĂ·ttingen.de.)
  1691.    *    --mdcki"
  1692. +  *
  1693. +  *
  1694. +  * Although some #ifdefs suggest that GTK 1.0 is supported, it isn't.  The
  1695. +  * code requires GTK version 1.1.16 or later.  Stuff for older versions will
  1696. +  * be removed some time.
  1697.    */
  1698.   
  1699.   #include "vim.h"
  1700. ***************
  1701. *** 36,46 ****
  1702.   
  1703.   /* slection distinguishers */
  1704.   enum {
  1705. !     SEL_TYPE_NONE,
  1706.       SELECTION_STRING,
  1707.       SELECTION_CLIPBOARD
  1708.   };
  1709.   
  1710.   /* This is the single only fixed width font in X11, which seems to be present
  1711.    * on all servers and available in all the variants we need.
  1712.    *
  1713. --- 41,69 ----
  1714.   
  1715.   /* slection distinguishers */
  1716.   enum {
  1717. !     SELECTION_TYPE_NONE,
  1718.       SELECTION_STRING,
  1719.       SELECTION_CLIPBOARD
  1720.   };
  1721.   
  1722. + /*
  1723. +  * Enable DND feature.  Disable this if it causes problems.
  1724. +  */
  1725. + #define GTK_DND
  1726. + #ifdef GTK_DND
  1727. + /* DND specification constants. */
  1728. + enum {
  1729. +   TARGET_STRING
  1730. + };
  1731. + static GtkTargetEntry target_table[] = {
  1732. +     { "STRING",     0, TARGET_STRING },
  1733. +     { "text/plain", 0, TARGET_STRING }
  1734. + };
  1735. + static guint n_targets = sizeof(target_table) / sizeof(target_table[0]);
  1736. + #endif
  1737.   /* This is the single only fixed width font in X11, which seems to be present
  1738.    * on all servers and available in all the variants we need.
  1739.    *
  1740. ***************
  1741. *** 50,78 ****
  1742.   
  1743.   #define DFLT_FONT        "-adobe-courier-medium-r-normal-*-14-*-*-*-m-*-*-*"
  1744.   
  1745. ! #ifdef GTK_HAVE_FEATURES_1_1_0
  1746. ! static void font_sel_ok(GtkWidget *wgt, gpointer cbdata);
  1747. ! static void font_sel_cancel(GtkWidget *wgt, gpointer cbdata);
  1748. ! static void font_sel_destroy(GtkWidget *wgt, gpointer cbdata);
  1749. ! #endif
  1750. ! static gint expose_event(GtkWidget * widget, GdkEventExpose * event);
  1751. ! static gint button_press_event(GtkWidget * widget, GdkEventButton * event);
  1752. ! static gint button_release_event(GtkWidget * widget, GdkEventButton * event);
  1753. ! static gint motion_notify_event(GtkWidget * widget, GdkEventMotion * event);
  1754. ! static void destroy_callback(void);
  1755. ! static int  delete_event_cb(GtkWidget *wgt, gpointer cbdata);
  1756.   
  1757.   /*
  1758. !  * If of the atom used to communicate save yourself from the X11 session
  1759. !  * manager. There is no need to move this into the GUI struct, since this
  1760. !  * should be always constant.
  1761.    */
  1762. ! GdkAtom save_yourself_atom = GDK_NONE;
  1763.   
  1764.   /*
  1765.    * Keycodes recognized by vim.
  1766. -  * we will be using the techniques described here later for real work.
  1767.    */
  1768.   static struct special_key {
  1769.       guint key_sym;
  1770. --- 73,93 ----
  1771.   
  1772.   #define DFLT_FONT        "-adobe-courier-medium-r-normal-*-14-*-*-*-m-*-*-*"
  1773.   
  1774. ! /*
  1775. !  * Atom used to communicate save yourself from the X11 session manager. There
  1776. !  * is no need to move this into the GUI struct, since this should be always
  1777. !  * constant.
  1778. !  */
  1779. ! static GdkAtom save_yourself_atom = GDK_NONE;
  1780.   
  1781.   /*
  1782. !  * Atom used to recognize requests for on the fly GTK+ style configuration
  1783. !  * changes.
  1784.    */
  1785. ! static GdkAtom reread_rcfiles_atom = GDK_NONE;
  1786.   
  1787.   /*
  1788.    * Keycodes recognized by vim.
  1789.    */
  1790.   static struct special_key {
  1791.       guint key_sym;
  1792. ***************
  1793. *** 306,311 ****
  1794. --- 321,357 ----
  1795.   #endif
  1796.   
  1797.   /*
  1798. +  * Redraw the corresponding portions of the screen.
  1799. +  */
  1800. + /*ARGSUSED*/
  1801. + static gint
  1802. + expose_event(GtkWidget * widget, GdkEventExpose * event)
  1803. + {
  1804. +     out_flush();        /* make sure all output has been processed */
  1805. +     gui_redraw(event->area.x, event->area.y,
  1806. +            event->area.width, event->area.height);
  1807. +     /* Clear the border areas if needed */
  1808. +     if (event->area.x < FILL_X(0))
  1809. +     gdk_window_clear_area(gui.drawarea->window, 0, 0, FILL_X(0), 0);
  1810. +     if (event->area.y < FILL_Y(0))
  1811. +     gdk_window_clear_area(gui.drawarea->window, 0, 0, 0, FILL_Y(0));
  1812. +     if (event->area.x > FILL_X(Columns))
  1813. +     gdk_window_clear_area(gui.drawarea->window,
  1814. +                   FILL_X((int)Columns), 0, 0, 0);
  1815. +     if (event->area.y > FILL_Y(Rows))
  1816. +     gdk_window_clear_area(gui.drawarea->window, 0, FILL_Y((int)Rows), 0, 0);
  1817. +     return FALSE;
  1818. + }
  1819. + /****************************************************************************
  1820. +  * Focus handlers:
  1821. +  */
  1822. + /*
  1823.    * This is a simple state machine:
  1824.    * BLINK_NONE   not blinking at all
  1825.    * BLINK_OFF    blinking, cursor is not shown
  1826. ***************
  1827. *** 347,364 ****
  1828.   
  1829.   /*ARGSUSED*/
  1830.   static gint
  1831. ! gui_gtk_blink_cb(gpointer data)
  1832.   {
  1833.       if (blink_state == BLINK_ON) {
  1834.       gui_undraw_cursor();
  1835.       blink_state = BLINK_OFF;
  1836. !     blink_timer = gtk_timeout_add(blink_offtime,
  1837. !                    (GtkFunction) gui_gtk_blink_cb, NULL);
  1838.       } else {
  1839.       gui_update_cursor(TRUE, FALSE);
  1840.       blink_state = BLINK_ON;
  1841. !     blink_timer = gtk_timeout_add(blink_ontime,
  1842. !                    (GtkFunction) gui_gtk_blink_cb, NULL);
  1843.       }
  1844.   
  1845.       return FALSE;        /* don't happen again */
  1846. --- 393,410 ----
  1847.   
  1848.   /*ARGSUSED*/
  1849.   static gint
  1850. ! blink_cb(gpointer data)
  1851.   {
  1852.       if (blink_state == BLINK_ON) {
  1853.       gui_undraw_cursor();
  1854.       blink_state = BLINK_OFF;
  1855. !     blink_timer = gtk_timeout_add((guint32)blink_offtime,
  1856. !                    (GtkFunction) blink_cb, NULL);
  1857.       } else {
  1858.       gui_update_cursor(TRUE, FALSE);
  1859.       blink_state = BLINK_ON;
  1860. !     blink_timer = gtk_timeout_add((guint32)blink_ontime,
  1861. !                    (GtkFunction) blink_cb, NULL);
  1862.       }
  1863.   
  1864.       return FALSE;        /* don't happen again */
  1865. ***************
  1866. *** 375,382 ****
  1867.       gtk_timeout_remove(blink_timer);
  1868.       /* Only switch blinking on if none of the times is zero */
  1869.       if (blink_waittime && blink_ontime && blink_offtime && gui.in_focus) {
  1870. !     blink_timer = gtk_timeout_add(blink_waittime,
  1871. !                    (GtkFunction) gui_gtk_blink_cb, NULL);
  1872.       blink_state = BLINK_ON;
  1873.       gui_update_cursor(TRUE, FALSE);
  1874.       }
  1875. --- 421,428 ----
  1876.       gtk_timeout_remove(blink_timer);
  1877.       /* Only switch blinking on if none of the times is zero */
  1878.       if (blink_waittime && blink_ontime && blink_offtime && gui.in_focus) {
  1879. !     blink_timer = gtk_timeout_add((guint32)blink_waittime,
  1880. !                    (GtkFunction) blink_cb, NULL);
  1881.       blink_state = BLINK_ON;
  1882.       gui_update_cursor(TRUE, FALSE);
  1883.       }
  1884. ***************
  1885. *** 437,451 ****
  1886.   }
  1887.   
  1888.   
  1889.   /*ARGSUSED*/
  1890.   static gint
  1891.   key_press_event(GtkWidget * widget, GdkEventKey * event, gpointer data)
  1892.   {
  1893. - #ifdef USE_XIM
  1894.       char_u string[256], string2[256];
  1895. - #else
  1896. -     char_u string[3], string2[3];
  1897. - #endif
  1898.       guint key_sym;
  1899.       int len;
  1900.       int i;
  1901. --- 483,497 ----
  1902.   }
  1903.   
  1904.   
  1905. + /****************************************************************************
  1906. +  * Main keyboard handler:
  1907. +  */
  1908.   /*ARGSUSED*/
  1909.   static gint
  1910.   key_press_event(GtkWidget * widget, GdkEventKey * event, gpointer data)
  1911.   {
  1912.       char_u string[256], string2[256];
  1913.       guint key_sym;
  1914.       int len;
  1915.       int i;
  1916. ***************
  1917. *** 571,576 ****
  1918. --- 617,628 ----
  1919.       return TRUE;
  1920.   }
  1921.   
  1922. + /****************************************************************************
  1923. +  * Selection handlers:
  1924. +  */
  1925.   /*ARGSUSED*/
  1926.   static gint
  1927.   selection_clear_event(GtkWidget * widget, GdkEventSelection * event)
  1928. ***************
  1929. *** 647,653 ****
  1930.       clip_get_selection();
  1931.   
  1932.       /* get the selection from the * register */
  1933. !     motion_type = clip_convert_selection(&string, (long_u *)&length);
  1934.       if (motion_type < 0)
  1935.       return;
  1936.   
  1937. --- 699,705 ----
  1938.       clip_get_selection();
  1939.   
  1940.       /* get the selection from the * register */
  1941. !     motion_type = clip_convert_selection(&string, &length);
  1942.       if (motion_type < 0)
  1943.       return;
  1944.   
  1945. ***************
  1946. *** 655,661 ****
  1947.       if (info == SELECTION_CLIPBOARD)
  1948.       length++;
  1949.   
  1950. !     result = (char_u *)malloc(2 * length);
  1951.       if (result == NULL)
  1952.       {
  1953.       vim_free(string);
  1954. --- 707,713 ----
  1955.       if (info == SELECTION_CLIPBOARD)
  1956.       length++;
  1957.   
  1958. !     result = lalloc((long_u)(2 * length), FALSE);
  1959.       if (result == NULL)
  1960.       {
  1961.       vim_free(string);
  1962. ***************
  1963. *** 676,682 ****
  1964.       selection_data->type = selection_data->target;
  1965.       selection_data->format = 8;    /* 8 bits per char */
  1966.   
  1967. !     gtk_selection_data_set(selection_data, type, 8, result, length);
  1968.       vim_free(string);
  1969.       vim_free(result);
  1970.   }
  1971. --- 728,734 ----
  1972.       selection_data->type = selection_data->target;
  1973.       selection_data->format = 8;    /* 8 bits per char */
  1974.   
  1975. !     gtk_selection_data_set(selection_data, type, 8, result, (gint)length);
  1976.       vim_free(string);
  1977.       vim_free(result);
  1978.   }
  1979. ***************
  1980. *** 771,2916 ****
  1981.       return OK;
  1982.   }
  1983.   
  1984.   /*
  1985. !  * Setup the window icon after the main window has bee realized.
  1986.    */
  1987. ! /*ARGSUSED*/
  1988. ! static void
  1989. ! mainwin_realize(GtkWidget *widget)
  1990.   {
  1991. ! /* If you get an error message here, you still need to unpack the runtime
  1992. !  * archive! */
  1993. ! #include "../runtime/vim32x32.xpm"
  1994. !     static GdkPixmap *icon = NULL;
  1995. !     static GdkBitmap *icon_mask = NULL;
  1996.   
  1997. !     if (!icon)
  1998. !     icon = gdk_pixmap_create_from_xpm_d(gui.mainwin->window,
  1999. !                             &icon_mask, NULL, magick);
  2000. !     gdk_window_set_icon(gui.mainwin->window, NULL, icon, icon_mask);
  2001.   }
  2002.   
  2003.   /*
  2004. !  * After the drawing area comes up, we calculate all colors and create the
  2005. !  * dummy blank cursor.
  2006. !  *
  2007. !  * Don't try to set any VIM scrollbar sizes anywhere here. I'm relying on the
  2008. !  * fact that the main VIM engine doesn't take them into account anywhere.
  2009.    */
  2010. ! static void
  2011. ! drawarea_realize_cb(GtkWidget *widget)
  2012.   {
  2013. !     char blank_data[] = {0x0};
  2014. !     GdkPixmap *blank_mask;
  2015. !     GdkColor color;
  2016. !     GtkWidget *sbar;
  2017.   
  2018. ! #ifdef USE_XIM
  2019. !     xim_init();
  2020. ! #endif
  2021. !     gui_mch_new_colors();
  2022.   
  2023. !     blank_mask = gdk_bitmap_create_from_data(NULL, blank_data, 1, 1);
  2024. !     gdk_color_white(gdk_colormap_get_system(), &color);
  2025. !     gui.blank_pointer = gdk_cursor_new_from_pixmap(blank_mask, blank_mask,
  2026. !                             &color, &color, 0, 0);
  2027. !     gdk_bitmap_unref(blank_mask);
  2028. !     if (gui.pointer_hidden)
  2029. !         gdk_window_set_cursor(widget->window, gui.blank_pointer);
  2030.   
  2031. !     /* get the actual size of the scrollbars, if they are realized */
  2032. !     sbar = firstwin->w_scrollbars[SBAR_LEFT].id;
  2033. !     if (!sbar || (!gui.which_scrollbars[SBAR_LEFT]
  2034. !                     && firstwin->w_scrollbars[SBAR_RIGHT].id))
  2035. !     sbar = firstwin->w_scrollbars[SBAR_RIGHT].id;
  2036. !     if (sbar && GTK_WIDGET_REALIZED(sbar) && sbar->allocation.width)
  2037. !     gui.scrollbar_width = sbar->allocation.width;
  2038.   
  2039. !     sbar = gui.bottom_sbar.id;
  2040. !     if (sbar && GTK_WIDGET_REALIZED(sbar) && sbar->allocation.height)
  2041. !     gui.scrollbar_height = sbar->allocation.height;
  2042.   }
  2043.   
  2044. ! /*
  2045. !  * Initialise the X GUI.  Create all the windows, set up all the call-backs etc.
  2046. !  * Returns OK for success, FAIL when the GUI can't be started.
  2047. !  */
  2048. ! int
  2049. ! gui_mch_init()
  2050.   {
  2051. !     GtkWidget *vbox;
  2052.   
  2053. !     /* Uncomment this to enable synchronous mode for debugging */
  2054. !     /* XSynchronize(gui.dpy, True); */
  2055.   
  2056. !     /* Initialize values */
  2057. !     gui.rev_video = FALSE;
  2058. !     gui.border_width = 2;
  2059. !     gui.scrollbar_width = SB_DEFAULT_WIDTH;
  2060. !     gui.scrollbar_height = SB_DEFAULT_WIDTH;
  2061. !     gui.fgcolor = g_new0(GdkColor, 1);
  2062. !     gui.bgcolor = g_new0(GdkColor, 1);
  2063.   
  2064. ! #ifdef WANT_MENU
  2065. !     /* Don't change the menu height values used in gui.c at runtime */
  2066. !     gui.menu_height_fixed = TRUE;
  2067. ! #endif
  2068.   
  2069. !     /* Set default foreground and background colours. */
  2070. !     gui.norm_pixel = gui.def_norm_pixel;
  2071. !     gui.back_pixel = gui.def_back_pixel;
  2072.   
  2073. !     gui.mainwin = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  2074. !     gtk_window_set_policy(GTK_WINDOW(gui.mainwin), TRUE, TRUE, TRUE);
  2075. !     gtk_container_border_width(GTK_CONTAINER(gui.mainwin), 0);
  2076. !     gtk_widget_set_events(gui.mainwin, GDK_VISIBILITY_NOTIFY_MASK);
  2077. !     (void)gtk_signal_connect(GTK_OBJECT(gui.mainwin), "delete_event",
  2078. !                  GTK_SIGNAL_FUNC(delete_event_cb), NULL);
  2079.   
  2080. !     /* Add an icon to the main window. For fun and convenience of the user. */
  2081. !     if (vim_strchr(p_go, GO_ICON) != NULL)
  2082. !     gtk_signal_connect(GTK_OBJECT(gui.mainwin), "realize",
  2083. !                       GTK_SIGNAL_FUNC(mainwin_realize), NULL);
  2084.   
  2085.   
  2086. ! #ifdef GTK_HAVE_FEATURES_1_1_0
  2087. !     /* FIXME: this should eventually get the accelgroup of the gui.mainwin */
  2088. !     gui.accel_group = gtk_accel_group_get_default();
  2089. ! #endif
  2090.   
  2091. !     vbox = gtk_vbox_new(FALSE, 0);
  2092. !     gtk_container_add(GTK_CONTAINER(gui.mainwin), vbox);
  2093. !     gtk_widget_show(vbox);
  2094.   
  2095. ! #ifdef WANT_MENU
  2096. !     /* create the menubar and handle */
  2097. !     gui.menubar = gtk_menu_bar_new();
  2098. !     gtk_widget_show(gui.menubar);
  2099. !     gtk_box_pack_start(GTK_BOX(vbox), gui.menubar, FALSE, TRUE, 0);
  2100. ! #endif
  2101.   
  2102. ! #ifdef USE_TOOLBAR
  2103. !     /* create the toolbar */
  2104. !     if (p_toolbar) {
  2105. !     if (strstr((const char *)p_toolbar, "text")
  2106. !         && strstr((const char *)p_toolbar, "icons"))
  2107. !         gui.toolbar = gtk_toolbar_new(GTK_ORIENTATION_HORIZONTAL,
  2108. !                       GTK_TOOLBAR_BOTH);
  2109. !     else if (strstr((const char *)p_toolbar, "text"))
  2110. !         gui.toolbar = gtk_toolbar_new(GTK_ORIENTATION_HORIZONTAL,
  2111. !                       GTK_TOOLBAR_TEXT);
  2112. !     else
  2113. !         gui.toolbar = gtk_toolbar_new(GTK_ORIENTATION_HORIZONTAL,
  2114. !                       GTK_TOOLBAR_ICONS);
  2115. !     } else
  2116. !     gui.toolbar = gtk_toolbar_new(GTK_ORIENTATION_HORIZONTAL,
  2117. !                       GTK_TOOLBAR_ICONS);
  2118.   
  2119. !     gtk_widget_show(gui.toolbar);
  2120. ! # ifdef GTK_HAVE_FEATURES_1_1_0
  2121. !     /* some aesthetics on the toolbar */
  2122. !     gtk_toolbar_set_button_relief(GTK_TOOLBAR(gui.toolbar), GTK_RELIEF_NONE);
  2123. ! # endif
  2124. !     gtk_container_border_width(GTK_CONTAINER(gui.toolbar), 1);
  2125. !     gtk_box_pack_start(GTK_BOX(vbox), gui.toolbar, FALSE, TRUE, 0);
  2126. ! #endif
  2127.   
  2128. !     gui.formwin = gtk_form_new();
  2129. !     gtk_container_border_width(GTK_CONTAINER(gui.formwin), 0);
  2130. !     gtk_widget_set_events(gui.formwin, GDK_EXPOSURE_MASK);
  2131.   
  2132. -     gui.drawarea = gtk_drawing_area_new();
  2133. -     /* Determine which events we will filter. */
  2134. -     gtk_widget_set_events(gui.drawarea,
  2135. -               GDK_EXPOSURE_MASK |
  2136. -               GDK_ENTER_NOTIFY_MASK |
  2137. -               GDK_LEAVE_NOTIFY_MASK |
  2138. -               GDK_BUTTON_PRESS_MASK |
  2139. -               GDK_BUTTON_RELEASE_MASK |
  2140. -               GDK_POINTER_MOTION_MASK |
  2141. -               GDK_POINTER_MOTION_HINT_MASK);
  2142. -     gtk_widget_show(gui.drawarea);
  2143. -     gtk_form_put(GTK_FORM(gui.formwin), gui.drawarea, 0, 0);
  2144. -     gtk_widget_show(gui.formwin);
  2145. -     gtk_box_pack_start(GTK_BOX(vbox), gui.formwin, TRUE, TRUE, 0);
  2146. -     gtk_signal_connect(GTK_OBJECT(gui.mainwin), "key_press_event",
  2147. -                (GtkSignalFunc) key_press_event, NULL);
  2148. -     gtk_signal_connect(GTK_OBJECT(gui.drawarea), "realize",
  2149. -                GTK_SIGNAL_FUNC(drawarea_realize_cb), NULL);
  2150.   
  2151. !     /* Check if reverse video needs to be applied (on Sun it's done by X) */
  2152. !     if (gui.rev_video && gui_mch_get_lightness(gui.back_pixel)
  2153. !     > gui_mch_get_lightness(gui.norm_pixel)) {
  2154. !     gui.norm_pixel = gui.def_back_pixel;
  2155. !     gui.back_pixel = gui.def_norm_pixel;
  2156. !     gui.def_norm_pixel = gui.norm_pixel;
  2157. !     gui.def_back_pixel = gui.back_pixel;
  2158. !     }
  2159. !     gui.visibility = GDK_VISIBILITY_UNOBSCURED;
  2160. !     clipboard.atom = gdk_atom_intern("_VIM_TEXT", FALSE);
  2161. !     save_yourself_atom = gdk_atom_intern("WM_SAVE_YOURSELF", FALSE);
  2162.   
  2163.       /*
  2164. !      * Start out by adding the configured border width into the border offset.
  2165.        */
  2166. !     gui.border_offset = gui.border_width;
  2167.   
  2168. ! #ifdef GTK_HAVE_FEATURES_1_1_0
  2169. !     gtk_signal_connect(GTK_OBJECT(gui.mainwin), "visibility_notify_event",
  2170. !                GTK_SIGNAL_FUNC(visibility_event), NULL);
  2171. ! #endif
  2172. !     gtk_signal_connect(GTK_OBJECT(gui.drawarea), "expose_event",
  2173. !                GTK_SIGNAL_FUNC(expose_event), NULL);
  2174.   
  2175. !     /*
  2176. !      * Only install these enter/leave callbacks when 'p' in 'guioptions'.
  2177. !      * Only needed for some window managers.
  2178. !      */
  2179. !     if (vim_strchr(p_go, GO_POINTER) != NULL) {
  2180. !     gtk_signal_connect(GTK_OBJECT(gui.drawarea), "leave_notify_event",
  2181. !                GTK_SIGNAL_FUNC(leave_notify_event), NULL);
  2182. !     gtk_signal_connect(GTK_OBJECT(gui.drawarea), "enter_notify_event",
  2183. !                GTK_SIGNAL_FUNC(enter_notify_event), NULL);
  2184.       }
  2185.   
  2186. !     gtk_signal_connect(GTK_OBJECT(gui.mainwin), "focus_out_event",
  2187. !                GTK_SIGNAL_FUNC(focus_out_event), NULL);
  2188. !     gtk_signal_connect(GTK_OBJECT(gui.mainwin), "focus_in_event",
  2189. !                GTK_SIGNAL_FUNC(focus_in_event), NULL);
  2190. !     gtk_signal_connect(GTK_OBJECT(gui.drawarea), "motion_notify_event",
  2191. !                GTK_SIGNAL_FUNC(motion_notify_event), NULL);
  2192. !     gtk_signal_connect(GTK_OBJECT(gui.drawarea), "button_press_event",
  2193. !                GTK_SIGNAL_FUNC(button_press_event), NULL);
  2194. !     gtk_signal_connect(GTK_OBJECT(gui.drawarea), "button_release_event",
  2195. !                GTK_SIGNAL_FUNC(button_release_event), NULL);
  2196.   
  2197. !     /*
  2198. !      * Add selection handler functions.
  2199. !      */
  2200. !     gtk_signal_connect(GTK_OBJECT(gui.drawarea), "selection_clear_event",
  2201. !                GTK_SIGNAL_FUNC(selection_clear_event), NULL);
  2202. !     gtk_signal_connect(GTK_OBJECT(gui.drawarea), "selection_received",
  2203. !                GTK_SIGNAL_FUNC(selection_received_event), NULL);
  2204.   
  2205. !     /* gtk_selection_add_target() is not in GTK 1.1.2 */
  2206. ! #ifdef GTK_HAVE_FEATURES_1_1_4
  2207. !     gtk_selection_add_target(gui.drawarea, GDK_SELECTION_PRIMARY,
  2208. !                 GDK_TARGET_STRING, SELECTION_STRING);
  2209. !     gtk_selection_add_target(gui.drawarea, GDK_SELECTION_PRIMARY,
  2210. !                 clipboard.atom, SELECTION_CLIPBOARD);
  2211. !     gtk_signal_connect(GTK_OBJECT(gui.drawarea), "selection_get",
  2212. !                GTK_SIGNAL_FUNC(selection_get_event), NULL);
  2213. ! #else
  2214. !     gtk_selection_add_handler(gui.drawarea, GDK_SELECTION_PRIMARY,
  2215. !                   GDK_TARGET_STRING, selection_handler, NULL);
  2216. !     gtk_selection_add_handler(gui.drawarea, GDK_SELECTION_PRIMARY,
  2217. !                   clipboard.atom, selection_handler, NULL);
  2218. ! #endif
  2219.   
  2220. !     /* Pretend we don't have input focus, we will get an event if we do. */
  2221. !     gui.in_focus = FALSE;
  2222.   
  2223. !     return OK;
  2224.   }
  2225.   
  2226. ! /*
  2227. !  * Called when the foreground or background color has been changed.
  2228. !  */
  2229. ! void
  2230. ! gui_mch_new_colors()
  2231.   {
  2232. !     /* This used to change the graphics contexts directly but we are currently
  2233. !      * manipulating them where desired.
  2234. !      */
  2235. !     if (gui.drawarea && gui.drawarea->window) {
  2236. !     GdkColor color;
  2237. !     color.pixel = gui.back_pixel;
  2238. !     gdk_window_set_background(gui.drawarea->window, &color);
  2239.       }
  2240.   }
  2241.   
  2242. - #ifdef GTK_HAVE_FEATURES_1_1_6
  2243. - # define USE_GEOMETRY_FOR_HINTS        1
  2244. - #endif
  2245.   
  2246.   static void
  2247. ! update_window_manager_hints(void)
  2248. ! {
  2249. !     int width;
  2250. !     int height;
  2251. ! #ifdef USE_GEOMETRY_FOR_HINTS
  2252. !     GdkGeometry geometry;
  2253. !     GdkWindowHints geometry_mask;
  2254.   
  2255. !     /* This also needs to be done when the main window isn't there yet,
  2256. !      * otherwise the hints don't work. */
  2257. !     width = gui_get_base_width();
  2258. !     height = gui_get_base_height();
  2259.   
  2260. !     geometry_mask = GDK_HINT_BASE_SIZE|GDK_HINT_RESIZE_INC|GDK_HINT_MIN_SIZE;
  2261. !     geometry.width_inc = gui.char_width;
  2262. !     geometry.height_inc = gui.char_height;
  2263. !     geometry.base_width = width;
  2264. !     geometry.base_height = height;
  2265. !     geometry.min_width = width + MIN_COLUMNS * gui.char_width;
  2266. !     geometry.min_height = height + MIN_LINES * gui.char_height;
  2267. !     gtk_window_set_geometry_hints(GTK_WINDOW(gui.mainwin), gui.formwin,
  2268. !                   &geometry, geometry_mask);
  2269. ! #else
  2270. !     XSizeHints size_hints;
  2271.   
  2272. !     /* Don't set the size until the main window is really there */
  2273. !     if (!GTK_WIDGET_REALIZED(gui.mainwin))
  2274. !     return;
  2275.   
  2276. !     width = gui_get_base_width();
  2277. !     height = gui_get_base_height();
  2278.   
  2279. !     /* The hints don't automatically take the menubar and toolbar into
  2280. !      * account.  Need to add their height here, if they are visible. */
  2281. ! # ifdef USE_TOOLBAR
  2282. !     if (gui.toolbar && GTK_WIDGET_REALIZED(gui.toolbar)
  2283. !         && GTK_WIDGET_VISIBLE(gui.toolbar))
  2284. !     height += gui.toolbar->allocation.height;
  2285. ! # endif
  2286. ! # ifdef WANT_MENU
  2287. !     if (gui.menubar && GTK_WIDGET_REALIZED(gui.menubar)
  2288. !         && GTK_WIDGET_VISIBLE(gui.menubar))
  2289. !     height += gui.menubar->allocation.height;
  2290. ! # endif
  2291.   
  2292.       /*
  2293. !      * Argh!!! Once again we need to deal with an ommission in GTK+ by
  2294. !      * resorting to direct Xlib calls. Fortunatly I know how to do it :-).
  2295.        */
  2296. !     size_hints.flags = (PResizeInc | PBaseSize | PMinSize | PSize);
  2297. !     size_hints.width_inc = gui.char_width;
  2298. !     size_hints.height_inc = gui.char_height;
  2299. !     size_hints.base_width = width;
  2300. !     size_hints.base_height = height;
  2301. !     size_hints.min_width = width + MIN_COLUMNS * gui.char_width;
  2302. !     size_hints.min_height = height + MIN_LINES * gui.char_height;
  2303.   
  2304. !     /* This is only needed for "older" window managers.  See a corresposning
  2305. !      * comment in the X11 headers. */
  2306. !     size_hints.width = width + Columns * gui.char_width;
  2307. !     size_hints.height = height + Rows * gui.char_height;
  2308.   
  2309. !     XSetWMNormalHints(GDK_DISPLAY(),
  2310. !               GDK_WINDOW_XWINDOW(gui.mainwin->window),
  2311. !               &size_hints);
  2312. ! #endif    /* USE_GEOMETRY_FOR_HINTS */
  2313.   }
  2314.   
  2315.   /*
  2316. !  * This signal informs us about the need to rearrange our subwidgets.
  2317.    */
  2318.   /*ARGSUSED*/
  2319. ! static gint
  2320. ! form_configure_event(GtkWidget * widget, GdkEventConfigure * event)
  2321.   {
  2322. !     gtk_form_freeze(GTK_FORM(gui.formwin));
  2323. !     gui_resize_window(event->width, event->height);
  2324. !     gtk_form_thaw(GTK_FORM(gui.formwin));
  2325. !     return TRUE;
  2326. ! }
  2327.   
  2328. ! /*ARGSUSED*/
  2329. ! static gint
  2330. ! client_event_cb(GtkWidget *widget, GdkEventClient *event)
  2331. ! {
  2332. !     if (event->message_type == save_yourself_atom ) {
  2333. !     out_flush();
  2334. !     ml_sync_all(FALSE, FALSE);      /* preserve all swap files */
  2335. !     return TRUE;
  2336. !     }
  2337. !     return FALSE;
  2338.   }
  2339.   
  2340.   /*
  2341. !  * Open the GUI window which was created by a call to gui_mch_init().
  2342.    */
  2343. ! int
  2344. ! gui_mch_open()
  2345.   {
  2346. !     int x = -1, y = -1;
  2347. !     /* Determine user specified geometry, if present. */
  2348. !     if (gui.geom) {
  2349. !     int mask;
  2350. !     unsigned w, h;
  2351. !     mask = XParseGeometry((char *)gui.geom, &x, &y, &w, &h);
  2352. !     if (mask & WidthValue)
  2353. !         Columns = w;
  2354. !     if (mask & HeightValue)
  2355. !         Rows = h;
  2356. !     if (mask & (XValue | YValue))
  2357. !         gtk_widget_set_uposition(gui.mainwin, x, y);
  2358. !     g_free(gui.geom);
  2359. !     gui.geom = NULL;
  2360. !     }
  2361. !     gtk_form_set_size(GTK_FORM(gui.formwin),
  2362. !         gui_get_base_width() + Columns * gui.char_width,
  2363. !         gui_get_base_height() + Rows * gui.char_height);
  2364. !     update_window_manager_hints();
  2365. !     if (found_reverse_arg )
  2366. !     {
  2367. !     gui.def_norm_pixel = gui_mch_get_color("White");
  2368. !     gui.def_back_pixel = gui_mch_get_color("Black");
  2369. !     }
  2370. !     else
  2371. !     {
  2372. !     gui.def_norm_pixel = gui_mch_get_color("Black");
  2373. !     gui.def_back_pixel = gui_mch_get_color("White");
  2374. !     }
  2375. !     /* Get the colors from the "Normal" and "Menu" group (set in syntax.c or
  2376. !      * in a vimrc file)
  2377. !      */
  2378. !     set_normal_colors();
  2379. !     /* Check that none of the colors are the same as the background color */
  2380. !     gui_check_colors();
  2381. !     /* Get the colors for the highlight groups (gui_check_colors() might have
  2382. !      * changed them).
  2383. !      */
  2384. !     highlight_gui_started();    /* re-init colors and fonts */
  2385. !     gtk_signal_connect(GTK_OBJECT(gui.mainwin), "destroy",
  2386. !                GTK_SIGNAL_FUNC(destroy_callback), NULL);
  2387.   
  2388. !     gtk_signal_connect(GTK_OBJECT(gui.mainwin), "client_event",
  2389. !                        GTK_SIGNAL_FUNC(client_event_cb), NULL);
  2390. ! #ifdef HANGUL_INPUT
  2391. !     hangul_keyboard_set();
  2392.   #endif
  2393.   
  2394. !     /*
  2395. !      * Notify the fixed area about the need to resize the contents of the
  2396. !      * gui.formwin, which we use for random positioning of the included
  2397. !      * components.
  2398. !      *
  2399. !      * We connect this signal deferred finally after anything is in place,
  2400. !      * since this is intended to handle resizements coming from the window
  2401. !      * manager upon us and should not interfere with what VIM is requesting
  2402. !      * upon startup.
  2403. !      */
  2404. !     gtk_signal_connect(GTK_OBJECT(gui.formwin), "configure_event",
  2405. !                GTK_SIGNAL_FUNC(form_configure_event), NULL);
  2406.   
  2407. !     gtk_widget_show(gui.mainwin);
  2408.   
  2409. !     return OK;
  2410.   }
  2411.   
  2412.   /*ARGSUSED*/
  2413. ! void
  2414. ! gui_mch_exit(int rc)
  2415.   {
  2416. !     gtk_exit(0);
  2417.   }
  2418.   
  2419.   /*
  2420. !  * Get the position of the top left corner of the window.
  2421.    */
  2422.   int
  2423. ! gui_mch_get_winpos(int *x, int *y)
  2424.   {
  2425. !     /* For some people this must be gdk_window_get_origin() for a correct
  2426. !      * result.  Where is the documentation! */
  2427. ! #ifdef GTK_HAVE_FEATURES_1_1_4
  2428. !     gdk_window_get_root_origin(gui.mainwin->window, x, y);
  2429. ! #else
  2430. !     gdk_window_get_origin(gui.mainwin->window, x, y);
  2431. ! #endif
  2432. !     return OK;
  2433. ! }
  2434.   
  2435. ! /*
  2436. !  * Set the position of the top left corner of the window to the given
  2437. !  * coordinates.
  2438. !  */
  2439. ! void
  2440. ! gui_mch_set_winpos(int x, int y)
  2441. ! {
  2442. !     gdk_window_move(gui.mainwin->window, x, y);
  2443. ! }
  2444.   
  2445. ! /*
  2446. !  * Set the windows size.
  2447. !  */
  2448. ! /*ARGSUSED*/
  2449. ! void
  2450. ! gui_mch_set_winsize(int width, int height,
  2451. !             int min_width, int min_height,
  2452. !             int base_width, int base_height)
  2453. ! {
  2454. !     gtk_form_set_size(GTK_FORM(gui.formwin), width, height);
  2455.   
  2456. !     /* give GTK+ a chance to put all widget's into place */
  2457. !     gui_mch_update();
  2458.   
  2459. !     /* this will cause the proper resizement to happen too */
  2460. !     update_window_manager_hints();
  2461. ! }
  2462.   
  2463.   
  2464. - /*
  2465. -  * The screen size is used to make sure the initial window doesn't get bigger
  2466. -  * then the screen.  This subtracts some room for menubar, toolbar and window
  2467. -  * decoreations.
  2468. -  */
  2469. - void
  2470. - gui_mch_get_screen_dimensions(int *screen_w, int *screen_h)
  2471. - {
  2472. -     *screen_w = gdk_screen_width();
  2473. -     /* Subtract 'guihearroom' from the height to allow some room for the
  2474. -      * window manager (task list and window title bar). */
  2475. -     *screen_h = gdk_screen_height() - p_ghr;
  2476.   
  2477. !     /*
  2478. !      * FIXME: dirty trick: Because the gui_get_base_height() doesn't include
  2479. !      * the toolbar and menubar for GTK, we subtract them from the screen
  2480. !      * hight, so that the window size can be made to fit on the screen.
  2481. !      * This should be completely changed later.
  2482. !      */
  2483. ! #ifdef USE_TOOLBAR
  2484. !     if (gui.toolbar && GTK_WIDGET_REALIZED(gui.toolbar)
  2485. !         && GTK_WIDGET_VISIBLE(gui.toolbar))
  2486. !     *screen_h -= gui.toolbar->allocation.height;
  2487. ! #endif
  2488. ! #ifdef WANT_MENU
  2489. !     if (gui.menubar && GTK_WIDGET_REALIZED(gui.menubar)
  2490. !         && GTK_WIDGET_VISIBLE(gui.menubar))
  2491. !     *screen_h -= gui.menubar->allocation.height;
  2492.   #endif
  2493. - }
  2494.   
  2495. ! #if defined(WANT_MENU) || defined(PROTO)
  2496. ! void
  2497. ! gui_mch_enable_menu(int flag)
  2498. ! {
  2499. !     if (flag)
  2500. !     gtk_widget_show(gui.menubar);
  2501. !     else
  2502. !     gtk_widget_hide(gui.menubar);
  2503.   
  2504. !     update_window_manager_hints();
  2505. ! }
  2506.   #endif
  2507.   
  2508. ! #if defined(USE_TOOLBAR) || defined(PROTO)
  2509. ! void
  2510. ! gui_mch_show_toolbar(int showit)
  2511. ! {
  2512. !     if (gui.toolbar == NULL)
  2513. !     return;
  2514. !     if (!showit) {
  2515. !     if (GTK_WIDGET_VISIBLE(gui.toolbar)) {
  2516. !         gtk_widget_hide(gui.toolbar);
  2517. !         /* wait util this gets done on the server side. */
  2518. !         update_window_manager_hints();
  2519. !     }
  2520. !     } else {
  2521. !     g_assert(p_toolbar != NULL);
  2522.       if (strstr((const char *)p_toolbar, "text")
  2523. !         && strstr((const char *)p_toolbar, "icons")) {
  2524. !         gtk_toolbar_set_style(GTK_TOOLBAR(gui.toolbar), GTK_TOOLBAR_BOTH);
  2525. !     } else if (strstr((const char *)p_toolbar, "text")) {
  2526. !         gtk_toolbar_set_style(GTK_TOOLBAR(gui.toolbar), GTK_TOOLBAR_TEXT);
  2527. !     } else if (strstr((const char *)p_toolbar, "icons")) {
  2528. !         gtk_toolbar_set_style(GTK_TOOLBAR(gui.toolbar), GTK_TOOLBAR_ICONS);
  2529. !     }
  2530. !     if (strstr((const char *)p_toolbar, "tooltips"))
  2531. !         gtk_toolbar_set_tooltips(GTK_TOOLBAR(gui.toolbar), TRUE);
  2532.       else
  2533. !         gtk_toolbar_set_tooltips(GTK_TOOLBAR(gui.toolbar), FALSE);
  2534.   
  2535. !     /*
  2536. !      * Black on white will catch the attention of the user more likely then
  2537. !      * black on grey. However due to errors / omissions in GTK+-1.1.5 this
  2538. !      * ceased to work properly. I had been looking after it and there seems
  2539. !      * to be no easy fix for it there. (--mdcki)
  2540. !      *
  2541. !      * This problem still applies for GTK+-1.2.3. (--mdcki)
  2542. !      * And I didn't find any current example where the tooltip colors
  2543. !      * would have need changed correctly.
  2544. !      */
  2545. !     gtk_tooltips_set_colors(GTK_TOOLBAR(gui.toolbar)->tooltips,
  2546. !                 &gui.toolbar->style->white,
  2547. !                 &gui.toolbar->style->black);
  2548. !     if (!GTK_WIDGET_VISIBLE(gui.toolbar)) {
  2549. !         gtk_widget_show(gui.toolbar);
  2550. !         update_window_manager_hints();
  2551. !     }
  2552. !     }
  2553. ! }
  2554.   #endif
  2555.   
  2556.   
  2557. ! #ifdef USE_FONTSET
  2558. ! static GuiFont
  2559. ! gui_mch_get_fontset(char_u * name, int report_error)
  2560. ! {
  2561. !     GdkFont *font;
  2562.   
  2563. !     if (!gui.in_use || name == NULL)
  2564. !     return (GuiFont) 0;
  2565.   
  2566. !     font = gdk_fontset_load((gchar *) name);
  2567.   
  2568. !     if (font == NULL) {
  2569. !     if (report_error)
  2570. !         EMSG2("Unknown fontset: %s", name);
  2571. !     return (GuiFont) 0;
  2572.       }
  2573.   
  2574. !     /* reference this font as beeing in use */
  2575. !     gdk_font_ref(font);
  2576.   
  2577. !     return (GuiFont) font;
  2578. ! }
  2579.   #endif
  2580.   
  2581. ! /*
  2582. !  * Initialise vim to use the font with the given name.
  2583. !  * Return FAIL if the font could not be loaded, OK otherwise.
  2584. !  */
  2585. ! int
  2586. ! gui_mch_init_font(char_u * font_name)
  2587. ! {
  2588. !     GdkFont    *font = NULL;
  2589. !     char    *chunk[28], *sdup, *tmp;
  2590. !     int        len, i;
  2591. ! #ifdef USE_FONTSET
  2592. !     {
  2593. !     static char_u *dflt_fontset = NULL;
  2594. !     if (gui.fontset)
  2595. !     {
  2596. !         /* If fontset is active, VIM treat all the font as a fontset. */
  2597. !         if (font_name == NULL || vim_strchr(font_name, ',') == NULL)
  2598. !         font_name = dflt_fontset;
  2599. !         font = gui_mch_get_fontset(font_name, FALSE);
  2600. !         if (font == NULL)
  2601. !         return FAIL;
  2602. !     }
  2603. !     else if (font_name == NULL && *p_guifontset)
  2604. !     {
  2605. !         font = gui_mch_get_fontset(p_guifontset, FALSE);
  2606. !         if (font)
  2607. !         {
  2608. !         font_name = p_guifontset;
  2609. !         dflt_fontset = alloc(STRLEN(p_guifontset) + 1);
  2610. !         STRCPY(dflt_fontset, p_guifontset);
  2611. !         }
  2612. !     }
  2613.       }
  2614.   
  2615. !     if (font == NULL)
  2616. ! #endif
  2617. !     {
  2618. !     /*
  2619. !      * If none of the fonts in 'font' could be loaded, try the default,
  2620. !      * which should be present on all X11 servers.
  2621. !      */
  2622. !     if (font_name == NULL)
  2623. !         font_name = (char_u *) DFLT_FONT;
  2624.   
  2625. ! #ifdef GTK_HAVE_FEATURES_1_1_0
  2626. !     if (STRCMP(font_name, "*") == 0) {
  2627. !         /*
  2628. !          * Request for a font handling dialog.
  2629. !          * Not quite sure we should handle this here...
  2630. !          */
  2631. !         /*
  2632. !          * NOTE about font selection widget: this can easily be backported
  2633. !          * to gtk-1.0.x.
  2634. !          */
  2635. !         if (!gui.fontdlg)
  2636. !         {
  2637. !         GtkFontSelectionDialog    *fsd = NULL;
  2638.   
  2639. !         gui.fontdlg = gtk_font_selection_dialog_new("Font Selection");
  2640. !         fsd = GTK_FONT_SELECTION_DIALOG(gui.fontdlg);
  2641. !         if (p_guifont != NULL)
  2642. !             gtk_font_selection_dialog_set_font_name(fsd,
  2643. !                                 (char *)p_guifont);
  2644. ! # ifdef GTK_HAVE_FEATURES_1_1_4
  2645. !         gtk_window_set_modal(GTK_WINDOW(gui.fontdlg), TRUE);
  2646. !         gtk_window_set_transient_for(GTK_WINDOW(gui.fontdlg),
  2647. !                              GTK_WINDOW(gui.mainwin));
  2648. ! # endif
  2649. !         gtk_signal_connect(GTK_OBJECT(gui.fontdlg), "destroy",
  2650. !                    GTK_SIGNAL_FUNC(font_sel_destroy), &gui);
  2651. !         gtk_signal_connect(GTK_OBJECT(fsd->ok_button), "clicked",
  2652. !                    GTK_SIGNAL_FUNC(font_sel_ok), &gui);
  2653. !         gtk_signal_connect(GTK_OBJECT(fsd->cancel_button), "clicked",
  2654. !                    GTK_SIGNAL_FUNC(font_sel_cancel), &gui);
  2655. !         }
  2656. !         if (gui.fontname)
  2657. !         {
  2658. !         g_free(gui.fontname);
  2659. !         gui.fontname = NULL;
  2660. !         }
  2661. !         gtk_window_position(GTK_WINDOW(gui.fontdlg), GTK_WIN_POS_MOUSE);
  2662. !         gtk_widget_show(gui.fontdlg);
  2663. ! # ifdef GTK_HAVE_FEATURES_1_1_4
  2664. !         {
  2665. !         static gchar        *spacings[] = {"c", "m", NULL};
  2666.   
  2667. !         /* In GTK 1.2.3 this must be after the gtk_widget_show() call,
  2668. !          * otherwise everything is blocked for ten seconds. */
  2669. !         gtk_font_selection_dialog_set_filter(
  2670. !             GTK_FONT_SELECTION_DIALOG(gui.fontdlg),
  2671. !             GTK_FONT_FILTER_BASE,
  2672. !             GTK_FONT_ALL, NULL, NULL,
  2673. !             NULL, NULL, spacings, NULL);
  2674. !         }
  2675. ! # endif
  2676.   
  2677. !         while (gui.fontdlg && GTK_WIDGET_VISIBLE(gui.fontdlg))
  2678. !         gtk_main_iteration_do(TRUE);
  2679.   
  2680. !         if (gui.fontname == NULL)
  2681. !         return FAIL;
  2682. !         vim_free(p_guifont);
  2683. !         p_guifont = vim_strsave(gui.fontname);
  2684. !         font_name = p_guifont;
  2685. !     }
  2686. ! #endif
  2687. !     if (font == NULL)
  2688. !         font = gui_mch_get_font(font_name, FALSE);
  2689.   
  2690. -     if (font == NULL)
  2691. -         return FAIL;
  2692. -     }
  2693.   
  2694. !     if (gui.norm_font != 0)
  2695. !     gdk_font_unref(font);
  2696. !     gui.norm_font = font;
  2697. ! #ifdef USE_FONTSET
  2698. !     if (font->type == GDK_FONT_FONTSET)
  2699. !     {
  2700. !     gui.fontset = (GuiFont) font;
  2701. !     gui.char_width = gdk_string_width(font, " ");
  2702.       }
  2703. !     else
  2704.   #endif
  2705. -     {
  2706. -     gui.char_width = ((XFontStruct *)
  2707. -                       GDK_FONT_XFONT(font))->max_bounds.width;
  2708. -     }
  2709.   
  2710. !     gui.char_height = font->ascent + font->descent;
  2711. !     gui.char_ascent = font->ascent;
  2712.   
  2713. !     /* Set the fontname, which will be used for information purposes */
  2714. !     hl_set_font_name(font_name);
  2715.   
  2716. !     if (font->type != GDK_FONT_FONTSET)
  2717. !     {
  2718. !     /* There is only one excuse I can give for the following attempt
  2719. !      * to manage font styles:
  2720. !      *
  2721. !      * I HATE THE BRAIN DEAD WAY X11 IS HANDLING FONTS (--mdcki)
  2722. !      */
  2723. !     if ((sdup = g_strdup((const char *)font_name)) == NULL)
  2724. !         return FAIL;
  2725.   
  2726. !     /* slipt up the whole */
  2727. !     i = 0;
  2728. !     for (tmp = sdup; *tmp != '\0'; ++tmp)
  2729. !         if (*tmp == '-')
  2730. !         {
  2731. !         *tmp = '\0';
  2732. !         chunk[i] = tmp + 1;
  2733. !         ++i;
  2734. !         }
  2735.   
  2736. !     g_free(sdup);
  2737.   
  2738. !     if (i == 14)
  2739. !     {
  2740. !         char *bold_name = NULL;
  2741. !         char *ital_name = NULL;
  2742. !         char *italbold_name = NULL;
  2743.   
  2744. !         /* font name was compleate */
  2745. !         len = strlen((const char *)font_name) + 32;
  2746. !         bold_name = (char *)alloc(len);
  2747. !         ital_name = (char *)alloc(len);
  2748. !         italbold_name = (char *)alloc(len);
  2749. !         if (bold_name == NULL || ital_name == NULL || italbold_name == NULL)
  2750. !         {
  2751. !         vim_free(bold_name);
  2752. !         vim_free(ital_name);
  2753. !         vim_free(italbold_name);
  2754. !         return FAIL;
  2755. !         }
  2756.   
  2757. !         *bold_name = '\0';
  2758. !         *ital_name = '\0';
  2759. !         *italbold_name = '\0';
  2760.   
  2761. !         for (i = 0; i < 14; ++i)
  2762. !         {
  2763. !         strcat(bold_name, "-");
  2764. !         strcat(ital_name, "-");
  2765. !         strcat(italbold_name, "-");
  2766. !         strcat(bold_name, (i != 2) ? chunk[i] : "bold");
  2767. !         strcat(ital_name, (i != 3) ? chunk[i] : "o");
  2768.   
  2769. !         if (i != 2 && i != 3)
  2770. !             strcat(italbold_name, chunk[i]);
  2771. !         else
  2772. !         {
  2773. !             if (i == 2)
  2774. !             strcat(italbold_name, "bold");
  2775. !             else if (i == 3)
  2776. !             strcat(italbold_name, "o");
  2777. !         }
  2778. !         }
  2779.   
  2780. !         font = gui_mch_get_font((char_u *)bold_name, FALSE);
  2781. !         if (font != NULL)
  2782. !         gui.bold_font = font;
  2783. !         else if (gui.bold_font)
  2784. !         {
  2785. !         gdk_font_unref(gui.bold_font);
  2786. !         gui.bold_font = NULL;
  2787. !         }
  2788.   
  2789. !         font = gui_mch_get_font((char_u *)ital_name, FALSE);
  2790. !         if (font != NULL)
  2791. !         gui.ital_font = font;
  2792. !         else if (gui.ital_font)
  2793. !         {
  2794. !         gdk_font_unref(gui.ital_font);
  2795. !         gui.ital_font = NULL;
  2796. !         }
  2797.   
  2798. !         font = gui_mch_get_font((char_u *)italbold_name, FALSE);
  2799. !         if (font != NULL)
  2800. !         gui.boldital_font = font;
  2801. !         else if (gui.boldital_font)
  2802. !         {
  2803. !         gdk_font_unref(gui.boldital_font);
  2804. !         gui.boldital_font = NULL;
  2805. !         }
  2806.   
  2807. -         vim_free(bold_name);
  2808. -         vim_free(ital_name);
  2809. -         vim_free(italbold_name);
  2810. -     }
  2811. -     }
  2812.   
  2813. !     /* Synchronize the fonts used in user input dialogs, since otherwise
  2814. !      * search/replace will be esp annoyig in case of international font usage.
  2815. !      */
  2816. !     gui_gtk_synch_fonts();
  2817.   
  2818. ! #ifdef USE_XIM
  2819. !     /* Adjust input management behaviour to the capabilities of the new
  2820. !      * fontset */
  2821. !     xim_decide_input_style();
  2822. !     if (xim_get_status_area_height())
  2823. !     {
  2824. !     /* Status area is required.  Just create the empty label so that
  2825. !      * mainwin will allocate the extra space for status area. */
  2826. !     GtkWidget *label = gtk_label_new("       ");
  2827.   
  2828. !     gtk_widget_set_usize(label, 20, gui.char_height + 2);
  2829. !     gtk_box_pack_end(GTK_BOX(GTK_BIN(gui.mainwin)->child), label,
  2830. !                                  FALSE, FALSE, 0);
  2831. !     gtk_widget_show(label);
  2832.       }
  2833. - #endif
  2834.   
  2835. !     /* Preserve the logical dimensions of the screen. */
  2836.       update_window_manager_hints();
  2837.   
  2838. !     return OK;
  2839. ! }
  2840.   
  2841.   
  2842. ! GuiFont
  2843. ! gui_mch_get_font(char_u * name, int report_error)
  2844. ! {
  2845. !     GdkFont *font;
  2846.   
  2847. !     if (!gui.in_use || name == NULL)    /* can't do this when GUI not running */
  2848. !     return (GuiFont) 0;
  2849.   
  2850. ! #ifdef USE_FONTSET
  2851. !     if (gui.fontset)
  2852. !     /* If fontset is active, VIM treat all the font as a fontset */
  2853. !     return gui_mch_get_fontset(name, report_error);
  2854. !     else if (vim_strchr(name, ','))
  2855. !     return (GuiFont)0;
  2856.   #endif
  2857.   
  2858. !     font = gdk_font_load((const gchar *) name);
  2859.   
  2860. !     if (font == NULL) {
  2861. !     if (report_error)
  2862. !         EMSG2("Unknown font: %s", name);
  2863. !     return (GuiFont) 0;
  2864. !     }
  2865.   
  2866. !     /* reference this font as beeing in use */
  2867. !     gdk_font_ref(font);
  2868. !     if (((XFontStruct *) GDK_FONT_XFONT(font))->max_bounds.width
  2869. !     != ((XFontStruct *) GDK_FONT_XFONT(font))->min_bounds.width) {
  2870. !     EMSG2("Font \"%s\" is not fixed-width", name);
  2871. !     gdk_font_unref(font);
  2872.   
  2873. !     return (GuiFont) 0;
  2874. !     }
  2875. !     return (GuiFont) font;
  2876.   }
  2877.   
  2878. ! /*
  2879. !  * Set the current text font.
  2880. !  * Since we create all GC on demand, we use just gui.current_font to
  2881. !  * indicate the desired current font.
  2882. !  */
  2883.   void
  2884. ! gui_mch_set_font(GuiFont font)
  2885.   {
  2886. !     gui.current_font = font;
  2887.   }
  2888.   
  2889. - #if 0 /* not used */
  2890.   /*
  2891. !  * Return TRUE if the two fonts given are equivalent.
  2892.    */
  2893.   int
  2894. ! gui_mch_same_font(GuiFont f1, GuiFont f2)
  2895.   {
  2896. !     return gdk_font_equal((GdkFont *) f1, (GdkFont *) f2);
  2897. ! }
  2898.   #endif
  2899.   
  2900.   /*
  2901. !  * If a font is not going to be used, free its structure.
  2902.    */
  2903.   void
  2904. ! gui_mch_free_font(GuiFont font)
  2905.   {
  2906. !     if (font)
  2907. !     gdk_font_unref((GdkFont *) font);
  2908.   }
  2909.   
  2910.   /*
  2911. !  * Return the Pixel value (color) for the given color name.  This routine was
  2912. !  * pretty much taken from example code in the Silicon Graphics OSF/Motif
  2913. !  * Programmer's Guide.
  2914. !  * Return -1 for error.
  2915.    */
  2916. ! GuiColor
  2917. ! gui_mch_get_color(char_u * name)
  2918.   {
  2919. !     int i;
  2920. !     static char *(vimnames[][2]) =
  2921. !     {
  2922. !     /* A number of colors that some X11 systems don't have */
  2923. !     {"LightRed", "#FFA0A0"},
  2924. !     {"LightGreen", "#80FF80"},
  2925. !     {"LightMagenta", "#FFA0FF"},
  2926. !     {"DarkCyan", "#008080"},
  2927. !     {"DarkBlue", "#0000C0"},
  2928. !     {"DarkRed", "#C00000"},
  2929. !     {"DarkMagenta", "#C000C0"},
  2930. !     {"DarkGrey", "#C0C0C0"},
  2931. !     {NULL, NULL}
  2932. !     };
  2933. !     if (!gui.in_use)        /* can't do this when GUI not running */
  2934. !     return (GuiColor)(-1);
  2935. !     while (name != NULL) {
  2936. !     GdkColor color;
  2937. !     if (gdk_color_parse((const gchar *)name, &color)) {
  2938. !         GdkColormap *colormap;
  2939. !         colormap = gtk_widget_get_colormap(gui.drawarea);
  2940. !         gdk_color_alloc(colormap, &color);
  2941.   
  2942. !         return (GuiColor) color.pixel;
  2943. !     }
  2944. !     /* add a few builtin names */
  2945. !     for (i = 0;; ++i) {
  2946. !         if (vimnames[i][0] == NULL) {
  2947. !         name = NULL;
  2948. !         break;
  2949. !         }
  2950. !         if (STRICMP(name, vimnames[i][0]) == 0) {
  2951. !         name = (char_u *) vimnames[i][1];
  2952. !         break;
  2953. !         }
  2954. !     }
  2955. !     }
  2956.   
  2957. !     return (GuiColor)(-1);
  2958.   }
  2959.   
  2960. - /*
  2961. -  * Set the current text foreground color.
  2962. -  */
  2963. - void
  2964. - gui_mch_set_fg_color(GuiColor color)
  2965. - {
  2966. -     gui.fgcolor->pixel = (Pixel) color;
  2967. - }
  2968.   
  2969.   /*
  2970. !  * Set the current text background color.
  2971.    */
  2972.   void
  2973. ! gui_mch_set_bg_color(GuiColor color)
  2974.   {
  2975. !     gui.bgcolor->pixel = (Pixel) color;
  2976.   }
  2977.   
  2978. ! /*
  2979. !  * Use the blank mouse pointer or not.
  2980. !  *
  2981. !  * hide: TRUE = use blank ptr, FALSE = use parent ptr
  2982. !  */
  2983.   void
  2984. ! gui_mch_mousehide(int hide)
  2985.   {
  2986. !     if (gui.pointer_hidden != hide) {
  2987. !     if (gui.drawarea->window && gui.blank_pointer) {
  2988. !         if (hide)
  2989. !         gdk_window_set_cursor(gui.drawarea->window, gui.blank_pointer);
  2990. !         else
  2991. !         gdk_window_set_cursor(gui.drawarea->window, NULL);
  2992. !     }
  2993. !     gui.pointer_hidden = hide;
  2994. !     }
  2995.   }
  2996.   
  2997.   void
  2998. ! gui_mch_draw_string(int row, int col, char_u * s, int len, int flags)
  2999.   {
  3000. !     GdkGC *gc;
  3001. !     if (gui.current_font == NULL || gui.drawarea->window == NULL)
  3002.       return;
  3003.   
  3004. ! #if defined(USE_FONTSET) && defined(MULTI_BYTE)
  3005. !     if (gui.fontset)
  3006. !     {
  3007. !     if (col > 0 && mb_isbyte1(LinePointers[row], col - 1))
  3008. !     {
  3009. !         col++;
  3010. !         len--;
  3011. !         s++;
  3012.       }
  3013. -     if (len == 1 && IsLeadByte(*s))
  3014. -         len = 2;
  3015. -     }
  3016. - #endif
  3017.   
  3018. !     gc = gdk_gc_new(gui.drawarea->window);
  3019. !     gdk_gc_set_exposures(gc, gui.visibility != GDK_VISIBILITY_UNOBSCURED);
  3020. !     if (flags & DRAW_TRANSP) {
  3021. !     gdk_gc_set_foreground(gc, gui.fgcolor);
  3022. !     gdk_draw_text(gui.drawarea->window,
  3023. !               gui.current_font,
  3024. !               gc,
  3025. !               TEXT_X(col), TEXT_Y(row),
  3026. !               (const gchar *)s, len);
  3027. !     } else {
  3028. !     int width;
  3029. !     int height;
  3030. !     width = gdk_text_width(gui.current_font, (const gchar *)s, len);
  3031. !     height = gui.char_height;
  3032. !     gdk_gc_set_foreground(gc, gui.bgcolor);
  3033. !     gdk_draw_rectangle(gui.drawarea->window,
  3034. !                gc,
  3035. !                TRUE,
  3036. !                FILL_X(col), FILL_Y(row), width, height);
  3037. !     gdk_gc_set_foreground(gc, gui.fgcolor);
  3038. !     gdk_draw_text(gui.drawarea->window,
  3039. !               gui.current_font,
  3040. !               gc,
  3041. !               TEXT_X(col), TEXT_Y(row),
  3042. !               (const gchar *)s, len);
  3043. !     }
  3044. !     /* redraw the contents with an offset of 1 to emulate bold */
  3045. !     if (flags & DRAW_BOLD) {
  3046. !     gdk_draw_text(gui.drawarea->window,
  3047. !               gui.current_font,
  3048. !               gc,
  3049. !               TEXT_X(col) + 1, TEXT_Y(row),
  3050. !               (const gchar *)s, len);
  3051. !     }
  3052. !     if (flags & DRAW_UNDERL) {
  3053. !     gdk_draw_line(gui.drawarea->window,
  3054. !               gc, FILL_X(col),
  3055. !     FILL_Y(row + 1) - 1, FILL_X(col + len) - 1, FILL_Y(row + 1) - 1);
  3056. !     }
  3057. !     gdk_gc_destroy(gc);
  3058. ! }
  3059. ! /*
  3060. !  * Return OK if the key with the termcap name "name" is supported.
  3061. !  */
  3062. ! int
  3063. ! gui_mch_haskey(char_u * name)
  3064. ! {
  3065. !     int i;
  3066. !     for (i = 0; special_keys[i].key_sym != 0; i++)
  3067. !     if (name[0] == special_keys[i].code0 &&
  3068. !         name[1] == special_keys[i].code1)
  3069. !         return OK;
  3070. !     return FAIL;
  3071. ! }
  3072.   
  3073. ! #if defined(WANT_TITLE) || defined(PROTO)
  3074. ! /*
  3075. !  * Return the text window-id and display.  Only required for X-based GUI's
  3076. !  */
  3077. ! int
  3078. ! gui_get_x11_windis(Window * win, Display ** dis)
  3079. ! {
  3080. !     /*
  3081. !      * This is currently only used by the code which is handling the
  3082. !      * window manager title of this program.
  3083. !      */
  3084. !     *dis = GDK_DISPLAY();
  3085. !     if (gui.mainwin->window) {
  3086. !     *win = GDK_WINDOW_XWINDOW(gui.mainwin->window);
  3087. !     return OK;
  3088.       }
  3089. -     *win = 0;
  3090. -     return FAIL;
  3091.   }
  3092.   #endif
  3093.   
  3094. - void
  3095. - gui_mch_beep()
  3096. - {
  3097. -     gdk_beep();
  3098. - }
  3099.   
  3100. ! void
  3101. ! gui_mch_flash()
  3102.   {
  3103. !     GdkGCValues values;
  3104. !     GdkGC *invert_gc;
  3105. !     GdkColor foreground;
  3106. !     GdkColor background;
  3107. !     if (gui.drawarea->window == NULL)
  3108. !     return;
  3109.   
  3110. !     foreground.pixel = gui.norm_pixel ^ gui.back_pixel;
  3111. !     background.pixel = gui.norm_pixel ^ gui.back_pixel;
  3112.   
  3113. !     values.foreground = foreground;
  3114. !     values.background = background;
  3115. !     values.function = GDK_XOR;
  3116. !     invert_gc = gdk_gc_new_with_values(gui.drawarea->window,
  3117. !                        &values,
  3118. !                        GDK_GC_FOREGROUND |
  3119. !                        GDK_GC_BACKGROUND |
  3120. !                        GDK_GC_FUNCTION);
  3121. !     gdk_gc_set_exposures(invert_gc, gui.visibility != GDK_VISIBILITY_UNOBSCURED);
  3122.   
  3123. !     /* Do a visual beep by changing back and forth in some undetermined way,
  3124. !      * the foreground and background colors.  This is due to the fact that
  3125. !      * there can't be really any prediction about the effects of XOR on
  3126. !      * arbitrary X11 servers. However this seems to be enought for what we
  3127. !      * intend it to do.
  3128. !      */
  3129. !     gdk_draw_rectangle(gui.drawarea->window, invert_gc,
  3130. !                TRUE,
  3131. !                0, 0,
  3132. !                FILL_X((int) Columns) + gui.border_offset,
  3133. !                FILL_Y((int) Rows) + gui.border_offset);
  3134.   
  3135. !     gdk_flush();
  3136. !     ui_delay(20L, TRUE);    /* wait 1/50 of a second */
  3137. !     gdk_draw_rectangle(gui.drawarea->window, invert_gc,
  3138. !                TRUE,
  3139. !                0, 0,
  3140. !                FILL_X((int) Columns) + gui.border_offset,
  3141. !                FILL_Y((int) Rows) + gui.border_offset);
  3142.   
  3143. !     gdk_gc_destroy(invert_gc);
  3144.   }
  3145.   
  3146.   /*
  3147. !  * Invert a rectangle from row r, column c, for nr rows and nc columns.
  3148.    */
  3149. ! void
  3150. ! gui_mch_invert_rectangle(int r, int c, int nr, int nc)
  3151.   {
  3152. !     GdkGCValues values;
  3153. !     GdkGC *invert_gc;
  3154. !     GdkColor foreground;
  3155. !     GdkColor background;
  3156.   
  3157. !     if (gui.drawarea->window == NULL)
  3158. !     return;
  3159.   
  3160. !     foreground.pixel = gui.norm_pixel ^ gui.back_pixel;
  3161. !     background.pixel = gui.norm_pixel ^ gui.back_pixel;
  3162.   
  3163. !     values.foreground = foreground;
  3164. !     values.background = background;
  3165. !     values.function = GDK_XOR;
  3166. !     invert_gc = gdk_gc_new_with_values(gui.drawarea->window,
  3167. !                        &values,
  3168. !                        GDK_GC_FOREGROUND |
  3169. !                        GDK_GC_BACKGROUND |
  3170. !                        GDK_GC_FUNCTION);
  3171. !     gdk_gc_set_exposures(invert_gc, gui.visibility != GDK_VISIBILITY_UNOBSCURED);
  3172. !     gdk_draw_rectangle(gui.drawarea->window, invert_gc,
  3173. !                TRUE,
  3174. !                FILL_X(c), FILL_Y(r),
  3175. !                (nc) * gui.char_width, (nr) * gui.char_height);
  3176. !     gdk_gc_destroy(invert_gc);
  3177.   }
  3178.   
  3179. ! /*
  3180. !  * Iconify the GUI window.
  3181. !  */
  3182. ! void
  3183. ! gui_mch_iconify()
  3184.   {
  3185. !     XIconifyWindow(GDK_DISPLAY(),
  3186. !            GDK_WINDOW_XWINDOW(gui.mainwin->window),
  3187. !            DefaultScreen(GDK_DISPLAY()));
  3188.   }
  3189.   
  3190.   /*
  3191. !  * Draw a cursor without focus.
  3192.    */
  3193. ! void
  3194. ! gui_mch_draw_hollow_cursor(GuiColor color)
  3195.   {
  3196. !     GdkGC *gc;
  3197.   
  3198. !     if (gui.drawarea->window == NULL)
  3199. !     return;
  3200.   
  3201. !     gui_mch_set_fg_color(color);
  3202.   
  3203. !     gc = gdk_gc_new(gui.drawarea->window);
  3204. !     gdk_gc_set_exposures(gc, gui.visibility != GDK_VISIBILITY_UNOBSCURED);
  3205. !     gdk_gc_set_foreground(gc, gui.fgcolor);
  3206. ! #if defined(USE_FONTSET) && defined(MULTI_BYTE)
  3207. !     if (gui.fontset)
  3208.       {
  3209. !     if (IsLeadByte(LinePointers[gui.row][gui.col])
  3210. ! # ifdef HANGUL_INPUT
  3211. !         || composing_hangul
  3212.   # endif
  3213. !        )
  3214. !         gdk_draw_rectangle(gui.drawarea->window, gc,
  3215. !                    FALSE,
  3216. !                    FILL_X(gui.col), FILL_Y(gui.row),
  3217. !                    2*gui.char_width - 1, gui.char_height - 1);
  3218. !     else
  3219. !         gdk_draw_rectangle(gui.drawarea->window, gc,
  3220. !                    FALSE,
  3221. !                    FILL_X(gui.col), FILL_Y(gui.row),
  3222. !                    gui.char_width - 1, gui.char_height - 1);
  3223.       }
  3224.       else
  3225.   #endif
  3226. !     gdk_draw_rectangle(gui.drawarea->window, gc,
  3227. !                FALSE,
  3228. !                FILL_X(gui.col), FILL_Y(gui.row),
  3229. !                gui.char_width - 1, gui.char_height - 1);
  3230. !     gdk_gc_destroy(gc);
  3231. ! }
  3232.   
  3233. ! /*
  3234. !  * Draw part of a cursor, "w" pixels wide, and "h" pixels high, using
  3235. !  * color "color".
  3236. !  */
  3237. ! void
  3238. ! gui_mch_draw_part_cursor(int w, int h, GuiColor color)
  3239. ! {
  3240. !     GdkGC *gc;
  3241.   
  3242. !     if (gui.drawarea->window == NULL)
  3243. !     return;
  3244.   
  3245. !     gui_mch_set_fg_color(color);
  3246.   
  3247. !     gc = gdk_gc_new(gui.drawarea->window);
  3248. !     gdk_gc_set_exposures(gc, gui.visibility != GDK_VISIBILITY_UNOBSCURED);
  3249. !     gdk_gc_set_foreground(gc, gui.fgcolor);
  3250. !     gdk_draw_rectangle(gui.drawarea->window, gc,
  3251. !                TRUE,
  3252. ! #ifdef RIGHTLEFT
  3253. !     /* vertical line should be on the right of current point */
  3254. !        State != CMDLINE && curwin->w_p_rl ? FILL_X(gui.col + 1) - w :
  3255. ! #endif
  3256. !                FILL_X(gui.col),
  3257. !                FILL_Y(gui.row) + gui.char_height - h,
  3258. !                w, h);
  3259. !     gdk_gc_destroy(gc);
  3260. ! }
  3261.   
  3262. ! #ifndef GTK_HAVE_FEATURES_1_1_0
  3263. ! static gint
  3264. ! idle_function(GtkWidget * label)
  3265. ! {
  3266. !     if (gtk_main_level() > 0)
  3267. !     gtk_main_quit();
  3268.   
  3269. !     return FALSE;
  3270.   }
  3271. - #endif
  3272.   
  3273.   
  3274. ! /*
  3275. !  * Catch up with any queued X11 events.  This may put keyboard input into the
  3276. !  * input buffer, call resize call-backs, trigger timers etc.  If there is
  3277. !  * nothing in the X11 event queue (& no timers pending), then we return
  3278. !  * immediately.
  3279. !  */
  3280. ! void
  3281. ! gui_mch_update()
  3282.   {
  3283. ! #ifdef GTK_HAVE_FEATURES_1_1_0
  3284. !     while (gtk_events_pending() && !vim_is_input_buf_full())
  3285. !     gtk_main_iteration_do(FALSE);
  3286. ! #else
  3287. !     int pending;
  3288.   
  3289. !     /* Somehow the above loop hangs on GTK 1.0.6.  Use the idle_function() to
  3290. !      * work around this weird problem. */
  3291. !     while (((pending = gtk_events_pending()) > 1) && !vim_is_input_buf_full())
  3292. !     gtk_main_iteration();
  3293.   
  3294. !     if ((pending == 1) && !vim_is_input_buf_full()) {
  3295. !     gtk_idle_add((GtkFunction)idle_function, gui.mainwin);
  3296. !     gtk_main_iteration_do(FALSE);
  3297. !     }
  3298.   #endif
  3299. - }
  3300.   
  3301. ! static gint
  3302. ! input_timer_cb(gpointer data)
  3303. ! {
  3304. !     int *timed_out = (int *) data;
  3305.   
  3306. !     /* Just inform the caller about the accurence of it */
  3307. !     *timed_out = TRUE;
  3308.   
  3309. !     if (gtk_main_level() > 0)
  3310. !     gtk_main_quit();
  3311.   
  3312. !     return FALSE;        /* don't happen again */
  3313.   }
  3314.   
  3315.   /*
  3316. !  * GUI input routine called by gui_wait_for_chars().  Waits for a character
  3317. !  * from the keyboard.
  3318. !  *  wtime == -1     Wait forever.
  3319. !  *  wtime == 0      This should never happen.
  3320. !  *  wtime > 0       Wait wtime milliseconds for a character.
  3321. !  * Returns OK if a character was found to be available within the given time,
  3322. !  * or FAIL otherwise.
  3323.    */
  3324. ! int
  3325. ! gui_mch_wait_for_chars(long wtime)
  3326.   {
  3327. !     int focus;
  3328. !     guint timer;
  3329. !     static int timed_out;
  3330. !     timed_out = FALSE;
  3331. !     /* this timeout makes sure that we will return if no characters arrived in
  3332. !      * time */
  3333. !     if (wtime > 0)
  3334. !     timer = gtk_timeout_add(wtime, input_timer_cb, &timed_out);
  3335. !     else
  3336. !     timer = 0;
  3337. !     focus = gui.in_focus;
  3338. !     do {
  3339. !     /* Stop or start blinking when focus changes */
  3340. !     if (gui.in_focus != focus) {
  3341. !         if (gui.in_focus)
  3342. !         gui_mch_start_blink();
  3343. !         else
  3344. !         gui_mch_stop_blink();
  3345. !         focus = gui.in_focus;
  3346. !     }
  3347. !     /*
  3348. !      * Loop in GTK+ processing  until a timeout or input occurs.
  3349. !      */
  3350. !     gtk_main();
  3351. !     /* Got char, return immediately */
  3352. !     if (!vim_is_input_buf_empty()) {
  3353. !         if (timer != 0 && !timed_out)
  3354. !         gtk_timeout_remove(timer);
  3355. !         return OK;
  3356. !     }
  3357. !     } while (wtime < 0 || !timed_out);
  3358. !     /*
  3359. !      * Flush all eventually pending (drawing) events.
  3360. !      */
  3361. !     gui_mch_update();
  3362. !     return FAIL;
  3363.   }
  3364.   
  3365. ! /****************************************************************************
  3366. !  * Output drawing routines.
  3367. !  ****************************************************************************/
  3368. ! /* Flush any output to the screen */
  3369. ! void
  3370. ! gui_mch_flush()
  3371.   {
  3372. !     gdk_flush();
  3373.   }
  3374.   
  3375.   /*
  3376. !  * Clear a rectangular region of the screen from text pos (row1, col1) to
  3377. !  * (row2, col2) inclusive.
  3378.    */
  3379.   void
  3380. ! gui_mch_clear_block(int row1, int col1, int row2, int col2)
  3381.   {
  3382. !     GdkGC *gc;
  3383. !     GdkColor color;
  3384.   
  3385. -     if (gui.drawarea->window == NULL)
  3386. -     return;
  3387.   
  3388. !     color.pixel = gui.back_pixel;
  3389.   
  3390. !     gc = gdk_gc_new(gui.drawarea->window);
  3391. !     gdk_gc_set_exposures(gc, gui.visibility != GDK_VISIBILITY_UNOBSCURED);
  3392. !     gdk_gc_set_foreground(gc, &color);
  3393.   
  3394. !     /*
  3395. !      * Clear one extra pixel at the right, for when bold characters have
  3396. !      * spilled over to the next column.  This can erase part of the next
  3397. !      * character however in the usage context of this function it will be
  3398. !      * overriden immediately by the correct character again.
  3399. !      */
  3400.   
  3401. !     gdk_draw_rectangle(gui.drawarea->window, gc, TRUE,
  3402. !                FILL_X(col1), FILL_Y(row1),
  3403. !                (col2 - col1 + 1) * gui.char_width + 1,
  3404. !                (row2 - row1 + 1) * gui.char_height);
  3405. !     gdk_gc_destroy(gc);
  3406. ! }
  3407.   
  3408. ! void
  3409. ! gui_mch_clear_all(void)
  3410. ! {
  3411. !     if (gui.drawarea->window == NULL)
  3412. !     return;
  3413.   
  3414. !     gdk_window_clear(gui.drawarea->window);
  3415.   }
  3416.   
  3417.   /*
  3418. !  * Scroll the text between gui.scroll_region_top & gui.scroll_region_bot by the
  3419. !  * number of lines given.  Positive scrolls down (text goes up) and negative
  3420. !  * scrolls up (text goes down).
  3421.    */
  3422. ! static void check_copy_area(void)
  3423.   {
  3424. !     XEvent event;
  3425. !     XGraphicsExposeEvent *gevent;
  3426. !     if (gui.visibility != GDK_VISIBILITY_PARTIAL)
  3427. !     return;
  3428. !     gdk_flush();
  3429. !     /* Wait to check whether the scroll worked or not */
  3430. !     for (;;) {
  3431. !     if (XCheckTypedEvent(GDK_DISPLAY(), NoExpose, &event))
  3432. !         return;        /* The scroll worked. */
  3433.   
  3434. !     if (XCheckTypedEvent(GDK_DISPLAY(), GraphicsExpose, &event)) {
  3435. !         gevent = (XGraphicsExposeEvent *) & event;
  3436. !         gui_redraw(gevent->x, gevent->y, gevent->width, gevent->height);
  3437. !         if (gevent->count == 0)
  3438. !         return;        /* This was the last expose event */
  3439. !     }
  3440. !     gdk_flush();
  3441. !     }
  3442.   }
  3443.   
  3444.   /*
  3445. !  * Delete the given number of lines from the given row, scrolling up any
  3446. !  * text further down within the scroll region.
  3447.    */
  3448.   void
  3449. ! gui_mch_delete_lines(int row, int num_lines)
  3450.   {
  3451. !     if (gui.visibility == GDK_VISIBILITY_FULLY_OBSCURED)
  3452. !     return;            /* Can't see the window */
  3453. !     if (num_lines <= 0)
  3454. !     return;
  3455. !     if (row + num_lines > gui.scroll_region_bot) {
  3456. !     /* Scrolled out of region, just blank the lines out */
  3457. !     gui_clear_block(row, 0, gui.scroll_region_bot, (int) Columns - 1);
  3458. !     } else {
  3459. !     GdkGC *gc;
  3460. !     gc = gdk_gc_new(gui.drawarea->window);
  3461. !     gdk_gc_set_exposures(gc, gui.visibility != GDK_VISIBILITY_UNOBSCURED);
  3462. !     gdk_gc_set_foreground(gc, gui.fgcolor);
  3463. !     gdk_gc_set_background(gc, gui.bgcolor);
  3464. !     /* copy one extra pixel, for when bold has spilled over */
  3465. !     gdk_window_copy_area(gui.drawarea->window, gc,
  3466. !                  FILL_X(0), FILL_Y(row),
  3467. !                  gui.drawarea->window,
  3468. !                  FILL_X(0), FILL_Y(row + num_lines),
  3469. !                  gui.char_width * (int) Columns + 1,
  3470. !                  gui.char_height *
  3471. !                 (gui.scroll_region_bot - row - num_lines + 1));
  3472. !     gdk_gc_destroy(gc);
  3473. !     /* Update gui.cursor_row if the cursor scrolled or copied over */
  3474. !     if (gui.cursor_row >= row) {
  3475. !         if (gui.cursor_row < row + num_lines)
  3476. !         gui.cursor_is_valid = FALSE;
  3477. !         else if (gui.cursor_row <= gui.scroll_region_bot)
  3478. !         gui.cursor_row -= num_lines;
  3479.       }
  3480. !     gui_clear_block(gui.scroll_region_bot - num_lines + 1, 0,
  3481. !             gui.scroll_region_bot, (int) Columns - 1);
  3482. !     check_copy_area();
  3483.       }
  3484.   }
  3485.   
  3486. - /*
  3487. -  * Insert the given number of lines before the given row, scrolling down any
  3488. -  * following text within the scroll region.
  3489. -  */
  3490.   void
  3491. ! gui_mch_insert_lines(int row, int num_lines)
  3492.   {
  3493. !     if (gui.visibility == GDK_VISIBILITY_FULLY_OBSCURED)
  3494. !     return;            /* Can't see the window */
  3495.   
  3496. !     if (num_lines <= 0)
  3497.       return;
  3498.   
  3499. !     if (row + num_lines > gui.scroll_region_bot) {
  3500. !     /* Scrolled out of region, just blank the lines out */
  3501. !     gui_clear_block(row, 0, gui.scroll_region_bot, (int) Columns - 1);
  3502.       } else {
  3503. !     GdkGC *gc;
  3504.   
  3505. !     gc = gdk_gc_new(gui.drawarea->window);
  3506. !     gdk_gc_set_exposures(gc, gui.visibility != GDK_VISIBILITY_UNOBSCURED);
  3507.       gdk_gc_set_foreground(gc, gui.fgcolor);
  3508. !     gdk_gc_set_background(gc, gui.bgcolor);
  3509.   
  3510. !     /* copy one extra pixel, for when bold has spilled over */
  3511. !     gdk_window_copy_area(gui.drawarea->window, gc,
  3512. !                  FILL_X(0), FILL_Y(row + num_lines),
  3513. !                  gui.drawarea->window,
  3514. !                  FILL_X(0), FILL_Y(row),
  3515. !                  gui.char_width * (int) Columns + 1,
  3516. !                  gui.char_height *
  3517. !                 (gui.scroll_region_bot - row - num_lines + 1));
  3518. !     gdk_gc_destroy(gc);
  3519.   
  3520. !     /* Update gui.cursor_row if the cursor scrolled or copied over */
  3521. !     if (gui.cursor_row >= gui.row) {
  3522. !         if (gui.cursor_row <= gui.scroll_region_bot - num_lines)
  3523. !         gui.cursor_row += num_lines;
  3524. !         else if (gui.cursor_row <= gui.scroll_region_bot)
  3525. !         gui.cursor_is_valid = FALSE;
  3526. !     }
  3527. !     gui_clear_block(row, 0, row + num_lines - 1, (int) Columns - 1);
  3528. !     check_copy_area();
  3529.       }
  3530.   }
  3531.   
  3532.   /*
  3533. !  * X Selection stuff, for cutting and pasting text to other windows.
  3534.    */
  3535. ! void
  3536. ! clip_mch_request_selection()
  3537.   {
  3538. !     /* First try to get the content of our own special clipboard. */
  3539. !     received_selection = RS_NONE;
  3540. !     (void)gtk_selection_convert(gui.drawarea,
  3541. !                     GDK_SELECTION_PRIMARY, clipboard.atom,
  3542. !                     GDK_CURRENT_TIME);
  3543. !     while (received_selection == RS_NONE)
  3544. !     gtk_main();        /* wait for selection_received_event */
  3545.   
  3546. !     if (received_selection == RS_FAIL)
  3547. !     {
  3548. !     /* Now try to get it out of the usual string selection. */
  3549. !     received_selection = RS_NONE;
  3550. !     (void)gtk_selection_convert(gui.drawarea, GDK_SELECTION_PRIMARY,
  3551. !                     GDK_TARGET_STRING,
  3552. !                     GDK_CURRENT_TIME);
  3553. !     while (received_selection == RS_NONE)
  3554. !         gtk_main();        /* wait for selection_received_event */
  3555.       }
  3556.   }
  3557.   
  3558.   void
  3559. ! clip_mch_lose_selection()
  3560.   {
  3561. !     gtk_selection_owner_set(gui.drawarea,
  3562. !                      GDK_SELECTION_PRIMARY, GDK_CURRENT_TIME);
  3563. !     gui_mch_update();
  3564.   }
  3565.   
  3566.   /*
  3567. !  * Check whatever we allready own the selection
  3568.    */
  3569. ! int
  3570. ! clip_mch_own_selection()
  3571.   {
  3572. ! #if 0
  3573. !     return gdk_selection_owner_get(
  3574. !                 GDK_SELECTION_PRIMARY) == gui.drawarea->window;
  3575. ! #else
  3576. !     /* At this point we always already own the clipboard */
  3577.   
  3578. !     return OK;
  3579. ! #endif
  3580.   }
  3581.   
  3582.   /*
  3583. !  * Send the current selection to the clipboard.
  3584.    */
  3585.   void
  3586. ! clip_mch_set_selection()
  3587.   {
  3588. !     gtk_selection_owner_set(gui.drawarea,
  3589. !                 GDK_SELECTION_PRIMARY,
  3590. !                 GDK_CURRENT_TIME);
  3591. !     gui_mch_update();
  3592.   }
  3593.   
  3594. - #if defined(WANT_MENU) || defined(PROTO)
  3595.   /*
  3596. !  * Make a menu item appear either active or not active (grey or not grey).
  3597.    */
  3598.   void
  3599. ! gui_mch_menu_grey(VimMenu * menu, int grey)
  3600.   {
  3601. !     if (menu->id == 0)
  3602.       return;
  3603.   
  3604. !     gui_mch_menu_hidden(menu, FALSE);
  3605. !     gtk_widget_set_sensitive(menu->id, !grey);
  3606.   
  3607. !     gui_mch_update();
  3608.   }
  3609.   
  3610.   /*
  3611. !  * Make menu item hidden or not hidden.
  3612.    */
  3613.   void
  3614. ! gui_mch_menu_hidden(VimMenu * menu, int hidden)
  3615.   {
  3616. !     if (menu->id == 0)
  3617.       return;
  3618.   
  3619. !     if (hidden) {
  3620. !     if (GTK_WIDGET_VISIBLE(menu->id))
  3621. !         gtk_widget_hide(menu->id);
  3622. !     } else {
  3623. !     if (!GTK_WIDGET_VISIBLE(menu->id))
  3624. !         gtk_widget_show(menu->id);
  3625. !     }
  3626.   
  3627. !     gui_mch_update();
  3628.   }
  3629.   
  3630. ! /*
  3631. !  * This is called after setting all the menus to grey/hidden or not.
  3632. !  */
  3633. ! void
  3634. ! gui_mch_draw_menubar()
  3635.   {
  3636. !     /* just make sure that the visual changes get effect immediately */
  3637. !     gui_mch_update();
  3638.   }
  3639.   #endif
  3640.   
  3641.   /*
  3642. !  * Scrollbar stuff.
  3643.    */
  3644.   void
  3645. ! gui_mch_enable_scrollbar(GuiScrollbar * sb, int flag)
  3646.   {
  3647. !     if (sb->id == 0)
  3648. !     return;
  3649. !     if (flag)
  3650. !     gtk_widget_show(sb->id);
  3651. !     else
  3652. !     gtk_widget_hide(sb->id);
  3653. !     update_window_manager_hints();
  3654.   }
  3655.   
  3656.   
  3657.   /*
  3658. !  * Return the lightness of a pixel.  White is 255.
  3659. !  *
  3660. !  * FIXME: port it compleatly to GDK.
  3661.    */
  3662.   int
  3663. ! gui_mch_get_lightness(GuiColor pixel)
  3664.   {
  3665. !     XColor xc;
  3666. !     GdkColormap *colormap;
  3667.   
  3668. !     colormap = gtk_widget_get_colormap(gui.mainwin);
  3669. !     xc.pixel = pixel;
  3670. !     XQueryColor(GDK_DISPLAY(), GDK_COLORMAP_XCOLORMAP(colormap), &xc);
  3671.   
  3672. !     return (int) (xc.red * 3 + xc.green * 6 + xc.blue) / (10 * 256);
  3673.   }
  3674.   
  3675. - #if (defined(SYNTAX_HL) && defined(WANT_EVAL)) || defined(PROTO)
  3676.   /*
  3677. !  * Return the RGB value of a pixel as "#RRGGBB".
  3678. !  *
  3679. !  * FIXME: It should be possible to avoid any direct usage of Xlib. Use gdk
  3680. !  * instead!
  3681.    */
  3682. ! char_u *
  3683. ! gui_mch_get_rgb(GuiColor pixel)
  3684.   {
  3685. !     XColor xc;
  3686. !     GdkColormap *colormap;
  3687. !     static char_u retval[10];
  3688. !     static int prevent_congestion = 0; /* Reduce the race! */
  3689.   
  3690. !     while (prevent_congestion)
  3691. !     /* shouldn't we do something here? */;
  3692.   
  3693. !     ++prevent_congestion;
  3694. !     colormap = gtk_widget_get_colormap(gui.mainwin);
  3695.   
  3696. !     xc.pixel = pixel;
  3697. !     XQueryColor(GDK_DISPLAY(), GDK_COLORMAP_XCOLORMAP(colormap), &xc);
  3698.   
  3699. !     sprintf((char *) retval, "#%02x%02x%02x",
  3700. !         (unsigned) xc.red >> 8,
  3701. !         (unsigned) xc.green >> 8,
  3702. !         (unsigned) xc.blue >> 8);
  3703. !     /* hope the following is atomic enought (99.999%) */
  3704. !     --prevent_congestion;
  3705.   
  3706. !     /* WOAH!!! Returning pointer to static string! */
  3707. !     return retval;
  3708.   }
  3709. - #endif
  3710.   
  3711.   /*
  3712. !  * Get current y mouse coordinate in text window.
  3713. !  * Return -1 when unknown.
  3714.    */
  3715. ! int
  3716. ! gui_mch_get_mouse_x(void)
  3717.   {
  3718. !     int winx, winy;
  3719. !     GdkModifierType mask;
  3720.   
  3721. !     if (gdk_window_get_pointer(gui.drawarea->window, &winx, &winy, &mask)) {
  3722. !     if (gui.which_scrollbars[SBAR_LEFT])
  3723. !         return winx;
  3724. !     return winx;
  3725. !     }
  3726. !     return -1;
  3727. ! }
  3728.   
  3729. ! int
  3730. ! gui_mch_get_mouse_y(void)
  3731. ! {
  3732. !     int winx, winy;
  3733. !     GdkModifierType mask;
  3734.   
  3735. !     if (gdk_window_get_pointer(gui.drawarea->window, &winx, &winy, &mask))
  3736. !     return winy;
  3737. !     return -1;
  3738.   }
  3739.   
  3740.   void
  3741. ! gui_mch_setmouse(int x, int y)
  3742.   {
  3743. !     /* Sorry for that, but we can't avoid it, since there seems to be
  3744. !        no internal GDK mechanism present to accomplish this */
  3745. !     XWarpPointer(GDK_DISPLAY(), (Window) 0,
  3746. !          GDK_WINDOW_XWINDOW(gui.drawarea->window), 0, 0, 0, 0, x, y);
  3747. ! }
  3748.   
  3749.   
  3750. ! /*** private function defintions ***/
  3751.   
  3752. ! /* redraw the corresponding portions of the screen */
  3753. ! /*ARGSUSED*/
  3754. ! static gint
  3755. ! expose_event(GtkWidget * widget, GdkEventExpose * event)
  3756. ! {
  3757. !     out_flush();        /* make sure all output has been processed */
  3758. !     gui_redraw(event->area.x, event->area.y,
  3759. !            event->area.width, event->area.height);
  3760.   
  3761. !     /* Clear the border areas if needed */
  3762. !     if (event->area.x < FILL_X(0))
  3763. !     gdk_window_clear_area(gui.drawarea->window, 0, 0, FILL_X(0), 0);
  3764. !     if (event->area.y < FILL_Y(0))
  3765. !     gdk_window_clear_area(gui.drawarea->window, 0, 0, 0, FILL_Y(0));
  3766. !     if (event->area.x > FILL_X(Columns))
  3767. !     gdk_window_clear_area(gui.drawarea->window,
  3768. !                   FILL_X((int)Columns), 0, 0, 0);
  3769. !     if (event->area.y > FILL_Y(Rows))
  3770. !     gdk_window_clear_area(gui.drawarea->window, 0, FILL_Y((int)Rows), 0, 0);
  3771.   
  3772. !     return FALSE;
  3773.   }
  3774.   
  3775. - static guint mouse_click_timer = 0;
  3776. - static int mouse_timed_out = TRUE;
  3777.   /*
  3778. !  * Timer used to recognize multiple clicks of the mouse button
  3779.    */
  3780. ! static gint
  3781. ! mouse_click_timer_cb(gpointer data)
  3782.   {
  3783. !     /* we don't use this information currently */
  3784. !     int *timed_out = (int *) data;
  3785. !     *timed_out = TRUE;
  3786. !     return FALSE;        /* don't happen again */
  3787. ! }
  3788.   
  3789. ! /*
  3790. !  * Mouse button handling. Note please that we are capturing multiple click's by
  3791. !  * our own timeout mechanis instead of the one provided by GTK+ istelf. This is
  3792. !  * due to the way the generic VIM code is recognizing multiple clicks.
  3793. !  */
  3794. ! /*ARGSUSED*/
  3795. ! static gint
  3796. ! button_press_event(GtkWidget * widget, GdkEventButton * event)
  3797. ! {
  3798. !     int button;
  3799. !     int repeated_click = FALSE;
  3800. !     int x, y;
  3801. !     int_u vim_modifiers;
  3802.   
  3803. !     /*
  3804. !      * Don't let additional events about multiple clicks send by GTK to us
  3805. !      * after the inital button press event confuse us.
  3806. !      */
  3807. !     if (event->type != GDK_BUTTON_PRESS)
  3808. !     return FALSE;
  3809.   
  3810. !     x = event->x;
  3811. !     y = event->y;
  3812.   
  3813.   
  3814. !     /* Handle multiple clicks */
  3815. !     if (!mouse_timed_out && mouse_click_timer) {
  3816. !     gtk_timeout_remove(mouse_click_timer);
  3817. !     mouse_click_timer = 0;
  3818. !     repeated_click = TRUE;
  3819.       }
  3820.   
  3821. !     mouse_timed_out = FALSE;
  3822. !     mouse_click_timer = gtk_timeout_add(p_mouset,
  3823. !                   mouse_click_timer_cb, &mouse_timed_out);
  3824.   
  3825. !     switch (event->button)
  3826.       {
  3827. !     case 1:
  3828. !     button = MOUSE_LEFT;
  3829. !     break;
  3830. !     case 2:
  3831. !     button = MOUSE_MIDDLE;
  3832. !     break;
  3833. !     case 3:
  3834. !     button = MOUSE_RIGHT;
  3835. !     break;
  3836. !     case 4:
  3837. !     button = MOUSE_4;
  3838. !     break;
  3839. !     case 5:
  3840. !     button = MOUSE_5;
  3841. !     break;
  3842. !     default:
  3843. !     return FALSE;        /* Unknown button */
  3844.       }
  3845.   
  3846. !     vim_modifiers = 0x0;
  3847. !     if (event->state & GDK_SHIFT_MASK)
  3848. !     vim_modifiers |= MOUSE_SHIFT;
  3849. !     if (event->state & GDK_CONTROL_MASK)
  3850. !     vim_modifiers |= MOUSE_CTRL;
  3851. !     if (event->state & GDK_MOD1_MASK)
  3852. !     vim_modifiers |= MOUSE_ALT;
  3853.   
  3854. !     gui_send_mouse_event(button, x, y, repeated_click, vim_modifiers);
  3855. !     if (gtk_main_level() > 0)
  3856. !     gtk_main_quit();    /* make sure the above will be handled immediately */
  3857.   
  3858. !     return TRUE;
  3859.   }
  3860.   
  3861. - static guint motion_repeat_timer = 0;
  3862.   /*
  3863. !  * Timer used to recognize multiple clicks of the mouse button
  3864.    */
  3865. ! /*ARGSUSED*/
  3866. ! static gint
  3867. ! motion_repeat_timer_cb(gpointer data)
  3868.   {
  3869. !     gint x, y;
  3870. !     GdkModifierType state;
  3871. !     GdkEventMotion event;
  3872. !     gdk_window_get_pointer(gui.drawarea->window, &x, &y, &state);
  3873. !     if (!(state & (GDK_BUTTON1_MASK | GDK_BUTTON3_MASK)))
  3874. !     return FALSE;
  3875. !     /* Fake a motion event. */
  3876. !     event.is_hint = 0;
  3877. !     event.x = x;
  3878. !     event.y = y;
  3879. !     event.state = state;
  3880.   
  3881. -     /* FIXME: argh! for some unknown reason this doesn't lead to nice
  3882. -      * autoscrolling and automatic extension of the selection area.  However
  3883. -      * the autorepeating works nice already.  We need certainly to investigate
  3884. -      * this further.
  3885. -      *
  3886. -      * BTW: It doesn't work properly in the motif version too. So maybe we need
  3887. -      * to look at how it's done in the Windows version again...
  3888. -      *
  3889. -      * I'm assuming that this is somehow related to the gui_mouse_moved
  3890. -      * stuff...
  3891. -      */
  3892.   
  3893. !     motion_notify_event(gui.drawarea, &event);
  3894.   
  3895. !     /* Don't happen again. We will get reinstalled in the synthetic
  3896. !      * event if needed - thus repeating should still work.
  3897. !      */
  3898.   
  3899. !     return FALSE;
  3900.   }
  3901.   
  3902. ! /*ARGSUSED*/
  3903. ! static gint
  3904. ! button_release_event(GtkWidget * widget, GdkEventButton * event)
  3905.   {
  3906. !     int x, y;
  3907. !     int_u vim_modifiers;
  3908.   
  3909. !     /* Remove any motion "mashine gun" timers used for automatic further
  3910. !        extension of allocation areas if outside of the applications window
  3911. !        area .*/
  3912. !     if (motion_repeat_timer) {
  3913. !     gtk_timeout_remove(motion_repeat_timer);
  3914. !     motion_repeat_timer = 0;
  3915.       }
  3916.   
  3917. !     x = event->x;
  3918. !     y = event->y;
  3919. !     vim_modifiers = 0x0;
  3920. !     if (event->state & GDK_SHIFT_MASK)
  3921. !     vim_modifiers |= MOUSE_SHIFT;
  3922. !     if (event->state & GDK_CONTROL_MASK)
  3923. !     vim_modifiers |= MOUSE_CTRL;
  3924. !     if (event->state & GDK_MOD1_MASK)
  3925. !     vim_modifiers |= MOUSE_ALT;
  3926. !     gui_send_mouse_event(MOUSE_RELEASE, x, y, FALSE, vim_modifiers);
  3927. !     if (gtk_main_level() > 0)
  3928. !     gtk_main_quit();        /* make sure it will be handled immediately */
  3929. !     return TRUE;
  3930.   }
  3931.   
  3932. ! /*ARGSUSED*/
  3933. ! static gint
  3934. ! motion_notify_event(GtkWidget * widget, GdkEventMotion * event)
  3935.   {
  3936. !     gint x, y;
  3937. !     GdkModifierType state;
  3938. !     int_u vim_modifiers;
  3939. !     int button;
  3940. !     if (event->is_hint)
  3941. !     gdk_window_get_pointer(event->window, &x, &y, &state);
  3942. !     else {
  3943. !     x = event->x;
  3944. !     y = event->y;
  3945. !     state = event->state;
  3946. !     }
  3947. !     button = (event->state & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK |
  3948. !                   GDK_BUTTON3_MASK | GDK_BUTTON4_MASK |
  3949. !                   GDK_BUTTON5_MASK))
  3950. !           ? MOUSE_DRAG : ' ';
  3951. !     /* If our pointer is currently hidden, then we should show it. */
  3952. !     gui_mch_mousehide(FALSE);
  3953. !     /* Just moving the rodent above the drawing area without
  3954. !        any button beeing pressed. */
  3955. !     if (button != MOUSE_DRAG) {
  3956. !     gui_mouse_moved(y);
  3957. !     return TRUE;
  3958. !     }
  3959. !     vim_modifiers = 0x0;
  3960. !     if (state & GDK_SHIFT_MASK)
  3961. !     vim_modifiers |= MOUSE_SHIFT;
  3962. !     if (state & GDK_CONTROL_MASK)
  3963. !     vim_modifiers |= MOUSE_CTRL;
  3964. !     if (state & GDK_MOD1_MASK)
  3965. !     vim_modifiers |= MOUSE_ALT;
  3966. !     /* inform the editor egine about the occurence of this event */
  3967. !     gui_send_mouse_event(button, x, y, FALSE, vim_modifiers);
  3968. !     if (gtk_main_level() > 0)
  3969. !     gtk_main_quit();
  3970. !     /*
  3971. !      * Auto repeat timer handling.
  3972. !      */
  3973. !     if (x < 0 || y < 0
  3974. !        || x >= gui.drawarea->allocation.width
  3975. !        || y >= gui.drawarea->allocation.height) {
  3976. !     /* just in case remove stale timers */
  3977. !     if (motion_repeat_timer)
  3978. !         gtk_timeout_remove(motion_repeat_timer);
  3979. !     /* shoot again */
  3980. !     motion_repeat_timer = gtk_timeout_add(100,
  3981. !                       motion_repeat_timer_cb, NULL);
  3982. !     }
  3983. !     return TRUE; /* handled */
  3984.   }
  3985.   
  3986.   /*
  3987. !  * Callback routine for the "delete_event" signal on the toplevel window.
  3988. !  * Tries to vim gracefully, or refuses to exit with changed buffers.
  3989.    */
  3990. ! /*ARGSUSED*/
  3991. ! static int
  3992. ! delete_event_cb(GtkWidget *wgt, gpointer cbdata)
  3993.   {
  3994. !     gui_window_closed();
  3995. !     return TRUE;
  3996.   }
  3997.   
  3998.   /*
  3999. !  * Function called when window already closed.
  4000. !  * We can't do much more here than to trying to preserve what had been done,
  4001. !  * since the window is already inevitably going away.
  4002.    */
  4003. ! static void
  4004. ! destroy_callback(void)
  4005.   {
  4006. !     /* preserve files and exit */
  4007. !     preserve_exit();
  4008. !     if (gtk_main_level() > 0)
  4009. !     gtk_main_quit();
  4010.   }
  4011.   
  4012. ! #ifdef GTK_HAVE_FEATURES_1_1_0
  4013.   /*
  4014. !  * Get a font structure for highlighting.
  4015. !  * "cbdata" is a pointer to the global gui structure.
  4016.    */
  4017. ! /*ARGSUSED*/
  4018. ! static void
  4019. ! font_sel_ok(GtkWidget *wgt, gpointer cbdata)
  4020.   {
  4021. !     Gui *vw = (Gui *)cbdata;
  4022. !     GtkFontSelectionDialog *fs = (GtkFontSelectionDialog *)vw->fontdlg;
  4023.   
  4024. !     if (vw->fontname)
  4025. !     g_free(vw->fontname);
  4026.   
  4027. !     vw->fontname = (char_u *)g_strdup(
  4028. !                 gtk_font_selection_dialog_get_font_name(fs));
  4029. !     gtk_widget_hide(vw->fontdlg);
  4030. !     if (gtk_main_level() > 0)
  4031. !     gtk_main_quit();
  4032.   }
  4033.   
  4034. ! /*ARGSUSED*/
  4035. ! static void
  4036. ! font_sel_cancel(GtkWidget *wgt, gpointer cbdata)
  4037.   {
  4038. !     Gui *vw = (Gui *)cbdata;
  4039.   
  4040. !     gtk_widget_hide(vw->fontdlg);
  4041. !     if (gtk_main_level() > 0)
  4042. !     gtk_main_quit();
  4043.   }
  4044.   
  4045. ! /*ARGSUSED*/
  4046. ! static void
  4047. ! font_sel_destroy(GtkWidget *wgt, gpointer cbdata)
  4048.   {
  4049. !     Gui *vw = (Gui *)cbdata;
  4050.   
  4051. !     vw->fontdlg = NULL;
  4052. !     if (gtk_main_level() > 0)
  4053. !     gtk_main_quit();
  4054.   }
  4055. - #endif
  4056. --- 823,3120 ----
  4057.       return OK;
  4058.   }
  4059.   
  4060. + /****************************************************************************
  4061. +  * Mouse handling callbacks
  4062. +  */
  4063. + static guint mouse_click_timer = 0;
  4064. + static int mouse_timed_out = TRUE;
  4065.   /*
  4066. !  * Timer used to recognize multiple clicks of the mouse button
  4067.    */
  4068. ! static gint
  4069. ! mouse_click_timer_cb(gpointer data)
  4070.   {
  4071. !     /* we don't use this information currently */
  4072. !     int *timed_out = (int *) data;
  4073.   
  4074. !     *timed_out = TRUE;
  4075. !     return FALSE;        /* don't happen again */
  4076.   }
  4077.   
  4078. + static guint motion_repeat_timer = 0;
  4079. + static int motion_repeat_offset = FALSE;
  4080. + static gint motion_notify_event(GtkWidget *, GdkEventMotion *);
  4081.   /*
  4082. !  * Timer used to recognize multiple clicks of the mouse button.
  4083.    */
  4084. ! /*ARGSUSED*/
  4085. ! static gint
  4086. ! motion_repeat_timer_cb(gpointer data)
  4087.   {
  4088. !     gint x, y;
  4089. !     GdkModifierType state;
  4090. !     GdkEventMotion event;
  4091.   
  4092. !     gdk_window_get_pointer(gui.drawarea->window, &x, &y, &state);
  4093.   
  4094. !     if (!(state & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK |
  4095. !             GDK_BUTTON3_MASK | GDK_BUTTON4_MASK |
  4096. !             GDK_BUTTON5_MASK)))
  4097. !     {
  4098. !     motion_repeat_timer = 0;
  4099. !     return FALSE;
  4100. !     }
  4101.   
  4102. !     /* If there already is a mouse click in the input buffer, wait another
  4103. !      * time (otherwise we would create a backlog of clicks) */
  4104. !     if (vim_used_in_input_buf() > 10)
  4105. !     return TRUE;
  4106.   
  4107. !     motion_repeat_timer = 0;
  4108. !     /* Fake a motion event.
  4109. !      * Trick: Pretend the mouse moved to the next character on every other
  4110. !      * event, otherwise drag events will be discarded, because they are still
  4111. !      * in the same character. */
  4112. !     event.is_hint = FALSE;
  4113. !     if (motion_repeat_offset)
  4114. !     {
  4115. !     event.x = x + gui.char_width;
  4116. !     motion_repeat_offset = FALSE;
  4117. !     }
  4118. !     else
  4119. !     {
  4120. !     event.x = x;
  4121. !     motion_repeat_offset = TRUE;
  4122. !     }
  4123. !     event.y = y;
  4124. !     event.state = state;
  4125. !     motion_notify_event(gui.drawarea, &event);
  4126. !     /* Don't happen again. We will get reinstalled in the synthetic event if
  4127. !      * needed - thus repeating should still work.
  4128. !      */
  4129. !     return FALSE;
  4130.   }
  4131.   
  4132. ! /*ARGSUSED*/
  4133. ! static gint
  4134. ! motion_notify_event(GtkWidget * widget, GdkEventMotion * event)
  4135.   {
  4136. !     gint x, y;
  4137. !     GdkModifierType state;
  4138. !     int_u vim_modifiers;
  4139. !     int button;
  4140.   
  4141. !     if (event->is_hint)
  4142. !     gdk_window_get_pointer(event->window, &x, &y, &state);
  4143. !     else {
  4144. !     x = event->x;
  4145. !     y = event->y;
  4146. !     state = event->state;
  4147. !     }
  4148.   
  4149. !     button = (event->state & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK |
  4150. !                   GDK_BUTTON3_MASK | GDK_BUTTON4_MASK |
  4151. !                   GDK_BUTTON5_MASK))
  4152. !           ? MOUSE_DRAG : ' ';
  4153.   
  4154. !     /* If our pointer is currently hidden, then we should show it. */
  4155. !     gui_mch_mousehide(FALSE);
  4156.   
  4157. !     /* Just moving the rodent above the drawing area without any button beeing
  4158. !      * pressed. */
  4159. !     if (button != MOUSE_DRAG) {
  4160. !     gui_mouse_moved(y);
  4161. !     return TRUE;
  4162. !     }
  4163.   
  4164. !     /* translate modifier coding between the main engine and GTK */
  4165. !     vim_modifiers = 0x0;
  4166. !     if (state & GDK_SHIFT_MASK)
  4167. !     vim_modifiers |= MOUSE_SHIFT;
  4168. !     if (state & GDK_CONTROL_MASK)
  4169. !     vim_modifiers |= MOUSE_CTRL;
  4170. !     if (state & GDK_MOD1_MASK)
  4171. !     vim_modifiers |= MOUSE_ALT;
  4172.   
  4173. !     /* inform the editor egine about the occurence of this event */
  4174. !     gui_send_mouse_event(button, x, y, FALSE, vim_modifiers);
  4175. !     if (gtk_main_level() > 0)
  4176. !     gtk_main_quit();
  4177.   
  4178. +     /*
  4179. +      * Auto repeat timer handling.
  4180. +      */
  4181. +     if (x < 0 || y < 0
  4182. +         || x >= gui.drawarea->allocation.width
  4183. +         || y >= gui.drawarea->allocation.height) {
  4184.   
  4185. !     int dx;
  4186. !     int dy;
  4187. !     int offshoot;
  4188. !     int delay = 10;
  4189.   
  4190. !     /* Calculate the maximal distance of the cursor from the drawing area.
  4191. !      * (offshoot can't become negative here!).
  4192. !      */
  4193. !     dx = x < 0 ? -x : x - gui.drawarea->allocation.width;
  4194. !     dy = y < 0 ? -y : y - gui.drawarea->allocation.height;
  4195.   
  4196. !     offshoot = dx > dy ? dx : dy;
  4197.   
  4198. !     /* Make a linearly declaying timer delay with a threshold of 5 at a
  4199. !      * distance of 127 pixels from the main window.
  4200. !      *
  4201. !      * One could think endlessly about the most ergonomic variant here.
  4202. !      * For example it could make sense to calculate the distance from the
  4203. !      * drags start instead...
  4204. !      *
  4205. !      * Maybe a parabolic interpolation would suite us better here too...
  4206. !      */
  4207. !     if (offshoot > 127) {
  4208. !         /* 5 appears to be somehow near to my perceptual limits :-). */
  4209. !         delay = 5;
  4210. !     } else {
  4211. !         delay = (130 * (127 - offshoot)) / 127 + 5;
  4212. !     }
  4213.   
  4214. !     /* shoot again */
  4215. !     if (!motion_repeat_timer)
  4216. !         motion_repeat_timer = gtk_timeout_add((guint32)delay,
  4217. !                         motion_repeat_timer_cb, NULL);
  4218. !     }
  4219.   
  4220. !     return TRUE; /* handled */
  4221. ! }
  4222.   
  4223.   
  4224. ! /*
  4225. !  * Mouse button handling.  Note please that we are capturing multiple click's
  4226. !  * by our own timeout mechanism instead of the one provided by GTK+ istelf.
  4227. !  * This is due to the way the generic VIM code is recognizing multiple clicks.
  4228. !  */
  4229. ! /*ARGSUSED*/
  4230. ! static gint
  4231. ! button_press_event(GtkWidget * widget, GdkEventButton * event)
  4232. ! {
  4233. !     int button;
  4234. !     int repeated_click = FALSE;
  4235. !     int x, y;
  4236. !     int_u vim_modifiers;
  4237.   
  4238.       /*
  4239. !      * Don't let additional events about multiple clicks send by GTK to us
  4240. !      * after the inital button press event confuse us.
  4241.        */
  4242. !     if (event->type != GDK_BUTTON_PRESS)
  4243. !     return FALSE;
  4244.   
  4245. !     x = event->x;
  4246. !     y = event->y;
  4247.   
  4248. !     /* Handle multiple clicks */
  4249. !     if (!mouse_timed_out && mouse_click_timer) {
  4250. !     gtk_timeout_remove(mouse_click_timer);
  4251. !     mouse_click_timer = 0;
  4252. !     repeated_click = TRUE;
  4253.       }
  4254.   
  4255. !     mouse_timed_out = FALSE;
  4256. !     mouse_click_timer = gtk_timeout_add((guint32)p_mouset,
  4257. !                   mouse_click_timer_cb, &mouse_timed_out);
  4258.   
  4259. !     switch (event->button) {
  4260. !     case 1:
  4261. !     button = MOUSE_LEFT;
  4262. !     break;
  4263. !     case 2:
  4264. !     button = MOUSE_MIDDLE;
  4265. !     break;
  4266. !     case 3:
  4267. !     button = MOUSE_RIGHT;
  4268. !     break;
  4269. !     case 4:
  4270. !     button = MOUSE_4;
  4271. !     break;
  4272. !     case 5:
  4273. !     button = MOUSE_5;
  4274. !     break;
  4275. !     default:
  4276. !     return FALSE;        /* Unknown button */
  4277. !     }
  4278.   
  4279. !     vim_modifiers = 0x0;
  4280. !     if (event->state & GDK_SHIFT_MASK)
  4281. !     vim_modifiers |= MOUSE_SHIFT;
  4282. !     if (event->state & GDK_CONTROL_MASK)
  4283. !     vim_modifiers |= MOUSE_CTRL;
  4284. !     if (event->state & GDK_MOD1_MASK)
  4285. !     vim_modifiers |= MOUSE_ALT;
  4286.   
  4287. !     gui_send_mouse_event(button, x, y, repeated_click, vim_modifiers);
  4288. !     if (gtk_main_level() > 0)
  4289. !     gtk_main_quit();    /* make sure the above will be handled immediately */
  4290.   
  4291. !     return TRUE;
  4292.   }
  4293.   
  4294. ! /*ARGSUSED*/
  4295. ! static gint
  4296. ! button_release_event(GtkWidget * widget, GdkEventButton * event)
  4297.   {
  4298. !     int x, y;
  4299. !     int_u vim_modifiers;
  4300. !     /* Remove any motion "mashine gun" timers used for automatic further
  4301. !        extension of allocation areas if outside of the applications window
  4302. !        area .*/
  4303. !     if (motion_repeat_timer) {
  4304. !     gtk_timeout_remove(motion_repeat_timer);
  4305. !     motion_repeat_timer = 0;
  4306.       }
  4307. +     x = event->x;
  4308. +     y = event->y;
  4309. +     vim_modifiers = 0x0;
  4310. +     if (event->state & GDK_SHIFT_MASK)
  4311. +     vim_modifiers |= MOUSE_SHIFT;
  4312. +     if (event->state & GDK_CONTROL_MASK)
  4313. +     vim_modifiers |= MOUSE_CTRL;
  4314. +     if (event->state & GDK_MOD1_MASK)
  4315. +     vim_modifiers |= MOUSE_ALT;
  4316. +     gui_send_mouse_event(MOUSE_RELEASE, x, y, FALSE, vim_modifiers);
  4317. +     if (gtk_main_level() > 0)
  4318. +     gtk_main_quit();        /* make sure it will be handled immediately */
  4319. +     return TRUE;
  4320.   }
  4321.   
  4322.   
  4323. + #ifdef GTK_DND
  4324. + /****************************************************************************
  4325. +  * Drag aNd Drop support handlers.
  4326. +  */
  4327. + /*
  4328. +  * DND receiver.
  4329. +  */
  4330. + /*ARGSUSED*/
  4331.   static void
  4332. ! drag_data_received(GtkWidget *widget, GdkDragContext *context,
  4333. !     gint x, gint y,
  4334. !     GtkSelectionData *data,
  4335. !     guint info, guint time)
  4336. ! {
  4337. !     char_u    **fnames;
  4338. !     int        redo_dirs = FALSE;
  4339. !     int        i;
  4340. !     int        n;
  4341. !     char    *start;
  4342. !     char    *stop;
  4343. !     char    *copy;
  4344. !     int        nfiles;
  4345. !     GdkModifierType current_modifiers;
  4346. !     /* Get the current modifier state for proper distinguishment between
  4347. !      * different operations later. */
  4348. !     current_modifiers = 0;
  4349. !     gdk_window_get_pointer(NULL, NULL, NULL, ¤t_modifiers);
  4350. !     /* guard against trash */
  4351. !     if (((data->length <=  0) && (data->format != 8))
  4352. !         || (((char *)data->data)[data->length] != '\0')) {
  4353. !     gtk_drag_finish(context, FALSE, FALSE, time);
  4354.   
  4355. !     return;
  4356. !     }
  4357.   
  4358. !     /* Count how meny items there may be there and normalize
  4359. !      * delimiters.
  4360. !      */
  4361. !     n = 1;
  4362. !     copy = strdup((char *)data->data);
  4363. !     for (i = 0; i < data->length; ++i) {
  4364. !     if (copy[i] == '\n')
  4365. !         ++n;
  4366. !     else if(copy[i] == '\r') {
  4367. !         copy[i] = '\n';
  4368. !         ++n;
  4369. !     }
  4370. !     }
  4371.   
  4372. !     fnames = (char_u **) alloc((n + 1) * sizeof(char_u *));
  4373.   
  4374. !     start = copy;
  4375. !     stop = copy;
  4376. !     nfiles = 0;
  4377. !     for (i = 0; i < n; ++i) {
  4378. !     stop = strchr(start, '\n');
  4379. !     if (stop)
  4380. !         *stop = '\0';
  4381. !     if (!strlen(start))
  4382. !         continue;
  4383. !     if (strncmp(start, "file:", 5)) {
  4384. !         int j;
  4385. !         free(copy);
  4386. !         for (j = 0; j < nfiles; ++j)
  4387. !         free(fnames[j]);
  4388. !         gtk_drag_finish(context, FALSE, FALSE, time);
  4389.   
  4390. !         return;
  4391. !     }
  4392. !     if (!strncmp(start, "file://localhost", 16)) {
  4393. !         fnames[nfiles] = (char_u *)strdup(start + 16);
  4394. !         ++nfiles;
  4395. !     } else {
  4396. !         fnames[nfiles] = (char_u *)strdup(start + 5);
  4397. !         ++nfiles;
  4398. !     }
  4399. !     start = stop + 2;
  4400. !     }
  4401. !     free(copy);
  4402. !     /* accept */
  4403. !     gtk_drag_finish (context, TRUE, FALSE, time);
  4404.   
  4405.       /*
  4406. !      * Handle dropping a directory on Vim.
  4407.        */
  4408. !     if (nfiles == 1) {
  4409. !     if (mch_isdir(fnames[0])) {
  4410. !         if (mch_chdir((char *)fnames[0]) == 0) {
  4411. !         free(fnames[0]);
  4412. !         fnames[0] = NULL;
  4413. !         redo_dirs = TRUE;
  4414. !         }
  4415. !     }
  4416. !     } else {
  4417. !     /* Ignore any directories */
  4418. !     for (i = 0; i < nfiles; ++i) {
  4419. !         if (mch_isdir(fnames[i])) {
  4420. !         free(fnames[i]);
  4421. !         fnames[i] = NULL;
  4422. !         }
  4423. !     }
  4424. !     }
  4425.   
  4426. !     if (current_modifiers & GDK_SHIFT_MASK) {
  4427. !     /* Shift held down, change to first file's directory */
  4428. !     if (fnames[0] != NULL && vim_chdirfile(fnames[0]) == 0)
  4429. !         redo_dirs = TRUE;
  4430. !     }
  4431.   
  4432. !     /* Handle the drop, :edit or :split to get to the file */
  4433. !     handle_drop(nfiles, fnames, current_modifiers & GDK_CONTROL_MASK);
  4434. !     if (redo_dirs)
  4435. !     shorten_fnames(TRUE);
  4436. !     /* Update the screen display */
  4437. !     update_screen(NOT_VALID);
  4438. !     setcursor();
  4439. !     out_flush();
  4440.   }
  4441. + #endif /* GTK_DND */
  4442.   
  4443.   /*
  4444. !  * Setup the window icon after the main window has bee realized.
  4445.    */
  4446.   /*ARGSUSED*/
  4447. ! static void
  4448. ! mainwin_realize(GtkWidget *widget)
  4449.   {
  4450. ! /* If you get an error message here, you still need to unpack the runtime
  4451. !  * archive! */
  4452. ! #include "../runtime/vim32x32.xpm"
  4453. !     static GdkPixmap *icon = NULL;
  4454. !     static GdkBitmap *icon_mask = NULL;
  4455.   
  4456. !     if (!icon)
  4457. !     icon = gdk_pixmap_create_from_xpm_d(gui.mainwin->window,
  4458. !                             &icon_mask, NULL, magick);
  4459. !     gdk_window_set_icon(gui.mainwin->window, NULL, icon, icon_mask);
  4460.   }
  4461.   
  4462.   /*
  4463. !  * After the drawing area comes up, we calculate all colors and create the
  4464. !  * dummy blank cursor.
  4465. !  *
  4466. !  * Don't try to set any VIM scrollbar sizes anywhere here. I'm relying on the
  4467. !  * fact that the main VIM engine doesn't take them into account anywhere.
  4468.    */
  4469. ! static void
  4470. ! drawarea_realize_cb(GtkWidget *widget)
  4471.   {
  4472. !     char blank_data[] = {0x0};
  4473. !     GdkPixmap *blank_mask;
  4474. !     GdkColor color;
  4475. !     GtkWidget *sbar;
  4476.   
  4477. ! #ifdef USE_XIM
  4478. !     xim_init();
  4479.   #endif
  4480. +     gui_mch_new_colors();
  4481.   
  4482. !     blank_mask = gdk_bitmap_create_from_data(NULL, blank_data, 1, 1);
  4483. !     gdk_color_white(gdk_colormap_get_system(), &color);
  4484. !     gui.blank_pointer = gdk_cursor_new_from_pixmap(blank_mask, blank_mask,
  4485. !                             &color, &color, 0, 0);
  4486. !     gdk_bitmap_unref(blank_mask);
  4487. !     if (gui.pointer_hidden)
  4488. !         gdk_window_set_cursor(widget->window, gui.blank_pointer);
  4489.   
  4490. !     /* get the actual size of the scrollbars, if they are realized */
  4491. !     sbar = firstwin->w_scrollbars[SBAR_LEFT].id;
  4492. !     if (!sbar || (!gui.which_scrollbars[SBAR_LEFT]
  4493. !                     && firstwin->w_scrollbars[SBAR_RIGHT].id))
  4494. !     sbar = firstwin->w_scrollbars[SBAR_RIGHT].id;
  4495. !     if (sbar && GTK_WIDGET_REALIZED(sbar) && sbar->allocation.width)
  4496. !     gui.scrollbar_width = sbar->allocation.width;
  4497.   
  4498. !     sbar = gui.bottom_sbar.id;
  4499. !     if (sbar && GTK_WIDGET_REALIZED(sbar) && sbar->allocation.height)
  4500. !     gui.scrollbar_height = sbar->allocation.height;
  4501.   }
  4502.   
  4503. ! /*
  4504. !  * Callback routine for the "delete_event" signal on the toplevel window.
  4505. !  * Tries to vim gracefully, or refuses to exit with changed buffers.
  4506. !  */
  4507.   /*ARGSUSED*/
  4508. ! static int
  4509. ! delete_event_cb(GtkWidget *wgt, gpointer cbdata)
  4510.   {
  4511. !     gui_window_closed();
  4512. !     return TRUE;
  4513.   }
  4514.   
  4515.   /*
  4516. !  * Initialise the X GUI.  Create all the windows, set up all the call-backs etc.
  4517. !  * Returns OK for success, FAIL when the GUI can't be started.
  4518.    */
  4519.   int
  4520. ! gui_mch_init()
  4521.   {
  4522. !     GtkWidget *vbox;
  4523.   
  4524. !     /* Initialize values */
  4525. !     gui.rev_video = FALSE;
  4526. !     gui.border_width = 2;
  4527. !     gui.scrollbar_width = SB_DEFAULT_WIDTH;
  4528. !     gui.scrollbar_height = SB_DEFAULT_WIDTH;
  4529. !     gui.fgcolor = g_new0(GdkColor, 1);
  4530. !     gui.bgcolor = g_new0(GdkColor, 1);
  4531.   
  4532. ! #ifdef WANT_MENU
  4533. !     /* Don't change the menu height values used in gui.c at runtime */
  4534. !     gui.menu_height_fixed = TRUE;
  4535. ! #endif
  4536.   
  4537. !     /* Set default foreground and background colours. */
  4538. !     gui.norm_pixel = gui.def_norm_pixel;
  4539. !     gui.back_pixel = gui.def_back_pixel;
  4540.   
  4541. !     gui.mainwin = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  4542. !     gtk_window_set_policy(GTK_WINDOW(gui.mainwin), TRUE, TRUE, TRUE);
  4543. !     gtk_container_border_width(GTK_CONTAINER(gui.mainwin), 0);
  4544. !     gtk_widget_set_events(gui.mainwin, GDK_VISIBILITY_NOTIFY_MASK);
  4545. !     (void)gtk_signal_connect(GTK_OBJECT(gui.mainwin), "delete_event",
  4546. !                  GTK_SIGNAL_FUNC(delete_event_cb), NULL);
  4547.   
  4548. +     /* Add an icon to the main window. For fun and convenience of the user. */
  4549. +     if (vim_strchr(p_go, GO_ICON) != NULL)
  4550. +     gtk_signal_connect(GTK_OBJECT(gui.mainwin), "realize",
  4551. +                       GTK_SIGNAL_FUNC(mainwin_realize), NULL);
  4552.   
  4553.   
  4554. ! #ifdef GTK_HAVE_FEATURES_1_1_0
  4555. !     /* FIXME: this should eventually get the accelgroup of the gui.mainwin */
  4556. !     gui.accel_group = gtk_accel_group_get_default();
  4557.   #endif
  4558.   
  4559. !     vbox = gtk_vbox_new(FALSE, 0);
  4560. !     gtk_container_add(GTK_CONTAINER(gui.mainwin), vbox);
  4561. !     gtk_widget_show(vbox);
  4562.   
  4563. ! #ifdef WANT_MENU
  4564. !     /* create the menubar and handle */
  4565. !     gui.menubar = gtk_menu_bar_new();
  4566. !     gtk_widget_show(gui.menubar);
  4567. !     gtk_box_pack_start(GTK_BOX(vbox), gui.menubar, FALSE, TRUE, 0);
  4568.   #endif
  4569.   
  4570. ! #ifdef USE_TOOLBAR
  4571. !     /* create the toolbar */
  4572. !     if (p_toolbar) {
  4573.       if (strstr((const char *)p_toolbar, "text")
  4574. !         && strstr((const char *)p_toolbar, "icons"))
  4575. !         gui.toolbar =
  4576. !         gtk_toolbar_new(GTK_ORIENTATION_HORIZONTAL, GTK_TOOLBAR_BOTH);
  4577. !     else if (strstr((const char *)p_toolbar, "text"))
  4578. !         gui.toolbar =
  4579. !         gtk_toolbar_new(GTK_ORIENTATION_HORIZONTAL, GTK_TOOLBAR_TEXT);
  4580.       else
  4581. !         gui.toolbar =
  4582. !         gtk_toolbar_new(GTK_ORIENTATION_HORIZONTAL, GTK_TOOLBAR_ICONS);
  4583. !     } else
  4584. !     gui.toolbar =
  4585. !         gtk_toolbar_new(GTK_ORIENTATION_HORIZONTAL, GTK_TOOLBAR_ICONS);
  4586.   
  4587. !     gtk_widget_show(gui.toolbar);
  4588. ! # ifdef GTK_HAVE_FEATURES_1_1_0
  4589. !     /* some aesthetics on the toolbar */
  4590. !     gtk_toolbar_set_button_relief(GTK_TOOLBAR(gui.toolbar), GTK_RELIEF_NONE);
  4591. ! # endif
  4592. !     gtk_container_border_width(GTK_CONTAINER(gui.toolbar), 1);
  4593. !     gtk_box_pack_start(GTK_BOX(vbox), gui.toolbar, FALSE, TRUE, 0);
  4594.   #endif
  4595.   
  4596. +     gui.formwin = gtk_form_new();
  4597. +     gtk_container_border_width(GTK_CONTAINER(gui.formwin), 0);
  4598. +     gtk_widget_set_events(gui.formwin, GDK_EXPOSURE_MASK);
  4599.   
  4600. !     gui.drawarea = gtk_drawing_area_new();
  4601.   
  4602. !     /* Determine which events we will filter. */
  4603. !     gtk_widget_set_events(gui.drawarea,
  4604. !               GDK_EXPOSURE_MASK |
  4605. !               GDK_ENTER_NOTIFY_MASK |
  4606. !               GDK_LEAVE_NOTIFY_MASK |
  4607. !               GDK_BUTTON_PRESS_MASK |
  4608. !               GDK_BUTTON_RELEASE_MASK |
  4609. !               GDK_POINTER_MOTION_MASK |
  4610. !               GDK_POINTER_MOTION_HINT_MASK);
  4611.   
  4612. !     gtk_widget_show(gui.drawarea);
  4613. !     gtk_form_put(GTK_FORM(gui.formwin), gui.drawarea, 0, 0);
  4614. !     gtk_widget_show(gui.formwin);
  4615. !     gtk_box_pack_start(GTK_BOX(vbox), gui.formwin, TRUE, TRUE, 0);
  4616.   
  4617. !     gtk_signal_connect(GTK_OBJECT(gui.mainwin), "key_press_event",
  4618. !                (GtkSignalFunc) key_press_event, NULL);
  4619. !     gtk_signal_connect(GTK_OBJECT(gui.drawarea), "realize",
  4620. !                GTK_SIGNAL_FUNC(drawarea_realize_cb), NULL);
  4621. !     /* Check if reverse video needs to be applied (on Sun it's done by X) */
  4622. !     if (gui.rev_video && gui_mch_get_lightness(gui.back_pixel)
  4623. !     > gui_mch_get_lightness(gui.norm_pixel)) {
  4624. !     gui.norm_pixel = gui.def_back_pixel;
  4625. !     gui.back_pixel = gui.def_norm_pixel;
  4626. !     gui.def_norm_pixel = gui.norm_pixel;
  4627. !     gui.def_back_pixel = gui.back_pixel;
  4628.       }
  4629. +     gui.visibility = GDK_VISIBILITY_UNOBSCURED;
  4630. +     clipboard.atom = gdk_atom_intern("_VIM_TEXT", FALSE);
  4631. +     save_yourself_atom = gdk_atom_intern("WM_SAVE_YOURSELF", FALSE);
  4632. +     reread_rcfiles_atom = gdk_atom_intern("_GTK_READ_RCFILES", FALSE);
  4633.   
  4634. !     /*
  4635. !      * Start out by adding the configured border width into the border offset.
  4636. !      */
  4637. !     gui.border_offset = gui.border_width;
  4638.   
  4639. ! #ifdef GTK_HAVE_FEATURES_1_1_0
  4640. !     gtk_signal_connect(GTK_OBJECT(gui.mainwin), "visibility_notify_event",
  4641. !                GTK_SIGNAL_FUNC(visibility_event), NULL);
  4642.   #endif
  4643. +     gtk_signal_connect(GTK_OBJECT(gui.drawarea), "expose_event",
  4644. +                GTK_SIGNAL_FUNC(expose_event), NULL);
  4645.   
  4646. !     /*
  4647. !      * Only install these enter/leave callbacks when 'p' in 'guioptions'.
  4648. !      * Only needed for some window managers.
  4649. !      */
  4650. !     if (vim_strchr(p_go, GO_POINTER) != NULL) {
  4651. !     gtk_signal_connect(GTK_OBJECT(gui.drawarea), "leave_notify_event",
  4652. !                GTK_SIGNAL_FUNC(leave_notify_event), NULL);
  4653. !     gtk_signal_connect(GTK_OBJECT(gui.drawarea), "enter_notify_event",
  4654. !                GTK_SIGNAL_FUNC(enter_notify_event), NULL);
  4655.       }
  4656.   
  4657. !     gtk_signal_connect(GTK_OBJECT(gui.mainwin), "focus_out_event",
  4658. !                GTK_SIGNAL_FUNC(focus_out_event), NULL);
  4659. !     gtk_signal_connect(GTK_OBJECT(gui.mainwin), "focus_in_event",
  4660. !                GTK_SIGNAL_FUNC(focus_in_event), NULL);
  4661.   
  4662. !     gtk_signal_connect(GTK_OBJECT(gui.drawarea), "motion_notify_event",
  4663. !                GTK_SIGNAL_FUNC(motion_notify_event), NULL);
  4664. !     gtk_signal_connect(GTK_OBJECT(gui.drawarea), "button_press_event",
  4665. !                GTK_SIGNAL_FUNC(button_press_event), NULL);
  4666. !     gtk_signal_connect(GTK_OBJECT(gui.drawarea), "button_release_event",
  4667. !                GTK_SIGNAL_FUNC(button_release_event), NULL);
  4668.   
  4669. !     /*
  4670. !      * Add selection handler functions.
  4671. !      */
  4672. !     gtk_signal_connect(GTK_OBJECT(gui.drawarea), "selection_clear_event",
  4673. !                GTK_SIGNAL_FUNC(selection_clear_event), NULL);
  4674. !     gtk_signal_connect(GTK_OBJECT(gui.drawarea), "selection_received",
  4675. !                GTK_SIGNAL_FUNC(selection_received_event), NULL);
  4676.   
  4677. !     /* gtk_selection_add_target() is not in GTK 1.1.2 */
  4678. ! #ifdef GTK_HAVE_FEATURES_1_1_4
  4679. !     gtk_selection_add_target(gui.drawarea, GDK_SELECTION_PRIMARY,
  4680. !                 GDK_TARGET_STRING, SELECTION_STRING);
  4681. !     gtk_selection_add_target(gui.drawarea, GDK_SELECTION_PRIMARY,
  4682. !                 clipboard.atom, SELECTION_CLIPBOARD);
  4683. !     gtk_signal_connect(GTK_OBJECT(gui.drawarea), "selection_get",
  4684. !                GTK_SIGNAL_FUNC(selection_get_event), NULL);
  4685. ! #else
  4686. !     gtk_selection_add_handler(gui.drawarea, GDK_SELECTION_PRIMARY,
  4687. !                   GDK_TARGET_STRING, selection_handler, NULL);
  4688. !     gtk_selection_add_handler(gui.drawarea, GDK_SELECTION_PRIMARY,
  4689. !                   clipboard.atom, selection_handler, NULL);
  4690. ! #endif
  4691.   
  4692. !     /* Pretend we don't have input focus, we will get an event if we do. */
  4693. !     gui.in_focus = FALSE;
  4694.   
  4695. !     return OK;
  4696. ! }
  4697.   
  4698.   
  4699. ! /*
  4700. !  * Called when the foreground or background color has been changed.
  4701. !  */
  4702. ! void
  4703. ! gui_mch_new_colors()
  4704. ! {
  4705. !     /* This used to change the graphics contexts directly but we are currently
  4706. !      * manipulating them where desired.
  4707. !      */
  4708. !     if (gui.drawarea && gui.drawarea->window) {
  4709. !     GdkColor color;
  4710. !     color.pixel = gui.back_pixel;
  4711. !     gdk_window_set_background(gui.drawarea->window, &color);
  4712.       }
  4713. ! }
  4714. ! #ifdef GTK_HAVE_FEATURES_1_1_6
  4715. ! # define USE_GEOMETRY_FOR_HINTS        1
  4716.   #endif
  4717.   
  4718. ! static void
  4719. ! update_window_manager_hints(void)
  4720. ! {
  4721. !     int width;
  4722. !     int height;
  4723. ! #ifdef USE_GEOMETRY_FOR_HINTS
  4724. !     GdkGeometry geometry;
  4725. !     GdkWindowHints geometry_mask;
  4726.   
  4727. !     /* This also needs to be done when the main window isn't there yet,
  4728. !      * otherwise the hints don't work. */
  4729. !     width = gui_get_base_width();
  4730. !     height = gui_get_base_height();
  4731.   
  4732. !     geometry_mask = GDK_HINT_BASE_SIZE|GDK_HINT_RESIZE_INC|GDK_HINT_MIN_SIZE;
  4733. !     geometry.width_inc = gui.char_width;
  4734. !     geometry.height_inc = gui.char_height;
  4735. !     geometry.base_width = width;
  4736. !     geometry.base_height = height;
  4737. !     geometry.min_width = width + MIN_COLUMNS * gui.char_width;
  4738. !     geometry.min_height = height + MIN_LINES * gui.char_height;
  4739. !     gtk_window_set_geometry_hints(GTK_WINDOW(gui.mainwin), gui.formwin,
  4740. !                   &geometry, geometry_mask);
  4741. ! #else
  4742. !     XSizeHints size_hints;
  4743.   
  4744. !     /* Don't set the size until the main window is really there */
  4745. !     if (!GTK_WIDGET_REALIZED(gui.mainwin))
  4746. !     return;
  4747.   
  4748. !     width = gui_get_base_width();
  4749. !     height = gui_get_base_height();
  4750.   
  4751. !     /* The hints don't automatically take the menubar and toolbar into
  4752. !      * account.  Need to add their height here, if they are visible. */
  4753. ! # ifdef USE_TOOLBAR
  4754. !     if (gui.toolbar && GTK_WIDGET_REALIZED(gui.toolbar)
  4755. !         && GTK_WIDGET_VISIBLE(gui.toolbar))
  4756. !     height += gui.toolbar->allocation.height;
  4757. ! # endif
  4758. ! # ifdef WANT_MENU
  4759. !     if (gui.menubar && GTK_WIDGET_REALIZED(gui.menubar)
  4760. !         && GTK_WIDGET_VISIBLE(gui.menubar))
  4761. !     height += gui.menubar->allocation.height;
  4762. ! # endif
  4763.   
  4764. !     /*
  4765. !      * Argh!!! Once again we need to deal with an ommission in GTK+ by
  4766. !      * resorting to direct Xlib calls. Fortunatly I know how to do it :-).
  4767. !      */
  4768. !     size_hints.flags = (PResizeInc | PBaseSize | PMinSize | PSize);
  4769. !     size_hints.width_inc = gui.char_width;
  4770. !     size_hints.height_inc = gui.char_height;
  4771. !     size_hints.base_width = width;
  4772. !     size_hints.base_height = height;
  4773. !     size_hints.min_width = width + MIN_COLUMNS * gui.char_width;
  4774. !     size_hints.min_height = height + MIN_LINES * gui.char_height;
  4775.   
  4776. !     /* This is only needed for "older" window managers.  See a corresposning
  4777. !      * comment in the X11 headers. */
  4778. !     size_hints.width = width + Columns * gui.char_width;
  4779. !     size_hints.height = height + Rows * gui.char_height;
  4780.   
  4781. !     XSetWMNormalHints(GDK_DISPLAY(),
  4782. !               GDK_WINDOW_XWINDOW(gui.mainwin->window),
  4783. !               &size_hints);
  4784. ! #endif    /* USE_GEOMETRY_FOR_HINTS */
  4785. ! }
  4786.   
  4787. ! /*
  4788. !  * This signal informs us about the need to rearrange our subwidgets.
  4789. !  */
  4790. ! /*ARGSUSED*/
  4791. ! static gint
  4792. ! form_configure_event(GtkWidget * widget, GdkEventConfigure * event)
  4793. ! {
  4794. !     gtk_form_freeze(GTK_FORM(gui.formwin));
  4795. !     gui_resize_window(event->width, event->height);
  4796. !     gtk_form_thaw(GTK_FORM(gui.formwin));
  4797.   
  4798. !     return TRUE;
  4799. ! }
  4800.   
  4801. ! /*
  4802. !  * X11 based inter client communication handler.
  4803. !  */
  4804. ! /*ARGSUSED*/
  4805. ! static gint
  4806. ! client_event_cb(GtkWidget *widget, GdkEventClient *event)
  4807. ! {
  4808. !     if (event->message_type == save_yourself_atom ) {
  4809. !     out_flush();
  4810. !     ml_sync_all(FALSE, FALSE);      /* preserve all swap files */
  4811. !     return TRUE;
  4812. !     } else if (event->message_type == reread_rcfiles_atom) {
  4813. !     gui_mch_new_colors();
  4814. !     return TRUE;
  4815. !     }
  4816. !     return FALSE;
  4817. ! }
  4818.   
  4819. ! /*
  4820. !  * Function called when window already closed.
  4821. !  * We can't do much more here than to trying to preserve what had been done,
  4822. !  * since the window is already inevitably going away.
  4823. !  */
  4824. ! static void
  4825. ! destroy_callback(void)
  4826. ! {
  4827. !     /* preserve files and exit */
  4828. !     preserve_exit();
  4829. !     if (gtk_main_level() > 0)
  4830. !     gtk_main_quit();
  4831. ! }
  4832.   
  4833.   
  4834. ! /*
  4835. !  * Open the GUI window which was created by a call to gui_mch_init().
  4836. !  */
  4837. ! int
  4838. ! gui_mch_open()
  4839. ! {
  4840. !     int x = -1, y = -1;
  4841.   
  4842. !     /* Determine user specified geometry, if present. */
  4843. !     if (gui.geom) {
  4844. !     int mask;
  4845. !     unsigned w, h;
  4846.   
  4847. !     mask = XParseGeometry((char *)gui.geom, &x, &y, &w, &h);
  4848. !     if (mask & WidthValue)
  4849. !         Columns = w;
  4850. !     if (mask & HeightValue)
  4851. !         Rows = h;
  4852. !     if (mask & (XValue | YValue))
  4853. !         gtk_widget_set_uposition(gui.mainwin, x, y);
  4854. !     g_free(gui.geom);
  4855. !     gui.geom = NULL;
  4856.       }
  4857.   
  4858. !     gtk_form_set_size(GTK_FORM(gui.formwin),
  4859. !         (guint)(gui_get_base_width() + Columns * gui.char_width),
  4860. !         (guint)(gui_get_base_height() + Rows * gui.char_height));
  4861.       update_window_manager_hints();
  4862.   
  4863. !     if (found_reverse_arg )
  4864. !     {
  4865. !     gui.def_norm_pixel = gui_mch_get_color((char_u *)"White");
  4866. !     gui.def_back_pixel = gui_mch_get_color((char_u *)"Black");
  4867. !     }
  4868. !     else
  4869. !     {
  4870. !     gui.def_norm_pixel = gui_mch_get_color((char_u *)"Black");
  4871. !     gui.def_back_pixel = gui_mch_get_color((char_u *)"White");
  4872. !     }
  4873.   
  4874. +     /* Get the colors from the "Normal" and "Menu" group (set in syntax.c or
  4875. +      * in a vimrc file)
  4876. +      */
  4877. +     set_normal_colors();
  4878.   
  4879. !     /* Check that none of the colors are the same as the background color */
  4880. !     gui_check_colors();
  4881.   
  4882. !     /* Get the colors for the highlight groups (gui_check_colors() might have
  4883. !      * changed them).
  4884. !      */
  4885. !     highlight_gui_started();    /* re-init colors and fonts */
  4886.   
  4887. !     gtk_signal_connect(GTK_OBJECT(gui.mainwin), "destroy",
  4888. !                GTK_SIGNAL_FUNC(destroy_callback), NULL);
  4889. !     /* Make this run after any internal handling of the client event happaned
  4890. !      * to make sure that all changes implicated by it are already in place and
  4891. !      * we thus can make our own adjustments.
  4892. !      */
  4893. !     gtk_signal_connect_after(GTK_OBJECT(gui.mainwin), "client_event",
  4894. !                        GTK_SIGNAL_FUNC(client_event_cb), NULL);
  4895. ! #ifdef HANGUL_INPUT
  4896. !     hangul_keyboard_set();
  4897.   #endif
  4898.   
  4899. !     /*
  4900. !      * Notify the fixed area about the need to resize the contents of the
  4901. !      * gui.formwin, which we use for random positioning of the included
  4902. !      * components.
  4903. !      *
  4904. !      * We connect this signal deferred finally after anything is in place,
  4905. !      * since this is intended to handle resizements coming from the window
  4906. !      * manager upon us and should not interfere with what VIM is requesting
  4907. !      * upon startup.
  4908. !      */
  4909. !     gtk_signal_connect(GTK_OBJECT(gui.formwin), "configure_event",
  4910. !                GTK_SIGNAL_FUNC(form_configure_event), NULL);
  4911.   
  4912. ! #ifdef GTK_DND
  4913. !     /*
  4914. !      * Set up for receiving DND items.
  4915. !      */
  4916. !     gtk_drag_dest_set(gui.drawarea,
  4917. !         GTK_DEST_DEFAULT_ALL,
  4918. !         target_table, n_targets,
  4919. !         GDK_ACTION_COPY | GDK_ACTION_MOVE);
  4920.   
  4921. !     gtk_signal_connect(GTK_OBJECT(gui.drawarea), "drag_data_received",
  4922. !         GTK_SIGNAL_FUNC(drag_data_received), NULL);
  4923. ! #endif
  4924.   
  4925. !     gtk_widget_show(gui.mainwin);
  4926. !     return OK;
  4927.   }
  4928.   
  4929. ! /*ARGSUSED*/
  4930.   void
  4931. ! gui_mch_exit(int rc)
  4932.   {
  4933. !     gtk_exit(0);
  4934.   }
  4935.   
  4936.   /*
  4937. !  * Get the position of the top left corner of the window.
  4938.    */
  4939.   int
  4940. ! gui_mch_get_winpos(int *x, int *y)
  4941.   {
  4942. !     /* For some people this must be gdk_window_get_origin() for a correct
  4943. !      * result.  Where is the documentation! */
  4944. ! #ifdef GTK_HAVE_FEATURES_1_1_4
  4945. !     gdk_window_get_root_origin(gui.mainwin->window, x, y);
  4946. ! #else
  4947. !     gdk_window_get_origin(gui.mainwin->window, x, y);
  4948.   #endif
  4949. +     return OK;
  4950. + }
  4951.   
  4952.   /*
  4953. !  * Set the position of the top left corner of the window to the given
  4954. !  * coordinates.
  4955.    */
  4956.   void
  4957. ! gui_mch_set_winpos(int x, int y)
  4958.   {
  4959. !     gdk_window_move(gui.mainwin->window, x, y);
  4960.   }
  4961.   
  4962.   /*
  4963. !  * Set the windows size.
  4964.    */
  4965. ! /*ARGSUSED*/
  4966. ! void
  4967. ! gui_mch_set_winsize(int width, int height,
  4968. !             int min_width, int min_height,
  4969. !             int base_width, int base_height)
  4970.   {
  4971. !     gtk_form_set_size(GTK_FORM(gui.formwin), width, height);
  4972.   
  4973. !     /* give GTK+ a chance to put all widget's into place */
  4974. !     gui_mch_update();
  4975.   
  4976. !     /* this will cause the proper resizement to happen too */
  4977. !     update_window_manager_hints();
  4978.   }
  4979.   
  4980.   
  4981.   /*
  4982. !  * The screen size is used to make sure the initial window doesn't get bigger
  4983. !  * then the screen.  This subtracts some room for menubar, toolbar and window
  4984. !  * decoreations.
  4985.    */
  4986.   void
  4987. ! gui_mch_get_screen_dimensions(int *screen_w, int *screen_h)
  4988.   {
  4989. !     *screen_w = gdk_screen_width();
  4990. !     /* Subtract 'guihearroom' from the height to allow some room for the
  4991. !      * window manager (task list and window title bar). */
  4992. !     *screen_h = gdk_screen_height() - p_ghr;
  4993. !     /*
  4994. !      * FIXME: dirty trick: Because the gui_get_base_height() doesn't include
  4995. !      * the toolbar and menubar for GTK, we subtract them from the screen
  4996. !      * hight, so that the window size can be made to fit on the screen.
  4997. !      * This should be completely changed later.
  4998. !      */
  4999. ! #ifdef USE_TOOLBAR
  5000. !     if (gui.toolbar && GTK_WIDGET_REALIZED(gui.toolbar)
  5001. !         && GTK_WIDGET_VISIBLE(gui.toolbar))
  5002. !     *screen_h -= gui.toolbar->allocation.height;
  5003. ! #endif
  5004. ! #ifdef WANT_MENU
  5005. !     if (gui.menubar && GTK_WIDGET_REALIZED(gui.menubar)
  5006. !         && GTK_WIDGET_VISIBLE(gui.menubar))
  5007. !     *screen_h -= gui.menubar->allocation.height;
  5008. ! #endif
  5009.   }
  5010.   
  5011. ! #if defined(WANT_MENU) || defined(PROTO)
  5012.   void
  5013. ! gui_mch_enable_menu(int flag)
  5014.   {
  5015. !     if (flag)
  5016. !     gtk_widget_show(gui.menubar);
  5017. !     else
  5018. !     gtk_widget_hide(gui.menubar);
  5019. !     update_window_manager_hints();
  5020.   }
  5021. + #endif
  5022.   
  5023. + #if defined(USE_TOOLBAR) || defined(PROTO)
  5024.   void
  5025. ! gui_mch_show_toolbar(int showit)
  5026.   {
  5027. !     if (gui.toolbar == NULL)
  5028.       return;
  5029.   
  5030. !     if (!showit) {
  5031. !     if (GTK_WIDGET_VISIBLE(gui.toolbar)) {
  5032. !         gtk_widget_hide(gui.toolbar);
  5033. !         /* wait util this gets done on the server side. */
  5034. !         update_window_manager_hints();
  5035. !     }
  5036. !     } else {
  5037. !     g_assert(p_toolbar != NULL);
  5038. !     if (strstr((const char *)p_toolbar, "text")
  5039. !         && strstr((const char *)p_toolbar, "icons")) {
  5040. !         gtk_toolbar_set_style(GTK_TOOLBAR(gui.toolbar), GTK_TOOLBAR_BOTH);
  5041. !     } else if (strstr((const char *)p_toolbar, "text")) {
  5042. !         gtk_toolbar_set_style(GTK_TOOLBAR(gui.toolbar), GTK_TOOLBAR_TEXT);
  5043. !     } else if (strstr((const char *)p_toolbar, "icons")) {
  5044. !         gtk_toolbar_set_style(GTK_TOOLBAR(gui.toolbar), GTK_TOOLBAR_ICONS);
  5045.       }
  5046.   
  5047. !     if (!GTK_WIDGET_VISIBLE(gui.toolbar)) {
  5048. !         gtk_widget_show(gui.toolbar);
  5049. !         update_window_manager_hints();
  5050. !     }
  5051.   
  5052. !     if (strstr((const char *)p_toolbar, "tooltips"))
  5053. !         gtk_toolbar_set_tooltips(GTK_TOOLBAR(gui.toolbar), TRUE);
  5054. !     else
  5055. !         gtk_toolbar_set_tooltips(GTK_TOOLBAR(gui.toolbar), FALSE);
  5056.       }
  5057.   }
  5058.   #endif
  5059.   
  5060.   
  5061. ! #ifdef USE_FONTSET
  5062. ! static GuiFont
  5063. ! gui_mch_get_fontset(char_u * name, int report_error)
  5064.   {
  5065. !     GdkFont *font;
  5066.   
  5067. !     if (!gui.in_use || name == NULL)
  5068. !     return (GuiFont) 0;
  5069.   
  5070. !     font = gdk_fontset_load((gchar *) name);
  5071.   
  5072. !     if (font == NULL) {
  5073. !     if (report_error)
  5074. !         EMSG2("Unknown fontset: %s", name);
  5075. !     return (GuiFont) 0;
  5076. !     }
  5077.   
  5078. !     /* reference this font as beeing in use */
  5079. !     gdk_font_ref(font);
  5080.   
  5081. !     return (GuiFont) font;
  5082.   }
  5083. + #endif
  5084.   
  5085. + #ifdef GTK_HAVE_FEATURES_1_1_0
  5086.   /*
  5087. !  * Get a font structure for highlighting.
  5088. !  * "cbdata" is a pointer to the global gui structure.
  5089.    */
  5090. ! /*ARGSUSED*/
  5091. ! static void
  5092. ! font_sel_ok(GtkWidget *wgt, gpointer cbdata)
  5093.   {
  5094. !     Gui *vw = (Gui *)cbdata;
  5095. !     GtkFontSelectionDialog *fs = (GtkFontSelectionDialog *)vw->fontdlg;
  5096.   
  5097. !     if (vw->fontname)
  5098. !     g_free(vw->fontname);
  5099.   
  5100. !     vw->fontname = (char_u *)g_strdup(
  5101. !                 gtk_font_selection_dialog_get_font_name(fs));
  5102. !     gtk_widget_hide(vw->fontdlg);
  5103. !     if (gtk_main_level() > 0)
  5104. !     gtk_main_quit();
  5105. ! }
  5106.   
  5107. ! /*ARGSUSED*/
  5108. ! static void
  5109. ! font_sel_cancel(GtkWidget *wgt, gpointer cbdata)
  5110. ! {
  5111. !     Gui *vw = (Gui *)cbdata;
  5112. !     gtk_widget_hide(vw->fontdlg);
  5113. !     if (gtk_main_level() > 0)
  5114. !     gtk_main_quit();
  5115.   }
  5116.   
  5117. ! /*ARGSUSED*/
  5118. ! static void
  5119. ! font_sel_destroy(GtkWidget *wgt, gpointer cbdata)
  5120.   {
  5121. !     Gui *vw = (Gui *)cbdata;
  5122. !     vw->fontdlg = NULL;
  5123. !     if (gtk_main_level() > 0)
  5124. !     gtk_main_quit();
  5125.   }
  5126. + #endif
  5127.   
  5128.   /*
  5129. !  * Initialise vim to use the font with the given name.
  5130. !  * Return FAIL if the font could not be loaded, OK otherwise.
  5131.    */
  5132. ! int
  5133. ! gui_mch_init_font(char_u * font_name)
  5134.   {
  5135. !     GdkFont    *font = NULL;
  5136. !     char    *chunk[28], *sdup, *tmp;
  5137. !     int        len, i;
  5138.   
  5139. ! #ifdef USE_FONTSET
  5140. !     {
  5141. !     static char_u *dflt_fontset = NULL;
  5142.   
  5143. !     if (gui.fontset)
  5144. !     {
  5145. !         /* If fontset is active, VIM treat all the font as a fontset. */
  5146. !         if (font_name == NULL || vim_strchr(font_name, ',') == NULL)
  5147. !         font_name = dflt_fontset;
  5148. !         font = gui_mch_get_fontset(font_name, FALSE);
  5149. !         if (font == NULL)
  5150. !         return FAIL;
  5151. !     }
  5152. !     else if (font_name == NULL && *p_guifontset)
  5153. !     {
  5154. !         font = gui_mch_get_fontset(p_guifontset, FALSE);
  5155. !         if (font)
  5156. !         {
  5157. !         font_name = p_guifontset;
  5158. !         dflt_fontset = alloc(STRLEN(p_guifontset) + 1);
  5159. !         STRCPY(dflt_fontset, p_guifontset);
  5160. !         }
  5161. !     }
  5162. !     }
  5163.   
  5164. !     if (font == NULL)
  5165. ! #endif
  5166.       {
  5167. !     /*
  5168. !      * If none of the fonts in 'font' could be loaded, try the default,
  5169. !      * which should be present on all X11 servers.
  5170. !      */
  5171. !     if (font_name == NULL)
  5172. !         font_name = (char_u *) DFLT_FONT;
  5173. ! #ifdef GTK_HAVE_FEATURES_1_1_0
  5174. !     if (STRCMP(font_name, "*") == 0) {
  5175. !         /*
  5176. !          * Request for a font handling dialog.
  5177. !          * Not quite sure we should handle this here...
  5178. !          */
  5179. !         /*
  5180. !          * NOTE about font selection widget: this can easily be backported
  5181. !          * to gtk-1.0.x.
  5182. !          */
  5183. !         if (!gui.fontdlg)
  5184. !         {
  5185. !         GtkFontSelectionDialog    *fsd = NULL;
  5186. !         gui.fontdlg = gtk_font_selection_dialog_new("Font Selection");
  5187. !         fsd = GTK_FONT_SELECTION_DIALOG(gui.fontdlg);
  5188. !         if (p_guifont != NULL)
  5189. !             gtk_font_selection_dialog_set_font_name(fsd,
  5190. !                                 (char *)p_guifont);
  5191. ! # ifdef GTK_HAVE_FEATURES_1_1_4
  5192. !         gtk_window_set_modal(GTK_WINDOW(gui.fontdlg), TRUE);
  5193. !         gtk_window_set_transient_for(GTK_WINDOW(gui.fontdlg),
  5194. !                              GTK_WINDOW(gui.mainwin));
  5195.   # endif
  5196. !         gtk_signal_connect(GTK_OBJECT(gui.fontdlg), "destroy",
  5197. !                    GTK_SIGNAL_FUNC(font_sel_destroy), &gui);
  5198. !         gtk_signal_connect(GTK_OBJECT(fsd->ok_button), "clicked",
  5199. !                    GTK_SIGNAL_FUNC(font_sel_ok), &gui);
  5200. !         gtk_signal_connect(GTK_OBJECT(fsd->cancel_button), "clicked",
  5201. !                    GTK_SIGNAL_FUNC(font_sel_cancel), &gui);
  5202. !         }
  5203. !         if (gui.fontname)
  5204. !         {
  5205. !         g_free(gui.fontname);
  5206. !         gui.fontname = NULL;
  5207. !         }
  5208. !         gtk_window_position(GTK_WINDOW(gui.fontdlg), GTK_WIN_POS_MOUSE);
  5209. !         gtk_widget_show(gui.fontdlg);
  5210. ! # ifdef GTK_HAVE_FEATURES_1_1_4
  5211. !         {
  5212. !         static gchar        *spacings[] = {"c", "m", NULL};
  5213. !         /* In GTK 1.2.3 this must be after the gtk_widget_show() call,
  5214. !          * otherwise everything is blocked for ten seconds. */
  5215. !         gtk_font_selection_dialog_set_filter(
  5216. !             GTK_FONT_SELECTION_DIALOG(gui.fontdlg),
  5217. !             GTK_FONT_FILTER_BASE,
  5218. !             GTK_FONT_ALL, NULL, NULL,
  5219. !             NULL, NULL, spacings, NULL);
  5220. !         }
  5221. ! # endif
  5222. !         while (gui.fontdlg && GTK_WIDGET_VISIBLE(gui.fontdlg))
  5223. !         gtk_main_iteration_do(TRUE);
  5224. !         if (gui.fontname == NULL)
  5225. !         return FAIL;
  5226. !         vim_free(p_guifont);
  5227. !         p_guifont = vim_strsave(gui.fontname);
  5228. !         font_name = p_guifont;
  5229. !     }
  5230. ! #endif
  5231. !     if (font == NULL)
  5232. !         font = gui_mch_get_font(font_name, FALSE);
  5233. !     if (font == NULL)
  5234. !         return FAIL;
  5235. !     }
  5236. !     if (gui.norm_font != 0)
  5237. !     gdk_font_unref(font);
  5238. !     gui.norm_font = font;
  5239. ! #ifdef USE_FONTSET
  5240. !     if (font->type == GDK_FONT_FONTSET)
  5241. !     {
  5242. !     gui.fontset = (GuiFont) font;
  5243. !     gui.char_width = gdk_string_width(font, " ");
  5244.       }
  5245.       else
  5246.   #endif
  5247. !     {
  5248. !     gui.char_width = ((XFontStruct *)
  5249. !                       GDK_FONT_XFONT(font))->max_bounds.width;
  5250. !     }
  5251.   
  5252. !     gui.char_height = font->ascent + font->descent;
  5253. !     gui.char_ascent = font->ascent;
  5254.   
  5255. !     /* Set the fontname, which will be used for information purposes */
  5256. !     hl_set_font_name(font_name);
  5257.   
  5258. !     if (font->type != GDK_FONT_FONTSET)
  5259. !     {
  5260. !     /* There is only one excuse I can give for the following attempt
  5261. !      * to manage font styles:
  5262. !      *
  5263. !      * I HATE THE BRAIN DEAD WAY X11 IS HANDLING FONTS (--mdcki)
  5264. !      */
  5265. !     if ((sdup = g_strdup((const char *)font_name)) == NULL)
  5266. !         return FAIL;
  5267.   
  5268. !     /* slipt up the whole */
  5269. !     i = 0;
  5270. !     for (tmp = sdup; *tmp != '\0'; ++tmp)
  5271. !         if (*tmp == '-')
  5272. !         {
  5273. !         *tmp = '\0';
  5274. !         chunk[i] = tmp + 1;
  5275. !         ++i;
  5276. !         }
  5277. !     g_free(sdup);
  5278. !     if (i == 14)
  5279. !     {
  5280. !         char *bold_name = NULL;
  5281. !         char *ital_name = NULL;
  5282. !         char *italbold_name = NULL;
  5283. !         /* font name was compleate */
  5284. !         len = strlen((const char *)font_name) + 32;
  5285. !         bold_name = (char *)alloc(len);
  5286. !         ital_name = (char *)alloc(len);
  5287. !         italbold_name = (char *)alloc(len);
  5288. !         if (bold_name == NULL || ital_name == NULL || italbold_name == NULL)
  5289. !         {
  5290. !         vim_free(bold_name);
  5291. !         vim_free(ital_name);
  5292. !         vim_free(italbold_name);
  5293. !         return FAIL;
  5294. !         }
  5295. !         *bold_name = '\0';
  5296. !         *ital_name = '\0';
  5297. !         *italbold_name = '\0';
  5298. !         for (i = 0; i < 14; ++i)
  5299. !         {
  5300. !         strcat(bold_name, "-");
  5301. !         strcat(ital_name, "-");
  5302. !         strcat(italbold_name, "-");
  5303. !         strcat(bold_name, (i != 2) ? chunk[i] : "bold");
  5304. !         strcat(ital_name, (i != 3) ? chunk[i] : "o");
  5305. !         if (i != 2 && i != 3)
  5306. !             strcat(italbold_name, chunk[i]);
  5307. !         else
  5308. !         {
  5309. !             if (i == 2)
  5310. !             strcat(italbold_name, "bold");
  5311. !             else if (i == 3)
  5312. !             strcat(italbold_name, "o");
  5313. !         }
  5314. !         }
  5315. !         font = gui_mch_get_font((char_u *)bold_name, FALSE);
  5316. !         if (font != NULL)
  5317. !         gui.bold_font = font;
  5318. !         else if (gui.bold_font)
  5319. !         {
  5320. !         gdk_font_unref(gui.bold_font);
  5321. !         gui.bold_font = NULL;
  5322. !         }
  5323. !         font = gui_mch_get_font((char_u *)ital_name, FALSE);
  5324. !         if (font != NULL)
  5325. !         gui.ital_font = font;
  5326. !         else if (gui.ital_font)
  5327. !         {
  5328. !         gdk_font_unref(gui.ital_font);
  5329. !         gui.ital_font = NULL;
  5330. !         }
  5331. !         font = gui_mch_get_font((char_u *)italbold_name, FALSE);
  5332. !         if (font != NULL)
  5333. !         gui.boldital_font = font;
  5334. !         else if (gui.boldital_font)
  5335. !         {
  5336. !         gdk_font_unref(gui.boldital_font);
  5337. !         gui.boldital_font = NULL;
  5338. !         }
  5339. !         vim_free(bold_name);
  5340. !         vim_free(ital_name);
  5341. !         vim_free(italbold_name);
  5342. !     }
  5343. !     }
  5344. !     /* Synchronize the fonts used in user input dialogs, since otherwise
  5345. !      * search/replace will be esp annoyig in case of international font usage.
  5346. !      */
  5347. !     gui_gtk_synch_fonts();
  5348. ! #ifdef USE_XIM
  5349. !     /* Adjust input management behaviour to the capabilities of the new
  5350. !      * fontset */
  5351. !     xim_decide_input_style();
  5352. !     if (xim_get_status_area_height())
  5353. !     {
  5354. !     /* Status area is required.  Just create the empty label so that
  5355. !      * mainwin will allocate the extra space for status area. */
  5356. !     GtkWidget *label = gtk_label_new("       ");
  5357. !     gtk_widget_set_usize(label, 20, gui.char_height + 2);
  5358. !     gtk_box_pack_end(GTK_BOX(GTK_BIN(gui.mainwin)->child), label,
  5359. !                                  FALSE, FALSE, 0);
  5360. !     gtk_widget_show(label);
  5361. !     }
  5362. ! #endif
  5363.   
  5364. !     /* Preserve the logical dimensions of the screen. */
  5365. !     update_window_manager_hints();
  5366.   
  5367. !     return OK;
  5368.   }
  5369.   
  5370.   
  5371. ! GuiFont
  5372. ! gui_mch_get_font(char_u * name, int report_error)
  5373.   {
  5374. !     GdkFont *font;
  5375.   
  5376. !     if (!gui.in_use || name == NULL)    /* can't do this when GUI not running */
  5377. !     return (GuiFont) 0;
  5378.   
  5379. ! #ifdef USE_FONTSET
  5380. !     if (gui.fontset)
  5381. !     /* If fontset is active, VIM treat all the font as a fontset */
  5382. !     return gui_mch_get_fontset(name, report_error);
  5383. !     else if (vim_strchr(name, ','))
  5384. !     return (GuiFont)0;
  5385.   #endif
  5386.   
  5387. !     font = gdk_font_load((const gchar *) name);
  5388.   
  5389. !     if (font == NULL) {
  5390. !     if (report_error)
  5391. !         EMSG2("Unknown font: %s", name);
  5392. !     return (GuiFont) 0;
  5393. !     }
  5394.   
  5395. !     /* reference this font as beeing in use */
  5396. !     gdk_font_ref(font);
  5397. !     if (((XFontStruct *) GDK_FONT_XFONT(font))->max_bounds.width
  5398. !     != ((XFontStruct *) GDK_FONT_XFONT(font))->min_bounds.width) {
  5399. !     EMSG2("Font \"%s\" is not fixed-width", name);
  5400. !     gdk_font_unref(font);
  5401.   
  5402. !     return (GuiFont) 0;
  5403. !     }
  5404. !     return (GuiFont) font;
  5405.   }
  5406.   
  5407.   /*
  5408. !  * Set the current text font.
  5409. !  * Since we create all GC on demand, we use just gui.current_font to
  5410. !  * indicate the desired current font.
  5411.    */
  5412. ! void
  5413. ! gui_mch_set_font(GuiFont font)
  5414.   {
  5415. !     gui.current_font = font;
  5416.   }
  5417.   
  5418. ! #if 0 /* not used */
  5419. ! /*
  5420. !  * Return TRUE if the two fonts given are equivalent.
  5421. !  */
  5422. ! int
  5423. ! gui_mch_same_font(GuiFont f1, GuiFont f2)
  5424.   {
  5425. !     return gdk_font_equal((GdkFont *) f1, (GdkFont *) f2);
  5426.   }
  5427. + #endif
  5428.   
  5429.   /*
  5430. !  * If a font is not going to be used, free its structure.
  5431.    */
  5432.   void
  5433. ! gui_mch_free_font(GuiFont font)
  5434.   {
  5435. !     if (font)
  5436. !     gdk_font_unref((GdkFont *) font);
  5437. ! }
  5438.   
  5439.   
  5440. ! /*
  5441. !  * Return the Pixel value (color) for the given color name.  This routine was
  5442. !  * pretty much taken from example code in the Silicon Graphics OSF/Motif
  5443. !  * Programmer's Guide.
  5444. !  * Return -1 for error.
  5445. !  */
  5446. ! GuiColor
  5447. ! gui_mch_get_color(char_u * name)
  5448. ! {
  5449. !     int i;
  5450. !     static char *(vimnames[][2]) =
  5451. !     {
  5452. !     /* A number of colors that some X11 systems don't have */
  5453. !     {"LightRed", "#FFA0A0"},
  5454. !     {"LightGreen", "#80FF80"},
  5455. !     {"LightMagenta", "#FFA0FF"},
  5456. !     {"DarkCyan", "#008080"},
  5457. !     {"DarkBlue", "#0000C0"},
  5458. !     {"DarkRed", "#C00000"},
  5459. !     {"DarkMagenta", "#C000C0"},
  5460. !     {"DarkGrey", "#C0C0C0"},
  5461. !     {NULL, NULL}
  5462. !     };
  5463.   
  5464. !     if (!gui.in_use)        /* can't do this when GUI not running */
  5465. !     return (GuiColor)(-1);
  5466.   
  5467. !     while (name != NULL) {
  5468. !     GdkColor color;
  5469.   
  5470. !     if (gdk_color_parse((const gchar *)name, &color)) {
  5471. !         GdkColormap *colormap;
  5472. !         colormap = gtk_widget_get_colormap(gui.drawarea);
  5473. !         gdk_color_alloc(colormap, &color);
  5474.   
  5475. !         return (GuiColor) color.pixel;
  5476. !     }
  5477. !     /* add a few builtin names */
  5478. !     for (i = 0;; ++i) {
  5479. !         if (vimnames[i][0] == NULL) {
  5480. !         name = NULL;
  5481. !         break;
  5482. !         }
  5483. !         if (STRICMP(name, vimnames[i][0]) == 0) {
  5484. !         name = (char_u *) vimnames[i][1];
  5485. !         break;
  5486. !         }
  5487. !     }
  5488. !     }
  5489.   
  5490. !     return (GuiColor)(-1);
  5491.   }
  5492.   
  5493.   /*
  5494. !  * Set the current text foreground color.
  5495.    */
  5496. ! void
  5497. ! gui_mch_set_fg_color(GuiColor color)
  5498.   {
  5499. !     gui.fgcolor->pixel = (Pixel) color;
  5500. ! }
  5501.   
  5502. ! /*
  5503. !  * Set the current text background color.
  5504. !  */
  5505. ! void
  5506. ! gui_mch_set_bg_color(GuiColor color)
  5507. ! {
  5508. !     gui.bgcolor->pixel = (Pixel) color;
  5509.   }
  5510.   
  5511.   /*
  5512. !  * Use the blank mouse pointer or not.
  5513. !  *
  5514. !  * hide: TRUE = use blank ptr, FALSE = use parent ptr
  5515.    */
  5516.   void
  5517. ! gui_mch_mousehide(int hide)
  5518.   {
  5519. !     if (gui.pointer_hidden != hide) {
  5520. !     if (gui.drawarea->window && gui.blank_pointer) {
  5521. !         if (hide)
  5522. !         gdk_window_set_cursor(gui.drawarea->window, gui.blank_pointer);
  5523. !         else
  5524. !         gdk_window_set_cursor(gui.drawarea->window, NULL);
  5525.       }
  5526. !     gui.pointer_hidden = hide;
  5527.       }
  5528.   }
  5529.   
  5530.   void
  5531. ! gui_mch_draw_string(int row, int col, char_u * s, int len, int flags)
  5532.   {
  5533. !     GdkGC *gc;
  5534.   
  5535. !     if (gui.current_font == NULL || gui.drawarea->window == NULL)
  5536.       return;
  5537.   
  5538. ! #if defined(USE_FONTSET) && defined(MULTI_BYTE)
  5539. !     if (gui.fontset)
  5540. !     {
  5541. !     if (col > 0 && mb_isbyte1(LinePointers[row], col - 1))
  5542. !     {
  5543. !         col++;
  5544. !         len--;
  5545. !         s++;
  5546. !     }
  5547. !     if (len == 1 && IsLeadByte(*s))
  5548. !         len = 2;
  5549. !     }
  5550. ! #endif
  5551. !     gc = gdk_gc_new(gui.drawarea->window);
  5552. !     gdk_gc_set_exposures(gc, gui.visibility != GDK_VISIBILITY_UNOBSCURED);
  5553. !     if (flags & DRAW_TRANSP) {
  5554. !     gdk_gc_set_foreground(gc, gui.fgcolor);
  5555. !     gdk_draw_text(gui.drawarea->window,
  5556. !               gui.current_font,
  5557. !               gc,
  5558. !               TEXT_X(col), TEXT_Y(row),
  5559. !               (const gchar *)s, len);
  5560.       } else {
  5561. !     int width;
  5562. !     int height;
  5563. !     width = gdk_text_width(gui.current_font, (const gchar *)s, len);
  5564. !     height = gui.char_height;
  5565.   
  5566. !     gdk_gc_set_foreground(gc, gui.bgcolor);
  5567. !     gdk_draw_rectangle(gui.drawarea->window,
  5568. !                gc,
  5569. !                TRUE,
  5570. !                FILL_X(col), FILL_Y(row), width, height);
  5571.       gdk_gc_set_foreground(gc, gui.fgcolor);
  5572. !     gdk_draw_text(gui.drawarea->window,
  5573. !               gui.current_font,
  5574. !               gc,
  5575. !               TEXT_X(col), TEXT_Y(row),
  5576. !               (const gchar *)s, len);
  5577. !     }
  5578.   
  5579. !     /* redraw the contents with an offset of 1 to emulate bold */
  5580. !     if (flags & DRAW_BOLD) {
  5581. !     gdk_draw_text(gui.drawarea->window,
  5582. !               gui.current_font,
  5583. !               gc,
  5584. !               TEXT_X(col) + 1, TEXT_Y(row),
  5585. !               (const gchar *)s, len);
  5586. !     }
  5587.   
  5588. !     if (flags & DRAW_UNDERL) {
  5589. !     gdk_draw_line(gui.drawarea->window,
  5590. !               gc, FILL_X(col),
  5591. !     FILL_Y(row + 1) - 1, FILL_X(col + len) - 1, FILL_Y(row + 1) - 1);
  5592.       }
  5593. +     gdk_gc_destroy(gc);
  5594.   }
  5595.   
  5596.   /*
  5597. !  * Return OK if the key with the termcap name "name" is supported.
  5598.    */
  5599. ! int
  5600. ! gui_mch_haskey(char_u * name)
  5601.   {
  5602. !     int i;
  5603.   
  5604. !     for (i = 0; special_keys[i].key_sym != 0; i++)
  5605. !     if (name[0] == special_keys[i].code0 &&
  5606. !         name[1] == special_keys[i].code1)
  5607. !         return OK;
  5608. !     return FAIL;
  5609. ! }
  5610. ! #if defined(WANT_TITLE) || defined(PROTO)
  5611. ! /*
  5612. !  * Return the text window-id and display.  Only required for X-based GUI's
  5613. !  */
  5614. ! int
  5615. ! gui_get_x11_windis(Window * win, Display ** dis)
  5616. ! {
  5617. !     /*
  5618. !      * This is currently only used by the code which is handling the
  5619. !      * window manager title of this program.
  5620. !      */
  5621. !     *dis = GDK_DISPLAY();
  5622. !     if (gui.mainwin->window) {
  5623. !     *win = GDK_WINDOW_XWINDOW(gui.mainwin->window);
  5624. !     return OK;
  5625.       }
  5626. +     *win = 0;
  5627. +     return FAIL;
  5628.   }
  5629. + #endif
  5630.   
  5631.   void
  5632. ! gui_mch_beep()
  5633.   {
  5634. !     gdk_beep();
  5635. ! }
  5636. ! void
  5637. ! gui_mch_flash()
  5638. ! {
  5639. !     GdkGCValues values;
  5640. !     GdkGC *invert_gc;
  5641. !     GdkColor foreground;
  5642. !     GdkColor background;
  5643. !     if (gui.drawarea->window == NULL)
  5644. !     return;
  5645. !     foreground.pixel = gui.norm_pixel ^ gui.back_pixel;
  5646. !     background.pixel = gui.norm_pixel ^ gui.back_pixel;
  5647. !     values.foreground = foreground;
  5648. !     values.background = background;
  5649. !     values.function = GDK_XOR;
  5650. !     invert_gc = gdk_gc_new_with_values(gui.drawarea->window,
  5651. !                        &values,
  5652. !                        GDK_GC_FOREGROUND |
  5653. !                        GDK_GC_BACKGROUND |
  5654. !                        GDK_GC_FUNCTION);
  5655. !     gdk_gc_set_exposures(invert_gc, gui.visibility != GDK_VISIBILITY_UNOBSCURED);
  5656. !     /* Do a visual beep by changing back and forth in some undetermined way,
  5657. !      * the foreground and background colors.  This is due to the fact that
  5658. !      * there can't be really any prediction about the effects of XOR on
  5659. !      * arbitrary X11 servers. However this seems to be enought for what we
  5660. !      * intend it to do.
  5661. !      */
  5662. !     gdk_draw_rectangle(gui.drawarea->window, invert_gc,
  5663. !                TRUE,
  5664. !                0, 0,
  5665. !                FILL_X((int) Columns) + gui.border_offset,
  5666. !                FILL_Y((int) Rows) + gui.border_offset);
  5667. !     gdk_flush();
  5668. !     ui_delay(20L, TRUE);    /* wait 1/50 of a second */
  5669. !     gdk_draw_rectangle(gui.drawarea->window, invert_gc,
  5670. !                TRUE,
  5671. !                0, 0,
  5672. !                FILL_X((int) Columns) + gui.border_offset,
  5673. !                FILL_Y((int) Rows) + gui.border_offset);
  5674. !     gdk_gc_destroy(invert_gc);
  5675.   }
  5676.   
  5677.   /*
  5678. !  * Invert a rectangle from row r, column c, for nr rows and nc columns.
  5679.    */
  5680. ! void
  5681. ! gui_mch_invert_rectangle(int r, int c, int nr, int nc)
  5682.   {
  5683. !     GdkGCValues values;
  5684. !     GdkGC *invert_gc;
  5685. !     GdkColor foreground;
  5686. !     GdkColor background;
  5687.   
  5688. !     if (gui.drawarea->window == NULL)
  5689. !     return;
  5690. !     foreground.pixel = gui.norm_pixel ^ gui.back_pixel;
  5691. !     background.pixel = gui.norm_pixel ^ gui.back_pixel;
  5692. !     values.foreground = foreground;
  5693. !     values.background = background;
  5694. !     values.function = GDK_XOR;
  5695. !     invert_gc = gdk_gc_new_with_values(gui.drawarea->window,
  5696. !                        &values,
  5697. !                        GDK_GC_FOREGROUND |
  5698. !                        GDK_GC_BACKGROUND |
  5699. !                        GDK_GC_FUNCTION);
  5700. !     gdk_gc_set_exposures(invert_gc, gui.visibility != GDK_VISIBILITY_UNOBSCURED);
  5701. !     gdk_draw_rectangle(gui.drawarea->window, invert_gc,
  5702. !                TRUE,
  5703. !                FILL_X(c), FILL_Y(r),
  5704. !                (nc) * gui.char_width, (nr) * gui.char_height);
  5705. !     gdk_gc_destroy(invert_gc);
  5706.   }
  5707.   
  5708.   /*
  5709. !  * Iconify the GUI window.
  5710.    */
  5711.   void
  5712. ! gui_mch_iconify()
  5713.   {
  5714. !     XIconifyWindow(GDK_DISPLAY(),
  5715. !            GDK_WINDOW_XWINDOW(gui.mainwin->window),
  5716. !            DefaultScreen(GDK_DISPLAY()));
  5717.   }
  5718.   
  5719.   /*
  5720. !  * Draw a cursor without focus.
  5721.    */
  5722.   void
  5723. ! gui_mch_draw_hollow_cursor(GuiColor color)
  5724.   {
  5725. !     GdkGC *gc;
  5726. !     if (gui.drawarea->window == NULL)
  5727.       return;
  5728.   
  5729. !     gui_mch_set_fg_color(color);
  5730.   
  5731. !     gc = gdk_gc_new(gui.drawarea->window);
  5732. !     gdk_gc_set_exposures(gc, gui.visibility != GDK_VISIBILITY_UNOBSCURED);
  5733. !     gdk_gc_set_foreground(gc, gui.fgcolor);
  5734. ! #if defined(USE_FONTSET) && defined(MULTI_BYTE)
  5735. !     if (gui.fontset)
  5736. !     {
  5737. !     if (IsLeadByte(LinePointers[gui.row][gui.col])
  5738. ! # ifdef HANGUL_INPUT
  5739. !         || composing_hangul
  5740. ! # endif
  5741. !        )
  5742. !         gdk_draw_rectangle(gui.drawarea->window, gc,
  5743. !                    FALSE,
  5744. !                    FILL_X(gui.col), FILL_Y(gui.row),
  5745. !                    2*gui.char_width - 1, gui.char_height - 1);
  5746. !     else
  5747. !         gdk_draw_rectangle(gui.drawarea->window, gc,
  5748. !                    FALSE,
  5749. !                    FILL_X(gui.col), FILL_Y(gui.row),
  5750. !                    gui.char_width - 1, gui.char_height - 1);
  5751. !     }
  5752. !     else
  5753. ! #endif
  5754. !     gdk_draw_rectangle(gui.drawarea->window, gc,
  5755. !                FALSE,
  5756. !                FILL_X(gui.col), FILL_Y(gui.row),
  5757. !                gui.char_width - 1, gui.char_height - 1);
  5758. !     gdk_gc_destroy(gc);
  5759.   }
  5760.   
  5761.   /*
  5762. !  * Draw part of a cursor, "w" pixels wide, and "h" pixels high, using
  5763. !  * color "color".
  5764.    */
  5765.   void
  5766. ! gui_mch_draw_part_cursor(int w, int h, GuiColor color)
  5767.   {
  5768. !     GdkGC *gc;
  5769. !     if (gui.drawarea->window == NULL)
  5770.       return;
  5771.   
  5772. !     gui_mch_set_fg_color(color);
  5773.   
  5774. !     gc = gdk_gc_new(gui.drawarea->window);
  5775. !     gdk_gc_set_exposures(gc, gui.visibility != GDK_VISIBILITY_UNOBSCURED);
  5776. !     gdk_gc_set_foreground(gc, gui.fgcolor);
  5777. !     gdk_draw_rectangle(gui.drawarea->window, gc,
  5778. !                TRUE,
  5779. ! #ifdef RIGHTLEFT
  5780. !     /* vertical line should be on the right of current point */
  5781. !        State != CMDLINE && curwin->w_p_rl ? FILL_X(gui.col + 1) - w :
  5782. ! #endif
  5783. !                FILL_X(gui.col),
  5784. !                FILL_Y(gui.row) + gui.char_height - h,
  5785. !                w, h);
  5786. !     gdk_gc_destroy(gc);
  5787.   }
  5788.   
  5789. ! #ifndef GTK_HAVE_FEATURES_1_1_0
  5790. ! static gint
  5791. ! idle_function(GtkWidget * label)
  5792.   {
  5793. !     if (gtk_main_level() > 0)
  5794. !     gtk_main_quit();
  5795. !     return FALSE;
  5796.   }
  5797.   #endif
  5798.   
  5799.   /*
  5800. !  * Catch up with any queued X11 events.  This may put keyboard input into the
  5801. !  * input buffer, call resize call-backs, trigger timers etc.  If there is
  5802. !  * nothing in the X11 event queue (& no timers pending), then we return
  5803. !  * immediately.
  5804.    */
  5805.   void
  5806. ! gui_mch_update()
  5807.   {
  5808. ! #ifdef GTK_HAVE_FEATURES_1_1_0
  5809. !     while (gtk_events_pending() && !vim_is_input_buf_full())
  5810. !     gtk_main_iteration_do(FALSE);
  5811. ! #else
  5812. !     int pending;
  5813. !     /* Somehow the above loop hangs on GTK 1.0.6.  Use the idle_function() to
  5814. !      * work around this weird problem. */
  5815. !     while (((pending = gtk_events_pending()) > 1) && !vim_is_input_buf_full())
  5816. !     gtk_main_iteration();
  5817. !     if ((pending == 1) && !vim_is_input_buf_full()) {
  5818. !     gtk_idle_add((GtkFunction)idle_function, gui.mainwin);
  5819. !     gtk_main_iteration_do(FALSE);
  5820. !     }
  5821. ! #endif
  5822.   }
  5823.   
  5824. + static gint
  5825. + input_timer_cb(gpointer data)
  5826. + {
  5827. +     int *timed_out = (int *) data;
  5828. +     /* Just inform the caller about the accurence of it */
  5829. +     *timed_out = TRUE;
  5830. +     if (gtk_main_level() > 0)
  5831. +     gtk_main_quit();
  5832. +     return FALSE;        /* don't happen again */
  5833. + }
  5834.   
  5835.   /*
  5836. !  * GUI input routine called by gui_wait_for_chars().  Waits for a character
  5837. !  * from the keyboard.
  5838. !  *  wtime == -1     Wait forever.
  5839. !  *  wtime == 0      This should never happen.
  5840. !  *  wtime > 0       Wait wtime milliseconds for a character.
  5841. !  * Returns OK if a character was found to be available within the given time,
  5842. !  * or FAIL otherwise.
  5843.    */
  5844.   int
  5845. ! gui_mch_wait_for_chars(long wtime)
  5846.   {
  5847. !     int focus;
  5848. !     guint timer;
  5849.   
  5850. !     static int timed_out;
  5851.   
  5852. !     timed_out = FALSE;
  5853. !     /* this timeout makes sure that we will return if no characters arrived in
  5854. !      * time */
  5855. !     if (wtime > 0)
  5856. !     timer = gtk_timeout_add((guint32)wtime, input_timer_cb, &timed_out);
  5857. !     else
  5858. !     timer = 0;
  5859. !     focus = gui.in_focus;
  5860. !     do {
  5861. !     /* Stop or start blinking when focus changes */
  5862. !     if (gui.in_focus != focus) {
  5863. !         if (gui.in_focus)
  5864. !         gui_mch_start_blink();
  5865. !         else
  5866. !         gui_mch_stop_blink();
  5867. !         focus = gui.in_focus;
  5868. !     }
  5869. !     /*
  5870. !      * Loop in GTK+ processing  until a timeout or input occurs.
  5871. !      */
  5872. !     gtk_main();
  5873. !     /* Got char, return immediately */
  5874. !     if (!vim_is_input_buf_empty()) {
  5875. !         if (timer != 0 && !timed_out)
  5876. !         gtk_timeout_remove(timer);
  5877. !         return OK;
  5878. !     }
  5879. !     } while (wtime < 0 || !timed_out);
  5880. !     /*
  5881. !      * Flush all eventually pending (drawing) events.
  5882. !      */
  5883. !     gui_mch_update();
  5884. !     return FAIL;
  5885. ! }
  5886. ! /****************************************************************************
  5887. !  * Output drawing routines.
  5888. !  ****************************************************************************/
  5889. ! /* Flush any output to the screen */
  5890. ! void
  5891. ! gui_mch_flush()
  5892. ! {
  5893. !     gdk_flush();
  5894.   }
  5895.   
  5896.   /*
  5897. !  * Clear a rectangular region of the screen from text pos (row1, col1) to
  5898. !  * (row2, col2) inclusive.
  5899.    */
  5900. ! void
  5901. ! gui_mch_clear_block(int row1, int col1, int row2, int col2)
  5902.   {
  5903. !     GdkGC *gc;
  5904. !     GdkColor color;
  5905. !     if (gui.drawarea->window == NULL)
  5906. !     return;
  5907. !     color.pixel = gui.back_pixel;
  5908.   
  5909. !     gc = gdk_gc_new(gui.drawarea->window);
  5910. !     gdk_gc_set_exposures(gc, gui.visibility != GDK_VISIBILITY_UNOBSCURED);
  5911. !     gdk_gc_set_foreground(gc, &color);
  5912.   
  5913. !     /*
  5914. !      * Clear one extra pixel at the right, for when bold characters have
  5915. !      * spilled over to the next column.  This can erase part of the next
  5916. !      * character however in the usage context of this function it will be
  5917. !      * overriden immediately by the correct character again.
  5918. !      */
  5919.   
  5920. !     gdk_draw_rectangle(gui.drawarea->window, gc, TRUE,
  5921. !                FILL_X(col1), FILL_Y(row1),
  5922. !                (col2 - col1 + 1) * gui.char_width + 1,
  5923. !                (row2 - row1 + 1) * gui.char_height);
  5924. !     gdk_gc_destroy(gc);
  5925. ! }
  5926.   
  5927. ! void
  5928. ! gui_mch_clear_all(void)
  5929. ! {
  5930. !     if (gui.drawarea->window == NULL)
  5931. !     return;
  5932.   
  5933. !     gdk_window_clear(gui.drawarea->window);
  5934.   }
  5935.   
  5936.   /*
  5937. !  * Scroll the text between gui.scroll_region_top & gui.scroll_region_bot by the
  5938. !  * number of lines given.  Positive scrolls down (text goes up) and negative
  5939. !  * scrolls up (text goes down).
  5940.    */
  5941. ! static void check_copy_area(void)
  5942.   {
  5943. !     XEvent event;
  5944. !     XGraphicsExposeEvent *gevent;
  5945.   
  5946. !     if (gui.visibility != GDK_VISIBILITY_PARTIAL)
  5947. !     return;
  5948.   
  5949. !     gdk_flush();
  5950. !     /* Wait to check whether the scroll worked or not. */
  5951. !     for (;;) {
  5952. !     if (XCheckTypedEvent(GDK_DISPLAY(), NoExpose, &event))
  5953. !         return;        /* The scroll worked. */
  5954.   
  5955. !     if (XCheckTypedEvent(GDK_DISPLAY(), GraphicsExpose, &event)) {
  5956. !         gevent = (XGraphicsExposeEvent *) & event;
  5957. !         gui_redraw(gevent->x, gevent->y, gevent->width, gevent->height);
  5958. !         if (gevent->count == 0)
  5959. !         return;        /* This was the last expose event */
  5960. !     }
  5961. !     gdk_flush();
  5962. !     }
  5963.   }
  5964.   
  5965. + /*
  5966. +  * Delete the given number of lines from the given row, scrolling up any
  5967. +  * text further down within the scroll region.
  5968. +  */
  5969.   void
  5970. ! gui_mch_delete_lines(int row, int num_lines)
  5971.   {
  5972. !     if (gui.visibility == GDK_VISIBILITY_FULLY_OBSCURED)
  5973. !     return;            /* Can't see the window */
  5974.   
  5975. +     if (num_lines <= 0)
  5976. +     return;
  5977.   
  5978. !     if (row + num_lines > gui.scroll_region_bot) {
  5979. !     /* Scrolled out of region, just blank the lines out */
  5980. !     gui_clear_block(row, 0, gui.scroll_region_bot, (int) Columns - 1);
  5981. !     } else {
  5982. !     GdkGC *gc;
  5983.   
  5984. !     gc = gdk_gc_new(gui.drawarea->window);
  5985. !     gdk_gc_set_exposures(gc, gui.visibility != GDK_VISIBILITY_UNOBSCURED);
  5986. !     gdk_gc_set_foreground(gc, gui.fgcolor);
  5987. !     gdk_gc_set_background(gc, gui.bgcolor);
  5988.   
  5989. !     /* copy one extra pixel, for when bold has spilled over */
  5990. !     gdk_window_copy_area(gui.drawarea->window, gc,
  5991. !                  FILL_X(0), FILL_Y(row),
  5992. !                  gui.drawarea->window,
  5993. !                  FILL_X(0), FILL_Y(row + num_lines),
  5994. !                  gui.char_width * (int) Columns + 1,
  5995. !                  gui.char_height *
  5996. !                 (gui.scroll_region_bot - row - num_lines + 1));
  5997. !     gdk_gc_destroy(gc);
  5998.   
  5999. !     /* Update gui.cursor_row if the cursor scrolled or copied over */
  6000. !     if (gui.cursor_row >= row) {
  6001. !         if (gui.cursor_row < row + num_lines)
  6002. !         gui.cursor_is_valid = FALSE;
  6003. !         else if (gui.cursor_row <= gui.scroll_region_bot)
  6004. !         gui.cursor_row -= num_lines;
  6005. !     }
  6006. !     gui_clear_block(gui.scroll_region_bot - num_lines + 1, 0,
  6007. !             gui.scroll_region_bot, (int) Columns - 1);
  6008. !     check_copy_area();
  6009. !     }
  6010.   }
  6011.   
  6012.   /*
  6013. !  * Insert the given number of lines before the given row, scrolling down any
  6014. !  * following text within the scroll region.
  6015.    */
  6016. ! void
  6017. ! gui_mch_insert_lines(int row, int num_lines)
  6018.   {
  6019. !     if (gui.visibility == GDK_VISIBILITY_FULLY_OBSCURED)
  6020. !     return;            /* Can't see the window */
  6021.   
  6022. !     if (num_lines <= 0)
  6023. !     return;
  6024.   
  6025. !     if (row + num_lines > gui.scroll_region_bot) {
  6026. !     /* Scrolled out of region, just blank the lines out */
  6027. !     gui_clear_block(row, 0, gui.scroll_region_bot, (int) Columns - 1);
  6028. !     } else {
  6029. !     GdkGC *gc;
  6030.   
  6031. !     gc = gdk_gc_new(gui.drawarea->window);
  6032. !     gdk_gc_set_exposures(gc, gui.visibility != GDK_VISIBILITY_UNOBSCURED);
  6033. !     gdk_gc_set_foreground(gc, gui.fgcolor);
  6034. !     gdk_gc_set_background(gc, gui.bgcolor);
  6035.   
  6036. +     /* copy one extra pixel, for when bold has spilled over */
  6037. +     gdk_window_copy_area(gui.drawarea->window, gc,
  6038. +                  FILL_X(0), FILL_Y(row + num_lines),
  6039. +                  gui.drawarea->window,
  6040. +                  FILL_X(0), FILL_Y(row),
  6041. +                  gui.char_width * (int) Columns + 1,
  6042. +                  gui.char_height *
  6043. +                 (gui.scroll_region_bot - row - num_lines + 1));
  6044. +     gdk_gc_destroy(gc);
  6045.   
  6046. !     /* Update gui.cursor_row if the cursor scrolled or copied over */
  6047. !     if (gui.cursor_row >= gui.row) {
  6048. !         if (gui.cursor_row <= gui.scroll_region_bot - num_lines)
  6049. !         gui.cursor_row += num_lines;
  6050. !         else if (gui.cursor_row <= gui.scroll_region_bot)
  6051. !         gui.cursor_is_valid = FALSE;
  6052. !     }
  6053. !     gui_clear_block(row, 0, row + num_lines - 1, (int) Columns - 1);
  6054. !     check_copy_area();
  6055.       }
  6056. + }
  6057.   
  6058. ! /*
  6059. !  * X Selection stuff, for cutting and pasting text to other windows.
  6060. !  */
  6061. ! void
  6062. ! clip_mch_request_selection()
  6063. ! {
  6064. !     /* First try to get the content of our own special clipboard. */
  6065. !     received_selection = RS_NONE;
  6066. !     (void)gtk_selection_convert(gui.drawarea,
  6067. !                     GDK_SELECTION_PRIMARY, clipboard.atom,
  6068. !                     (guint32)GDK_CURRENT_TIME);
  6069. !     while (received_selection == RS_NONE)
  6070. !     gtk_main();        /* wait for selection_received_event */
  6071.   
  6072. !     if (received_selection == RS_FAIL)
  6073.       {
  6074. !     /* Now try to get it out of the usual string selection. */
  6075. !     received_selection = RS_NONE;
  6076. !     (void)gtk_selection_convert(gui.drawarea, GDK_SELECTION_PRIMARY,
  6077. !                     GDK_TARGET_STRING,
  6078. !                     (guint32)GDK_CURRENT_TIME);
  6079. !     while (received_selection == RS_NONE)
  6080. !         gtk_main();        /* wait for selection_received_event */
  6081.       }
  6082. + }
  6083.   
  6084. ! void
  6085. ! clip_mch_lose_selection()
  6086. ! {
  6087. !     gtk_selection_owner_set(gui.drawarea,
  6088. !                 GDK_SELECTION_PRIMARY, (guint32)GDK_CURRENT_TIME);
  6089. !     gui_mch_update();
  6090. ! }
  6091.   
  6092. ! /*
  6093. !  * Check whatever we allready own the selection.
  6094. !  */
  6095. ! int
  6096. ! clip_mch_own_selection()
  6097. ! {
  6098. ! #if 0
  6099. !     return gdk_selection_owner_get(
  6100. !                 GDK_SELECTION_PRIMARY) == gui.drawarea->window;
  6101. ! #else
  6102. !     /* At this point we always already own the clipboard */
  6103.   
  6104. !     return OK;
  6105. ! #endif
  6106.   }
  6107.   
  6108.   /*
  6109. !  * Send the current selection to the clipboard.
  6110.    */
  6111. ! void
  6112. ! clip_mch_set_selection()
  6113.   {
  6114. !     gtk_selection_owner_set(gui.drawarea,
  6115. !                 GDK_SELECTION_PRIMARY,
  6116. !                 (guint32)GDK_CURRENT_TIME);
  6117. !     gui_mch_update();
  6118. ! }
  6119.   
  6120.   
  6121. ! #if defined(WANT_MENU) || defined(PROTO)
  6122. ! /*
  6123. !  * Make a menu item appear either active or not active (grey or not grey).
  6124. !  */
  6125. ! void
  6126. ! gui_mch_menu_grey(VimMenu * menu, int grey)
  6127. ! {
  6128. !     if (menu->id == 0)
  6129. !     return;
  6130.   
  6131. !     gui_mch_menu_hidden(menu, FALSE);
  6132. !     gtk_widget_set_sensitive(menu->id, !grey);
  6133.   
  6134. !     gui_mch_update();
  6135.   }
  6136.   
  6137. ! /*
  6138. !  * Make menu item hidden or not hidden.
  6139. !  */
  6140. ! void
  6141. ! gui_mch_menu_hidden(VimMenu * menu, int hidden)
  6142.   {
  6143. !     if (menu->id == 0)
  6144. !     return;
  6145.   
  6146. !     if (hidden) {
  6147. !     if (GTK_WIDGET_VISIBLE(menu->id))
  6148. !         gtk_widget_hide(menu->id);
  6149. !     } else {
  6150. !     if (!GTK_WIDGET_VISIBLE(menu->id))
  6151. !         gtk_widget_show(menu->id);
  6152.       }
  6153.   
  6154. !     gui_mch_update();
  6155.   }
  6156.   
  6157. ! /*
  6158. !  * This is called after setting all the menus to grey/hidden or not.
  6159. !  */
  6160. ! void
  6161. ! gui_mch_draw_menubar()
  6162.   {
  6163. !     /* just make sure that the visual changes get effect immediately */
  6164. !     gui_mch_update();
  6165.   }
  6166. + #endif
  6167.   
  6168.   /*
  6169. !  * Scrollbar stuff.
  6170.    */
  6171. ! void
  6172. ! gui_mch_enable_scrollbar(GuiScrollbar * sb, int flag)
  6173.   {
  6174. !     if (sb->id == 0)
  6175. !     return;
  6176. !     if (flag)
  6177. !     gtk_widget_show(sb->id);
  6178. !     else
  6179. !     gtk_widget_hide(sb->id);
  6180. !     update_window_manager_hints();
  6181.   }
  6182.   
  6183.   /*
  6184. !  * Return the lightness of a pixel.  White is 255.
  6185.    */
  6186. ! int
  6187. ! gui_mch_get_lightness(GuiColor pixel)
  6188.   {
  6189. !     XColor xc;
  6190. !     GdkColormap *colormap;
  6191. !     colormap = gtk_widget_get_colormap(gui.mainwin);
  6192. !     xc.pixel = pixel;
  6193. !     /* FIXME: this is crap in terms of actual accuracy */
  6194. !     XQueryColor(GDK_DISPLAY(), GDK_COLORMAP_XCOLORMAP(colormap), &xc);
  6195. !     return (int) (xc.red * 3 + xc.green * 6 + xc.blue) / (10 * 256);
  6196.   }
  6197.   
  6198. ! #if (defined(SYNTAX_HL) && defined(WANT_EVAL)) || defined(PROTO)
  6199.   /*
  6200. !  * Return the RGB value of a pixel as "#RRGGBB".
  6201. !  *
  6202. !  * Unfortunately there appears to be no way to accomplish this entierly
  6203. !  * without resorting to native X11 functions.
  6204.    */
  6205. ! char_u *
  6206. ! gui_mch_get_rgb(GuiColor pixel)
  6207.   {
  6208. !     XColor xc;
  6209. !     GdkColormap *colormap;
  6210. !     static char_u retval[10];
  6211.   
  6212. !     colormap = gtk_widget_get_colormap(gui.mainwin);
  6213.   
  6214. !     xc.pixel = pixel;
  6215. !     XQueryColor(GDK_DISPLAY(), GDK_COLORMAP_XCOLORMAP(colormap), &xc);
  6216. !     sprintf((char *) retval, "#%02x%02x%02x",
  6217. !         (unsigned) xc.red >> 8,
  6218. !         (unsigned) xc.green >> 8,
  6219. !         (unsigned) xc.blue >> 8);
  6220. !     /* WOAH!!! Returning pointer to static string!  Could be overwritten when
  6221. !      * this function is called recursively (e.g., when some event occurs). */
  6222. !     return retval;
  6223.   }
  6224. + #endif
  6225.   
  6226. ! /*
  6227. !  * Get current y mouse coordinate in text window.
  6228. !  * Return -1 when unknown.
  6229. !  */
  6230. ! int
  6231. ! gui_mch_get_mouse_x(void)
  6232.   {
  6233. !     int winx, winy;
  6234. !     GdkModifierType mask;
  6235.   
  6236. !     gdk_window_get_pointer(gui.drawarea->window, &winx, &winy, &mask);
  6237. !     return winx;
  6238.   }
  6239.   
  6240. ! int
  6241. ! gui_mch_get_mouse_y(void)
  6242.   {
  6243. !     int winx, winy;
  6244. !     GdkModifierType mask;
  6245.   
  6246. !     gdk_window_get_pointer(gui.drawarea->window, &winx, &winy, &mask);
  6247. !     return winy;
  6248. ! }
  6249. ! void
  6250. ! gui_mch_setmouse(int x, int y)
  6251. ! {
  6252. !     /* Sorry for the Xlib call, but we can't avoid it, since there is no
  6253. !      * internal GDK mechanism present to accomplish this.
  6254. !      */
  6255. !     XWarpPointer(GDK_DISPLAY(), (Window) 0,
  6256. !          GDK_WINDOW_XWINDOW(gui.drawarea->window), 0, 0, 0, 0, x, y);
  6257.   }
  6258. *** ../vim-5.6a.17/src/ui.c    Mon Dec 20 09:59:15 1999
  6259. --- src/ui.c    Sat Jan  8 20:56:28 2000
  6260. ***************
  6261. *** 1156,1161 ****
  6262. --- 1156,1169 ----
  6263.   }
  6264.   #endif
  6265.   
  6266. + #if defined(USE_GUI_GTK) || defined(PROTO)
  6267. +     int
  6268. + vim_used_in_input_buf()
  6269. + {
  6270. +     return inbufcount;
  6271. + }
  6272. + #endif
  6273.   /* Add the given bytes to the input buffer */
  6274.       void
  6275.   add_to_input_buf(s, len)
  6276. *** ../vim-5.6a.17/src/proto/ui.pro    Mon Dec 20 09:58:55 1999
  6277. --- src/proto/ui.pro    Sat Jan  8 20:56:32 2000
  6278. ***************
  6279. *** 30,35 ****
  6280. --- 30,36 ----
  6281.   int vim_is_input_buf_full __ARGS((void));
  6282.   int vim_is_input_buf_empty __ARGS((void));
  6283.   int vim_free_in_input_buf __ARGS((void));
  6284. + int vim_used_in_input_buf __ARGS((void));
  6285.   void add_to_input_buf __ARGS((char_u *s, int len));
  6286.   void push_raw_key __ARGS((char_u *s, int len));
  6287.   void trash_input_buf __ARGS((void));
  6288. *** ../vim-5.6a.17/src/misc2.c    Thu Dec 23 11:13:43 1999
  6289. --- src/misc2.c    Sat Jan  8 21:27:11 2000
  6290. ***************
  6291. *** 2031,2037 ****
  6292.       return State;
  6293.   }
  6294.   
  6295. ! #if defined(MKSESSION) || defined(MSWIN) || defined(PROTO)
  6296.   /*
  6297.    * Change to a file's directory.
  6298.    */
  6299. --- 2031,2037 ----
  6300.       return State;
  6301.   }
  6302.   
  6303. ! #if defined(MKSESSION) || defined(MSWIN) || defined(USE_GUI_GTK) || defined(PROTO)
  6304.   /*
  6305.    * Change to a file's directory.
  6306.    */
  6307. *** ../vim-5.6a.17/src/version.c    Sat Jan  8 22:58:58 2000
  6308. --- src/version.c    Sat Jan  8 22:58:33 2000
  6309. ***************
  6310. *** 420,421 ****
  6311. --- 420,423 ----
  6312.   {   /* Add new patch number below this line */
  6313. + /**/
  6314. +     18,
  6315.   /**/
  6316.  
  6317. -- 
  6318. hundred-and-one symptoms of being an internet addict:
  6319. 79. All of your most erotic dreams have a scrollbar at the right side.
  6320.  
  6321. --/-/---- Bram Moolenaar ---- Bram@moolenaar.net ---- Bram@vim.org ---\-\--
  6322.   \ \    www.vim.org/iccf      www.moolenaar.net       www.vim.org    / /
  6323.