📄 dispnew.c.dist
字号:
/* Newly written part of redisplay code. Copyright (C) 1985, 1986, 1987, 1988, 1990 Free Software Foundation, Inc.This file is part of GNU Emacs.GNU Emacs is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 1, or (at your option)any later version.GNU Emacs is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU Emacs; see the file COPYING. If not, write tothe Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */#include <signal.h>#include "config.h"#include <stdio.h>#ifdef HAVE_TIMEVAL#ifdef HPUX#include <time.h>#else#include <sys/time.h>#endif#endif#ifdef HAVE_TERMIO#include <termio.h>#ifdef TCOUTQ#undef TIOCOUTQ#define TIOCOUTQ TCOUTQ#include <fcntl.h>#endif /* TCOUTQ defined */#else#ifndef VMS#include <sys/ioctl.h>#endif /* not VMS */#endif /* not HAVE_TERMIO *//* Allow m- file to inhibit use of FIONREAD. */#ifdef BROKEN_FIONREAD#undef FIONREAD#endif/* We are unable to use interrupts if FIONREAD is not available, so flush SIGIO so we won't try. */#ifndef FIONREAD#ifdef SIGIO#undef SIGIO#endif#endif#undef NULL#include "termchar.h"#include "termopts.h"#include "cm.h"#include "dispextern.h"#include "lisp.h"#include "buffer.h"#include "window.h"#include "commands.h"#define max(a, b) ((a) > (b) ? (a) : (b))#define min(a, b) ((a) < (b) ? (a) : (b))#ifndef PENDING_OUTPUT_COUNT/* Get number of chars of output now in the buffer of a stdio stream. This ought to be built in in stdio, but it isn't. Some s- files override this because their stdio internals differ. */#ifdef __GNU_LIBRARY__#define PENDING_OUTPUT_COUNT(FILE) ((FILE)->__bp - (FILE)->__buf)#else#define PENDING_OUTPUT_COUNT(FILE) ((FILE)->_ptr - (FILE)->_base)#endif#endif /* No PENDING_OUTPUT_COUNT *//* Nonzero means do not assume anything about current contents of actual terminal screen */int screen_garbaged;/* Desired terminal cursor position (to show position of point), origin zero */int cursor_hpos, cursor_vpos;/* Nonzero means last display completed and cursor is really at cursor_hpos, cursor_vpos. Zero means it was preempted. */int display_completed;/* Lisp variable visible-bell; enables use of screen-flash instead of audible bell. */int visible_bell;/* Invert the color of the whole screen, at a low level. */int inverse_video;/* Line speed of the terminal. */int baud_rate;/* nil or a symbol naming the window system under which emacs is running ('x is the only current possibility). */Lisp_Object Vwindow_system;/* Version number of window system, or nil if no window system. */Lisp_Object Vwindow_system_version;/* Nonzero means reading single-character input with prompt so put cursor on minibuffer after the prompt. */int cursor_in_echo_area;/* Description of actual screen contents. */ struct matrix *current_screen;/* Description of desired screen contents. */struct matrix *new_screen;/* Buffer sometimes used to hold partial screen contents. */struct matrix *temp_screen;/* Stdio stream being used for copy of all terminal output. */FILE *termscript;/* Structure for info on cursor positioning */struct cm Wcm;int in_display; /* 1 if in redisplay: can't handle SIGWINCH now. */int delayed_size_change; /* 1 means SIGWINCH happened when not safe. */int delayed_screen_height; /* Remembered new screen height. */int delayed_screen_width; /* Remembered new screen width. *//* This buffer records the history of display preemption. */struct preempt{ /* Number of keyboard characters read so far at preempt. */ int keyboard_char_count; /* Vertical position at which preemption occurred. */ int vpos;};#define N_PREEMPTIONS 50/* Circular buffer recording recent display preemptions. */struct preempt preemptions[N_PREEMPTIONS];/* Index of next element in preemptions. */int preemption_index;/* Set these variables in the debugger to force a display preemption. */int debug_preemption_vpos = -1;int debug_preemption_char_count = -1;extern int num_input_chars;/* Free and reallocate current_screen and new_screen. */struct matrix *make_screen_structure ();remake_screen_structures (){ if (current_screen) free_screen_structure (current_screen); if (new_screen) free_screen_structure (new_screen); if (temp_screen) free_screen_structure (temp_screen); current_screen = make_screen_structure (0); new_screen = make_screen_structure (0); temp_screen = make_screen_structure (1); if (message_buf) message_buf = (char *) xrealloc (message_buf, screen_width + 1); else message_buf = (char *) xmalloc (screen_width + 1);}struct matrix *make_screen_structure (empty) int empty;{ int i; struct matrix *new = (struct matrix *) xmalloc (sizeof (struct matrix)); new->height = screen_height; new->width = screen_width; new->highlight = (char *) xmalloc (screen_height); new->enable = (char *) xmalloc (screen_height); new->contents = (unsigned char **) xmalloc (screen_height * sizeof (char *)); new->used = (int *) xmalloc (screen_height * sizeof (int)); if (empty) { /* Make the buffer used by decode_mode_spec. */ new->total_contents = (unsigned char *) xmalloc (screen_width + 2); bzero (new->contents, screen_height * sizeof (char *)); } else { /* Add 2 to leave extra bytes at beginning and end of each line. */ new->total_contents = (unsigned char *) xmalloc (screen_height * (screen_width + 2)); bzero (new->total_contents, screen_height * (screen_width + 2)); for (i = 0; i < screen_height; i++) new->contents[i] = new->total_contents + i * (screen_width + 2) + 1; } bzero (new->enable, screen_height); return new;}free_screen_structure (matrix) struct matrix *matrix;{ if (matrix->total_contents) free (matrix->total_contents); free (matrix->contents); free (matrix->highlight); free (matrix->enable); free (matrix->used); free (matrix);}/* Return the hash code of contents of line VPOS of screen-matrix M. */intline_hash_code (m, vpos) struct matrix *m; int vpos;{ register unsigned char *body; register int h = 0; /* Give all lighlighted lines the same hash code so as to encourage scrolling to leave them in place. */ if (m->highlight[vpos]) return -1; body = m->contents[vpos]; if (must_write_spaces) { while (1) { int c = *body++; if (c == 0) break; h = (((h << 4) + (h >> 24)) & 0x0fffffff) + c - ' '; } } else { while (1) { int c = *body++; if (c == 0) break; h = (((h << 4) + (h >> 24)) & 0x0fffffff) + c; } } if (h) return h; return 1;}/* Return number of characters in line in M at vpos VPOS, except don't count leading and trailing spaces unless the terminal requires those to be explicitly output. */intline_draw_cost (m, vpos) struct matrix *m; int vpos;{ register unsigned char *body; register int i; if (must_write_spaces) return m->used[vpos]; body = m->contents[vpos]; for (i = m->used[vpos]; i > 0 && body[i - 2] == ' '; i--); i -= count_blanks (body); return max (i, 0);}/* The functions on this page are the interface from xdisp.c to redisplay. The only other interface into redisplay is through setting cursor_hpos and cursor_vpos (in xdisp.c) and setting screen_garbaged. *//* cancel_line eliminates any request to display a line at position `vpos' */cancel_line (vpos) int vpos;{ new_screen->enable[vpos] = 0;}clear_screen_records (){ int i; bzero (current_screen->enable, screen_height);}/* Get ready to display on line `vpos' and set it up for outputting starting at `hpos' within it. Return the text string where that line is stored. */unsigned char *get_display_line (vpos, hpos) int vpos; register int hpos;{ if (new_screen->enable[vpos] && new_screen->used[vpos] > hpos) abort (); if (! new_screen->enable[vpos]) { new_screen->used[vpos] = 0; new_screen->highlight[vpos] = 0; new_screen->enable[vpos] = 1; } if (hpos > new_screen->used[vpos]) { unsigned char *p = new_screen->contents[vpos] + new_screen->used[vpos]; unsigned char *end = new_screen->contents[vpos] + hpos; new_screen->used[vpos] = hpos; while (p != end) *p++ = ' '; } return new_screen->contents[vpos];}/* Scroll lines from vpos `from' up to but not including vpos `end' down by `amount' lines (`amount' may be negative). Returns nonzero if done, zero if terminal cannot scroll them. */intscroll_screen_lines (from, end, amount) int from, end, amount;{ register int i; if (!line_ins_del_ok) return 0; if (amount == 0) return 1; if (amount > 0) { set_terminal_window (end + amount); if (!scroll_region_ok) ins_del_lines (end, -amount); ins_del_lines (from, amount); set_terminal_window (0); rotate_vector (current_screen->contents + from, sizeof (char *) * (end + amount - from), amount * sizeof (char *)); safe_bcopy (current_screen->used + from, current_screen->used + from + amount, (end - from) * sizeof current_screen->used[0]); safe_bcopy (current_screen->highlight + from, current_screen->highlight + from + amount, (end - from) * sizeof current_screen->highlight[0]); safe_bcopy (current_screen->enable + from, current_screen->enable + from + amount, (end - from) * sizeof current_screen->enable[0]); /* Mark the lines made empty by scrolling as enabled, empty and normal video. */ bzero (current_screen->used + from, amount * sizeof current_screen->used[0]); bzero (current_screen->highlight + from, amount * sizeof current_screen->highlight[0]); for (i = from; i < from + amount; i++) { current_screen->contents[i][0] = '\0'; current_screen->enable[i] = 1; } } if (amount < 0) { set_terminal_window (end); ins_del_lines (from + amount, amount); if (!scroll_region_ok) ins_del_lines (end + amount, -amount); set_terminal_window (0); rotate_vector (current_screen->contents + from + amount, sizeof (char *) * (end - from - amount), (end - from) * sizeof (char *)); safe_bcopy (current_screen->used + from, current_screen->used + from + amount, (end - from) * sizeof current_screen->used[0]); safe_bcopy (current_screen->highlight + from, current_screen->highlight + from + amount, (end - from) * sizeof current_screen->highlight[0]); safe_bcopy (current_screen->enable + from, current_screen->enable + from + amount, (end - from) * sizeof current_screen->enable[0]); /* Mark the lines made empty by scrolling as enabled, empty and normal video. */ bzero (current_screen->used + end + amount, - amount * sizeof current_screen->used[0]); bzero (current_screen->highlight + end + amount, - amount * sizeof current_screen->highlight[0]); for (i = end + amount; i < end; i++) { current_screen->contents[i][0] = '\0'; current_screen->enable[i] = 1; } } return 1;}/* Rotate a vector of SIZE bytes, by DISTANCE bytes. DISTANCE may be negative. */rotate_vector (vector, size, distance) char *vector; int size; int distance;{ char *temp = (char *) alloca (size); if (distance < 0) distance += size; bcopy (vector, temp + distance, size - distance); bcopy (vector + size - distance, temp, distance); bcopy (temp, vector, size);}/* Like bcopy except never gets confused by overlap. */safe_bcopy (from, to, size) char *from, *to; int size;{ register char *endf; register char *endt; if (size == 0) return; if (from > to) { /* If destination is lower in memory, we can go from the beginning. */ endf = from + size; while (from != endf) *to++ = *from++; return; } /* If destination is higher in memory, we can go backwards from the end. */ endf = from + size; endt = to + size; do *--endt = *--endf; while (endf != from);}/* After updating a window w that isn't the full screen wide, copy all the columns that w does not occupy from current_screen to new_screen, so that update_screen will not change those columns. */preserve_other_columns (w) struct window *w;{ register int vpos; int start = XFASTINT (w->left); int end = XFASTINT (w->left) + XFASTINT (w->width); int bot = XFASTINT (w->top) + XFASTINT (w->height); for (vpos = XFASTINT (w->top); vpos < bot; vpos++) { if (current_screen->enable[vpos] && new_screen->enable[vpos]) { if (start > 0) { int len; bcopy (current_screen->contents[vpos], new_screen->contents[vpos], start); len = min (start, current_screen->used[vpos]); if (new_screen->used[vpos] < len) new_screen->used[vpos] = len; } if (current_screen->used[vpos] > end && new_screen->used[vpos] < current_screen->used[vpos]) { while (new_screen->used[vpos] < end) new_screen->contents[vpos][new_screen->used[vpos]++] = ' '; bcopy (current_screen->contents[vpos] + end, new_screen->contents[vpos] + end,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -