📄 x11term.c
字号:
/* X Communication module for terminals which understand the X protocol. Copyright (C) 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. *//* Written by Yakim Martillo, mods and things by Robert Krawitz *//* Redone for X11 by Robert French *//* Thanks to Mark Biggers for all of the Window Manager support *//* * $Source: /mit/emacs/src/RCS/11xterm.c,v $ * $Author: rfrench $ * $Locker: $ * $Header: x11term.c,v 1.12 88/02/29 14:11:07 rfrench Exp $ */#ifndef lintstatic char *rcsid_xterm_c = "$Header: x11term.c,v 1.12 88/02/29 14:11:07 rfrench Exp $";#endif lint/* On 4.3 this loses if it comes after x11term.h. On hp-ux it loses if it comes after config.h. */#include <signal.h>#include <sys/ioctl.h>/* Load sys/types.h if not already loaded. In some systems loading it twice is suicidal. */#ifndef makedev#include <sys/types.h>#endif#include "config.h"#ifdef HAVE_X_WINDOWS/* Get FIONREAD, if it is available. It would be logical to include <sys/ioctl.h> here, but it was moved up above to avoid problems. */#ifdef USG#include <termio.h>#include <fcntl.h>#endif /* USG */#include "lisp.h"#undef NULL/* Allow m- file to inhibit use of interrupt-driven input. */#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/* This may include sys/types.h, and that somehow loses if this is not done before the other system files. However, perhaps the problem has been avoided by loading types.h above. */#include "x11term.h"#ifdef IRIS#include <sys/sysmacros.h> /* for "minor" */#include <sys/time.h>#else#ifdef UNIPLUS#include <sys/time.h>#else /* not IRIS, not UNIPLUS *//* Use socket.h just to control whether to use time.h or sys/time.h. This works like the code in process.c. */#ifdef HAVE_SOCKETS#include <sys/socket.h>#endif#ifdef HAVE_TIMEVAL/* _h_BSDTYPES is checked because on ISC unix, socket.h includes both time.h and sys/time.h, and the latter file is protected from repeated inclusion. */#if defined(USG) && !defined(_h_BSDTYPES)#include <time.h>#else /* _h_BSDTYPES or not USG */#include <sys/time.h>#endif /* _h_BSDTYPES or not USG */#endif /* HAVE_TIMEVAL */#endif /* not UNIPLUS */#endif /* not IRIS */#ifdef BAT68K#include <sys/time.h> /* In addition to time.h. */#endif#ifdef AIX#include <sys/time.h> /* In addition to time.h. */static KeySym XMOD_Alt[] = { XK_Alt_L };static KeySym XMOD_Shift[] = { XK_Shift_L };static KeySym XMOD_ShiftAlt[] = { XK_Alt_L, XK_Shift_L };static KeySym XMOD_CtrlAlt[] = { XK_Control_L, XK_Alt_L };static KeySym XMOD_Ctrl[] = { XK_Control_L };static KeySym XMOD_CtrlShift[] = { XK_Control_L, XK_Shift_L };static KeySym XMOD_ShiftCtrlAlt[] = { XK_Control_L, XK_Alt_L, XK_Shift_L };#endif#include <fcntl.h>#include <stdio.h>#include <ctype.h>#include <errno.h>#ifdef BSD#include <strings.h>#endif#include <sys/stat.h>#include "dispextern.h"#include "termhooks.h"#include "termopts.h"#include "termchar.h"#include "sink11.h"#include "sink11mask.h"#define min(a,b) ((a)<(b) ? (a) : (b))#define max(a,b) ((a)>(b) ? (a) : (b))extern int errno;#define sigunblockx(sig) sigblock (0)#define sigblockx(sig) sigblock (1 << ((sig) - 1))#define METABIT 0200#define MINWIDTH 12 /* In pixels */#define MINHEIGHT 5 /* In pixels */#define MAXHEIGHT 300 /* In lines */int pixelwidth,pixelheight;char *progname;XEvent *XXm_queue[XMOUSEBUFSIZE];int XXm_queue_num, XXm_queue_in, XXm_queue_out;char *XXcurrentfont;XFontStruct *fontinfo;Font XXfid;int XXfontw, XXfonth, XXbase, XXisColor;/* Nonzero means Emacs has explicit keyboard focus. */int x_focus_flag;Colormap XXColorMap;char *default_window;int configure_pending;extern int initialized;extern int screen_width, screen_height;/* Function for init_keyboard to call with no args (if nonzero). */extern void (*keyboard_init_hook) ();extern char *alternate_display;extern int xargc;extern char **xargv;int XXdebug;int XXpid;int WindowMapped;char *XXidentity; /* Resource name of this invocation of Emacs */static char *XXicon_name; /* user-supplied icon info */static int XXicon_usebitmap; /* Use bitmap or not */static char *XXheader; /* user-supplied window header info */static int flexlines; /* last line affected by dellines or * inslines functions */int VisibleX, VisibleY; /* genuine location of cursor on screen * if it is there *//* Last cursor position specified by move_cursor. During an update, this does not display a cursor on the screen; But it controls the position that is output. */static int local_cursor_hpos;static int local_cursor_vpos;static int SavedX, SavedY; /* Where the cursor was before update * started */int CursorExists; /* during updates cursor is turned off */int CursorOutline; /* when the pointer is not in the Emacs * widow the cursor should be drawn in * outline form a la xterm */static int InUpdate; /* many of functions here may be invoked * even if no update in progress; when * no update is in progress the action * can be slightly different */Display *XXdisplay;int XXscreen;Window XXwindow;GC XXgc_norm,XXgc_rev,XXgc_curs,XXgc_temp;XGCValues XXgcv;Cursor EmacsCursor;Pixmap SinkPixmap, SinkMaskPixmap;char *fore_color; /* Variables to store color names */char *back_color;char *brdr_color;char *curs_color;char *mous_color;unsigned long fore; /* Variables to store pixel values */unsigned long back;unsigned long brdr;unsigned long curs;char *desiredwindow;int CurHL; /* Current Highlighting (ala mode line) */int XXborder; /* Window border width */int XXInternalBorder; /* Internal border width */int updated[MAXHEIGHT];static char *temp_font; /* needed because of loading hacks */static char *temp_reverseVideo;static char *temp_borderWidth;static char *temp_internalBorder;static char *temp_useBitmap;struct _xdeftab { char *iname; /* instance name */ char *cname; /* class name (fake it) */ char **varp; /* variable to set */};static struct _xdeftab xDefaultsValueTable[] = { { "reverseVideo", "ReverseVideo", &temp_reverseVideo }, { "borderWidth", "BorderWidth", &temp_borderWidth }, { "internalBorder","BorderWidth", &temp_internalBorder }, { "bitmapIcon", "BitmapIcon", &temp_useBitmap }, { "borderColor", "BorderColor", &brdr_color }, { "background", "Background", &back_color }, { "foreground", "Foreground", &fore_color }, { "pointerColor", "Foreground", &mous_color }, { "cursorColor", "Foreground", &curs_color }, { "font", "Font", &temp_font }, { "geometry", "Geometry", &desiredwindow }, { "title", "Title", &XXheader }, { "iconName", "Title", &XXicon_name }, { NULL, NULL, NULL } };int (*handler)();static void x_init_1 ();char *rindex();/* HLmode -- Changes the GX function for output strings. Could be used to * change font. Check an XText library function call. */HLmode (new) int new;{ extern Lisp_Object inverse_video; CurHL = new;}/* External interface to control of standout mode. Call this when about to modify line at position VPOS and not change whether it is highlighted. */XTreassert_line_highlight (highlight, vpos) int highlight, vpos;{ HLmode (highlight);}/* Call this when about to modify line at position VPOS and change whether it is highlighted. */XTchange_line_highlight (new_highlight, vpos, first_unused_hpos) int new_highlight, vpos, first_unused_hpos;{ HLmode (new_highlight); XTmove_cursor (vpos, 0); x_clear_end_of_line (0);}/* Used for starting or restarting (after suspension) the X window. Puts the * cursor in a known place, update does not begin with this routine but only * with a call to redisplay. */XTset_terminal_modes (){ int stuffpending;#ifdef XDEBUG fprintf (stderr, "XTset_terminal_modes\n");#endif InUpdate = 0; stuffpending = 0; if (!initialized) { CursorExists = 0; CursorOutline = 1; VisibleX = 0; VisibleY = 0; } XTclear_screen ();}/* XTmove_cursor moves the cursor to the correct location and checks whether an * update is in progress in order to toggle it on. */XTmove_cursor (row, col) register int row, col;{ BLOCK_INPUT_DECLARE ();#ifdef XDEBUG fprintf (stderr, "XTmove_cursor (X %d, Y %d)\n",col,row);#endif BLOCK_INPUT (); local_cursor_hpos = col; local_cursor_vpos = row; if (InUpdate) { if (CursorExists) CursorToggle (); UNBLOCK_INPUT (); return; /* Generally, XTmove_cursor will be invoked */ /* when InUpdate with !CursorExists */ /* so that wasteful XFlush is not called */ } if ((row == VisibleY) && (col == VisibleX)) { if (!CursorExists) CursorToggle (); XFlush (XXdisplay); UNBLOCK_INPUT (); return; } if (CursorExists) CursorToggle (); VisibleX = col; VisibleY = row; if (!CursorExists) CursorToggle (); XFlush (XXdisplay); UNBLOCK_INPUT ();}/* Used to get the terminal back to a known state after resets. Usually * used when restarting suspended or waiting emacs */cleanup (){ inverse_video = 0; HLmode (0);}/* Erase current line from current column to column END. Leave cursor at END. */XTclear_end_of_line (end) register int end;{ register int numcols; BLOCK_INPUT_DECLARE ();#ifdef XDEBUG fprintf (stderr, "XTclear_end_of_line (to %d)\n",end);#endif if (local_cursor_vpos < 0 || local_cursor_vpos >= screen_height) return; if (end <= local_cursor_hpos) return; if (end >= screen_width) end = screen_width; numcols = end - local_cursor_hpos; BLOCK_INPUT (); if (local_cursor_vpos == VisibleY && VisibleX >= local_cursor_hpos && VisibleX < end) if (CursorExists) CursorToggle (); if (CurHL) XFillRectangle (XXdisplay, XXwindow, XXgc_norm, local_cursor_hpos*XXfontw+XXInternalBorder, local_cursor_vpos*XXfonth+XXInternalBorder, XXfontw*numcols, XXfonth); else XClearArea (XXdisplay, XXwindow, local_cursor_hpos*XXfontw+XXInternalBorder, local_cursor_vpos*XXfonth+XXInternalBorder, XXfontw*numcols, XXfonth, 0); XTmove_cursor (local_cursor_vpos, end); UNBLOCK_INPUT ();}/* Erase current line from column START to right margin. Leave cursor at START. */x_clear_end_of_line (start) register int start;{ register int numcols; BLOCK_INPUT_DECLARE ();#ifdef XDEBUG fprintf (stderr, "x_clear_end_of_line (start %d)\n", start);#endif if (local_cursor_vpos < 0 || local_cursor_vpos >= screen_height) return; if (start >= screen_width) return; if (start < 0) start = 0; numcols = screen_width - start; BLOCK_INPUT (); if (local_cursor_vpos == VisibleY && VisibleX >= start) if (CursorExists) CursorToggle (); if (CurHL) XFillRectangle (XXdisplay, XXwindow, XXgc_norm, start*XXfontw+XXInternalBorder, local_cursor_vpos*XXfonth+XXInternalBorder, XXfontw*numcols, XXfonth); else XClearArea (XXdisplay, XXwindow, start*XXfontw+XXInternalBorder, local_cursor_vpos*XXfonth+XXInternalBorder, XXfontw*numcols, XXfonth, 0); XTmove_cursor (local_cursor_vpos, start); UNBLOCK_INPUT ();}XTreset_terminal_modes (){#ifdef XDEBUG fprintf (stderr, "XTreset_terminal_modes\n");#endif XTclear_screen ();}XTclear_screen (){ BLOCK_INPUT_DECLARE ();#ifdef XDEBUG fprintf (stderr, "XTclear_screen\n");#endif BLOCK_INPUT (); HLmode (0); CursorExists = 0; local_cursor_hpos = 0; local_cursor_vpos = 0; SavedX = 0; SavedY = 0; VisibleX = 0; VisibleY = 0; XClearWindow(XXdisplay, XXwindow); CursorToggle (); if (!InUpdate) XFlush (XXdisplay); UNBLOCK_INPUT ();}/* used by dumprectangle which is usually invoked upon Expose * events which come from bit blt's or moving an obscuring opaque window */dumpchars (active_screen, numcols, tempX, tempY, tempHL) register struct matrix *active_screen; register int numcols; register int tempX, tempY, tempHL;{ if (numcols <= 0) return; if (numcols-1+tempX > screen_width) numcols = screen_width-tempX+1; if (tempX < 0 || tempX >= screen_width || tempY < 0 || tempY >= screen_height) return; XDrawImageString(XXdisplay, XXwindow, tempHL ? XXgc_rev : XXgc_norm, tempX*XXfontw+XXInternalBorder, tempY*XXfonth+XXInternalBorder+XXbase, &active_screen->contents[tempY][tempX], numcols);}/* When a line has been changed this function is called. Due to various * bits of braindamage on the parts of both X11 and Emacs, the new * version of the line is simply output if this function is invoked while * in UpDate. Sometimes writechars can be invoked when not in update if * text is to be output at the end of the line. In this case the whole * line is not output. Simply the new text at the current cursor * position given by VisibleX,Y. The cursor is moved to the end of the * new text. */updateline (first) int first;{ register int temp_length; BLOCK_INPUT_DECLARE ();#ifdef XDEBUG fprintf(stderr, "updateline\n");#endif XDEBUG BLOCK_INPUT (); if ((local_cursor_vpos < 0) || (local_cursor_vpos >= screen_height) || updated[local_cursor_vpos]) { UNBLOCK_INPUT (); return; } if (!first) updated[local_cursor_vpos] = 1; if (CursorExists) CursorToggle (); if (new_screen->enable[local_cursor_vpos]) temp_length = new_screen->used[local_cursor_vpos]-first; else temp_length = 0; if (temp_length > 0) { XDrawImageString (XXdisplay, XXwindow, CurHL ? XXgc_rev : XXgc_norm, first*XXfontw+XXInternalBorder, local_cursor_vpos*XXfonth+XXInternalBorder+XXbase, &new_screen->contents[local_cursor_vpos][first], temp_length); if (temp_length < screen_width) x_clear_end_of_line (temp_length); XTmove_cursor (local_cursor_vpos, temp_length); } else { x_clear_end_of_line (0); XTmove_cursor (local_cursor_vpos, 0); } UNBLOCK_INPUT ();}writechars (start, end) register char *start, *end;{ BLOCK_INPUT_DECLARE ();#ifdef XDEBUG fprintf(stderr, "writechars (local_cursor_hpos %d temp_len %d InUpd %d)\n", local_cursor_hpos, end-start+1, InUpdate);#endif XDEBUG BLOCK_INPUT (); if ((local_cursor_vpos < 0) || (local_cursor_vpos >= screen_height)) { UNBLOCK_INPUT (); return; } if (CursorExists) CursorToggle (); if (InUpdate) { XDrawImageString (XXdisplay, XXwindow, CurHL ? XXgc_rev : XXgc_norm, local_cursor_hpos*XXfontw+XXInternalBorder, local_cursor_vpos*XXfonth+XXInternalBorder+XXbase, start, (end - start) + 1); XTmove_cursor (local_cursor_vpos, (end - start) + 1); UNBLOCK_INPUT (); return; } if ((VisibleX < 0) || (VisibleX >= screen_width)) { UNBLOCK_INPUT (); return; } if ((VisibleY < 0) || (VisibleY >= screen_height)) { UNBLOCK_INPUT (); return; } if (((end - start) + VisibleX) >= screen_width) end = start + (screen_width - (VisibleX + 1)); if (end >= start) { XDrawImageString (XXdisplay, XXwindow, CurHL ? XXgc_rev : XXgc_norm, (VisibleX * XXfontw+XXInternalBorder), VisibleY * XXfonth+XXInternalBorder+XXbase, start, ((end - start) + 1)); VisibleX = VisibleX + (end - start) + 1; } if (!CursorExists)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -