@@ -4455,6 +4455,9 @@ static int xim_has_preediting INIT(= FALSE); /* IM current status */
44554455
44564456static int im_is_active = FALSE; /* IM is enabled for current mode */
44574457static int preedit_is_active = FALSE;
4458+ static int im_preedit_start = 0 ; /* start offset in characters */
4459+ static int im_preedit_cursor = 0 ; /* cursor offset in characters */
4460+ static int im_preedit_trailing = 0 ; /* number of characters after cursor */
44584461
44594462static unsigned long im_commit_handler_id = 0 ;
44604463# ifndef FEAT_GUI_MACVIM
@@ -4533,6 +4536,7 @@ im_set_position(int row, int col)
45334536 im_preedit_window_set_position ();
45344537 }
45354538}
4539+ # endif
45364540
45374541# if 0 || defined(PROTO ) /* apparently only used in gui_x11.c */
45384542 void
@@ -4557,10 +4561,51 @@ im_add_to_input(char_u *str, int len)
45574561 if (input_conv .vc_type != CONV_NONE )
45584562 vim_free (str );
45594563
4564+ # ifndef FEAT_GUI_MACVIM
45604565 if (p_mh ) /* blank out the pointer if necessary */
45614566 gui_mch_mousehide (TRUE);
4567+ # endif
4568+ }
4569+
4570+ static void
4571+ im_delete_preedit (void )
4572+ {
4573+ char_u bskey [] = {CSI , 'k' , 'b' };
4574+ char_u delkey [] = {CSI , 'k' , 'D' };
4575+
4576+ if (State & NORMAL )
4577+ {
4578+ im_preedit_cursor = 0 ;
4579+ return ;
4580+ }
4581+ for (; im_preedit_cursor > 0 ; -- im_preedit_cursor )
4582+ add_to_input_buf (bskey , (int )sizeof (bskey ));
4583+
4584+ for (; im_preedit_trailing > 0 ; -- im_preedit_trailing )
4585+ add_to_input_buf (delkey , (int )sizeof (delkey ));
4586+ }
4587+
4588+ /*
4589+ * Move the cursor left by "num_move_back" characters.
4590+ * Note that ins_left() checks im_is_preediting() to avoid breaking undo for
4591+ * these K_LEFT keys.
4592+ */
4593+ static void
4594+ im_correct_cursor (int num_move_back )
4595+ {
4596+ char_u backkey [] = {CSI , 'k' , 'l' };
4597+
4598+ if (State & NORMAL )
4599+ return ;
4600+ # ifdef FEAT_RIGHTLEFT
4601+ if ((State & CMDLINE ) == 0 && curwin != NULL && curwin -> w_p_rl )
4602+ backkey [2 ] = 'r' ;
4603+ # endif
4604+ for (; num_move_back > 0 ; -- num_move_back )
4605+ add_to_input_buf (backkey , (int )sizeof (backkey ));
45624606}
45634607
4608+ # ifndef FEAT_GUI_MACVIM
45644609 static void
45654610im_preedit_window_set_position (void )
45664611{
@@ -4581,12 +4626,10 @@ im_preedit_window_set_position(void)
45814626 y = sh - h ;
45824627 gtk_window_move (GTK_WINDOW (preedit_window ), x , y );
45834628}
4584- # endif
45854629
45864630 static void
45874631im_preedit_window_open ()
45884632{
4589- # ifndef FEAT_GUI_MACVIM
45904633 char * preedit_string ;
45914634 char buf [8 ];
45924635 PangoAttrList * attr_list ;
@@ -4630,36 +4673,24 @@ im_preedit_window_open()
46304673
46314674 g_free (preedit_string );
46324675 pango_attr_list_unref (attr_list );
4633- # endif
46344676}
46354677
46364678 static void
46374679im_preedit_window_close ()
46384680{
4639- # ifndef FEAT_GUI_MACVIM
46404681 if (preedit_window != NULL )
46414682 gtk_widget_hide (preedit_window );
4642- # endif
46434683}
46444684
46454685 static void
46464686im_show_preedit ()
46474687{
46484688 im_preedit_window_open ();
46494689
4650- # ifndef FEAT_GUI_MACVIM
46514690 if (p_mh ) /* blank out the pointer if necessary */
46524691 gui_mch_mousehide (TRUE);
4653- # endif
46544692}
46554693
4656- static void
4657- im_delete_preedit (void )
4658- {
4659- im_preedit_window_close ();
4660- }
4661-
4662- # ifndef FEAT_GUI_MACVIM
46634694static int xim_expected_char = NUL ;
46644695static int xim_ignored_char = FALSE;
46654696# endif
@@ -4786,6 +4817,9 @@ im_preedit_end_macvim()
47864817im_preedit_abandon_macvim ()
47874818{
47884819 /* Abandon preedit text, don't send any backspace sequences. */
4820+ im_preedit_cursor = 0 ;
4821+ im_preedit_trailing = 0 ;
4822+
47894823 im_preedit_end_macvim ();
47904824}
47914825#endif
@@ -4837,25 +4871,57 @@ im_preedit_changed_macvim(char *preedit_string, int start_index, int cursor_inde
48374871{
48384872# ifndef FEAT_GUI_MACVIM
48394873 char * preedit_string = NULL ;
4874+ int cursor_index = 0 ;
4875+ # endif
4876+ int num_move_back = 0 ;
4877+ char_u * str ;
4878+ char_u * p ;
4879+ int i ;
48404880
4841- gtk_im_context_get_preedit_string (context , & preedit_string , NULL , NULL );
4842- #endif
4881+ # ifndef FEAT_GUI_MACVIM
4882+ gtk_im_context_get_preedit_string (context ,
4883+ & preedit_string , NULL ,
4884+ & cursor_index );
4885+ # endif
48434886
48444887#ifdef XIM_DEBUG
48454888 xim_log ("im_preedit_changed_cb(): %s\n" , preedit_string );
48464889#endif
48474890
48484891 g_return_if_fail (preedit_string != NULL ); /* just in case */
48494892
4850- if (preedit_string [0 ] == NUL )
4893+ im_delete_preedit ();
4894+
4895+ str = (char_u * )preedit_string ;
4896+ for (p = str , i = 0 ; * p != NUL ; p += utf_byte2len (* p ), ++ i )
48514897 {
4852- xim_has_preediting = FALSE;
4853- im_delete_preedit ();
4898+ int is_composing ;
4899+
4900+ is_composing = ((* p & 0x80 ) != 0 && utf_iscomposing (utf_ptr2char (p )));
4901+ /*
4902+ * These offsets are used as counters when generating <BS> and <Del>
4903+ * to delete the preedit string. So don't count composing characters
4904+ * unless 'delcombine' is enabled.
4905+ */
4906+ if (!is_composing || p_deco )
4907+ {
4908+ if (i < cursor_index )
4909+ ++ im_preedit_cursor ;
4910+ else
4911+ ++ im_preedit_trailing ;
4912+ }
4913+ if (!is_composing && i >= cursor_index )
4914+ {
4915+ /* This is essentially the same as im_preedit_trailing, except
4916+ * composing characters are not counted even if p_deco is set. */
4917+ ++ num_move_back ;
4918+ }
48544919 }
4855- else
4920+
4921+ if (p > str )
48564922 {
4857- xim_has_preediting = TRUE ;
4858- im_show_preedit ( );
4923+ im_add_to_input ( str , ( int )( p - str )) ;
4924+ im_correct_cursor ( num_move_back );
48594925 }
48604926
48614927# ifndef FEAT_GUI_MACVIM
@@ -4866,6 +4932,21 @@ im_preedit_changed_macvim(char *preedit_string, int start_index, int cursor_inde
48664932# endif
48674933}
48684934
4935+ # ifdef FEAT_GUI_MACVIM
4936+ /*
4937+ * Retrieve the highlighting attributes at column col in the preedit string.
4938+ * Return -1 if not in preediting mode or if col is out of range.
4939+ */
4940+ int
4941+ im_get_feedback_attr (int col )
4942+ {
4943+ if (col >= im_preedit_start && col < im_preedit_cursor )
4944+ return HL_THICKUNDERLINE ;
4945+ else
4946+ return HL_UNDERLINE ;
4947+ }
4948+ # endif
4949+
48694950 void
48704951xim_init (void )
48714952{
@@ -5192,10 +5273,10 @@ xim_queue_key_press_event(GdkEventKey *event, int down)
51925273}
51935274# endif
51945275
5195- # ifndef FEAT_GUI_MACVIM
51965276 int
51975277im_get_status (void )
51985278{
5279+ # ifndef FEAT_GUI_MACVIM
51995280# ifdef FEAT_EVAL
52005281 if (p_imsf [0 ] != NUL )
52015282 {
@@ -5217,17 +5298,13 @@ im_get_status(void)
52175298 }
52185299# endif
52195300 return im_is_active ;
5220- }
52215301# else /* FEAT_GUI_MACVIM */
5222- int
5223- im_get_status (void )
5224- {
52255302 if (gui .in_use )
52265303 return gui_im_get_status ();
52275304 else
5228- return im_is_active ;
5229- }
5305+ return im_is_active ;
52305306# endif
5307+ }
52315308
52325309 int
52335310preedit_get_status (void )
0 commit comments