To: vim-dev@vim.org Subject: Patch 6.0.209 Fcc: outbox From: Bram Moolenaar MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit ------------ Patch 6.0.209 Problem: GUI GTK: After selecting a 'guifont' with the font dialog there are redraw problems for multi-byte characters. Solution: Separate the font dialog from setting the new font name to avoid that "*" is used to find wide and bold fonts. When redrawing extra characters for the bold trick, take care of UTF-8 characters. Files: src/gui.c, src/gui_gtk_x11.c, src/option.c, src/proto/gui.pro, src/proto/gui_gtk_x11.pro *** ../vim60.208/src/gui.c Tue Feb 5 21:59:55 2002 --- src/gui.c Mon Feb 11 11:51:53 2002 *************** *** 19,25 **** static void gui_check_pos __ARGS((void)); static void gui_position_components __ARGS((int)); static void gui_outstr __ARGS((char_u *, int)); ! static void gui_screenchar __ARGS((int off, int flags, guicolor_T fg, guicolor_T bg, int back)); static void gui_delete_lines __ARGS((int row, int count)); static void gui_insert_lines __ARGS((int row, int count)); static void gui_do_scrollbar __ARGS((win_T *wp, int which, int enable)); --- 19,25 ---- static void gui_check_pos __ARGS((void)); static void gui_position_components __ARGS((int)); static void gui_outstr __ARGS((char_u *, int)); ! static int gui_screenchar __ARGS((int off, int flags, guicolor_T fg, guicolor_T bg, int back)); static void gui_delete_lines __ARGS((int row, int count)); static void gui_insert_lines __ARGS((int row, int count)); static void gui_do_scrollbar __ARGS((win_T *wp, int which, int enable)); *************** *** 909,919 **** gui.highlight_mask = (cattr | attr); #ifdef FEAT_HANGULIN if (composing_hangul) ! gui_outstr_nowrap(composing_hangul_buffer, 2, GUI_MON_IS_CURSOR | GUI_MON_NOCLEAR, cfg, cbg, 0); else #endif ! gui_screenchar(LineOffset[gui.row] + gui.col, GUI_MON_IS_CURSOR | GUI_MON_NOCLEAR, cfg, cbg, 0); } else --- 909,919 ---- gui.highlight_mask = (cattr | attr); #ifdef FEAT_HANGULIN if (composing_hangul) ! (void)gui_outstr_nowrap(composing_hangul_buffer, 2, GUI_MON_IS_CURSOR | GUI_MON_NOCLEAR, cfg, cbg, 0); else #endif ! (void)gui_screenchar(LineOffset[gui.row] + gui.col, GUI_MON_IS_CURSOR | GUI_MON_NOCLEAR, cfg, cbg, 0); } else *************** *** 942,948 **** #ifndef FEAT_GUI_MSWIN /* doesn't seem to work for MSWindows */ gui.highlight_mask = ScreenAttrs[LineOffset[gui.row] + gui.col]; ! gui_screenchar(LineOffset[gui.row] + gui.col, GUI_MON_TRS_CURSOR | GUI_MON_NOCLEAR, (guicolor_T)0, (guicolor_T)0, 0); #endif --- 942,948 ---- #ifndef FEAT_GUI_MSWIN /* doesn't seem to work for MSWindows */ gui.highlight_mask = ScreenAttrs[LineOffset[gui.row] + gui.col]; ! (void)gui_screenchar(LineOffset[gui.row] + gui.col, GUI_MON_TRS_CURSOR | GUI_MON_NOCLEAR, (guicolor_T)0, (guicolor_T)0, 0); #endif *************** *** 1627,1639 **** else this_len = len; ! gui_outstr_nowrap(s, this_len, 0, (guicolor_T)0, (guicolor_T)0, 0); s += this_len; len -= this_len; #ifdef FEAT_MBYTE /* fill up for a double-width char that doesn't fit. */ if (len > 0 && gui.col < Columns) ! gui_outstr_nowrap((char_u *)" ", 1, 0, (guicolor_T)0, (guicolor_T)0, 0); #endif /* The cursor may wrap to the next line. */ --- 1627,1640 ---- else this_len = len; ! (void)gui_outstr_nowrap(s, this_len, ! 0, (guicolor_T)0, (guicolor_T)0, 0); s += this_len; len -= this_len; #ifdef FEAT_MBYTE /* fill up for a double-width char that doesn't fit. */ if (len > 0 && gui.col < Columns) ! (void)gui_outstr_nowrap((char_u *)" ", 1, 0, (guicolor_T)0, (guicolor_T)0, 0); #endif /* The cursor may wrap to the next line. */ *************** *** 1648,1655 **** /* * Output one character (may be one or two display cells). * Caller must check for valid "off". */ ! static void gui_screenchar(off, flags, fg, bg, back) int off; /* Offset from start of screen */ int flags; --- 1649,1657 ---- /* * Output one character (may be one or two display cells). * Caller must check for valid "off". + * Returns FAIL or OK, just like gui_outstr_nowrap(). */ ! static int gui_screenchar(off, flags, fg, bg, back) int off; /* Offset from start of screen */ int flags; *************** *** 1661,1687 **** /* Don't draw right halve of a double-width UTF-8 char. "cannot happen" */ if (enc_utf8 && ScreenLines[off] == 0) ! return; if (enc_utf8 && ScreenLinesUC[off] != 0) /* Draw UTF-8 multi-byte character. */ ! gui_outstr_nowrap(buf, ! utfc_char2bytes(off, buf), ! flags, fg, bg, 0); ! else if (enc_dbcs == DBCS_JPNU && ScreenLines[off] == 0x8e) { buf[0] = ScreenLines[off]; buf[1] = ScreenLines2[off]; ! gui_outstr_nowrap(buf, 2, flags, fg, bg, 0); } ! else ! /* Draw non-multi-byte character or DBCS character. */ ! gui_outstr_nowrap(ScreenLines + off, ! enc_dbcs ? (*mb_ptr2len_check)(ScreenLines + off) : 1, ! flags, fg, bg, back); #else ! gui_outstr_nowrap(ScreenLines + off, ! 1, ! flags, fg, bg, back); #endif } --- 1663,1688 ---- /* Don't draw right halve of a double-width UTF-8 char. "cannot happen" */ if (enc_utf8 && ScreenLines[off] == 0) ! return OK; ! if (enc_utf8 && ScreenLinesUC[off] != 0) /* Draw UTF-8 multi-byte character. */ ! return gui_outstr_nowrap(buf, utfc_char2bytes(off, buf), ! flags, fg, bg, back); ! ! if (enc_dbcs == DBCS_JPNU && ScreenLines[off] == 0x8e) { buf[0] = ScreenLines[off]; buf[1] = ScreenLines2[off]; ! return gui_outstr_nowrap(buf, 2, flags, fg, bg, back); } ! ! /* Draw non-multi-byte character or DBCS character. */ ! return gui_outstr_nowrap(ScreenLines + off, ! enc_dbcs ? (*mb_ptr2len_check)(ScreenLines + off) : 1, ! flags, fg, bg, back); #else ! return gui_outstr_nowrap(ScreenLines + off, 1, flags, fg, bg, back); #endif } *************** *** 1693,1700 **** * actually draw (an inverted) cursor. * GUI_MON_TRS_CURSOR is used to draw the cursor text with a transparant * background. */ ! void gui_outstr_nowrap(s, len, flags, fg, bg, back) char_u *s; int len; --- 1694,1703 ---- * actually draw (an inverted) cursor. * GUI_MON_TRS_CURSOR is used to draw the cursor text with a transparant * background. + * Returns OK, unless "back" is non-zero and using the bold trick, then return + * FAIL (the caller should start drawing "back" chars back). */ ! int gui_outstr_nowrap(s, len, flags, fg, bg, back) char_u *s; int len; *************** *** 1722,1728 **** if (len < 0) len = (int)STRLEN(s); if (len == 0) ! return; #ifdef FEAT_SIGN_ICONS if (*s == SIGN_BYTE) --- 1725,1731 ---- if (len < 0) len = (int)STRLEN(s); if (len == 0) ! return OK; #ifdef FEAT_SIGN_ICONS if (*s == SIGN_BYTE) *************** *** 1853,1867 **** /* * When drawing bold or italic characters the spill-over from the left ! * neighbor may be destroyed. Backup to start redrawing just after a ! * blank. */ ! if ((draw_flags & DRAW_BOLD) || (highlight_mask & HL_ITALIC)) ! { ! s -= back; ! len += back; ! col -= back; ! } #ifdef RISCOS /* If there's no italic font, then fake it */ --- 1856,1866 ---- /* * When drawing bold or italic characters the spill-over from the left ! * neighbor may be destroyed. Let the caller backup to start redrawing ! * just after a blank. */ ! if (back != 0 && ((draw_flags & DRAW_BOLD) || (highlight_mask & HL_ITALIC))) ! return FAIL; #ifdef RISCOS /* If there's no italic font, then fake it */ *************** *** 2022,2027 **** --- 2021,2028 ---- /* Draw the sign on top of the spaces. */ gui_mch_drawsign(gui.row, col, gui.highlight_mask); #endif + + return OK; } /* *************** *** 2036,2042 **** #ifdef FEAT_HANGULIN if (composing_hangul && gui.col == gui.cursor_col && gui.row == gui.cursor_row) ! gui_outstr_nowrap(composing_hangul_buffer, 2, GUI_MON_IS_CURSOR | GUI_MON_NOCLEAR, gui.norm_pixel, gui.back_pixel, 0); else --- 2037,2043 ---- #ifdef FEAT_HANGULIN if (composing_hangul && gui.col == gui.cursor_col && gui.row == gui.cursor_row) ! (void)gui_outstr_nowrap(composing_hangul_buffer, 2, GUI_MON_IS_CURSOR | GUI_MON_NOCLEAR, gui.norm_pixel, gui.back_pixel, 0); else *************** *** 2102,2108 **** int off; char_u first_attr; int idx, len; ! int back; int retval = FALSE; #ifdef FEAT_MBYTE int orig_col1, orig_col2; --- 2103,2109 ---- int off; char_u first_attr; int idx, len; ! int back, nback; int retval = FALSE; #ifdef FEAT_MBYTE int orig_col1, orig_col2; *************** *** 2160,2169 **** if (ScreenAttrs[off - 1 - back] != ScreenAttrs[off] || ScreenLines[off - 1 - back] == ' ') break; ! retval = (col1 > 0 && ScreenAttrs[off - 1] != 0 && back == 0); ! /* break it up in strings of characters with the same attributes */ ! /* print UTF-8 characters individually */ while (len > 0) { first_attr = ScreenAttrs[off]; --- 2161,2171 ---- if (ScreenAttrs[off - 1 - back] != ScreenAttrs[off] || ScreenLines[off - 1 - back] == ' ') break; ! retval = (col1 > 0 && ScreenAttrs[off - 1] != 0 && back == 0 ! && ScreenLines[off - 1] != ' '); ! /* Break it up in strings of characters with the same attributes. */ ! /* Print UTF-8 characters individually. */ while (len > 0) { first_attr = ScreenAttrs[off]; *************** *** 2172,2197 **** if (enc_utf8 && ScreenLinesUC[off] != 0) { /* output multi-byte character separately */ ! gui_screenchar(off, flags, (guicolor_T)0, (guicolor_T)0, back); ! ++off; ! --len; ! if (ScreenLines[off] == 0) ! { ! ++off; ! --len; ! } } else if (enc_dbcs == DBCS_JPNU && ScreenLines[off] == 0x8e) { /* output double-byte, single-width character separately */ ! gui_screenchar(off, flags, (guicolor_T)0, (guicolor_T)0, back); ! ++off; ! --len; } else #endif { ! for (idx = 0; len > 0 && ScreenAttrs[off + idx] == first_attr; idx++) { #ifdef FEAT_MBYTE --- 2174,2197 ---- if (enc_utf8 && ScreenLinesUC[off] != 0) { /* output multi-byte character separately */ ! nback = gui_screenchar(off, flags, ! (guicolor_T)0, (guicolor_T)0, back); ! if (gui.col < Columns && ScreenLines[off + 1] == 0) ! idx = 2; ! else ! idx = 1; } else if (enc_dbcs == DBCS_JPNU && ScreenLines[off] == 0x8e) { /* output double-byte, single-width character separately */ ! nback = gui_screenchar(off, flags, ! (guicolor_T)0, (guicolor_T)0, back); ! idx = 1; } else #endif { ! for (idx = 0; idx < len && ScreenAttrs[off + idx] == first_attr; idx++) { #ifdef FEAT_MBYTE *************** *** 2205,2221 **** break; if (len > 1 && (*mb_ptr2len_check)(ScreenLines + off + idx) == 2) - { ++idx; /* skip second byte of double-byte char */ - --len; - } } #endif - --len; } ! gui_outstr_nowrap(ScreenLines + off, idx, flags, (guicolor_T)0, (guicolor_T)0, back); off += idx; } back = 0; } --- 2205,2229 ---- break; if (len > 1 && (*mb_ptr2len_check)(ScreenLines + off + idx) == 2) ++idx; /* skip second byte of double-byte char */ } #endif } ! nback = gui_outstr_nowrap(ScreenLines + off, idx, flags, (guicolor_T)0, (guicolor_T)0, back); + } + if (nback == FAIL) + { + /* Must back up to start drawing where a bold or italic word + * starts. */ + off -= back; + len += back; + gui.col -= back; + } + else + { off += idx; + len -= idx; } back = 0; } *** ../vim60.208/src/gui_gtk_x11.c Fri Dec 14 20:19:45 2001 --- src/gui_gtk_x11.c Sun Feb 10 21:41:49 2002 *************** *** 2445,2509 **** #endif /* ! * Try to load the requested single font. */ ! static GuiFont ! get_font(char_u *font_name) { ! if (STRCMP(font_name, "*") == 0) { ! /* Request for a font handling dialog. ! */ ! ! if (!gui.fontdlg) ! { ! GtkFontSelectionDialog *fsd = NULL; ! gui.fontdlg = gtk_font_selection_dialog_new(_("Font Selection")); ! fsd = GTK_FONT_SELECTION_DIALOG(gui.fontdlg); ! if (p_guifont != NULL) ! gtk_font_selection_dialog_set_font_name(fsd, ! (char *)p_guifont); ! gtk_window_set_modal(GTK_WINDOW(gui.fontdlg), TRUE); ! gtk_window_set_transient_for(GTK_WINDOW(gui.fontdlg), ! GTK_WINDOW(gui.mainwin)); ! gtk_signal_connect(GTK_OBJECT(gui.fontdlg), "destroy", ! GTK_SIGNAL_FUNC(font_sel_destroy), &gui); ! gtk_signal_connect(GTK_OBJECT(fsd->ok_button), "clicked", ! GTK_SIGNAL_FUNC(font_sel_ok), &gui); ! gtk_signal_connect(GTK_OBJECT(fsd->cancel_button), "clicked", ! GTK_SIGNAL_FUNC(font_sel_cancel), &gui); ! } ! if (gui.fontname) ! { ! g_free(gui.fontname); ! gui.fontname = NULL; ! } ! gtk_window_position(GTK_WINDOW(gui.fontdlg), GTK_WIN_POS_MOUSE); ! gtk_widget_show(gui.fontdlg); ! { ! static gchar *spacings[] = {"c", "m", NULL}; ! /* In GTK 1.2.3 this must be after the gtk_widget_show() call, ! * otherwise everything is blocked for ten seconds. */ ! gtk_font_selection_dialog_set_filter( ! GTK_FONT_SELECTION_DIALOG(gui.fontdlg), ! GTK_FONT_FILTER_BASE, ! GTK_FONT_ALL, NULL, NULL, ! NULL, NULL, spacings, NULL); ! } ! while (gui.fontdlg && GTK_WIDGET_VISIBLE(gui.fontdlg)) ! gtk_main_iteration_do(TRUE); ! if (gui.fontname == NULL) ! return NOFONT; ! vim_free(p_guifont); ! p_guifont = vim_strsave(gui.fontname); ! font_name = p_guifont; } ! return gui_mch_get_font(font_name, FALSE); } /* --- 2445,2504 ---- #endif /* ! * Put up a font dialog and return the selected font name in allocated memory. ! * "oldval" is the previous value. ! * Return NULL when cancelled. */ ! char_u * ! gui_mch_font_dialog(char_u *oldval) { ! if (!gui.fontdlg) { ! GtkFontSelectionDialog *fsd = NULL; ! gui.fontdlg = gtk_font_selection_dialog_new(_("Font Selection")); ! fsd = GTK_FONT_SELECTION_DIALOG(gui.fontdlg); ! gtk_window_set_modal(GTK_WINDOW(gui.fontdlg), TRUE); ! gtk_window_set_transient_for(GTK_WINDOW(gui.fontdlg), ! GTK_WINDOW(gui.mainwin)); ! gtk_signal_connect(GTK_OBJECT(gui.fontdlg), "destroy", ! GTK_SIGNAL_FUNC(font_sel_destroy), &gui); ! gtk_signal_connect(GTK_OBJECT(fsd->ok_button), "clicked", ! GTK_SIGNAL_FUNC(font_sel_ok), &gui); ! gtk_signal_connect(GTK_OBJECT(fsd->cancel_button), "clicked", ! GTK_SIGNAL_FUNC(font_sel_cancel), &gui); ! } ! if (oldval != NULL && *oldval != NUL) ! gtk_font_selection_dialog_set_font_name( ! GTK_FONT_SELECTION_DIALOG(gui.fontdlg), (char *)oldval); ! if (gui.fontname) ! { ! g_free(gui.fontname); ! gui.fontname = NULL; ! } ! gtk_window_position(GTK_WINDOW(gui.fontdlg), GTK_WIN_POS_MOUSE); ! gtk_widget_show(gui.fontdlg); ! { ! static gchar *spacings[] = {"c", "m", NULL}; ! /* In GTK 1.2.3 this must be after the gtk_widget_show() call, ! * otherwise everything is blocked for ten seconds. */ ! gtk_font_selection_dialog_set_filter( ! GTK_FONT_SELECTION_DIALOG(gui.fontdlg), ! GTK_FONT_FILTER_BASE, ! GTK_FONT_ALL, NULL, NULL, ! NULL, NULL, spacings, NULL); } ! /* Wait for the font dialog to be closed. */ ! while (gui.fontdlg && GTK_WIDGET_VISIBLE(gui.fontdlg)) ! gtk_main_iteration_do(TRUE); ! ! if (gui.fontname == NULL) ! return NULL; ! return vim_strsave(gui.fontname); } /* *************** *** 2619,2625 **** * be present on all X11 servers. */ if (font_name == NULL) font_name = (char_u *)DFLT_FONT; ! font = get_font(font_name); } if (font == NULL) --- 2614,2620 ---- * be present on all X11 servers. */ if (font_name == NULL) font_name = (char_u *)DFLT_FONT; ! font = gui_mch_get_font(font_name, FALSE); } if (font == NULL) *** ../vim60.208/src/option.c Fri Feb 8 10:30:44 2002 --- src/option.c Mon Feb 11 10:19:01 2002 *************** *** 4734,4745 **** /* 'guifont' */ else if (varp == &p_guifont) { ! if (gui.in_use && gui_init_font(p_guifont, FALSE) != OK ! # if defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_PHOTON) ! && *p_guifont != '*' # endif ! ) ! errmsg = (char_u *)N_("Invalid font(s)"); } # ifdef FEAT_XFONTSET else if (varp == &p_guifontset) --- 4734,4766 ---- /* 'guifont' */ else if (varp == &p_guifont) { ! if (gui.in_use) ! { ! # ifdef FEAT_GUI_GTK ! if (STRCMP(p_guifont, "*") == 0) ! { ! /* ! * Put up a font dialog and let the user select a new value. ! * If this is cancelled go back to the old value but don't ! * give an error message. ! */ ! p = gui_mch_font_dialog(oldval); ! if (p != NULL) ! { ! free_string_option(p_guifont); ! p_guifont = p; ! } ! else ! errmsg = (char_u *)""; ! } # endif ! if (errmsg == NULL && gui_init_font(p_guifont, FALSE) != OK ! # if defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_PHOTON) ! && STRCMP(p_guifont, "*") != 0 ! # endif ! ) ! errmsg = (char_u *)N_("Invalid font(s)"); ! } } # ifdef FEAT_XFONTSET else if (varp == &p_guifontset) *** ../vim60.208/src/proto/gui.pro Tue Sep 25 21:49:28 2001 --- src/proto/gui.pro Mon Feb 11 11:29:04 2002 *************** *** 25,31 **** void gui_write __ARGS((char_u *s, int len)); void gui_dont_update_cursor __ARGS((void)); void gui_can_update_cursor __ARGS((void)); ! void gui_outstr_nowrap __ARGS((char_u *s, int len, int flags, guicolor_T fg, guicolor_T bg, int back)); void gui_undraw_cursor __ARGS((void)); void gui_redraw __ARGS((int x, int y, int w, int h)); int gui_redraw_block __ARGS((int row1, int col1, int row2, int col2, int flags)); --- 25,31 ---- void gui_write __ARGS((char_u *s, int len)); void gui_dont_update_cursor __ARGS((void)); void gui_can_update_cursor __ARGS((void)); ! int gui_outstr_nowrap __ARGS((char_u *s, int len, int flags, guicolor_T fg, guicolor_T bg, int back)); void gui_undraw_cursor __ARGS((void)); void gui_redraw __ARGS((int x, int y, int w, int h)); int gui_redraw_block __ARGS((int row1, int col1, int row2, int col2, int flags)); *** ../vim60.208/src/proto/gui_gtk_x11.pro Tue Sep 25 21:49:30 2001 --- src/proto/gui_gtk_x11.pro Sun Feb 10 21:40:25 2002 *************** *** 16,21 **** --- 16,22 ---- void gui_mch_show_toolbar __ARGS((int showit)); int gui_mch_adjust_charsize __ARGS((void)); GuiFontset gui_mch_get_fontset __ARGS((char_u *name, int report_error, int fixed_width)); + char_u *gui_mch_font_dialog __ARGS((char_u *oldval)); int gui_mch_init_font __ARGS((char_u *font_name, int fontset)); GuiFont gui_mch_get_font __ARGS((char_u *name, int report_error)); void gui_mch_set_font __ARGS((GuiFont font)); *** ../vim60.208/src/version.c Sun Feb 10 17:03:39 2002 --- src/version.c Mon Feb 11 11:55:19 2002 *************** *** 608,609 **** --- 608,611 ---- { /* Add new patch number below this line */ + /**/ + 209, /**/ -- Shit makes the flowers grow and that's beautiful /// Bram Moolenaar -- Bram@moolenaar.net -- http://www.moolenaar.net \\\ ((( Creator of Vim -- http://vim.sf.net -- ftp://ftp.vim.org/pub/vim ))) \\\ Help me helping AIDS orphans in Uganda - http://iccf-holland.org ///