Skip to content

Commit

Permalink
patch 8.1.2042: the evalfunc.c file is too big
Browse files Browse the repository at this point in the history
Problem:    The evalfunc.c file is too big.
Solution:   Move getchar() and parse_queued_messages() to getchar.c.
  • Loading branch information
brammool committed Sep 15, 2019
1 parent 248fdb3 commit 9c658c9
Show file tree
Hide file tree
Showing 6 changed files with 204 additions and 199 deletions.
121 changes: 0 additions & 121 deletions src/evalfunc.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,6 @@ static void f_function(typval_T *argvars, typval_T *rettv);
static void f_garbagecollect(typval_T *argvars, typval_T *rettv);
static void f_get(typval_T *argvars, typval_T *rettv);
static void f_getchangelist(typval_T *argvars, typval_T *rettv);
static void f_getchar(typval_T *argvars, typval_T *rettv);
static void f_getcharmod(typval_T *argvars, typval_T *rettv);
static void f_getcharsearch(typval_T *argvars, typval_T *rettv);
static void f_getcmdwintype(typval_T *argvars, typval_T *rettv);
static void f_getenv(typval_T *argvars, typval_T *rettv);
Expand Down Expand Up @@ -2857,125 +2855,6 @@ f_getchangelist(typval_T *argvars, typval_T *rettv)
}
#endif
}
/*
* "getchar()" function
*/
static void
f_getchar(typval_T *argvars, typval_T *rettv)
{
varnumber_T n;
int error = FALSE;

#ifdef MESSAGE_QUEUE
// vpeekc() used to check for messages, but that caused problems, invoking
// a callback where it was not expected. Some plugins use getchar(1) in a
// loop to await a message, therefore make sure we check for messages here.
parse_queued_messages();
#endif

/* Position the cursor. Needed after a message that ends in a space. */
windgoto(msg_row, msg_col);

++no_mapping;
++allow_keys;
for (;;)
{
if (argvars[0].v_type == VAR_UNKNOWN)
/* getchar(): blocking wait. */
n = plain_vgetc();
else if (tv_get_number_chk(&argvars[0], &error) == 1)
/* getchar(1): only check if char avail */
n = vpeekc_any();
else if (error || vpeekc_any() == NUL)
/* illegal argument or getchar(0) and no char avail: return zero */
n = 0;
else
/* getchar(0) and char avail: return char */
n = plain_vgetc();

if (n == K_IGNORE)
continue;
break;
}
--no_mapping;
--allow_keys;

set_vim_var_nr(VV_MOUSE_WIN, 0);
set_vim_var_nr(VV_MOUSE_WINID, 0);
set_vim_var_nr(VV_MOUSE_LNUM, 0);
set_vim_var_nr(VV_MOUSE_COL, 0);

rettv->vval.v_number = n;
if (IS_SPECIAL(n) || mod_mask != 0)
{
char_u temp[10]; /* modifier: 3, mbyte-char: 6, NUL: 1 */
int i = 0;

/* Turn a special key into three bytes, plus modifier. */
if (mod_mask != 0)
{
temp[i++] = K_SPECIAL;
temp[i++] = KS_MODIFIER;
temp[i++] = mod_mask;
}
if (IS_SPECIAL(n))
{
temp[i++] = K_SPECIAL;
temp[i++] = K_SECOND(n);
temp[i++] = K_THIRD(n);
}
else 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);

#ifdef FEAT_MOUSE
if (is_mouse_key(n))
{
int row = mouse_row;
int col = mouse_col;
win_T *win;
linenr_T lnum;
win_T *wp;
int winnr = 1;

if (row >= 0 && col >= 0)
{
/* Find the window at the mouse coordinates and compute the
* text position. */
win = mouse_find_win(&row, &col, FIND_POPUP);
if (win == NULL)
return;
(void)mouse_comp_pos(win, &row, &col, &lnum, NULL);
# ifdef FEAT_TEXT_PROP
if (WIN_IS_POPUP(win))
winnr = 0;
else
# endif
for (wp = firstwin; wp != win && wp != NULL;
wp = wp->w_next)
++winnr;
set_vim_var_nr(VV_MOUSE_WIN, winnr);
set_vim_var_nr(VV_MOUSE_WINID, win->w_id);
set_vim_var_nr(VV_MOUSE_LNUM, lnum);
set_vim_var_nr(VV_MOUSE_COL, col + 1);
}
}
#endif
}
}

/*
* "getcharmod()" function
*/
static void
f_getcharmod(typval_T *argvars UNUSED, typval_T *rettv)
{
rettv->vval.v_number = mod_mask;
}

/*
* "getcharsearch()" function
Expand Down
200 changes: 199 additions & 1 deletion src/getchar.c
Original file line number Diff line number Diff line change
Expand Up @@ -1901,6 +1901,205 @@ char_avail(void)
return (retval != NUL);
}

#if defined(FEAT_EVAL) || defined(PROTO)
/*
* "getchar()" function
*/
void
f_getchar(typval_T *argvars, typval_T *rettv)
{
varnumber_T n;
int error = FALSE;

#ifdef MESSAGE_QUEUE
// vpeekc() used to check for messages, but that caused problems, invoking
// a callback where it was not expected. Some plugins use getchar(1) in a
// loop to await a message, therefore make sure we check for messages here.
parse_queued_messages();
#endif

/* Position the cursor. Needed after a message that ends in a space. */
windgoto(msg_row, msg_col);

++no_mapping;
++allow_keys;
for (;;)
{
if (argvars[0].v_type == VAR_UNKNOWN)
/* getchar(): blocking wait. */
n = plain_vgetc();
else if (tv_get_number_chk(&argvars[0], &error) == 1)
/* getchar(1): only check if char avail */
n = vpeekc_any();
else if (error || vpeekc_any() == NUL)
/* illegal argument or getchar(0) and no char avail: return zero */
n = 0;
else
/* getchar(0) and char avail: return char */
n = plain_vgetc();

if (n == K_IGNORE)
continue;
break;
}
--no_mapping;
--allow_keys;

set_vim_var_nr(VV_MOUSE_WIN, 0);
set_vim_var_nr(VV_MOUSE_WINID, 0);
set_vim_var_nr(VV_MOUSE_LNUM, 0);
set_vim_var_nr(VV_MOUSE_COL, 0);

rettv->vval.v_number = n;
if (IS_SPECIAL(n) || mod_mask != 0)
{
char_u temp[10]; /* modifier: 3, mbyte-char: 6, NUL: 1 */
int i = 0;

/* Turn a special key into three bytes, plus modifier. */
if (mod_mask != 0)
{
temp[i++] = K_SPECIAL;
temp[i++] = KS_MODIFIER;
temp[i++] = mod_mask;
}
if (IS_SPECIAL(n))
{
temp[i++] = K_SPECIAL;
temp[i++] = K_SECOND(n);
temp[i++] = K_THIRD(n);
}
else 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);

#ifdef FEAT_MOUSE
if (is_mouse_key(n))
{
int row = mouse_row;
int col = mouse_col;
win_T *win;
linenr_T lnum;
win_T *wp;
int winnr = 1;

if (row >= 0 && col >= 0)
{
/* Find the window at the mouse coordinates and compute the
* text position. */
win = mouse_find_win(&row, &col, FIND_POPUP);
if (win == NULL)
return;
(void)mouse_comp_pos(win, &row, &col, &lnum, NULL);
# ifdef FEAT_TEXT_PROP
if (WIN_IS_POPUP(win))
winnr = 0;
else
# endif
for (wp = firstwin; wp != win && wp != NULL;
wp = wp->w_next)
++winnr;
set_vim_var_nr(VV_MOUSE_WIN, winnr);
set_vim_var_nr(VV_MOUSE_WINID, win->w_id);
set_vim_var_nr(VV_MOUSE_LNUM, lnum);
set_vim_var_nr(VV_MOUSE_COL, col + 1);
}
}
#endif
}
}

/*
* "getcharmod()" function
*/
void
f_getcharmod(typval_T *argvars UNUSED, typval_T *rettv)
{
rettv->vval.v_number = mod_mask;
}
#endif // FEAT_EVAL

#if defined(MESSAGE_QUEUE) || defined(PROTO)
# define MAX_REPEAT_PARSE 8

/*
* Process messages that have been queued for netbeans or clientserver.
* Also check if any jobs have ended.
* These functions can call arbitrary vimscript and should only be called when
* it is safe to do so.
*/
void
parse_queued_messages(void)
{
int old_curwin_id = curwin->w_id;
int old_curbuf_fnum = curbuf->b_fnum;
int i;
int save_may_garbage_collect = may_garbage_collect;

// Do not handle messages while redrawing, because it may cause buffers to
// change or be wiped while they are being redrawn.
if (updating_screen)
return;

// may_garbage_collect is set in main_loop() to do garbage collection when
// blocking to wait on a character. We don't want that while parsing
// messages, a callback may invoke vgetc() while lists and dicts are in use
// in the call stack.
may_garbage_collect = FALSE;

// Loop when a job ended, but don't keep looping forever.
for (i = 0; i < MAX_REPEAT_PARSE; ++i)
{
// For Win32 mch_breakcheck() does not check for input, do it here.
# if defined(MSWIN) && defined(FEAT_JOB_CHANNEL)
channel_handle_events(FALSE);
# endif

# ifdef FEAT_NETBEANS_INTG
// Process the queued netbeans messages.
netbeans_parse_messages();
# endif
# ifdef FEAT_JOB_CHANNEL
// Write any buffer lines still to be written.
channel_write_any_lines();

// Process the messages queued on channels.
channel_parse_messages();
# endif
# if defined(FEAT_CLIENTSERVER) && defined(FEAT_X11)
// Process the queued clientserver messages.
server_parse_messages();
# endif
# ifdef FEAT_JOB_CHANNEL
// Check if any jobs have ended. If so, repeat the above to handle
// changes, e.g. stdin may have been closed.
if (job_check_ended())
continue;
# endif
# ifdef FEAT_TERMINAL
free_unused_terminals();
# endif
# ifdef FEAT_SOUND_CANBERRA
if (has_sound_callback_in_queue())
invoke_sound_callback();
# endif
break;
}

may_garbage_collect = save_may_garbage_collect;

// If the current window or buffer changed we need to bail out of the
// waiting loop. E.g. when a job exit callback closes the terminal window.
if (curwin->w_id != old_curwin_id || curbuf->b_fnum != old_curbuf_fnum)
ins_char_typebuf(K_IGNORE);
}
#endif


typedef enum {
map_result_fail, // failed, break loop
map_result_get, // get a character from typeahead
Expand Down Expand Up @@ -3016,7 +3215,6 @@ inchar(
#endif
)
{

#ifdef MESSAGE_QUEUE
parse_queued_messages();
#endif
Expand Down
Loading

0 comments on commit 9c658c9

Please sign in to comment.