mirror of
				https://github.com/neovim/neovim.git
				synced 2025-10-26 12:27:24 +00:00 
			
		
		
		
	tui: Do some deferred wrap on iTerm2.
Partly undo 8ab08a65ba3bc9a44741a2ec9aa81fbcc77467fb. Further testing by Enrico Ghirardi suggests limiting the non-deferred automatic wrap to only the bottom line, whose rightmost column is not printed for iTerm.
This commit is contained in:
		| @@ -91,6 +91,7 @@ typedef struct { | ||||
|   bool can_set_lr_margin; | ||||
|   bool can_set_left_right_margin; | ||||
|   bool immediate_wrap_after_last_column; | ||||
|   bool no_bottom_right_corner; | ||||
|   bool mouse_enabled; | ||||
|   bool busy; | ||||
|   cursorentry_T cursor_shapes[SHAPE_IDX_COUNT]; | ||||
| @@ -201,10 +202,11 @@ static void terminfo_start(UI *ui) | ||||
|   data->can_set_left_right_margin = | ||||
|     !!unibi_get_str(data->ut, unibi_set_left_margin_parm) | ||||
|     && !!unibi_get_str(data->ut, unibi_set_right_margin_parm); | ||||
|   data->immediate_wrap_after_last_column = | ||||
|   data->no_bottom_right_corner = | ||||
|     terminfo_is_term_family(term, "iterm") | ||||
|     || terminfo_is_term_family(term, "interix") | ||||
|     || (terminfo_is_term_family(term, "xterm") && iterm_env); | ||||
|   data->immediate_wrap_after_last_column = | ||||
|     terminfo_is_term_family(term, "interix"); | ||||
|   // Set 't_Co' from the result of unibilium & fix_terminfo. | ||||
|   t_colors = unibi_get_num(data->ut, unibi_max_colors); | ||||
|   // Enter alternate screen and clear | ||||
| @@ -414,20 +416,43 @@ static void update_attrs(UI *ui, HlAttrs attrs) | ||||
|   } | ||||
| } | ||||
|  | ||||
| static void final_column_wrap(UI *ui) | ||||
| { | ||||
|   TUIData *data = ui->data; | ||||
|   UGrid *grid = &data->grid; | ||||
|   if (grid->col == ui->width) { | ||||
|     grid->col = 0; | ||||
|     if (grid->row < ui->height) { | ||||
|       grid->row++; | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| /// It is undocumented, but in the majority of terminals and terminal emulators | ||||
| /// printing at the right margin does not cause an automatic wrap until the | ||||
| /// next character is printed, holding the cursor in place until then. | ||||
| static void print_cell(UI *ui, UCell *ptr) | ||||
| { | ||||
|   TUIData *data = ui->data; | ||||
|   UGrid *grid = &data->grid; | ||||
|   if (data->immediate_wrap_after_last_column | ||||
|   if (data->no_bottom_right_corner | ||||
|       && grid->row >= ui->height - 1 | ||||
|       && grid->col >= ui->width - 1) { | ||||
|     // This (rare) kind of terminal simply cannot print in this corner without | ||||
|     // scrolling the entire screen up a line, which we do not want to happen. | ||||
|     return; | ||||
|   } | ||||
|   if (!data->immediate_wrap_after_last_column) { | ||||
|     // Printing the next character finally advances the cursor. | ||||
|     final_column_wrap(ui); | ||||
|   } | ||||
|   update_attrs(ui, ptr->attrs); | ||||
|   out(ui, ptr->data, strlen(ptr->data)); | ||||
|   grid->col++; | ||||
|   if (data->immediate_wrap_after_last_column) { | ||||
|     // Printing at the right margin immediately advances the cursor. | ||||
|     final_column_wrap(ui); | ||||
|   } | ||||
| } | ||||
|  | ||||
| static bool cheap_to_print(UI *ui, int row, int col, int next) | ||||
| @@ -450,25 +475,6 @@ static bool cheap_to_print(UI *ui, int row, int col, int next) | ||||
|   return true; | ||||
| } | ||||
|  | ||||
| /// The behaviour that this is checking for the absence of is undocumented, | ||||
| /// but is implemented in the majority of terminals and terminal emulators. | ||||
| /// Printing at the right margin does not cause an automatic wrap until the | ||||
| /// next character is printed, holding the cursor in place until then. | ||||
| static void check_final_column_wrap(UI *ui) | ||||
| { | ||||
|   TUIData *data = ui->data; | ||||
|   if (!data->immediate_wrap_after_last_column) { | ||||
|     return; | ||||
|   } | ||||
|   UGrid *grid = &data->grid; | ||||
|   if (grid->col == ui->width) { | ||||
|     grid->col = 0; | ||||
|     if (grid->row < ui->height) { | ||||
|       grid->row++; | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| /// This optimizes several cases where it is cheaper to do something other | ||||
| /// than send a full cursor positioning control sequence.  However, there are | ||||
| /// some further optimizations that may seem obvious but that will not work. | ||||
| @@ -506,7 +512,6 @@ static void cursor_goto(UI *ui, int row, int col) | ||||
|         UGRID_FOREACH_CELL(grid, grid->row, grid->row, | ||||
|           grid->col, col - 1, { | ||||
|           print_cell(ui, cell); | ||||
|           check_final_column_wrap(ui); | ||||
|         }); | ||||
|       } | ||||
|   } | ||||
| @@ -614,7 +619,6 @@ static void clear_region(UI *ui, int top, int bot, int left, int right) | ||||
|     UGRID_FOREACH_CELL(grid, top, bot, left, right, { | ||||
|       cursor_goto(ui, row, col); | ||||
|       print_cell(ui, cell); | ||||
|       check_final_column_wrap(ui); | ||||
|     }); | ||||
|   } | ||||
|  | ||||
| @@ -937,7 +941,6 @@ static void tui_put(UI *ui, String text) | ||||
|   // we have to undo what it has just done before doing it right. | ||||
|   grid->col--; | ||||
|   print_cell(ui, cell); | ||||
|   check_final_column_wrap(ui); | ||||
| } | ||||
|  | ||||
| static void tui_bell(UI *ui) | ||||
| @@ -990,7 +993,6 @@ static void tui_flush(UI *ui) | ||||
|     UGRID_FOREACH_CELL(grid, r.top, r.bot, r.left, r.right, { | ||||
|       cursor_goto(ui, row, col); | ||||
|       print_cell(ui, cell); | ||||
|       check_final_column_wrap(ui); | ||||
|     }); | ||||
|   } | ||||
|  | ||||
| @@ -1265,6 +1267,9 @@ static void patch_terminfo_bugs(TUIData *data, const char *term, | ||||
|       unibi_set_if_empty(ut, unibi_set_left_margin_parm, "\x1b[%i%p1%ds"); | ||||
|       unibi_set_if_empty(ut, unibi_set_right_margin_parm, "\x1b[%i;%p2%ds"); | ||||
|     } | ||||
|     if (iterm_pretending_xterm) { | ||||
|       unibi_set_if_empty(ut, unibi_enter_italics_mode, "\x1b[3m"); | ||||
|     } | ||||
|   } else if (rxvt) { | ||||
|     unibi_set_if_empty(ut, unibi_enter_italics_mode, "\x1b[3m"); | ||||
|     unibi_set_if_empty(ut, unibi_to_status_line, "\x1b]2"); | ||||
| @@ -1284,7 +1289,15 @@ static void patch_terminfo_bugs(TUIData *data, const char *term, | ||||
|   } else if (putty) { | ||||
|     // No bugs in the vanilla terminfo for our purposes. | ||||
|   } else if (iterm) { | ||||
|     unibi_set_str(ut, unibi_enter_ca_mode, "\x1b[?1049h"); | ||||
|     unibi_set_str(ut, unibi_exit_ca_mode, "\x1b[?1049l"); | ||||
|     unibi_set_if_empty(ut, unibi_set_tb_margin, "\x1b[%i%p1%d;%p2%dr"); | ||||
|     unibi_set_if_empty(ut, unibi_orig_pair, "\x1b[39;49m"); | ||||
|     unibi_set_if_empty(ut, unibi_enter_dim_mode, "\x1b[2m"); | ||||
|     unibi_set_if_empty(ut, unibi_enter_italics_mode, "\x1b[3m"); | ||||
|     unibi_set_if_empty(ut, unibi_exit_italics_mode, "\x1b[23m"); | ||||
|     unibi_set_if_empty(ut, unibi_exit_underline_mode, "\x1b[24m"); | ||||
|     unibi_set_if_empty(ut, unibi_exit_standout_mode, "\x1b[27m"); | ||||
|   } else if (st) { | ||||
|     // No bugs in the vanilla terminfo for our purposes. | ||||
|   } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Jonathan de Boyne Pollard
					Jonathan de Boyne Pollard