Patch 9.0.1158

4 views
Skip to first unread message

Bram Moolenaar

unread,
Jan 8, 2023, 8:45:10 AM1/8/23
to vim...@googlegroups.com

Patch 9.0.1158
Problem: Code is indented more than necessary.
Solution: Use an early return where it makes sense. (Yegappan Lakshmanan,
closes #11787)
Files: src/findfile.c, src/fold.c, src/getchar.c, src/gui.c,
src/gui_beval.c, src/gui_gtk.c, src/gui_gtk_f.c,
src/gui_gtk_x11.c, src/gui_motif.c, src/gui_photon.c,
src/gui_w32.c, src/gui_x11.c, src/gui_xim.c


*** ../vim-9.0.1157/src/findfile.c 2022-10-01 19:43:48.606494048 +0100
--- src/findfile.c 2023-01-08 13:38:57.101602496 +0000
***************
*** 1426,1436 ****
{
// check for NULL pointer, not to return an error to the user, but
// to prevent a crash
! if (stack_ptr != NULL)
! {
! stack_ptr->ffs_prev = search_ctx->ffsc_stack_ptr;
! search_ctx->ffsc_stack_ptr = stack_ptr;
! }
}

/*
--- 1426,1436 ----
{
// check for NULL pointer, not to return an error to the user, but
// to prevent a crash
! if (stack_ptr == NULL)
! return;
!
! stack_ptr->ffs_prev = search_ctx->ffsc_stack_ptr;
! search_ctx->ffsc_stack_ptr = stack_ptr;
}

/*
*** ../vim-9.0.1157/src/fold.c 2023-01-02 16:54:48.932860868 +0000
--- src/fold.c 2023-01-08 13:38:57.101602496 +0000
***************
*** 513,525 ****
void
foldCheckClose(void)
{
! if (*p_fcl != NUL) // can only be "all" right now
! {
! checkupdate(curwin);
! if (checkCloseRec(&curwin->w_folds, curwin->w_cursor.lnum,
! (int)curwin->w_p_fdl))
! changed_window_setting();
! }
}

// checkCloseRec() {{{2
--- 513,526 ----
void
foldCheckClose(void)
{
! if (*p_fcl == NUL)
! return;
!
! // can only be "all" right now
! checkupdate(curwin);
! if (checkCloseRec(&curwin->w_folds, curwin->w_cursor.lnum,
! (int)curwin->w_p_fdl))
! changed_window_setting();
}

// checkCloseRec() {{{2
***************
*** 1077,1092 ****
}
if (hasFolding(start->lnum, &start->lnum, NULL))
start->col = 0;
! if (hasFolding(end->lnum, NULL, &end->lnum))
! {
! ptr = ml_get(end->lnum);
! end->col = (colnr_T)STRLEN(ptr);
! if (end->col > 0 && *p_sel == 'o')
! --end->col;
! // prevent cursor from moving on the trail byte
! if (has_mbyte)
! mb_adjust_cursor();
! }
}

// cursor_foldstart() {{{2
--- 1078,1094 ----
}
if (hasFolding(start->lnum, &start->lnum, NULL))
start->col = 0;
!
! if (!hasFolding(end->lnum, NULL, &end->lnum))
! return;
!
! ptr = ml_get(end->lnum);
! end->col = (colnr_T)STRLEN(ptr);
! if (end->col > 0 && *p_sel == 'o')
! --end->col;
! // prevent cursor from moving on the trail byte
! if (has_mbyte)
! mb_adjust_cursor();
}

// cursor_foldstart() {{{2
***************
*** 1215,1225 ****
static void
checkupdate(win_T *wp)
{
! if (wp->w_foldinvalid)
! {
! foldUpdate(wp, (linenr_T)1, (linenr_T)MAXLNUM); // will update all
! wp->w_foldinvalid = FALSE;
! }
}

// setFoldRepeat() {{{2
--- 1217,1227 ----
static void
checkupdate(win_T *wp)
{
! if (!wp->w_foldinvalid)
! return;
!
! foldUpdate(wp, (linenr_T)1, (linenr_T)MAXLNUM); // will update all
! wp->w_foldinvalid = FALSE;
}

// setFoldRepeat() {{{2
*** ../vim-9.0.1157/src/getchar.c 2022-11-29 20:33:16.592850638 +0000
--- src/getchar.c 2023-01-08 13:38:57.101602496 +0000
***************
*** 259,269 ****
if (buf->bh_curr == NULL)
return; // nothing to delete
len = (int)STRLEN(buf->bh_curr->b_str);
! if (len >= slen)
! {
! buf->bh_curr->b_str[len - slen] = NUL;
! buf->bh_space += slen;
! }
}

/*
--- 259,269 ----
if (buf->bh_curr == NULL)
return; // nothing to delete
len = (int)STRLEN(buf->bh_curr->b_str);
! if (len < slen)
! return;
!
! buf->bh_curr->b_str[len - slen] = NUL;
! buf->bh_space += slen;
}

/*
***************
*** 478,489 ****
void
ResetRedobuff(void)
{
! if (!block_redo)
! {
! free_buff(&old_redobuff);
! old_redobuff = redobuff;
! redobuff.bh_first.b_next = NULL;
! }
}

/*
--- 478,489 ----
void
ResetRedobuff(void)
{
! if (block_redo)
! return;
!
! free_buff(&old_redobuff);
! old_redobuff = redobuff;
! redobuff.bh_first.b_next = NULL;
}

/*
***************
*** 493,507 ****
void
CancelRedo(void)
{
! if (!block_redo)
! {
! free_buff(&redobuff);
! redobuff = old_redobuff;
! old_redobuff.bh_first.b_next = NULL;
! start_stuff();
! while (read_readbuffers(TRUE) != NUL)
! ;
! }
}

/*
--- 493,507 ----
void
CancelRedo(void)
{
! if (block_redo)
! return;
!
! free_buff(&redobuff);
! redobuff = old_redobuff;
! old_redobuff.bh_first.b_next = NULL;
! start_stuff();
! while (read_readbuffers(TRUE) != NUL)
! ;
}

/*
***************
*** 520,530 ****

// Make a copy, so that ":normal ." in a function works.
s = get_buffcont(&save_redo->sr_redobuff, FALSE);
! if (s != NULL)
! {
! add_buff(&redobuff, s, -1L);
! vim_free(s);
! }
}

/*
--- 520,530 ----

// Make a copy, so that ":normal ." in a function works.
s = get_buffcont(&save_redo->sr_redobuff, FALSE);
! if (s == NULL)
! return;
!
! add_buff(&redobuff, s, -1L);
! vim_free(s);
}

/*
***************
*** 944,958 ****
static void
init_typebuf(void)
{
! if (typebuf.tb_buf == NULL)
! {
! typebuf.tb_buf = typebuf_init;
! typebuf.tb_noremap = noremapbuf_init;
! typebuf.tb_buflen = TYPELEN_INIT;
! typebuf.tb_len = 0;
! typebuf.tb_off = MAXMAPLEN + 4;
! typebuf.tb_change_cnt = 1;
! }
}

/*
--- 944,958 ----
static void
init_typebuf(void)
{
! if (typebuf.tb_buf != NULL)
! return;
!
! typebuf.tb_buf = typebuf_init;
! typebuf.tb_noremap = noremapbuf_init;
! typebuf.tb_buflen = TYPELEN_INIT;
! typebuf.tb_len = 0;
! typebuf.tb_off = MAXMAPLEN + 4;
! typebuf.tb_change_cnt = 1;
}

/*
***************
*** 1324,1334 ****
void
ungetchars(int len)
{
! if (reg_recording != 0)
! {
! delete_buff_tail(&recordbuff, len);
! last_recorded_len -= len;
! }
}

/*
--- 1324,1334 ----
void
ungetchars(int len)
{
! if (reg_recording == 0)
! return;
!
! delete_buff_tail(&recordbuff, len);
! last_recorded_len -= len;
}

/*
***************
*** 2230,2252 ****
{
getchar_common(argvars, rettv);

! if (rettv->v_type == VAR_NUMBER)
! {
! char_u temp[7]; // mbyte-char: 6, NUL: 1
! varnumber_T n = rettv->vval.v_number;
! int i = 0;

! if (n != 0)
! {
! if (has_mbyte)
! i += (*mb_char2bytes)(n, temp + i);
! else
! temp[i++] = n;
! }
! temp[i++] = NUL;
! rettv->v_type = VAR_STRING;
! rettv->vval.v_string = vim_strsave(temp);
}
}

/*
--- 2230,2252 ----
{
getchar_common(argvars, rettv);

! if (rettv->v_type != VAR_NUMBER)
! return;

! char_u temp[7]; // mbyte-char: 6, NUL: 1
! varnumber_T n = rettv->vval.v_number;
! int i = 0;
!
! if (n != 0)
! {
! if (has_mbyte)
! i += (*mb_char2bytes)(n, temp + i);
! else
! temp[i++] = n;
}
+ temp[i++] = NUL;
+ rettv->v_type = VAR_STRING;
+ rettv->vval.v_string = vim_strsave(temp);
}

/*
***************
*** 4031,4040 ****
void
reset_last_used_map(mapblock_T *mp)
{
! if (last_used_map == mp)
! {
! last_used_map = NULL;
! last_used_sid = -1;
! }
}
#endif
--- 4031,4040 ----
void
reset_last_used_map(mapblock_T *mp)
{
! if (last_used_map != mp)
! return;
!
! last_used_map = NULL;
! last_used_sid = -1;
}
#endif
*** ../vim-9.0.1157/src/gui.c 2022-11-22 12:40:44.066427878 +0000
--- src/gui.c 2023-01-08 13:38:57.105602496 +0000
***************
*** 1171,1241 ****
return;

gui_check_pos();
- if (!gui.cursor_is_valid || force
- || gui.row != gui.cursor_row || gui.col != gui.cursor_col)
- {
- gui_undraw_cursor();

! // If a cursor-less sleep is ongoing, leave the cursor invisible
! if (cursor_is_sleeping())
! return;

! if (gui.row < 0)
! return;
#ifdef HAVE_INPUT_METHOD
! if (gui.row != gui.cursor_row || gui.col != gui.cursor_col)
! im_set_position(gui.row, gui.col);
#endif
! gui.cursor_row = gui.row;
! gui.cursor_col = gui.col;

! // Only write to the screen after ScreenLines[] has been initialized
! if (!screen_cleared || ScreenLines == NULL)
! return;

! // Clear the selection if we are about to write over it
! if (clear_selection)
! clip_may_clear_selection(gui.row, gui.row);
! // Check that the cursor is inside the shell (resizing may have made
! // it invalid)
! if (gui.row >= screen_Rows || gui.col >= screen_Columns)
! return;

! gui.cursor_is_valid = TRUE;

! /*
! * How the cursor is drawn depends on the current mode.
! * When in a terminal window use the shape/color specified there.
! */
#ifdef FEAT_TERMINAL
! if (terminal_is_active())
! shape = term_get_cursor_shape(&shape_fg, &shape_bg);
! else
#endif
! shape = &shape_table[get_shape_idx(FALSE)];
! if (State & MODE_LANGMAP)
! id = shape->id_lm;
! else
! id = shape->id;

! // get the colors and attributes for the cursor. Default is inverted
! cfg = INVALCOLOR;
! cbg = INVALCOLOR;
! cattr = HL_INVERSE;
! gui_mch_set_blinking(shape->blinkwait,
! shape->blinkon,
! shape->blinkoff);
! if (shape->blinkwait == 0 || shape->blinkon == 0
! || shape->blinkoff == 0)
! gui_mch_stop_blink(FALSE);
#ifdef FEAT_TERMINAL
! if (shape_bg != INVALCOLOR)
! {
! cattr = 0;
! cfg = shape_fg;
! cbg = shape_bg;
! }
! else
#endif
if (id > 0)
{
--- 1171,1243 ----
return;

gui_check_pos();

! if (gui.cursor_is_valid && !force
! && gui.row == gui.cursor_row && gui.col == gui.cursor_col)
! return;

! gui_undraw_cursor();
!
! // If a cursor-less sleep is ongoing, leave the cursor invisible
! if (cursor_is_sleeping())
! return;
!
! if (gui.row < 0)
! return;
#ifdef HAVE_INPUT_METHOD
! if (gui.row != gui.cursor_row || gui.col != gui.cursor_col)
! im_set_position(gui.row, gui.col);
#endif
! gui.cursor_row = gui.row;
! gui.cursor_col = gui.col;

! // Only write to the screen after ScreenLines[] has been initialized
! if (!screen_cleared || ScreenLines == NULL)
! return;

! // Clear the selection if we are about to write over it
! if (clear_selection)
! clip_may_clear_selection(gui.row, gui.row);
! // Check that the cursor is inside the shell (resizing may have made
! // it invalid)
! if (gui.row >= screen_Rows || gui.col >= screen_Columns)
! return;

! gui.cursor_is_valid = TRUE;

! /*
! * How the cursor is drawn depends on the current mode.
! * When in a terminal window use the shape/color specified there.
! */
#ifdef FEAT_TERMINAL
! if (terminal_is_active())
! shape = term_get_cursor_shape(&shape_fg, &shape_bg);
! else
#endif
! shape = &shape_table[get_shape_idx(FALSE)];
! if (State & MODE_LANGMAP)
! id = shape->id_lm;
! else
! id = shape->id;

! // get the colors and attributes for the cursor. Default is inverted
! cfg = INVALCOLOR;
! cbg = INVALCOLOR;
! cattr = HL_INVERSE;
! gui_mch_set_blinking(shape->blinkwait,
! shape->blinkon,
! shape->blinkoff);
! if (shape->blinkwait == 0 || shape->blinkon == 0
! || shape->blinkoff == 0)
! gui_mch_stop_blink(FALSE);
#ifdef FEAT_TERMINAL
! if (shape_bg != INVALCOLOR)
! {
! cattr = 0;
! cfg = shape_fg;
! cbg = shape_bg;
! }
! else
#endif
if (id > 0)
{
***************
*** 1251,1257 ****
# else
im_get_status()
# endif
! )
{
iid = syn_name2id((char_u *)"CursorIM");
if (iid > 0)
--- 1253,1259 ----
# else
im_get_status()
# endif
! )
{
iid = syn_name2id((char_u *)"CursorIM");
if (iid > 0)
***************
*** 1267,1398 ****
#endif
}

! /*
! * Get the attributes for the character under the cursor.
! * When no cursor color was given, use the character color.
! */
! attr = ScreenAttrs[LineOffset[gui.row] + gui.col];
! if (attr > HL_ALL)
! aep = syn_gui_attr2entry(attr);
! if (aep != NULL)
! {
! attr = aep->ae_attr;
! if (cfg == INVALCOLOR)
! cfg = ((attr & HL_INVERSE) ? aep->ae_u.gui.bg_color
! : aep->ae_u.gui.fg_color);
! if (cbg == INVALCOLOR)
! cbg = ((attr & HL_INVERSE) ? aep->ae_u.gui.fg_color
! : aep->ae_u.gui.bg_color);
! }
if (cfg == INVALCOLOR)
! cfg = (attr & HL_INVERSE) ? gui.back_pixel : gui.norm_pixel;
if (cbg == INVALCOLOR)
! cbg = (attr & HL_INVERSE) ? gui.norm_pixel : gui.back_pixel;

#ifdef FEAT_XIM
! if (aep != NULL)
! {
! xim_bg_color = ((attr & HL_INVERSE) ? aep->ae_u.gui.fg_color
! : aep->ae_u.gui.bg_color);
! xim_fg_color = ((attr & HL_INVERSE) ? aep->ae_u.gui.bg_color
! : aep->ae_u.gui.fg_color);
! if (xim_bg_color == INVALCOLOR)
! xim_bg_color = (attr & HL_INVERSE) ? gui.norm_pixel
! : gui.back_pixel;
! if (xim_fg_color == INVALCOLOR)
! xim_fg_color = (attr & HL_INVERSE) ? gui.back_pixel
! : gui.norm_pixel;
! }
! else
! {
xim_bg_color = (attr & HL_INVERSE) ? gui.norm_pixel
! : gui.back_pixel;
xim_fg_color = (attr & HL_INVERSE) ? gui.back_pixel
! : gui.norm_pixel;
! }
#endif

! attr &= ~HL_INVERSE;
! if (cattr & HL_INVERSE)
! {
! cc = cbg;
! cbg = cfg;
! cfg = cc;
! }
! cattr &= ~HL_INVERSE;

/*
! * When we don't have window focus, draw a hollow cursor.
*/
! if (!gui.in_focus)
{
! gui_mch_draw_hollow_cursor(cbg);
! return;
}
!
! old_hl_mask = gui.highlight_mask;
! if (shape->shape == SHAPE_BLOCK)
{
! /*
! * Draw the text character with the cursor colors. Use the
! * character attributes plus the cursor attributes.
! */
! gui.highlight_mask = (cattr | attr);
! (void)gui_screenchar(LineOffset[gui.row] + gui.col,
! GUI_MON_IS_CURSOR | GUI_MON_NOCLEAR, cfg, cbg, 0);
}
! else
{
! #if defined(FEAT_RIGHTLEFT)
! int col_off = FALSE;
! #endif
! /*
! * First draw the partial cursor, then overwrite with the text
! * character, using a transparent background.
! */
! if (shape->shape == SHAPE_VER)
! {
! cur_height = gui.char_height;
! cur_width = (gui.char_width * shape->percentage + 99) / 100;
! }
! else
{
! cur_height = (gui.char_height * shape->percentage + 99) / 100;
! cur_width = gui.char_width;
}
- if (has_mbyte && (*mb_off2cells)(LineOffset[gui.row] + gui.col,
- LineOffset[gui.row] + screen_Columns) > 1)
- {
- // Double wide character.
- if (shape->shape != SHAPE_VER)
- cur_width += gui.char_width;
- #ifdef FEAT_RIGHTLEFT
- if (CURSOR_BAR_RIGHT)
- {
- // gui.col points to the left half of the character but
- // the vertical line needs to be on the right half.
- // A double-wide horizontal line is also drawn from the
- // right half in gui_mch_draw_part_cursor().
- col_off = TRUE;
- ++gui.col;
- }
#endif
! }
! gui_mch_draw_part_cursor(cur_width, cur_height, cbg);
#if defined(FEAT_RIGHTLEFT)
! if (col_off)
! --gui.col;
#endif

#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
- }
- gui.highlight_mask = old_hl_mask;
}
}

#if defined(FEAT_MENU) || defined(PROTO)
--- 1269,1399 ----
#endif
}

! /*
! * Get the attributes for the character under the cursor.
! * When no cursor color was given, use the character color.
! */
! attr = ScreenAttrs[LineOffset[gui.row] + gui.col];
! if (attr > HL_ALL)
! aep = syn_gui_attr2entry(attr);
! if (aep != NULL)
! {
! attr = aep->ae_attr;
if (cfg == INVALCOLOR)
! cfg = ((attr & HL_INVERSE) ? aep->ae_u.gui.bg_color
! : aep->ae_u.gui.fg_color);
if (cbg == INVALCOLOR)
! cbg = ((attr & HL_INVERSE) ? aep->ae_u.gui.fg_color
! : aep->ae_u.gui.bg_color);
! }
! if (cfg == INVALCOLOR)
! cfg = (attr & HL_INVERSE) ? gui.back_pixel : gui.norm_pixel;
! if (cbg == INVALCOLOR)
! cbg = (attr & HL_INVERSE) ? gui.norm_pixel : gui.back_pixel;

#ifdef FEAT_XIM
! if (aep != NULL)
! {
! xim_bg_color = ((attr & HL_INVERSE) ? aep->ae_u.gui.fg_color
! : aep->ae_u.gui.bg_color);
! xim_fg_color = ((attr & HL_INVERSE) ? aep->ae_u.gui.bg_color
! : aep->ae_u.gui.fg_color);
! if (xim_bg_color == INVALCOLOR)
xim_bg_color = (attr & HL_INVERSE) ? gui.norm_pixel
! : gui.back_pixel;
! if (xim_fg_color == INVALCOLOR)
xim_fg_color = (attr & HL_INVERSE) ? gui.back_pixel
! : gui.norm_pixel;
! }
! else
! {
! xim_bg_color = (attr & HL_INVERSE) ? gui.norm_pixel
! : gui.back_pixel;
! xim_fg_color = (attr & HL_INVERSE) ? gui.back_pixel
! : gui.norm_pixel;
! }
#endif

! attr &= ~HL_INVERSE;
! if (cattr & HL_INVERSE)
! {
! cc = cbg;
! cbg = cfg;
! cfg = cc;
! }
! cattr &= ~HL_INVERSE;
!
! /*
! * When we don't have window focus, draw a hollow cursor.
! */
! if (!gui.in_focus)
! {
! gui_mch_draw_hollow_cursor(cbg);
! return;
! }

+ old_hl_mask = gui.highlight_mask;
+ if (shape->shape == SHAPE_BLOCK)
+ {
/*
! * Draw the text character with the cursor colors. Use the
! * character attributes plus the cursor attributes.
*/
! gui.highlight_mask = (cattr | attr);
! (void)gui_screenchar(LineOffset[gui.row] + gui.col,
! GUI_MON_IS_CURSOR | GUI_MON_NOCLEAR, cfg, cbg, 0);
! }
! else
! {
! #if defined(FEAT_RIGHTLEFT)
! int col_off = FALSE;
! #endif
! /*
! * First draw the partial cursor, then overwrite with the text
! * character, using a transparent background.
! */
! if (shape->shape == SHAPE_VER)
{
! cur_height = gui.char_height;
! cur_width = (gui.char_width * shape->percentage + 99) / 100;
}
! else
{
! cur_height = (gui.char_height * shape->percentage + 99) / 100;
! cur_width = gui.char_width;
}
! if (has_mbyte && (*mb_off2cells)(LineOffset[gui.row] + gui.col,
! LineOffset[gui.row] + screen_Columns) > 1)
{
! // Double wide character.
! if (shape->shape != SHAPE_VER)
! cur_width += gui.char_width;
! #ifdef FEAT_RIGHTLEFT
! if (CURSOR_BAR_RIGHT)
{
! // gui.col points to the left half of the character but
! // the vertical line needs to be on the right half.
! // A double-wide horizontal line is also drawn from the
! // right half in gui_mch_draw_part_cursor().
! col_off = TRUE;
! ++gui.col;
}
#endif
! }
! gui_mch_draw_part_cursor(cur_width, cur_height, cbg);
#if defined(FEAT_RIGHTLEFT)
! if (col_off)
! --gui.col;
#endif

#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
}
+ gui.highlight_mask = old_hl_mask;
}

#if defined(FEAT_MENU) || defined(PROTO)
***************
*** 2054,2066 ****
void
gui_dont_update_cursor(int undraw)
{
! if (gui.in_use)
! {
! // Undraw the cursor now, we probably can't do it after the change.
! if (undraw)
! gui_undraw_cursor();
! can_update_cursor = FALSE;
! }
}

void
--- 2055,2067 ----
void
gui_dont_update_cursor(int undraw)
{
! if (!gui.in_use)
! return;
!
! // Undraw the cursor now, we probably can't do it after the change.
! if (undraw)
! gui_undraw_cursor();
! can_update_cursor = FALSE;
}

void
***************
*** 2679,2701 ****
void
gui_undraw_cursor(void)
{
! if (gui.cursor_is_valid)
! {
! // Always redraw the character just before if there is one, because
! // with some fonts and characters there can be a one pixel overlap.
! int startcol = gui.cursor_col > 0 ? gui.cursor_col - 1 : gui.cursor_col;
! int endcol = gui.cursor_col;

#ifdef FEAT_GUI_GTK
! gui_adjust_undraw_cursor_for_ligatures(&startcol, &endcol);
#endif
! gui_redraw_block(gui.cursor_row, startcol,
! gui.cursor_row, endcol, GUI_MON_NOCLEAR);

! // Cursor_is_valid is reset when the cursor is undrawn, also reset it
! // here in case it wasn't needed to undraw it.
! gui.cursor_is_valid = FALSE;
! }
}

void
--- 2680,2702 ----
void
gui_undraw_cursor(void)
{
! if (!gui.cursor_is_valid)
! return;
!
! // Always redraw the character just before if there is one, because
! // with some fonts and characters there can be a one pixel overlap.
! int startcol = gui.cursor_col > 0 ? gui.cursor_col - 1 : gui.cursor_col;
! int endcol = gui.cursor_col;

#ifdef FEAT_GUI_GTK
! gui_adjust_undraw_cursor_for_ligatures(&startcol, &endcol);
#endif
! gui_redraw_block(gui.cursor_row, startcol,
! gui.cursor_row, endcol, GUI_MON_NOCLEAR);

! // Cursor_is_valid is reset when the cursor is undrawn, also reset it
! // here in case it wasn't needed to undraw it.
! gui.cursor_is_valid = FALSE;
}

void
***************
*** 3559,3695 ****
break;
}

! if (gui.in_use)
! {
! need_set_size = 0;
! fix_size = FALSE;

#ifdef FEAT_GUI_DARKTHEME
! if (using_dark_theme != prev_dark_theme)
! {
! gui_mch_set_dark_theme(using_dark_theme);
! prev_dark_theme = using_dark_theme;
! }
#endif

#ifdef FEAT_GUI_TABLINE
! // Update the GUI tab line, it may appear or disappear. This may
! // cause the non-GUI tab line to disappear or appear.
! using_tabline = gui_has_tabline();
! if (!gui_mch_showing_tabline() != !using_tabline)
! {
! // We don't want a resize event change "Rows" here, save and
! // restore it. Resizing is handled below.
! i = Rows;
! gui_update_tabline();
! Rows = i;
! need_set_size |= RESIZE_VERT;
! if (using_tabline)
! fix_size = TRUE;
! if (!gui_use_tabline())
! redraw_tabline = TRUE; // may draw non-GUI tab line
! }
#endif

! for (i = 0; i < 3; i++)
! {
! // The scrollbar needs to be updated when it is shown/unshown and
! // when switching tab pages. But the size only changes when it's
! // shown/unshown. Thus we need two places to remember whether a
! // scrollbar is there or not.
! if (gui.which_scrollbars[i] != prev_which_scrollbars[i]
! || gui.which_scrollbars[i]
! != curtab->tp_prev_which_scrollbars[i])
{
if (i == SBAR_BOTTOM)
! gui_mch_enable_scrollbar(&gui.bottom_sbar,
! gui.which_scrollbars[i]);
else
! {
! FOR_ALL_WINDOWS(wp)
! gui_do_scrollbar(wp, i, gui.which_scrollbars[i]);
! }
! if (gui.which_scrollbars[i] != prev_which_scrollbars[i])
! {
! if (i == SBAR_BOTTOM)
! need_set_size |= RESIZE_VERT;
! else
! need_set_size |= RESIZE_HOR;
! if (gui.which_scrollbars[i])
! fix_size = TRUE;
! }
}
- curtab->tp_prev_which_scrollbars[i] = gui.which_scrollbars[i];
- prev_which_scrollbars[i] = gui.which_scrollbars[i];
}

#ifdef FEAT_MENU
! if (gui.menu_is_active != prev_menu_is_active)
! {
! // We don't want a resize event change "Rows" here, save and
! // restore it. Resizing is handled below.
! i = Rows;
! gui_mch_enable_menu(gui.menu_is_active);
! Rows = i;
! prev_menu_is_active = gui.menu_is_active;
! need_set_size |= RESIZE_VERT;
! if (gui.menu_is_active)
! fix_size = TRUE;
! }
#endif

#ifdef FEAT_TOOLBAR
! if (using_toolbar != prev_toolbar)
! {
! gui_mch_show_toolbar(using_toolbar);
! prev_toolbar = using_toolbar;
! need_set_size |= RESIZE_VERT;
! if (using_toolbar)
! fix_size = TRUE;
! }
#endif
#if defined(FEAT_MENU) && !(defined(MSWIN) && !defined(FEAT_TEAROFF))
! if (using_tearoff != prev_tearoff)
! {
! gui_mch_toggle_tearoffs(using_tearoff);
! prev_tearoff = using_tearoff;
! }
#endif
! if (need_set_size != 0)
! {
#ifdef FEAT_GUI_GTK
! long prev_Columns = Columns;
! long prev_Rows = Rows;
#endif
! // Adjust the size of the window to make the text area keep the
! // same size and to avoid that part of our window is off-screen
! // and a scrollbar can't be used, for example.
! gui_set_shellsize(FALSE, fix_size, need_set_size);

#ifdef FEAT_GUI_GTK
! // GTK has the annoying habit of sending us resize events when
! // changing the window size ourselves. This mostly happens when
! // waiting for a character to arrive, quite unpredictably, and may
! // change Columns and Rows when we don't want it. Wait for a
! // character here to avoid this effect.
! // If you remove this, please test this command for resizing
! // effects (with optional left scrollbar): ":vsp|q|vsp|q|vsp|q".
! // Don't do this while starting up though.
! // Don't change Rows when adding menu/toolbar/tabline.
! // Don't change Columns when adding vertical toolbar.
! if (!gui.starting && need_set_size != (RESIZE_VERT | RESIZE_HOR))
! (void)char_avail();
! if ((need_set_size & RESIZE_VERT) == 0)
! Rows = prev_Rows;
! if ((need_set_size & RESIZE_HOR) == 0)
! Columns = prev_Columns;
! #endif
! }
! // When the console tabline appears or disappears the window positions
! // change.
! if (firstwin->w_winrow != tabline_height())
! shell_new_rows(); // recompute window positions and heights
! }
}

#if defined(FEAT_GUI_TABLINE) || defined(PROTO)
--- 3560,3696 ----
break;
}

! if (!gui.in_use)
! return;
!
! need_set_size = 0;
! fix_size = FALSE;

#ifdef FEAT_GUI_DARKTHEME
! if (using_dark_theme != prev_dark_theme)
! {
! gui_mch_set_dark_theme(using_dark_theme);
! prev_dark_theme = using_dark_theme;
! }
#endif

#ifdef FEAT_GUI_TABLINE
! // Update the GUI tab line, it may appear or disappear. This may
! // cause the non-GUI tab line to disappear or appear.
! using_tabline = gui_has_tabline();
! if (!gui_mch_showing_tabline() != !using_tabline)
! {
! // We don't want a resize event change "Rows" here, save and
! // restore it. Resizing is handled below.
! i = Rows;
! gui_update_tabline();
! Rows = i;
! need_set_size |= RESIZE_VERT;
! if (using_tabline)
! fix_size = TRUE;
! if (!gui_use_tabline())
! redraw_tabline = TRUE; // may draw non-GUI tab line
! }
#endif

! for (i = 0; i < 3; i++)
! {
! // The scrollbar needs to be updated when it is shown/unshown and
! // when switching tab pages. But the size only changes when it's
! // shown/unshown. Thus we need two places to remember whether a
! // scrollbar is there or not.
! if (gui.which_scrollbars[i] != prev_which_scrollbars[i]
! || gui.which_scrollbars[i]
! != curtab->tp_prev_which_scrollbars[i])
! {
! if (i == SBAR_BOTTOM)
! gui_mch_enable_scrollbar(&gui.bottom_sbar,
! gui.which_scrollbars[i]);
! else
! {
! FOR_ALL_WINDOWS(wp)
! gui_do_scrollbar(wp, i, gui.which_scrollbars[i]);
! }
! if (gui.which_scrollbars[i] != prev_which_scrollbars[i])
{
if (i == SBAR_BOTTOM)
! need_set_size |= RESIZE_VERT;
else
! need_set_size |= RESIZE_HOR;
! if (gui.which_scrollbars[i])
! fix_size = TRUE;
}
}
+ curtab->tp_prev_which_scrollbars[i] = gui.which_scrollbars[i];
+ prev_which_scrollbars[i] = gui.which_scrollbars[i];
+ }

#ifdef FEAT_MENU
! if (gui.menu_is_active != prev_menu_is_active)
! {
! // We don't want a resize event change "Rows" here, save and
! // restore it. Resizing is handled below.
! i = Rows;
! gui_mch_enable_menu(gui.menu_is_active);
! Rows = i;
! prev_menu_is_active = gui.menu_is_active;
! need_set_size |= RESIZE_VERT;
! if (gui.menu_is_active)
! fix_size = TRUE;
! }
#endif

#ifdef FEAT_TOOLBAR
! if (using_toolbar != prev_toolbar)
! {
! gui_mch_show_toolbar(using_toolbar);
! prev_toolbar = using_toolbar;
! need_set_size |= RESIZE_VERT;
! if (using_toolbar)
! fix_size = TRUE;
! }
#endif
#if defined(FEAT_MENU) && !(defined(MSWIN) && !defined(FEAT_TEAROFF))
! if (using_tearoff != prev_tearoff)
! {
! gui_mch_toggle_tearoffs(using_tearoff);
! prev_tearoff = using_tearoff;
! }
#endif
! if (need_set_size != 0)
! {
#ifdef FEAT_GUI_GTK
! long prev_Columns = Columns;
! long prev_Rows = Rows;
#endif
! // Adjust the size of the window to make the text area keep the
! // same size and to avoid that part of our window is off-screen
! // and a scrollbar can't be used, for example.
! gui_set_shellsize(FALSE, fix_size, need_set_size);

#ifdef FEAT_GUI_GTK
! // GTK has the annoying habit of sending us resize events when
! // changing the window size ourselves. This mostly happens when
! // waiting for a character to arrive, quite unpredictably, and may
! // change Columns and Rows when we don't want it. Wait for a
! // character here to avoid this effect.
! // If you remove this, please test this command for resizing
! // effects (with optional left scrollbar): ":vsp|q|vsp|q|vsp|q".
! // Don't do this while starting up though.
! // Don't change Rows when adding menu/toolbar/tabline.
! // Don't change Columns when adding vertical toolbar.
! if (!gui.starting && need_set_size != (RESIZE_VERT | RESIZE_HOR))
! (void)char_avail();
! if ((need_set_size & RESIZE_VERT) == 0)
! Rows = prev_Rows;
! if ((need_set_size & RESIZE_HOR) == 0)
! Columns = prev_Columns;
! #endif
! }
! // When the console tabline appears or disappears the window positions
! // change.
! if (firstwin->w_winrow != tabline_height())
! shell_new_rows(); // recompute window positions and heights
}

#if defined(FEAT_GUI_TABLINE) || defined(PROTO)
***************
*** 4768,4774 ****
return;

/*
! * format a mouse click on status line input
* ala gui_send_mouse_event(0, x, y, 0, 0);
* Trick: Use a column number -1, so that get_pseudo_mouse_code() will
* generate a K_LEFTMOUSE_NM key code.
--- 4769,4775 ----
return;

/*
! * Format a mouse click on status line input,
* ala gui_send_mouse_event(0, x, y, 0, 0);
* Trick: Use a column number -1, so that get_pseudo_mouse_code() will
* generate a K_LEFTMOUSE_NM key code.
***************
*** 4852,4864 ****
need_mouse_correct = FALSE;

wp = gui_mouse_window(IGNORE_POPUP);
! if (wp != curwin && wp != NULL) // If in other than current window
! {
! validate_cline_row();
! gui_mch_setmouse((int)W_ENDCOL(curwin) * gui.char_width - 3,
! (W_WINROW(curwin) + curwin->w_wrow) * gui.char_height
! + (gui.char_height) / 2);
! }
}

/*
--- 4853,4866 ----
need_mouse_correct = FALSE;

wp = gui_mouse_window(IGNORE_POPUP);
! if (wp == curwin || wp == NULL)
! return;
!
! // If in other than current window
! validate_cline_row();
! gui_mch_setmouse((int)W_ENDCOL(curwin) * gui.char_width - 3,
! (W_WINROW(curwin) + curwin->w_wrow) * gui.char_height
! + (gui.char_height) / 2);
}

/*
***************
*** 5014,5035 ****
char_u *p;

if (isatty(2))
- fflush(stderr);
- else if (error_ga.ga_data != NULL)
{
! // avoid putting up a message box with blanks only
! for (p = (char_u *)error_ga.ga_data; *p != NUL; ++p)
! if (!isspace(*p))
! {
! // Truncate a very long message, it will go off-screen.
! if (STRLEN(p) > 2000)
! STRCPY(p + 2000 - 14, "...(truncated)");
! (void)do_dialog(VIM_ERROR, (char_u *)_("Error"),
! p, (char_u *)_("&Ok"), 1, NULL, FALSE);
! break;
! }
! ga_clear(&error_ga);
}
}
#endif

--- 5016,5041 ----
char_u *p;

if (isatty(2))
{
! fflush(stderr);
! return;
}
+
+ if (error_ga.ga_data == NULL)
+ return;
+
+ // avoid putting up a message box with blanks only
+ for (p = (char_u *)error_ga.ga_data; *p != NUL; ++p)
+ if (!isspace(*p))
+ {
+ // Truncate a very long message, it will go off-screen.
+ if (STRLEN(p) > 2000)
+ STRCPY(p + 2000 - 14, "...(truncated)");
+ (void)do_dialog(VIM_ERROR, (char_u *)_("Error"),
+ p, (char_u *)_("&Ok"), 1, NULL, FALSE);
+ break;
+ }
+ ga_clear(&error_ga);
}
#endif

***************
*** 5339,5350 ****
int col = X_2_COL(x);
win_T *wp;

! if (row >= 0 && col >= 0)
! {
! wp = mouse_find_win(&row, &col, FAIL_POPUP);
! if (wp != NULL && wp != curwin)
! win_goto(wp);
! }
}

/*
--- 5345,5356 ----
int col = X_2_COL(x);
win_T *wp;

! if (row < 0 || col < 0)
! return;
!
! wp = mouse_find_win(&row, &col, FAIL_POPUP);
! if (wp != NULL && wp != curwin)
! win_goto(wp);
}

/*
*** ../vim-9.0.1157/src/gui_beval.c 2022-04-03 17:19:01.000000000 +0100
--- src/gui_beval.c 2023-01-08 13:38:57.105602496 +0000
***************
*** 373,412 ****

distance = ABS(x - beval->x) + ABS(y - beval->y);

! if (distance > 4)
{
! /*
! * Moved out of the balloon location: cancel it.
! * Remember button state
! */
! beval->state = state;
! cancelBalloon(beval);

! // Mouse buttons are pressed - no balloon now
! if (!(state & ((int)GDK_BUTTON1_MASK | (int)GDK_BUTTON2_MASK
! | (int)GDK_BUTTON3_MASK)))
{
! beval->x = x;
! beval->y = y;
!
! if (state & (int)GDK_MOD1_MASK)
! {
! /*
! * Alt is pressed -- enter super-evaluate-mode,
! * where there is no time delay
! */
! if (beval->msgCB != NULL)
! {
! beval->showState = ShS_PENDING;
! (*beval->msgCB)(beval, state);
! }
! }
! else
{
! beval->timerID = g_timeout_add((guint)p_bdlay,
! &timeout_cb, beval);
}
}
}
}

--- 373,412 ----

distance = ABS(x - beval->x) + ABS(y - beval->y);

! if (distance <= 4)
! return;
!
! /*
! * Moved out of the balloon location: cancel it.
! * Remember button state
! */
! beval->state = state;
! cancelBalloon(beval);
!
! // Mouse buttons are pressed - no balloon now
! if (!(state & ((int)GDK_BUTTON1_MASK | (int)GDK_BUTTON2_MASK
! | (int)GDK_BUTTON3_MASK)))
{
! beval->x = x;
! beval->y = y;

! if (state & (int)GDK_MOD1_MASK)
{
! /*
! * Alt is pressed -- enter super-evaluate-mode,
! * where there is no time delay
! */
! if (beval->msgCB != NULL)
{
! beval->showState = ShS_PENDING;
! (*beval->msgCB)(beval, state);
}
}
+ else
+ {
+ beval->timerID = g_timeout_add((guint)p_bdlay,
+ &timeout_cb, beval);
+ }
}
}

***************
*** 698,714 ****
static void
requestBalloon(BalloonEval *beval)
{
! if (beval->showState != ShS_PENDING)
{
! // Determine the beval to display
! if (beval->msgCB != NULL)
! {
! beval->showState = ShS_PENDING;
! (*beval->msgCB)(beval, beval->state);
! }
! else if (beval->msg != NULL)
! drawBalloon(beval);
}
}

#ifdef FEAT_GUI_GTK
--- 698,714 ----
static void
requestBalloon(BalloonEval *beval)
{
! if (beval->showState == ShS_PENDING)
! return;
!
! // Determine the beval to display
! if (beval->msgCB != NULL)
{
! beval->showState = ShS_PENDING;
! (*beval->msgCB)(beval, beval->state);
}
+ else if (beval->msg != NULL)
+ drawBalloon(beval);
}

#ifdef FEAT_GUI_GTK
***************
*** 900,984 ****
static void
drawBalloon(BalloonEval *beval)
{
! if (beval->msg != NULL)
! {
! GtkRequisition requisition;
! int screen_w;
! int screen_h;
! int screen_x;
! int screen_y;
! int x;
! int y;
! int x_offset = EVAL_OFFSET_X;
! int y_offset = EVAL_OFFSET_Y;
! PangoLayout *layout;

# if !GTK_CHECK_VERSION(3,22,2)
! GdkScreen *screen;

! screen = gtk_widget_get_screen(beval->target);
! gtk_window_set_screen(GTK_WINDOW(beval->balloonShell), screen);
# endif
! gui_gtk_get_screen_geom_of_win(beval->target, 0, 0,
! &screen_x, &screen_y, &screen_w, &screen_h);
# if !GTK_CHECK_VERSION(3,0,0)
! gtk_widget_ensure_style(beval->balloonShell);
! gtk_widget_ensure_style(beval->balloonLabel);
# endif

! set_printable_label_text(GTK_LABEL(beval->balloonLabel), beval->msg);
! /*
! * Dirty trick: Enable wrapping mode on the label's layout behind its
! * back. This way GtkLabel won't try to constrain the wrap width to a
! * builtin maximum value of about 65 Latin characters.
! */
! layout = gtk_label_get_layout(GTK_LABEL(beval->balloonLabel));
# ifdef PANGO_WRAP_WORD_CHAR
! pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR);
# else
! pango_layout_set_wrap(layout, PANGO_WRAP_WORD);
# endif
! pango_layout_set_width(layout,
! // try to come up with some reasonable width
! PANGO_SCALE * CLAMP(gui.num_cols * gui.char_width,
! screen_w / 2,
! MAX(20, screen_w - 20)));

! // Calculate the balloon's width and height.
# if GTK_CHECK_VERSION(3,0,0)
! gtk_widget_get_preferred_size(beval->balloonShell, &requisition, NULL);
# else
! gtk_widget_size_request(beval->balloonShell, &requisition);
# endif

! // Compute position of the balloon area
! gdk_window_get_origin(gtk_widget_get_window(beval->target), &x, &y);
! x += beval->x;
! y += beval->y;
!
! // Get out of the way of the mouse pointer
! if (x + x_offset + requisition.width > screen_x + screen_w)
! y_offset += 15;
! if (y + y_offset + requisition.height > screen_y + screen_h)
! y_offset = -requisition.height - EVAL_OFFSET_Y;
!
! // Sanitize values
! x = CLAMP(x + x_offset, 0,
! MAX(0, screen_x + screen_w - requisition.width));
! y = CLAMP(y + y_offset, 0,
! MAX(0, screen_y + screen_h - requisition.height));

! // Show the balloon
# if GTK_CHECK_VERSION(3,0,0)
! gtk_window_move(GTK_WINDOW(beval->balloonShell), x, y);
# else
! gtk_widget_set_uposition(beval->balloonShell, x, y);
# endif
! gtk_widget_show(beval->balloonShell);

! beval->showState = ShS_SHOWING;
! gui_mch_update();
! }
}

/*
--- 900,984 ----
static void
drawBalloon(BalloonEval *beval)
{
! if (beval->msg == NULL)
! return;
!
! GtkRequisition requisition;
! int screen_w;
! int screen_h;
! int screen_x;
! int screen_y;
! int x;
! int y;
! int x_offset = EVAL_OFFSET_X;
! int y_offset = EVAL_OFFSET_Y;
! PangoLayout *layout;

# if !GTK_CHECK_VERSION(3,22,2)
! GdkScreen *screen;

! screen = gtk_widget_get_screen(beval->target);
! gtk_window_set_screen(GTK_WINDOW(beval->balloonShell), screen);
# endif
! gui_gtk_get_screen_geom_of_win(beval->target, 0, 0,
! &screen_x, &screen_y, &screen_w, &screen_h);
# if !GTK_CHECK_VERSION(3,0,0)
! gtk_widget_ensure_style(beval->balloonShell);
! gtk_widget_ensure_style(beval->balloonLabel);
# endif

! set_printable_label_text(GTK_LABEL(beval->balloonLabel), beval->msg);
! /*
! * Dirty trick: Enable wrapping mode on the label's layout behind its
! * back. This way GtkLabel won't try to constrain the wrap width to a
! * builtin maximum value of about 65 Latin characters.
! */
! layout = gtk_label_get_layout(GTK_LABEL(beval->balloonLabel));
# ifdef PANGO_WRAP_WORD_CHAR
! pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR);
# else
! pango_layout_set_wrap(layout, PANGO_WRAP_WORD);
# endif
! pango_layout_set_width(layout,
! // try to come up with some reasonable width
! PANGO_SCALE * CLAMP(gui.num_cols * gui.char_width,
! screen_w / 2,
! MAX(20, screen_w - 20)));

! // Calculate the balloon's width and height.
# if GTK_CHECK_VERSION(3,0,0)
! gtk_widget_get_preferred_size(beval->balloonShell, &requisition, NULL);
# else
! gtk_widget_size_request(beval->balloonShell, &requisition);
# endif

! // Compute position of the balloon area
! gdk_window_get_origin(gtk_widget_get_window(beval->target), &x, &y);
! x += beval->x;
! y += beval->y;
!
! // Get out of the way of the mouse pointer
! if (x + x_offset + requisition.width > screen_x + screen_w)
! y_offset += 15;
! if (y + y_offset + requisition.height > screen_y + screen_h)
! y_offset = -requisition.height - EVAL_OFFSET_Y;
!
! // Sanitize values
! x = CLAMP(x + x_offset, 0,
! MAX(0, screen_x + screen_w - requisition.width));
! y = CLAMP(y + y_offset, 0,
! MAX(0, screen_y + screen_h - requisition.height));

! // Show the balloon
# if GTK_CHECK_VERSION(3,0,0)
! gtk_window_move(GTK_WINDOW(beval->balloonShell), x, y);
# else
! gtk_widget_set_uposition(beval->balloonShell, x, y);
# endif
! gtk_widget_show(beval->balloonShell);

! beval->showState = ShS_SHOWING;
! gui_mch_update();
}

/*
***************
*** 1060,1124 ****
Position tx;
Position ty;

! if (beval->msg != NULL)
! {
! XmString s;
! // Show the Balloon

! // Calculate the label's width and height

! // For the callback function we parse NL characters to create a
! // multi-line label. This doesn't work for all languages, but
! // XmStringCreateLocalized() doesn't do multi-line labels...
! if (beval->msgCB != NULL)
! s = XmStringCreateLtoR((char *)beval->msg, XmFONTLIST_DEFAULT_TAG);
! else
! s = XmStringCreateLocalized((char *)beval->msg);
! {
! XmFontList fl;

! fl = gui_motif_fontset2fontlist(&gui.tooltip_fontset);
! if (fl == NULL)
! {
! XmStringFree(s);
! return;
! }
! XmStringExtent(fl, s, &w, &h);
! XmFontListFree(fl);
! }
! w += gui.border_offset << 1;
! h += gui.border_offset << 1;
! XtVaSetValues(beval->balloonLabel, XmNlabelString, s, NULL);
! XmStringFree(s);
!
! // Compute position of the balloon area
! tx = beval->x_root + EVAL_OFFSET_X;
! ty = beval->y_root + EVAL_OFFSET_Y;
! if ((tx + w) > beval->screen_width)
! tx = beval->screen_width - w;
! if ((ty + h) > beval->screen_height)
! ty = beval->screen_height - h;
! XtVaSetValues(beval->balloonShell,
! XmNx, tx,
! XmNy, ty,
! NULL);
! // Set tooltip colors
! {
! Arg args[2];

! args[0].name = XmNbackground;
! args[0].value = gui.tooltip_bg_pixel;
! args[1].name = XmNforeground;
! args[1].value = gui.tooltip_fg_pixel;
! XtSetValues(beval->balloonLabel, &args[0], XtNumber(args));
}

! XtPopup(beval->balloonShell, XtGrabNone);

! beval->showState = ShS_SHOWING;

! current_beval = beval;
! }
}

/*
--- 1060,1124 ----
Position tx;
Position ty;

! if (beval->msg == NULL)
! return;

! XmString s;
! // Show the Balloon

! // Calculate the label's width and height

! // For the callback function we parse NL characters to create a
! // multi-line label. This doesn't work for all languages, but
! // XmStringCreateLocalized() doesn't do multi-line labels...
! if (beval->msgCB != NULL)
! s = XmStringCreateLtoR((char *)beval->msg, XmFONTLIST_DEFAULT_TAG);
! else
! s = XmStringCreateLocalized((char *)beval->msg);
! {
! XmFontList fl;

! fl = gui_motif_fontset2fontlist(&gui.tooltip_fontset);
! if (fl == NULL)
! {
! XmStringFree(s);
! return;
}
+ XmStringExtent(fl, s, &w, &h);
+ XmFontListFree(fl);
+ }
+ w += gui.border_offset << 1;
+ h += gui.border_offset << 1;
+ XtVaSetValues(beval->balloonLabel, XmNlabelString, s, NULL);
+ XmStringFree(s);
+
+ // Compute position of the balloon area
+ tx = beval->x_root + EVAL_OFFSET_X;
+ ty = beval->y_root + EVAL_OFFSET_Y;
+ if ((tx + w) > beval->screen_width)
+ tx = beval->screen_width - w;
+ if ((ty + h) > beval->screen_height)
+ ty = beval->screen_height - h;
+ XtVaSetValues(beval->balloonShell,
+ XmNx, tx,
+ XmNy, ty,
+ NULL);
+ // Set tooltip colors
+ {
+ Arg args[2];
+
+ args[0].name = XmNbackground;
+ args[0].value = gui.tooltip_bg_pixel;
+ args[1].name = XmNforeground;
+ args[1].value = gui.tooltip_fg_pixel;
+ XtSetValues(beval->balloonLabel, &args[0], XtNumber(args));
+ }

! XtPopup(beval->balloonShell, XtGrabNone);

! beval->showState = ShS_SHOWING;

! current_beval = beval;
}

/*
***************
*** 1161,1178 ****
beval->balloonShell = XtAppCreateShell("balloonEval", "BalloonEval",
overrideShellWidgetClass, gui.dpy, args, n);

! {
! XmFontList fl;

! n = 0;
! fl = gui_motif_fontset2fontlist(&gui.tooltip_fontset);
! XtSetArg(args[n], XmNforeground, gui.tooltip_fg_pixel); n++;
! XtSetArg(args[n], XmNbackground, gui.tooltip_bg_pixel); n++;
! XtSetArg(args[n], XmNfontList, fl); n++;
! XtSetArg(args[n], XmNalignment, XmALIGNMENT_BEGINNING); n++;
! beval->balloonLabel = XtCreateManagedWidget("balloonLabel",
! xmLabelWidgetClass, beval->balloonShell, args, n);
! }
}

#endif // !FEAT_GUI_GTK
--- 1161,1176 ----
beval->balloonShell = XtAppCreateShell("balloonEval", "BalloonEval",
overrideShellWidgetClass, gui.dpy, args, n);

! XmFontList fl;

! n = 0;
! fl = gui_motif_fontset2fontlist(&gui.tooltip_fontset);
! XtSetArg(args[n], XmNforeground, gui.tooltip_fg_pixel); n++;
! XtSetArg(args[n], XmNbackground, gui.tooltip_bg_pixel); n++;
! XtSetArg(args[n], XmNfontList, fl); n++;
! XtSetArg(args[n], XmNalignment, XmALIGNMENT_BEGINNING); n++;
! beval->balloonLabel = XtCreateManagedWidget("balloonLabel",
! xmLabelWidgetClass, beval->balloonShell, args, n);
}

#endif // !FEAT_GUI_GTK
*** ../vim-9.0.1157/src/gui_gtk.c 2022-05-07 18:08:58.000000000 +0100
--- src/gui_gtk.c 2023-01-08 13:38:57.105602496 +0000
***************
*** 924,945 ****
void
gui_mch_menu_set_tip(vimmenu_T *menu)
{
! if (menu->id != NULL && menu->parent != NULL && gui.toolbar != NULL)
! {
! char_u *tooltip;

! tooltip = CONVERT_TO_UTF8(menu->strings[MENU_INDEX_TIP]);
! if (tooltip != NULL && utf_valid_string(tooltip, NULL))
# if GTK_CHECK_VERSION(3,0,0)
! // Only set the tooltip when it's valid utf-8.
! gtk_widget_set_tooltip_text(menu->id, (const gchar *)tooltip);
# else
! // Only set the tooltip when it's valid utf-8.
! gtk_tooltips_set_tip(GTK_TOOLBAR(gui.toolbar)->tooltips,
! menu->id, (const char *)tooltip, NULL);
# endif
! CONVERT_TO_UTF8_FREE(tooltip);
! }
}
#endif // FEAT_TOOLBAR

--- 924,945 ----
void
gui_mch_menu_set_tip(vimmenu_T *menu)
{
! if (menu->id == NULL || menu->parent == NULL || gui.toolbar == NULL)
! return;
!
! char_u *tooltip;

! tooltip = CONVERT_TO_UTF8(menu->strings[MENU_INDEX_TIP]);
! if (tooltip != NULL && utf_valid_string(tooltip, NULL))
# if GTK_CHECK_VERSION(3,0,0)
! // Only set the tooltip when it's valid utf-8.
! gtk_widget_set_tooltip_text(menu->id, (const gchar *)tooltip);
# else
! // Only set the tooltip when it's valid utf-8.
! gtk_tooltips_set_tip(GTK_TOOLBAR(gui.toolbar)->tooltips,
! menu->id, (const char *)tooltip, NULL);
# endif
! CONVERT_TO_UTF8_FREE(tooltip);
}
#endif // FEAT_TOOLBAR

***************
*** 1007,1040 ****
void
gui_mch_set_scrollbar_thumb(scrollbar_T *sb, long val, long size, long max)
{
! if (sb->id != NULL)
! {
! GtkAdjustment *adjustment;

! // ignore events triggered by moving the thumb (happens in GTK 3)
! ++hold_gui_events;

! adjustment = gtk_range_get_adjustment(GTK_RANGE(sb->id));

! gtk_adjustment_set_lower(adjustment, 0.0);
! gtk_adjustment_set_value(adjustment, val);
! gtk_adjustment_set_upper(adjustment, max + 1);
! gtk_adjustment_set_page_size(adjustment, size);
! gtk_adjustment_set_page_increment(adjustment,
! size < 3L ? 1L : size - 2L);
! gtk_adjustment_set_step_increment(adjustment, 1.0);

! g_signal_handler_block(G_OBJECT(adjustment), (gulong)sb->handler_id);

! --hold_gui_events;

#if !GTK_CHECK_VERSION(3,18,0)
! gtk_adjustment_changed(adjustment);
#endif

! g_signal_handler_unblock(G_OBJECT(adjustment),
! (gulong)sb->handler_id);
! }
}

void
--- 1007,1040 ----
void
gui_mch_set_scrollbar_thumb(scrollbar_T *sb, long val, long size, long max)
{
! if (sb->id == NULL)
! return;

! GtkAdjustment *adjustment;

! // ignore events triggered by moving the thumb (happens in GTK 3)
! ++hold_gui_events;

! adjustment = gtk_range_get_adjustment(GTK_RANGE(sb->id));

! gtk_adjustment_set_lower(adjustment, 0.0);
! gtk_adjustment_set_value(adjustment, val);
! gtk_adjustment_set_upper(adjustment, max + 1);
! gtk_adjustment_set_page_size(adjustment, size);
! gtk_adjustment_set_page_increment(adjustment,
! size < 3L ? 1L : size - 2L);
! gtk_adjustment_set_step_increment(adjustment, 1.0);

! g_signal_handler_block(G_OBJECT(adjustment), (gulong)sb->handler_id);
!
! --hold_gui_events;

#if !GTK_CHECK_VERSION(3,18,0)
! gtk_adjustment_changed(adjustment);
#endif

! g_signal_handler_unblock(G_OBJECT(adjustment),
! (gulong)sb->handler_id);
}

void
***************
*** 1157,1177 ****
sb->id = gtk_vscrollbar_new(NULL);
#endif

! if (sb->id != NULL)
! {
! GtkAdjustment *adjustment;

! gtk_widget_set_can_focus(sb->id, FALSE);
! gui_gtk_form_put(GTK_FORM(gui.formwin), sb->id, 0, 0);

! adjustment = gtk_range_get_adjustment(GTK_RANGE(sb->id));

! sb->handler_id = g_signal_connect(
! G_OBJECT(adjustment), "value-changed",
! G_CALLBACK(adjustment_value_changed),
! GINT_TO_POINTER(sb->ident));
! gui_mch_update();
! }
}

void
--- 1157,1177 ----
sb->id = gtk_vscrollbar_new(NULL);
#endif

! if (sb->id == NULL)
! return;

! GtkAdjustment *adjustment;

! gtk_widget_set_can_focus(sb->id, FALSE);
! gui_gtk_form_put(GTK_FORM(gui.formwin), sb->id, 0, 0);

! adjustment = gtk_range_get_adjustment(GTK_RANGE(sb->id));
!
! sb->handler_id = g_signal_connect(
! G_OBJECT(adjustment), "value-changed",
! G_CALLBACK(adjustment_value_changed),
! GINT_TO_POINTER(sb->ident));
! gui_mch_update();
}

void
***************
*** 1994,2052 ****
popup_mouse_pos = mouse_pos;

menu = gui_find_menu(path_name);

- if (menu != NULL && menu->submenu_id != NULL)
- {
# if GTK_CHECK_VERSION(3,22,2)
! GdkWindow * const win = gtk_widget_get_window(gui.drawarea);
! GdkEventButton trigger;

! // A pseudo event to have gtk_menu_popup_at_*() functions work. Since
! // the position where the menu pops up is automatically adjusted by
! // the functions, none of the fields x, y, x_root and y_root has to be
! // set to a specific value here; therefore, they are set to zero for
! // convenience.
! trigger.type = GDK_BUTTON_PRESS;
! trigger.window = win;
! trigger.send_event = FALSE;
! trigger.time = GDK_CURRENT_TIME;
! trigger.x = 0.0;
! trigger.y = 0.0;
! trigger.axes = NULL;
! trigger.state = 0;
! trigger.button = 0;
! trigger.device = NULL;
! trigger.x_root = 0.0;
! trigger.y_root = 0.0;

! if (mouse_pos)
! gtk_menu_popup_at_pointer(GTK_MENU(menu->submenu_id),
! (GdkEvent *)&trigger);
! else
! {
! gint origin_x, origin_y;
! GdkRectangle rect = { 0, 0, 0, 0 };

! gdk_window_get_origin(win, &origin_x, &origin_y);
! popup_menu_position_func(NULL, &rect.x, &rect.y, NULL, NULL);

! rect.x -= origin_x;
! rect.y -= origin_y;

! gtk_menu_popup_at_rect(GTK_MENU(menu->submenu_id),
! win,
! &rect,
! GDK_GRAVITY_SOUTH_EAST,
! GDK_GRAVITY_NORTH_WEST,
! (GdkEvent *)&trigger);
! }
# else
! gtk_menu_popup(GTK_MENU(menu->submenu_id),
! NULL, NULL,
! &popup_menu_position_func, NULL,
! 0U, (guint32)GDK_CURRENT_TIME);
# endif
- }
}

#endif // FEAT_MENU
--- 1994,2051 ----
popup_mouse_pos = mouse_pos;

menu = gui_find_menu(path_name);
+ if (menu == NULL || menu->submenu_id == NULL)
+ return;

# if GTK_CHECK_VERSION(3,22,2)
! GdkWindow * const win = gtk_widget_get_window(gui.drawarea);
! GdkEventButton trigger;

! // A pseudo event to have gtk_menu_popup_at_*() functions work. Since
! // the position where the menu pops up is automatically adjusted by
! // the functions, none of the fields x, y, x_root and y_root has to be
! // set to a specific value here; therefore, they are set to zero for
! // convenience.
! trigger.type = GDK_BUTTON_PRESS;
! trigger.window = win;
! trigger.send_event = FALSE;
! trigger.time = GDK_CURRENT_TIME;
! trigger.x = 0.0;
! trigger.y = 0.0;
! trigger.axes = NULL;
! trigger.state = 0;
! trigger.button = 0;
! trigger.device = NULL;
! trigger.x_root = 0.0;
! trigger.y_root = 0.0;

! if (mouse_pos)
! gtk_menu_popup_at_pointer(GTK_MENU(menu->submenu_id),
! (GdkEvent *)&trigger);
! else
! {
! gint origin_x, origin_y;
! GdkRectangle rect = { 0, 0, 0, 0 };

! gdk_window_get_origin(win, &origin_x, &origin_y);
! popup_menu_position_func(NULL, &rect.x, &rect.y, NULL, NULL);

! rect.x -= origin_x;
! rect.y -= origin_y;

! gtk_menu_popup_at_rect(GTK_MENU(menu->submenu_id),
! win,
! &rect,
! GDK_GRAVITY_SOUTH_EAST,
! GDK_GRAVITY_NORTH_WEST,
! (GdkEvent *)&trigger);
! }
# else
! gtk_menu_popup(GTK_MENU(menu->submenu_id),
! NULL, NULL,
! &popup_menu_position_func, NULL,
! 0U, (guint32)GDK_CURRENT_TIME);
# endif
}

#endif // FEAT_MENU
*** ../vim-9.0.1157/src/gui_gtk_f.c 2021-10-17 11:27:49.000000000 +0100
--- src/gui_gtk_f.c 2023-01-08 13:38:57.105602496 +0000
***************
*** 188,200 ****
{
g_return_if_fail(GTK_IS_FORM(form));

! if (form->freeze_count)
{
! if (!(--form->freeze_count))
! {
! form_position_children(form);
! gtk_widget_queue_draw(GTK_WIDGET(form));
! }
}
}

--- 188,200 ----
{
g_return_if_fail(GTK_IS_FORM(form));

! if (!form->freeze_count)
! return;
!
! if (!(--form->freeze_count))
{
! form_position_children(form);
! gtk_widget_queue_draw(GTK_WIDGET(form));
}
}

***************
*** 610,641 ****
tmp_list = tmp_list->next;
}

! if (tmp_list)
! {
#if GTK_CHECK_VERSION(3,0,0)
! const gboolean was_visible = gtk_widget_get_visible(widget);
#endif
! if (child->window)
! {
! g_signal_handlers_disconnect_by_func(G_OBJECT(child->widget),
! FUNC2GENERIC(&form_child_map), child);
! g_signal_handlers_disconnect_by_func(G_OBJECT(child->widget),
! FUNC2GENERIC(&form_child_unmap), child);

! // FIXME: This will cause problems for reparenting NO_WINDOW
! // widgets out of a GtkForm
! gdk_window_set_user_data(child->window, NULL);
! gdk_window_destroy(child->window);
! }
! gtk_widget_unparent(widget);
#if GTK_CHECK_VERSION(3,0,0)
! if (was_visible)
! gtk_widget_queue_resize(GTK_WIDGET(container));
#endif
! form->children = g_list_remove_link(form->children, tmp_list);
! g_list_free_1(tmp_list);
! g_free(child);
! }
}

static void
--- 610,641 ----
tmp_list = tmp_list->next;
}

! if (tmp_list == NULL)
! return;
!
#if GTK_CHECK_VERSION(3,0,0)
! const gboolean was_visible = gtk_widget_get_visible(widget);
#endif
! if (child->window)
! {
! g_signal_handlers_disconnect_by_func(G_OBJECT(child->widget),
! FUNC2GENERIC(&form_child_map), child);
! g_signal_handlers_disconnect_by_func(G_OBJECT(child->widget),
! FUNC2GENERIC(&form_child_unmap), child);

! // FIXME: This will cause problems for reparenting NO_WINDOW
! // widgets out of a GtkForm
! gdk_window_set_user_data(child->window, NULL);
! gdk_window_destroy(child->window);
! }
! gtk_widget_unparent(widget);
#if GTK_CHECK_VERSION(3,0,0)
! if (was_visible)
! gtk_widget_queue_resize(GTK_WIDGET(container));
#endif
! form->children = g_list_remove_link(form->children, tmp_list);
! g_list_free_1(tmp_list);
! g_free(child);
}

static void
*** ../vim-9.0.1157/src/gui_gtk_x11.c 2022-12-01 19:40:51.796701665 +0000
--- src/gui_gtk_x11.c 2023-01-08 13:38:57.105602496 +0000
***************
*** 2435,2450 ****
GnomeClient *client;

client = gnome_master_client();

! if (client != NULL)
! {
! // Must use the deprecated gtk_signal_connect() for compatibility
! // with GNOME 1. Arrgh, zombies!
! gtk_signal_connect(GTK_OBJECT(client), "save_yourself",
! GTK_SIGNAL_FUNC(&sm_client_save_yourself), NULL);
! gtk_signal_connect(GTK_OBJECT(client), "die",
! GTK_SIGNAL_FUNC(&sm_client_die), NULL);
! }
}

#else // !USE_GNOME_SESSION
--- 2435,2449 ----
GnomeClient *client;

client = gnome_master_client();
+ if (client == NULL)
+ return;

! // Must use the deprecated gtk_signal_connect() for compatibility
! // with GNOME 1. Arrgh, zombies!
! gtk_signal_connect(GTK_OBJECT(client), "save_yourself",
! GTK_SIGNAL_FUNC(&sm_client_save_yourself), NULL);
! gtk_signal_connect(GTK_OBJECT(client), "die",
! GTK_SIGNAL_FUNC(&sm_client_die), NULL);
}

#else // !USE_GNOME_SESSION
***************
*** 3379,3391 ****
gint idx,
gpointer data UNUSED)
{
! if (!ignore_tabline_evt)
! {
! if ((tabpage_index(curtab) - 1) < idx)
! tabpage_move(idx + 1);
! else
! tabpage_move(idx);
! }
}
# endif

--- 3378,3390 ----
gint idx,
gpointer data UNUSED)
{
! if (ignore_tabline_evt)
! return;
!
! if ((tabpage_index(curtab) - 1) < idx)
! tabpage_move(idx + 1);
! else
! tabpage_move(idx);
}
# endif

***************
*** 4069,4083 ****
void
gui_mch_forked(void)
{
! if (using_gnome)
! {
! GnomeClient *client;

! client = gnome_master_client();

! if (client != NULL)
! gnome_client_set_process_id(client, getpid());
! }
}
#endif // USE_GNOME_SESSION

--- 4068,4082 ----
void
gui_mch_forked(void)
{
! if (!using_gnome)
! return;
!
! GnomeClient *client;

! client = gnome_master_client();

! if (client != NULL)
! gnome_client_set_process_id(client, getpid());
}
#endif // USE_GNOME_SESSION

***************
*** 6860,6870 ****
void
clip_mch_lose_selection(Clipboard_T *cbd UNUSED)
{
! if (!in_selection_clear_event)
! {
! gtk_selection_owner_set(NULL, cbd->gtk_sel_atom, gui.event_time);
! gui_mch_update();
! }
}

/*
--- 6859,6869 ----
void
clip_mch_lose_selection(Clipboard_T *cbd UNUSED)
{
! if (in_selection_clear_event)
! return;
!
! gtk_selection_owner_set(NULL, cbd->gtk_sel_atom, gui.event_time);
! gui_mch_update();
}

/*
***************
*** 7029,7049 ****
void
gui_mch_mousehide(int hide)
{
! if (gui.pointer_hidden != hide)
{
! gui.pointer_hidden = hide;
! if (gtk_widget_get_window(gui.drawarea) && gui.blank_pointer != NULL)
! {
! if (hide)
! gdk_window_set_cursor(gtk_widget_get_window(gui.drawarea),
! gui.blank_pointer);
! else
#ifdef FEAT_MOUSESHAPE
! mch_set_mouse_shape(last_shape);
#else
! gdk_window_set_cursor(gtk_widget_get_window(gui.drawarea), NULL);
#endif
- }
}
}

--- 7028,7048 ----
void
gui_mch_mousehide(int hide)
{
! if (gui.pointer_hidden == hide)
! return;
!
! gui.pointer_hidden = hide;
! if (gtk_widget_get_window(gui.drawarea) && gui.blank_pointer != NULL)
{
! if (hide)
! gdk_window_set_cursor(gtk_widget_get_window(gui.drawarea),
! gui.blank_pointer);
! else
#ifdef FEAT_MOUSESHAPE
! mch_set_mouse_shape(last_shape);
#else
! gdk_window_set_cursor(gtk_widget_get_window(gui.drawarea), NULL);
#endif
}
}

***************
*** 7132,7272 ****

sign = (GdkPixbuf *)sign_get_image(typenr);

! if (sign != NULL && gui.drawarea != NULL
! && gtk_widget_get_window(gui.drawarea) != NULL)
! {
! int width;
! int height;
! int xoffset;
! int yoffset;
! int need_scale;

! width = gdk_pixbuf_get_width(sign);
! height = gdk_pixbuf_get_height(sign);
! /*
! * Decide whether we need to scale. Allow one pixel of border
! * width to be cut off, in order to avoid excessive scaling for
! * tiny differences in font size.
! * Do scale to fit the height to avoid gaps because of linespacing.
! */
! need_scale = (width > SIGN_WIDTH + 2
! || height != SIGN_HEIGHT
! || (width < 3 * SIGN_WIDTH / 4
! && height < 3 * SIGN_HEIGHT / 4));
! if (need_scale)
! {
! double aspect;
! int w = width;
! int h = height;
!
! // Keep the original aspect ratio
! aspect = (double)height / (double)width;
! width = (double)SIGN_WIDTH * SIGN_ASPECT / aspect;
! width = MIN(width, SIGN_WIDTH);
! if (((double)(MAX(height, SIGN_HEIGHT)) /
! (double)(MIN(height, SIGN_HEIGHT))) < 1.15)
! {
! // Change the aspect ratio by at most 15% to fill the
! // available space completely.
! height = (double)SIGN_HEIGHT * SIGN_ASPECT / aspect;
! height = MIN(height, SIGN_HEIGHT);
! }
! else
! height = (double)width * aspect;

! if (w == width && h == height)
! {
! // no change in dimensions; don't decrease reference counter
! // (below)
! need_scale = FALSE;
! }
! else
! {
! // This doesn't seem to be worth caching, and doing so would
! // complicate the code quite a bit.
! sign = gdk_pixbuf_scale_simple(sign, width, height,
! GDK_INTERP_BILINEAR);
! if (sign == NULL)
! return; // out of memory
! }
}

! // The origin is the upper-left corner of the pixmap. Therefore
! // these offset may become negative if the pixmap is smaller than
! // the 2x1 cells reserved for the sign icon.
! xoffset = (width - SIGN_WIDTH) / 2;
! yoffset = (height - SIGN_HEIGHT) / 2;

# if GTK_CHECK_VERSION(3,0,0)
! {
! cairo_t *cr;
! cairo_surface_t *bg_surf;
! cairo_t *bg_cr;
! cairo_surface_t *sign_surf;
! cairo_t *sign_cr;
!
! cr = cairo_create(gui.surface);
!
! bg_surf = cairo_surface_create_similar(gui.surface,
! cairo_surface_get_content(gui.surface),
! SIGN_WIDTH, SIGN_HEIGHT);
! bg_cr = cairo_create(bg_surf);
! cairo_set_source_rgba(bg_cr,
! gui.bgcolor->red, gui.bgcolor->green, gui.bgcolor->blue,
! gui.bgcolor->alpha);
! cairo_paint(bg_cr);
!
! sign_surf = cairo_surface_create_similar(gui.surface,
! cairo_surface_get_content(gui.surface),
! SIGN_WIDTH, SIGN_HEIGHT);
! sign_cr = cairo_create(sign_surf);
! gdk_cairo_set_source_pixbuf(sign_cr, sign, -xoffset, -yoffset);
! cairo_paint(sign_cr);
!
! cairo_set_operator(sign_cr, CAIRO_OPERATOR_DEST_OVER);
! cairo_set_source_surface(sign_cr, bg_surf, 0, 0);
! cairo_paint(sign_cr);
!
! cairo_set_source_surface(cr, sign_surf, FILL_X(col), FILL_Y(row));
! cairo_paint(cr);
!
! cairo_destroy(sign_cr);
! cairo_surface_destroy(sign_surf);
! cairo_destroy(bg_cr);
! cairo_surface_destroy(bg_surf);
! cairo_destroy(cr);

! gtk_widget_queue_draw_area(gui.drawarea,
! FILL_X(col), FILL_Y(col), width, height);

! }
# else // !GTK_CHECK_VERSION(3,0,0)
! gdk_gc_set_foreground(gui.text_gc, gui.bgcolor);

! gdk_draw_rectangle(gui.drawarea->window,
! gui.text_gc,
! TRUE,
! FILL_X(col),
! FILL_Y(row),
! SIGN_WIDTH,
! SIGN_HEIGHT);

! gdk_pixbuf_render_to_drawable_alpha(sign,
! gui.drawarea->window,
! MAX(0, xoffset),
! MAX(0, yoffset),
! FILL_X(col) - MIN(0, xoffset),
! FILL_Y(row) - MIN(0, yoffset),
! MIN(width, SIGN_WIDTH),
! MIN(height, SIGN_HEIGHT),
! GDK_PIXBUF_ALPHA_BILEVEL,
! 127,
! GDK_RGB_DITHER_NORMAL,
! 0, 0);
# endif // !GTK_CHECK_VERSION(3,0,0)
! if (need_scale)
! g_object_unref(sign);
! }
}

void *
--- 7131,7271 ----

sign = (GdkPixbuf *)sign_get_image(typenr);

! if (sign == NULL || gui.drawarea == NULL
! || gtk_widget_get_window(gui.drawarea) == NULL)
! return;

! int width;
! int height;
! int xoffset;
! int yoffset;
! int need_scale;

! width = gdk_pixbuf_get_width(sign);
! height = gdk_pixbuf_get_height(sign);
! /*
! * Decide whether we need to scale. Allow one pixel of border
! * width to be cut off, in order to avoid excessive scaling for
! * tiny differences in font size.
! * Do scale to fit the height to avoid gaps because of linespacing.
! */
! need_scale = (width > SIGN_WIDTH + 2
! || height != SIGN_HEIGHT
! || (width < 3 * SIGN_WIDTH / 4
! && height < 3 * SIGN_HEIGHT / 4));
! if (need_scale)
! {
! double aspect;
! int w = width;
! int h = height;
!
! // Keep the original aspect ratio
! aspect = (double)height / (double)width;
! width = (double)SIGN_WIDTH * SIGN_ASPECT / aspect;
! width = MIN(width, SIGN_WIDTH);
! if (((double)(MAX(height, SIGN_HEIGHT)) /
! (double)(MIN(height, SIGN_HEIGHT))) < 1.15)
! {
! // Change the aspect ratio by at most 15% to fill the
! // available space completely.
! height = (double)SIGN_HEIGHT * SIGN_ASPECT / aspect;
! height = MIN(height, SIGN_HEIGHT);
}
+ else
+ height = (double)width * aspect;
+
+ if (w == width && h == height)
+ {
+ // no change in dimensions; don't decrease reference counter
+ // (below)
+ need_scale = FALSE;
+ }
+ else
+ {
+ // This doesn't seem to be worth caching, and doing so would
+ // complicate the code quite a bit.
+ sign = gdk_pixbuf_scale_simple(sign, width, height,
+ GDK_INTERP_BILINEAR);
+ if (sign == NULL)
+ return; // out of memory
+ }
+ }

! // The origin is the upper-left corner of the pixmap. Therefore
! // these offset may become negative if the pixmap is smaller than
! // the 2x1 cells reserved for the sign icon.
! xoffset = (width - SIGN_WIDTH) / 2;
! yoffset = (height - SIGN_HEIGHT) / 2;

# if GTK_CHECK_VERSION(3,0,0)
! {
! cairo_t *cr;
! cairo_surface_t *bg_surf;
! cairo_t *bg_cr;
! cairo_surface_t *sign_surf;
! cairo_t *sign_cr;

! cr = cairo_create(gui.surface);

! bg_surf = cairo_surface_create_similar(gui.surface,
! cairo_surface_get_content(gui.surface),
! SIGN_WIDTH, SIGN_HEIGHT);
! bg_cr = cairo_create(bg_surf);
! cairo_set_source_rgba(bg_cr,
! gui.bgcolor->red, gui.bgcolor->green, gui.bgcolor->blue,
! gui.bgcolor->alpha);
! cairo_paint(bg_cr);
!
! sign_surf = cairo_surface_create_similar(gui.surface,
! cairo_surface_get_content(gui.surface),
! SIGN_WIDTH, SIGN_HEIGHT);
! sign_cr = cairo_create(sign_surf);
! gdk_cairo_set_source_pixbuf(sign_cr, sign, -xoffset, -yoffset);
! cairo_paint(sign_cr);
!
! cairo_set_operator(sign_cr, CAIRO_OPERATOR_DEST_OVER);
! cairo_set_source_surface(sign_cr, bg_surf, 0, 0);
! cairo_paint(sign_cr);
!
! cairo_set_source_surface(cr, sign_surf, FILL_X(col), FILL_Y(row));
! cairo_paint(cr);
!
! cairo_destroy(sign_cr);
! cairo_surface_destroy(sign_surf);
! cairo_destroy(bg_cr);
! cairo_surface_destroy(bg_surf);
! cairo_destroy(cr);
!
! gtk_widget_queue_draw_area(gui.drawarea,
! FILL_X(col), FILL_Y(col), width, height);
!
! }
# else // !GTK_CHECK_VERSION(3,0,0)
! gdk_gc_set_foreground(gui.text_gc, gui.bgcolor);

! gdk_draw_rectangle(gui.drawarea->window,
! gui.text_gc,
! TRUE,
! FILL_X(col),
! FILL_Y(row),
! SIGN_WIDTH,
! SIGN_HEIGHT);

! gdk_pixbuf_render_to_drawable_alpha(sign,
! gui.drawarea->window,
! MAX(0, xoffset),
! MAX(0, yoffset),
! FILL_X(col) - MIN(0, xoffset),
! FILL_Y(row) - MIN(0, yoffset),
! MIN(width, SIGN_WIDTH),
! MIN(height, SIGN_HEIGHT),
! GDK_PIXBUF_ALPHA_BILEVEL,
! 127,
! GDK_RGB_DITHER_NORMAL,
! 0, 0);
# endif // !GTK_CHECK_VERSION(3,0,0)
! if (need_scale)
! g_object_unref(sign);
}

void *
*** ../vim-9.0.1157/src/gui_motif.c 2022-10-04 16:23:39.014042183 +0100
--- src/gui_motif.c 2023-01-08 13:38:57.105602496 +0000
***************
*** 979,992 ****
XmString label;

// Add accelerator text, if there is one
! if (menu->actext != NULL && menu->id != (Widget)0)
! {
! label = XmStringCreate((char *)menu->actext, STRING_TAG);
! if (label == NULL)
! return;
! XtVaSetValues(menu->id, XmNacceleratorText, label, NULL);
! XmStringFree(label);
! }
}

void
--- 979,992 ----
XmString label;

// Add accelerator text, if there is one
! if (menu->actext == NULL || menu->id == (Widget)0)
! return;
!
! label = XmStringCreate((char *)menu->actext, STRING_TAG);
! if (label == NULL)
! return;
! XtVaSetValues(menu->id, XmNacceleratorText, label, NULL);
! XmStringFree(label);
}

void
***************
*** 1573,1616 ****
menu->submenu_id = (Widget)0;
}

! if (menu->id != (Widget)0)
! {
! Widget parent;

! parent = XtParent(menu->id);
#if defined(FEAT_TOOLBAR) && defined(FEAT_BEVAL_GUI)
! if (parent == toolBar && menu->tip != NULL)
! {
! // We try to destroy this before the actual menu, because there are
! // callbacks, etc. that will be unregistered during the tooltip
! // destruction.
! //
! // If you call "gui_mch_destroy_beval_area()" after destroying
! // menu->id, then the tooltip's window will have already been
! // deallocated by Xt, and unknown behaviour will ensue (probably
! // a core dump).
! gui_mch_destroy_beval_area(menu->tip);
! menu->tip = NULL;
! }
! #endif
! XtDestroyWidget(menu->id);
! menu->id = (Widget)0;
! if (parent == menuBar)
! gui_mch_compute_menu_height((Widget)0);
#ifdef FEAT_TOOLBAR
! else if (parent == toolBar)
! {
! Cardinal num_children;

! // When removing last toolbar item, don't display the toolbar.
! XtVaGetValues(toolBar, XmNnumChildren, &num_children, NULL);
! if (num_children == 0)
! gui_mch_show_toolbar(FALSE);
! else
! gui.toolbar_height = gui_mch_compute_toolbar_height();
! }
! #endif
}
}

void
--- 1573,1616 ----
menu->submenu_id = (Widget)0;
}

! if (menu->id == (Widget)0)
! return;

! Widget parent;
!
! parent = XtParent(menu->id);
#if defined(FEAT_TOOLBAR) && defined(FEAT_BEVAL_GUI)
! if (parent == toolBar && menu->tip != NULL)
! {
! // We try to destroy this before the actual menu, because there are
! // callbacks, etc. that will be unregistered during the tooltip
! // destruction.
! //
! // If you call "gui_mch_destroy_beval_area()" after destroying
! // menu->id, then the tooltip's window will have already been
! // deallocated by Xt, and unknown behaviour will ensue (probably
! // a core dump).
! gui_mch_destroy_beval_area(menu->tip);
! menu->tip = NULL;
! }
! #endif
! XtDestroyWidget(menu->id);
! menu->id = (Widget)0;
! if (parent == menuBar)
! gui_mch_compute_menu_height((Widget)0);
#ifdef FEAT_TOOLBAR
! else if (parent == toolBar)
! {
! Cardinal num_children;

! // When removing last toolbar item, don't display the toolbar.
! XtVaGetValues(toolBar, XmNnumChildren, &num_children, NULL);
! if (num_children == 0)
! gui_mch_show_toolbar(FALSE);
! else
! gui.toolbar_height = gui_mch_compute_toolbar_height();
}
+ #endif
}

void
***************
*** 1630,1648 ****
void
gui_mch_def_colors(void)
{
! if (gui.in_use)
! {
! gui.menu_fg_pixel = gui_get_color((char_u *)gui.rsrc_menu_fg_name);
! gui.menu_bg_pixel = gui_get_color((char_u *)gui.rsrc_menu_bg_name);
! gui.scroll_fg_pixel = gui_get_color((char_u *)gui.rsrc_scroll_fg_name);
! gui.scroll_bg_pixel = gui_get_color((char_u *)gui.rsrc_scroll_bg_name);
#ifdef FEAT_BEVAL_GUI
! gui.tooltip_fg_pixel =
! gui_get_color((char_u *)gui.rsrc_tooltip_fg_name);
! gui.tooltip_bg_pixel =
! gui_get_color((char_u *)gui.rsrc_tooltip_bg_name);
#endif
- }
}


--- 1630,1648 ----
void
gui_mch_def_colors(void)
{
! if (!gui.in_use)
! return;
!
! gui.menu_fg_pixel = gui_get_color((char_u *)gui.rsrc_menu_fg_name);
! gui.menu_bg_pixel = gui_get_color((char_u *)gui.rsrc_menu_bg_name);
! gui.scroll_fg_pixel = gui_get_color((char_u *)gui.rsrc_scroll_fg_name);
! gui.scroll_bg_pixel = gui_get_color((char_u *)gui.rsrc_scroll_bg_name);
#ifdef FEAT_BEVAL_GUI
! gui.tooltip_fg_pixel =
! gui_get_color((char_u *)gui.rsrc_tooltip_fg_name);
! gui.tooltip_bg_pixel =
! gui_get_color((char_u *)gui.rsrc_tooltip_bg_name);
#endif
}


***************
*** 1674,1703 ****
int w,
int h)
{
! if (sb->id != (Widget)0)
{
! if (sb->type == SBAR_LEFT || sb->type == SBAR_RIGHT)
! {
! if (y == 0)
! h -= gui.border_offset;
! else
! y -= gui.border_offset;
! XtVaSetValues(sb->id,
! XmNtopOffset, y,
! XmNbottomOffset, -y - h,
! XmNwidth, w,
! NULL);
! }
else
! XtVaSetValues(sb->id,
! XmNtopOffset, y,
! XmNleftOffset, x,
! XmNrightOffset, gui.which_scrollbars[SBAR_RIGHT]
! ? gui.scrollbar_width : 0,
! XmNheight, h,
! NULL);
! XtManageChild(sb->id);
}
}

int
--- 1674,1703 ----
int w,
int h)
{
! if (sb->id == (Widget)0)
! return;
!
! if (sb->type == SBAR_LEFT || sb->type == SBAR_RIGHT)
{
! if (y == 0)
! h -= gui.border_offset;
else
! y -= gui.border_offset;
! XtVaSetValues(sb->id,
! XmNtopOffset, y,
! XmNbottomOffset, -y - h,
! XmNwidth, w,
! NULL);
}
+ else
+ XtVaSetValues(sb->id,
+ XmNtopOffset, y,
+ XmNleftOffset, x,
+ XmNrightOffset, gui.which_scrollbars[SBAR_RIGHT]
+ ? gui.scrollbar_width : 0,
+ XmNheight, h,
+ NULL);
+ XtManageChild(sb->id);
}

int
***************
*** 1732,1783 ****
Arg args[16];
int n;

! if (sb->id != (Widget)0)
{
! n = 0;
! if (flag)
{
switch (sb->type)
{
case SBAR_LEFT:
! XtSetArg(args[n], XmNleftOffset, gui.scrollbar_width); n++;
break;

case SBAR_RIGHT:
! XtSetArg(args[n], XmNrightOffset, gui.scrollbar_width); n++;
break;

case SBAR_BOTTOM:
! XtSetArg(args[n], XmNbottomOffset, gui.scrollbar_height);n++;
break;
}
XtSetValues(textArea, args, n);
- XtManageChild(sb->id);
- }
- else
- {
- if (!gui.which_scrollbars[sb->type])
- {
- // The scrollbars of this type are all disabled, adjust the
- // textArea attachment offset.
- switch (sb->type)
- {
- case SBAR_LEFT:
- XtSetArg(args[n], XmNleftOffset, 0); n++;
- break;
-
- case SBAR_RIGHT:
- XtSetArg(args[n], XmNrightOffset, 0); n++;
- break;
-
- case SBAR_BOTTOM:
- XtSetArg(args[n], XmNbottomOffset, 0);n++;
- break;
- }
- XtSetValues(textArea, args, n);
- }
- XtUnmanageChild(sb->id);
}
}
}

--- 1732,1783 ----
Arg args[16];
int n;

! if (sb->id == (Widget)0)
! return;
!
! n = 0;
! if (flag)
{
! switch (sb->type)
! {
! case SBAR_LEFT:
! XtSetArg(args[n], XmNleftOffset, gui.scrollbar_width); n++;
! break;
!
! case SBAR_RIGHT:
! XtSetArg(args[n], XmNrightOffset, gui.scrollbar_width); n++;
! break;
!
! case SBAR_BOTTOM:
! XtSetArg(args[n], XmNbottomOffset, gui.scrollbar_height);n++;
! break;
! }
! XtSetValues(textArea, args, n);
! XtManageChild(sb->id);
! }
! else
! {
! if (!gui.which_scrollbars[sb->type])
{
+ // The scrollbars of this type are all disabled, adjust the
+ // textArea attachment offset.
switch (sb->type)
{
case SBAR_LEFT:
! XtSetArg(args[n], XmNleftOffset, 0); n++;
break;

case SBAR_RIGHT:
! XtSetArg(args[n], XmNrightOffset, 0); n++;
break;

case SBAR_BOTTOM:
! XtSetArg(args[n], XmNbottomOffset, 0);n++;
break;
}
XtSetValues(textArea, args, n);
}
+ XtUnmanageChild(sb->id);
}
}

***************
*** 1817,1833 ****

sb->id = XtCreateWidget("scrollBar",
xmScrollBarWidgetClass, textAreaForm, args, n);

! if (sb->id != (Widget)0)
! {
! gui_mch_set_scrollbar_colors(sb);
! XtAddCallback(sb->id, XmNvalueChangedCallback,
! scroll_cb, (XtPointer)sb->ident);
! XtAddCallback(sb->id, XmNdragCallback,
! scroll_cb, (XtPointer)sb->ident);
! XtAddEventHandler(sb->id, KeyPressMask, FALSE, gui_x11_key_hit_cb,
(XtPointer)0);
- }
}

void
--- 1817,1832 ----

sb->id = XtCreateWidget("scrollBar",
xmScrollBarWidgetClass, textAreaForm, args, n);
+ if (sb->id == (Widget)0)
+ return;

! gui_mch_set_scrollbar_colors(sb);
! XtAddCallback(sb->id, XmNvalueChangedCallback,
! scroll_cb, (XtPointer)sb->ident);
! XtAddCallback(sb->id, XmNdragCallback,
! scroll_cb, (XtPointer)sb->ident);
! XtAddEventHandler(sb->id, KeyPressMask, FALSE, gui_x11_key_hit_cb,
(XtPointer)0);
}

void
*** ../vim-9.0.1157/src/gui_photon.c 2021-12-31 20:47:48.000000000 +0000
--- src/gui_photon.c 2023-01-08 13:38:57.109602493 +0000
***************
*** 992,1010 ****
char **new_titles = NULL;

new_titles = ALLOC_MULT(char *, (num_panels + 1));
! if (new_titles != NULL)
! {
! if (num_panels > 0)
! memcpy(new_titles, panel_titles, num_panels * sizeof(char **));

! new_titles[ num_panels++ ] = name;

! PtSetResource(gui.vimPanelGroup, Pt_ARG_PG_PANEL_TITLES, new_titles,
! num_panels);

! vim_free(panel_titles);
! panel_titles = new_titles;
! }
}

static void
--- 992,1010 ----
char **new_titles = NULL;

new_titles = ALLOC_MULT(char *, (num_panels + 1));
! if (new_titles == NULL)
! return;

! if (num_panels > 0)
! memcpy(new_titles, panel_titles, num_panels * sizeof(char **));

! new_titles[ num_panels++ ] = name;

! PtSetResource(gui.vimPanelGroup, Pt_ARG_PG_PANEL_TITLES, new_titles,
! num_panels);
!
! vim_free(panel_titles);
! panel_titles = new_titles;
}

static void
***************
*** 1901,1921 ****
void
gui_mch_mousehide(int hide)
{
! if (gui.pointer_hidden != hide)
! {
! gui.pointer_hidden = hide;
#ifdef FEAT_MOUSESHAPE
! if (hide)
! PtSetResource(gui.vimTextArea, Pt_ARG_CURSOR_TYPE,
! Ph_CURSOR_NONE, 0);
! else
! mch_set_mouse_shape(last_shape);
! #else
PtSetResource(gui.vimTextArea, Pt_ARG_CURSOR_TYPE,
! (hide == MOUSE_SHOW) ? GUI_PH_MOUSE_TYPE : Ph_CURSOR_NONE,
! 0);
#endif
- }
}

void
--- 1901,1921 ----
void
gui_mch_mousehide(int hide)
{
! if (gui.pointer_hidden == hide)
! return;
!
! gui.pointer_hidden = hide;
#ifdef FEAT_MOUSESHAPE
! if (hide)
PtSetResource(gui.vimTextArea, Pt_ARG_CURSOR_TYPE,
! Ph_CURSOR_NONE, 0);
! else
! mch_set_mouse_shape(last_shape);
! #else
! PtSetResource(gui.vimTextArea, Pt_ARG_CURSOR_TYPE,
! (hide == MOUSE_SHOW) ? GUI_PH_MOUSE_TYPE : Ph_CURSOR_NONE,
! 0);
#endif
}

void
*** ../vim-9.0.1157/src/gui_w32.c 2022-12-30 16:54:53.452987924 +0000
--- src/gui_w32.c 2023-01-08 13:38:57.109602493 +0000
***************
*** 434,445 ****
static void
directx_binddc(void)
{
! if (s_textArea != NULL)
! {
! RECT rect;
! GetClientRect(s_textArea, &rect);
! DWriteContext_BindDC(s_dwc, s_hdc, &rect);
! }
}
#endif

--- 434,445 ----
static void
directx_binddc(void)
{
! if (s_textArea == NULL)
! return;
!
! RECT rect;
! GetClientRect(s_textArea, &rect);
! DWriteContext_BindDC(s_dwc, s_hdc, &rect);
}
#endif

***************
*** 663,676 ****
{
MSG msg;

! if (blink_timer != 0)
! {
! KillTimer(NULL, blink_timer);
! // Eat spurious WM_TIMER messages
! while (PeekMessageW(&msg, s_hwnd, WM_TIMER, WM_TIMER, PM_REMOVE))
! ;
! blink_timer = 0;
! }
}

/*
--- 663,676 ----
{
MSG msg;

! if (blink_timer == 0)
! return;
!
! KillTimer(NULL, blink_timer);
! // Eat spurious WM_TIMER messages
! while (PeekMessageW(&msg, s_hwnd, WM_TIMER, WM_TIMER, PM_REMOVE))
! ;
! blink_timer = 0;
}

/*
***************
*** 888,894 ****
modifiers = get_active_modifiers();

ch = simplify_key(ch, &modifiers);
!
// Some keys need adjustment when the Ctrl modifier is used.
++no_reduce_keys;
ch = may_adjust_key_for_ctrl(modifiers, ch);
--- 888,894 ----
modifiers = get_active_modifiers();

ch = simplify_key(ch, &modifiers);
!
// Some keys need adjustment when the Ctrl modifier is used.
++no_reduce_keys;
ch = may_adjust_key_for_ctrl(modifiers, ch);
***************
*** 1034,1096 ****
else
button = MOUSE_LEFT;
}
- if (button >= 0)
- {
- repeated_click = ((int)(currentTime - s_prevTime) < p_mouset);

/*
! * Holding down the left and right buttons simulates pushing the middle
! * button.
*/
! if (repeated_click
! && ((button == MOUSE_LEFT && s_button_pending == MOUSE_RIGHT)
! || (button == MOUSE_RIGHT
! && s_button_pending == MOUSE_LEFT)))
{
! /*
! * Hmm, gui.c will ignore more than one button down at a time, so
! * pretend we let go of it first.
! */
! gui_send_mouse_event(MOUSE_RELEASE, x, y, FALSE, 0x0);
! button = MOUSE_MIDDLE;
! repeated_click = FALSE;
s_button_pending = -1;
- _OnMouseEvent(button, x, y, repeated_click, keyFlags);
}
! else if ((repeated_click)
! || (mouse_model_popup() && (button == MOUSE_RIGHT)))
! {
! if (s_button_pending > -1)
! {
! _OnMouseEvent(s_button_pending, x, y, FALSE, keyFlags);
! s_button_pending = -1;
! }
! // TRACE("Button down at x %d, y %d\n", x, y);
! _OnMouseEvent(button, x, y, repeated_click, keyFlags);
! }
! else
! {
! /*
! * If this is the first press (i.e. not a multiple click) don't
! * action immediately, but store and wait for:
! * i) button-up
! * ii) mouse move
! * iii) another button press
! * before using it.
! * This enables us to make left+right simulate middle button,
! * without left or right being actioned first. The side-effect is
! * that if you click and hold the mouse without dragging, the
! * cursor doesn't move until you release the button. In practice
! * this is hardly a problem.
! */
! s_button_pending = button;
! s_x_pending = x;
! s_y_pending = y;
! s_kFlags_pending = keyFlags;
! }
!
! s_prevTime = currentTime;
}
}

static void
--- 1034,1097 ----
else
button = MOUSE_LEFT;
}

+ if (button < 0)
+ return;
+
+ repeated_click = ((int)(currentTime - s_prevTime) < p_mouset);
+
+ /*
+ * Holding down the left and right buttons simulates pushing the middle
+ * button.
+ */
+ if (repeated_click
+ && ((button == MOUSE_LEFT && s_button_pending == MOUSE_RIGHT)
+ || (button == MOUSE_RIGHT
+ && s_button_pending == MOUSE_LEFT)))
+ {
/*
! * Hmm, gui.c will ignore more than one button down at a time, so
! * pretend we let go of it first.
*/
! gui_send_mouse_event(MOUSE_RELEASE, x, y, FALSE, 0x0);
! button = MOUSE_MIDDLE;
! repeated_click = FALSE;
! s_button_pending = -1;
! _OnMouseEvent(button, x, y, repeated_click, keyFlags);
! }
! else if ((repeated_click)
! || (mouse_model_popup() && (button == MOUSE_RIGHT)))
! {
! if (s_button_pending > -1)
{
! _OnMouseEvent(s_button_pending, x, y, FALSE, keyFlags);
s_button_pending = -1;
}
! // TRACE("Button down at x %d, y %d\n", x, y);
! _OnMouseEvent(button, x, y, repeated_click, keyFlags);
! }
! else
! {
! /*
! * If this is the first press (i.e. not a multiple click) don't
! * action immediately, but store and wait for:
! * i) button-up
! * ii) mouse move
! * iii) another button press
! * before using it.
! * This enables us to make left+right simulate middle button,
! * without left or right being actioned first. The side-effect is
! * that if you click and hold the mouse without dragging, the
! * cursor doesn't move until you release the button. In practice
! * this is hardly a problem.
! */
! s_button_pending = button;
! s_x_pending = x;
! s_y_pending = y;
! s_kFlags_pending = keyFlags;
}
+
+ s_prevTime = currentTime;
}

static void
***************
*** 1233,1255 ****
flags = FRD_REPLACEALL;
}

! if (flags != 0)
! {
! char_u *p, *q;

! // Call the generic GUI function to do the actual work.
! if (s_findrep_struct.Flags & FR_WHOLEWORD)
! flags |= FRD_WHOLE_WORD;
! if (s_findrep_struct.Flags & FR_MATCHCASE)
! flags |= FRD_MATCH_CASE;
! down = (s_findrep_struct.Flags & FR_DOWN) != 0;
! p = utf16_to_enc(s_findrep_struct.lpstrFindWhat, NULL);
! q = utf16_to_enc(s_findrep_struct.lpstrReplaceWith, NULL);
! if (p != NULL && q != NULL)
! gui_do_findrepl(flags, p, q, down);
! vim_free(p);
! vim_free(q);
! }
}
#endif

--- 1234,1256 ----
flags = FRD_REPLACEALL;
}

! if (flags == 0)
! return;

! char_u *p, *q;
!
! // Call the generic GUI function to do the actual work.
! if (s_findrep_struct.Flags & FR_WHOLEWORD)
! flags |= FRD_WHOLE_WORD;
! if (s_findrep_struct.Flags & FR_MATCHCASE)
! flags |= FRD_MATCH_CASE;
! down = (s_findrep_struct.Flags & FR_DOWN) != 0;
! p = utf16_to_enc(s_findrep_struct.lpstrFindWhat, NULL);
! q = utf16_to_enc(s_findrep_struct.lpstrReplaceWith, NULL);
! if (p != NULL && q != NULL)
! gui_do_findrepl(flags, p, q, down);
! vim_free(p);
! vim_free(q);
}
#endif

***************
*** 2932,2942 ****
void
gui_mch_mousehide(int hide)
{
! if (hide != gui.pointer_hidden)
! {
! ShowCursor(!hide);
! gui.pointer_hidden = hide;
! }
}

#ifdef FEAT_MENU
--- 2933,2943 ----
void
gui_mch_mousehide(int hide)
{
! if (hide == gui.pointer_hidden)
! return;
!
! ShowCursor(!hide);
! gui.pointer_hidden = hide;
}

#ifdef FEAT_MENU
***************
*** 2993,3025 ****
_OnPaint(
HWND hwnd)
{
! if (!IsMinimized(hwnd))
! {
! PAINTSTRUCT ps;

! out_flush(); // make sure all output has been processed
! (void)BeginPaint(hwnd, &ps);

! // prevent multi-byte characters from misprinting on an invalid
! // rectangle
! if (has_mbyte)
! {
! RECT rect;

! GetClientRect(hwnd, &rect);
! ps.rcPaint.left = rect.left;
! ps.rcPaint.right = rect.right;
! }

! if (!IsRectEmpty(&ps.rcPaint))
! {
! gui_redraw(ps.rcPaint.left, ps.rcPaint.top,
! ps.rcPaint.right - ps.rcPaint.left + 1,
! ps.rcPaint.bottom - ps.rcPaint.top + 1);
! }

! EndPaint(hwnd, &ps);
}
}

static void
--- 2994,3026 ----
_OnPaint(
HWND hwnd)
{
! if (IsMinimized(hwnd))
! return;

! PAINTSTRUCT ps;

! out_flush(); // make sure all output has been processed
! (void)BeginPaint(hwnd, &ps);

! // prevent multi-byte characters from misprinting on an invalid
! // rectangle
! if (has_mbyte)
! {
! RECT rect;

! GetClientRect(hwnd, &rect);
! ps.rcPaint.left = rect.left;
! ps.rcPaint.right = rect.right;
! }

! if (!IsRectEmpty(&ps.rcPaint))
! {
! gui_redraw(ps.rcPaint.left, ps.rcPaint.top,
! ps.rcPaint.right - ps.rcPaint.left + 1,
! ps.rcPaint.bottom - ps.rcPaint.top + 1);
}
+
+ EndPaint(hwnd, &ps);
}

static void
***************
*** 3904,3924 ****

DragFinish(hDrop);

! if (fnames != NULL)
! {
! int kbd_modifiers = get_active_modifiers();

! if ((kbd_modifiers & MOD_MASK_SHIFT) != 0)
! modifiers |= MOUSE_SHIFT;
! if ((kbd_modifiers & MOD_MASK_CTRL) != 0)
! modifiers |= MOUSE_CTRL;
! if ((kbd_modifiers & MOD_MASK_ALT) != 0)
! modifiers |= MOUSE_ALT;

! gui_handle_drop(pt.x, pt.y, modifiers, fnames, cFiles);

! s_need_activate = TRUE;
! }
}

static int
--- 3905,3925 ----

DragFinish(hDrop);

! if (fnames == NULL)
! return;

! int kbd_modifiers = get_active_modifiers();

! if ((kbd_modifiers & MOD_MASK_SHIFT) != 0)
! modifiers |= MOUSE_SHIFT;
! if ((kbd_modifiers & MOD_MASK_CTRL) != 0)
! modifiers |= MOUSE_CTRL;
! if ((kbd_modifiers & MOD_MASK_ALT) != 0)
! modifiers |= MOUSE_ALT;

! gui_handle_drop(pt.x, pt.y, modifiers, fnames, cFiles);
!
! s_need_activate = TRUE;
}

static int
***************
*** 4461,4471 ****
static void
destroy_sizing_tip(void)
{
! if (hwndTip != NULL)
! {
! DestroyWindow(hwndTip);
! hwndTip = NULL;
! }
}

static int
--- 4462,4472 ----
static void
destroy_sizing_tip(void)
{
! if (hwndTip == NULL)
! return;
!
! DestroyWindow(hwndTip);
! hwndTip = NULL;
}

static int
***************
*** 5844,5907 ****
}
# endif

! if (pImmGetContext) // if NULL imm32.dll wasn't loaded (yet)
{
! if (p_imdisable)
{
! if (hImcOld == (HIMC)0)
! {
! hImcOld = pImmGetContext(s_hwnd);
! if (hImcOld)
! pImmAssociateContext(s_hwnd, (HIMC)0);
! }
! active = FALSE;
}
! else if (hImcOld != (HIMC)0)
{
! pImmAssociateContext(s_hwnd, hImcOld);
! hImcOld = (HIMC)0;
}
!
! hImc = pImmGetContext(s_hwnd);
! if (hImc)
{
! /*
! * for Korean ime
! */
! HKL hKL = GetKeyboardLayout(0);
!
! if (LOWORD(hKL) == MAKELANGID(LANG_KOREAN, SUBLANG_KOREAN))
{
! static DWORD dwConversionSaved = 0, dwSentenceSaved = 0;
! static BOOL bSaved = FALSE;
!
! if (active)
! {
! // if we have a saved conversion status, restore it
! if (bSaved)
! pImmSetConversionStatus(hImc, dwConversionSaved,
! dwSentenceSaved);
! bSaved = FALSE;
! }
! else
! {
! // save conversion status and disable korean
! if (pImmGetConversionStatus(hImc, &dwConversionSaved,
! &dwSentenceSaved))
! {
! bSaved = TRUE;
! pImmSetConversionStatus(hImc,
! dwConversionSaved & ~(IME_CMODE_NATIVE
! | IME_CMODE_FULLSHAPE),
! dwSentenceSaved);
! }
! }
}
-
- pImmSetOpenStatus(hImc, active);
- pImmReleaseContext(s_hwnd, hImc);
}
}
}

/*
--- 5845,5908 ----
}
# endif

! if (!pImmGetContext) // if NULL imm32.dll wasn't loaded (yet)
! return;
!
! if (p_imdisable)
{
! if (hImcOld == (HIMC)0)
{
! hImcOld = pImmGetContext(s_hwnd);
! if (hImcOld)
! pImmAssociateContext(s_hwnd, (HIMC)0);
}
! active = FALSE;
! }
! else if (hImcOld != (HIMC)0)
! {
! pImmAssociateContext(s_hwnd, hImcOld);
! hImcOld = (HIMC)0;
! }
!
! hImc = pImmGetContext(s_hwnd);
! if (!hImc)
! return;
!
! /*
! * for Korean ime
! */
! HKL hKL = GetKeyboardLayout(0);
!
! if (LOWORD(hKL) == MAKELANGID(LANG_KOREAN, SUBLANG_KOREAN))
! {
! static DWORD dwConversionSaved = 0, dwSentenceSaved = 0;
! static BOOL bSaved = FALSE;
!
! if (active)
{
! // if we have a saved conversion status, restore it
! if (bSaved)
! pImmSetConversionStatus(hImc, dwConversionSaved,
! dwSentenceSaved);
! bSaved = FALSE;
}
! else
{
! // save conversion status and disable korean
! if (pImmGetConversionStatus(hImc, &dwConversionSaved,
! &dwSentenceSaved))
{
! bSaved = TRUE;
! pImmSetConversionStatus(hImc,
! dwConversionSaved & ~(IME_CMODE_NATIVE
! | IME_CMODE_FULLSHAPE),
! dwSentenceSaved);
}
}
}
+
+ pImmSetOpenStatus(hImc, active);
+ pImmReleaseContext(s_hwnd, hImc);
}

/*
***************
*** 6459,6486 ****
{
vimmenu_T *menu = gui_find_menu(path_name);

! if (menu != NULL)
! {
! POINT p;

! // Find the position of the current cursor
! GetDCOrgEx(s_hdc, &p);
! if (mouse_pos)
! {
! int mx, my;

! gui_mch_getmouse(&mx, &my);
! p.x += mx;
! p.y += my;
! }
! else if (curwin != NULL)
! {
! p.x += TEXT_X(curwin->w_wincol + curwin->w_wcol + 1);
! p.y += TEXT_Y(W_WINROW(curwin) + curwin->w_wrow + 1);
! }
! msg_scroll = FALSE;
! gui_mch_show_popupmenu_at(menu, (int)p.x, (int)p.y);
}
}

# if defined(FEAT_TEAROFF) || defined(PROTO)
--- 6460,6487 ----
{
vimmenu_T *menu = gui_find_menu(path_name);

! if (menu == NULL)
! return;

! POINT p;

! // Find the position of the current cursor
! GetDCOrgEx(s_hdc, &p);
! if (mouse_pos)
! {
! int mx, my;
!
! gui_mch_getmouse(&mx, &my);
! p.x += mx;
! p.y += my;
}
+ else if (curwin != NULL)
+ {
+ p.x += TEXT_X(curwin->w_wincol + curwin->w_wcol + 1);
+ p.y += TEXT_Y(W_WINROW(curwin) + curwin->w_wrow + 1);
+ }
+ msg_scroll = FALSE;
+ gui_mch_show_popupmenu_at(menu, (int)p.x, (int)p.y);
}

# if defined(FEAT_TEAROFF) || defined(PROTO)
***************
*** 8274,8298 ****
static void
close_signicon_image(signicon_t *sign)
{
! if (sign)
! switch (sign->uType)
! {
! case IMAGE_BITMAP:
! DeleteObject((HGDIOBJ)sign->hImage);
! break;
! case IMAGE_CURSOR:
! DestroyCursor((HCURSOR)sign->hImage);
! break;
! case IMAGE_ICON:
! DestroyIcon((HICON)sign->hImage);
! break;
# ifdef FEAT_XPM_W32
! case IMAGE_XPM:
! DeleteObject((HBITMAP)sign->hImage);
! DeleteObject((HBITMAP)sign->hShape);
! break;
# endif
! }
}

void *
--- 8275,8301 ----
static void
close_signicon_image(signicon_t *sign)
{
! if (sign == NULL)
! return;
!
! switch (sign->uType)
! {
! case IMAGE_BITMAP:
! DeleteObject((HGDIOBJ)sign->hImage);
! break;
! case IMAGE_CURSOR:
! DestroyCursor((HCURSOR)sign->hImage);
! break;
! case IMAGE_ICON:
! DestroyIcon((HICON)sign->hImage);
! break;
# ifdef FEAT_XPM_W32
! case IMAGE_XPM:
! DeleteObject((HBITMAP)sign->hImage);
! DeleteObject((HBITMAP)sign->hShape);
! break;
# endif
! }
}

void *
***************
*** 8347,8357 ****
void
gui_mch_destroy_sign(void *sign)
{
! if (sign)
! {
! close_signicon_image((signicon_t *)sign);
! vim_free(sign);
! }
}
#endif

--- 8350,8360 ----
void
gui_mch_destroy_sign(void *sign)
{
! if (sign == NULL)
! return;
!
! close_signicon_image((signicon_t *)sign);
! vim_free(sign);
}
#endif

***************
*** 8561,8570 ****
if (pnmh->idFrom != ID_BEVAL_TOOLTIP) // it is not our tooltip
return;

! if (cur_beval != NULL)
{
- switch (pnmh->code)
- {
case TTN_SHOW:
break;
case TTN_POP: // Before tooltip disappear
--- 8564,8574 ----
if (pnmh->idFrom != ID_BEVAL_TOOLTIP) // it is not our tooltip
return;

! if (cur_beval == NULL)
! return;
!
! switch (pnmh->code)
{
case TTN_SHOW:
break;
case TTN_POP: // Before tooltip disappear
***************
*** 8589,8595 ****
info->uFlags |= TTF_DI_SETITEM;
}
break;
- }
}
}

--- 8593,8598 ----
*** ../vim-9.0.1157/src/gui_x11.c 2022-09-17 21:07:52.099993159 +0100
--- src/gui_x11.c 2023-01-08 13:38:57.109602493 +0000
***************
*** 2194,2204 ****
void
gui_mch_set_fg_color(guicolor_T color)
{
! if (color != prev_fg_color)
! {
! XSetForeground(gui.dpy, gui.text_gc, (Pixel)color);
! prev_fg_color = color;
! }
}

/*
--- 2194,2204 ----
void
gui_mch_set_fg_color(guicolor_T color)
{
! if (color == prev_fg_color)
! return;
!
! XSetForeground(gui.dpy, gui.text_gc, (Pixel)color);
! prev_fg_color = color;
}

/*
***************
*** 2207,2217 ****
void
gui_mch_set_bg_color(guicolor_T color)
{
! if (color != prev_bg_color)
! {
! XSetBackground(gui.dpy, gui.text_gc, (Pixel)color);
! prev_bg_color = color;
! }
}

/*
--- 2207,2217 ----
void
gui_mch_set_bg_color(guicolor_T color)
{
! if (color == prev_bg_color)
! return;
!
! XSetBackground(gui.dpy, gui.text_gc, (Pixel)color);
! prev_bg_color = color;
}

/*
***************
*** 2814,2831 ****
void
gui_mch_menu_grey(vimmenu_T *menu, int grey)
{
! if (menu->id != (Widget)0)
! {
! gui_mch_menu_hidden(menu, False);
! if (grey
#ifdef FEAT_GUI_MOTIF
! || !menu->sensitive
#endif
! )
! XtSetSensitive(menu->id, False);
! else
! XtSetSensitive(menu->id, True);
! }
}

/*
--- 2814,2831 ----
void
gui_mch_menu_grey(vimmenu_T *menu, int grey)
{
! if (menu->id == (Widget)0)
! return;
!
! gui_mch_menu_hidden(menu, False);
! if (grey
#ifdef FEAT_GUI_MOTIF
! || !menu->sensitive
#endif
! )
! XtSetSensitive(menu->id, False);
! else
! XtSetSensitive(menu->id, True);
}

/*
***************
*** 2834,2846 ****
void
gui_mch_menu_hidden(vimmenu_T *menu, int hidden)
{
! if (menu->id != (Widget)0)
! {
! if (hidden)
! XtUnmanageChild(menu->id);
! else
! XtManageChild(menu->id);
! }
}

/*
--- 2834,2846 ----
void
gui_mch_menu_hidden(vimmenu_T *menu, int hidden)
{
! if (menu->id == (Widget)0)
! return;
!
! if (hidden)
! XtUnmanageChild(menu->id);
! else
! XtManageChild(menu->id);
}

/*
***************
*** 3130,3144 ****
{
XImage *sign;

! if (gui.in_use && (sign = (XImage *)sign_get_image(typenr)) != NULL)
! {
! XClearArea(gui.dpy, gui.wid, TEXT_X(col), TEXT_Y(row) - sign->height,
! SIGN_WIDTH, gui.char_height, FALSE);
! XPutImage(gui.dpy, gui.wid, gui.text_gc, sign, 0, 0,
! TEXT_X(col) + (SIGN_WIDTH - sign->width) / 2,
! TEXT_Y(row) - sign->height,
! sign->width, sign->height);
! }
}

void *
--- 3130,3144 ----
{
XImage *sign;

! if (!gui.in_use || (sign = (XImage *)sign_get_image(typenr)) == NULL)
! return;
!
! XClearArea(gui.dpy, gui.wid, TEXT_X(col), TEXT_Y(row) - sign->height,
! SIGN_WIDTH, gui.char_height, FALSE);
! XPutImage(gui.dpy, gui.wid, gui.text_gc, sign, 0, 0,
! TEXT_X(col) + (SIGN_WIDTH - sign->width) / 2,
! TEXT_Y(row) - sign->height,
! sign->width, sign->height);
}

void *
***************
*** 3202,3219 ****
gui_mch_mousehide(
int hide) // TRUE = use blank ptr, FALSE = use parent ptr
{
! if (gui.pointer_hidden != hide)
! {
! gui.pointer_hidden = hide;
! if (hide)
! XDefineCursor(gui.dpy, gui.wid, gui.blank_pointer);
! else
#ifdef FEAT_MOUSESHAPE
! mch_set_mouse_shape(last_shape);
#else
! XUndefineCursor(gui.dpy, gui.wid);
#endif
- }
}

#if defined(FEAT_MOUSESHAPE) || defined(PROTO)
--- 3202,3219 ----
gui_mch_mousehide(
int hide) // TRUE = use blank ptr, FALSE = use parent ptr
{
! if (gui.pointer_hidden == hide)
! return;
!
! gui.pointer_hidden = hide;
! if (hide)
! XDefineCursor(gui.dpy, gui.wid, gui.blank_pointer);
! else
#ifdef FEAT_MOUSESHAPE
! mch_set_mouse_shape(last_shape);
#else
! XUndefineCursor(gui.dpy, gui.wid);
#endif
}

#if defined(FEAT_MOUSESHAPE) || defined(PROTO)
***************
*** 3280,3301 ****
void
gui_mch_menu_set_tip(vimmenu_T *menu)
{
! if (menu->id != NULL && menu->parent != NULL
! && menu_is_toolbar(menu->parent->name))
! {
! // Always destroy and create the balloon, in case the string was
! // changed.
! if (menu->tip != NULL)
! {
! gui_mch_destroy_beval_area(menu->tip);
! menu->tip = NULL;
! }
! if (menu->strings[MENU_INDEX_TIP] != NULL)
! menu->tip = gui_mch_create_beval_area(
! menu->id,
! menu->strings[MENU_INDEX_TIP],
! NULL,
! NULL);
! }
}
#endif
--- 3280,3301 ----
void
gui_mch_menu_set_tip(vimmenu_T *menu)
{
! if (menu->id == NULL || menu->parent == NULL
! || !menu_is_toolbar(menu->parent->name))
! return;
!
! // Always destroy and create the balloon, in case the string was
! // changed.
! if (menu->tip != NULL)
! {
! gui_mch_destroy_beval_area(menu->tip);
! menu->tip = NULL;
! }
! if (menu->strings[MENU_INDEX_TIP] != NULL)
! menu->tip = gui_mch_create_beval_area(
! menu->id,
! menu->strings[MENU_INDEX_TIP],
! NULL,
! NULL);
}
#endif
*** ../vim-9.0.1157/src/gui_xim.c 2022-11-24 00:08:58.465010528 +0000
--- src/gui_xim.c 2023-01-08 13:38:57.109602493 +0000
***************
*** 199,230 ****
void
xim_set_focus(int focus)
{
! if (xic != NULL)
! {
! if (focus)
! gtk_im_context_focus_in(xic);
! else
! gtk_im_context_focus_out(xic);
! }
}

void
im_set_position(int row, int col)
{
! if (xic != NULL)
! {
! GdkRectangle area;
!
! area.x = FILL_X(col);
! area.y = FILL_Y(row);
! area.width = gui.char_width * (mb_lefthalve(row, col) ? 2 : 1);
! area.height = gui.char_height;
!
! gtk_im_context_set_cursor_location(xic, &area);
!
! if (p_imst == IM_OVER_THE_SPOT)
! im_preedit_window_set_position();
! }
}

# if 0 || defined(PROTO) // apparently only used in gui_x11.c
--- 199,230 ----
void
xim_set_focus(int focus)
{
! if (xic == NULL)
! return;
!
! if (focus)
! gtk_im_context_focus_in(xic);
! else
! gtk_im_context_focus_out(xic);
}

void
im_set_position(int row, int col)
{
! if (xic == NULL)
! return;
!
! GdkRectangle area;
!
! area.x = FILL_X(col);
! area.y = FILL_Y(row);
! area.width = gui.char_width * (mb_lefthalve(row, col) ? 2 : 1);
! area.height = gui.char_height;
!
! gtk_im_context_set_cursor_location(xic, &area);
!
! if (p_imst == IM_OVER_THE_SPOT)
! im_preedit_window_set_position();
}

# if 0 || defined(PROTO) // apparently only used in gui_x11.c
*** ../vim-9.0.1157/src/version.c 2023-01-07 14:50:59.044362174 +0000
--- src/version.c 2023-01-08 13:40:52.941514804 +0000
***************
*** 697,698 ****
--- 697,700 ----
{ /* Add new patch number below this line */
+ /**/
+ 1158,
/**/

--
Mrs Abbott: I'm a paediatrician.
Basil: Feet?
Mrs Abbott: Children.
Sybil: Oh, Basil!
Basil: Well, children have feet, don't they? That's how they move
around, my dear. You must take a look next time, it's most
interesting. (Fawlty Towers)

/// Bram Moolenaar -- Br...@Moolenaar.net -- http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
Reply all
Reply to author
Forward
0 new messages