📄 screen.c
字号:
/*--------------------------------*-C-*--------------------------------------* * File: screen.c *---------------------------------------------------------------------------* * $Id: screen.c,v 1.258 2003/03/23 16:55:50 gcw Exp $ * * Copyright (c) 1997-2001 Geoff Wing <gcw@pobox.com> * * This program 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 2 of the License, or * (at your option) any later version. * * This program 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 this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *--------------------------------------------------------------------------*//* * We handle _all_ screen updates and selections */#include "../config.h" /* NECESSARY */#define INTERN_SCREEN#include "rxvt.h" /* NECESSARY */#include "screen.intpro" /* PROTOS for internal routines */#include <X11/Xmd.h> /* get the typedef for CARD32 *//* ------------------------------------------------------------------------- */#ifdef MULTICHAR_SET#define RESET_CHSTAT(H) \ if ((H)->chstat == WBYTE) \ (H)->chstat = SBYTE, (H)->lost_multi = 1const KNOWN_ENCODINGS known_encodings[] = { { SJIS, rxvt_sjis2jis, "sjis" }, { EUCJ, rxvt_euc2jis, "eucj" }, { GB, rxvt_euc2jis, "gb" }, { BIG5, rxvt_decodedummy, "big5" }, { EUCKR, rxvt_euc2jis, "kr" }, { NOENC, rxvt_decodedummy, "noenc" }, { 0, NULL, NULL }};#else# define RESET_CHSTAT(H)#endif/* ------------------------------------------------------------------------- */#define PROP_SIZE 16384#define TABSIZE 8 /* default tab size *//* ------------------------------------------------------------------------- * * GENERAL SCREEN AND SELECTION UPDATE ROUTINES * * ------------------------------------------------------------------------- */#define ZERO_SCROLLBACK(R) \ if (((R)->Options & Opt_scrollTtyOutput) == Opt_scrollTtyOutput) \ (R)->TermWin.view_start = 0#define CLEAR_SELECTION(R) \ (R)->selection.beg.row = (R)->selection.beg.col \ = (R)->selection.end.row = (R)->selection.end.col = 0#define CLEAR_ALL_SELECTION(R) \ (R)->selection.beg.row = (R)->selection.beg.col \ = (R)->selection.mark.row = (R)->selection.mark.col \ = (R)->selection.end.row = (R)->selection.end.col = 0#define ROW_AND_COL_IS_AFTER(A, B, C, D) \ (((A) > (C)) || (((A) == (C)) && ((B) > (D))))#define ROW_AND_COL_IS_BEFORE(A, B, C, D) \ (((A) < (C)) || (((A) == (C)) && ((B) < (D))))#define ROW_AND_COL_IN_ROW_AFTER(A, B, C, D) \ (((A) == (C)) && ((B) > (D)))#define ROW_AND_COL_IN_ROW_AT_OR_AFTER(A, B, C, D) \ (((A) == (C)) && ((B) >= (D)))#define ROW_AND_COL_IN_ROW_BEFORE(A, B, C, D) \ (((A) == (C)) && ((B) < (D)))#define ROW_AND_COL_IN_ROW_AT_OR_BEFORE(A, B, C, D) \ (((A) == (C)) && ((B) <= (D)))/* these must be row_col_t */#define ROWCOL_IS_AFTER(X, Y) \ ROW_AND_COL_IS_AFTER((X).row, (X).col, (Y).row, (Y).col)#define ROWCOL_IS_BEFORE(X, Y) \ ROW_AND_COL_IS_BEFORE((X).row, (X).col, (Y).row, (Y).col)#define ROWCOL_IN_ROW_AFTER(X, Y) \ ROW_AND_COL_IN_ROW_AFTER((X).row, (X).col, (Y).row, (Y).col)#define ROWCOL_IN_ROW_BEFORE(X, Y) \ ROW_AND_COL_IN_ROW_BEFORE((X).row, (X).col, (Y).row, (Y).col)#define ROWCOL_IN_ROW_AT_OR_AFTER(X, Y) \ ROW_AND_COL_IN_ROW_AT_OR_AFTER((X).row, (X).col, (Y).row, (Y).col)#define ROWCOL_IN_ROW_AT_OR_BEFORE(X, Y) \ ROW_AND_COL_IN_ROW_AT_OR_BEFORE((X).row, (X).col, (Y).row, (Y).col)/* * CLEAR_ROWS : clear <num> rows starting from row <row> * CLEAR_CHARS: clear <num> chars starting from pixel position <x,y> * ERASE_ROWS : set <num> rows starting from row <row> to the foreground colour */#define drawBuffer (r->TermWin.vt)#define CLEAR_ROWS(row, num) \ if (r->TermWin.mapped) \ XClearArea(r->Xdisplay, drawBuffer, r->TermWin.int_bwidth, \ Row2Pixel(row), (unsigned int)r->TermWin.width, \ (unsigned int)Height2Pixel(num), False)#define CLEAR_CHARS(x, y, num) \ if (r->TermWin.mapped) \ XClearArea(r->Xdisplay, drawBuffer, x, y, \ (unsigned int)Width2Pixel(num), \ (unsigned int)Height2Pixel(1), False)#define ERASE_ROWS(row, num) \ XFillRectangle(r->Xdisplay, drawBuffer, r->TermWin.gc, \ r->TermWin.int_bwidth, Row2Pixel(row), \ (unsigned int)r->TermWin.width, \ (unsigned int)Height2Pixel(num))/* ------------------------------------------------------------------------- * * SCREEN `COMMON' ROUTINES * * ------------------------------------------------------------------------- *//* Fill part/all of a line with blanks. *//* INTPROTO */voidrxvt_blank_line(text_t *et, rend_t *er, unsigned int width, rend_t efs){ MEMSET(et, ' ', (size_t)width); efs &= ~RS_baseattrMask; for (; width--;) *er++ = efs;}/* ------------------------------------------------------------------------- *//* Fill a full line with blanks - make sure it is allocated first *//* INTPROTO */voidrxvt_blank_screen_mem(rxvt_t *r, text_t **tp, rend_t **rp, unsigned int row, rend_t efs){ int width = r->TermWin.ncol; rend_t *er;#ifdef DEBUG_STRICT assert((tp[row] && rp[row]) || (tp[row] == NULL && rp[row] == NULL));#endif if (tp[row] == NULL) { tp[row] = rxvt_malloc(sizeof(text_t) * width); rp[row] = rxvt_malloc(sizeof(rend_t) * width); } MEMSET(tp[row], ' ', width); efs &= ~RS_baseattrMask; for (er = rp[row]; width--;) *er++ = efs;}/* ------------------------------------------------------------------------- * * SCREEN INITIALISATION * * ------------------------------------------------------------------------- *//* EXTPROTO */voidrxvt_scr_reset(rxvt_t *r){ unsigned int ncol, nrow, prev_ncol, prev_nrow, total_rows, prev_total_rows; unsigned int p, q; int k; rend_t setrstyle; D_SCREEN((stderr, "rxvt_scr_reset()")); r->TermWin.view_start = 0; RESET_CHSTAT(r->h); r->h->num_scr = 0; prev_ncol = r->h->prev_ncol; prev_nrow = r->h->prev_nrow; if (r->TermWin.ncol == 0) r->TermWin.ncol = 80; if (r->TermWin.nrow == 0) r->TermWin.nrow = 24; ncol = r->TermWin.ncol; nrow = r->TermWin.nrow; if (ncol == prev_ncol && nrow == prev_nrow) return; r->h->want_refresh = 1; total_rows = nrow + r->TermWin.saveLines; prev_total_rows = prev_nrow + r->TermWin.saveLines; r->screen.tscroll = 0; r->screen.bscroll = nrow - 1; if (prev_nrow == 0) {/* * A: first time called so just malloc everything : don't rely on realloc * Note: this is still needed so that all the scrollback lines are NULL */ r->screen.text = rxvt_calloc(total_rows, sizeof(text_t *)); r->buf_text = rxvt_calloc(total_rows, sizeof(text_t *)); r->drawn_text = rxvt_calloc(nrow, sizeof(text_t *)); r->swap.text = rxvt_calloc(nrow, sizeof(text_t *)); r->screen.tlen = rxvt_calloc(total_rows, sizeof(int16_t)); r->swap.tlen = rxvt_calloc(nrow, sizeof(int16_t)); r->screen.rend = rxvt_calloc(total_rows, sizeof(rend_t *)); r->buf_rend = rxvt_calloc(total_rows, sizeof(rend_t *)); r->drawn_rend = rxvt_calloc(nrow, sizeof(rend_t *)); r->swap.rend = rxvt_calloc(nrow, sizeof(rend_t *)); for (p = 0; p < nrow; p++) { q = p + r->TermWin.saveLines; rxvt_blank_screen_mem(r, r->screen.text, r->screen.rend, q, DEFAULT_RSTYLE); rxvt_blank_screen_mem(r, r->swap.text, r->swap.rend, p, DEFAULT_RSTYLE); r->screen.tlen[q] = r->swap.tlen[p] = 0; rxvt_blank_screen_mem(r, r->drawn_text, r->drawn_rend, p, DEFAULT_RSTYLE); } MEMSET(r->h->charsets, 'B', sizeof(r->h->charsets)); r->TermWin.nscrolled = 0; /* no saved lines */ r->h->rstyle = DEFAULT_RSTYLE; r->screen.flags = Screen_DefaultFlags; r->screen.cur.row = r->screen.cur.col = 0; r->screen.charset = 0; r->h->current_screen = PRIMARY; rxvt_scr_cursor(r, SAVE);#if NSCREENS r->swap.flags = Screen_DefaultFlags; r->swap.cur.row = r->swap.cur.col = 0; r->swap.charset = 0; r->h->current_screen = SECONDARY; rxvt_scr_cursor(r, SAVE); r->h->current_screen = PRIMARY;#endif r->selection.text = NULL; r->selection.len = 0; r->selection.op = SELECTION_CLEAR; r->selection.screen = PRIMARY; r->selection.clicks = 0; CLEAR_ALL_SELECTION(r); r->h->rvideo = 0;#ifdef MULTICHAR_SET r->h->multi_byte = 0; r->h->lost_multi = 0; r->h->chstat = SBYTE;#endif } else {/* * B1: add or delete rows as appropriate */ setrstyle = DEFAULT_RSTYLE; if (nrow < prev_nrow) { /* delete rows */ k = min(r->TermWin.nscrolled, prev_nrow - nrow); rxvt_scroll_text(r, 0, (int)prev_nrow - 1, k, 1); for (p = nrow; p < prev_nrow; p++) { q = p + r->TermWin.saveLines; if (r->screen.text[q]) {#ifdef DEBUG_STRICT assert(r->screen.rend[q]);#endif free(r->screen.text[q]); free(r->screen.rend[q]); } if (r->swap.text[p]) {#ifdef DEBUG_STRICT assert(r->swap.rend[p]);#endif free(r->swap.text[p]); free(r->swap.rend[p]); }#ifdef DEBUG_STRICT assert(r->drawn_text[p] && r->drawn_rend[p]);#endif free(r->drawn_text[p]); free(r->drawn_rend[p]); } /* we have fewer rows so fix up cursor position */ MIN_IT(r->screen.cur.row, (int32_t)nrow - 1); MIN_IT(r->swap.cur.row, (int32_t)nrow - 1); rxvt_scr_reset_realloc(r); /* realloc _last_ */ } else if (nrow > prev_nrow) { /* add rows */ rxvt_scr_reset_realloc(r); /* realloc _first_ */ k = min(r->TermWin.nscrolled, nrow - prev_nrow); for (p = prev_total_rows; p < total_rows; p++) { r->screen.tlen[p] = 0; r->screen.text[p] = NULL; r->screen.rend[p] = NULL; } for (p = prev_total_rows; p < total_rows - k; p++) rxvt_blank_screen_mem(r, r->screen.text, r->screen.rend, p, setrstyle); for (p = prev_nrow; p < nrow; p++) { r->swap.tlen[p] = 0; r->swap.text[p] = NULL; r->swap.rend[p] = NULL; r->drawn_text[p] = NULL; r->drawn_rend[p] = NULL; rxvt_blank_screen_mem(r, r->swap.text, r->swap.rend, p, setrstyle); rxvt_blank_screen_mem(r, r->drawn_text, r->drawn_rend, p, setrstyle); } if (k > 0) { rxvt_scroll_text(r, 0, (int)nrow - 1, -k, 1); r->screen.cur.row += k; r->screen.s_cur.row += k; r->TermWin.nscrolled -= k; }#ifdef DEBUG_STRICT assert(r->screen.cur.row < r->TermWin.nrow); assert(r->swap.cur.row < r->TermWin.nrow);#else /* drive with your eyes closed */ MIN_IT(r->screen.cur.row, nrow - 1); MIN_IT(r->swap.cur.row, nrow - 1);#endif }/* B2: resize columns */ if (ncol != prev_ncol) { for (p = 0; p < total_rows; p++) { if (r->screen.text[p]) { r->screen.text[p] = rxvt_realloc(r->screen.text[p], ncol * sizeof(text_t)); r->screen.rend[p] = rxvt_realloc(r->screen.rend[p], ncol * sizeof(rend_t)); MIN_IT(r->screen.tlen[p], (int16_t)ncol); if (ncol > prev_ncol) rxvt_blank_line(&(r->screen.text[p][prev_ncol]), &(r->screen.rend[p][prev_ncol]), ncol - prev_ncol, setrstyle); } } for (p = 0; p < nrow; p++) { r->drawn_text[p] = rxvt_realloc(r->drawn_text[p], ncol * sizeof(text_t)); r->drawn_rend[p] = rxvt_realloc(r->drawn_rend[p], ncol * sizeof(rend_t)); if (r->swap.text[p]) { r->swap.text[p] = rxvt_realloc(r->swap.text[p], ncol * sizeof(text_t)); r->swap.rend[p] = rxvt_realloc(r->swap.rend[p], ncol * sizeof(rend_t)); MIN_IT(r->swap.tlen[p], (int16_t)ncol); if (ncol > prev_ncol) rxvt_blank_line(&(r->swap.text[p][prev_ncol]), &(r->swap.rend[p][prev_ncol]), ncol - prev_ncol, setrstyle); } if (ncol > prev_ncol) rxvt_blank_line(&(r->drawn_text[p][prev_ncol]), &(r->drawn_rend[p][prev_ncol]), ncol - prev_ncol, setrstyle); } MIN_IT(r->screen.cur.col, (int16_t)ncol - 1); MIN_IT(r->swap.cur.col, (int16_t)ncol - 1); } if (r->tabs) free(r->tabs); } r->tabs = rxvt_malloc(ncol * sizeof(char)); for (p = 0; p < ncol; p++) r->tabs[p] = (p % TABSIZE == 0) ? 1 : 0; r->h->prev_nrow = nrow; r->h->prev_ncol = ncol; rxvt_tt_winsize(r->cmd_fd, r->TermWin.ncol, r->TermWin.nrow);}/* INTPROTO */voidrxvt_scr_reset_realloc(rxvt_t *r){ u_int16_t total_rows, nrow; nrow = r->TermWin.nrow; total_rows = nrow + r->TermWin.saveLines;/* *INDENT-OFF* */ r->screen.text = rxvt_realloc(r->screen.text, total_rows * sizeof(text_t *)); r->buf_text = rxvt_realloc(r->buf_text , total_rows * sizeof(text_t *)); r->drawn_text = rxvt_realloc(r->drawn_text , nrow * sizeof(text_t *)); r->swap.text = rxvt_realloc(r->swap.text , nrow * sizeof(text_t *)); r->screen.tlen = rxvt_realloc(r->screen.tlen, total_rows * sizeof(int16_t)); r->swap.tlen = rxvt_realloc(r->swap.tlen , total_rows * sizeof(int16_t)); r->screen.rend = rxvt_realloc(r->screen.rend, total_rows * sizeof(rend_t *)); r->buf_rend = rxvt_realloc(r->buf_rend , total_rows * sizeof(rend_t *)); r->drawn_rend = rxvt_realloc(r->drawn_rend , nrow * sizeof(rend_t *)); r->swap.rend = rxvt_realloc(r->swap.rend , nrow * sizeof(rend_t *));/* *INDENT-ON* */}/* ------------------------------------------------------------------------- *//* * Free everything. That way malloc debugging can find leakage. *//* EXTPROTO */voidrxvt_scr_release(rxvt_t *r){ u_int16_t total_rows; int i; total_rows = r->TermWin.nrow + r->TermWin.saveLines; for (i = 0; i < total_rows; i++) { if (r->screen.text[i]) { /* then so is r->screen.rend[i] */ free(r->screen.text[i]);#ifdef DEBUG_STRICT assert(r->screen.rend[i]);#endif free(r->screen.rend[i]); } } for (i = 0; i < r->TermWin.nrow; i++) { free(r->drawn_text[i]); free(r->drawn_rend[i]); free(r->swap.text[i]); free(r->swap.rend[i]); } free(r->screen.text); free(r->screen.tlen); free(r->screen.rend); free(r->drawn_text); free(r->drawn_rend); free(r->swap.text); free(r->swap.tlen); free(r->swap.rend); free(r->buf_text);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -