mirror of
https://github.com/neovim/neovim.git
synced 2025-10-17 15:21:47 +00:00
feat: click support for 'statusline', 'winbar' #18650
The mouseclick item "%@" is now supported by 'statusline' and 'winbar'. Previously it was only supported by 'tabline'.
This commit is contained in:
@@ -6,6 +6,8 @@
|
||||
// for FILE
|
||||
#include <stdio.h>
|
||||
|
||||
#include "grid_defs.h"
|
||||
|
||||
typedef struct file_buffer buf_T; // Forward declaration
|
||||
|
||||
// Reference to a buffer that stores the value of buf_free_count.
|
||||
@@ -1492,6 +1494,16 @@ struct window_S {
|
||||
// Location list reference used in the location list window.
|
||||
// In a non-location list window, w_llist_ref is NULL.
|
||||
qf_info_T *w_llist_ref;
|
||||
|
||||
// Status line click definitions
|
||||
StlClickDefinition *w_status_click_defs;
|
||||
// Size of the w_status_click_defs array
|
||||
size_t w_status_click_defs_size;
|
||||
|
||||
// Window bar click definitions
|
||||
StlClickDefinition *w_winbar_click_defs;
|
||||
// Size of the w_winbar_click_defs array
|
||||
size_t w_winbar_click_defs_size;
|
||||
};
|
||||
|
||||
static inline int win_hl_attr(win_T *wp, int hlf)
|
||||
|
@@ -111,4 +111,22 @@ struct ScreenGrid {
|
||||
false, 0, 0, NULL, false, true, 0, \
|
||||
0, 0, 0, 0, 0, false }
|
||||
|
||||
/// Status line click definition
|
||||
typedef struct {
|
||||
enum {
|
||||
kStlClickDisabled = 0, ///< Clicks to this area are ignored.
|
||||
kStlClickTabSwitch, ///< Switch to the given tab.
|
||||
kStlClickTabClose, ///< Close given tab.
|
||||
kStlClickFuncRun, ///< Run user function.
|
||||
} type; ///< Type of the click.
|
||||
int tabnr; ///< Tab page number.
|
||||
char *func; ///< Function to run.
|
||||
} StlClickDefinition;
|
||||
|
||||
/// Used for tabline clicks
|
||||
typedef struct {
|
||||
StlClickDefinition def; ///< Click definition.
|
||||
const char *start; ///< Location where region starts.
|
||||
} StlClickRecord;
|
||||
|
||||
#endif // NVIM_GRID_DEFS_H
|
||||
|
@@ -241,8 +241,8 @@ retnomove:
|
||||
}
|
||||
|
||||
curwin->w_cursor.lnum = curwin->w_topline;
|
||||
} else if (on_status_line && which_button == MOUSE_LEFT) {
|
||||
if (dragwin != NULL) {
|
||||
} else if (on_status_line) {
|
||||
if (which_button == MOUSE_LEFT && dragwin != NULL) {
|
||||
// Drag the status line
|
||||
count = row - dragwin->w_winrow - dragwin->w_height + 1
|
||||
- on_status_line;
|
||||
|
@@ -32,6 +32,7 @@
|
||||
#include "nvim/fold.h"
|
||||
#include "nvim/getchar.h"
|
||||
#include "nvim/globals.h"
|
||||
#include "nvim/grid_defs.h"
|
||||
#include "nvim/indent.h"
|
||||
#include "nvim/keycodes.h"
|
||||
#include "nvim/log.h"
|
||||
@@ -1432,6 +1433,63 @@ static void move_tab_to_mouse(void)
|
||||
}
|
||||
}
|
||||
|
||||
/// Call click definition function for column "col" in the "click_defs" array for button
|
||||
/// "which_button".
|
||||
static void call_click_def_func(StlClickDefinition *click_defs, int col, int which_button)
|
||||
{
|
||||
typval_T argv[] = {
|
||||
{
|
||||
.v_lock = VAR_FIXED,
|
||||
.v_type = VAR_NUMBER,
|
||||
.vval = {
|
||||
.v_number = (varnumber_T)click_defs[col].tabnr
|
||||
},
|
||||
},
|
||||
{
|
||||
.v_lock = VAR_FIXED,
|
||||
.v_type = VAR_NUMBER,
|
||||
.vval = {
|
||||
.v_number = ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_4CLICK
|
||||
? 4
|
||||
: ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_3CLICK
|
||||
? 3
|
||||
: ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK
|
||||
? 2
|
||||
: 1)))
|
||||
},
|
||||
},
|
||||
{
|
||||
.v_lock = VAR_FIXED,
|
||||
.v_type = VAR_STRING,
|
||||
.vval = {
|
||||
.v_string = (which_button == MOUSE_LEFT
|
||||
? "l"
|
||||
: (which_button == MOUSE_RIGHT
|
||||
? "r"
|
||||
: (which_button == MOUSE_MIDDLE
|
||||
? "m"
|
||||
: "?")))
|
||||
},
|
||||
},
|
||||
{
|
||||
.v_lock = VAR_FIXED,
|
||||
.v_type = VAR_STRING,
|
||||
.vval = {
|
||||
.v_string = (char[]) {
|
||||
(char)(mod_mask & MOD_MASK_SHIFT ? 's' : ' '),
|
||||
(char)(mod_mask & MOD_MASK_CTRL ? 'c' : ' '),
|
||||
(char)(mod_mask & MOD_MASK_ALT ? 'a' : ' '),
|
||||
(char)(mod_mask & MOD_MASK_META ? 'm' : ' '),
|
||||
NUL
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
typval_T rettv;
|
||||
(void)call_vim_function(click_defs[col].func, ARRAY_SIZE(argv), argv, &rettv);
|
||||
tv_clear(&rettv);
|
||||
}
|
||||
|
||||
/// Do the appropriate action for the current mouse click in the current mode.
|
||||
/// Not used for Command-line mode.
|
||||
///
|
||||
@@ -1481,6 +1539,7 @@ bool do_mouse(oparg_T *oap, int c, int dir, long count, bool fixindent)
|
||||
int jump_flags = 0; // flags for jump_to_mouse()
|
||||
pos_T start_visual;
|
||||
bool moved; // Has cursor moved?
|
||||
bool in_winbar; // mouse in window bar
|
||||
bool in_status_line; // mouse in status line
|
||||
static bool in_tab_line = false; // mouse clicked in tab line
|
||||
bool in_sep_line; // mouse in vertical separator line
|
||||
@@ -1711,66 +1770,10 @@ bool do_mouse(oparg_T *oap, int c, int dir, long count, bool fixindent)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case kStlClickFuncRun: {
|
||||
typval_T argv[] = {
|
||||
{
|
||||
.v_lock = VAR_FIXED,
|
||||
.v_type = VAR_NUMBER,
|
||||
.vval = {
|
||||
.v_number = (varnumber_T)tab_page_click_defs[mouse_col].tabnr
|
||||
},
|
||||
},
|
||||
{
|
||||
.v_lock = VAR_FIXED,
|
||||
.v_type = VAR_NUMBER,
|
||||
.vval = {
|
||||
.v_number = ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_4CLICK
|
||||
? 4
|
||||
: ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_3CLICK
|
||||
? 3
|
||||
: ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK
|
||||
? 2
|
||||
: 1)))
|
||||
},
|
||||
},
|
||||
{
|
||||
.v_lock = VAR_FIXED,
|
||||
.v_type = VAR_STRING,
|
||||
.vval = {
|
||||
.v_string = (which_button == MOUSE_LEFT
|
||||
? "l"
|
||||
: (which_button == MOUSE_RIGHT
|
||||
? "r"
|
||||
: (which_button == MOUSE_MIDDLE
|
||||
? "m"
|
||||
: "?")))
|
||||
},
|
||||
},
|
||||
{
|
||||
.v_lock = VAR_FIXED,
|
||||
.v_type = VAR_STRING,
|
||||
.vval = {
|
||||
.v_string = (char[]) {
|
||||
(char)(mod_mask & MOD_MASK_SHIFT ? 's' : ' '),
|
||||
(char)(mod_mask & MOD_MASK_CTRL ? 'c' : ' '),
|
||||
(char)(mod_mask & MOD_MASK_ALT ? 'a' : ' '),
|
||||
(char)(mod_mask & MOD_MASK_META ? 'm' : ' '),
|
||||
NUL
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
typval_T rettv;
|
||||
funcexe_T funcexe = FUNCEXE_INIT;
|
||||
funcexe.firstline = curwin->w_cursor.lnum;
|
||||
funcexe.lastline = curwin->w_cursor.lnum;
|
||||
funcexe.evaluate = true;
|
||||
(void)call_func(tab_page_click_defs[mouse_col].func, -1,
|
||||
&rettv, ARRAY_SIZE(argv), argv, &funcexe);
|
||||
tv_clear(&rettv);
|
||||
case kStlClickFuncRun:
|
||||
call_click_def_func(tab_page_click_defs, mouse_col, which_button);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else if (is_drag && in_tab_line) {
|
||||
@@ -1840,15 +1843,39 @@ bool do_mouse(oparg_T *oap, int c, int dir, long count, bool fixindent)
|
||||
oap == NULL ? NULL : &(oap->inclusive),
|
||||
which_button);
|
||||
|
||||
// A click in the window bar has no side effects.
|
||||
if (jump_flags & MOUSE_WINBAR) {
|
||||
return false;
|
||||
}
|
||||
|
||||
moved = (jump_flags & CURSOR_MOVED);
|
||||
in_winbar = (jump_flags & MOUSE_WINBAR);
|
||||
in_status_line = (jump_flags & IN_STATUS_LINE);
|
||||
in_sep_line = (jump_flags & IN_SEP_LINE);
|
||||
|
||||
if ((in_winbar || in_status_line) && is_click) {
|
||||
// Handle click event on window bar or status lin
|
||||
int click_grid = mouse_grid;
|
||||
int click_row = mouse_row;
|
||||
int click_col = mouse_col;
|
||||
win_T *wp = mouse_find_win(&click_grid, &click_row, &click_col);
|
||||
|
||||
StlClickDefinition *click_defs = in_status_line ? wp->w_status_click_defs
|
||||
: wp->w_winbar_click_defs;
|
||||
|
||||
if (click_defs != NULL) {
|
||||
switch (click_defs[click_col].type) {
|
||||
case kStlClickDisabled:
|
||||
break;
|
||||
case kStlClickFuncRun:
|
||||
call_click_def_func(click_defs, click_col, which_button);
|
||||
break;
|
||||
default:
|
||||
assert(false && "winbar and statusline only support %@ for clicks");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
} else if (in_winbar) {
|
||||
// A drag or release event in the window bar has no side effects.
|
||||
return false;
|
||||
}
|
||||
|
||||
// When jumping to another window, clear a pending operator. That's a bit
|
||||
// friendlier than beeping and not jumping to that window.
|
||||
|
@@ -88,6 +88,7 @@
|
||||
#include "nvim/fold.h"
|
||||
#include "nvim/garray.h"
|
||||
#include "nvim/getchar.h"
|
||||
#include "nvim/grid_defs.h"
|
||||
#include "nvim/highlight.h"
|
||||
#include "nvim/highlight_group.h"
|
||||
#include "nvim/indent.h"
|
||||
@@ -5337,11 +5338,27 @@ static void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler)
|
||||
attr = (wp == curwin) ? HL_ATTR(HLF_WBR) : HL_ATTR(HLF_WBRNC);
|
||||
maxwidth = wp->w_width_inner;
|
||||
use_sandbox = was_set_insecurely(wp, "winbar", 0);
|
||||
|
||||
stl_clear_click_defs(wp->w_winbar_click_defs, wp->w_winbar_click_defs_size);
|
||||
// Allocate / resize the click definitions array for winbar if needed.
|
||||
if (wp->w_winbar_height && wp->w_winbar_click_defs_size < (size_t)maxwidth) {
|
||||
xfree(wp->w_winbar_click_defs);
|
||||
wp->w_winbar_click_defs_size = (size_t)maxwidth;
|
||||
wp->w_winbar_click_defs = xcalloc(wp->w_winbar_click_defs_size, sizeof(StlClickRecord));
|
||||
}
|
||||
} else {
|
||||
row = is_stl_global ? (Rows - p_ch - 1) : W_ENDROW(wp);
|
||||
fillchar = fillchar_status(&attr, wp);
|
||||
maxwidth = is_stl_global ? Columns : wp->w_width;
|
||||
|
||||
stl_clear_click_defs(wp->w_status_click_defs, wp->w_status_click_defs_size);
|
||||
// Allocate / resize the click definitions array for statusline if needed.
|
||||
if (wp->w_status_click_defs_size < (size_t)maxwidth) {
|
||||
xfree(wp->w_status_click_defs);
|
||||
wp->w_status_click_defs_size = maxwidth;
|
||||
wp->w_status_click_defs = xcalloc(wp->w_status_click_defs_size, sizeof(StlClickRecord));
|
||||
}
|
||||
|
||||
if (draw_ruler) {
|
||||
stl = p_ruf;
|
||||
// advance past any leading group spec - implicit in ru_col
|
||||
@@ -5445,26 +5462,38 @@ static void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler)
|
||||
|
||||
grid_puts_line_flush(false);
|
||||
|
||||
if (wp == NULL) {
|
||||
// Fill the tab_page_click_defs array for clicking in the tab pages line.
|
||||
col = 0;
|
||||
len = 0;
|
||||
p = buf;
|
||||
StlClickDefinition cur_click_def = {
|
||||
.type = kStlClickDisabled,
|
||||
};
|
||||
for (n = 0; tabtab[n].start != NULL; n++) {
|
||||
len += vim_strnsize(p, (int)(tabtab[n].start - (char *)p));
|
||||
while (col < len) {
|
||||
tab_page_click_defs[col++] = cur_click_def;
|
||||
}
|
||||
p = (char_u *)tabtab[n].start;
|
||||
cur_click_def = tabtab[n].def;
|
||||
// Fill the tab_page_click_defs, w_status_click_defs or w_winbar_click_defs array for clicking
|
||||
// in the tab page line, status line or window bar
|
||||
StlClickDefinition *click_defs = (wp == NULL) ? tab_page_click_defs
|
||||
: draw_winbar ? wp->w_winbar_click_defs
|
||||
: wp->w_status_click_defs;
|
||||
|
||||
if (click_defs == NULL) {
|
||||
goto theend;
|
||||
}
|
||||
|
||||
col = 0;
|
||||
len = 0;
|
||||
p = buf;
|
||||
StlClickDefinition cur_click_def = {
|
||||
.type = kStlClickDisabled,
|
||||
};
|
||||
for (n = 0; tabtab[n].start != NULL; n++) {
|
||||
len += vim_strnsize(p, (int)(tabtab[n].start - (char *)p));
|
||||
while (col < len) {
|
||||
click_defs[col++] = cur_click_def;
|
||||
}
|
||||
while (col < Columns) {
|
||||
tab_page_click_defs[col++] = cur_click_def;
|
||||
p = (char_u *)tabtab[n].start;
|
||||
cur_click_def = tabtab[n].def;
|
||||
if ((wp != NULL) && !(cur_click_def.type == kStlClickDisabled
|
||||
|| cur_click_def.type == kStlClickFuncRun)) {
|
||||
// window bar and status line only support click functions
|
||||
cur_click_def.type = kStlClickDisabled;
|
||||
}
|
||||
}
|
||||
while (col < maxwidth) {
|
||||
click_defs[col++] = cur_click_def;
|
||||
}
|
||||
|
||||
theend:
|
||||
entered = false;
|
||||
@@ -5572,7 +5601,6 @@ void check_for_delay(bool check_msg_scroll)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Resize the screen to Rows and Columns.
|
||||
///
|
||||
/// Allocate default_grid.chars[] and other grid arrays.
|
||||
@@ -5641,7 +5669,7 @@ retry:
|
||||
StlClickDefinition *new_tab_page_click_defs =
|
||||
xcalloc((size_t)Columns, sizeof(*new_tab_page_click_defs));
|
||||
|
||||
clear_tab_page_click_defs(tab_page_click_defs, tab_page_click_defs_size);
|
||||
stl_clear_click_defs(tab_page_click_defs, tab_page_click_defs_size);
|
||||
xfree(tab_page_click_defs);
|
||||
|
||||
tab_page_click_defs = new_tab_page_click_defs;
|
||||
@@ -5672,19 +5700,19 @@ retry:
|
||||
resizing = false;
|
||||
}
|
||||
|
||||
/// Clear tab_page_click_defs table
|
||||
/// Clear status line, window bar or tab page line click definition table
|
||||
///
|
||||
/// @param[out] tpcd Table to clear.
|
||||
/// @param[in] tpcd_size Size of the table.
|
||||
void clear_tab_page_click_defs(StlClickDefinition *const tpcd, const long tpcd_size)
|
||||
void stl_clear_click_defs(StlClickDefinition *const click_defs, const long click_defs_size)
|
||||
{
|
||||
if (tpcd != NULL) {
|
||||
for (long i = 0; i < tpcd_size; i++) {
|
||||
if (i == 0 || tpcd[i].func != tpcd[i - 1].func) {
|
||||
xfree(tpcd[i].func);
|
||||
if (click_defs != NULL) {
|
||||
for (long i = 0; i < click_defs_size; i++) {
|
||||
if (i == 0 || click_defs[i].func != click_defs[i - 1].func) {
|
||||
xfree(click_defs[i].func);
|
||||
}
|
||||
}
|
||||
memset(tpcd, 0, (size_t)tpcd_size * sizeof(tpcd[0]));
|
||||
memset(click_defs, 0, (size_t)click_defs_size * sizeof(click_defs[0]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6200,7 +6228,7 @@ void draw_tabline(void)
|
||||
|
||||
// Init TabPageIdxs[] to zero: Clicking outside of tabs has no effect.
|
||||
assert(Columns == tab_page_click_defs_size);
|
||||
clear_tab_page_click_defs(tab_page_click_defs, tab_page_click_defs_size);
|
||||
stl_clear_click_defs(tab_page_click_defs, tab_page_click_defs_size);
|
||||
|
||||
// Use the 'tabline' option if it's set.
|
||||
if (*p_tal != NUL) {
|
||||
|
@@ -30,24 +30,6 @@ typedef enum {
|
||||
// Maximum columns for terminal highlight attributes
|
||||
#define TERM_ATTRS_MAX 1024
|
||||
|
||||
/// Status line click definition
|
||||
typedef struct {
|
||||
enum {
|
||||
kStlClickDisabled = 0, ///< Clicks to this area are ignored.
|
||||
kStlClickTabSwitch, ///< Switch to the given tab.
|
||||
kStlClickTabClose, ///< Close given tab.
|
||||
kStlClickFuncRun, ///< Run user function.
|
||||
} type; ///< Type of the click.
|
||||
int tabnr; ///< Tab page number.
|
||||
char *func; ///< Function to run.
|
||||
} StlClickDefinition;
|
||||
|
||||
/// Used for tabline clicks
|
||||
typedef struct {
|
||||
StlClickDefinition def; ///< Click definition.
|
||||
const char *start; ///< Location where region starts.
|
||||
} StlClickRecord;
|
||||
|
||||
/// Array defining what should be done when tabline is clicked
|
||||
EXTERN StlClickDefinition *tab_page_click_defs INIT(= NULL);
|
||||
|
||||
|
@@ -5119,6 +5119,12 @@ static void win_free(win_T *wp, tabpage_T *tp)
|
||||
xfree(wp->w_localdir);
|
||||
xfree(wp->w_prevdir);
|
||||
|
||||
stl_clear_click_defs(wp->w_status_click_defs, wp->w_status_click_defs_size);
|
||||
xfree(wp->w_status_click_defs);
|
||||
|
||||
stl_clear_click_defs(wp->w_winbar_click_defs, wp->w_winbar_click_defs_size);
|
||||
xfree(wp->w_winbar_click_defs);
|
||||
|
||||
// Remove the window from the b_wininfo lists, it may happen that the
|
||||
// freed memory is re-used for another window.
|
||||
FOR_ALL_BUFFERS(buf) {
|
||||
@@ -6612,6 +6618,23 @@ void last_status(bool morewin)
|
||||
global_stl_height() > 0);
|
||||
}
|
||||
|
||||
// Remove status line from window, replacing it with a horizontal separator if needed.
|
||||
static void win_remove_status_line(win_T *wp, bool add_hsep)
|
||||
{
|
||||
wp->w_status_height = 0;
|
||||
if (add_hsep) {
|
||||
wp->w_hsep_height = 1;
|
||||
} else {
|
||||
win_new_height(wp, wp->w_height + STATUS_HEIGHT);
|
||||
}
|
||||
comp_col();
|
||||
|
||||
stl_clear_click_defs(wp->w_status_click_defs, wp->w_status_click_defs_size);
|
||||
xfree(wp->w_status_click_defs);
|
||||
wp->w_status_click_defs_size = 0;
|
||||
wp->w_status_click_defs = NULL;
|
||||
}
|
||||
|
||||
// Look for resizable frames and take lines from them to make room for the statusline
|
||||
static void resize_frame_for_status(frame_T *fr)
|
||||
{
|
||||
@@ -6652,10 +6675,7 @@ static void last_status_rec(frame_T *fr, bool statusline, bool is_stl_global)
|
||||
|
||||
if (is_last) {
|
||||
if (wp->w_status_height != 0 && (!statusline || is_stl_global)) {
|
||||
// Remove status line
|
||||
wp->w_status_height = 0;
|
||||
win_new_height(wp, wp->w_height + STATUS_HEIGHT);
|
||||
comp_col();
|
||||
win_remove_status_line(wp, false);
|
||||
} else if (wp->w_status_height == 0 && !is_stl_global && statusline) {
|
||||
// Add statusline to window if needed
|
||||
wp->w_status_height = STATUS_HEIGHT;
|
||||
@@ -6665,9 +6685,7 @@ static void last_status_rec(frame_T *fr, bool statusline, bool is_stl_global)
|
||||
} else if (wp->w_status_height != 0 && is_stl_global) {
|
||||
// If statusline is global and the window has a statusline, replace it with a horizontal
|
||||
// separator
|
||||
wp->w_status_height = 0;
|
||||
wp->w_hsep_height = 1;
|
||||
comp_col();
|
||||
win_remove_status_line(wp, true);
|
||||
} else if (wp->w_status_height == 0 && !is_stl_global) {
|
||||
// If statusline isn't global and the window doesn't have a statusline, re-add it
|
||||
wp->w_status_height = STATUS_HEIGHT;
|
||||
@@ -6675,13 +6693,8 @@ static void last_status_rec(frame_T *fr, bool statusline, bool is_stl_global)
|
||||
comp_col();
|
||||
}
|
||||
redraw_all_later(SOME_VALID);
|
||||
} else if (fr->fr_layout == FR_COL) {
|
||||
// For a column frame, recursively call this function for all child frames
|
||||
FOR_ALL_FRAMES(fp, fr->fr_child) {
|
||||
last_status_rec(fp, statusline, is_stl_global);
|
||||
}
|
||||
} else {
|
||||
// For a row frame, recursively call this function for all child frames
|
||||
// For a column or row frame, recursively call this function for all child frames
|
||||
FOR_ALL_FRAMES(fp, fr->fr_child) {
|
||||
last_status_rec(fp, statusline, is_stl_global);
|
||||
}
|
||||
@@ -6697,6 +6710,14 @@ void set_winbar(void)
|
||||
wp->w_winbar_height = winbar_height;
|
||||
win_set_inner_size(wp);
|
||||
wp->w_redr_winbar = winbar_height;
|
||||
|
||||
if (winbar_height == 0) {
|
||||
// When removing winbar, deallocate the w_winbar_click_defs array
|
||||
stl_clear_click_defs(wp->w_winbar_click_defs, wp->w_winbar_click_defs_size);
|
||||
xfree(wp->w_winbar_click_defs);
|
||||
wp->w_winbar_click_defs_size = 0;
|
||||
wp->w_winbar_click_defs = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user