Skip to content

Instantly share code, notes, and snippets.

@ynkdir
Created March 13, 2015 08:55
Show Gist options
  • Save ynkdir/6eff3903cc417a933d61 to your computer and use it in GitHub Desktop.
Save ynkdir/6eff3903cc417a933d61 to your computer and use it in GitHub Desktop.
vim patches
ynkdir-imoverthespot
gtk2: Changed Input Method editing style from on-the-spot to over-the-spot. On-the-spot implementation is buggy and has problems detailed in mbyte.c:im_preedit_changed_cb().
ynkdir-imactivatekey
gtk2: Removed 'imactivatekey' option and related code because it doesn't work.
ynkdir-imcursorhold
x11: Changed to not fire CursorHold? autocmd event while IM pre-editing. It may cause trouble.
ynkdir-pangolineheight
gtk2: Fixed that default line height is too small in ja_JP locale. Use pango_language_get_sample_string() and calculate height for the text ("locale's sample" + "C's sample"). FIXME: What is the correct way?
pango_font_metrics_get_ascent() and pango_font_metrics_get_descent() returns small height in ja_JP locale.
For example, for "Monospace 10":
LC_ALL=C ascent:13px + descent:4px = 17px
LC_ALL=ja_JP.UTF-8 ascent:12px + descent:2px = 14px
So some characters are displayed shortly and underscore is not shown. It is required to :set linespace=4 to show underscore.
Ubuntu 11.04
$ pkg-config --modversion pango
1.28.4
$ pkg-config --modversion cairo
1.10.2
test code: https://gist.github.com/849071
diff -r 03e6a768a028 -r 4f8b66f4c1dc src/fileio.c
--- a/src/fileio.c Sun Mar 08 14:48:49 2015 +0100
+++ b/src/fileio.c Fri Mar 13 16:20:54 2015 +0900
@@ -9132,6 +9132,9 @@
#ifdef FEAT_INS_EXPAND
&& !ins_compl_active()
#endif
+#ifdef FEAT_XIM
+ && !im_is_preediting()
+#endif
)
{
state = get_real_state();
diff -r 03e6a768a028 -r 269048781420 src/edit.c
--- a/src/edit.c Sun Mar 08 14:48:49 2015 +0100
+++ b/src/edit.c Fri Mar 13 16:21:44 2015 +0900
@@ -9369,12 +9369,7 @@
tpos = curwin->w_cursor;
if (oneleft() == OK)
{
-#if defined(FEAT_XIM) && defined(FEAT_GUI_GTK)
- /* Only call start_arrow() when not busy with preediting, it will
- * break undo. K_LEFT is inserted in im_correct_cursor(). */
- if (!im_is_preediting())
-#endif
- start_arrow(&tpos);
+ start_arrow(&tpos);
#ifdef FEAT_RIGHTLEFT
/* If exit reversed string, position is fixed */
if (revins_scol != -1 && (int)curwin->w_cursor.col >= revins_scol)
diff -r 03e6a768a028 -r 269048781420 src/ex_getln.c
--- a/src/ex_getln.c Sun Mar 08 14:48:49 2015 +0100
+++ b/src/ex_getln.c Fri Mar 13 16:21:44 2015 +0900
@@ -94,9 +94,6 @@
static void save_cmdline __ARGS((struct cmdline_info *ccp));
static void restore_cmdline __ARGS((struct cmdline_info *ccp));
static int cmdline_paste __ARGS((int regname, int literally, int remcr));
-#if defined(FEAT_XIM) && defined(FEAT_GUI_GTK)
-static void redrawcmd_preedit __ARGS((void));
-#endif
#ifdef FEAT_WILDMENU
static void cmdline_del __ARGS((int from));
#endif
@@ -2484,106 +2481,6 @@
}
#endif
-#if (defined(FEAT_XIM) && (defined(FEAT_GUI_GTK))) || defined(PROTO)
-/*
- * Return the virtual column number at the current cursor position.
- * This is used by the IM code to obtain the start of the preedit string.
- */
- colnr_T
-cmdline_getvcol_cursor()
-{
- if (ccline.cmdbuff == NULL || ccline.cmdpos > ccline.cmdlen)
- return MAXCOL;
-
-# ifdef FEAT_MBYTE
- if (has_mbyte)
- {
- colnr_T col;
- int i = 0;
-
- for (col = 0; i < ccline.cmdpos; ++col)
- i += (*mb_ptr2len)(ccline.cmdbuff + i);
-
- return col;
- }
- else
-# endif
- return ccline.cmdpos;
-}
-#endif
-
-#if defined(FEAT_XIM) && defined(FEAT_GUI_GTK)
-/*
- * If part of the command line is an IM preedit string, redraw it with
- * IM feedback attributes. The cursor position is restored after drawing.
- */
- static void
-redrawcmd_preedit()
-{
- if ((State & CMDLINE)
- && xic != NULL
- /* && im_get_status() doesn't work when using SCIM */
- && !p_imdisable
- && im_is_preediting())
- {
- int cmdpos = 0;
- int cmdspos;
- int old_row;
- int old_col;
- colnr_T col;
-
- old_row = msg_row;
- old_col = msg_col;
- cmdspos = ((ccline.cmdfirstc != NUL) ? 1 : 0) + ccline.cmdindent;
-
-# ifdef FEAT_MBYTE
- if (has_mbyte)
- {
- for (col = 0; col < preedit_start_col
- && cmdpos < ccline.cmdlen; ++col)
- {
- cmdspos += (*mb_ptr2cells)(ccline.cmdbuff + cmdpos);
- cmdpos += (*mb_ptr2len)(ccline.cmdbuff + cmdpos);
- }
- }
- else
-# endif
- {
- cmdspos += preedit_start_col;
- cmdpos += preedit_start_col;
- }
-
- msg_row = cmdline_row + (cmdspos / (int)Columns);
- msg_col = cmdspos % (int)Columns;
- if (msg_row >= Rows)
- msg_row = Rows - 1;
-
- for (col = 0; cmdpos < ccline.cmdlen; ++col)
- {
- int char_len;
- int char_attr;
-
- char_attr = im_get_feedback_attr(col);
- if (char_attr < 0)
- break; /* end of preedit string */
-
-# ifdef FEAT_MBYTE
- if (has_mbyte)
- char_len = (*mb_ptr2len)(ccline.cmdbuff + cmdpos);
- else
-# endif
- char_len = 1;
-
- msg_outtrans_len_attr(ccline.cmdbuff + cmdpos, char_len, char_attr);
- cmdpos += char_len;
- }
-
- msg_row = old_row;
- msg_col = old_col;
- }
-}
-#endif /* FEAT_XIM && FEAT_GUI_GTK */
-
/*
* Allocate a new command line buffer.
* Assigns the new buffer to ccline.cmdbuff and ccline.cmdbufflen.
@@ -3318,9 +3215,6 @@
}
windgoto(msg_row, msg_col);
-#if defined(FEAT_XIM) && defined(FEAT_GUI_GTK)
- redrawcmd_preedit();
-#endif
#ifdef MCH_CURSOR_SHAPE
mch_update_cursor();
#endif
diff -r 03e6a768a028 -r 269048781420 src/globals.h
--- a/src/globals.h Sun Mar 08 14:48:49 2015 +0100
+++ b/src/globals.h Fri Mar 13 16:21:44 2015 +0900
@@ -872,19 +872,6 @@
#ifdef FEAT_XIM
# ifdef FEAT_GUI_GTK
EXTERN GtkIMContext *xic INIT(= NULL);
-/*
- * Start and end column of the preedit area in virtual columns from the start
- * of the text line. When there is no preedit area they are set to MAXCOL.
- * "preedit_end_col" is needed for coloring the preedited string. Drawing the
- * color between "preedit_start_col" and curpos did not work, because some XIM
- * set the cursor position to the first char of the string.
- */
-EXTERN colnr_T preedit_start_col INIT(= MAXCOL);
-EXTERN colnr_T preedit_end_col INIT(= MAXCOL);
-
-/* "xim_changed_while_preediting" is set when changed() can set the 'modified'
- * flag even while preediting. */
-EXTERN int xim_changed_while_preediting INIT(= FALSE);
# else
EXTERN XIC xic INIT(= NULL);
# endif
diff -r 03e6a768a028 -r 269048781420 src/mbyte.c
--- a/src/mbyte.c Sun Mar 08 14:48:49 2015 +0100
+++ b/src/mbyte.c Fri Mar 13 16:21:44 2015 +0900
@@ -4499,29 +4499,18 @@
# if defined(FEAT_GUI_GTK) || defined(PROTO)
static int xim_has_preediting INIT(= FALSE); /* IM current status */
-/*
- * Set preedit_start_col to the current cursor position.
- */
- static void
-init_preedit_start_col(void)
-{
- if (State & CMDLINE)
- preedit_start_col = cmdline_getvcol_cursor();
- else if (curwin != NULL)
- getvcol(curwin, &curwin->w_cursor, &preedit_start_col, NULL, NULL);
- /* Prevent that preediting marks the buffer as changed. */
- xim_changed_while_preediting = curbuf->b_changed;
-}
-
static int im_is_active = FALSE; /* IM is enabled for current mode */
static int preedit_is_active = FALSE;
-static int im_preedit_cursor = 0; /* cursor offset in characters */
-static int im_preedit_trailing = 0; /* number of characters after cursor */
static unsigned long im_commit_handler_id = 0;
static unsigned int im_activatekey_keyval = GDK_VoidSymbol;
static unsigned int im_activatekey_state = 0;
+static GtkWidget *preedit_window = NULL;
+static GtkWidget *preedit_label = NULL;
+
+static void im_preedit_window_set_position(void);
+
void
im_set_active(int active)
{
@@ -4559,6 +4548,8 @@
area.height = gui.char_height;
gtk_im_context_set_cursor_location(xic, &area);
+
+ im_preedit_window_set_position();
}
}
@@ -4589,42 +4580,95 @@
gui_mch_mousehide(TRUE);
}
+ static void
+im_preedit_window_set_position(void)
+{
+ int x, y, w, h, sw, sh;
+
+ if (preedit_window == NULL)
+ return;
+
+ sw = gdk_screen_get_width(gtk_widget_get_screen(preedit_window));
+ sh = gdk_screen_get_height(gtk_widget_get_screen(preedit_window));
+ gdk_window_get_origin(gui.drawarea->window, &x, &y);
+ gtk_window_get_size(GTK_WINDOW(preedit_window), &w, &h);
+ x = x + FILL_X(gui.col);
+ y = y + FILL_Y(gui.row);
+ if (x + w > sw)
+ x = sw - w;
+ if (y + h > sh)
+ y = sh - h;
+ gtk_window_move(GTK_WINDOW(preedit_window), x, y);
+}
+
+ static void
+im_preedit_window_open()
+{
+ char *preedit_string;
+ char buf[8];
+ PangoAttrList *attr_list;
+ PangoLayout *layout;
+ GdkColor color;
+ gint w, h;
+
+ if (preedit_window == NULL)
+ {
+ preedit_window = gtk_window_new(GTK_WINDOW_POPUP);
+ preedit_label = gtk_label_new("");
+ gtk_container_add(GTK_CONTAINER(preedit_window), preedit_label);
+ }
+
+ gtk_widget_modify_font(preedit_label, gui.norm_font);
+
+ vim_snprintf(buf, sizeof(buf), "#%06X", gui.norm_pixel);
+ gdk_color_parse(buf, &color);
+ gtk_widget_modify_fg(preedit_label, GTK_STATE_NORMAL, &color);
+
+ vim_snprintf(buf, sizeof(buf), "#%06X", gui.back_pixel);
+ gdk_color_parse(buf, &color);
+ gtk_widget_modify_bg(preedit_window, GTK_STATE_NORMAL, &color);
+
+ gtk_im_context_get_preedit_string(xic, &preedit_string, &attr_list, NULL);
+
+ if (preedit_string[0] != NUL)
+ {
+ gtk_label_set_text(GTK_LABEL(preedit_label), preedit_string);
+ gtk_label_set_attributes(GTK_LABEL(preedit_label), attr_list);
+
+ layout = gtk_label_get_layout(GTK_LABEL(preedit_label));
+ pango_layout_get_pixel_size(layout, &w, &h);
+ h = MAX(h, gui.char_height);
+ gtk_window_resize(GTK_WINDOW(preedit_window), w, h);
+
+ gtk_widget_show_all(preedit_window);
+
+ im_preedit_window_set_position();
+ }
+
+ g_free(preedit_string);
+ pango_attr_list_unref(attr_list);
+}
+
+ static void
+im_preedit_window_close()
+{
+ if (preedit_window != NULL)
+ gtk_widget_hide(preedit_window);
+}
+
+ static void
+im_show_preedit()
+{
+ im_preedit_window_open();
+
+ if (p_mh) /* blank out the pointer if necessary */
+ gui_mch_mousehide(TRUE);
+}
+
static void
im_delete_preedit(void)
{
- char_u bskey[] = {CSI, 'k', 'b'};
- char_u delkey[] = {CSI, 'k', 'D'};
-
- if (State & NORMAL)
- {
- im_preedit_cursor = 0;
- return;
- }
- for (; im_preedit_cursor > 0; --im_preedit_cursor)
- add_to_input_buf(bskey, (int)sizeof(bskey));
-
- for (; im_preedit_trailing > 0; --im_preedit_trailing)
- add_to_input_buf(delkey, (int)sizeof(delkey));
-}
-
-/*
- * Move the cursor left by "num_move_back" characters.
- * Note that ins_left() checks im_is_preediting() to avoid breaking undo for
- * these K_LEFT keys.
- */
- static void
-im_correct_cursor(int num_move_back)
-{
- char_u backkey[] = {CSI, 'k', 'l'};
-
- if (State & NORMAL)
- return;
-# ifdef FEAT_RIGHTLEFT
- if ((State & CMDLINE) == 0 && curwin != NULL && curwin->w_p_rl)
- backkey[2] = 'r';
-# endif
- for (; num_move_back > 0; --num_move_back)
- add_to_input_buf(backkey, (int)sizeof(backkey));
+ im_preedit_window_close();
}
static int xim_expected_char = NUL;
@@ -4637,6 +4681,8 @@
im_show_info(void)
{
int old_vgetc_busy;
+ int old_row = gui.row;
+ int old_col = gui.col;
old_vgetc_busy = vgetc_busy;
vgetc_busy = TRUE;
@@ -4645,6 +4691,8 @@
if ((State & NORMAL) || (State & INSERT))
setcursor();
out_flush();
+ gui.row = old_row;
+ gui.col = old_col;
}
/*
@@ -4658,49 +4706,11 @@
{
int slen = (int)STRLEN(str);
int add_to_input = TRUE;
- int clen;
- int len = slen;
- int commit_with_preedit = TRUE;
- char_u *im_str;
#ifdef XIM_DEBUG
xim_log("im_commit_cb(): %s\n", str);
#endif
- /* The imhangul module doesn't reset the preedit string before
- * committing. Call im_delete_preedit() to work around that. */
- im_delete_preedit();
-
- /* Indicate that preediting has finished. */
- if (preedit_start_col == MAXCOL)
- {
- init_preedit_start_col();
- commit_with_preedit = FALSE;
- }
-
- /* The thing which setting "preedit_start_col" to MAXCOL means that
- * "preedit_start_col" will be set forcedly when calling
- * preedit_changed_cb() next time.
- * "preedit_start_col" should not reset with MAXCOL on this part. Vim
- * is simulating the preediting by using add_to_input_str(). when
- * preedit begin immediately before committed, the typebuf is not
- * flushed to screen, then it can't get correct "preedit_start_col".
- * Thus, it should calculate the cells by adding cells of the committed
- * string. */
- if (input_conv.vc_type != CONV_NONE)
- {
- im_str = string_convert(&input_conv, (char_u *)str, &len);
- g_return_if_fail(im_str != NULL);
- }
- else
- im_str = (char_u *)str;
-
- clen = mb_string2cells(im_str, len);
-
- if (input_conv.vc_type != CONV_NONE)
- vim_free(im_str);
- preedit_start_col += clen;
-
/* Is this a single character that matches a keypad key that's just
* been pressed? If so, we don't want it to be entered as such - let
* us carry on processing the raw keycode so that it may be used in
@@ -4724,15 +4734,6 @@
if (add_to_input)
im_add_to_input((char_u *)str, slen);
- /* Inserting chars while "im_is_active" is set does not cause a change of
- * buffer. When the chars are committed the buffer must be marked as
- * changed. */
- if (!commit_with_preedit)
- preedit_start_col = MAXCOL;
-
- /* This flag is used in changed() at next call. */
- xim_changed_while_preediting = TRUE;
-
if (gtk_main_level() > 0)
gtk_main_quit();
}
@@ -4765,7 +4766,6 @@
im_delete_preedit();
/* Indicate that preediting has finished */
- preedit_start_col = MAXCOL;
xim_has_preediting = FALSE;
#if 0
@@ -4820,15 +4820,8 @@
im_preedit_changed_cb(GtkIMContext *context, gpointer data UNUSED)
{
char *preedit_string = NULL;
- int cursor_index = 0;
- int num_move_back = 0;
- char_u *str;
- char_u *p;
- int i;
-
- gtk_im_context_get_preedit_string(context,
- &preedit_string, NULL,
- &cursor_index);
+
+ gtk_im_context_get_preedit_string(context, &preedit_string, NULL, NULL);
#ifdef XIM_DEBUG
xim_log("im_preedit_changed_cb(): %s\n", preedit_string);
@@ -4836,66 +4829,15 @@
g_return_if_fail(preedit_string != NULL); /* just in case */
- /* If preedit_start_col is MAXCOL set it to the current cursor position. */
- if (preedit_start_col == MAXCOL && preedit_string[0] != '\0')
+ if (preedit_string[0] == NUL)
+ {
+ xim_has_preediting = FALSE;
+ im_delete_preedit();
+ }
+ else
{
xim_has_preediting = TRUE;
-
- /* Urgh, this breaks if the input buffer isn't empty now */
- init_preedit_start_col();
- }
- else if (cursor_index == 0 && preedit_string[0] == '\0')
- {
- xim_has_preediting = FALSE;
-
- /* If at the start position (after typing backspace)
- * preedit_start_col must be reset. */
- preedit_start_col = MAXCOL;
- }
-
- im_delete_preedit();
-
- /*
- * Compute the end of the preediting area: "preedit_end_col".
- * According to the documentation of gtk_im_context_get_preedit_string(),
- * the cursor_pos output argument returns the offset in bytes. This is
- * unfortunately not true -- real life shows the offset is in characters,
- * and the GTK+ source code agrees with me. Will file a bug later.
- */
- if (preedit_start_col != MAXCOL)
- preedit_end_col = preedit_start_col;
- str = (char_u *)preedit_string;
- for (p = str, i = 0; *p != NUL; p += utf_byte2len(*p), ++i)
- {
- int is_composing;
-
- is_composing = ((*p & 0x80) != 0 && utf_iscomposing(utf_ptr2char(p)));
- /*
- * These offsets are used as counters when generating <BS> and <Del>
- * to delete the preedit string. So don't count composing characters
- * unless 'delcombine' is enabled.
- */
- if (!is_composing || p_deco)
- {
- if (i < cursor_index)
- ++im_preedit_cursor;
- else
- ++im_preedit_trailing;
- }
- if (!is_composing && i >= cursor_index)
- {
- /* This is essentially the same as im_preedit_trailing, except
- * composing characters are not counted even if p_deco is set. */
- ++num_move_back;
- }
- if (preedit_start_col != MAXCOL)
- preedit_end_col += utf_ptr2cells(p);
- }
-
- if (p > str)
- {
- im_add_to_input(str, (int)(p - str));
- im_correct_cursor(num_move_back);
+ im_show_preedit();
}
g_free(preedit_string);
@@ -4904,98 +4846,6 @@
gtk_main_quit();
}
-/*
- * Translate the Pango attributes at iter to Vim highlighting attributes.
- * Ignore attributes not supported by Vim highlighting. This shouldn't have
- * too much impact -- right now we handle even more attributes than necessary
- * for the IM modules I tested with.
- */
- static int
-translate_pango_attributes(PangoAttrIterator *iter)
-{
- PangoAttribute *attr;
- int char_attr = HL_NORMAL;
-
- attr = pango_attr_iterator_get(iter, PANGO_ATTR_UNDERLINE);
- if (attr != NULL && ((PangoAttrInt *)attr)->value
- != (int)PANGO_UNDERLINE_NONE)
- char_attr |= HL_UNDERLINE;
-
- attr = pango_attr_iterator_get(iter, PANGO_ATTR_WEIGHT);
- if (attr != NULL && ((PangoAttrInt *)attr)->value >= (int)PANGO_WEIGHT_BOLD)
- char_attr |= HL_BOLD;
-
- attr = pango_attr_iterator_get(iter, PANGO_ATTR_STYLE);
- if (attr != NULL && ((PangoAttrInt *)attr)->value
- != (int)PANGO_STYLE_NORMAL)
- char_attr |= HL_ITALIC;
-
- attr = pango_attr_iterator_get(iter, PANGO_ATTR_BACKGROUND);
- if (attr != NULL)
- {
- const PangoColor *color = &((PangoAttrColor *)attr)->color;
-
- /* Assume inverse if black background is requested */
- if ((color->red | color->green | color->blue) == 0)
- char_attr |= HL_INVERSE;
- }
-
- return char_attr;
-}
-
-/*
- * Retrieve the highlighting attributes at column col in the preedit string.
- * Return -1 if not in preediting mode or if col is out of range.
- */
- int
-im_get_feedback_attr(int col)
-{
- char *preedit_string = NULL;
- PangoAttrList *attr_list = NULL;
- int char_attr = -1;
-
- if (xic == NULL)
- return char_attr;
-
- gtk_im_context_get_preedit_string(xic, &preedit_string, &attr_list, NULL);
-
- if (preedit_string != NULL && attr_list != NULL)
- {
- int idx;
-
- /* Get the byte index as used by PangoAttrIterator */
- for (idx = 0; col > 0 && preedit_string[idx] != '\0'; --col)
- idx += utfc_ptr2len((char_u *)preedit_string + idx);
-
- if (preedit_string[idx] != '\0')
- {
- PangoAttrIterator *iter;
- int start, end;
-
- char_attr = HL_NORMAL;
- iter = pango_attr_list_get_iterator(attr_list);
-
- /* Extract all relevant attributes from the list. */
- do
- {
- pango_attr_iterator_range(iter, &start, &end);
-
- if (idx >= start && idx < end)
- char_attr |= translate_pango_attributes(iter);
- }
- while (pango_attr_iterator_next(iter));
-
- pango_attr_iterator_destroy(iter);
- }
- }
-
- if (attr_list != NULL)
- pango_attr_list_unref(attr_list);
- g_free(preedit_string);
-
- return char_attr;
-}
-
void
xim_init(void)
{
@@ -5036,7 +4886,6 @@
}
im_is_active = FALSE;
im_commit_handler_id = 0;
- preedit_start_col = MAXCOL;
xim_has_preediting = FALSE;
}
@@ -5191,7 +5040,6 @@
}
}
- preedit_start_col = MAXCOL;
xim_has_preediting = FALSE;
}
@@ -5296,21 +5144,6 @@
{
int imresult = gtk_im_context_filter_keypress(xic, event);
- /* Some XIM send following sequence:
- * 1. preedited string.
- * 2. committed string.
- * 3. line changed key.
- * 4. preedited string.
- * 5. remove preedited string.
- * if 3, Vim can't move back the above line for 5.
- * thus, this part should not parse the key. */
- if (!imresult && preedit_start_col != MAXCOL
- && event->keyval == GDK_Return)
- {
- im_synthesize_keypress(GDK_Return, 0U);
- return FALSE;
- }
-
/* If XIM tried to commit a keypad key as a single char.,
* ignore it so we can use the keypad key 'raw', for mappings. */
if (xim_expected_char != NUL && xim_ignored_char)
diff -r 03e6a768a028 -r 269048781420 src/misc1.c
--- a/src/misc1.c Sun Mar 08 14:48:49 2015 +0100
+++ b/src/misc1.c Fri Mar 13 16:21:44 2015 +0900
@@ -2753,15 +2753,6 @@
void
changed()
{
-#if defined(FEAT_XIM) && defined(FEAT_GUI_GTK)
- /* The text of the preediting area is inserted, but this doesn't
- * mean a change of the buffer yet. That is delayed until the
- * text is committed. (this means preedit becomes empty) */
- if (im_is_preediting() && !xim_changed_while_preediting)
- return;
- xim_changed_while_preediting = FALSE;
-#endif
-
if (!curbuf->b_changed)
{
int save_msg_scroll = msg_scroll;
diff -r 03e6a768a028 -r 269048781420 src/proto/ex_getln.pro
--- a/src/proto/ex_getln.pro Sun Mar 08 14:48:49 2015 +0100
+++ b/src/proto/ex_getln.pro Fri Mar 13 16:21:44 2015 +0900
@@ -9,7 +9,6 @@
char_u *getexmodeline __ARGS((int promptc, void *cookie, int indent));
int cmdline_overstrike __ARGS((void));
int cmdline_at_end __ARGS((void));
-colnr_T cmdline_getvcol_cursor __ARGS((void));
void free_cmdline_buf __ARGS((void));
void putcmdline __ARGS((int c, int shift));
void unputcmdline __ARGS((void));
diff -r 03e6a768a028 -r 269048781420 src/proto/mbyte.pro
--- a/src/proto/mbyte.pro Sun Mar 08 14:48:49 2015 +0100
+++ b/src/proto/mbyte.pro Fri Mar 13 16:21:44 2015 +0900
@@ -76,7 +76,6 @@
void xim_set_focus __ARGS((int focus));
void im_set_position __ARGS((int row, int col));
void xim_set_preedit __ARGS((void));
-int im_get_feedback_attr __ARGS((int col));
void xim_init __ARGS((void));
void im_shutdown __ARGS((void));
int im_xim_isvalid_imactivate __ARGS((void));
diff -r 03e6a768a028 -r 269048781420 src/screen.c
--- a/src/screen.c Sun Mar 08 14:48:49 2015 +0100
+++ b/src/screen.c Fri Mar 13 16:21:44 2015 +0900
@@ -3010,10 +3010,6 @@
#endif
#define WL_LINE WL_SBR + 1 /* text in the line */
int draw_state = WL_START; /* what to draw next */
-#if defined(FEAT_XIM) && defined(FEAT_GUI_GTK)
- int feedback_col = 0;
- int feedback_old_attr = -1;
-#endif
#ifdef FEAT_CONCEAL
int syntax_flags = 0;
@@ -4923,43 +4919,6 @@
&& !attr_pri)
char_attr = extra_attr;
-#if defined(FEAT_XIM) && defined(FEAT_GUI_GTK)
- /* XIM don't send preedit_start and preedit_end, but they send
- * preedit_changed and commit. Thus Vim can't set "im_is_active", use
- * im_is_preediting() here. */
- if (xic != NULL
- && lnum == wp->w_cursor.lnum
- && (State & INSERT)
- && !p_imdisable
- && im_is_preediting()
- && draw_state == WL_LINE)
- {
- colnr_T tcol;
-
- if (preedit_end_col == MAXCOL)
- getvcol(curwin, &(wp->w_cursor), &tcol, NULL, NULL);
- else
- tcol = preedit_end_col;
- if ((long)preedit_start_col <= vcol && vcol < (long)tcol)
- {
- if (feedback_old_attr < 0)
- {
- feedback_col = 0;
- feedback_old_attr = char_attr;
- }
- char_attr = im_get_feedback_attr(feedback_col);
- if (char_attr < 0)
- char_attr = feedback_old_attr;
- feedback_col++;
- }
- else if (feedback_old_attr >= 0)
- {
- char_attr = feedback_old_attr;
- feedback_old_attr = -1;
- feedback_col = 0;
- }
- }
-#endif
/*
* Handle the case where we are in column 0 but not on the first
* character of the line and the user wants us to show us a
diff -r 03e6a768a028 -r 269048781420 src/undo.c
--- a/src/undo.c Sun Mar 08 14:48:49 2015 +0100
+++ b/src/undo.c Fri Mar 13 16:21:44 2015 +0900
@@ -3022,10 +3022,6 @@
/* Skip it when already synced or syncing is disabled. */
if (curbuf->b_u_synced || (!force && no_u_sync > 0))
return;
-#if defined(FEAT_XIM) && defined(FEAT_GUI_GTK)
- if (im_is_preediting())
- return; /* XIM is busy, don't break an undo sequence */
-#endif
if (get_undolevel() < 0)
curbuf->b_u_synced = TRUE; /* no entries, nothing to do */
else
diff -r 03e6a768a028 -r 2ab7cf549c7b src/gui.c
--- a/src/gui.c Sun Mar 08 14:48:49 2015 +0100
+++ b/src/gui.c Fri Mar 13 17:34:37 2015 +0900
@@ -764,10 +764,6 @@
gui_mch_disable_beval_area(balloonEval);
#endif
-#if defined(FEAT_XIM) && defined(FEAT_GUI_GTK)
- if (!im_xim_isvalid_imactivate())
- EMSG(_("E599: Value of 'imactivatekey' is invalid"));
-#endif
/* When 'cmdheight' was set during startup it may not have taken
* effect yet. */
if (p_ch != 1L)
@@ -1124,13 +1120,7 @@
static int iid;
guicolor_T fg, bg;
- if (
-# if defined(FEAT_GUI_GTK) && !defined(FEAT_HANGULIN)
- preedit_get_status()
-# else
- im_get_status()
-# endif
- )
+ if (im_get_status())
{
iid = syn_name2id((char_u *)"CursorIM");
if (iid > 0)
diff -r 03e6a768a028 -r 2ab7cf549c7b src/mbyte.c
--- a/src/mbyte.c Sun Mar 08 14:48:49 2015 +0100
+++ b/src/mbyte.c Fri Mar 13 17:34:37 2015 +0900
@@ -4514,13 +4514,10 @@
}
static int im_is_active = FALSE; /* IM is enabled for current mode */
-static int preedit_is_active = FALSE;
static int im_preedit_cursor = 0; /* cursor offset in characters */
static int im_preedit_trailing = 0; /* number of characters after cursor */
static unsigned long im_commit_handler_id = 0;
-static unsigned int im_activatekey_keyval = GDK_VoidSymbol;
-static unsigned int im_activatekey_state = 0;
void
im_set_active(int active)
@@ -4642,8 +4639,7 @@
vgetc_busy = TRUE;
showmode();
vgetc_busy = old_vgetc_busy;
- if ((State & NORMAL) || (State & INSERT))
- setcursor();
+ setcursor();
out_flush();
}
@@ -4746,11 +4742,6 @@
#ifdef XIM_DEBUG
xim_log("im_preedit_start_cb()\n");
#endif
-
- im_is_active = TRUE;
- preedit_is_active = TRUE;
- gui_update_cursor(TRUE, FALSE);
- im_show_info();
}
/*
@@ -4767,16 +4758,6 @@
/* Indicate that preediting has finished */
preedit_start_col = MAXCOL;
xim_has_preediting = FALSE;
-
-#if 0
- /* Removal of this line suggested by Takuhiro Nishioka. Fixes that IM was
- * switched off unintentionally. We now use preedit_is_active (added by
- * SungHyun Nam). */
- im_is_active = FALSE;
-#endif
- preedit_is_active = FALSE;
- gui_update_cursor(TRUE, FALSE);
- im_show_info();
}
/*
@@ -5040,112 +5021,6 @@
xim_has_preediting = FALSE;
}
-/*
- * Convert the string argument to keyval and state for GdkEventKey.
- * If str is valid return TRUE, otherwise FALSE.
- *
- * See 'imactivatekey' for documentation of the format.
- */
- static int
-im_string_to_keyval(const char *str, unsigned int *keyval, unsigned int *state)
-{
- const char *mods_end;
- unsigned tmp_keyval;
- unsigned tmp_state = 0;
-
- mods_end = strrchr(str, '-');
- mods_end = (mods_end != NULL) ? mods_end + 1 : str;
-
- /* Parse modifier keys */
- while (str < mods_end)
- switch (*str++)
- {
- case '-': break;
- case 'S': case 's': tmp_state |= (unsigned)GDK_SHIFT_MASK; break;
- case 'L': case 'l': tmp_state |= (unsigned)GDK_LOCK_MASK; break;
- case 'C': case 'c': tmp_state |= (unsigned)GDK_CONTROL_MASK;break;
- case '1': tmp_state |= (unsigned)GDK_MOD1_MASK; break;
- case '2': tmp_state |= (unsigned)GDK_MOD2_MASK; break;
- case '3': tmp_state |= (unsigned)GDK_MOD3_MASK; break;
- case '4': tmp_state |= (unsigned)GDK_MOD4_MASK; break;
- case '5': tmp_state |= (unsigned)GDK_MOD5_MASK; break;
- default:
- return FALSE;
- }
-
- tmp_keyval = gdk_keyval_from_name(str);
-
- if (tmp_keyval == 0 || tmp_keyval == GDK_VoidSymbol)
- return FALSE;
-
- if (keyval != NULL)
- *keyval = tmp_keyval;
- if (state != NULL)
- *state = tmp_state;
-
- return TRUE;
-}
-
-/*
- * Return TRUE if p_imak is valid, otherwise FALSE. As a special case, an
- * empty string is also regarded as valid.
- *
- * Note: The numerical key value of p_imak is cached if it was valid; thus
- * boldly assuming im_xim_isvalid_imactivate() will always be called whenever
- * 'imak' changes. This is currently the case but not obvious -- should
- * probably rename the function for clarity.
- */
- int
-im_xim_isvalid_imactivate(void)
-{
- if (p_imak[0] == NUL)
- {
- im_activatekey_keyval = GDK_VoidSymbol;
- im_activatekey_state = 0;
- return TRUE;
- }
-
- return im_string_to_keyval((const char *)p_imak,
- &im_activatekey_keyval,
- &im_activatekey_state);
-}
-
- static void
-im_synthesize_keypress(unsigned int keyval, unsigned int state)
-{
- GdkEventKey *event;
-
-# ifdef HAVE_GTK_MULTIHEAD
- event = (GdkEventKey *)gdk_event_new(GDK_KEY_PRESS);
- g_object_ref(gui.drawarea->window); /* unreffed by gdk_event_free() */
-# else
- event = (GdkEventKey *)g_malloc0((gulong)sizeof(GdkEvent));
- event->type = GDK_KEY_PRESS;
-# endif
- event->window = gui.drawarea->window;
- event->send_event = TRUE;
- event->time = GDK_CURRENT_TIME;
- event->state = state;
- event->keyval = keyval;
- event->hardware_keycode = /* needed for XIM */
- XKeysymToKeycode(GDK_WINDOW_XDISPLAY(event->window), (KeySym)keyval);
- event->length = 0;
- event->string = NULL;
-
- gtk_im_context_filter_keypress(xic, event);
-
- /* For consistency, also send the corresponding release event. */
- event->type = GDK_KEY_RELEASE;
- event->send_event = FALSE;
- gtk_im_context_filter_keypress(xic, event);
-
-# ifdef HAVE_GTK_MULTIHEAD
- gdk_event_free((GdkEvent *)event);
-# else
- g_free(event);
-# endif
-}
-
void
xim_reset(void)
{
@@ -5240,90 +5115,21 @@
* gtk_im_context_filter_keypress() in Normal mode.
* And while doing :sh too.
*/
- if (xic != NULL && !p_imdisable
- && (State & (INSERT | CMDLINE | NORMAL | EXTERNCMD)) != 0)
+ if (xic != NULL && !p_imdisable)
{
- /*
- * Filter 'imactivatekey' and map it to CTRL-^. This way, Vim is
- * always aware of the current status of IM, and can even emulate
- * the activation key for modules that don't support one.
- */
- if (event->keyval == im_activatekey_keyval
- && (event->state & im_activatekey_state) == im_activatekey_state)
- {
- unsigned int state_mask;
-
- /* Require the state of the 3 most used modifiers to match exactly.
- * Otherwise e.g. <S-C-space> would be unusable for other purposes
- * if the IM activate key is <S-space>. */
- state_mask = im_activatekey_state;
- state_mask |= ((int)GDK_SHIFT_MASK | (int)GDK_CONTROL_MASK
- | (int)GDK_MOD1_MASK);
-
- if ((event->state & state_mask) != im_activatekey_state)
- return FALSE;
-
- /* Don't send it a second time on GDK_KEY_RELEASE. */
- if (event->type != GDK_KEY_PRESS)
- return TRUE;
-
- if (map_to_exists_mode((char_u *)"", LANGMAP, FALSE))
- {
- im_set_active(FALSE);
-
- /* ":lmap" mappings exists, toggle use of mappings. */
- State ^= LANGMAP;
- if (State & LANGMAP)
- {
- curbuf->b_p_iminsert = B_IMODE_NONE;
- State &= ~LANGMAP;
- }
- else
- {
- curbuf->b_p_iminsert = B_IMODE_LMAP;
- State |= LANGMAP;
- }
- return TRUE;
- }
-
- return gtk_im_context_filter_keypress(xic, event);
- }
-
- /* Don't filter events through the IM context if IM isn't active
- * right now. Unlike with GTK+ 1.2 we cannot rely on the IM module
- * not doing anything before the activation key was sent. */
- if (im_activatekey_keyval == GDK_VoidSymbol || im_is_active)
- {
- int imresult = gtk_im_context_filter_keypress(xic, event);
-
- /* Some XIM send following sequence:
- * 1. preedited string.
- * 2. committed string.
- * 3. line changed key.
- * 4. preedited string.
- * 5. remove preedited string.
- * if 3, Vim can't move back the above line for 5.
- * thus, this part should not parse the key. */
- if (!imresult && preedit_start_col != MAXCOL
- && event->keyval == GDK_Return)
- {
- im_synthesize_keypress(GDK_Return, 0U);
- return FALSE;
- }
-
- /* If XIM tried to commit a keypad key as a single char.,
- * ignore it so we can use the keypad key 'raw', for mappings. */
- if (xim_expected_char != NUL && xim_ignored_char)
- /* We had a keypad key, and XIM tried to thieve it */
- return FALSE;
-
- /* This is supposed to fix a problem with iBus, that space
- * characters don't work in input mode. */
- xim_expected_char = NUL;
-
- /* Normal processing */
- return imresult;
- }
+ int imresult = gtk_im_context_filter_keypress(xic, event);
+
+ /* If XIM tried to commit a keypad key as a single char.,
+ * ignore it so we can use the keypad key 'raw', for mappings. */
+ if (xim_expected_char != NUL && xim_ignored_char)
+ /* We had a keypad key, and XIM tried to thieve it */
+ return FALSE;
+
+ /* This is supposed to fix a problem with iBus, that space
+ * characters don't work in input mode. */
+ xim_expected_char = NUL;
+
+ return imresult;
}
return FALSE;
@@ -5356,12 +5162,6 @@
}
int
-preedit_get_status(void)
-{
- return preedit_is_active;
-}
-
- int
im_is_preediting()
{
return xim_has_preediting;
diff -r 03e6a768a028 -r 2ab7cf549c7b src/option.c
--- a/src/option.c Sun Mar 08 14:48:49 2015 +0100
+++ b/src/option.c Fri Mar 13 17:34:37 2015 +0900
@@ -6067,14 +6067,6 @@
}
#endif
-#if defined(FEAT_XIM) && defined(FEAT_GUI_GTK)
- else if (varp == &p_imak)
- {
- if (gui.in_use && !im_xim_isvalid_imactivate())
- errmsg = e_invarg;
- }
-#endif
-
#ifdef FEAT_KEYMAP
else if (varp == &curbuf->b_p_keymap)
{
diff -r 03e6a768a028 -r 2ab7cf549c7b src/option.h
--- a/src/option.h Sun Mar 08 14:48:49 2015 +0100
+++ b/src/option.h Fri Mar 13 17:34:37 2015 +0900
@@ -558,7 +558,6 @@
#endif
EXTERN int p_ic; /* 'ignorecase' */
#if defined(FEAT_XIM) && defined(FEAT_GUI_GTK)
-EXTERN char_u *p_imak; /* 'imactivatekey' */
EXTERN char_u *p_imaf; /* 'imactivatefunc' */
EXTERN char_u *p_imsf; /* 'imstatusfunc' */
#endif
diff -r 03e6a768a028 -r 2ab7cf549c7b src/proto/mbyte.pro
--- a/src/proto/mbyte.pro Sun Mar 08 14:48:49 2015 +0100
+++ b/src/proto/mbyte.pro Fri Mar 13 17:34:37 2015 +0900
@@ -79,11 +79,9 @@
int im_get_feedback_attr __ARGS((int col));
void xim_init __ARGS((void));
void im_shutdown __ARGS((void));
-int im_xim_isvalid_imactivate __ARGS((void));
void xim_reset __ARGS((void));
int xim_queue_key_press_event __ARGS((GdkEventKey *event, int down));
int im_get_status __ARGS((void));
-int preedit_get_status __ARGS((void));
int im_is_preediting __ARGS((void));
void xim_set_status_area __ARGS((void));
int xim_get_status_area_height __ARGS((void));
diff -r 03e6a768a028 -r 2ab7cf549c7b src/screen.c
--- a/src/screen.c Sun Mar 08 14:48:49 2015 +0100
+++ b/src/screen.c Fri Mar 13 17:34:37 2015 +0900
@@ -9971,13 +9971,7 @@
{
MSG_PUTS_ATTR("--", attr);
#if defined(FEAT_XIM)
- if (
-# ifdef FEAT_GUI_GTK
- preedit_get_status()
-# else
- im_get_status()
-# endif
- )
+ if (im_get_status())
# ifdef FEAT_GUI_GTK /* most of the time, it's not XIM being used */
MSG_PUTS_ATTR(" IM", attr);
# else
diff -r 03e6a768a028 -r 87ae595f97e3 src/gui_gtk_x11.c
--- a/src/gui_gtk_x11.c Sun Mar 08 14:48:49 2015 +0100
+++ b/src/gui_gtk_x11.c Fri Mar 13 16:22:33 2015 +0900
@@ -4159,21 +4159,31 @@
int
gui_mch_adjust_charheight(void)
{
- PangoFontMetrics *metrics;
+ PangoLayout *layout;
int ascent;
- int descent;
-
- metrics = pango_context_get_metrics(gui.text_context, gui.norm_font,
- pango_context_get_language(gui.text_context));
- ascent = pango_font_metrics_get_ascent(metrics);
- descent = pango_font_metrics_get_descent(metrics);
-
- pango_font_metrics_unref(metrics);
-
- gui.char_height = (ascent + descent + PANGO_SCALE - 1) / PANGO_SCALE
- + p_linespace;
+ int height;
+ int linespace;
+ garray_T ga;
+
+ ga_init2(&ga, (int)sizeof(char_u), 100);
+ ga_concat(&ga, (char_u *)pango_language_get_sample_string(NULL));
+ ga_concat(&ga, (char_u *)pango_language_get_sample_string(
+ pango_language_from_string("c")));
+ ga_append(&ga, NUL);
+
+ layout = pango_layout_new(gui.text_context);
+ pango_layout_set_markup(layout, (char *)ga.ga_data, -1);
+ pango_layout_get_size(layout, NULL, &height);
+ ascent = pango_layout_get_baseline(layout);
+
+ g_object_unref(layout);
+ ga_clear(&ga);
+
+ linespace = p_linespace * PANGO_SCALE;
+
+ gui.char_height = PANGO_PIXELS_CEIL(height + linespace);
/* LINTED: avoid warning: bitwise operation on signed value */
- gui.char_ascent = PANGO_PIXELS(ascent + p_linespace * PANGO_SCALE / 2);
+ gui.char_ascent = PANGO_PIXELS(ascent + linespace / 2);
/* A not-positive value of char_height may crash Vim. Only happens
* if 'linespace' is negative (which does make sense sometimes). */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment