diff options
author | Thiago de Arruda <tpadilha84@gmail.com> | 2015-02-21 06:33:18 -0300 |
---|---|---|
committer | Thiago de Arruda <tpadilha84@gmail.com> | 2015-02-21 06:33:18 -0300 |
commit | c48f835749913f48267ed3b389bdd333e19e6dc4 (patch) | |
tree | edc8d4310b1e4025697a4ae0e9f39c2973fb3725 /src | |
parent | 486d2e944dffb30d97d65c88bbcc77f6fd1208f6 (diff) | |
parent | 6293b5513c54557bbf56077374df83cb52344fa3 (diff) | |
download | rneovim-c48f835749913f48267ed3b389bdd333e19e6dc4.tar.gz rneovim-c48f835749913f48267ed3b389bdd333e19e6dc4.tar.bz2 rneovim-c48f835749913f48267ed3b389bdd333e19e6dc4.zip |
Merge PR #1997 'Remove term modules'
Diffstat (limited to 'src')
49 files changed, 877 insertions, 3704 deletions
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 33020c5b8c..e23a97bfc9 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -22,7 +22,6 @@ #include "nvim/eval.h" #include "nvim/misc2.h" #include "nvim/syntax.h" -#include "nvim/term.h" #include "nvim/getchar.h" #include "nvim/os/input.h" diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 4db2b4ef6b..fa25b68641 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -68,7 +68,7 @@ #include "nvim/spell.h" #include "nvim/strings.h" #include "nvim/syntax.h" -#include "nvim/term.h" +#include "nvim/ui.h" #include "nvim/undo.h" #include "nvim/window.h" #include "nvim/os/os.h" @@ -1420,7 +1420,7 @@ buflist_new ( if (top_file_num < 0) { /* wrap around (may cause duplicates) */ EMSG(_("W14: Warning: List of file names overflow")); if (emsg_silent == 0) { - out_flush(); + ui_flush(); os_delay(3000L, true); /* make sure it is noticed */ } top_file_num = 1; @@ -2159,7 +2159,7 @@ void buflist_list(exarg_T *eap) buf == curbuf ? (int64_t)curwin->w_cursor.lnum : (int64_t)buflist_findlnum(buf)); msg_outtrans(IObuff); - out_flush(); /* output one line at a time */ + ui_flush(); /* output one line at a time */ os_breakcheck(); } } @@ -2745,7 +2745,8 @@ static int ti_change(char_u *str, char_u **last) */ void resettitle(void) { - mch_settitle(lasttitle, lasticon); + ui_set_title((char *)lasttitle); + ui_set_icon((char *)lasticon); } # if defined(EXITFREE) diff --git a/src/nvim/edit.c b/src/nvim/edit.c index 7913a37d2c..c0bd8cc8fd 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -54,7 +54,6 @@ #include "nvim/strings.h" #include "nvim/syntax.h" #include "nvim/tag.h" -#include "nvim/term.h" #include "nvim/ui.h" #include "nvim/mouse.h" #include "nvim/undo.h" @@ -1406,7 +1405,7 @@ void display_dollar(colnr_T col) if (!redrawing()) return; - cursor_off(); + ui_cursor_off(); save_col = curwin->w_cursor.col; curwin->w_cursor.col = col; if (has_mbyte) { @@ -1755,7 +1754,7 @@ static int has_compl_option(int dict_opt) if (emsg_silent == 0) { vim_beep(); setcursor(); - out_flush(); + ui_flush(); os_delay(2000L, false); } return FALSE; @@ -2243,7 +2242,7 @@ void set_completion(colnr_T startcol, list_T *list) compl_curr_match = compl_first_match; ins_complete(Ctrl_N); - out_flush(); + ui_flush(); } @@ -4469,7 +4468,7 @@ static int ins_complete(int c) edit_submode_highl = HLF_COUNT; showmode(); edit_submode_extra = NULL; - out_flush(); + ui_flush(); } compl_shown_match = compl_curr_match; diff --git a/src/nvim/eval.c b/src/nvim/eval.c index ab24dce472..a47473930a 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -75,7 +75,6 @@ #include "nvim/syntax.h" #include "nvim/tag.h" #include "nvim/tempfile.h" -#include "nvim/term.h" #include "nvim/ui.h" #include "nvim/mouse.h" #include "nvim/undo.h" @@ -9099,7 +9098,7 @@ static void f_getchar(typval_T *argvars, typval_T *rettv) int error = FALSE; /* Position the cursor. Needed after a message that ends in a space. */ - windgoto(msg_row, msg_col); + ui_cursor_goto(msg_row, msg_col); ++no_mapping; ++allow_keys; @@ -12740,7 +12739,7 @@ static void f_screenchar(typval_T *argvars, typval_T *rettv) */ static void f_screencol(typval_T *argvars, typval_T *rettv) { - rettv->vval.v_number = screen_screencol() + 1; + rettv->vval.v_number = ui_current_col() + 1; } /* @@ -12748,7 +12747,7 @@ static void f_screencol(typval_T *argvars, typval_T *rettv) */ static void f_screenrow(typval_T *argvars, typval_T *rettv) { - rettv->vval.v_number = screen_screenrow() + 1; + rettv->vval.v_number = ui_current_row() + 1; } /* @@ -17148,7 +17147,7 @@ void ex_execute(exarg_T *eap) if (ret != FAIL && ga.ga_data != NULL) { if (eap->cmdidx == CMD_echomsg) { MSG_ATTR(ga.ga_data, echo_attr); - out_flush(); + ui_flush(); } else if (eap->cmdidx == CMD_echoerr) { /* We don't want to abort following commands, restore did_emsg. */ save_did_emsg = did_emsg; @@ -17346,7 +17345,7 @@ void ex_function(exarg_T *eap) if (j < 99) msg_putchar(' '); msg_prt_line(FUNCLINE(fp, j), FALSE); - out_flush(); /* show a line at a time */ + ui_flush(); /* show a line at a time */ os_breakcheck(); } if (!got_int) { @@ -19354,7 +19353,7 @@ void ex_oldfiles(exarg_T *eap) MSG_PUTS(": "); msg_outtrans(get_tv_string(&li->li_tv)); msg_putchar('\n'); - out_flush(); /* output one line at a time */ + ui_flush(); /* output one line at a time */ os_breakcheck(); } /* Assume "got_int" was set to truncate the listing. */ diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index ad49153a1e..3dde055c2a 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -62,7 +62,7 @@ #include "nvim/syntax.h" #include "nvim/tag.h" #include "nvim/tempfile.h" -#include "nvim/term.h" +#include "nvim/ui.h" #include "nvim/undo.h" #include "nvim/window.h" #include "nvim/os/os.h" @@ -946,7 +946,7 @@ void do_bang(int addr_count, exarg_T *eap, int forceit, int do_in, int do_out) msg_putchar('!'); msg_outtrans(newcmd); msg_clr_eos(); - windgoto(msg_row, msg_col); + ui_cursor_goto(msg_row, msg_col); do_shell(newcmd, 0); } else { /* :range! */ @@ -1064,8 +1064,8 @@ do_filter ( /* Create the shell command in allocated memory. */ cmd_buf = make_filter_cmd(cmd, itmp, otmp); - windgoto((int)Rows - 1, 0); - cursor_on(); + ui_cursor_goto((int)Rows - 1, 0); + ui_cursor_on(); /* * When not redirecting the output the command can write anything to the @@ -1245,23 +1245,18 @@ do_shell ( } } - /* This windgoto is required for when the '\n' resulted in a "delete line - * 1" command to the terminal. */ - if (!swapping_screen()) - windgoto(msg_row, msg_col); - cursor_on(); + // This ui_cursor_goto is required for when the '\n' resulted in a "delete line + // 1" command to the terminal. + ui_cursor_goto(msg_row, msg_col); + ui_cursor_on(); (void)call_shell(cmd, flags, NULL); did_check_timestamps = FALSE; need_check_timestamps = TRUE; - /* - * put the message cursor at the end of the screen, avoids wait_return() - * to overwrite the text that the external command showed - */ - if (!swapping_screen()) { - msg_row = Rows - 1; - msg_col = 0; - } + // put the message cursor at the end of the screen, avoids wait_return() + // to overwrite the text that the external command showed + msg_row = Rows - 1; + msg_col = 0; if (autocmd_busy) { if (msg_silent == 0) @@ -1284,8 +1279,6 @@ do_shell ( * want to wait for "hit return to continue". */ save_nwr = no_wait_return; - if (swapping_screen()) - no_wait_return = FALSE; wait_return(msg_silent == 0); no_wait_return = save_nwr; } @@ -1945,21 +1938,6 @@ void viminfo_writestring(FILE *fd, char_u *p) putc('\n', fd); } -/* - * Implementation of ":fixdel", also used by get_stty(). - * <BS> resulting <Del> - * ^? ^H - * not ^? ^? - */ -void do_fixdel(exarg_T *eap) -{ - char_u *p; - - p = find_termcode((char_u *)"kb"); - add_termcode((char_u *)"kD", p != NULL - && *p == DEL ? (char_u *)CTRL_H_STR : DEL_STR, FALSE); -} - void print_line_no_prefix(linenr_T lnum, int use_number, int list) { char_u numbuf[30]; @@ -1985,8 +1963,8 @@ void print_line(linenr_T lnum, int use_number, int list) print_line_no_prefix(lnum, use_number, list); if (save_silent) { msg_putchar('\n'); - cursor_on(); /* msg_start() switches it off */ - out_flush(); + ui_cursor_on(); /* msg_start() switches it off */ + ui_flush(); silent_mode = save_silent; } info_message = FALSE; @@ -3971,7 +3949,7 @@ void do_sub(exarg_T *eap) msg_no_more = FALSE; msg_scroll = i; showruler(TRUE); - windgoto(msg_row, msg_col); + ui_cursor_goto(msg_row, msg_col); RedrawingDisabled = temp; #ifdef USE_ON_FLY_SCROLL diff --git a/src/nvim/ex_cmds.lua b/src/nvim/ex_cmds.lua index 98a2b2814d..0897006555 100644 --- a/src/nvim/ex_cmds.lua +++ b/src/nvim/ex_cmds.lua @@ -766,11 +766,6 @@ return { func='ex_rewind', }, { - command='fixdel', - flags=bit.bor(TRLBAR, CMDWIN), - func='do_fixdel', - }, - { command='fold', flags=bit.bor(RANGE, WHOLEFOLD, TRLBAR, SBOXOK, CMDWIN), func='ex_fold', diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c index 9bcbfa2f26..ffafe3cffb 100644 --- a/src/nvim/ex_cmds2.c +++ b/src/nvim/ex_cmds2.c @@ -48,7 +48,6 @@ #include "nvim/regexp.h" #include "nvim/screen.h" #include "nvim/strings.h" -#include "nvim/term.h" #include "nvim/undo.h" #include "nvim/window.h" #include "nvim/profile.h" diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index bf9b5c16d7..22ffd67fdd 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -62,7 +62,6 @@ #include "nvim/strings.h" #include "nvim/syntax.h" #include "nvim/tag.h" -#include "nvim/term.h" #include "nvim/ui.h" #include "nvim/undo.h" #include "nvim/version.h" @@ -4333,7 +4332,7 @@ static void uc_list(char_u *name, size_t name_len) msg_outtrans_special(cmd->uc_rep, FALSE); if (p_verbose > 0) last_set_msg(cmd->uc_scriptID); - out_flush(); + ui_flush(); os_breakcheck(); if (got_int) break; @@ -5389,21 +5388,18 @@ static void ex_stop(exarg_T *eap) /* * Disallow suspending for "rvim". */ - if (!check_restricted() - ) { - if (!eap->forceit) + if (!check_restricted()) { + if (!eap->forceit) { autowrite_all(); - windgoto((int)Rows - 1, 0); - out_char('\n'); - out_flush(); - out_flush(); /* needed for SUN to restore xterm buffer */ - mch_restore_title(3); /* restore window titles */ + } + ui_cursor_goto((int)Rows - 1, 0); + ui_putc('\n'); + ui_flush(); ui_suspend(); /* call machine specific function */ maketitle(); resettitle(); /* force updating the title */ - scroll_start(); /* scroll screen before redrawing */ redraw_later_clear(); - shell_resized(); /* may have resized window */ + ui_refresh(); /* may have resized window */ } } @@ -5461,7 +5457,7 @@ static void ex_print(exarg_T *eap) eap->cmdidx == CMD_list || (eap->flags & EXFLAG_LIST)); if (++eap->line1 > eap->line2) break; - out_flush(); /* show one line at a time */ + ui_flush(); /* show one line at a time */ } setpcmark(); /* put cursor at last line */ @@ -5837,7 +5833,7 @@ static void ex_tabs(exarg_T *eap) msg_putchar('\n'); vim_snprintf((char *)IObuff, IOSIZE, _("Tab page %d"), tabcount++); msg_outtrans_attr(IObuff, hl_attr(HLF_T)); - out_flush(); /* output one line at a time */ + ui_flush(); /* output one line at a time */ os_breakcheck(); FOR_ALL_WINDOWS_IN_TAB(wp, tp) { @@ -5856,7 +5852,7 @@ static void ex_tabs(exarg_T *eap) home_replace(wp->w_buffer, wp->w_buffer->b_fname, IObuff, IOSIZE, TRUE); msg_outtrans(IObuff); - out_flush(); /* output one line at a time */ + ui_flush(); /* output one line at a time */ os_breakcheck(); } } @@ -5870,7 +5866,7 @@ static void ex_tabs(exarg_T *eap) static void ex_mode(exarg_T *eap) { if (*eap->arg == NUL) { - shell_resized(); + ui_refresh(); } else { EMSG(_(e_screenmode)); } @@ -6379,7 +6375,7 @@ static void ex_sleep(exarg_T *eap) if (cursor_valid()) { n = curwin->w_winrow + curwin->w_wrow - msg_scrolled; if (n >= 0) - windgoto((int)n, curwin->w_wincol + curwin->w_wcol); + ui_cursor_goto((int)n, curwin->w_wincol + curwin->w_wcol); } len = eap->line2; @@ -6398,8 +6394,8 @@ void do_sleep(long msec) { long done; - cursor_on(); - out_flush(); + ui_cursor_on(); + ui_flush(); for (done = 0; !got_int && done < msec; done += 1000L) { os_delay(msec - done > 1000L ? 1000L : msec - done, true); os_breakcheck(); @@ -6831,7 +6827,7 @@ static void ex_redraw(exarg_T *eap) /* No need to wait after an intentional redraw. */ need_wait_return = FALSE; - out_flush(); + ui_flush(); } /* @@ -6853,7 +6849,7 @@ static void ex_redrawstatus(exarg_T *eap) 0); RedrawingDisabled = r; p_lz = p; - out_flush(); + ui_flush(); } static void close_redir(void) diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 6a3bd16feb..3dffb1f1d3 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -59,7 +59,6 @@ #include "nvim/strings.h" #include "nvim/syntax.h" #include "nvim/tag.h" -#include "nvim/term.h" #include "nvim/window.h" #include "nvim/ui.h" #include "nvim/os/os.h" @@ -656,8 +655,8 @@ getcmdline ( if (ccheck_abbr(c + ABBR_OFF)) goto cmdline_changed; if (!cmd_silent) { - windgoto(msg_row, 0); - out_flush(); + ui_cursor_goto(msg_row, 0); + ui_flush(); } break; } @@ -1374,8 +1373,8 @@ cmdline_changed: if (ccline.cmdlen == 0) i = 0; else { - cursor_off(); /* so the user knows we're busy */ - out_flush(); + ui_cursor_off(); /* so the user knows we're busy */ + ui_flush(); ++emsg_off; /* So it doesn't beep if bad expr */ /* Set the time limit to half a second. */ tm = profile_setlimit(500L); @@ -1713,7 +1712,7 @@ getexmodeline ( /* Switch cursor on now. This avoids that it happens after the "\n", which * confuses the system function that computes tabstops. */ - cursor_on(); + ui_cursor_on(); /* always start in column 0; write a newline if necessary */ compute_cmdrow(); @@ -1821,7 +1820,7 @@ redraw: } } msg_clr_eos(); - windgoto(msg_row, msg_col); + ui_cursor_goto(msg_row, msg_col); continue; } @@ -1877,7 +1876,7 @@ redraw: ++line_ga.ga_len; escaped = FALSE; - windgoto(msg_row, msg_col); + ui_cursor_goto(msg_row, msg_col); pend = (char_u *)(line_ga.ga_data) + line_ga.ga_len; /* We are done when a NL is entered, but not when it comes after an @@ -2459,7 +2458,7 @@ void redrawcmd(void) /* when 'incsearch' is set there may be no command line while redrawing */ if (ccline.cmdbuff == NULL) { - windgoto(cmdline_row, 0); + ui_cursor_goto(cmdline_row, 0); msg_clr_eos(); return; } @@ -2512,7 +2511,7 @@ static void cursorcmd(void) msg_row = Rows - 1; } - windgoto(msg_row, msg_col); + ui_cursor_goto(msg_row, msg_col); } void gotocmdline(int clr) @@ -2524,7 +2523,7 @@ void gotocmdline(int clr) msg_col = 0; /* always start in column 0 */ if (clr) /* clear the bottom line(s) */ msg_clr_eos(); /* will reset clear_cmdline */ - windgoto(cmdline_row, 0); + ui_cursor_goto(cmdline_row, 0); } /* @@ -2585,7 +2584,7 @@ nextwild ( } MSG_PUTS("..."); /* show that we are busy */ - out_flush(); + ui_flush(); i = (int)(xp->xp_pattern - ccline.cmdbuff); xp->xp_pattern_len = ccline.cmdpos - i; @@ -3076,7 +3075,7 @@ static int showmatches(expand_T *xp, int wildmenu) msg_didany = FALSE; /* lines_left will be set */ msg_start(); /* prepare for paging */ msg_putchar('\n'); - out_flush(); + ui_flush(); cmdline_row = msg_row; msg_didany = FALSE; /* lines_left will be set again */ msg_start(); /* prepare for paging */ @@ -3173,7 +3172,7 @@ static int showmatches(expand_T *xp, int wildmenu) msg_clr_eos(); msg_putchar('\n'); } - out_flush(); /* show one line at a time */ + ui_flush(); /* show one line at a time */ if (got_int) { got_int = FALSE; break; @@ -4724,7 +4723,7 @@ void ex_history(exarg_T *eap) else STRCAT(IObuff, hist[i].hisstr); msg_outtrans(IObuff); - out_flush(); + ui_flush(); } if (i == idx) break; diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index cd27567bd8..651c57f5b6 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -53,7 +53,7 @@ #include "nvim/sha256.h" #include "nvim/strings.h" #include "nvim/tempfile.h" -#include "nvim/term.h" +#include "nvim/ui.h" #include "nvim/types.h" #include "nvim/undo.h" #include "nvim/window.h" @@ -221,7 +221,7 @@ void filemess(buf_T *buf, char_u *name, char_u *s, int attr) /* may truncate the message to avoid a hit-return prompt */ msg_outtrans_attr(msg_may_trunc(FALSE, IObuff), attr); msg_clr_eos(); - out_flush(); + ui_flush(); msg_scrolled_ign = FALSE; } @@ -3484,7 +3484,7 @@ restore_backup: * know we got the message. */ if (got_int) { MSG(_(e_interr)); - out_flush(); + ui_flush(); } if ((fd = os_open((char *)backup, O_RDONLY, 0)) >= 0) { if ((write_info.bw_fd = os_open((char *)fname, @@ -4682,7 +4682,7 @@ check_timestamps ( if (need_wait_return && didit == 2) { /* make sure msg isn't overwritten */ msg_puts((char_u *)"\n"); - out_flush(); + ui_flush(); } } return didit; @@ -4910,7 +4910,7 @@ buf_check_timestamp ( msg_clr_eos(); (void)msg_end(); if (emsg_silent == 0) { - out_flush(); + ui_flush(); /* give the user some time to think about it */ os_delay(1000L, true); diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c index b8a145483f..b3e274d952 100644 --- a/src/nvim/getchar.c +++ b/src/nvim/getchar.c @@ -47,7 +47,7 @@ #include "nvim/regexp.h" #include "nvim/screen.h" #include "nvim/strings.h" -#include "nvim/term.h" +#include "nvim/ui.h" #include "nvim/undo.h" #include "nvim/os/event.h" #include "nvim/os/input.h" @@ -2161,7 +2161,7 @@ static int vgetorpeek(int advance) } } setcursor(); - out_flush(); + ui_flush(); new_wcol = curwin->w_wcol; new_wrow = curwin->w_wrow; curwin->w_wcol = old_wcol; @@ -2380,8 +2380,8 @@ inchar ( int script_char; if (wait_time == -1L || wait_time > 100L) { /* flush output before waiting */ - cursor_on(); - out_flush(); + ui_cursor_on(); + ui_flush(); } /* @@ -2450,7 +2450,7 @@ inchar ( * Always flush the output characters when getting input characters * from the user. */ - out_flush(); + ui_flush(); /* * Fill up to a third of the buffer, because each character may be @@ -3246,7 +3246,7 @@ showmap ( } if (p_verbose > 0) last_set_msg(mp->m_script_ID); - out_flush(); /* show one line at a time */ + ui_flush(); /* show one line at a time */ } /* @@ -4084,75 +4084,6 @@ int put_escstr(FILE *fd, char_u *strstart, int what) } /* - * Check all mappings for the presence of special key codes. - * Used after ":set term=xxx". - */ -void check_map_keycodes(void) -{ - mapblock_T *mp; - char_u *p; - int i; - char_u buf[3]; - char_u *save_name; - int abbr; - int hash; - buf_T *bp; - - validate_maphash(); - save_name = sourcing_name; - sourcing_name = (char_u *)"mappings"; /* avoids giving error messages */ - - /* This this once for each buffer, and then once for global - * mappings/abbreviations with bp == NULL */ - for (bp = firstbuf;; bp = bp->b_next) { - /* - * Do the loop twice: Once for mappings, once for abbreviations. - * Then loop over all map hash lists. - */ - for (abbr = 0; abbr <= 1; ++abbr) - for (hash = 0; hash < 256; ++hash) { - if (abbr) { - if (hash) /* there is only one abbr list */ - break; - if (bp != NULL) - mp = bp->b_first_abbr; - else - mp = first_abbr; - } else { - if (bp != NULL) - mp = bp->b_maphash[hash]; - else - mp = maphash[hash]; - } - for (; mp != NULL; mp = mp->m_next) { - for (i = 0; i <= 1; ++i) { /* do this twice */ - if (i == 0) - p = mp->m_keys; /* once for the "from" part */ - else - p = mp->m_str; /* and once for the "to" part */ - while (*p) { - if (*p == K_SPECIAL) { - ++p; - if (*p < 128) { /* for "normal" tcap entries */ - buf[0] = p[0]; - buf[1] = p[1]; - buf[2] = NUL; - (void)add_termcap_entry(buf, FALSE); - } - ++p; - } - ++p; - } - } - } - } - if (bp == NULL) - break; - } - sourcing_name = save_name; -} - -/* * Check the string "keys" against the lhs of all mappings. * Return pointer to rhs of mapping (mapblock->m_str). * NULL when no mapping found. @@ -4236,3 +4167,71 @@ void add_map(char_u *map, int mode) free(s); p_cpo = cpo_save; } + +// Translate an internal mapping/abbreviation representation into the +// corresponding external one recognized by :map/:abbrev commands; +// respects the current B/k/< settings of 'cpoption'. +// +// This function is called when expanding mappings/abbreviations on the +// command-line, and for building the "Ambiguous mapping..." error message. +// +// It uses a growarray to build the translation string since the +// latter can be wider than the original description. The caller has to +// free the string afterwards. +// +// Returns NULL when there is a problem. +static char_u * translate_mapping ( + char_u *str, + int expmap // TRUE when expanding mappings on command-line +) +{ + garray_T ga; + ga_init(&ga, 1, 40); + + int cpo_bslash = (vim_strchr(p_cpo, CPO_BSLASH) != NULL); + int cpo_special = (vim_strchr(p_cpo, CPO_SPECI) != NULL); + + for (; *str; ++str) { + int c = *str; + if (c == K_SPECIAL && str[1] != NUL && str[2] != NUL) { + int modifiers = 0; + if (str[1] == KS_MODIFIER) { + str++; + modifiers = *++str; + c = *++str; + } + + if (c == K_SPECIAL && str[1] != NUL && str[2] != NUL) { + if (expmap && cpo_special) { + ga_clear(&ga); + return NULL; + } + c = TO_SPECIAL(str[1], str[2]); + if (c == K_ZERO) { + // display <Nul> as ^@ + c = NUL; + } + str += 2; + } + if (IS_SPECIAL(c) || modifiers) { /* special key */ + if (expmap && cpo_special) { + ga_clear(&ga); + return NULL; + } + ga_concat(&ga, get_special_key_name(c, modifiers)); + continue; /* for (str) */ + } + } + + if (c == ' ' || c == '\t' || c == Ctrl_J || c == Ctrl_V + || (c == '<' && !cpo_special) || (c == '\\' && !cpo_bslash)) { + ga_append(&ga, cpo_bslash ? Ctrl_V : '\\'); + } + + if (c) { + ga_append(&ga, (char)c); + } + } + ga_append(&ga, NUL); + return (char_u *)(ga.ga_data); +} diff --git a/src/nvim/globals.h b/src/nvim/globals.h index 86c28e823a..e6a8ee33c5 100644 --- a/src/nvim/globals.h +++ b/src/nvim/globals.h @@ -376,7 +376,6 @@ EXTERN int provider_call_nesting INIT(= 0); EXTERN char_u hash_removed; -EXTERN int scroll_region INIT(= FALSE); /* term supports scroll region */ EXTERN int t_colors INIT(= 0); /* int value of T_CCO */ /* diff --git a/src/nvim/hardcopy.c b/src/nvim/hardcopy.c index cc6aa57419..0da5caf7cd 100644 --- a/src/nvim/hardcopy.c +++ b/src/nvim/hardcopy.c @@ -41,7 +41,7 @@ #include "nvim/screen.h" #include "nvim/strings.h" #include "nvim/syntax.h" -#include "nvim/term.h" +#include "nvim/ui.h" #include "nvim/tempfile.h" #include "nvim/os/os.h" #include "nvim/os/input.h" @@ -572,7 +572,7 @@ static void prt_message(char_u *s) { screen_fill((int)Rows - 1, (int)Rows, 0, (int)Columns, ' ', ' ', 0); screen_puts(s, (int)Rows - 1, 0, hl_attr(HLF_R)); - out_flush(); + ui_flush(); } void ex_hardcopy(exarg_T *eap) diff --git a/src/nvim/keymap.c b/src/nvim/keymap.c index 67f342fd37..25a8457aba 100644 --- a/src/nvim/keymap.c +++ b/src/nvim/keymap.c @@ -10,8 +10,12 @@ #include "nvim/ascii.h" #include "nvim/keymap.h" #include "nvim/charset.h" +#include "nvim/memory.h" #include "nvim/edit.h" -#include "nvim/term.h" +#include "nvim/eval.h" +#include "nvim/message.h" +#include "nvim/strings.h" +#include "nvim/mouse.h" /* @@ -709,35 +713,18 @@ int find_special_key_in_table(int c) int get_special_key_code(char_u *name) { char_u *table_name; - char_u string[3]; int i, j; - /* - * If it's <t_xx> we get the code for xx from the termcap - */ - if (name[0] == 't' && name[1] == '_' && name[2] != NUL && name[3] != NUL) { - string[0] = name[2]; - string[1] = name[3]; - string[2] = NUL; - if (add_termcap_entry(string, FALSE) == OK) - return TERMCAP2KEY(name[2], name[3]); - } else - for (i = 0; key_names_table[i].name != NULL; i++) { - table_name = key_names_table[i].name; - for (j = 0; vim_isIDc(name[j]) && table_name[j] != NUL; j++) - if (TOLOWER_ASC(table_name[j]) != TOLOWER_ASC(name[j])) - break; - if (!vim_isIDc(name[j]) && table_name[j] == NUL) - return key_names_table[i].key; - } - return 0; -} + for (i = 0; key_names_table[i].name != NULL; i++) { + table_name = key_names_table[i].name; + for (j = 0; vim_isIDc(name[j]) && table_name[j] != NUL; j++) + if (TOLOWER_ASC(table_name[j]) != TOLOWER_ASC(name[j])) + break; + if (!vim_isIDc(name[j]) && table_name[j] == NUL) + return key_names_table[i].key; + } -char_u *get_key_name(size_t i) -{ - if (i >= KEY_NAMES_TABLE_LEN) - return NULL; - return key_names_table[i].name; + return 0; } /* @@ -756,3 +743,156 @@ int get_mouse_button(int code, bool *is_click, bool *is_drag) } return 0; /* Shouldn't get here */ } + +// Replace any terminal code strings in from[] with the equivalent internal +// vim representation. This is used for the "from" and "to" part of a +// mapping, and the "to" part of a menu command. +// Any strings like "<C-UP>" are also replaced, unless 'cpoptions' contains +// '<'. +// K_SPECIAL by itself is replaced by K_SPECIAL KS_SPECIAL KE_FILLER. +// +// The replacement is done in result[] and finally copied into allocated +// memory. If this all works well *bufp is set to the allocated memory and a +// pointer to it is returned. If something fails *bufp is set to NULL and from +// is returned. +// +// CTRL-V characters are removed. When "from_part" is TRUE, a trailing CTRL-V +// is included, otherwise it is removed (for ":map xx ^V", maps xx to +// nothing). When 'cpoptions' does not contain 'B', a backslash can be used +// instead of a CTRL-V. +char_u * replace_termcodes ( + char_u *from, + char_u **bufp, + int from_part, + int do_lt, // also translate <lt> + int special // always accept <key> notation +) +{ + ssize_t i; + size_t slen; + char_u key; + size_t dlen = 0; + char_u *src; + int do_backslash; // backslash is a special character + int do_special; // recognize <> key codes + char_u *result; // buffer for resulting string + + do_backslash = (vim_strchr(p_cpo, CPO_BSLASH) == NULL); + do_special = (vim_strchr(p_cpo, CPO_SPECI) == NULL) || special; + + // Allocate space for the translation. Worst case a single character is + // replaced by 6 bytes (shifted special key), plus a NUL at the end. + result = xmalloc(STRLEN(from) * 6 + 1); + + src = from; + + // Check for #n at start only: function key n + if (from_part && src[0] == '#' && VIM_ISDIGIT(src[1])) { // function key + result[dlen++] = K_SPECIAL; + result[dlen++] = 'k'; + if (src[1] == '0') { + result[dlen++] = ';'; // #0 is F10 is "k;" + } else { + result[dlen++] = src[1]; // #3 is F3 is "k3" + } + src += 2; + } + + // Copy each byte from *from to result[dlen] + while (*src != NUL) { + // If 'cpoptions' does not contain '<', check for special key codes, + // like "<C-S-LeftMouse>" + if (do_special && (do_lt || STRNCMP(src, "<lt>", 4) != 0)) { + // Replace <SID> by K_SNR <script-nr> _. + // (room: 5 * 6 = 30 bytes; needed: 3 + <nr> + 1 <= 14) + if (STRNICMP(src, "<SID>", 5) == 0) { + if (current_SID <= 0) { + EMSG(_(e_usingsid)); + } else { + src += 5; + result[dlen++] = K_SPECIAL; + result[dlen++] = (int)KS_EXTRA; + result[dlen++] = (int)KE_SNR; + sprintf((char *)result + dlen, "%" PRId64, (int64_t)current_SID); + dlen += STRLEN(result + dlen); + result[dlen++] = '_'; + continue; + } + } + + slen = trans_special(&src, result + dlen, TRUE); + if (slen) { + dlen += slen; + continue; + } + } + + if (do_special) { + char_u *p, *s, len; + + // Replace <Leader> by the value of "mapleader". + // Replace <LocalLeader> by the value of "maplocalleader". + // If "mapleader" or "maplocalleader" isn't set use a backslash. + if (STRNICMP(src, "<Leader>", 8) == 0) { + len = 8; + p = get_var_value((char_u *)"g:mapleader"); + } else if (STRNICMP(src, "<LocalLeader>", 13) == 0) { + len = 13; + p = get_var_value((char_u *)"g:maplocalleader"); + } else { + len = 0; + p = NULL; + } + + if (len != 0) { + // Allow up to 8 * 6 characters for "mapleader". + if (p == NULL || *p == NUL || STRLEN(p) > 8 * 6) { + s = (char_u *)"\\"; + } else { + s = p; + } + while (*s != NUL) { + result[dlen++] = *s++; + } + src += len; + continue; + } + } + + // Remove CTRL-V and ignore the next character. + // For "from" side the CTRL-V at the end is included, for the "to" + // part it is removed. + // If 'cpoptions' does not contain 'B', also accept a backslash. + key = *src; + if (key == Ctrl_V || (do_backslash && key == '\\')) { + ++src; // skip CTRL-V or backslash + if (*src == NUL) { + if (from_part) { + result[dlen++] = key; + } + break; + } + } + + // skip multibyte char correctly + for (i = (*mb_ptr2len)(src); i > 0; --i) { + // If the character is K_SPECIAL, replace it with K_SPECIAL + // KS_SPECIAL KE_FILLER. + // If compiled with the GUI replace CSI with K_CSI. + if (*src == K_SPECIAL) { + result[dlen++] = K_SPECIAL; + result[dlen++] = KS_SPECIAL; + result[dlen++] = KE_FILLER; + } else { + result[dlen++] = *src; + } + ++src; + } + } + result[dlen] = NUL; + + *bufp = xrealloc(result, dlen + 1); + + return *bufp; +} + diff --git a/src/nvim/main.c b/src/nvim/main.c index f2891f0979..897f251bb3 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -55,7 +55,6 @@ #include "nvim/screen.h" #include "nvim/strings.h" #include "nvim/syntax.h" -#include "nvim/term.h" #include "nvim/ui.h" #include "nvim/version.h" #include "nvim/window.h" @@ -234,26 +233,16 @@ int main(int argc, char **argv) if (recoverymode && fname == NULL) params.want_full_screen = FALSE; - // term_init() sets up the terminal (window) for use. This must be - // done after resetting full_screen, otherwise it may move the cursor - term_init(); - TIME_MSG("shell init"); + setbuf(stdout, NULL); /* This message comes before term inits, but after setting "silent_mode" * when the input is not a tty. */ if (GARGCOUNT > 1 && !silent_mode) printf(_("%d files to edit\n"), GARGCOUNT); - if (params.want_full_screen && !silent_mode) { - termcapinit((uint8_t *)"abstract_ui"); - screen_start(); /* don't know where cursor is now */ - TIME_MSG("Termcap init"); - } - event_init(); full_screen = true; t_colors = 256; - T_CCO = (uint8_t *)"256"; check_tty(¶ms); /* @@ -364,13 +353,6 @@ int main(int argc, char **argv) if (params.edit_type == EDIT_STDIN && !recoverymode) read_stdin(); -#if defined(UNIX) - /* When switching screens and something caused a message from a vimrc - * script, need to output an extra newline on exit. */ - if ((did_emsg || msg_didout) && *T_TI != NUL) - newline_on_exit = TRUE; -#endif - if (!params.headless && (params.output_isatty || params.err_isatty)) { if (params.input_isatty && (need_wait_return || msg_didany)) { // Since at this point there's no UI instance running yet, error messages @@ -388,16 +370,9 @@ int main(int argc, char **argv) } setmouse(); // may start using the mouse + ui_reset_scroll_region(); // In case Rows changed - if (scroll_region) { - scroll_region_reset(); // In case Rows changed - } - - scroll_start(); // may scroll the screen to the right position - - /* - * Don't clear the screen when starting in Ex mode, unless using the GUI. - */ + // Don't clear the screen when starting in Ex mode, unless using the GUI. if (exmode_active) must_redraw = CLEAR; else { @@ -668,7 +643,7 @@ main_loop ( curwin->w_valid &= ~VALID_CROW; } setcursor(); - cursor_on(); + ui_cursor_on(); do_redraw = FALSE; @@ -724,7 +699,7 @@ void getout(int exitval) exitval += ex_exitval; /* Position the cursor on the last screen line, below all the text */ - windgoto((int)Rows - 1, 0); + ui_cursor_goto((int)Rows - 1, 0); /* Optionally print hashtable efficiency. */ hash_debug_results(); @@ -780,7 +755,7 @@ void getout(int exitval) } /* Position the cursor again, the autocommands may have moved it */ - windgoto((int)Rows - 1, 0); + ui_cursor_goto((int)Rows - 1, 0); #if defined(USE_ICONV) && defined(DYNAMIC_ICONV) iconv_end(); @@ -1490,7 +1465,7 @@ static void handle_quickfix(mparm_T *paramp) paramp->use_ef, OPT_FREE, SID_CARG); vim_snprintf((char *)IObuff, IOSIZE, "cfile %s", p_ef); if (qf_init(NULL, p_ef, p_efm, TRUE, IObuff) < 0) { - out_char('\n'); + ui_putc('\n'); mch_exit(3); } TIME_MSG("reading errorfile"); @@ -1540,7 +1515,7 @@ static void check_tty(mparm_T *parmp) mch_errmsg(_("Vim: Warning: Input is not from a terminal\n")); } - out_flush(); + ui_flush(); if (scriptin[0] == NULL) { os_delay(2000L, true); diff --git a/src/nvim/mark.c b/src/nvim/mark.c index ddbe4e76cb..228ba3a925 100644 --- a/src/nvim/mark.c +++ b/src/nvim/mark.c @@ -37,7 +37,7 @@ #include "nvim/quickfix.h" #include "nvim/search.h" #include "nvim/strings.h" -#include "nvim/term.h" +#include "nvim/ui.h" #include "nvim/os/os.h" #include "nvim/os/input.h" @@ -701,7 +701,7 @@ show_one_mark ( free(name); } } - out_flush(); /* show one line at a time */ + ui_flush(); /* show one line at a time */ } } @@ -813,7 +813,7 @@ void ex_jumps(exarg_T *eap) free(name); os_breakcheck(); } - out_flush(); + ui_flush(); } if (curwin->w_jumplistidx == curwin->w_jumplistlen) MSG_PUTS("\n>"); @@ -847,7 +847,7 @@ void ex_changes(exarg_T *eap) free(name); os_breakcheck(); } - out_flush(); + ui_flush(); } if (curwin->w_changelistidx == curbuf->b_changelistlen) MSG_PUTS("\n>"); diff --git a/src/nvim/memfile.c b/src/nvim/memfile.c index d8d59474a2..baab70ee6a 100644 --- a/src/nvim/memfile.c +++ b/src/nvim/memfile.c @@ -954,7 +954,6 @@ static void mf_do_open(memfile_T *mfp, char_u *fname, int flags) #ifdef HAVE_SELINUX mch_copy_sec(fname, mfp->mf_fname); #endif - mch_hide(mfp->mf_fname); // try setting the 'hidden' flag } } diff --git a/src/nvim/memline.c b/src/nvim/memline.c index 29b372e057..817fd08a9c 100644 --- a/src/nvim/memline.c +++ b/src/nvim/memline.c @@ -69,7 +69,7 @@ #include "nvim/sha256.h" #include "nvim/spell.h" #include "nvim/strings.h" -#include "nvim/term.h" +#include "nvim/ui.h" #include "nvim/tempfile.h" #include "nvim/undo.h" #include "nvim/window.h" @@ -969,7 +969,7 @@ void ml_recover(void) || org_file_info.stat.st_mtim.tv_sec != mtime)) { EMSG(_("E308: Warning: Original file may have been changed")); } - out_flush(); + ui_flush(); /* Get the 'fileformat' and 'fileencoding' from block zero. */ b0_ff = (b0p->b0_flags & B0_FF_MASK); @@ -1436,7 +1436,7 @@ recover_names ( } } else MSG_PUTS(_(" -- none --\n")); - out_flush(); + ui_flush(); } else file_count += num_files; diff --git a/src/nvim/memory.c b/src/nvim/memory.c index c954ab3c7b..cb9ad97749 100644 --- a/src/nvim/memory.c +++ b/src/nvim/memory.c @@ -13,7 +13,7 @@ #include "nvim/memory.h" #include "nvim/message.h" #include "nvim/misc1.h" -#include "nvim/term.h" +#include "nvim/ui.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "memory.c.generated.h" @@ -86,8 +86,8 @@ void *xmalloc(size_t size) { void *ret = try_malloc(size); if (!ret) { - OUT_STR(e_outofmem); - out_char('\n'); + mch_errmsg(e_outofmem); + mch_errmsg("\n"); preserve_exit(); } return ret; @@ -109,8 +109,8 @@ void *xcalloc(size_t count, size_t size) try_to_free_memory(); ret = calloc(allocated_count, allocated_size); if (!ret) { - OUT_STR(e_outofmem); - out_char('\n'); + mch_errmsg(e_outofmem); + mch_errmsg("\n"); preserve_exit(); } } @@ -131,8 +131,8 @@ void *xrealloc(void *ptr, size_t size) try_to_free_memory(); ret = realloc(ptr, allocated_size); if (!ret) { - OUT_STR(e_outofmem); - out_char('\n'); + mch_errmsg(e_outofmem); + mch_errmsg("\n"); preserve_exit(); } } @@ -149,7 +149,7 @@ void *xmallocz(size_t size) { size_t total_size = size + 1; if (total_size < size) { - OUT_STR(_("Vim: Data too large to fit into virtual memory space\n")); + mch_errmsg(_("Vim: Data too large to fit into virtual memory space\n")); preserve_exit(); } @@ -369,8 +369,8 @@ char *xstrdup(const char *str) try_to_free_memory(); ret = strdup(str); if (!ret) { - OUT_STR(e_outofmem); - out_char('\n'); + mch_errmsg(e_outofmem); + mch_errmsg("\n"); preserve_exit(); } } @@ -524,7 +524,6 @@ void free_all_mem(void) /* Obviously named calls. */ free_all_autocmds(); - clear_termcodes(); free_all_options(); free_all_marks(); alist_clear(&global_alist); @@ -591,11 +590,6 @@ void free_all_mem(void) free_tabpage(first_tabpage); first_tabpage = NULL; -# ifdef UNIX - /* Machine-specific free. */ - mch_free_mem(); -# endif - /* message history */ for (;; ) if (delete_first_msg() == FAIL) @@ -603,8 +597,6 @@ void free_all_mem(void) eval_clear(); - free_termoptions(); - /* screenlines (can't display anything now!) */ free_screenlines(); diff --git a/src/nvim/menu.c b/src/nvim/menu.c index 9c1ca71477..2b1bc3b721 100644 --- a/src/nvim/menu.c +++ b/src/nvim/menu.c @@ -29,7 +29,6 @@ #include "nvim/keymap.h" #include "nvim/garray.h" #include "nvim/strings.h" -#include "nvim/term.h" #define MENUDEPTH 10 /* maximum depth of menus */ diff --git a/src/nvim/message.c b/src/nvim/message.c index 5179921d76..24cb727802 100644 --- a/src/nvim/message.c +++ b/src/nvim/message.c @@ -39,7 +39,6 @@ #include "nvim/normal.h" #include "nvim/screen.h" #include "nvim/strings.h" -#include "nvim/term.h" #include "nvim/ui.h" #include "nvim/mouse.h" #include "nvim/os/os.h" @@ -928,7 +927,7 @@ void wait_return(int redraw) } if (tmpState == SETWSIZE) { /* got resize event while in vgetc() */ - shell_resized(); + ui_refresh(); } else if (!skip_redraw && (redraw == TRUE || (msg_scrolled != 0 && redraw != -1))) { redraw_later(VALID); @@ -1002,7 +1001,7 @@ void msg_start(void) msg_starthere(); if (msg_silent == 0) { msg_didout = FALSE; /* no output on current line yet */ - cursor_off(); + ui_cursor_off(); } /* when redirecting, may need to start a new line. */ @@ -1758,7 +1757,7 @@ static void msg_puts_display(char_u *str, int maxlen, int attr, int recurse) static void msg_scroll_up(void) { /* scrolling up always works */ - screen_del_lines(0, 0, 1, (int)Rows, TRUE, NULL); + screen_del_lines(0, 0, 1, (int)Rows, NULL); } /* @@ -2321,7 +2320,7 @@ void repeat_message(void) display_confirm_msg(); /* display ":confirm" message again */ msg_row = Rows - 1; } else if (State == EXTERNCMD) { - windgoto(msg_row, msg_col); /* put cursor back */ + ui_cursor_goto(msg_row, msg_col); /* put cursor back */ } else if (State == HITRETURN || State == SETWSIZE) { if (msg_row == Rows - 1) { /* Avoid drawing the "hit-enter" prompt below the previous one, @@ -2353,22 +2352,12 @@ void msg_clr_eos(void) */ void msg_clr_eos_force(void) { - if (msg_use_printf()) { - if (full_screen) { /* only when termcap codes are valid */ - if (*T_CD) - out_str(T_CD); /* clear to end of display */ - else if (*T_CE) - out_str(T_CE); /* clear to end of line */ - } + if (cmdmsg_rl) { + screen_fill(msg_row, msg_row + 1, 0, msg_col + 1, ' ', ' ', 0); + screen_fill(msg_row + 1, (int)Rows, 0, (int)Columns, ' ', ' ', 0); } else { - if (cmdmsg_rl) { - screen_fill(msg_row, msg_row + 1, 0, msg_col + 1, ' ', ' ', 0); - screen_fill(msg_row + 1, (int)Rows, 0, (int)Columns, ' ', ' ', 0); - } else { - screen_fill(msg_row, msg_row + 1, msg_col, (int)Columns, - ' ', ' ', 0); - screen_fill(msg_row + 1, (int)Rows, 0, (int)Columns, ' ', ' ', 0); - } + screen_fill(msg_row, msg_row + 1, msg_col, (int)Columns, ' ', ' ', 0); + screen_fill(msg_row + 1, (int)Rows, 0, (int)Columns, ' ', ' ', 0); } } @@ -2399,7 +2388,7 @@ int msg_end(void) wait_return(FALSE); return FALSE; } - out_flush(); + ui_flush(); return TRUE; } diff --git a/src/nvim/misc1.c b/src/nvim/misc1.c index a7e471625b..19ddf6f82c 100644 --- a/src/nvim/misc1.c +++ b/src/nvim/misc1.c @@ -53,7 +53,6 @@ #include "nvim/search.h" #include "nvim/strings.h" #include "nvim/tag.h" -#include "nvim/term.h" #include "nvim/tempfile.h" #include "nvim/ui.h" #include "nvim/undo.h" @@ -1844,7 +1843,7 @@ void changed(void) * message. Since we could be anywhere, call wait_return() now, * and don't let the emsg() set msg_scroll. */ if (need_wait_return && emsg_silent == 0) { - out_flush(); + ui_flush(); os_delay(2000L, true); wait_return(TRUE); msg_scroll = save_msg_scroll; @@ -2265,7 +2264,7 @@ change_warning ( msg_clr_eos(); (void)msg_end(); if (msg_silent == 0 && !silent_mode) { - out_flush(); + ui_flush(); os_delay(1000L, true); /* give the user time to think about it */ } curbuf->b_did_warn = true; @@ -2308,7 +2307,7 @@ int ask_yesno(char_u *str, int direct) if (r == Ctrl_C || r == ESC) r = 'n'; msg_putchar(r); /* show what you typed */ - out_flush(); + ui_flush(); } --no_wait_return; State = save_State; @@ -2367,8 +2366,8 @@ int get_keystroke(void) mapped_ctrl_c = FALSE; /* mappings are not used here */ for (;; ) { - cursor_on(); - out_flush(); + ui_cursor_on(); + ui_flush(); /* Leave some room for check_termcode() to insert a key code into (max * 5 chars plus NUL). And fix_input_buffer() can triple the number of @@ -2471,7 +2470,7 @@ get_number ( ++no_mapping; ++allow_keys; /* no mapping here, but recognize keys */ for (;; ) { - windgoto(msg_row, msg_col); + ui_cursor_goto(msg_row, msg_col); c = safe_vgetc(); if (VIM_ISDIGIT(c)) { n = n * 10 + c - '0'; @@ -2600,11 +2599,10 @@ void beep_flush(void) void vim_beep(void) { if (emsg_silent == 0) { - if (p_vb - ) { - out_str(T_VB); + if (p_vb) { + ui_visual_bell(); } else { - out_char(BELL); + ui_putc(BELL); } /* When 'verbose' is set and we are sourcing a script or executing a @@ -3313,17 +3311,16 @@ void preserve_exit(void) } really_exiting = true; - out_str(IObuff); - screen_start(); // don't know where cursor is now - out_flush(); + mch_errmsg(IObuff); + mch_errmsg("\n"); + ui_flush(); ml_close_notmod(); // close all not-modified buffers FOR_ALL_BUFFERS(buf) { if (buf->b_ml.ml_mfp != NULL && buf->b_ml.ml_mfp->mf_fname != NULL) { - OUT_STR("Vim: preserving files...\n"); - screen_start(); // don't know where cursor is now - out_flush(); + mch_errmsg((uint8_t *)"Vim: preserving files...\n"); + ui_flush(); ml_sync_all(false, false); // preserve all swap files break; } @@ -3331,7 +3328,7 @@ void preserve_exit(void) ml_close_all(false); // close all memfiles, without deleting - OUT_STR("Vim: Finished.\n"); + mch_errmsg("Vim: Finished.\n"); getout(1); } diff --git a/src/nvim/misc2.c b/src/nvim/misc2.c index 1407dcf04b..be5150fdc0 100644 --- a/src/nvim/misc2.c +++ b/src/nvim/misc2.c @@ -49,7 +49,7 @@ #include "nvim/strings.h" #include "nvim/syntax.h" #include "nvim/tag.h" -#include "nvim/term.h" +#include "nvim/ui.h" #include "nvim/window.h" #include "nvim/os/os.h" #include "nvim/os/shell.h" @@ -296,8 +296,8 @@ int call_shell(char_u *cmd, ShellOpts opts, char_u *extra_shell_arg) verbose_enter(); smsg((char_u *)_("Calling shell to execute: \"%s\""), cmd == NULL ? p_sh : cmd); - out_char('\n'); - cursor_on(); + ui_putc('\n'); + ui_cursor_on(); verbose_leave(); } @@ -333,11 +333,6 @@ int call_shell(char_u *cmd, ShellOpts opts, char_u *extra_shell_arg) if (ecmd != cmd) free(ecmd); } - /* - * Check the window size, in case it changed while executing the - * external command. - */ - shell_resized_check(); } set_vim_var_nr(VV_SHELL_ERROR, (long)retval); diff --git a/src/nvim/mouse.c b/src/nvim/mouse.c index 84a1732a6a..5d1c5b35db 100644 --- a/src/nvim/mouse.c +++ b/src/nvim/mouse.c @@ -8,7 +8,6 @@ #include "nvim/screen.h" #include "nvim/ui.h" #include "nvim/os_unix.h" -#include "nvim/term.h" #include "nvim/fold.h" #include "nvim/diff.h" #include "nvim/move.h" @@ -20,6 +19,9 @@ # include "mouse.c.generated.h" #endif +static linenr_T orig_topline = 0; +static int orig_topfill = 0; + // Move the cursor to the specified row and column on the screen. // Change current window if necessary. Returns an integer with the // CURSOR_MOVED bit set if the cursor has moved or unset otherwise. @@ -492,3 +494,12 @@ int mouse_has(int c) } return false; } + +// Set orig_topline. Used when jumping to another window, so that a double +// click still works. +void set_mouse_topline(win_T *wp) +{ + orig_topline = wp->w_topline; + orig_topfill = wp->w_topfill; +} + diff --git a/src/nvim/mouse.h b/src/nvim/mouse.h index 4f797c7480..c824bcc8f0 100644 --- a/src/nvim/mouse.h +++ b/src/nvim/mouse.h @@ -25,6 +25,16 @@ #define MOUSE_MAY_STOP_VIS 0x10 // may stop Visual mode #define MOUSE_RELEASED 0x20 // button was released +// Codes for mouse button events in lower three bits: +#define MOUSE_LEFT 0x00 +#define MOUSE_MIDDLE 0x01 +#define MOUSE_RIGHT 0x02 +#define MOUSE_RELEASE 0x03 + +#define MOUSE_X1 0x300 // Mouse-button X1 (6th) +#define MOUSE_X2 0x400 // Mouse-button X2 + + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "mouse.h.generated.h" #endif diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c index 58c181e4de..3df3200d3d 100644 --- a/src/nvim/msgpack_rpc/channel.c +++ b/src/nvim/msgpack_rpc/channel.c @@ -24,7 +24,6 @@ #include "nvim/memory.h" #include "nvim/os_unix.h" #include "nvim/message.h" -#include "nvim/term.h" #include "nvim/map.h" #include "nvim/log.h" #include "nvim/misc1.h" @@ -407,8 +406,8 @@ static void parse_msgpack(RStream *rstream, void *data, bool eof) } if (result == MSGPACK_UNPACK_NOMEM_ERROR) { - OUT_STR(e_outofmem); - out_char('\n'); + mch_errmsg(e_outofmem); + mch_errmsg("\n"); decref(channel); preserve_exit(); } diff --git a/src/nvim/normal.c b/src/nvim/normal.c index 8c7deaa243..3906226b2e 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -57,7 +57,6 @@ #include "nvim/strings.h" #include "nvim/syntax.h" #include "nvim/tag.h" -#include "nvim/term.h" #include "nvim/ui.h" #include "nvim/mouse.h" #include "nvim/undo.h" @@ -427,7 +426,7 @@ normal_cmd ( int c; bool ctrl_w = false; /* got CTRL-W command */ int old_col = curwin->w_curswant; - bool need_flushbuf; /* need to call out_flush() */ + bool need_flushbuf; /* need to call ui_flush() */ pos_T old_pos; /* cursor position before command */ int mapped_len; static int old_mapped_len = 0; @@ -869,7 +868,7 @@ getcount: * mappings. */ if (need_flushbuf) - out_flush(); + ui_flush(); if (ca.cmdchar != K_IGNORE) did_cursorhold = false; @@ -987,8 +986,8 @@ getcount: free(kmsg); } setcursor(); - cursor_on(); - out_flush(); + ui_cursor_on(); + ui_flush(); if (msg_scroll || emsg_on_display) os_delay(1000L, true); /* wait at least one second */ os_delay(3000L, false); /* wait up to three seconds */ @@ -3002,7 +3001,7 @@ static void display_showcmd(void) { int len; - cursor_off(); + ui_cursor_off(); len = (int)STRLEN(showcmd_buf); if (len == 0) diff --git a/src/nvim/ops.c b/src/nvim/ops.c index cdd2ddcc12..395ddf95a7 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -45,7 +45,7 @@ #include "nvim/screen.h" #include "nvim/search.h" #include "nvim/strings.h" -#include "nvim/term.h" +#include "nvim/ui.h" #include "nvim/undo.h" #include "nvim/window.h" #include "nvim/os/input.h" @@ -3243,7 +3243,7 @@ void ex_display(exarg_T *eap) } if (n > 1 && yb->y_type == MLINE) MSG_PUTS_ATTR("^J", attr); - out_flush(); /* show one line at a time */ + ui_flush(); /* show one line at a time */ } os_breakcheck(); } diff --git a/src/nvim/option.c b/src/nvim/option.c index bf7d0d0bf3..5435a1adeb 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -77,7 +77,7 @@ #include "nvim/spell.h" #include "nvim/strings.h" #include "nvim/syntax.h" -#include "nvim/term.h" +#include "nvim/ui.h" #include "nvim/undo.h" #include "nvim/window.h" #include "nvim/os/os.h" @@ -1531,10 +1531,6 @@ static vimoption_T {"tagstack", "tgst", P_BOOL|P_VI_DEF, (char_u *)&p_tgst, PV_NONE, {(char_u *)TRUE, (char_u *)0L} SCRIPTID_INIT}, - {"term", NULL, P_STRING|P_EXPAND|P_NODEFAULT|P_NO_MKRC|P_VI_DEF| - P_RALL, - (char_u *)&T_NAME, PV_NONE, - {(char_u *)"", (char_u *)0L} SCRIPTID_INIT}, {"termbidi", "tbidi", P_BOOL|P_VI_DEF, (char_u *)&p_tbidi, PV_NONE, {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, @@ -1580,9 +1576,6 @@ static vimoption_T {"ttimeoutlen", "ttm", P_NUM|P_VI_DEF, (char_u *)&p_ttm, PV_NONE, {(char_u *)-1L, (char_u *)0L} SCRIPTID_INIT}, - {"ttybuiltin", "tbi", P_BOOL|P_VI_DEF, - (char_u *)&p_tbi, PV_NONE, - {(char_u *)TRUE, (char_u *)0L} SCRIPTID_INIT}, {"ttymouse", "ttym", P_STRING|P_NODEFAULT|P_NO_MKRC|P_VI_DEF, #if defined(FEAT_MOUSE) && defined(UNIX) (char_u *)&p_ttym, PV_NONE, @@ -1590,13 +1583,6 @@ static vimoption_T (char_u *)NULL, PV_NONE, #endif {(char_u *)"", (char_u *)0L} SCRIPTID_INIT}, - {"ttyscroll", "tsl", P_NUM|P_VI_DEF, - (char_u *)&p_ttyscroll, PV_NONE, - {(char_u *)999L, (char_u *)0L} SCRIPTID_INIT}, - {"ttytype", "tty", P_STRING|P_EXPAND|P_NODEFAULT|P_NO_MKRC|P_VI_DEF| - P_RALL, - (char_u *)&T_NAME, PV_NONE, - {(char_u *)"", (char_u *)0L} SCRIPTID_INIT}, {"undodir", "udir", P_STRING|P_EXPAND|P_COMMA|P_NODUP|P_SECURE|P_VI_DEF, (char_u *)&p_udir, PV_NONE, {(char_u *)".", (char_u *)0L} @@ -1660,9 +1646,6 @@ static vimoption_T {"warn", NULL, P_BOOL|P_VI_DEF, (char_u *)&p_warn, PV_NONE, {(char_u *)TRUE, (char_u *)0L} SCRIPTID_INIT}, - {"weirdinvert", "wiv", P_BOOL|P_VI_DEF|P_RCLR, - (char_u *)&p_wiv, PV_NONE, - {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, {"whichwrap", "ww", P_STRING|P_VIM|P_COMMA|P_FLAGLIST, (char_u *)&p_ww, PV_NONE, {(char_u *)"", (char_u *)"b,s"} SCRIPTID_INIT}, @@ -1739,69 +1722,6 @@ static vimoption_T (char_u *)&p_wd, PV_NONE, {(char_u *)0L, (char_u *)0L} SCRIPTID_INIT}, - /* terminal output codes */ -#define p_term(sss, vvv) {sss, NULL, P_STRING|P_VI_DEF|P_RALL|P_SECURE, \ - (char_u *)&vvv, PV_NONE, \ - {(char_u *)"", (char_u *)0L} SCRIPTID_INIT}, - - p_term("t_AB", T_CAB) - p_term("t_AF", T_CAF) - p_term("t_AL", T_CAL) - p_term("t_al", T_AL) - p_term("t_bc", T_BC) - p_term("t_cd", T_CD) - p_term("t_ce", T_CE) - p_term("t_cl", T_CL) - p_term("t_cm", T_CM) - p_term("t_Co", T_CCO) - p_term("t_CS", T_CCS) - p_term("t_cs", T_CS) - p_term("t_CV", T_CSV) - p_term("t_ut", T_UT) - p_term("t_da", T_DA) - p_term("t_db", T_DB) - p_term("t_DL", T_CDL) - p_term("t_dl", T_DL) - p_term("t_fs", T_FS) - p_term("t_IE", T_CIE) - p_term("t_IS", T_CIS) - p_term("t_ke", T_KE) - p_term("t_ks", T_KS) - p_term("t_le", T_LE) - p_term("t_mb", T_MB) - p_term("t_md", T_MD) - p_term("t_me", T_ME) - p_term("t_mr", T_MR) - p_term("t_ms", T_MS) - p_term("t_nd", T_ND) - p_term("t_op", T_OP) - p_term("t_RI", T_CRI) - p_term("t_RV", T_CRV) - p_term("t_u7", T_U7) - p_term("t_Sb", T_CSB) - p_term("t_Sf", T_CSF) - p_term("t_se", T_SE) - p_term("t_so", T_SO) - p_term("t_sr", T_SR) - p_term("t_ts", T_TS) - p_term("t_te", T_TE) - p_term("t_ti", T_TI) - p_term("t_ue", T_UE) - p_term("t_us", T_US) - p_term("t_vb", T_VB) - p_term("t_ve", T_VE) - p_term("t_vi", T_VI) - p_term("t_vs", T_VS) - p_term("t_WP", T_CWP) - p_term("t_WS", T_CWS) - p_term("t_SI", T_CSI) - p_term("t_EI", T_CEI) - p_term("t_xs", T_XS) - p_term("t_ZH", T_CZH) - p_term("t_ZR", T_CZR) - - /* terminal key codes are not in here */ - /* end marker */ { NULL, NULL, 0, NULL, PV_NONE, {NULL, NULL} SCRIPTID_INIT @@ -2018,7 +1938,7 @@ void set_init_1(void) * Don't set the P_ALLOCED flag, because we don't want to free the * default. */ - for (opt_idx = 0; !istermoption(&options[opt_idx]); opt_idx++) { + for (opt_idx = 0; options[opt_idx].fullname; opt_idx++) { if ((options[opt_idx].flags & P_GETTEXT) && options[opt_idx].var != NULL) p = (char_u *)_(*(char **)options[opt_idx].var); @@ -2183,7 +2103,7 @@ set_options_default ( int opt_flags /* OPT_FREE, OPT_LOCAL and/or OPT_GLOBAL */ ) { - for (int i = 0; !istermoption(&options[i]); i++) { + for (int i = 0; options[i].fullname; i++) { if (!(options[i].flags & P_NODEFAULT)) { set_option_default(i, opt_flags, p_cp); } @@ -2236,7 +2156,7 @@ void free_all_options(void) { int i; - for (i = 0; !istermoption(&options[i]); i++) { + for (i = 0; options[i].fullname; i++) { if (options[i].indir == PV_NONE) { /* global option: free value and default value. */ if (options[i].flags & P_ALLOCED && options[i].var != NULL) @@ -2278,55 +2198,11 @@ void set_init_2(void) if (!option_was_set((char_u *)"window")) p_window = Rows - 1; set_number_default("window", Rows - 1); - - /* For DOS console the default is always black. */ - /* - * If 'background' wasn't set by the user, try guessing the value, - * depending on the terminal name. Only need to check for terminals - * with a dark background, that can handle color. - */ - idx = findoption((char_u *)"bg"); - if (idx >= 0 && !(options[idx].flags & P_WAS_SET) - && *term_bg_default() == 'd') { - set_string_option_direct(NULL, idx, (char_u *)"dark", OPT_FREE, 0); - /* don't mark it as set, when starting the GUI it may be - * changed again */ - options[idx].flags &= ~P_WAS_SET; - } - parse_shape_opt(SHAPE_CURSOR); /* set cursor shapes from 'guicursor' */ (void)parse_printoptions(); /* parse 'printoptions' default value */ } /* - * Return "dark" or "light" depending on the kind of terminal. - * This is just guessing! Recognized are: - * "linux" Linux console - * "screen.linux" Linux console with screen - * "cygwin" Cygwin shell - * "putty" Putty program - * We also check the COLORFGBG environment variable, which is set by - * rxvt and derivatives. This variable contains either two or three - * values separated by semicolons; we want the last value in either - * case. If this value is 0-6 or 8, our background is dark. - */ -static char_u *term_bg_default(void) -{ - char_u *p; - - if (STRCMP(T_NAME, "linux") == 0 - || STRCMP(T_NAME, "screen.linux") == 0 - || STRCMP(T_NAME, "cygwin") == 0 - || STRCMP(T_NAME, "putty") == 0 - || ((p = (char_u *)os_getenv("COLORFGBG")) != NULL - && (p = vim_strrchr(p, ';')) != NULL - && ((p[1] >= '0' && p[1] <= '6') || p[1] == '8') - && p[2] == NUL)) - return (char_u *)"dark"; - return (char_u *)"light"; -} - -/* * Initialize the options, part three: After reading the .vimrc */ void set_init_3(void) @@ -2435,7 +2311,6 @@ void set_helplang_default(char_u *lang) void set_title_defaults(void) { int idx1; - int val; /* * If GUI is (going to be) used, we can always set the window title and @@ -2444,15 +2319,13 @@ void set_title_defaults(void) */ idx1 = findoption((char_u *)"title"); if (idx1 >= 0 && !(options[idx1].flags & P_WAS_SET)) { - val = mch_can_restore_title(); - options[idx1].def_val[VI_DEFAULT] = (char_u *)(intptr_t)val; - p_title = val; + options[idx1].def_val[VI_DEFAULT] = (char_u *)(intptr_t)0; + p_title = 0; } idx1 = findoption((char_u *)"icon"); if (idx1 >= 0 && !(options[idx1].flags & P_WAS_SET)) { - val = mch_can_restore_icon(); - options[idx1].def_val[VI_DEFAULT] = (char_u *)(intptr_t)val; - p_icon = val; + options[idx1].def_val[VI_DEFAULT] = (char_u *)(intptr_t)0; + p_icon = 0; } } @@ -2495,7 +2368,6 @@ do_set ( int prepending; /* "opt^=arg" */ int removing; /* "opt-=arg" */ int cp_val = 0; - char_u key_name[2]; if (*arg == NUL) { showoptions(0, opt_flags); @@ -2524,8 +2396,6 @@ do_set ( } } else if (STRNCMP(arg, "termcap", 7) == 0 && !(opt_flags & OPT_MODELINE)) { - showoptions(2, opt_flags); - show_termcodes(); did_show = TRUE; arg += 7; } else { @@ -2622,13 +2492,6 @@ do_set ( varp = get_varp_scope(&(options[opt_idx]), opt_flags); } else { flags = P_STRING; - if (key < 0) { - key_name[0] = (char_u)KEY2TERMCAP0(key); - key_name[1] = KEY2TERMCAP1(key); - } else { - key_name[0] = KS_KEY; - key_name[1] = (char_u)(key & 0xff); - } } /* Skip all options that are not window-local (used when showing @@ -2716,14 +2579,8 @@ do_set ( (int)options[opt_idx].indir & PV_MASK]); } } else { - char_u *p; - - p = find_termcode(key_name); - if (p == NULL) { - errmsg = (char_u *)N_("E846: Key code not set"); - goto skip; - } else - (void)show_one_termcode(key_name, p, TRUE); + errmsg = (char_u *)N_("E846: Key code not set"); + goto skip; } if (nextchar != '?' && nextchar != NUL && !vim_iswhite(afterchar)) @@ -2867,11 +2724,6 @@ do_set ( newval = options[opt_idx].def_val[ ((flags & P_VI_DEF) || cp_val) ? VI_DEFAULT : VIM_DEFAULT]; - if ((char_u **)varp == &p_bg) { - /* guess the value of 'background' */ - newval = term_bg_default(); - } - /* expand environment variables and ~ (since the * default value was already expanded, only * required when an environment variable was set @@ -3126,25 +2978,9 @@ do_set ( /* If error detected, print the error message. */ if (errmsg != NULL) goto skip; - } else { /* key code option */ - char_u *p; - - if (nextchar == '&') { - if (add_termcap_entry(key_name, TRUE) == FAIL) - errmsg = (char_u *)N_("E522: Not found in termcap"); - } else { - ++arg; /* jump to after the '=' or ':' */ - for (p = arg; *p && !vim_iswhite(*p); ++p) - if (*p == '\\' && p[1] != NUL) - ++p; - nextchar = *p; - *p = NUL; - add_termcode(key_name, arg, FALSE); - *p = nextchar; - } - if (full_screen) - ttest(FALSE); - redraw_all_later(CLEAR); + } else { + // key code option(FIXME(tarruda): Show a warning or something + // similar) } } @@ -3199,8 +3035,8 @@ theend: silent_mode = FALSE; info_message = TRUE; /* use mch_msg(), not mch_errmsg() */ msg_putchar('\n'); - cursor_on(); /* msg_start() switches it off */ - out_flush(); + ui_cursor_on(); /* msg_start() switches it off */ + ui_flush(); silent_mode = TRUE; info_message = FALSE; /* use mch_msg(), not mch_errmsg() */ } @@ -3279,7 +3115,7 @@ static char_u *check_cedit(void) /* * When changing 'title', 'titlestring', 'icon' or 'iconstring', call * maketitle() to create and display it. - * When switching the title or icon off, call mch_restore_title() to get + * When switching the title or icon off, call ui_set_{icon,title}(NULL) to get * the old value back. */ static void @@ -3287,15 +3123,16 @@ did_set_title ( int icon /* Did set icon instead of title */ ) { - if (starting != NO_SCREEN - ) { + if (starting != NO_SCREEN) { maketitle(); if (icon) { - if (!p_icon) - mch_restore_title(2); + if (!p_icon) { + ui_set_icon(NULL); + } } else { - if (!p_title) - mch_restore_title(1); + if (!p_title) { + ui_set_title(NULL); + } } } } @@ -3549,21 +3386,6 @@ static void check_string_option(char_u **pp) } /* - * Mark a terminal option as allocated, found by a pointer into term_strings[]. - */ -void set_term_option_alloced(char_u **p) -{ - int opt_idx; - - for (opt_idx = 1; options[opt_idx].fullname != NULL; opt_idx++) - if (options[opt_idx].var == (char_u *)p) { - options[opt_idx].flags |= P_ALLOCED; - return; - } - return; /* cannot happen: didn't find it! */ -} - -/* * Return TRUE when option "opt" was set from a modeline or in secure mode. * Return FALSE when it wasn't. * Return -1 for an unknown option. @@ -3765,16 +3587,6 @@ did_set_string_option ( && vim_strpbrk(*varp, (char_u *)"/\\*?[|<>") != NULL) { errmsg = e_invarg; } - /* 'term' */ - else if (varp == &T_NAME) { - if (T_NAME[0] == NUL) - errmsg = (char_u *)N_("E529: Cannot set 'term' to empty string"); - else if (set_termname(T_NAME) == FAIL) - errmsg = (char_u *)N_("E522: Not found in termcap"); - else - /* Screen colors may have changed. */ - redraw_later_clear(); - } /* 'backupcopy' */ else if (gvarp == &p_bkc) { char_u *bkc = p_bkc; @@ -4155,32 +3967,6 @@ did_set_string_option ( if (*p_viminfo && errmsg == NULL && get_viminfo_parameter('\'') < 0) errmsg = (char_u *)N_("E528: Must specify a ' value"); } - /* terminal options */ - else if (istermoption(&options[opt_idx]) && full_screen) { - /* ":set t_Co=0" and ":set t_Co=1" do ":set t_Co=" */ - if (varp == &T_CCO) { - int colors = atoi((char *)T_CCO); - - /* Only reinitialize colors if t_Co value has really changed to - * avoid expensive reload of colorscheme if t_Co is set to the - * same value multiple times. */ - if (colors != t_colors) { - t_colors = colors; - if (t_colors <= 1) { - if (new_value_alloced) - free(T_CCO); - T_CCO = empty_option; - } - /* We now have a different color setup, initialize it again. */ - init_highlight(TRUE, FALSE); - } - } - ttest(FALSE); - if (varp == &T_ME) { - out_str(T_ME); - redraw_later(CLEAR); - } - } /* 'showbreak' */ else if (varp == &p_sbr) { for (s = p_sbr; *s; ) { @@ -4595,10 +4381,11 @@ did_set_string_option ( } if (varp == &p_mouse) { - if (*p_mouse == NUL) - mch_setmouse(FALSE); /* switch mouse off */ - else - setmouse(); /* in case 'mouse' changed */ + if (*p_mouse == NUL) { + ui_mouse_off(); + } else { + setmouse(); // in case 'mouse' changed + } } if (curwin->w_curswant != MAXCOL @@ -5104,16 +4891,6 @@ set_bool_option ( } else if ((int *)varp == &p_ea) { if (p_ea && !old_value) win_equal(curwin, FALSE, 0); - } else if ((int *)varp == &p_wiv) { - /* - * When 'weirdinvert' changed, set/reset 't_xs'. - * Then set 'weirdinvert' according to value of 't_xs'. - */ - if (p_wiv && !old_value) - T_XS = (char_u *)"y"; - else if (!p_wiv && old_value) - T_XS = empty_option; - p_wiv = (*T_XS != NUL); } else if ((int *)varp == &p_acd) { /* Change directories when the 'acd' option is set now. */ do_autochdir(); @@ -5712,6 +5489,64 @@ static int findoption(char_u *arg) return opt_idx; } +bool is_tty_option(char *name) +{ + return (name[0] == 't' && name[1] == '_') || !strcmp((char *)name, "term"); +} + +#define TCO_BUFFER_SIZE 8 +bool get_tty_option(char *name, char **value) +{ + if (!strcmp(name, "t_Co")) { + if (value) { + if (t_colors <= 1) { + *value = xstrdup(""); + } else { + *value = xmalloc(TCO_BUFFER_SIZE); + snprintf(*value, TCO_BUFFER_SIZE, "%d", t_colors); + } + } + return true; + } + + if (!strcmp(name, "term") || !strcmp(name, "ttytype")) { + if (value) { + *value = xstrdup("nvim"); + } + return true; + } + + if (is_tty_option(name)) { + if (value) { + *value = xstrdup(""); + } + return true; + } + + return false; +} + +bool set_tty_option(char *name, char *value) +{ + if (!strcmp(name, "t_Co")) { + int colors = atoi(value); + + // Only reinitialize colors if t_Co value has really changed to + // avoid expensive reload of colorscheme if t_Co is set to the + // same value multiple times + if (colors != t_colors) { + t_colors = colors; + // We now have a different color setup, initialize it again. + init_highlight(TRUE, FALSE); + } + + return true; + } + + return is_tty_option(name) || !strcmp(name, "term") + || !strcmp(name, "ttytype"); +} + /* * Get the value for an option. * @@ -5730,6 +5565,10 @@ get_option_value ( int opt_flags ) { + if (get_tty_option((char *)name, (char **)stringval)) { + return 0; + } + int opt_idx; char_u *varp; @@ -5785,6 +5624,10 @@ int get_option_value_strict(char *name, int opt_type, void *from) { + if (get_tty_option(name, stringval)) { + return SOPT_STRING | SOPT_GLOBAL; + } + char_u *varp = NULL; vimoption_T *p; int rv = 0; @@ -5896,6 +5739,10 @@ set_option_value ( int opt_flags /* OPT_LOCAL or 0 (both) */ ) { + if (set_tty_option((char *)name, (char *)string)) { + return NULL; + } + int opt_idx; char_u *varp; @@ -5992,7 +5839,6 @@ static int find_key_option(char_u *arg) /* * if 'all' == 0: show changed options * if 'all' == 1: show all normal options - * if 'all' == 2: show all terminal options */ static void showoptions ( @@ -6002,7 +5848,6 @@ showoptions ( { vimoption_T *p; int col; - int isterm; char_u *varp; int item_count; int run; @@ -6038,16 +5883,13 @@ showoptions ( item_count = 0; for (p = &options[0]; p->fullname != NULL; p++) { varp = NULL; - isterm = istermoption(p); if (opt_flags != 0) { - if (p->indir != PV_NONE && !isterm) + if (p->indir != PV_NONE) varp = get_varp_scope(p, opt_flags); } else varp = get_varp(p); if (varp != NULL - && ((all == 2 && isterm) - || (all == 1 && !isterm) - || (all == 0 && !optval_default(p, varp)))) { + && (all == 1 || (all == 0 && !optval_default(p, varp)))) { if (p->flags & P_BOOL) len = 1; /* a toggle option fits always */ else { @@ -6084,7 +5926,7 @@ showoptions ( showoneopt(items[i], opt_flags); col += INC; } - out_flush(); + ui_flush(); os_breakcheck(); } } @@ -6189,7 +6031,7 @@ int makeset(FILE *fd, int opt_flags, int local_only) * P_PRI_MKRC flag and once without. */ for (pri = 1; pri >= 0; --pri) { - for (p = &options[0]; !istermoption(p); p++) + for (p = &options[0]; p->fullname; p++) if (!(p->flags & P_NO_MKRC) && ((pri == 1) == ((p->flags & P_PRI_MKRC) != 0))) { /* skip global option when only doing locals */ @@ -6355,91 +6197,6 @@ static int put_setbool(FILE *fd, char *cmd, char *name, int value) } /* - * Clear all the terminal options. - * If the option has been allocated, free the memory. - * Terminal options are never hidden or indirect. - */ -void clear_termoptions(void) -{ - /* - * Reset a few things before clearing the old options. This may cause - * outputting a few things that the terminal doesn't understand, but the - * screen will be cleared later, so this is OK. - */ - mch_setmouse(FALSE); /* switch mouse off */ - mch_restore_title(3); /* restore window titles */ - - free_termoptions(); -} - -void free_termoptions(void) -{ - vimoption_T *p; - - for (p = &options[0]; p->fullname != NULL; p++) - if (istermoption(p)) { - if (p->flags & P_ALLOCED) - free_string_option(*(char_u **)(p->var)); - if (p->flags & P_DEF_ALLOCED) - free_string_option(p->def_val[VI_DEFAULT]); - *(char_u **)(p->var) = empty_option; - p->def_val[VI_DEFAULT] = empty_option; - p->flags &= ~(P_ALLOCED|P_DEF_ALLOCED); - } - clear_termcodes(); -} - -/* - * Free the string for one term option, if it was allocated. - * Set the string to empty_option and clear allocated flag. - * "var" points to the option value. - */ -void free_one_termoption(char_u *var) -{ - vimoption_T *p; - - for (p = &options[0]; p->fullname != NULL; p++) - if (p->var == var) { - if (p->flags & P_ALLOCED) - free_string_option(*(char_u **)(p->var)); - *(char_u **)(p->var) = empty_option; - p->flags &= ~P_ALLOCED; - break; - } -} - -/* - * Set the terminal option defaults to the current value. - * Used after setting the terminal name. - */ -void set_term_defaults(void) -{ - vimoption_T *p; - - for (p = &options[0]; p->fullname != NULL; p++) { - if (istermoption(p) && p->def_val[VI_DEFAULT] != *(char_u **)(p->var)) { - if (p->flags & P_DEF_ALLOCED) { - free_string_option(p->def_val[VI_DEFAULT]); - p->flags &= ~P_DEF_ALLOCED; - } - p->def_val[VI_DEFAULT] = *(char_u **)(p->var); - if (p->flags & P_ALLOCED) { - p->flags |= P_DEF_ALLOCED; - p->flags &= ~P_ALLOCED; /* don't free the value now */ - } - } - } -} - -/* - * return TRUE if 'p' starts with 't_' - */ -static int istermoption(vimoption_T *p) -{ - return p->fullname[0] == 't' && p->fullname[1] == '_'; -} - -/* * Compute columns for ruler and shown command. 'sc_col' is also used to * decide what the maximum length of a message on the status line can be. * If there is a status line for the last window, 'sc_col' is independent @@ -7229,14 +6986,11 @@ set_context_in_set_cmd ( int ExpandSettings(expand_T *xp, regmatch_T *regmatch, int *num_file, char_u ***file) { - int num_normal = 0; /* Nr of matching non-term-code settings */ - int num_term = 0; /* Nr of matching terminal code settings */ + int num_normal = 0; // Nr of matching non-term-code settings int match; int count = 0; char_u *str; int loop; - int is_term_opt; - char_u name_buf[MAX_KEY_NAME_LEN]; static char *(names[]) = {"all", "termcap"}; int ic = regmatch->rm_ic; /* remember the ignore-case flag */ @@ -7263,99 +7017,28 @@ int ExpandSettings(expand_T *xp, regmatch_T *regmatch, int *num_file, char_u *** if (xp->xp_context == EXPAND_BOOL_SETTINGS && !(options[opt_idx].flags & P_BOOL)) continue; - is_term_opt = istermoption(&options[opt_idx]); - if (is_term_opt && num_normal > 0) - continue; match = FALSE; if (vim_regexec(regmatch, str, (colnr_T)0) || (options[opt_idx].shortname != NULL && vim_regexec(regmatch, - (char_u *)options[opt_idx].shortname, (colnr_T)0))) + (char_u *)options[opt_idx].shortname, (colnr_T)0))){ match = TRUE; - else if (is_term_opt) { - name_buf[0] = '<'; - name_buf[1] = 't'; - name_buf[2] = '_'; - name_buf[3] = str[2]; - name_buf[4] = str[3]; - name_buf[5] = '>'; - name_buf[6] = NUL; - if (vim_regexec(regmatch, name_buf, (colnr_T)0)) { - match = TRUE; - str = name_buf; - } } + if (match) { if (loop == 0) { - if (is_term_opt) - num_term++; - else - num_normal++; + num_normal++; } else (*file)[count++] = vim_strsave(str); } } - /* - * Check terminal key codes, these are not in the option table - */ - if (xp->xp_context != EXPAND_BOOL_SETTINGS && num_normal == 0) { - for (size_t opt_idx = 0; (str = get_termcode(opt_idx)) != NULL; opt_idx++) { - if (!isprint(str[0]) || !isprint(str[1])) - continue; - - name_buf[0] = 't'; - name_buf[1] = '_'; - name_buf[2] = str[0]; - name_buf[3] = str[1]; - name_buf[4] = NUL; - match = FALSE; - if (vim_regexec(regmatch, name_buf, (colnr_T)0)) - match = TRUE; - else { - name_buf[0] = '<'; - name_buf[1] = 't'; - name_buf[2] = '_'; - name_buf[3] = str[0]; - name_buf[4] = str[1]; - name_buf[5] = '>'; - name_buf[6] = NUL; - - if (vim_regexec(regmatch, name_buf, (colnr_T)0)) - match = TRUE; - } - if (match) { - if (loop == 0) - num_term++; - else - (*file)[count++] = vim_strsave(name_buf); - } - } - - /* - * Check special key names. - */ - regmatch->rm_ic = TRUE; /* ignore case here */ - for (size_t opt_idx = 0; (str = get_key_name(opt_idx)) != NULL; opt_idx++) { - name_buf[0] = '<'; - STRCPY(name_buf + 1, str); - STRCAT(name_buf, ">"); - - if (vim_regexec(regmatch, name_buf, (colnr_T)0)) { - if (loop == 0) - num_term++; - else - (*file)[count++] = vim_strsave(name_buf); - } - } - } if (loop == 0) { - if (num_normal > 0) + if (num_normal > 0) { *num_file = num_normal; - else if (num_term > 0) - *num_file = num_term; - else + } else { return OK; + } *file = (char_u **)xmalloc((size_t)(*num_file) * sizeof(char_u *)); } } @@ -7373,9 +7056,7 @@ void ExpandOldSetting(int *num_file, char_u ***file) * For a terminal key code expand_option_idx is < 0. */ if (expand_option_idx < 0) { - var = find_termcode(expand_option_name + 2); - if (var == NULL) - expand_option_idx = findoption(expand_option_name); + expand_option_idx = findoption(expand_option_name); } if (expand_option_idx >= 0) { diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h index c8b63cd155..c75137f765 100644 --- a/src/nvim/option_defs.h +++ b/src/nvim/option_defs.h @@ -568,7 +568,6 @@ EXTERN char_u *p_titlestring; /* 'titlestring' */ EXTERN char_u *p_tsr; /* 'thesaurus' */ EXTERN int p_ttimeout; /* 'ttimeout' */ EXTERN long p_ttm; /* 'ttimeoutlen' */ -EXTERN int p_tbi; /* 'ttybuiltin' */ EXTERN long p_ttyscroll; /* 'ttyscroll' */ #if defined(FEAT_MOUSE) && defined(UNIX) EXTERN char_u *p_ttym; /* 'ttymouse' */ @@ -615,7 +614,6 @@ EXTERN char_u *p_wop; /* 'wildoptions' */ EXTERN long p_window; /* 'window' */ EXTERN char_u *p_wak; /* 'winaltkeys' */ EXTERN char_u *p_wig; /* 'wildignore' */ -EXTERN int p_wiv; /* 'weirdinvert' */ EXTERN char_u *p_ww; /* 'whichwrap' */ EXTERN long p_wc; /* 'wildchar' */ EXTERN long p_wcm; /* 'wildcharm' */ diff --git a/src/nvim/os/event.c b/src/nvim/os/event.c index 9a15bf92d0..c4d38c6a28 100644 --- a/src/nvim/os/event.c +++ b/src/nvim/os/event.c @@ -18,7 +18,7 @@ #include "nvim/vim.h" #include "nvim/memory.h" #include "nvim/misc2.h" -#include "nvim/term.h" +#include "nvim/ui.h" #include "nvim/screen.h" #include "nvim/lib/klist.h" @@ -162,7 +162,7 @@ void event_process(void) if (must_redraw) { update_screen(0); - out_flush(); + ui_flush(); } } diff --git a/src/nvim/os/shell.c b/src/nvim/os/shell.c index d481d6af56..32c7ea564d 100644 --- a/src/nvim/os/shell.c +++ b/src/nvim/os/shell.c @@ -17,7 +17,7 @@ #include "nvim/vim.h" #include "nvim/message.h" #include "nvim/memory.h" -#include "nvim/term.h" +#include "nvim/ui.h" #include "nvim/misc2.h" #include "nvim/screen.h" #include "nvim/memline.h" @@ -99,7 +99,7 @@ int os_call_shell(char_u *cmd, ShellOpts opts, char_u *extra_args) char *output = NULL, **output_ptr = NULL; int current_state = State; bool forward_output = true; - out_flush(); + ui_flush(); // While the child is running, ignore terminating signals signal_reject_deadly(); @@ -421,7 +421,7 @@ static size_t write_output(char *output, size_t remaining, bool to_buffer, if (to_buffer) { ml_append(curwin->w_cursor.lnum++, (char_u *)output, 0, false); } else { - screen_del_lines(0, 0, 1, (int)Rows, true, NULL); + screen_del_lines(0, 0, 1, (int)Rows, NULL); screen_puts_len((char_u *)output, (int)off, lastrow, 0, 0); } size_t skip = off + 1; @@ -446,7 +446,7 @@ static size_t write_output(char *output, size_t remaining, bool to_buffer, // remember that the NL was missing curbuf->b_no_eol_lnum = curwin->w_cursor.lnum; } else { - screen_del_lines(0, 0, 1, (int)Rows, true, NULL); + screen_del_lines(0, 0, 1, (int)Rows, NULL); screen_puts_len((char_u *)output, (int)remaining, lastrow, 0, 0); } output += remaining; @@ -455,7 +455,7 @@ static size_t write_output(char *output, size_t remaining, bool to_buffer, } } - out_flush(); + ui_flush(); return (size_t)(output - start); } diff --git a/src/nvim/os/signal.c b/src/nvim/os/signal.c index df21bed446..a332ad2314 100644 --- a/src/nvim/os/signal.c +++ b/src/nvim/os/signal.c @@ -9,7 +9,6 @@ #include "nvim/globals.h" #include "nvim/memline.h" #include "nvim/eval.h" -#include "nvim/term.h" #include "nvim/memory.h" #include "nvim/misc1.h" #include "nvim/misc2.h" diff --git a/src/nvim/os/time.c b/src/nvim/os/time.c index b69be88fc7..63570e9a0c 100644 --- a/src/nvim/os/time.c +++ b/src/nvim/os/time.c @@ -8,7 +8,6 @@ #include "nvim/os/time.h" #include "nvim/os/event.h" #include "nvim/vim.h" -#include "nvim/term.h" static uv_mutex_t delay_mutex; static uv_cond_t delay_cond; diff --git a/src/nvim/os_unix.c b/src/nvim/os_unix.c index bfdf5969ff..87ef1220e7 100644 --- a/src/nvim/os_unix.c +++ b/src/nvim/os_unix.c @@ -43,7 +43,6 @@ #include "nvim/strings.h" #include "nvim/syntax.h" #include "nvim/tempfile.h" -#include "nvim/term.h" #include "nvim/ui.h" #include "nvim/types.h" #include "nvim/os/os.h" @@ -69,119 +68,6 @@ static int selinux_enabled = -1; #ifdef INCLUDE_GENERATED_DECLARATIONS # include "os_unix.c.generated.h" #endif -static char_u *oldtitle = NULL; -static int did_set_title = FALSE; -static char_u *oldicon = NULL; -static int did_set_icon = FALSE; - -static int get_x11_title(int test_only) -{ - return FALSE; -} - -static int get_x11_icon(int test_only) -{ - if (!test_only) { - if (STRNCMP(T_NAME, "builtin_", 8) == 0) - oldicon = vim_strsave(T_NAME + 8); - else - oldicon = vim_strsave(T_NAME); - } - return FALSE; -} - - -int mch_can_restore_title(void) -{ - return get_x11_title(TRUE); -} - -int mch_can_restore_icon(void) -{ - return get_x11_icon(TRUE); -} - -/* - * Set the window title and icon. - */ -void mch_settitle(char_u *title, char_u *icon) -{ - static int recursive = 0; - - if (T_NAME == NULL) /* no terminal name (yet) */ - return; - if (title == NULL && icon == NULL) /* nothing to do */ - return; - - /* When one of the X11 functions causes a deadly signal, we get here again - * recursively. Avoid hanging then (something is probably locked). */ - if (recursive) - return; - ++recursive; - - if (title != NULL) { - ui_set_title((char *)title); - did_set_title = TRUE; - } - - if (icon != NULL) { - ui_set_icon((char *)icon); - did_set_icon = TRUE; - } - --recursive; -} - -/* - * Restore the window/icon title. - * "which" is one of: - * 1 only restore title - * 2 only restore icon - * 3 restore title and icon - */ -void mch_restore_title(int which) -{ - /* only restore the title or icon when it has been set */ - mch_settitle(((which & 1) && did_set_title) ? - (oldtitle ? oldtitle : p_titleold) : NULL, - ((which & 2) && did_set_icon) ? oldicon : NULL); -} - - -/* - * Return TRUE if "name" looks like some xterm name. - * Seiichi Sato mentioned that "mlterm" works like xterm. - */ -int vim_is_xterm(char_u *name) -{ - if (name == NULL) - return FALSE; - return STRNICMP(name, "xterm", 5) == 0 - || STRNICMP(name, "nxterm", 6) == 0 - || STRNICMP(name, "kterm", 5) == 0 - || STRNICMP(name, "mlterm", 6) == 0 - || STRNICMP(name, "rxvt", 4) == 0 - || STRCMP(name, "builtin_xterm") == 0; -} - -/* - * Return non-zero when using an xterm mouse, according to 'ttymouse'. - * Return 1 for "xterm". - * Return 2 for "xterm2". - * Return 3 for "urxvt". - * Return 4 for "sgr". - */ -int use_xterm_mouse(void) -{ - if (ttym_flags == TTYM_SGR) - return 4; - if (ttym_flags == TTYM_URXVT) - return 3; - if (ttym_flags == TTYM_XTERM2) - return 2; - if (ttym_flags == TTYM_XTERM) - return 1; - return 0; -} #if defined(USE_FNAME_CASE) /* @@ -323,14 +209,6 @@ void mch_free_acl(vim_acl_T aclent) #endif /* - * Set hidden flag for "name". - */ -void mch_hide(char_u *name) -{ - /* can't hide a file */ -} - -/* * Check what "name" is: * NODE_NORMAL: file or directory (or doesn't exist) * NODE_WRITABLE: writable device, socket, fifo, etc. @@ -350,69 +228,20 @@ int mch_nodetype(char_u *name) return NODE_WRITABLE; } -#if defined(EXITFREE) -void mch_free_mem(void) -{ - free(oldtitle); - free(oldicon); -} - -#endif - - -/* - * Output a newline when exiting. - * Make sure the newline goes to the same stream as the text. - */ -static void exit_scroll(void) -{ - if (silent_mode) - return; - if (newline_on_exit || msg_didout) { - if (msg_use_printf()) { - if (info_message) - mch_msg("\n"); - else - mch_errmsg("\r\n"); - } else - out_char('\n'); - } else { - restore_cterm_colors(); /* get original colors back */ - msg_clr_eos_force(); /* clear the rest of the display */ - windgoto((int)Rows - 1, 0); /* may have moved the cursor */ - } -} - void mch_exit(int r) { exiting = TRUE; { - mch_restore_title(3); /* restore xterm title and icon name */ - /* - * When t_ti is not empty but it doesn't cause swapping terminal - * pages, need to output a newline when msg_didout is set. But when - * t_ti does swap pages it should not go to the shell page. Do this - * before stoptermcap(). - */ - if (swapping_screen() && !newline_on_exit) - exit_scroll(); - ui_builtin_stop(); - /* - * A newline is only required after a message in the alternate screen. - * This is set to TRUE by wait_return(). - */ - if (!swapping_screen() || newline_on_exit) - exit_scroll(); - - /* Cursor may have been switched off without calling starttermcap() - * when doing "vim -u vimrc" and vimrc contains ":q". */ - if (full_screen) - cursor_on(); + // Cursor may have been switched off without calling starttermcap() + // when doing "vim -u vimrc" and vimrc contains ":q". */ + if (full_screen) { + ui_cursor_on(); + } } - out_flush(); + ui_flush(); ml_close_all(TRUE); /* remove all memfiles */ event_teardown(); @@ -425,57 +254,6 @@ void mch_exit(int r) } /* - * Set mouse clicks on or off. - */ -void mch_setmouse(int on) -{ - static int ison = FALSE; - int xterm_mouse_vers; - - if (on == ison) /* return quickly if nothing to do */ - return; - - xterm_mouse_vers = use_xterm_mouse(); - - if (ttym_flags == TTYM_URXVT) { - out_str_nf((char_u *) - (on - ? "\033[?1015h" - : "\033[?1015l")); - ison = on; - } - - if (ttym_flags == TTYM_SGR) { - out_str_nf((char_u *) - (on - ? "\033[?1006h" - : "\033[?1006l")); - ison = on; - } - - if (xterm_mouse_vers > 0) { - if (on) /* enable mouse events, use mouse tracking if available */ - out_str_nf((char_u *) - (xterm_mouse_vers > 1 - ? "\033[?1002h" - : "\033[?1000h")); - else /* disable mouse events, could probably always send the same */ - out_str_nf((char_u *) - (xterm_mouse_vers > 1 - ? "\033[?1002l" - : "\033[?1000l")); - ison = on; - } else if (ttym_flags == TTYM_DEC) { - if (on) /* enable mouse events */ - out_str_nf((char_u *)"\033[1;2'z\033[1;3'{"); - else /* disable mouse events */ - out_str_nf((char_u *)"\033['z"); - ison = on; - } - -} - -/* * mch_expand_wildcards() - this code does wild-card pattern matching using * the shell * diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index 4baba00ccf..b025d3a5e1 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -47,7 +47,7 @@ #include "nvim/screen.h" #include "nvim/search.h" #include "nvim/strings.h" -#include "nvim/term.h" +#include "nvim/ui.h" #include "nvim/tempfile.h" #include "nvim/window.h" #include "nvim/os/os.h" @@ -1786,7 +1786,7 @@ void qf_list(exarg_T *eap) ? skipwhite(qfp->qf_text) : qfp->qf_text, IObuff, IOSIZE); msg_prt_line(IObuff, FALSE); - out_flush(); /* show one line at a time */ + ui_flush(); /* show one line at a time */ } qfp = qfp->qf_next; @@ -2845,7 +2845,7 @@ void ex_vimgrep(exarg_T *eap) msg_didout = FALSE; /* overwrite this message */ msg_nowait = TRUE; /* don't wait for this message */ msg_col = 0; - out_flush(); + ui_flush(); } buf = buflist_findname_exp(fnames[fi]); diff --git a/src/nvim/screen.c b/src/nvim/screen.c index cec5753879..8ba7de83a6 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -130,7 +130,6 @@ #include "nvim/spell.h" #include "nvim/strings.h" #include "nvim/syntax.h" -#include "nvim/term.h" #include "nvim/ui.h" #include "nvim/undo.h" #include "nvim/version.h" @@ -146,12 +145,6 @@ */ static int screen_attr = 0; -/* - * Positioning the cursor is reduced by remembering the last position. - * Mostly used by windgoto() and screen_char(). - */ -static int screen_cur_row, screen_cur_col; /* last known cursor position */ - static match_T search_hl; /* used for 'hlsearch' highlight matching */ static foldinfo_T win_foldinfo; /* info for 'foldcolumn' */ @@ -422,7 +415,7 @@ void update_screen(int type) search_hl.rm.regprog = NULL; FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { if (wp->w_redr_type != 0) { - cursor_off(); + ui_cursor_off(); if (!did_one) { did_one = TRUE; start_search_hl(); @@ -432,7 +425,7 @@ void update_screen(int type) /* redraw status line after the window to minimize cursor movement */ if (wp->w_redr_status) { - cursor_off(); + ui_cursor_off(); win_redr_status(wp); } } @@ -507,7 +500,6 @@ void update_single_line(win_T *wp, linenr_T lnum) row = 0; for (j = 0; j < wp->w_lines_valid; ++j) { if (lnum == wp->w_lines[j].wl_lnum) { - screen_start(); /* not sure of screen cursor */ init_search_hl(wp); start_search_hl(); prepare_search_hl(wp, lnum); @@ -528,7 +520,7 @@ void update_single_line(win_T *wp, linenr_T lnum) */ static void update_prepare(void) { - cursor_off(); + ui_cursor_off(); updating_screen = TRUE; start_search_hl(); } @@ -4065,7 +4057,7 @@ win_line ( break; } - if (screen_cur_row == screen_row - 1 + if (ui_current_row() == screen_row - 1 && filler_todo <= 0 && wp->w_width == Columns) { /* Remember that the line wraps, used for modeless copy. */ @@ -4096,7 +4088,7 @@ win_line ( * then output the same character again to let the * terminal know about the wrap. If the terminal doesn't * auto-wrap, we overwrite the character. */ - if (screen_cur_col != wp->w_width) + if (ui_current_col() != wp->w_width) screen_char(LineOffset[screen_row - 1] + (unsigned)Columns - 1, screen_row - 1, (int)(Columns - 1)); @@ -4105,14 +4097,13 @@ win_line ( * space to keep it simple. */ if (has_mbyte && MB_BYTE2LEN(ScreenLines[LineOffset[ screen_row - - 1] + (Columns - 1)]) > 1) - out_char(' '); - else - out_char(ScreenLines[LineOffset[screen_row - 1] - + (Columns - 1)]); + 1] + (Columns - 1)]) > 1) { + ui_putc(' '); + } else { + ui_putc(ScreenLines[LineOffset[screen_row - 1] + (Columns - 1)]); + } /* force a redraw of the first char on the next line */ ScreenAttrs[LineOffset[screen_row]] = (sattr_T)-1; - screen_start(); /* don't know where cursor is now */ } } @@ -4271,42 +4262,6 @@ static void screen_line(int row, int coloff, int endcol, int clear_width, int rl if (redraw_this) { - /* - * Special handling when 'xs' termcap flag set (hpterm): - * Attributes for characters are stored at the position where the - * cursor is when writing the highlighting code. The - * start-highlighting code must be written with the cursor on the - * first highlighted character. The stop-highlighting code must - * be written with the cursor just after the last highlighted - * character. - * Overwriting a character doesn't remove it's highlighting. Need - * to clear the rest of the line, and force redrawing it - * completely. - */ - if ( p_wiv - && !force - && ScreenAttrs[off_to] != 0 - && ScreenAttrs[off_from] != ScreenAttrs[off_to]) { - /* - * Need to remove highlighting attributes here. - */ - windgoto(row, col + coloff); - out_str(T_CE); /* clear rest of this screen line */ - screen_start(); /* don't know where cursor is now */ - force = TRUE; /* force redraw of rest of the line */ - redraw_next = TRUE; /* or else next char would miss out */ - - /* - * If the previous character was highlighted, need to stop - * highlighting at this character. - */ - if (col + coloff > 0 && ScreenAttrs[off_to - 1] != 0) { - screen_attr = ScreenAttrs[off_to - 1]; - term_windgoto(row, col + coloff); - screen_stop_highlight(); - } else - screen_attr = 0; /* highlighting has stopped */ - } if (enc_dbcs != 0) { /* Check if overwriting a double-byte with a single-byte or * the other way around requires another character to be @@ -4369,16 +4324,6 @@ static void screen_line(int row, int coloff, int endcol, int clear_width, int rl screen_char_2(off_to, row, col + coloff); else screen_char(off_to, row, col + coloff); - } else if ( p_wiv - && col + coloff > 0) { - if (ScreenAttrs[off_to] == ScreenAttrs[off_to - 1]) { - /* - * Don't output stop-highlight when moving the cursor, it will - * stop the highlighting when it should continue. - */ - screen_attr = 0; - } else if (screen_attr != 0) - screen_stop_highlight(); } off_to += CHAR_CELLS; @@ -4720,7 +4665,7 @@ win_redr_status_matches ( /* Put the wildmenu just above the command line. If there is * no room, scroll the screen one line up. */ if (cmdline_row == Rows - 1) { - screen_del_lines(0, 0, 1, (int)Rows, TRUE, NULL); + screen_del_lines(0, 0, 1, (int)Rows, NULL); ++msg_scrolled; } else { ++cmdline_row; @@ -5686,25 +5631,15 @@ next_search_hl_pos( return false; } - static void screen_start_highlight(int attr) { screen_attr = attr; - if (full_screen) { - char buf[20]; - sprintf(buf, "\033|%dh", attr); - OUT_STR(buf); - } + ui_start_highlight(attr); } void screen_stop_highlight(void) { - if (screen_attr != 0) { - // Handled in ui.c - char buf[20]; - sprintf(buf, "\033|%dH", screen_attr); - OUT_STR(buf); - } + ui_stop_highlight(); screen_attr = 0; } @@ -5741,7 +5676,7 @@ static void screen_char(unsigned off, int row, int col) if (screen_attr != attr) screen_stop_highlight(); - windgoto(row, col); + ui_cursor_goto(row, col); if (screen_attr != attr) screen_start_highlight(attr); @@ -5749,25 +5684,18 @@ static void screen_char(unsigned off, int row, int col) if (enc_utf8 && ScreenLinesUC[off] != 0) { char_u buf[MB_MAXBYTES + 1]; - /* Convert UTF-8 character to bytes and write it. */ - + // Convert UTF-8 character to bytes and write it. buf[utfc_char2bytes(off, buf)] = NUL; - - out_str(buf); - if (utf_char2cells(ScreenLinesUC[off]) > 1) - ++screen_cur_col; + ui_puts(buf); } else { - out_flush_check(); - out_char(ScreenLines[off]); - /* double-byte character in single-width cell */ - if (enc_dbcs == DBCS_JPNU && ScreenLines[off] == 0x8e) - out_char(ScreenLines2[off]); + ui_putc(ScreenLines[off]); + // double-byte character in single-width cell + if (enc_dbcs == DBCS_JPNU && ScreenLines[off] == 0x8e) { + ui_putc(ScreenLines2[off]); + } } - - screen_cur_col++; } - /* * Used for enc_dbcs only: Put one double-wide character at ScreenLines["off"] * on the screen at position 'row' and 'col'. @@ -5790,60 +5718,7 @@ static void screen_char_2(unsigned off, int row, int col) /* Output the first byte normally (positions the cursor), then write the * second byte directly. */ screen_char(off, row, col); - out_char(ScreenLines[off + 1]); - ++screen_cur_col; -} - -/* - * Draw a rectangle of the screen, inverted when "invert" is TRUE. - * This uses the contents of ScreenLines[] and doesn't change it. - */ -void screen_draw_rectangle(int row, int col, int height, int width, int invert) -{ - int r, c; - int off; - int max_off; - - /* Can't use ScreenLines unless initialized */ - if (ScreenLines == NULL) - return; - - if (invert) - screen_char_attr = HL_INVERSE; - for (r = row; r < row + height; ++r) { - off = LineOffset[r]; - max_off = off + screen_Columns; - for (c = col; c < col + width; ++c) { - if (enc_dbcs != 0 && dbcs_off2cells(off + c, max_off) > 1) { - screen_char_2(off + c, r, c); - ++c; - } else { - screen_char(off + c, r, c); - if (utf_off2cells(off + c, max_off) > 1) - ++c; - } - } - } - screen_char_attr = 0; -} - -/* - * Redraw the characters for a vertically split window. - */ -static void redraw_block(int row, int end, win_T *wp) -{ - int col; - int width; - - - if (wp == NULL) { - col = 0; - width = Columns; - } else { - col = wp->w_wincol; - width = wp->w_width; - } - screen_draw_rectangle(row, col, end - row, width, FALSE); + ui_putc(ScreenLines[off + 1]); } /* @@ -5859,9 +5734,6 @@ void screen_fill(int start_row, int end_row, int start_col, int end_col, int c1, int end_off; int did_delete; int c; -#if defined(FEAT_GUI) || defined(UNIX) - int force_next = FALSE; -#endif if (end_row > screen_Rows) /* safety check */ end_row = screen_Rows; @@ -5874,16 +5746,17 @@ void screen_fill(int start_row, int end_row, int start_col, int end_col, int c1, /* it's a "normal" terminal when not in a GUI or cterm */ for (row = start_row; row < end_row; ++row) { - if (has_mbyte - ) { - /* When drawing over the right halve of a double-wide char clear - * out the left halve. When drawing over the left halve of a - * double wide-char clear out the right halve. Only needed in a - * terminal. */ - if (start_col > 0 && mb_fix_col(start_col, row) != start_col) + if (has_mbyte) { + // When drawing over the right halve of a double-wide char clear + // out the left halve. When drawing over the left halve of a + // double wide-char clear out the right halve. Only needed in a + // terminal. + if (start_col > 0 && mb_fix_col(start_col, row) != start_col) { screen_puts_len((char_u *)" ", 1, row, start_col - 1, 0); - if (end_col < screen_Columns && mb_fix_col(end_col, row) != end_col) + } + if (end_col < screen_Columns && mb_fix_col(end_col, row) != end_col) { screen_puts_len((char_u *)" ", 1, row, end_col, 0); + } } /* * Try to use delete-line termcap code, when no attributes or in a @@ -5916,9 +5789,8 @@ void screen_fill(int start_row, int end_row, int start_col, int end_col, int c1, if (off < end_off) { /* something to be cleared */ col = off - LineOffset[row]; screen_stop_highlight(); - term_windgoto(row, col); /* clear rest of this screen line */ - out_str(T_CE); - screen_start(); /* don't know where cursor is now */ + ui_cursor_goto(row, col); // clear rest of this screen line + ui_eol_clear(); col = end_col - col; while (col--) { /* clear chars in ScreenLines */ ScreenLines[off] = ' '; @@ -5938,9 +5810,6 @@ void screen_fill(int start_row, int end_row, int start_col, int end_col, int c1, || (enc_utf8 && (int)ScreenLinesUC[off] != (c >= 0x80 ? c : 0)) || ScreenAttrs[off] != attr -#if defined(FEAT_GUI) || defined(UNIX) - || force_next -#endif ) { ScreenLines[off] = c; if (enc_utf8) { @@ -5982,7 +5851,7 @@ void check_for_delay(int check_msg_scroll) if ((emsg_on_display || (check_msg_scroll && msg_scroll)) && !did_wait_return && emsg_silent == 0) { - out_flush(); + ui_flush(); os_delay(1000L, true); emsg_on_display = FALSE; if (check_msg_scroll) @@ -6290,7 +6159,7 @@ static void screenclear2(void) LineWraps[i] = FALSE; } - out_str(T_CL); /* clear the display */ + ui_clear(); // clear the display clear_cmdline = FALSE; mode_displayed = FALSE; screen_cleared = TRUE; /* can use contents of ScreenLines now */ @@ -6303,7 +6172,6 @@ static void screenclear2(void) compute_cmdrow(); msg_row = cmdline_row; /* put cursor on last line for messages */ msg_col = 0; - screen_start(); /* don't know where cursor is now */ msg_scrolled = 0; /* can't scroll back */ msg_didany = FALSE; msg_didout = FALSE; @@ -6348,238 +6216,13 @@ static void linecopy(int to, int from, win_T *wp) } /* - * Reset cursor position. Use whenever cursor was moved because of outputting - * something directly to the screen (shell commands) or a terminal control - * code. - */ -void screen_start(void) -{ - screen_cur_row = screen_cur_col = 9999; -} - -/* - * Move the cursor to position "row","col" in the screen. - * This tries to find the most efficient way to move, minimizing the number of - * characters sent to the terminal. - */ -void windgoto(int row, int col) -{ - sattr_T *p; - int i; - int plan; - int cost; - int wouldbe_col; - int noinvcurs; - char_u *bs; - int goto_cost; - int attr; - -#define GOTO_COST 7 /* assume a term_windgoto() takes about 7 chars */ -#define HIGHL_COST 5 /* assume unhighlight takes 5 chars */ - -#define PLAN_LE 1 -#define PLAN_CR 2 -#define PLAN_NL 3 -#define PLAN_WRITE 4 - /* Can't use ScreenLines unless initialized */ - if (ScreenLines == NULL) - return; - - if (col != screen_cur_col || row != screen_cur_row) { - /* Check for valid position. */ - if (row < 0) /* window without text lines? */ - row = 0; - if (row >= screen_Rows) - row = screen_Rows - 1; - if (col >= screen_Columns) - col = screen_Columns - 1; - - /* check if no cursor movement is allowed in highlight mode */ - if (screen_attr && *T_MS == NUL) - noinvcurs = HIGHL_COST; - else - noinvcurs = 0; - goto_cost = GOTO_COST + noinvcurs; - - /* - * Plan how to do the positioning: - * 1. Use CR to move it to column 0, same row. - * 2. Use T_LE to move it a few columns to the left. - * 3. Use NL to move a few lines down, column 0. - * 4. Move a few columns to the right with T_ND or by writing chars. - * - * Don't do this if the cursor went beyond the last column, the cursor - * position is unknown then (some terminals wrap, some don't ) - * - * First check if the highlighting attributes allow us to write - * characters to move the cursor to the right. - */ - if (row >= screen_cur_row && screen_cur_col < Columns) { - /* - * If the cursor is in the same row, bigger col, we can use CR - * or T_LE. - */ - bs = NULL; /* init for GCC */ - attr = screen_attr; - if (row == screen_cur_row && col < screen_cur_col) { - /* "le" is preferred over "bc", because "bc" is obsolete */ - if (*T_LE) - bs = T_LE; /* "cursor left" */ - else - bs = T_BC; /* "backspace character (old) */ - if (*bs) - cost = (screen_cur_col - col) * (int)STRLEN(bs); - else - cost = 999; - if (col + 1 < cost) { /* using CR is less characters */ - plan = PLAN_CR; - wouldbe_col = 0; - cost = 1; /* CR is just one character */ - } else { - plan = PLAN_LE; - wouldbe_col = col; - } - if (noinvcurs) { /* will stop highlighting */ - cost += noinvcurs; - attr = 0; - } - } - /* - * If the cursor is above where we want to be, we can use CR LF. - */ - else if (row > screen_cur_row) { - plan = PLAN_NL; - wouldbe_col = 0; - cost = (row - screen_cur_row) * 2; /* CR LF */ - if (noinvcurs) { /* will stop highlighting */ - cost += noinvcurs; - attr = 0; - } - } - /* - * If the cursor is in the same row, smaller col, just use write. - */ - else { - plan = PLAN_WRITE; - wouldbe_col = screen_cur_col; - cost = 0; - } - - /* - * Check if any characters that need to be written have the - * correct attributes. Also avoid UTF-8 characters. - */ - i = col - wouldbe_col; - if (i > 0) - cost += i; - if (cost < goto_cost && i > 0) { - /* - * Check if the attributes are correct without additionally - * stopping highlighting. - */ - p = ScreenAttrs + LineOffset[row] + wouldbe_col; - while (i && *p++ == attr) - --i; - if (i != 0) { - /* - * Try if it works when highlighting is stopped here. - */ - if (*--p == 0) { - cost += noinvcurs; - while (i && *p++ == 0) - --i; - } - if (i != 0) - cost = 999; /* different attributes, don't do it */ - } - if (enc_utf8) { - /* Don't use an UTF-8 char for positioning, it's slow. */ - for (i = wouldbe_col; i < col; ++i) - if (ScreenLinesUC[LineOffset[row] + i] != 0) { - cost = 999; - break; - } - } - } - - /* - * We can do it without term_windgoto()! - */ - if (cost < goto_cost) { - if (plan == PLAN_LE) { - if (noinvcurs) - screen_stop_highlight(); - while (screen_cur_col > col) { - out_str(bs); - --screen_cur_col; - } - } else if (plan == PLAN_CR) { - if (noinvcurs) - screen_stop_highlight(); - out_char('\r'); - screen_cur_col = 0; - } else if (plan == PLAN_NL) { - if (noinvcurs) - screen_stop_highlight(); - while (screen_cur_row < row) { - out_char('\n'); - ++screen_cur_row; - } - screen_cur_col = 0; - } - - i = col - screen_cur_col; - if (i > 0) { - /* - * Use cursor-right if it's one character only. Avoids - * removing a line of pixels from the last bold char, when - * using the bold trick in the GUI. - */ - if (T_ND[0] != NUL && T_ND[1] == NUL) { - while (i-- > 0) - out_char(*T_ND); - } else { - int off; - - off = LineOffset[row] + screen_cur_col; - while (i-- > 0) { - if (ScreenAttrs[off] != screen_attr) - screen_stop_highlight(); - out_flush_check(); - out_char(ScreenLines[off]); - if (enc_dbcs == DBCS_JPNU - && ScreenLines[off] == 0x8e) - out_char(ScreenLines2[off]); - ++off; - } - } - } - } - } else - cost = 999; - - if (cost >= goto_cost) { - if (noinvcurs) - screen_stop_highlight(); - if (row == screen_cur_row && (col > screen_cur_col) && - *T_CRI != NUL) - term_cursor_right(col - screen_cur_col); - else - term_windgoto(row, col); - } - screen_cur_row = row; - screen_cur_col = col; - } -} - -/* * Set cursor to its position in the current window. */ void setcursor(void) { if (redrawing()) { validate_cursor(); - windgoto(curwin->w_winrow + curwin->w_wrow, + ui_cursor_goto(curwin->w_winrow + curwin->w_wrow, curwin->w_wincol + ( /* With 'rightleft' set and the cursor on a double-wide * character, position it on the leftmost column. */ @@ -6628,7 +6271,7 @@ int win_ins_lines(win_T *wp, int row, int line_count, int invalid, int mayclear) did_delete = FALSE; if (wp->w_next != NULL || wp->w_status_height) { if (screen_del_lines(0, wp->w_winrow + wp->w_height - line_count, - line_count, (int)Rows, FALSE, NULL) == OK) + line_count, (int)Rows, NULL) == OK) did_delete = TRUE; else if (wp->w_next) return FAIL; @@ -6683,8 +6326,9 @@ int win_del_lines(win_T *wp, int row, int line_count, int invalid, int mayclear) return retval; if (screen_del_lines(0, wp->w_winrow + row, line_count, - (int)Rows, FALSE, NULL) == FAIL) + (int)Rows, NULL) == FAIL) { return FAIL; + } /* * If there are windows or status lines below, try to put them at the @@ -6706,29 +6350,21 @@ int win_del_lines(win_T *wp, int row, int line_count, int invalid, int mayclear) return OK; } -/* - * Common code for win_ins_lines() and win_del_lines(). - * Returns OK or FAIL when the work has been done. - * Returns MAYBE when not finished yet. - */ +// Common code for win_ins_lines() and win_del_lines(). +// Returns OK or FAIL when the work has been done. static int win_do_lines(win_T *wp, int row, int line_count, int mayclear, int del) { - int retval; - - if (!redrawing() || line_count <= 0) + if (!redrawing() || line_count <= 0) { return FAIL; + } - /* only a few lines left: redraw is faster */ - if (mayclear && Rows - line_count < 5 - && wp->w_width == Columns - ) { + // only a few lines left: redraw is faster + if (mayclear && Rows - line_count < 5 && wp->w_width == Columns) { screenclear(); /* will set wp->w_lines_valid to 0 */ return FAIL; } - /* - * Delete all remaining lines - */ + // Delete all remaining lines if (row + line_count >= wp->w_height) { screen_fill(wp->w_winrow + row, wp->w_winrow + wp->w_height, wp->w_wincol, (int)W_ENDCOL(wp), @@ -6736,42 +6372,20 @@ static int win_do_lines(win_T *wp, int row, int line_count, int mayclear, int de return OK; } - /* - * when scrolling, the message on the command line should be cleared, - * otherwise it will stay there forever. - */ + // when scrolling, the message on the command line should be cleared, + // otherwise it will stay there forever. clear_cmdline = TRUE; - - /* - * If the terminal can set a scroll region, use that. - * Always do this in a vertically split window. This will redraw from - * ScreenLines[] when t_CV isn't defined. That's faster than using - * win_line(). - * Don't use a scroll region when we are going to redraw the text, writing - * a character in the lower right corner of the scroll region causes a - * scroll-up in the DJGPP version. - */ - if (scroll_region - || wp->w_width != Columns - ) { - if (scroll_region && (wp->w_width == Columns || *T_CSV != NUL)) - scroll_region_set(wp, row); - if (del) - retval = screen_del_lines(wp->w_winrow + row, 0, line_count, - wp->w_height - row, FALSE, wp); - else - retval = screen_ins_lines(wp->w_winrow + row, 0, line_count, - wp->w_height - row, wp); - if (scroll_region && (wp->w_width == Columns || *T_CSV != NUL)) - scroll_region_reset(); - return retval; - } - - if (wp->w_next != NULL) { - return FAIL; + int retval; + ui_set_scroll_region(wp, row); + if (del) { + retval = screen_del_lines(wp->w_winrow + row, 0, line_count, + wp->w_height - row, wp); + } else { + retval = screen_ins_lines(wp->w_winrow + row, 0, line_count, + wp->w_height - row, wp); } - - return MAYBE; + ui_reset_scroll_region(); + return retval; } /* @@ -6810,16 +6424,13 @@ static void win_rest_invalid(win_T *wp) #define USE_T_CD 8 #define USE_REDRAW 9 -/* - * insert lines on the screen and update ScreenLines[] - * 'end' is the line after the scrolled part. Normally it is Rows. - * When scrolling region used 'off' is the offset from the top for the region. - * 'row' and 'end' are relative to the start of the region. - * - * return FAIL for failure, OK for success. - */ -int -screen_ins_lines ( +// insert lines on the screen and update ScreenLines[] +// 'end' is the line after the scrolled part. Normally it is Rows. +// When scrolling region used 'off' is the offset from the top for the region. +// 'row' and 'end' are relative to the start of the region. +// +// return FAIL for failure, OK for success. +int screen_ins_lines ( int off, int row, int line_count, @@ -6830,101 +6441,27 @@ screen_ins_lines ( int i; int j; unsigned temp; - int cursor_row; - int type; - int result_empty; - int can_ce = true; - /* - * FAIL if - * - there is no valid screen - * - the screen has to be redrawn completely - * - the line count is less than one - * - the line count is more than 'ttyscroll' - */ - if (!screen_valid(TRUE) || line_count <= 0 || line_count > p_ttyscroll) + // FAIL if + // - there is no valid screen + // - the screen has to be redrawn completely + // - the line count is less than one + // - the line count is more than 'ttyscroll' + if (!screen_valid(TRUE) || line_count <= 0) { return FAIL; + } - /* - * There are seven ways to insert lines: - * 0. When in a vertically split window and t_CV isn't set, redraw the - * characters from ScreenLines[]. - * 1. Use T_CD (clear to end of display) if it exists and the result of - * the insert is just empty lines - * 2. Use T_CAL (insert multiple lines) if it exists and T_AL is not - * present or line_count > 1. It looks better if we do all the inserts - * at once. - * 3. Use T_CDL (delete multiple lines) if it exists and the result of the - * insert is just empty lines and T_CE is not present or line_count > - * 1. - * 4. Use T_AL (insert line) if it exists. - * 5. Use T_CE (erase line) if it exists and the result of the insert is - * just empty lines. - * 6. Use T_DL (delete line) if it exists and the result of the insert is - * just empty lines. - * 7. Use T_SR (scroll reverse) if it exists and inserting at row 0 and - * the 'da' flag is not set or we have clear line capability. - * 8. redraw the characters from ScreenLines[]. - * - * Careful: In a hpterm scroll reverse doesn't work as expected, it moves - * the scrollbar for the window. It does have insert line, use that if it - * exists. - */ - result_empty = (row + line_count >= end); - if (wp != NULL && wp->w_width != Columns && *T_CSV == NUL) - type = USE_REDRAW; - else if (result_empty) - type = USE_T_CD; - else if (*T_CAL != NUL && (line_count > 1 || *T_AL == NUL)) - type = USE_T_CAL; - else if (*T_CDL != NUL && result_empty && (line_count > 1 || !can_ce)) - type = USE_T_CDL; - else if (*T_AL != NUL) - type = USE_T_AL; - else if (can_ce && result_empty) - type = USE_T_CE; - else if (*T_DL != NUL && result_empty) - type = USE_T_DL; - else if (*T_SR != NUL && row == 0 && (*T_DA == NUL || can_ce)) - type = USE_T_SR; - else - return FAIL; - - /* - * For clearing the lines screen_del_lines() is used. This will also take - * care of t_db if necessary. - */ - if (type == USE_T_CD || type == USE_T_CDL || - type == USE_T_CE || type == USE_T_DL) - return screen_del_lines(off, row, line_count, end, FALSE, wp); - - /* - * If text is retained below the screen, first clear or delete as many - * lines at the bottom of the window as are about to be inserted so that - * the deleted lines won't later surface during a screen_del_lines. - */ - if (*T_DB) - screen_del_lines(off, end - line_count, line_count, end, FALSE, wp); - - - - if (*T_CCS != NUL) /* cursor relative to region */ - cursor_row = row; - else - cursor_row = row + off; - - /* - * Shift LineOffset[] line_count down to reflect the inserted lines. - * Clear the inserted lines in ScreenLines[]. - */ + // Shift LineOffset[] line_count down to reflect the inserted lines. + // Clear the inserted lines in ScreenLines[]. row += off; end += off; for (i = 0; i < line_count; ++i) { if (wp != NULL && wp->w_width != Columns) { - /* need to copy part of a line */ + // need to copy part of a line j = end - 1 - i; - while ((j -= line_count) >= row) + while ((j -= line_count) >= row) { linecopy(j + line_count, j, wp); + } j += line_count; lineclear(LineOffset[j] + wp->w_wincol, wp->w_width); LineWraps[j] = FALSE; @@ -6941,151 +6478,54 @@ screen_ins_lines ( } } - screen_stop_highlight(); - windgoto(cursor_row, 0); - - /* redraw the characters */ - if (type == USE_REDRAW) - redraw_block(row, end, wp); - else if (type == USE_T_CAL) { - term_append_lines(line_count); - screen_start(); /* don't know where cursor is now */ - } else { - for (i = 0; i < line_count; i++) { - if (type == USE_T_AL) { - if (i && cursor_row != 0) - windgoto(cursor_row, 0); - out_str(T_AL); - } else /* type == USE_T_SR */ - out_str(T_SR); - screen_start(); /* don't know where cursor is now */ - } - } - - /* - * With scroll-reverse and 'da' flag set we need to clear the lines that - * have been scrolled down into the region. - */ - if (type == USE_T_SR && *T_DA) { - for (i = 0; i < line_count; ++i) { - windgoto(off + i, 0); - out_str(T_CE); - screen_start(); /* don't know where cursor is now */ - } - } + ui_append_lines(line_count); return OK; } -/* - * delete lines on the screen and update ScreenLines[] - * 'end' is the line after the scrolled part. Normally it is Rows. - * When scrolling region used 'off' is the offset from the top for the region. - * 'row' and 'end' are relative to the start of the region. - * - * Return OK for success, FAIL if the lines are not deleted. - */ -int -screen_del_lines ( +// delete lines on the screen and update ScreenLines[] +// 'end' is the line after the scrolled part. Normally it is Rows. +// When scrolling region used 'off' is the offset from the top for the region. +// 'row' and 'end' are relative to the start of the region. +// +// Return OK for success, FAIL if the lines are not deleted. +int screen_del_lines ( int off, int row, int line_count, int end, - int force, /* even when line_count > p_ttyscroll */ win_T *wp /* NULL or window to use width from */ ) { int j; int i; unsigned temp; - int cursor_row; - int cursor_end; - int result_empty; /* result is empty until end of region */ - int can_delete; /* deleting line codes can be used */ - int type; - /* - * FAIL if - * - there is no valid screen - * - the screen has to be redrawn completely - * - the line count is less than one - * - the line count is more than 'ttyscroll' - */ - if (!screen_valid(TRUE) || line_count <= 0 || - (!force && line_count > p_ttyscroll)) - return FAIL; - - /* - * Check if the rest of the current region will become empty. - */ - result_empty = row + line_count >= end; - - /* - * We can delete lines only when 'db' flag not set or when 'ce' option - * available. - */ - can_delete = true; - - /* - * There are six ways to delete lines: - * 0. When in a vertically split window and t_CV isn't set, redraw the - * characters from ScreenLines[]. - * 1. Use T_CD if it exists and the result is empty. - * 2. Use newlines if row == 0 and count == 1 or T_CDL does not exist. - * 3. Use T_CDL (delete multiple lines) if it exists and line_count > 1 or - * none of the other ways work. - * 4. Use T_CE (erase line) if the result is empty. - * 5. Use T_DL (delete line) if it exists. - * 6. redraw the characters from ScreenLines[]. - */ - if (wp != NULL && wp->w_width != Columns && *T_CSV == NUL) - type = USE_REDRAW; - else if (result_empty) - type = USE_T_CD; - else if (row == 0 && ( - /* On the Amiga, somehow '\n' on the last line doesn't always scroll - * up, so use delete-line command */ - line_count == 1 || - *T_CDL == NUL)) - type = USE_NL; - else if (*T_CDL != NUL && line_count > 1 && can_delete) - type = USE_T_CDL; - else if (result_empty && (wp == NULL || wp->w_width == Columns)) - type = USE_T_CE; - else if (*T_DL != NUL && can_delete) - type = USE_T_DL; - else if (*T_CDL != NUL && can_delete) - type = USE_T_CDL; - else + // FAIL if + // - there is no valid screen + // - the screen has to be redrawn completely + // - the line count is less than one + // - the line count is more than 'ttyscroll' + if (!screen_valid(TRUE) || line_count <= 0) { return FAIL; - - - - if (*T_CCS != NUL) { /* cursor relative to region */ - cursor_row = row; - cursor_end = end; - } else { - cursor_row = row + off; - cursor_end = end + off; } - /* - * Now shift LineOffset[] line_count up to reflect the deleted lines. - * Clear the inserted lines in ScreenLines[]. - */ + // Now shift LineOffset[] line_count up to reflect the deleted lines. + // Clear the inserted lines in ScreenLines[]. row += off; end += off; for (i = 0; i < line_count; ++i) { if (wp != NULL && wp->w_width != Columns) { - /* need to copy part of a line */ + // need to copy part of a line j = row + i; - while ((j += line_count) <= end - 1) + while ((j += line_count) <= end - 1) { linecopy(j - line_count, j, wp); + } j -= line_count; lineclear(LineOffset[j] + wp->w_wincol, wp->w_width); LineWraps[j] = FALSE; } else { - /* whole width, moving the line pointers is faster */ + // whole width, moving the line pointers is faster j = row + i; temp = LineOffset[j]; while ((j += line_count) <= end - 1) { @@ -7098,54 +6538,7 @@ screen_del_lines ( } } - screen_stop_highlight(); - - /* redraw the characters */ - if (type == USE_REDRAW) - redraw_block(row, end, wp); - else if (type == USE_T_CD) { /* delete the lines */ - windgoto(cursor_row, 0); - out_str(T_CD); - screen_start(); /* don't know where cursor is now */ - } else if (type == USE_T_CDL) { - windgoto(cursor_row, 0); - term_delete_lines(line_count); - screen_start(); /* don't know where cursor is now */ - } - /* - * Deleting lines at top of the screen or scroll region: Just scroll - * the whole screen (scroll region) up by outputting newlines on the - * last line. - */ - else if (type == USE_NL) { - windgoto(cursor_end - 1, 0); - for (i = line_count; --i >= 0; ) - out_char('\n'); /* cursor will remain on same line */ - } else { - for (i = line_count; --i >= 0; ) { - if (type == USE_T_DL) { - windgoto(cursor_row, 0); - out_str(T_DL); /* delete a line */ - } else { /* type == USE_T_CE */ - windgoto(cursor_row + i, 0); - out_str(T_CE); /* erase a line */ - } - screen_start(); /* don't know where cursor is now */ - } - } - - /* - * If the 'db' flag is set, we need to clear the lines that have been - * scrolled up at the bottom of the region. - */ - if (*T_DB && (type == USE_T_DL || type == USE_T_CDL)) { - for (i = line_count; i > 0; --i) { - windgoto(cursor_end - i, 0); - out_str(T_CE); /* erase a line */ - screen_start(); /* don't know where cursor is now */ - } - } - + ui_delete_lines(line_count); return OK; } @@ -7195,7 +6588,7 @@ int showmode(void) /* Position on the last line in the window, column 0 */ msg_pos_mode(); - cursor_off(); + ui_cursor_off(); attr = hl_attr(HLF_CM); /* Highlight mode */ if (do_mode) { MSG_PUTS_ATTR("--", attr); @@ -7644,7 +7037,7 @@ static void win_redr_ruler(win_T *wp, int always) || wp->w_buffer->b_ml.ml_line_count != wp->w_ru_line_count || wp->w_topfill != wp->w_ru_topfill || empty_line != wp->w_ru_empty) { - cursor_off(); + ui_cursor_off(); int width; int row; @@ -7781,24 +7174,6 @@ int number_width(win_T *wp) } /* - * Return the current cursor column. This is the actual position on the - * screen. First column is 0. - */ -int screen_screencol(void) -{ - return screen_cur_col; -} - -/* - * Return the current cursor row. This is the actual position on the screen. - * First row is 0. - */ -int screen_screenrow(void) -{ - return screen_cur_row; -} - -/* * Set size of the Vim shell. * If 'mustset' is TRUE, we must set Rows and Columns, do not get the real * window size (this is used for the :win command). @@ -7839,19 +7214,15 @@ void screen_resize(int width, int height) check_shellsize(); height = Rows; width = Columns; - // Clear the output buffer to ensure UIs don't receive redraw command meant - // for invalid screen sizes. - out_buf_clear(); ui_resize(width, height); /* The window layout used to be adjusted here, but it now happens in * screenalloc() (also invoked from screenclear()). That is because the * "busy" check above may skip this, but not screenalloc(). */ - if (State != ASKMORE && State != EXTERNCMD && State != CONFIRM) + if (State != ASKMORE && State != EXTERNCMD && State != CONFIRM) { screenclear(); - else - screen_start(); /* don't know where cursor is now */ + } if (starting != NO_SCREEN) { maketitle(); @@ -7889,8 +7260,52 @@ void screen_resize(int width, int height) setcursor(); } } - cursor_on(); /* redrawing may have switched it off */ + ui_cursor_on(); /* redrawing may have switched it off */ } - out_flush(); + ui_flush(); --busy; } + +// Check if the new shell size is valid, correct it if it's too small or way +// too big. +void check_shellsize(void) +{ + if (Rows < min_rows()) { + // need room for one window and command line + Rows = min_rows(); + } + limit_screen_size(); +} + +// Limit Rows and Columns to avoid an overflow in Rows * Columns. +void limit_screen_size(void) +{ + if (Columns < MIN_COLUMNS) { + Columns = MIN_COLUMNS; + } else if (Columns > 10000) { + Columns = 10000; + } + + if (Rows > 1000) { + Rows = 1000; + } +} + +void win_new_shellsize(void) +{ + static long old_Rows = 0; + static long old_Columns = 0; + + if (old_Rows != Rows) { + // if 'window' uses the whole screen, keep it using that */ + if (p_window == old_Rows - 1 || old_Rows == 0) { + p_window = Rows - 1; + } + old_Rows = Rows; + shell_new_rows(); // update window sizes + } + if (old_Columns != Columns) { + old_Columns = Columns; + shell_new_columns(); // update window sizes + } +} diff --git a/src/nvim/search.c b/src/nvim/search.c index 095d7484a5..3b8f0bb6ba 100644 --- a/src/nvim/search.c +++ b/src/nvim/search.c @@ -47,7 +47,6 @@ #include "nvim/regexp.h" #include "nvim/screen.h" #include "nvim/strings.h" -#include "nvim/term.h" #include "nvim/ui.h" #include "nvim/window.h" #include "nvim/os/time.h" @@ -1089,7 +1088,7 @@ int do_search( free(msgbuf); gotocmdline(FALSE); - out_flush(); + ui_flush(); msg_nowait = TRUE; /* don't wait for this message */ } } @@ -2045,8 +2044,8 @@ showmatch ( p_siso = 0; /* don't use 'sidescrolloff' here */ showruler(FALSE); setcursor(); - cursor_on(); /* make sure that the cursor is shown */ - out_flush(); + ui_cursor_on(); /* make sure that the cursor is shown */ + ui_flush(); /* Restore dollar_vcol(), because setcursor() may call curs_rows() * which resets it if the matching position is in a previous line * and has a higher column number. */ @@ -4156,7 +4155,7 @@ find_pattern_in_path ( MSG_PUTS(_(" NOT FOUND")); } } - out_flush(); /* output each line directly */ + ui_flush(); /* output each line directly */ } if (new_fname != NULL) { @@ -4555,7 +4554,7 @@ static void show_pat_in_path(char_u *line, int type, int did_show, int action, F MSG_PUTS(" "); } msg_prt_line(line, FALSE); - out_flush(); /* show one line at a time */ + ui_flush(); /* show one line at a time */ /* Definition continues until line that doesn't end with '\' */ if (got_int || type != FIND_DEFINE || p < line || *p != '\\') diff --git a/src/nvim/spell.c b/src/nvim/spell.c index f66560f772..126a435463 100644 --- a/src/nvim/spell.c +++ b/src/nvim/spell.c @@ -325,7 +325,7 @@ #include "nvim/search.h" #include "nvim/strings.h" #include "nvim/syntax.h" -#include "nvim/term.h" +#include "nvim/ui.h" #include "nvim/tempfile.h" #include "nvim/undo.h" #include "nvim/os/os.h" @@ -5476,7 +5476,7 @@ static int spell_read_dic(spellinfo_T *spin, char_u *fname, afffile_T *affile) msg_clr_eos(); msg_didout = FALSE; msg_col = 0; - out_flush(); + ui_flush(); } // Store the word in the hashtable to be able to find duplicates. @@ -6327,7 +6327,7 @@ static int tree_add_word(spellinfo_T *spin, char_u *word, wordnode_T *root, int msg_clr_eos(); msg_didout = FALSE; msg_col = 0; - out_flush(); + ui_flush(); } // Compress both trees. Either they both have many nodes, which makes @@ -7749,7 +7749,7 @@ static void spell_message(spellinfo_T *spin, char_u *str) if (!spin->si_verbose) verbose_enter(); MSG(str); - out_flush(); + ui_flush(); if (!spin->si_verbose) verbose_leave(); } diff --git a/src/nvim/strings.c b/src/nvim/strings.c index 2a0014c6c1..dd10184d38 100644 --- a/src/nvim/strings.c +++ b/src/nvim/strings.c @@ -41,7 +41,6 @@ #include "nvim/spell.h" #include "nvim/syntax.h" #include "nvim/tag.h" -#include "nvim/term.h" #include "nvim/window.h" #include "nvim/os/os.h" #include "nvim/os/shell.h" diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c index c94e6e437b..3fc004036e 100644 --- a/src/nvim/syntax.c +++ b/src/nvim/syntax.c @@ -44,7 +44,6 @@ #include "nvim/screen.h" #include "nvim/strings.h" #include "nvim/syntax_defs.h" -#include "nvim/term.h" #include "nvim/ui.h" #include "nvim/os/os.h" #include "nvim/os/time.h" @@ -7394,7 +7393,7 @@ static void highlight_list_two(int cnt, int attr) { msg_puts_attr((char_u *)&("N \bI \b! \b"[cnt / 11]), attr); msg_clr_eos(); - out_flush(); + ui_flush(); os_delay(cnt == 99 ? 40L : (long)cnt * 50L, false); } diff --git a/src/nvim/tag.c b/src/nvim/tag.c index 5c3d7cc30b..44c653c852 100644 --- a/src/nvim/tag.c +++ b/src/nvim/tag.c @@ -48,7 +48,7 @@ #include "nvim/screen.h" #include "nvim/search.h" #include "nvim/strings.h" -#include "nvim/term.h" +#include "nvim/ui.h" #include "nvim/window.h" #include "nvim/os/os.h" #include "nvim/os/time.h" @@ -881,7 +881,7 @@ do_tag ( } else give_warning(IObuff, ic); if (ic && !msg_scrolled && msg_silent == 0) { - out_flush(); + ui_flush(); os_delay(1000L, true); } } @@ -985,7 +985,7 @@ void do_tags(exarg_T *eap) ? hl_attr(HLF_D) : 0); free(name); } - out_flush(); /* show one line at a time */ + ui_flush(); /* show one line at a time */ } if (tagstackidx == tagstacklen) /* idx at top of stack */ MSG_PUTS("\n>"); @@ -2497,7 +2497,7 @@ jumpto_tag ( if (found == 2 || !save_p_ic) { MSG(_("E435: Couldn't find tag, just guessing!")); if (!msg_scrolled && msg_silent == 0) { - out_flush(); + ui_flush(); os_delay(1000L, true); } } diff --git a/src/nvim/term.c b/src/nvim/term.c deleted file mode 100644 index a16c1a59ca..0000000000 --- a/src/nvim/term.c +++ /dev/null @@ -1,1514 +0,0 @@ -/* - * VIM - Vi IMproved by Bram Moolenaar - * - * Do ":help uganda" in Vim to read copying and usage conditions. - * Do ":help credits" in Vim to see a list of people who contributed. - * See README.txt for an overview of the Vim source code. - */ -/* - * - * term.c: functions for controlling the terminal - * - * primitive termcap support for Win32 included - * - * NOTE: padding and variable substitution is not performed, - * when compiling without HAVE_TGETENT, we use tputs() and tgoto() dummies. - */ - -/* - * Some systems have a prototype for tgetstr() with (char *) instead of - * (char **). This define removes that prototype. We include our own prototype - * below. - */ - -#define tgetstr tgetstr_defined_wrong -#include <assert.h> -#include <errno.h> -#include <inttypes.h> -#include <stdbool.h> -#include <string.h> - -#include "nvim/vim.h" -#include "nvim/ascii.h" -#include "nvim/term.h" -#include "nvim/buffer.h" -#include "nvim/charset.h" -#include "nvim/edit.h" -#include "nvim/eval.h" -#include "nvim/ex_getln.h" -#include "nvim/fileio.h" -#include "nvim/getchar.h" -#include "nvim/message.h" -#include "nvim/misc2.h" -#include "nvim/garray.h" -#include "nvim/keymap.h" -#include "nvim/memory.h" -#include "nvim/move.h" -#include "nvim/mouse.h" -#include "nvim/normal.h" -#include "nvim/option.h" -#include "nvim/os_unix.h" -#include "nvim/popupmnu.h" -#include "nvim/screen.h" -#include "nvim/strings.h" -#include "nvim/syntax.h" -#include "nvim/ui.h" -#include "nvim/window.h" -#include "nvim/os/os.h" -#include "nvim/os/time.h" -#include "nvim/os/input.h" - - -#undef tgetstr - -/* - * Here are the builtin termcap entries. They are not stored as complete - * structures with all entries, as such a structure is too big. - * - * The entries are compact, therefore they normally are included even when - * HAVE_TGETENT is defined. When HAVE_TGETENT is defined, the builtin entries - * can be accessed with "builtin_ansi", "builtin_debug", etc. - * - * Each termcap is a list of builtin_term structures. It always starts with - * KS_NAME, which separates the entries. See parse_builtin_tcap() for all - * details. - * bt_entry is either a KS_xxx code (>= 0), or a K_xxx code. - * - * Entries marked with "guessed" may be wrong. - */ -struct builtin_term { - int bt_entry; - char *bt_string; -}; - -/* start of keys that are not directly used by Vim but can be mapped */ -#define BT_EXTRA_KEYS 0x101 - -#ifdef INCLUDE_GENERATED_DECLARATIONS -# include "term.c.generated.h" -#endif - - -static bool detected_8bit = false; // detected 8-bit terminal - -static struct builtin_term builtin_termcaps[] = -{ - // abstract UI pseudo termcap, based on vim's "builtin_gui" termcap - {(int)KS_NAME, "abstract_ui"}, - {(int)KS_CE, "\033|$"}, - {(int)KS_AL, "\033|i"}, - {(int)KS_CAL, "\033|%p1%dI"}, - {(int)KS_DL, "\033|d"}, - {(int)KS_CDL, "\033|%p1%dD"}, - {(int)KS_CS, "\033|%p1%d;%p2%dR"}, - {(int)KS_CSV, "\033|%p1%d;%p2%dV"}, - {(int)KS_CL, "\033|C"}, - // attributes switched on with 'h', off with * 'H' - {(int)KS_ME, "\033|31H"}, // HL_ALL - {(int)KS_MR, "\033|1h"}, // HL_INVERSE - {(int)KS_MD, "\033|2h"}, // HL_BOLD - {(int)KS_SE, "\033|16H"}, // HL_STANDOUT - {(int)KS_SO, "\033|16h"}, // HL_STANDOUT - {(int)KS_UE, "\033|8H"}, // HL_UNDERLINE - {(int)KS_US, "\033|8h"}, // HL_UNDERLINE - {(int)KS_CZR, "\033|4H"}, // HL_ITALIC - {(int)KS_CZH, "\033|4h"}, // HL_ITALIC - {(int)KS_VB, "\033|f"}, - {(int)KS_MS, "y"}, - {(int)KS_UT, "y"}, - {(int)KS_LE, "\b"}, // cursor-left = BS - {(int)KS_ND, "\014"}, // cursor-right = CTRL-L - {(int)KS_CM, "\033|%p1%d;%p2%dM"}, - // there are no key sequences here, for "abstract_ui" vim key codes are - // parsed directly in input_enqueue() - {(int)KS_NAME, NULL} - -}; /* end of builtin_termcaps */ - -/* - * DEFAULT_TERM is used, when no terminal is specified with -T option or $TERM. - */ - - - -#if defined(UNIX) -# define DEFAULT_TERM (char_u *)"ansi" -#endif - - - - - -#ifndef DEFAULT_TERM -# define DEFAULT_TERM (char_u *)"dumb" -#endif - -/// Sets up the terminal window for use. -/// -/// This must be done after resetting full_screen, otherwise it may move the -/// cursor. -/// -/// @remark We may call mch_exit() before calling this. -void term_init(void) -{ - Columns = 80; - Rows = 24; - - // Prevent buffering output. - // Output gets explicitly buffered and flushed by out_flush() at times like, - // for example, when the user presses a key. Without this line, vim will not - // render the screen correctly. - setbuf(stdout, NULL); - - out_flush(); -} - -/* - * Term_strings contains currently used terminal output strings. - * It is initialized with the default values by parse_builtin_tcap(). - * The values can be changed by setting the option with the same name. - */ -char_u *(term_strings[(int)KS_LAST + 1]); - -static bool need_gather = false; // need to fill termleader[] - -static struct builtin_term *find_builtin_term(char_u *term) -{ - struct builtin_term *p = builtin_termcaps; - while (p->bt_string != NULL) { - if (p->bt_entry == (int)KS_NAME) { -#ifdef UNIX - if (STRCMP(p->bt_string, "xterm") == 0 && vim_is_xterm(term)) - return p; - else -#endif - if (STRCMP(term, p->bt_string) == 0) - return p; - } - ++p; - } - return p; -} - -/* - * Parsing of the builtin termcap entries. - * Caller should check if 'name' is a valid builtin term. - * The terminal's name is not set, as this is already done in termcapinit(). - */ -static void parse_builtin_tcap(char_u *term) -{ - char_u name[2]; - - struct builtin_term *p = find_builtin_term(term); - bool term_8bit = term_is_8bit(term); - - /* Do not parse if builtin term not found */ - if (p->bt_string == NULL) - return; - - for (++p; p->bt_entry != (int)KS_NAME && p->bt_entry != BT_EXTRA_KEYS; ++p) { - if ((int)p->bt_entry >= 0) { /* KS_xx entry */ - /* Only set the value if it wasn't set yet. */ - if (term_strings[p->bt_entry] == NULL - || term_strings[p->bt_entry] == empty_option) { - /* 8bit terminal: use CSI instead of <Esc>[ */ - if (term_8bit && term_7to8bit((char_u *)p->bt_string) != 0) { - char_u *s, *t; - - s = vim_strsave((char_u *)p->bt_string); - for (t = s; *t; ++t) - if (term_7to8bit(t)) { - *t = term_7to8bit(t); - STRCPY(t + 1, t + 2); - } - term_strings[p->bt_entry] = s; - set_term_option_alloced(&term_strings[p->bt_entry]); - } else - term_strings[p->bt_entry] = (char_u *)p->bt_string; - } - } else { - name[0] = (char_u)KEY2TERMCAP0(p->bt_entry); - name[1] = (char_u)KEY2TERMCAP1(p->bt_entry); - if (find_termcode(name) == NULL) - add_termcode(name, (char_u *)p->bt_string, term_8bit); - } - } -} - -/* - * Set terminal options for terminal "term". - * Return OK if terminal 'term' was found in a termcap, FAIL otherwise. - * - * While doing this, until ttest(), some options may be NULL, be careful. - */ -int set_termname(char_u *term) -{ - int width = 0, height = 0; - char_u *error_msg = NULL; - char_u *bs_p, *del_p; - - /* In silect mode (ex -s) we don't use the 'term' option. */ - if (silent_mode) - return OK; - - term = (uint8_t *)"abstract_ui"; - detected_8bit = false; // reset 8-bit detection - - if (term_is_builtin(term)) { - term += 8; - } - - /* - * If HAVE_TGETENT is not defined, only the builtin termcap is used, otherwise: - * If builtin_first is TRUE: - * 0. try builtin termcap - * 1. try external termcap - * 2. if both fail default to a builtin terminal - * If builtin_first is FALSE: - * 1. try external termcap - * 2. try builtin termcap, if both fail default to a builtin terminal - */ - /* - * Use builtin termcap - */ - { - /* - * search for 'term' in builtin_termcaps[] - */ - struct builtin_term *termp = find_builtin_term(term); - if (termp->bt_string == NULL) { /* did not find it */ - - mch_errmsg("\r\n"); - if (error_msg != NULL) { - mch_errmsg((char *)error_msg); - mch_errmsg("\r\n"); - } - mch_errmsg("'"); - mch_errmsg((char *)term); - mch_errmsg(_("' not known. Available builtin terminals are:")); - mch_errmsg("\r\n"); - for (termp = &(builtin_termcaps[0]); termp->bt_string != NULL; - ++termp) { - if (termp->bt_entry == (int)KS_NAME) { - mch_errmsg(" "); - mch_errmsg(termp->bt_string); - mch_errmsg("\r\n"); - } - } - /* when user typed :set term=xxx, quit here */ - if (starting != NO_SCREEN) { - screen_start(); /* don't know where cursor is now */ - wait_return(TRUE); - return FAIL; - } - term = DEFAULT_TERM; - mch_errmsg(_("defaulting to '")); - mch_errmsg((char *)term); - mch_errmsg("'\r\n"); - if (emsg_silent == 0) { - screen_start(); /* don't know where cursor is now */ - out_flush(); - os_delay(2000L, true); - } - set_string_option_direct((char_u *)"term", -1, term, - OPT_FREE, 0); - display_errors(); - } - out_flush(); - clear_termoptions(); /* clear old options */ - parse_builtin_tcap(term); - } - - /* - * special: There is no info in the termcap about whether the cursor - * positioning is relative to the start of the screen or to the start of the - * scrolling region. We just guess here. Only msdos pcterm is known to do it - * relative. - */ - if (STRCMP(term, "pcterm") == 0) - T_CCS = (char_u *)"yes"; - else - T_CCS = empty_option; - - /* - * If the termcap has no entry for 'bs' and/or 'del' and the ioctl() also - * didn't work, use the default CTRL-H - * The default for t_kD is DEL, unless t_kb is DEL. - * The vim_strsave'd strings are probably lost forever, well it's only two - * bytes. Don't do this when the GUI is active, it uses "t_kb" and "t_kD" - * directly. - */ - { - bs_p = find_termcode((char_u *)"kb"); - del_p = find_termcode((char_u *)"kD"); - if (bs_p == NULL || *bs_p == NUL) - add_termcode((char_u *)"kb", (bs_p = (char_u *)CTRL_H_STR), FALSE); - if ((del_p == NULL || *del_p == NUL) && - (bs_p == NULL || *bs_p != DEL)) - add_termcode((char_u *)"kD", (char_u *)DEL_STR, FALSE); - } - -#if defined(UNIX) - term_is_xterm = vim_is_xterm(term); -#endif - - ttest(TRUE); /* make sure we have a valid set of terminal codes */ - - full_screen = TRUE; /* we can use termcap codes from now on */ - set_term_defaults(); /* use current values as defaults */ - - /* - * Initialize the terminal with the appropriate termcap codes. - * Set the mouse and window title if possible. - * Don't do this when starting, need to parse the .vimrc first, because it - * may redefine t_TI etc. - */ - if (starting != NO_SCREEN) { - setmouse(); /* may start using the mouse */ - maketitle(); /* may display window title */ - } - - /* display initial screen after ttest() checking. jw. */ - if (width <= 0 || height <= 0) { - /* termcap failed to report size */ - /* set defaults, in case ui_get_shellsize() also fails */ - width = 80; - height = 24; /* most terminals are 24 lines */ - } - screen_resize(width, height); // may change Rows - if (starting != NO_SCREEN) { - if (scroll_region) - scroll_region_reset(); /* In case Rows changed */ - check_map_keycodes(); /* check mappings for terminal codes used */ - - { - /* - * Execute the TermChanged autocommands for each buffer that is - * loaded. - */ - buf_T *old_curbuf = curbuf; - for (curbuf = firstbuf; curbuf != NULL; curbuf = curbuf->b_next) { - if (curbuf->b_ml.ml_mfp != NULL) - apply_autocmds(EVENT_TERMCHANGED, NULL, NULL, FALSE, - curbuf); - } - if (buf_valid(old_curbuf)) - curbuf = old_curbuf; - } - } - - return OK; -} - - -# define HMT_NORMAL 1 -# define HMT_NETTERM 2 -# define HMT_DEC 4 -# define HMT_URXVT 16 -# define HMT_SGR 32 - -/* - * Get a string entry from the termcap and add it to the list of termcodes. - * Used for <t_xx> special keys. - * Give an error message for failure when not sourcing. - * If force given, replace an existing entry. - * Return FAIL if the entry was not found, OK if the entry was added. - */ -int add_termcap_entry(char_u *name, int force) -{ - char_u *term; - int key; - struct builtin_term *termp; - - /* - * If the GUI is running or will start in a moment, we only support the keys - * that the GUI can produce. - */ - - if (!force && find_termcode(name) != NULL) /* it's already there */ - return OK; - - term = T_NAME; - if (term == NULL || *term == NUL) /* 'term' not defined yet */ - return FAIL; - - if (term_is_builtin(term)) { /* name starts with "builtin_" */ - term += 8; - } - - /* - * Search in builtin termcap - */ - { - termp = find_builtin_term(term); - if (termp->bt_string != NULL) { /* found it */ - key = TERMCAP2KEY(name[0], name[1]); - while (termp->bt_entry != (int)KS_NAME) { - if ((int)termp->bt_entry == key) { - add_termcode(name, (char_u *)termp->bt_string, - term_is_8bit(term)); - return OK; - } - ++termp; - } - } - } - - if (sourcing_name == NULL) { - EMSG2(_("E436: No \"%s\" entry in termcap"), name); - } - return FAIL; -} - -static int term_is_builtin(char_u *name) -{ - return STRNCMP(name, "builtin_", (size_t)8) == 0; -} - -/* - * Return true if terminal "name" uses CSI instead of <Esc>[. - * Assume that the terminal is using 8-bit controls when the name contains - * "8bit", like in "xterm-8bit". - */ -bool term_is_8bit(char_u *name) -{ - return detected_8bit || strstr((char *)name, "8bit") != NULL; -} - -/* - * Translate terminal control chars from 7-bit to 8-bit: - * <Esc>[ -> CSI - * <Esc>] -> <M-C-]> - * <Esc>O -> <M-C-O> - */ -static char_u term_7to8bit(char_u *p) -{ - if (*p == ESC) { - if (p[1] == '[') - return CSI; - if (p[1] == ']') - return 0x9d; - if (p[1] == 'O') - return 0x8f; - } - return 0; -} - - -char_u *tltoa(unsigned long i) -{ - static char_u buf[16]; - char_u *p = buf + 15; - *p = '\0'; - do { - --p; - *p = (char_u) (i % 10 + '0'); - i /= 10; - } while (i > 0 && p > buf); - return p; -} - -/* - * Set the terminal name and initialize the terminal options. - * If "name" is NULL or empty, get the terminal name from the environment. - * If that fails, use the default terminal name. - */ -void termcapinit(char_u *name) -{ - if (name != NULL && *name == NUL) - name = NULL; /* empty name is equal to no name */ - char_u *term = name; - - if (term == NULL) - term = (char_u *)os_getenv("TERM"); - if (term == NULL || *term == NUL) - term = DEFAULT_TERM; - set_string_option_direct((char_u *)"term", -1, term, OPT_FREE, 0); - - /* Set the default terminal name. */ - set_string_default("term", term); - set_string_default("ttytype", term); - - /* - * Avoid using "term" here, because the next os_getenv() may overwrite it. - */ - set_termname(T_NAME != NULL ? T_NAME : term); -} - -/* - * the number of calls to ui_write is reduced by using the buffer "out_buf" - */ -# define OUT_SIZE 2047 -// Add one to allow term_write() in os_win32.c to append a NUL -static char_u out_buf[OUT_SIZE + 1]; -static size_t out_pos = 0; /* number of chars in out_buf */ - -// Clear the output buffer -void out_buf_clear(void) -{ - out_pos = 0; -} - -/* - * out_flush(): flush the output buffer - */ -void out_flush(void) -{ - size_t len = out_pos; - out_pos = 0; - ui_write(out_buf, len); -} - -/* - * Sometimes a byte out of a multi-byte character is written with out_char(). - * To avoid flushing half of the character, call this function first. - */ -void out_flush_check(void) -{ - if (enc_dbcs != 0 && out_pos >= OUT_SIZE - MB_MAXBYTES) - out_flush(); -} - -/* - * out_char(c): put a byte into the output buffer. - * Flush it if it becomes full. - * This should not be used for outputting text on the screen (use functions - * like msg_puts() and screen_putchar() for that). - */ -void out_char(char_u c) -{ -#if defined(UNIX) || defined(MACOS_X_UNIX) - if (c == '\n') /* turn LF into CR-LF (CRMOD doesn't seem to do this) */ - out_char('\r'); -#endif - - out_buf[out_pos++] = c; - - /* For testing we flush each time. */ - if (out_pos >= OUT_SIZE || p_wd) - out_flush(); -} - - -/* - * out_char_nf(c): like out_char(), but don't flush when p_wd is set - */ -static void out_char_nf(char_u c) -{ -#if defined(UNIX) || defined(MACOS_X_UNIX) - if (c == '\n') /* turn LF into CR-LF (CRMOD doesn't seem to do this) */ - out_char_nf('\r'); -#endif - - out_buf[out_pos++] = c; - - if (out_pos >= OUT_SIZE) - out_flush(); -} - -/* - * A never-padding out_str. - * use this whenever you don't want to run the string through tputs. - * tputs above is harmless, but tputs from the termcap library - * is likely to strip off leading digits, that it mistakes for padding - * information, and "%i", "%d", etc. - * This should only be used for writing terminal codes, not for outputting - * normal text (use functions like msg_puts() and screen_putchar() for that). - */ -void out_str_nf(char_u *s) -{ - if (out_pos > OUT_SIZE - 20) /* avoid terminal strings being split up */ - out_flush(); - while (*s) - out_char_nf(*s++); - - /* For testing we write one string at a time. */ - if (p_wd) - out_flush(); -} - -/* - * out_str(s): Put a character string a byte at a time into the output buffer. - * If HAVE_TGETENT is defined use the termcap parser. (jw) - * This should only be used for writing terminal codes, not for outputting - * normal text (use functions like msg_puts() and screen_putchar() for that). - */ -void out_str(char_u *s) -{ - if (s != NULL && *s) { - /* avoid terminal strings being split up */ - if (out_pos > OUT_SIZE - 20) - out_flush(); - while (*s) - out_char_nf(*s++); - - /* For testing we write one string at a time. */ - if (p_wd) - out_flush(); - } -} - -/* - * cursor positioning using termcap parser. (jw) - */ -void term_windgoto(int row, int col) -{ - char buf[32]; - snprintf(buf, sizeof(buf), "\033|%d;%dM", row, col); - OUT_STR(buf); -} - -void term_cursor_right(int i) -{ - abort(); -} - -void term_append_lines(int line_count) -{ - char buf[32]; - snprintf(buf, sizeof(buf), "\033|%dI", line_count); - OUT_STR(buf); -} - -void term_delete_lines(int line_count) -{ - char buf[32]; - snprintf(buf, sizeof(buf), "\033|%dD", line_count); - OUT_STR(buf); -} - -/* - * Make sure we have a valid set or terminal options. - * Replace all entries that are NULL by empty_option - */ -void ttest(int pairs) -{ - check_options(); /* make sure no options are NULL */ - - /* - * MUST have "cm": cursor motion. - */ - if (*T_CM == NUL) - EMSG(_("E437: terminal capability \"cm\" required")); - - /* - * if "cs" defined, use a scroll region, it's faster. - */ - if (*T_CS != NUL) - scroll_region = TRUE; - else - scroll_region = FALSE; - - if (pairs) { - /* - * optional pairs - */ - /* TP goes to normal mode for TI (invert) and TB (bold) */ - if (*T_ME == NUL) - T_ME = T_MR = T_MD = T_MB = empty_option; - if (*T_SO == NUL || *T_SE == NUL) - T_SO = T_SE = empty_option; - if (*T_US == NUL || *T_UE == NUL) - T_US = T_UE = empty_option; - if (*T_CZH == NUL || *T_CZR == NUL) - T_CZH = T_CZR = empty_option; - - /* T_VE is needed even though T_VI is not defined */ - if (*T_VE == NUL) - T_VI = empty_option; - - /* if 'mr' or 'me' is not defined use 'so' and 'se' */ - if (*T_ME == NUL) { - T_ME = T_SE; - T_MR = T_SO; - T_MD = T_SO; - } - - /* if 'so' or 'se' is not defined use 'mr' and 'me' */ - if (*T_SO == NUL) { - T_SE = T_ME; - if (*T_MR == NUL) - T_SO = T_MD; - else - T_SO = T_MR; - } - - /* if 'ZH' or 'ZR' is not defined use 'mr' and 'me' */ - if (*T_CZH == NUL) { - T_CZR = T_ME; - if (*T_MR == NUL) - T_CZH = T_MD; - else - T_CZH = T_MR; - } - - /* "Sb" and "Sf" come in pairs */ - if (*T_CSB == NUL || *T_CSF == NUL) { - T_CSB = empty_option; - T_CSF = empty_option; - } - - /* "AB" and "AF" come in pairs */ - if (*T_CAB == NUL || *T_CAF == NUL) { - T_CAB = empty_option; - T_CAF = empty_option; - } - - /* if 'Sb' and 'AB' are not defined, reset "Co" */ - if (*T_CSB == NUL && *T_CAB == NUL) - free_one_termoption(T_CCO); - - /* Set 'weirdinvert' according to value of 't_xs' */ - p_wiv = (*T_XS != NUL); - } - need_gather = true; - - /* Set t_colors to the value of t_Co. */ - t_colors = atoi((char *)T_CCO); -} - -/* - * Check if the new shell size is valid, correct it if it's too small or way - * too big. - */ -void check_shellsize(void) -{ - if (Rows < min_rows()) /* need room for one window and command line */ - Rows = min_rows(); - limit_screen_size(); -} - -/* - * Limit Rows and Columns to avoid an overflow in Rows * Columns. - */ -void limit_screen_size(void) -{ - if (Columns < MIN_COLUMNS) - Columns = MIN_COLUMNS; - else if (Columns > 10000) - Columns = 10000; - if (Rows > 1000) - Rows = 1000; -} - -/* - * Invoked just before the screen structures are going to be (re)allocated. - */ -void win_new_shellsize(void) -{ - static long old_Rows = 0; - static long old_Columns = 0; - - if (old_Rows != Rows) { - /* if 'window' uses the whole screen, keep it using that */ - if (p_window == old_Rows - 1 || old_Rows == 0) - p_window = Rows - 1; - old_Rows = Rows; - shell_new_rows(); /* update window sizes */ - } - if (old_Columns != Columns) { - old_Columns = Columns; - shell_new_columns(); /* update window sizes */ - } -} - -/* - * Call this function when the Vim shell has been resized in any way. - * Will obtain the current size and redraw (also when size didn't change). - */ -void shell_resized(void) -{ - ui_refresh(); -} - -/* - * Check if the shell size changed. Handle a resize. - * When the size didn't change, nothing happens. - */ -void shell_resized_check(void) -{ - long old_Rows = Rows; - long old_Columns = Columns; - - if (!exiting) { - check_shellsize(); - if (old_Rows != Rows || old_Columns != Columns) - shell_resized(); - } -} - -/* - * Return TRUE when saving and restoring the screen. - */ -int swapping_screen(void) -{ - return full_screen && *T_TI != NUL; -} - -/* - * By outputting the 'cursor very visible' termcap code, for some windowed - * terminals this makes the screen scrolled to the correct position. - * Used when starting Vim or returning from a shell. - */ -void scroll_start(void) -{ - if (*T_VS != NUL) { - out_str(T_VS); - out_str(T_VE); - screen_start(); /* don't know where cursor is now */ - } -} - -/* - * Enable the cursor. - */ -void cursor_on(void) -{ - ui_cursor_on(); -} - -/* - * Disable the cursor. - */ -void cursor_off(void) -{ - ui_cursor_off(); -} - -/* - * Set scrolling region for window 'wp'. - * The region starts 'off' lines from the start of the window. - * Also set the vertical scroll region for a vertically split window. Always - * the full width of the window, excluding the vertical separator. - */ -void scroll_region_set(win_T *wp, int off) -{ - char buf[32]; - - snprintf(buf, sizeof(buf), "\033|%d;%dR", wp->w_winrow + wp->w_height - 1, - wp->w_winrow + off); - OUT_STR(buf); - - if (wp->w_width != Columns) { - snprintf(buf, sizeof(buf), "\033|%d;%dV", wp->w_wincol + wp->w_width - 1, - wp->w_wincol); - OUT_STR(buf); - } - - screen_start(); /* don't know where cursor is now */ -} - -/* - * Reset scrolling region to the whole screen. - */ -void scroll_region_reset(void) -{ - char buf[32]; - - snprintf(buf, sizeof(buf), "\033|%d;%dR", (int)Rows - 1, 0); - OUT_STR(buf); - snprintf(buf, sizeof(buf), "\033|%d;%dV", (int)Columns - 1, 0); - OUT_STR(buf); - - screen_start(); /* don't know where cursor is now */ -} - -/* - * List of terminal codes that are currently recognized. - */ - -static struct termcode { - char_u name[2]; /* termcap name of entry */ - char_u *code; /* terminal code (in allocated memory) */ - int len; /* STRLEN(code) */ - int modlen; /* length of part before ";*~". */ -} *termcodes = NULL; - -static size_t tc_max_len = 0; /* number of entries that termcodes[] can hold */ -static size_t tc_len = 0; /* current number of entries in termcodes[] */ - - -void clear_termcodes(void) -{ - while (tc_len != 0) - free(termcodes[--tc_len].code); - free(termcodes); - termcodes = NULL; - tc_max_len = 0; - - - need_gather = true; // need to fill termleader[] -} - -#define ATC_FROM_TERM 55 - -/* - * Add a new entry to the list of terminal codes. - * The list is kept alphabetical for ":set termcap" - * "flags" is TRUE when replacing 7-bit by 8-bit controls is desired. - * "flags" can also be ATC_FROM_TERM for got_code_from_term(). - */ -void add_termcode(char_u *name, char_u *string, int flags) -{ - struct termcode *new_tc; - size_t i, j; - - if (string == NULL || *string == NUL) { - del_termcode(name); - return; - } - - char_u *s = vim_strsave(string); - - /* Change leading <Esc>[ to CSI, change <Esc>O to <M-O>. */ - if (flags != 0 && flags != ATC_FROM_TERM && term_7to8bit(string) != 0) { - STRMOVE(s, s + 1); - s[0] = term_7to8bit(string); - } - size_t len = STRLEN(s); - - need_gather = true; // need to fill termleader[] - - /* - * need to make space for more entries - */ - if (tc_len == tc_max_len) { - tc_max_len += 20; - new_tc = xmalloc(tc_max_len * sizeof(struct termcode)); - for (i = 0; i < tc_len; ++i) - new_tc[i] = termcodes[i]; - free(termcodes); - termcodes = new_tc; - } - - /* - * Look for existing entry with the same name, it is replaced. - * Look for an existing entry that is alphabetical higher, the new entry - * is inserted in front of it. - */ - for (i = 0; i < tc_len; ++i) { - if (termcodes[i].name[0] < name[0]) - continue; - if (termcodes[i].name[0] == name[0]) { - if (termcodes[i].name[1] < name[1]) - continue; - /* - * Exact match: May replace old code. - */ - if (termcodes[i].name[1] == name[1]) { - if (flags == ATC_FROM_TERM - && (j = termcode_star(termcodes[i].code, termcodes[i].len)) > 0) { - /* Don't replace ESC[123;*X or ESC O*X with another when - * invoked from got_code_from_term(). */ - assert(termcodes[i].len >= 0); - if (len == (size_t)termcodes[i].len - j - && STRNCMP(s, termcodes[i].code, len - 1) == 0 - && s[len - 1] == termcodes[i].code[termcodes[i].len - 1]) { - /* They are equal but for the ";*": don't add it. */ - free(s); - return; - } - } else { - /* Replace old code. */ - free(termcodes[i].code); - --tc_len; - break; - } - } - } - /* - * Found alphabetical larger entry, move rest to insert new entry - */ - for (j = tc_len; j > i; --j) - termcodes[j] = termcodes[j - 1]; - break; - } - - termcodes[i].name[0] = name[0]; - termcodes[i].name[1] = name[1]; - termcodes[i].code = s; - assert(len <= INT_MAX); - termcodes[i].len = (int)len; - - /* For xterm we recognize special codes like "ESC[42;*X" and "ESC O*X" that - * accept modifiers. */ - termcodes[i].modlen = 0; - j = termcode_star(s, (int)len); - if (j > 0) - termcodes[i].modlen = (int)(len - 1 - j); - ++tc_len; -} - -/* - * Check termcode "code[len]" for ending in ;*X, <Esc>O*X or <M-O>*X. - * The "X" can be any character. - * Return 0 if not found, 2 for ;*X and 1 for O*X and <M-O>*X. - */ -static unsigned int termcode_star(char_u *code, int len) -{ - /* Shortest is <M-O>*X. With ; shortest is <CSI>1;*X */ - if (len >= 3 && code[len - 2] == '*') { - if (len >= 5 && code[len - 3] == ';') - return 2; - if ((len >= 4 && code[len - 3] == 'O') || code[len - 3] == 'O' + 128) - return 1; - } - return 0; -} - -char_u *find_termcode(char_u *name) -{ - for (size_t i = 0; i < tc_len; ++i) - if (termcodes[i].name[0] == name[0] && termcodes[i].name[1] == name[1]) - return termcodes[i].code; - return NULL; -} - -char_u *get_termcode(size_t i) -{ - if (i >= tc_len) - return NULL; - return &termcodes[i].name[0]; -} - -void del_termcode(char_u *name) -{ - if (termcodes == NULL) /* nothing there yet */ - return; - - need_gather = true; // need to fill termleader[] - - for (size_t i = 0; i < tc_len; ++i) - if (termcodes[i].name[0] == name[0] && termcodes[i].name[1] == name[1]) { - del_termcode_idx(i); - return; - } - /* not found. Give error message? */ -} - -static void del_termcode_idx(size_t idx) -{ - free(termcodes[idx].code); - --tc_len; - for (size_t i = idx; i < tc_len; ++i) - termcodes[i] = termcodes[i + 1]; -} - -static linenr_T orig_topline = 0; -static int orig_topfill = 0; - -/* - * Checking for double clicks ourselves. - * "orig_topline" is used to avoid detecting a double-click when the window - * contents scrolled (e.g., when 'scrolloff' is non-zero). - */ -/* - * Set orig_topline. Used when jumping to another window, so that a double - * click still works. - */ -void set_mouse_topline(win_T *wp) -{ - orig_topline = wp->w_topline; - orig_topfill = wp->w_topfill; -} - -/* - * Replace any terminal code strings in from[] with the equivalent internal - * vim representation. This is used for the "from" and "to" part of a - * mapping, and the "to" part of a menu command. - * Any strings like "<C-UP>" are also replaced, unless 'cpoptions' contains - * '<'. - * K_SPECIAL by itself is replaced by K_SPECIAL KS_SPECIAL KE_FILLER. - * - * The replacement is done in result[] and finally copied into allocated - * memory. If this all works well *bufp is set to the allocated memory and a - * pointer to it is returned. If something fails *bufp is set to NULL and from - * is returned. - * - * CTRL-V characters are removed. When "from_part" is TRUE, a trailing CTRL-V - * is included, otherwise it is removed (for ":map xx ^V", maps xx to - * nothing). When 'cpoptions' does not contain 'B', a backslash can be used - * instead of a CTRL-V. - */ -char_u * -replace_termcodes ( - char_u *from, - char_u **bufp, - int from_part, - int do_lt, /* also translate <lt> */ - int special /* always accept <key> notation */ -) -{ - ssize_t i; - size_t slen; - char_u key; - size_t dlen = 0; - char_u *src; - int do_backslash; /* backslash is a special character */ - int do_special; /* recognize <> key codes */ - int do_key_code; /* recognize raw key codes */ - char_u *result; /* buffer for resulting string */ - - do_backslash = (vim_strchr(p_cpo, CPO_BSLASH) == NULL); - do_special = (vim_strchr(p_cpo, CPO_SPECI) == NULL) || special; - do_key_code = (vim_strchr(p_cpo, CPO_KEYCODE) == NULL); - - /* - * Allocate space for the translation. Worst case a single character is - * replaced by 6 bytes (shifted special key), plus a NUL at the end. - */ - result = xmalloc(STRLEN(from) * 6 + 1); - - src = from; - - /* - * Check for #n at start only: function key n - */ - if (from_part && src[0] == '#' && VIM_ISDIGIT(src[1])) { /* function key */ - result[dlen++] = K_SPECIAL; - result[dlen++] = 'k'; - if (src[1] == '0') - result[dlen++] = ';'; /* #0 is F10 is "k;" */ - else - result[dlen++] = src[1]; /* #3 is F3 is "k3" */ - src += 2; - } - - /* - * Copy each byte from *from to result[dlen] - */ - while (*src != NUL) { - /* - * If 'cpoptions' does not contain '<', check for special key codes, - * like "<C-S-LeftMouse>" - */ - if (do_special && (do_lt || STRNCMP(src, "<lt>", 4) != 0)) { - /* - * Replace <SID> by K_SNR <script-nr> _. - * (room: 5 * 6 = 30 bytes; needed: 3 + <nr> + 1 <= 14) - */ - if (STRNICMP(src, "<SID>", 5) == 0) { - if (current_SID <= 0) - EMSG(_(e_usingsid)); - else { - src += 5; - result[dlen++] = K_SPECIAL; - result[dlen++] = (int)KS_EXTRA; - result[dlen++] = (int)KE_SNR; - sprintf((char *)result + dlen, "%" PRId64, (int64_t)current_SID); - dlen += STRLEN(result + dlen); - result[dlen++] = '_'; - continue; - } - } - - slen = trans_special(&src, result + dlen, TRUE); - if (slen) { - dlen += slen; - continue; - } - } - - /* - * If 'cpoptions' does not contain 'k', see if it's an actual key-code. - * Note that this is also checked after replacing the <> form. - * Single character codes are NOT replaced (e.g. ^H or DEL), because - * it could be a character in the file. - */ - if (do_key_code) { - i = find_term_bykeys(src); - if (i >= 0) { - result[dlen++] = K_SPECIAL; - result[dlen++] = termcodes[i].name[0]; - result[dlen++] = termcodes[i].name[1]; - src += termcodes[i].len; - /* If terminal code matched, continue after it. */ - continue; - } - } - - if (do_special) { - char_u *p, *s, len; - - /* - * Replace <Leader> by the value of "mapleader". - * Replace <LocalLeader> by the value of "maplocalleader". - * If "mapleader" or "maplocalleader" isn't set use a backslash. - */ - if (STRNICMP(src, "<Leader>", 8) == 0) { - len = 8; - p = get_var_value((char_u *)"g:mapleader"); - } else if (STRNICMP(src, "<LocalLeader>", 13) == 0) { - len = 13; - p = get_var_value((char_u *)"g:maplocalleader"); - } else { - len = 0; - p = NULL; - } - if (len != 0) { - /* Allow up to 8 * 6 characters for "mapleader". */ - if (p == NULL || *p == NUL || STRLEN(p) > 8 * 6) - s = (char_u *)"\\"; - else - s = p; - while (*s != NUL) - result[dlen++] = *s++; - src += len; - continue; - } - } - - /* - * Remove CTRL-V and ignore the next character. - * For "from" side the CTRL-V at the end is included, for the "to" - * part it is removed. - * If 'cpoptions' does not contain 'B', also accept a backslash. - */ - key = *src; - if (key == Ctrl_V || (do_backslash && key == '\\')) { - ++src; /* skip CTRL-V or backslash */ - if (*src == NUL) { - if (from_part) - result[dlen++] = key; - break; - } - } - - /* skip multibyte char correctly */ - for (i = (*mb_ptr2len)(src); i > 0; --i) { - /* - * If the character is K_SPECIAL, replace it with K_SPECIAL - * KS_SPECIAL KE_FILLER. - * If compiled with the GUI replace CSI with K_CSI. - */ - if (*src == K_SPECIAL) { - result[dlen++] = K_SPECIAL; - result[dlen++] = KS_SPECIAL; - result[dlen++] = KE_FILLER; - } else - result[dlen++] = *src; - ++src; - } - } - result[dlen] = NUL; - - *bufp = xrealloc(result, dlen + 1); - - return *bufp; -} - -/* - * Find a termcode with keys 'src' (must be NUL terminated). - * Return the index in termcodes[], or -1 if not found. - */ -ssize_t find_term_bykeys(char_u *src) -{ - size_t slen = STRLEN(src); - - for (size_t i = 0; i < tc_len; ++i) { - assert(termcodes[i].len >= 0); - if (slen == (size_t)termcodes[i].len - && STRNCMP(termcodes[i].code, src, slen) == 0) { - assert(i <= SSIZE_MAX); - return (ssize_t)i; - } - } - return -1; -} - -/* - * Show all termcodes (for ":set termcap") - * This code looks a lot like showoptions(), but is different. - */ -void show_termcodes(void) -{ -#define INC3 27 /* try to make three columns */ -#define INC2 40 /* try to make two columns */ -#define GAP 2 /* spaces between columns */ - - if (tc_len == 0) /* no terminal codes (must be GUI) */ - return; - - size_t *items = xmalloc(sizeof(size_t) * tc_len); - - /* Highlight title */ - MSG_PUTS_TITLE(_("\n--- Terminal keys ---")); - - /* - * do the loop two times: - * 1. display the short items (non-strings and short strings) - * 2. display the medium items (medium length strings) - * 3. display the long items (remaining strings) - */ - for (int run = 1; run <= 3 && !got_int; ++run) { - /* - * collect the items in items[] - */ - size_t item_count = 0; - for (size_t i = 0; i < tc_len; i++) { - int len = show_one_termcode(termcodes[i].name, - termcodes[i].code, FALSE); - if (len <= INC3 - GAP ? run == 1 - : len <= INC2 - GAP ? run == 2 - : run == 3) - items[item_count++] = i; - } - - /* - * display the items - */ - size_t rows, cols; - if (run <= 2) { - cols = (size_t)(Columns + GAP) / (run == 1 ? INC3 : INC2); - if (cols == 0) - cols = 1; - rows = (item_count + cols - 1) / cols; - } else /* run == 3 */ - rows = item_count; - for (size_t row = 0; row < rows && !got_int; ++row) { - msg_putchar('\n'); /* go to next line */ - if (got_int) /* 'q' typed in more */ - break; - size_t col = 0; - for (size_t i = row; i < item_count; i += rows) { - assert(col <= INT_MAX); - msg_col = (int)col; /* make columns */ - show_one_termcode(termcodes[items[i]].name, - termcodes[items[i]].code, TRUE); - if (run == 2) - col += INC2; - else - col += INC3; - } - out_flush(); - os_breakcheck(); - } - } - free(items); -} - -/* - * Show one termcode entry. - * Output goes into IObuff[] - */ -int show_one_termcode(char_u *name, char_u *code, int printit) -{ - char_u *p; - int len; - - if (name[0] > '~') { - IObuff[0] = ' '; - IObuff[1] = ' '; - IObuff[2] = ' '; - IObuff[3] = ' '; - } else { - IObuff[0] = 't'; - IObuff[1] = '_'; - IObuff[2] = name[0]; - IObuff[3] = name[1]; - } - IObuff[4] = ' '; - - p = get_special_key_name(TERMCAP2KEY(name[0], name[1]), 0); - if (p[1] != 't') - STRCPY(IObuff + 5, p); - else - IObuff[5] = NUL; - len = (int)STRLEN(IObuff); - do - IObuff[len++] = ' '; - while (len < 17); - IObuff[len] = NUL; - if (code == NULL) - len += 4; - else - len += vim_strsize(code); - - if (printit) { - msg_puts(IObuff); - if (code == NULL) - msg_puts((char_u *)"NULL"); - else - msg_outtrans(code); - } - return len; -} - -/* - * Translate an internal mapping/abbreviation representation into the - * corresponding external one recognized by :map/:abbrev commands; - * respects the current B/k/< settings of 'cpoption'. - * - * This function is called when expanding mappings/abbreviations on the - * command-line, and for building the "Ambiguous mapping..." error message. - * - * It uses a growarray to build the translation string since the - * latter can be wider than the original description. The caller has to - * free the string afterwards. - * - * Returns NULL when there is a problem. - */ -char_u * -translate_mapping ( - char_u *str, - int expmap /* TRUE when expanding mappings on command-line */ -) -{ - garray_T ga; - ga_init(&ga, 1, 40); - - int cpo_bslash = (vim_strchr(p_cpo, CPO_BSLASH) != NULL); - int cpo_special = (vim_strchr(p_cpo, CPO_SPECI) != NULL); - int cpo_keycode = (vim_strchr(p_cpo, CPO_KEYCODE) == NULL); - - for (; *str; ++str) { - int c = *str; - if (c == K_SPECIAL && str[1] != NUL && str[2] != NUL) { - int modifiers = 0; - if (str[1] == KS_MODIFIER) { - str++; - modifiers = *++str; - c = *++str; - } - if (cpo_special && cpo_keycode && c == K_SPECIAL && !modifiers) { - /* try to find special key in termcodes */ - size_t i; - for (i = 0; i < tc_len; ++i) - if (termcodes[i].name[0] == str[1] - && termcodes[i].name[1] == str[2]) - break; - if (i < tc_len) { - ga_concat(&ga, termcodes[i].code); - str += 2; - continue; /* for (str) */ - } - } - if (c == K_SPECIAL && str[1] != NUL && str[2] != NUL) { - if (expmap && cpo_special) { - ga_clear(&ga); - return NULL; - } - c = TO_SPECIAL(str[1], str[2]); - if (c == K_ZERO) /* display <Nul> as ^@ */ - c = NUL; - str += 2; - } - if (IS_SPECIAL(c) || modifiers) { /* special key */ - if (expmap && cpo_special) { - ga_clear(&ga); - return NULL; - } - ga_concat(&ga, get_special_key_name(c, modifiers)); - continue; /* for (str) */ - } - } - if (c == ' ' || c == '\t' || c == Ctrl_J || c == Ctrl_V - || (c == '<' && !cpo_special) || (c == '\\' && !cpo_bslash)) - ga_append(&ga, cpo_bslash ? Ctrl_V : '\\'); - if (c) - ga_append(&ga, (char)c); - } - ga_append(&ga, NUL); - return (char_u *)(ga.ga_data); -} - diff --git a/src/nvim/term.h b/src/nvim/term.h deleted file mode 100644 index 3f70f484a7..0000000000 --- a/src/nvim/term.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef NVIM_TERM_H -#define NVIM_TERM_H - -/* Size of the buffer used for tgetent(). Unfortunately this is largely - * undocumented, some systems use 1024. Using a buffer that is too small - * causes a buffer overrun and a crash. Use the maximum known value to stay - * on the safe side. */ -#define TBUFSZ 2048 /* buffer size for termcap entry */ - -/* Codes for mouse button events in lower three bits: */ -#define MOUSE_LEFT 0x00 -#define MOUSE_MIDDLE 0x01 -#define MOUSE_RIGHT 0x02 -#define MOUSE_RELEASE 0x03 - -/* bit masks for modifiers: */ -#define MOUSE_SHIFT 0x04 -#define MOUSE_ALT 0x08 -#define MOUSE_CTRL 0x10 - -/* mouse buttons that are handled like a key press (GUI only) */ -/* Note that the scroll wheel keys are inverted: MOUSE_5 scrolls lines up but - * the result of this is that the window moves down, similarly MOUSE_6 scrolls - * columns left but the window moves right. */ -#define MOUSE_4 0x100 /* scroll wheel down */ -#define MOUSE_5 0x200 /* scroll wheel up */ - -#define MOUSE_X1 0x300 /* Mouse-button X1 (6th) */ -#define MOUSE_X2 0x400 /* Mouse-button X2 */ - -#define MOUSE_6 0x500 /* scroll wheel left */ -#define MOUSE_7 0x600 /* scroll wheel right */ - -/* 0x20 is reserved by xterm */ -#define MOUSE_DRAG_XTERM 0x40 - -#define MOUSE_DRAG (0x40 | MOUSE_RELEASE) - -/* Lowest button code for using the mouse wheel (xterm only) */ -#define MOUSEWHEEL_LOW 0x60 - -#define MOUSE_CLICK_MASK 0x03 - -#define NUM_MOUSE_CLICKS(code) \ - (((unsigned)((code) & 0xC0) >> 6) + 1) - -#define SET_NUM_MOUSE_CLICKS(code, num) \ - (code) = ((code) & 0x3f) | ((((num) - 1) & 3) << 6) - -/* Added to mouse column for GUI when 'mousefocus' wants to give focus to a - * window by simulating a click on its status line. We could use up to 128 * - * 128 = 16384 columns, now it's reduced to 10000. */ -#define MOUSE_COLOFF 10000 - -#ifdef INCLUDE_GENERATED_DECLARATIONS -# include "term.h.generated.h" -#endif -#endif // NVIM_TERM_H diff --git a/src/nvim/term_defs.h b/src/nvim/term_defs.h deleted file mode 100644 index 757792ea7c..0000000000 --- a/src/nvim/term_defs.h +++ /dev/null @@ -1,160 +0,0 @@ -#ifndef NVIM_TERM_DEFS_H -#define NVIM_TERM_DEFS_H - -/* - * VIM - Vi IMproved by Bram Moolenaar - * - * Do ":help uganda" in Vim to read copying and usage conditions. - * Do ":help credits" in Vim to see a list of people who contributed. - */ - -/* - * This file contains the defines for the machine dependent escape sequences - * that the editor needs to perform various operations. All of the sequences - * here are optional, except "cm" (cursor motion). - */ - - -/* - * Index of the termcap codes in the term_strings array. - */ -enum SpecialKey { - KS_NAME = 0, /* name of this terminal entry */ - KS_CE, /* clear to end of line */ - KS_AL, /* add new blank line */ - KS_CAL, /* add number of blank lines */ - KS_DL, /* delete line */ - KS_CDL, /* delete number of lines */ - KS_CS, /* scroll region */ - KS_CL, /* clear screen */ - KS_CD, /* clear to end of display */ - KS_UT, /* clearing uses current background color */ - KS_DA, /* text may be scrolled down from up */ - KS_DB, /* text may be scrolled up from down */ - KS_VI, /* cursor invisible */ - KS_VE, /* cursor visible */ - KS_VS, /* cursor very visible */ - KS_ME, /* normal mode */ - KS_MR, /* reverse mode */ - KS_MD, /* bold mode */ - KS_SE, /* normal mode */ - KS_SO, /* standout mode */ - KS_CZH, /* italic mode start */ - KS_CZR, /* italic mode end */ - KS_UE, /* exit underscore (underline) mode */ - KS_US, /* underscore (underline) mode */ - KS_UCE, /* exit undercurl mode */ - KS_UCS, /* undercurl mode */ - KS_MS, /* save to move cur in reverse mode */ - KS_CM, /* cursor motion */ - KS_SR, /* scroll reverse (backward) */ - KS_CRI, /* cursor number of chars right */ - KS_VB, /* visual bell */ - KS_KS, /* put term in "keypad transmit" mode */ - KS_KE, /* out of "keypad transmit" mode */ - KS_TI, /* put terminal in termcap mode */ - KS_TE, /* out of termcap mode */ - KS_BC, /* backspace character (cursor left) */ - KS_CCS, /* cur is relative to scroll region */ - KS_CCO, /* number of colors */ - KS_CSF, /* set foreground color */ - KS_CSB, /* set background color */ - KS_XS, /* standout not erased by overwriting (hpterm) */ - KS_MB, /* blink mode */ - KS_CAF, /* set foreground color (ANSI) */ - KS_CAB, /* set background color (ANSI) */ - KS_LE, /* cursor left (mostly backspace) */ - KS_ND, /* cursor right */ - KS_CIS, /* set icon text start */ - KS_CIE, /* set icon text end */ - KS_TS, /* set window title start (to status line)*/ - KS_FS, /* set window title end (from status line) */ - KS_CWP, /* set window position in pixels */ - KS_CWS, /* set window size in characters */ - KS_CRV, /* request version string */ - KS_CSI, /* start insert mode (bar cursor) */ - KS_CEI, /* end insert mode (block cursor) */ - KS_CSV, /* scroll region vertical */ - KS_OP, /* original color pair */ - KS_U7 /* request cursor position */ -}; - -#define KS_LAST KS_U7 - -/* - * the terminal capabilities are stored in this array - * IMPORTANT: When making changes, note the following: - * - there should be an entry for each code in the builtin termcaps - * - there should be an option for each code in option.c - * - there should be code in term.c to obtain the value from the termcap - */ - -extern char_u *(term_strings[]); /* current terminal strings */ - -/* - * strings used for terminal - */ -#define T_NAME (term_str(KS_NAME)) /* terminal name */ -#define T_CE (term_str(KS_CE)) /* clear to end of line */ -#define T_AL (term_str(KS_AL)) /* add new blank line */ -#define T_CAL (term_str(KS_CAL)) /* add number of blank lines */ -#define T_DL (term_str(KS_DL)) /* delete line */ -#define T_CDL (term_str(KS_CDL)) /* delete number of lines */ -#define T_CS (term_str(KS_CS)) /* scroll region */ -#define T_CSV (term_str(KS_CSV)) /* scroll region vertical */ -#define T_CL (term_str(KS_CL)) /* clear screen */ -#define T_CD (term_str(KS_CD)) /* clear to end of display */ -#define T_UT (term_str(KS_UT)) /* clearing uses background color */ -#define T_DA (term_str(KS_DA)) /* text may be scrolled down from up */ -#define T_DB (term_str(KS_DB)) /* text may be scrolled up from down */ -#define T_VI (term_str(KS_VI)) /* cursor invisible */ -#define T_VE (term_str(KS_VE)) /* cursor visible */ -#define T_VS (term_str(KS_VS)) /* cursor very visible */ -#define T_ME (term_str(KS_ME)) /* normal mode */ -#define T_MR (term_str(KS_MR)) /* reverse mode */ -#define T_MD (term_str(KS_MD)) /* bold mode */ -#define T_SE (term_str(KS_SE)) /* normal mode */ -#define T_SO (term_str(KS_SO)) /* standout mode */ -#define T_CZH (term_str(KS_CZH)) /* italic mode start */ -#define T_CZR (term_str(KS_CZR)) /* italic mode end */ -#define T_UE (term_str(KS_UE)) /* exit underscore (underline) mode */ -#define T_US (term_str(KS_US)) /* underscore (underline) mode */ -#define T_UCE (term_str(KS_UCE)) /* exit undercurl mode */ -#define T_UCS (term_str(KS_UCS)) /* undercurl mode */ -#define T_MS (term_str(KS_MS)) /* save to move cur in reverse mode */ -#define T_CM (term_str(KS_CM)) /* cursor motion */ -#define T_SR (term_str(KS_SR)) /* scroll reverse (backward) */ -#define T_CRI (term_str(KS_CRI)) /* cursor number of chars right */ -#define T_VB (term_str(KS_VB)) /* visual bell */ -#define T_KS (term_str(KS_KS)) /* put term in "keypad transmit" mode */ -#define T_KE (term_str(KS_KE)) /* out of "keypad transmit" mode */ -#define T_TI (term_str(KS_TI)) /* put terminal in termcap mode */ -#define T_TE (term_str(KS_TE)) /* out of termcap mode */ -#define T_BC (term_str(KS_BC)) /* backspace character */ -#define T_CCS (term_str(KS_CCS)) /* cur is relative to scroll region */ -#define T_CCO (term_str(KS_CCO)) /* number of colors */ -#define T_CSF (term_str(KS_CSF)) /* set foreground color */ -#define T_CSB (term_str(KS_CSB)) /* set background color */ -#define T_XS (term_str(KS_XS)) /* standout not erased by overwriting */ -#define T_MB (term_str(KS_MB)) /* blink mode */ -#define T_CAF (term_str(KS_CAF)) /* set foreground color (ANSI) */ -#define T_CAB (term_str(KS_CAB)) /* set background color (ANSI) */ -#define T_LE (term_str(KS_LE)) /* cursor left */ -#define T_ND (term_str(KS_ND)) /* cursor right */ -#define T_CIS (term_str(KS_CIS)) /* set icon text start */ -#define T_CIE (term_str(KS_CIE)) /* set icon text end */ -#define T_TS (term_str(KS_TS)) /* set window title start */ -#define T_FS (term_str(KS_FS)) /* set window title end */ -#define T_CWP (term_str(KS_CWP)) /* window position */ -#define T_CWS (term_str(KS_CWS)) /* window size */ -#define T_CSI (term_str(KS_CSI)) /* start insert mode */ -#define T_CEI (term_str(KS_CEI)) /* end insert mode */ -#define T_CRV (term_str(KS_CRV)) /* request version string */ -#define T_OP (term_str(KS_OP)) /* original color pair */ -#define T_U7 (term_str(KS_U7)) /* request cursor position */ - -#define TMODE_COOK 0 /* terminal mode for external cmds and Ex mode */ -#define TMODE_SLEEP 1 /* terminal mode for sleeping (cooked but no echo) */ -#define TMODE_RAW 2 /* terminal mode for Normal and Insert mode */ - -#endif // NVIM_TERM_DEFS_H diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c index 5951408c42..0d366c2325 100644 --- a/src/nvim/tui/tui.c +++ b/src/nvim/tui/tui.c @@ -30,7 +30,6 @@ typedef struct { } Cell; typedef struct { - PMap(cstr_t) *option_cache; unibi_var_t params[9]; char buf[0xffff]; size_t bufpos; @@ -87,7 +86,6 @@ void tui_start(void) data->fg = data->bg = -1; data->can_use_terminal_scroll = true; data->bufpos = 0; - data->option_cache = pmap_new(cstr_t)(); data->unibi_ext.enable_mouse = -1; data->unibi_ext.disable_mouse = -1; data->unibi_ext.enable_bracketed_paste = -1; @@ -184,11 +182,6 @@ static void tui_stop(UI *ui) } free(data->write_loop); unibi_destroy(data->ut); - char *opt_value; - map_foreach_value(data->option_cache, opt_value, { - free(opt_value); - }); - pmap_free(cstr_t)(data->option_cache); destroy_screen(data); free(data); ui_detach(ui); @@ -257,7 +250,7 @@ static void update_attrs(UI *ui, HlAttrs attrs) static void print_cell(UI *ui, Cell *ptr) { update_attrs(ui, ptr->attrs); - out(ui, ptr->data); + out(ui, ptr->data, strlen(ptr->data)); } static void clear_region(UI *ui, int top, int bot, int left, int right, @@ -547,12 +540,12 @@ static void tui_suspend(UI *ui) static void tui_set_title(UI *ui, char *title) { TUIData *data = ui->data; - if (!(unibi_get_str(data->ut, unibi_to_status_line) - && unibi_get_str(data->ut, unibi_from_status_line))) { + if (!(title && unibi_get_str(data->ut, unibi_to_status_line) && + unibi_get_str(data->ut, unibi_from_status_line))) { return; } unibi_out(ui, unibi_to_status_line); - out(ui, title); + out(ui, title, strlen(title)); unibi_out(ui, unibi_from_status_line); } @@ -655,16 +648,23 @@ static void unibi_out(UI *ui, int unibi_index) } if (str) { - data->bufpos += unibi_run(str, data->params, data->buf + data->bufpos, - sizeof(data->buf) - data->bufpos); + unibi_var_t vars[26 + 26] = {{0}}; + unibi_format(vars, vars + 26, str, data->params, out, ui, NULL, NULL); } } -static void out(UI *ui, const char *str) +static void out(void *ctx, const char *str, size_t len) { + UI *ui = ctx; TUIData *data = ui->data; - data->bufpos += (size_t)snprintf(data->buf + data->bufpos, - sizeof(data->buf) - data->bufpos, "%s", str); + size_t available = sizeof(data->buf) - data->bufpos; + + if (len > available) { + flush_buf(ui); + } + + memcpy(data->buf + data->bufpos, str, len); + data->bufpos += len; } static void unibi_set_if_empty(unibi_term *ut, enum unibi_string str, @@ -717,6 +717,19 @@ static void fix_terminfo(TUIData *data) "\x1b[?2004l"); } +#define XTERM_SETAF \ + "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m" +#define XTERM_SETAB \ + "\x1b[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m" + + if (!strcmp(term, "xterm") && os_getenv("COLORTERM") != NULL) { + // probably every modern terminal that sets TERM=xterm supports 256 + // colors(eg: gnome-terminal). + unibi_set_num(ut, unibi_max_colors, 256); + unibi_set_str(ut, unibi_set_a_foreground, XTERM_SETAF); + unibi_set_str(ut, unibi_set_a_background, XTERM_SETAB); + } + if (os_getenv("NVIM_TUI_ENABLE_CURSOR_SHAPE") == NULL) { goto end; } @@ -748,10 +761,8 @@ end: "\x1b[?1002l\x1b[?1006l"); unibi_set_if_empty(ut, unibi_cursor_address, "\x1b[%i%p1%d;%p2%dH"); unibi_set_if_empty(ut, unibi_exit_attribute_mode, "\x1b[0;10m"); - unibi_set_if_empty(ut, unibi_set_a_foreground, - "\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m"); - unibi_set_if_empty(ut, unibi_set_a_background, - "\x1b[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m"); + unibi_set_if_empty(ut, unibi_set_a_foreground, XTERM_SETAF); + unibi_set_if_empty(ut, unibi_set_a_background, XTERM_SETAB); unibi_set_if_empty(ut, unibi_enter_bold_mode, "\x1b[1m"); unibi_set_if_empty(ut, unibi_enter_underline_mode, "\x1b[4m"); unibi_set_if_empty(ut, unibi_enter_reverse_mode, "\x1b[7m"); diff --git a/src/nvim/ui.c b/src/nvim/ui.c index c09cca1347..97fffa4f4e 100644 --- a/src/nvim/ui.c +++ b/src/nvim/ui.c @@ -1,20 +1,3 @@ -/* - * VIM - Vi IMproved by Bram Moolenaar - * - * Do ":help uganda" in Vim to read copying and usage conditions. - * Do ":help credits" in Vim to see a list of people who contributed. - * See README.txt for an overview of the Vim source code. - */ - -/* - * ui.c: functions that handle the user interface. - * 1. Keyboard input stuff, and a bit of windowing stuff. These are called - * before the machine specific stuff (mch_*) so that we can call the GUI - * stuff instead if the GUI is running. - * 2. Clipboard stuff. - * 3. Input buffer stuff. - */ - #include <assert.h> #include <inttypes.h> #include <stdbool.h> @@ -44,7 +27,6 @@ #include "nvim/os/signal.h" #include "nvim/screen.h" #include "nvim/syntax.h" -#include "nvim/term.h" #include "nvim/window.h" #include "nvim/tui/tui.h" @@ -56,7 +38,7 @@ static UI *uis[MAX_UI_COUNT]; static size_t ui_count = 0; -static int row, col; +static int row = 0, col = 0; static struct { int top, bot, left, right; } sr; @@ -95,16 +77,6 @@ void ui_builtin_stop(void) UI_CALL(stop); } -void ui_write(uint8_t *s, size_t len) -{ - if (silent_mode && !p_verbose) { - // Don't output anything in silent mode ("ex -s") unless 'verbose' set - return; - } - - parse_abstract_ui_codes(s, len); -} - bool ui_rgb_attached(void) { for (size_t i = 0; i < ui_count; i++) { @@ -120,11 +92,6 @@ bool ui_active(void) return ui_count != 0; } -/* - * If the machine has job control, use it to suspend the program, - * otherwise fake it by starting a new shell. - * When running the GUI iconify the window. - */ void ui_suspend(void) { UI_CALL(suspend); @@ -143,9 +110,7 @@ void ui_set_icon(char *icon) UI_CALL(flush); } -/* - * May update the shape of the cursor. - */ +// May update the shape of the cursor. void ui_cursor_shape(void) { ui_change_mode(); @@ -165,6 +130,7 @@ void ui_refresh(void) height = ui->height < height ? ui->height : height; } + row = col = 0; screen_resize(width, height); } @@ -211,29 +177,6 @@ void ui_mouse_off(void) UI_CALL(mouse_off); } -// Notify that the current mode has changed. Can be used to change cursor -// shape, for example. -void ui_change_mode(void) -{ - static int showing_insert_mode = MAYBE; - - if (!full_screen) - return; - - if (State & INSERT) { - if (showing_insert_mode != TRUE) { - UI_CALL(insert_mode); - } - showing_insert_mode = TRUE; - } else { - if (showing_insert_mode != FALSE) { - UI_CALL(normal_mode); - } - showing_insert_mode = FALSE; - } - conceal_check_cursur_line(); -} - void ui_attach(UI *ui) { if (ui_count == MAX_UI_COUNT) { @@ -273,7 +216,54 @@ void ui_detach(UI *ui) } } -static void highlight_start(int attr_code) +void ui_clear(void) +{ + UI_CALL(clear); +} + +// Set scrolling region for window 'wp'. +// The region starts 'off' lines from the start of the window. +// Also set the vertical scroll region for a vertically split window. Always +// the full width of the window, excluding the vertical separator. +void ui_set_scroll_region(win_T *wp, int off) +{ + sr.top = wp->w_winrow + off; + sr.bot = wp->w_winrow + wp->w_height - 1; + + if (wp->w_width != Columns) { + sr.left = wp->w_wincol; + sr.right = wp->w_wincol + wp->w_width - 1; + } + + UI_CALL(set_scroll_region, sr.top, sr.bot, sr.left, sr.right); +} + +// Reset scrolling region to the whole screen. +void ui_reset_scroll_region(void) +{ + sr.top = 0; + sr.bot = (int)Rows - 1; + sr.left = 0; + sr.right = (int)Columns - 1; + UI_CALL(set_scroll_region, sr.top, sr.bot, sr.left, sr.right); +} + +void ui_append_lines(int count) +{ + UI_CALL(scroll, -count); +} + +void ui_delete_lines(int count) +{ + UI_CALL(scroll, count); +} + +void ui_eol_clear(void) +{ + UI_CALL(eol_clear); +} + +void ui_start_highlight(int attr_code) { current_attr_code = attr_code; @@ -284,7 +274,7 @@ static void highlight_start(int attr_code) set_highlight_args(current_attr_code); } -static void highlight_stop(int mask) +void ui_stop_highlight(void) { current_attr_code = HL_NORMAL; @@ -295,6 +285,94 @@ static void highlight_stop(int mask) set_highlight_args(current_attr_code); } +void ui_visual_bell(void) +{ + UI_CALL(visual_bell); +} + +void ui_puts(uint8_t *str) +{ + uint8_t *ptr = str; + uint8_t c; + + while ((c = *ptr)) { + if (c < 0x20) { + parse_control_character(c); + ptr++; + } else { + send_output(&ptr); + } + } +} + +void ui_putc(uint8_t c) +{ + uint8_t buf[2] = {c, 0}; + ui_puts(buf); +} + +void ui_cursor_goto(int new_row, int new_col) +{ + if (new_row == row && new_col == col) { + return; + } + row = new_row; + col = new_col; + pending_cursor_update = true; +} + +int ui_current_row(void) +{ + return row; +} + +int ui_current_col(void) +{ + return col; +} + +void ui_flush(void) +{ + UI_CALL(flush); +} + +static void send_output(uint8_t **ptr) +{ + uint8_t *p = *ptr; + + while (*p >= 0x20) { + size_t clen = (size_t)mb_ptr2len(p); + UI_CALL(put, p, (size_t)clen); + col++; + if (mb_ptr2cells(p) > 1) { + // double cell character, blank the next cell + UI_CALL(put, NULL, 0); + col++; + } + if (col >= width) { + ui_linefeed(); + } + p += clen; + } + + *ptr = p; +} + +static void parse_control_character(uint8_t c) +{ + if (c == '\n') { + ui_linefeed(); + } else if (c == '\r') { + ui_carriage_return(); + } else if (c == '\b') { + ui_cursor_left(); + } else if (c == Ctrl_L) { + ui_cursor_right(); + } else if (c == Ctrl_G) { + UI_CALL(bell); + } +} + static void set_highlight_args(int attr_code) { HlAttrs rgb_attrs = { false, false, false, false, false, -1, -1 }; @@ -346,138 +424,6 @@ end: UI_CALL(highlight_set, (ui->rgb ? rgb_attrs : cterm_attrs)); } -static void parse_abstract_ui_codes(uint8_t *ptr, size_t len) -{ - if (!ui_active()) { - return; - } - - int arg1 = 0, arg2 = 0; - uint8_t *end = ptr + len, *p, c; - bool update_cursor = false; - - while (ptr < end) { - if (ptr < end - 1 && ptr[0] == ESC && ptr[1] == '|') { - p = ptr + 2; - assert(p != end); - - if (VIM_ISDIGIT(*p)) { - arg1 = getdigits_int(&p); - if (p >= end) { - break; - } - - if (*p == ';') { - p++; - arg2 = getdigits_int(&p); - if (p >= end) - break; - } - } - - switch (*p) { - case 'C': - UI_CALL(clear); - break; - case 'M': - ui_cursor_goto(arg1, arg2); - break; - case 's': - update_cursor = true; - break; - case 'R': - if (arg1 < arg2) { - sr.top = arg1; - sr.bot = arg2; - UI_CALL(set_scroll_region, sr.top, sr.bot, sr.left, sr.right); - } else { - sr.top = arg2; - sr.bot = arg1; - UI_CALL(set_scroll_region, sr.top, sr.bot, sr.left, sr.right); - } - break; - case 'V': - if (arg1 < arg2) { - sr.left = arg1; - sr.right = arg2; - UI_CALL(set_scroll_region, sr.top, sr.bot, sr.left, sr.right); - } else { - sr.left = arg2; - sr.right = arg1; - UI_CALL(set_scroll_region, sr.top, sr.bot, sr.left, sr.right); - } - break; - case 'd': - UI_CALL(scroll, 1); - break; - case 'D': - UI_CALL(scroll, arg1); - break; - case 'i': - UI_CALL(scroll, -1); - break; - case 'I': - UI_CALL(scroll, -arg1); - break; - case '$': - UI_CALL(eol_clear); - break; - case 'h': - highlight_start(arg1); - break; - case 'H': - highlight_stop(arg1); - break; - case 'f': - UI_CALL(visual_bell); - break; - default: - // Skip the ESC - p = ptr + 1; - break; - } - ptr = ++p; - } else if ((c = *ptr) < 0x20) { - // Ctrl character - if (c == '\n') { - ui_linefeed(); - } else if (c == '\r') { - ui_carriage_return(); - } else if (c == '\b') { - ui_cursor_left(); - } else if (c == Ctrl_L) { // cursor right - ui_cursor_right(); - } else if (c == Ctrl_G) { - UI_CALL(bell); - } - ptr++; - } else { - p = ptr; - while (p < end && (*p >= 0x20)) { - size_t clen = (size_t)mb_ptr2len(p); - UI_CALL(put, p, (size_t)clen); - col++; - if (mb_ptr2cells(p) > 1) { - // double cell character, blank the next cell - UI_CALL(put, NULL, 0); - col++; - } - if (col >= width) { - ui_linefeed(); - } - p += clen; - } - ptr = p; - } - } - - if (update_cursor) { - ui_cursor_shape(); - } - - UI_CALL(flush); -} - static void ui_linefeed(void) { int new_col = 0; @@ -510,16 +456,6 @@ static void ui_cursor_right(void) ui_cursor_goto(row, new_col); } -static void ui_cursor_goto(int new_row, int new_col) -{ - if (new_row == row && new_col == col) { - return; - } - row = new_row; - col = new_col; - pending_cursor_update = true; -} - static void flush_cursor_update(void) { if (pending_cursor_update) { @@ -527,3 +463,28 @@ static void flush_cursor_update(void) UI_CALL(cursor_goto, row, col); } } + +// Notify that the current mode has changed. Can be used to change cursor +// shape, for example. +static void ui_change_mode(void) +{ + static int showing_insert_mode = MAYBE; + + if (!full_screen) { + return; + } + + if (State & INSERT) { + if (showing_insert_mode != TRUE) { + UI_CALL(insert_mode); + } + showing_insert_mode = TRUE; + } else { + if (showing_insert_mode != FALSE) { + UI_CALL(normal_mode); + } + showing_insert_mode = FALSE; + } + conceal_check_cursur_line(); +} + diff --git a/src/nvim/vim.h b/src/nvim/vim.h index 5a89a3c861..8f80efd88a 100644 --- a/src/nvim/vim.h +++ b/src/nvim/vim.h @@ -53,7 +53,6 @@ Error: configure did not run properly.Check auto/config.log. # define MAX_TYPENR 65535 #include "nvim/keymap.h" -#include "nvim/term_defs.h" #include "nvim/macros.h" diff --git a/src/nvim/window.c b/src/nvim/window.c index adc6e9f1c2..e51ef670da 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -52,7 +52,6 @@ #include "nvim/search.h" #include "nvim/strings.h" #include "nvim/syntax.h" -#include "nvim/term.h" #include "nvim/undo.h" #include "nvim/os/os.h" |