To: vim_dev@googlegroups.com Subject: Patch 9.0.1158 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ 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 -- Bram@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 ///