To: vim_dev@googlegroups.com Subject: Patch 8.1.2042 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.1.2042 Problem: The evalfunc.c file is too big. Solution: Move getchar() and parse_queued_messages() to getchar.c. Files: src/getchar.c, src/proto/getchar.pro, src/evalfunc.c, src/misc2.c, src/proto/misc2.pro *** ../vim-8.1.2041/src/getchar.c 2019-08-21 14:36:29.387376100 +0200 --- src/getchar.c 2019-09-15 20:20:11.909631856 +0200 *************** *** 1901,1906 **** --- 1901,2105 ---- 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 *************** *** 3016,3022 **** #endif ) { - #ifdef MESSAGE_QUEUE parse_queued_messages(); #endif --- 3215,3220 ---- *** ../vim-8.1.2041/src/proto/getchar.pro 2019-08-20 20:13:40.330821936 +0200 --- src/proto/getchar.pro 2019-09-15 20:20:29.873564735 +0200 *************** *** 44,49 **** --- 44,52 ---- int vpeekc_nomap(void); int vpeekc_any(void); int char_avail(void); + void f_getchar(typval_T *argvars, typval_T *rettv); + void f_getcharmod(typval_T *argvars, typval_T *rettv); + void parse_queued_messages(void); void vungetc(int c); int fix_input_buffer(char_u *buf, int len); int input_available(void); *** ../vim-8.1.2041/src/evalfunc.c 2019-09-15 17:49:06.516490668 +0200 --- src/evalfunc.c 2019-09-15 20:16:36.142437358 +0200 *************** *** 90,97 **** 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); --- 90,95 ---- *************** *** 2857,2981 **** } #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 --- 2855,2860 ---- *** ../vim-8.1.2041/src/misc2.c 2019-09-13 22:30:07.588524105 +0200 --- src/misc2.c 2019-09-15 20:19:50.037713567 +0200 *************** *** 4349,4430 **** } #endif - #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 - #ifndef PROTO /* proto is defined in vim.h */ # ifdef ELAPSED_TIMEVAL /* --- 4349,4354 ---- *** ../vim-8.1.2041/src/proto/misc2.pro 2019-09-13 22:30:07.588524105 +0200 --- src/proto/misc2.pro 2019-09-15 20:20:33.041552897 +0200 *************** *** 102,108 **** int put_time(FILE *fd, time_T the_time); void time_to_bytes(time_T the_time, char_u *buf); int has_non_ascii(char_u *s); - void parse_queued_messages(void); int mch_parse_cmd(char_u *cmd, int use_shcf, char ***argv, int *argc); int build_argv_from_string(char_u *cmd, char ***argv, int *argc); int build_argv_from_list(list_T *l, char ***argv, int *argc); --- 102,107 ---- *** ../vim-8.1.2041/src/version.c 2019-09-15 19:31:12.840226946 +0200 --- src/version.c 2019-09-15 20:59:56.610701946 +0200 *************** *** 759,760 **** --- 759,762 ---- { /* Add new patch number below this line */ + /**/ + 2042, /**/ -- God made the integers; all else is the work of Man. -- Kronecker /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///