📄 display.c
字号:
/* display.c -- readline redisplay facility. *//* Copyright (C) 1987-2009 Free Software Foundation, Inc. This file is part of the GNU Readline Library (Readline), a library for reading lines of text with interactive input and history editing. Readline is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Readline is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Readline. If not, see <http://www.gnu.org/licenses/>.*/#define READLINE_LIBRARY#if defined (HAVE_CONFIG_H)# include <config.h>#endif#include <sys/types.h>#if defined (HAVE_UNISTD_H)# include <unistd.h>#endif /* HAVE_UNISTD_H */#include "posixstat.h"#if defined (HAVE_STDLIB_H)# include <stdlib.h>#else# include "ansi_stdlib.h"#endif /* HAVE_STDLIB_H */#include <stdio.h>/* System-specific feature definitions and include files. */#include "rldefs.h"#include "rlmbutil.h"/* Termcap library stuff. */#include "tcap.h"/* Some standard library routines. */#include "readline.h"#include "history.h"#include "rlprivate.h"#include "xmalloc.h"#if !defined (strchr) && !defined (__STDC__)extern char *strchr (), *strrchr ();#endif /* !strchr && !__STDC__ */static void update_line PARAMS((char *, char *, int, int, int, int));static void space_to_eol PARAMS((int));static void delete_chars PARAMS((int));static void insert_some_chars PARAMS((char *, int, int));static void cr PARAMS((void));/* State of visible and invisible lines. */struct line_state { char *line; int *lbreaks; int lbsize;#if defined (HANDLE_MULTIBYTE) int *wrapped_line; int wbsize;#endif };/* The line display buffers. One is the line currently displayed on the screen. The other is the line about to be displayed. */static struct line_state line_state_array[2];static struct line_state *line_state_visible = &line_state_array[0];static struct line_state *line_state_invisible = &line_state_array[1];static int line_structures_initialized = 0;/* Backwards-compatible names. */#define inv_lbreaks (line_state_invisible->lbreaks)#define inv_lbsize (line_state_invisible->lbsize)#define vis_lbreaks (line_state_visible->lbreaks)#define vis_lbsize (line_state_visible->lbsize)#define visible_line (line_state_visible->line)#define invisible_line (line_state_invisible->line)#if defined (HANDLE_MULTIBYTE)static int _rl_col_width PARAMS((const char *, int, int, int));#else# define _rl_col_width(l, s, e, f) (((e) <= (s)) ? 0 : (e) - (s))#endif/* Heuristic used to decide whether it is faster to move from CUR to NEW by backing up or outputting a carriage return and moving forward. CUR and NEW are either both buffer positions or absolute screen positions. */#define CR_FASTER(new, cur) (((new) + 1) < ((cur) - (new)))/* _rl_last_c_pos is an absolute cursor position in multibyte locales and a buffer index in others. This macro is used when deciding whether the current cursor position is in the middle of a prompt string containing invisible characters. XXX - might need to take `modmark' into account. */#define PROMPT_ENDING_INDEX \ ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) ? prompt_physical_chars : prompt_last_invisible+1) /* **************************************************************** *//* *//* Display stuff *//* *//* **************************************************************** *//* This is the stuff that is hard for me. I never seem to write good display routines in C. Let's see how I do this time. *//* (PWP) Well... Good for a simple line updater, but totally ignores the problems of input lines longer than the screen width. update_line and the code that calls it makes a multiple line, automatically wrapping line update. Careful attention needs to be paid to the vertical position variables. *//* Keep two buffers; one which reflects the current contents of the screen, and the other to draw what we think the new contents should be. Then compare the buffers, and make whatever changes to the screen itself that we should. Finally, make the buffer that we just drew into be the one which reflects the current contents of the screen, and place the cursor where it belongs. Commands that want to can fix the display themselves, and then let this function know that the display has been fixed by setting the RL_DISPLAY_FIXED variable. This is good for efficiency. *//* Application-specific redisplay function. */rl_voidfunc_t *rl_redisplay_function = rl_redisplay;/* Global variables declared here. *//* What YOU turn on when you have handled all redisplay yourself. */int rl_display_fixed = 0;int _rl_suppress_redisplay = 0;int _rl_want_redisplay = 0;/* The stuff that gets printed out before the actual text of the line. This is usually pointing to rl_prompt. */char *rl_display_prompt = (char *)NULL;/* Pseudo-global variables declared here. *//* The visible cursor position. If you print some text, adjust this. *//* NOTE: _rl_last_c_pos is used as a buffer index when not in a locale supporting multibyte characters, and an absolute cursor position when in such a locale. This is an artifact of the donated multibyte support. Care must be taken when modifying its value. */int _rl_last_c_pos = 0;int _rl_last_v_pos = 0;static int cpos_adjusted;static int cpos_buffer_position;static int prompt_multibyte_chars;/* Number of lines currently on screen minus 1. */int _rl_vis_botlin = 0;/* Variables used only in this file. *//* The last left edge of text that was displayed. This is used when doing horizontal scrolling. It shifts in thirds of a screenwidth. */static int last_lmargin;/* A buffer for `modeline' messages. */static char msg_buf[128];/* Non-zero forces the redisplay even if we thought it was unnecessary. */static int forced_display;/* Default and initial buffer size. Can grow. */static int line_size = 1024;/* Variables to keep track of the expanded prompt string, which may include invisible characters. */static char *local_prompt, *local_prompt_prefix;static int local_prompt_len;static int prompt_visible_length, prompt_prefix_length;/* The number of invisible characters in the line currently being displayed on the screen. */static int visible_wrap_offset;/* The number of invisible characters in the prompt string. Static so it can be shared between rl_redisplay and update_line */static int wrap_offset;/* The index of the last invisible character in the prompt string. */static int prompt_last_invisible;/* The length (buffer offset) of the first line of the last (possibly multi-line) buffer displayed on the screen. */static int visible_first_line_len;/* Number of invisible characters on the first physical line of the prompt. Only valid when the number of physical characters in the prompt exceeds (or is equal to) _rl_screenwidth. */static int prompt_invis_chars_first_line;static int prompt_last_screen_line;static int prompt_physical_chars;/* set to a non-zero value by rl_redisplay if we are marking modified history lines and the current line is so marked. */static int modmark;/* Variables to save and restore prompt and display information. *//* These are getting numerous enough that it's time to create a struct. */static char *saved_local_prompt;static char *saved_local_prefix;static int saved_last_invisible;static int saved_visible_length;static int saved_prefix_length;static int saved_local_length;static int saved_invis_chars_first_line;static int saved_physical_chars;/* Expand the prompt string S and return the number of visible characters in *LP, if LP is not null. This is currently more-or-less a placeholder for expansion. LIP, if non-null is a place to store the index of the last invisible character in the returned string. NIFLP, if non-zero, is a place to store the number of invisible characters in the first prompt line. The previous are used as byte counts -- indexes into a character buffer. *//* Current implementation: \001 (^A) start non-visible characters \002 (^B) end non-visible characters all characters except \001 and \002 (following a \001) are copied to the returned string; all characters except those between \001 and \002 are assumed to be `visible'. */ static char *expand_prompt (pmt, lp, lip, niflp, vlp) char *pmt; int *lp, *lip, *niflp, *vlp;{ char *r, *ret, *p, *igstart; int l, rl, last, ignoring, ninvis, invfl, invflset, ind, pind, physchars; /* Short-circuit if we can. */ if ((MB_CUR_MAX <= 1 || rl_byte_oriented) && strchr (pmt, RL_PROMPT_START_IGNORE) == 0) { r = savestring (pmt); if (lp) *lp = strlen (r); if (lip) *lip = 0; if (niflp) *niflp = 0; if (vlp) *vlp = lp ? *lp : strlen (r); return r; } l = strlen (pmt); r = ret = (char *)xmalloc (l + 1); invfl = 0; /* invisible chars in first line of prompt */ invflset = 0; /* we only want to set invfl once */ igstart = 0; for (rl = ignoring = last = ninvis = physchars = 0, p = pmt; p && *p; p++) { /* This code strips the invisible character string markers RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE */ if (ignoring == 0 && *p == RL_PROMPT_START_IGNORE) /* XXX - check ignoring? */ { ignoring = 1; igstart = p; continue; } else if (ignoring && *p == RL_PROMPT_END_IGNORE) { ignoring = 0; if (p != (igstart + 1)) last = r - ret - 1; continue; } else {#if defined (HANDLE_MULTIBYTE) if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) { pind = p - pmt; ind = _rl_find_next_mbchar (pmt, pind, 1, MB_FIND_NONZERO); l = ind - pind; while (l--) *r++ = *p++; if (!ignoring) { /* rl ends up being assigned to prompt_visible_length, which is the number of characters in the buffer that contribute to characters on the screen, which might not be the same as the number of physical characters on the screen in the presence of multibyte characters */ rl += ind - pind; physchars += _rl_col_width (pmt, pind, ind, 0); } else ninvis += ind - pind; p--; /* compensate for later increment */ } else#endif { *r++ = *p; if (!ignoring) { rl++; /* visible length byte counter */ physchars++; } else ninvis++; /* invisible chars byte counter */ } if (invflset == 0 && rl >= _rl_screenwidth) { invfl = ninvis; invflset = 1; } } } if (rl < _rl_screenwidth) invfl = ninvis; *r = '\0'; if (lp) *lp = rl; if (lip) *lip = last; if (niflp) *niflp = invfl; if (vlp) *vlp = physchars; return ret;}/* Just strip out RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE from PMT and return the rest of PMT. */char *_rl_strip_prompt (pmt) char *pmt;{ char *ret; ret = expand_prompt (pmt, (int *)NULL, (int *)NULL, (int *)NULL, (int *)NULL); return ret;}/* * Expand the prompt string into the various display components, if * necessary. * * local_prompt = expanded last line of string in rl_display_prompt * (portion after the final newline) * local_prompt_prefix = portion before last newline of rl_display_prompt, * expanded via expand_prompt * prompt_visible_length = number of visible characters in local_prompt * prompt_prefix_length = number of visible characters in local_prompt_prefix * * This function is called once per call to readline(). It may also be * called arbitrarily to expand the primary prompt. * * The return value is the number of visible characters on the last line * of the (possibly multi-line) prompt. */intrl_expand_prompt (prompt) char *prompt;{ char *p, *t; int c; /* Clear out any saved values. */ FREE (local_prompt); FREE (local_prompt_prefix); local_prompt = local_prompt_prefix = (char *)0; local_prompt_len = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -