📄 screen.c
字号:
/*--------------------------------*-C-*---------------------------------* * File: screen.c *----------------------------------------------------------------------* * * All portions of code are copyright by their respective author/s. * Copyright (c) 1997-2001 Geoff Wing <gcw@pobox.com> * Copyright (C) 2000,2001 Teepanis Chachiyo <teepanis@physics.purdue.edu> * Copyright (c) 2001 Marius Gedminas <marius.gedminas@uosis.mif.vu.lt> * Copyright (c) 2003 David Hull * Copyright (c) 2003 Yamanobe Kiichiro <yamky@cocoa.freemail.ne.jp> * Copyright (c) 2003 Mamoru Komachi <usata@usata.org> * Copyright (c) 2005 William P. Y. Hadisoeseno <williampoetra@users.sourceforge.net> * Copyright (c) 2004-2006 Jingmin Zhou <jimmyzhou@users.sourceforge.net> * Copyright (c) 2005-2006 Gautam Iyer <gi1242@users.sourceforge.net> * Copyright (c) 2007 Jehan Hysseo <hysseo@users.sourceforge.net> * * 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. *----------------------------------------------------------------------*/#include "../config.h"#define INTERN_SCREEN#include "rxvt.h"#ifdef XFT_SUPPORT# include <xftacs.h>#endif#ifdef HAVE_WORDEXP_H# include <wordexp.h>#endif/* ------------------------------------------------------------------------- */#ifdef MULTICHAR_SET#define RESET_CHSTAT(R, P) \ if (PVTS((R),(P))->chstat == WBYTE) \ PVTS((R),(P))->chstat = SBYTE, PVTS((R),(P))->lost_multi = 1#else# define RESET_CHSTAT(R, P)#endif/* ------------------------------------------------------------------------- */#define PROP_SIZE 16384/* ------------------------------------------------------------------------- * * GENERAL SCREEN AND SELECTION UPDATE ROUTINES * * ------------------------------------------------------------------------- *//*** If inhibit scrolling on tty output, we should keep the view_start.** Otherwise, we set it to zero.*/#define ZERO_SCROLLBACK(R, P) \ if (NOTSET_OPTION(R, Opt_scrollTtyOutputInhibit)) \ (R)->vts[(P)]->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 RC_AFTER(X, Y) \ ROW_AND_COL_IS_AFTER((X).row, (X).col, (Y).row, (Y).col)#define RC_BEFORE(X, Y) \ ROW_AND_COL_IS_BEFORE((X).row, (X).col, (Y).row, (Y).col)#define RC_ROW_AFTER(X, Y) \ ROW_AND_COL_IN_ROW_AFTER((X).row, (X).col, (Y).row, (Y).col)#define RC_ROW_BEFORE(X, Y) \ ROW_AND_COL_IN_ROW_BEFORE((X).row, (X).col, (Y).row, (Y).col)#define RC_ROW_ATAFTER(X, Y) \ ROW_AND_COL_IN_ROW_AT_OR_AFTER((X).row, (X).col, (Y).row, (Y).col)#define RC_ROW_ATBEFORE(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 (PVTS(r, page)->vt)#define CLEAR_ROWS(row, num) \ if (r->TermWin.mapped) \ rxvt_clear_area (r, page, \ r->TermWin.int_bwidth, Row2Pixel(row), \ VT_WIDTH(r), (unsigned int)Height2Pixel(num))/* * If already_cleared, then we got here during a clipped refresh. In this case, * areas we draw into are already cleared by the server. We don't need to clear * it ourself. (Doing so will cause problems under transparency: E.g. We want to * clear an entire character cell, but an expose event was generated for only * half the character cell. By our wonderful clippings, we redraw only half the * char cell. However requests to this function will clear an ENTIRE char cell, * causing problems. * * If garbage is found due to clipped refreshes, then we should explicitly call * XClearArea before generating a clipped refresh. */#define CLEAR_CHARS(r, page, already_cleared, x, y, num) \ if( !already_cleared ) \ rxvt_clear_area( (r), (page), (x), (y), \ (unsigned) Width2Pixel((num)), \ (unsigned) Height2Pixel(1));#define ERASE_ROWS(row, num) \ rxvt_fill_rectangle (r, page, \ r->TermWin.int_bwidth, Row2Pixel(row), \ VT_WIDTH(r), (unsigned int)Height2Pixel(num))#ifdef DONT_SELECT_TRAILING_SPACES# define STRIP_TRAILING_SPACE(str, fence) \ while (str > fence && ' ' == str[-1]) \ str --;#endif/* Here are some simple macros for convenience */#undef CURROW#undef CURCOL#undef SVLINES#undef VSTART#define CURROW (PSCR(r, page).cur.row)#define CURCOL (PSCR(r, page).cur.col)#define SVLINES (PVTS(r, page)->saveLines)#define VSTART (PVTS(r, page)->view_start)/*--------------------------------------------------------------------* * BEGIN `INTERNAL' ROUTINE PROTOTYPES * *--------------------------------------------------------------------*/void rxvt_blank_line (text_t*, rend_t*, unsigned int, rend_t);void rxvt_blank_screen_mem (rxvt_t*, int, text_t**, rend_t **, unsigned int, rend_t);void rxvt_scr_reset_realloc (rxvt_t*, int);void rxvt_scr_delete_row (rxvt_t*, int);void rxvt_scr_add_row (rxvt_t*, int, unsigned int, unsigned int);void static inline rxvt_clear_area (rxvt_t*, int page, int x, int y, unsigned int w, unsigned int h);void static inline rxvt_fill_rectangle (rxvt_t*, int page, int x, int y, unsigned int w, unsigned int h);voidrxvt_scr_draw_string (rxvt_t* r, int page, int x, int y, char* str, int len, int drawfunc, uint16_t fore, uint16_t back, __attribute__((unused)) rend_t rend, Region refreshRegion);void rxvt_scr_adjust_col (rxvt_t*, int, unsigned int);void rxvt_set_font_style (rxvt_t*, int);int rxvt_scr_change_view (rxvt_t*, int, uint16_t);void rxvt_scr_reverse_selection (rxvt_t*, int);void rxvt_paste_str (rxvt_t*, int, const unsigned char*, unsigned int);int rxvt_selection_request_other (rxvt_t*, int, Atom, int);void rxvt_selection_start_colrow (rxvt_t*, int, int, int);void rxvt_selection_delimit_word (rxvt_t*, int, enum page_dirn, const row_col_t*, row_col_t*);#ifdef MULTICHAR_SETvoid rxvt_selection_adjust_kanji (rxvt_t*, int);#endifvoid rxvt_selection_extend_colrow (rxvt_t*, int, int32_t, int32_t, int, int, int);#ifndef NO_FRILLSvoid rxvt_selection_trim (rxvt_t*, int);#endif#ifdef TEXT_SHADOW# ifdef XFT_SUPPORTvoid rxvt_set_clipping (rxvt_t*, XftDraw*, GC, Region, int, int, unsigned, unsigned, int*, int*);void rxvt_free_clipping (rxvt_t*, XftDraw*, GC, Region);# elsevoid rxvt_set_clipping (rxvt_t*, __attribute__((unused)) void*, GC, Region, int, int, unsigned, unsigned, int*, int*);void rxvt_free_clipping (rxvt_t*, __attribute__((unused)) void*, GC, Region);# endif#endif#ifdef XFT_SUPPORT#endif /* XFT_SUPPORT *//*--------------------------------------------------------------------* * END `INTERNAL' ROUTINE PROTOTYPES * *--------------------------------------------------------------------*/ /* ------------------------------------------------------------------------- * * 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, int page, text_t **tp, rend_t **rp, unsigned int row, rend_t efs){ int width = r->TermWin.ncol; rend_t *er; assert ((tp[row] && rp[row]) || (tp[row] == NULL && rp[row] == NULL)); /* possible integer overflow? */ assert (width > 0); assert (sizeof (text_t) * width > 0); assert (sizeof (rend_t) * width > 0); 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_init_screen (rxvt_t* r){ int p; int ncol = r->TermWin.ncol; /* first time, we don't have r->tabstop yet */ rxvt_dbgmsg ((DBG_VERBOSE, DBG_SCREEN, "allocate r->tabstop as %d\n", ncol)); assert (ncol > 0); /* possible integer overflow? */ r->tabstop = rxvt_malloc(ncol * sizeof(char)); for (p = 0; p < ncol; p++) r->tabstop[p] = (p % TABSTOP_SIZE == 0) ? 1 : 0;}voidrxvt_scr_alloc (rxvt_t* r, int page){ unsigned int ncol, nrow, total_rows; unsigned int p, q; rxvt_dbgmsg ((DBG_VERBOSE, DBG_SCREEN, "rxvt_scr_alloc %d ()\n", page)); ncol = r->TermWin.ncol; nrow = r->TermWin.nrow; total_rows = nrow + SVLINES; /* ** 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 */ PVTS(r, page)->buf_text = rxvt_calloc(total_rows, sizeof(text_t*)); PVTS(r, page)->buf_rend = rxvt_calloc(total_rows, sizeof(rend_t*)); PVTS(r, page)->drawn_text = rxvt_calloc(nrow, sizeof(text_t*)); PVTS(r, page)->drawn_rend = rxvt_calloc(nrow, sizeof(rend_t*)); PSCR(r, page).text = rxvt_calloc(total_rows, sizeof(text_t*)); PSCR(r, page).tlen = rxvt_calloc(total_rows, sizeof(int16_t)); PSCR(r, page).rend = rxvt_calloc(total_rows, sizeof(rend_t*));#if NSCREENS PVTS(r, page)->swap.text = rxvt_calloc(nrow, sizeof(text_t*)); PVTS(r, page)->swap.tlen = rxvt_calloc(nrow, sizeof(int16_t)); PVTS(r, page)->swap.rend = rxvt_calloc(nrow, sizeof(rend_t*));#endif for (p = 0; p < nrow; p++) { q = p + SVLINES; rxvt_blank_screen_mem (r, page, PSCR(r, page).text, PSCR(r, page).rend, q, DEFAULT_RSTYLE); PSCR(r, page).tlen[q] = 0;#if NSCREENS rxvt_blank_screen_mem (r, page, PVTS(r, page)->swap.text, PVTS(r, page)->swap.rend, p, DEFAULT_RSTYLE); PVTS(r, page)->swap.tlen[p] = 0;#endif rxvt_blank_screen_mem (r, page, PVTS(r, page)->drawn_text, PVTS(r, page)->drawn_rend, p, DEFAULT_RSTYLE); } PVTS(r, page)->nscrolled = 0; /* no saved lines */ PSCR(r, page).flags = Screen_DefaultFlags; PSCR(r, page).cur.row = 0; PSCR(r, page).cur.col = 0; PSCR(r, page).charset = 0; PVTS(r, page)->current_screen = PRIMARY; rxvt_scr_cursor(r, page, SAVE);#if NSCREENS PVTS(r, page)->swap.flags = Screen_DefaultFlags; PVTS(r, page)->swap.cur.row = 0; PVTS(r, page)->swap.cur.col = 0; PVTS(r, page)->swap.charset = 0; PVTS(r, page)->current_screen = SECONDARY; rxvt_scr_cursor(r, page, SAVE); PVTS(r, page)->current_screen = PRIMARY;#endif PVTS(r, page)->rstyle = DEFAULT_RSTYLE; PVTS(r, page)->rvideo = 0; MEMSET(&(PVTS(r, page)->charsets), 'B', sizeof(PVTS(r, page)->charsets));#ifdef MULTICHAR_SET PVTS(r, page)->multi_byte = 0; PVTS(r, page)->lost_multi = 0; PVTS(r, page)->chstat = SBYTE;#endif /* Now set screen initialization flag */ PVTS(r, page)->init_screen = 1;}/* INTPROTO */voidrxvt_scr_reset_realloc(rxvt_t* r, int page){ unsigned int total_rows, nrow; rxvt_dbgmsg ((DBG_VERBOSE, DBG_SCREEN, "rxvt_scr_reset_realloc %d ()\n", page)); nrow = r->TermWin.nrow; total_rows = nrow + SVLINES; PSCR(r, page).text = rxvt_realloc ( PSCR(r, page).text, total_rows * sizeof(text_t *)); PSCR(r, page).tlen = rxvt_realloc ( PSCR(r, page).tlen, total_rows * sizeof(int16_t)); PSCR(r, page).rend = rxvt_realloc ( PSCR(r, page).rend, total_rows * sizeof(rend_t *));#if NSCREENS PVTS(r, page)->swap.text = rxvt_realloc ( PVTS(r, page)->swap.text, nrow * sizeof(text_t *)); PVTS(r, page)->swap.tlen = rxvt_realloc ( PVTS(r, page)->swap.tlen , total_rows * sizeof(int16_t)); PVTS(r, page)->swap.rend = rxvt_realloc ( PVTS(r, page)->swap.rend, nrow * sizeof(rend_t *));#endif PVTS(r, page)->buf_text = rxvt_realloc ( PVTS(r, page)->buf_text, total_rows * sizeof(text_t *)); PVTS(r, page)->buf_rend = rxvt_realloc ( PVTS(r, page)->buf_rend, total_rows * sizeof(rend_t *)); PVTS(r, page)->drawn_text = rxvt_realloc ( PVTS(r, page)->drawn_text, nrow * sizeof(text_t *)); PVTS(r, page)->drawn_rend = rxvt_realloc ( PVTS(r, page)->drawn_rend, nrow * sizeof(rend_t *));}/* INTPROTO */voidrxvt_scr_delete_row (rxvt_t* r, int page){ unsigned int nrow, prev_nrow; unsigned int p, q; register int i; rxvt_dbgmsg ((DBG_VERBOSE, DBG_SCREEN, "rxvt_scr_delete_row %d ()\n", page)); nrow = r->TermWin.nrow; prev_nrow = PVTS(r, page)->prev_nrow; /* delete rows */ i = min(PVTS(r, page)->nscrolled, prev_nrow - nrow); rxvt_scroll_text(r, page, 0, (int)prev_nrow - 1, i, 1); for (p = nrow; p < prev_nrow; p++) { q = p + SVLINES; if (PSCR(r, page).text[q]) { assert(PSCR(r, page).rend[q]); rxvt_free(PSCR(r, page).text[q]); PSCR(r, page).text[q] = NULL; rxvt_free(PSCR(r, page).rend[q]); PSCR(r, page).rend[q] = NULL; }#if NSCREENS if (PVTS(r, page)->swap.text[p]) { assert(PVTS(r, page)->swap.rend[p]); rxvt_free(PVTS(r, page)->swap.text[p]); PVTS(r, page)->swap.text[p] = NULL; rxvt_free(PVTS(r, page)->swap.rend[p]); PVTS(r, page)->swap.rend[p] = NULL; }#endif assert (PVTS(r, page)->drawn_text[p]); assert (PVTS(r, page)->drawn_rend[p]); rxvt_free(PVTS(r, page)->drawn_text[p]); PVTS(r, page)->drawn_text[p] = NULL; rxvt_free(PVTS(r, page)->drawn_rend[p]); PVTS(r, page)->drawn_rend[p] = NULL; } /* we have fewer rows so fix up cursor position */ MIN_IT(PSCR(r, page).cur.row, (int32_t)nrow - 1);#if NSCREENS MIN_IT(PVTS(r, page)->swap.cur.row, (int32_t)nrow - 1);#endif rxvt_scr_reset_realloc (r, page); /* realloc _last_ */}/* INTPROTO */voidrxvt_scr_add_row (rxvt_t* r, int page, unsigned int total_rows, unsigned int prev_total_rows){ unsigned int nrow, prev_nrow; unsigned int p; register int i; rxvt_dbgmsg ((DBG_DEBUG, DBG_SCREEN, "%s( page=%d, total_rows=%u, prev_total_rows=%u )\n", __func__, page, total_rows, prev_total_rows )); nrow = r->TermWin.nrow; prev_nrow = PVTS(r, page)->prev_nrow;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -