📄 button.c
字号:
/* $XConsortium: button.c,v 1.66 91/05/31 17:00:03 gildea Exp $ *//* * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. * * All Rights Reserved * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appear in all copies and that * both that copyright notice and this permission notice appear in * supporting documentation, and that the name of Digital Equipment * Corporation not be used in advertising or publicity pertaining to * distribution of the software without specific, written prior permission. * * * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. *//*button.c Handles button events in the terminal emulator. does cut/paste operations, change modes via menu, passes button events through to some applications. J. Gettys.*/#include "ptyx.h" /* Xlib headers included here. */#include <X11/Xatom.h>#include <stdio.h>#include <X11/Xmu/Atoms.h>#include <X11/Xmu/StdSel.h>#include "data.h"#include "error.h"#include "menu.h"extern char *malloc();extern void DoSecureKeyboard();#define KeyState(x) (((x) & (ShiftMask|ControlMask)) + (((x) & Mod1Mask) ? 2 : 0)) /* adds together the bits: shift key -> 1 meta key -> 2 control key -> 4 */ #define TEXTMODES 4#define NBUTS 3#define DIRS 2#define UP 1#define DOWN 0#define SHIFTS 8 /* three keys, so eight combinations */#define Coordinate(r,c) ((r) * (term->screen.max_col+1) + (c))extern char *xterm_name;static void PointToRowCol();static void SelectionReceived();static void TrackDown();static void ComputeSelect();static void EditorButton();static void ExtendExtend();static void ReHiliteText();static void SelectSet();static void StartSelect();static int Length();static char *SaveText();extern XtermWidget term;/* Selection/extension variables *//* Raw char position where the selection started */static int rawRow, rawCol;/* Selected area before CHAR, WORD, LINE selectUnit processing */static int startRRow, startRCol, endRRow, endRCol = 0;/* Selected area after CHAR, WORD, LINE selectUnit processing */static int startSRow, startSCol, endSRow, endSCol = 0;/* Valid rows for selection clipping */static int firstValidRow, lastValidRow;/* Start, end of extension */static int startERow, startECol, endERow, endECol;/* Saved values of raw selection for extend to restore to */static int saveStartRRow, saveStartRCol, saveEndRRow, saveEndRCol;/* Multi-click handling */static int numberOfClicks = 0;static long int lastButtonUpTime = 0;typedef int SelectUnit;#define SELECTCHAR 0#define SELECTWORD 1#define SELECTLINE 2#define NSELECTUNITS 3static SelectUnit selectUnit;/* Send emacs escape code when done selecting or extending? */static int replyToEmacs;Boolean SendMousePosition(w, event)Widget w;XEvent* event;{ register TScreen *screen = &((XtermWidget)w)->screen; if (screen->send_mouse_pos == 0) return False; if (event->type != ButtonPress && event->type != ButtonRelease) return False;#define KeyModifiers \ (event->xbutton.state & (ShiftMask | LockMask | ControlMask | Mod1Mask | \ Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask ))#define ButtonModifiers \ (event->xbutton.state & (ShiftMask | LockMask | ControlMask | Mod1Mask | \ Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask )) switch (screen->send_mouse_pos) { case 1: /* X10 compatibility sequences */ if (KeyModifiers == 0) { if (event->type == ButtonPress) EditorButton(event); return True; } return False; case 2: /* DEC vt200 compatible */ if (KeyModifiers == 0 || KeyModifiers == ControlMask) { EditorButton(event); return True; } return False; case 3: /* DEC vt200 hilite tracking */ if ( event->type == ButtonPress && KeyModifiers == 0 && event->xbutton.button == Button1 ) { TrackDown(event); return True; } if (KeyModifiers == 0 || KeyModifiers == ControlMask) { EditorButton(event); return True; } /* fall through */ default: return False; }#undef KeyModifiers}voidCursorButton(w, event, params, num_params)Widget w;XEvent *event; /* must be XButtonEvent */String *params; /* selections */Cardinal *num_params;{ register TScreen *screen = &term->screen; int pty = screen->respond; char prefix[3]; register int line, col; if (event->type != ButtonPress && event->type != ButtonRelease) return; line = screen->cur_row - (( event->xbutton.y - screen->border ) / FontHeight( screen )); col = screen->cur_col - (event->xbutton.x - screen->border - screen->scrollbar) / FontWidth(screen); if (term->keyboard.flags & CURSOR_APL) strcpy(prefix , "\033O"); else strcpy(prefix , "\033["); if ( line < 0 ) { prefix[2] = 'B'; line = -line; } else prefix[2] = 'A'; while ( --line >= 0 ) v_write(pty, prefix, 3); if ( col < 0 ) { prefix[2] = 'C'; col = -col; } else prefix[2] = 'D'; while ( --col >= 0 ) v_write(pty, prefix, 3);}/*ARGSUSED*/void HandleSelectExtend(w, event, params, num_params)Widget w;XEvent *event; /* must be XMotionEvent */String *params; /* unused */Cardinal *num_params; /* unused */{ register TScreen *screen = &((XtermWidget)w)->screen; int row, col; screen->selection_time = event->xmotion.time; switch (eventMode) { case LEFTEXTENSION : case RIGHTEXTENSION : PointToRowCol (event->xmotion.y, event->xmotion.x, &row, &col); ExtendExtend (row, col); break; case NORMAL : /* will get here if send_mouse_pos != 0 */ break; }}static void EndExtend();static void do_select_end (w, event, params, num_params, use_cursor_loc)Widget w;XEvent *event; /* must be XButtonEvent */String *params; /* selections */Cardinal *num_params;Bool use_cursor_loc;{ ((XtermWidget)w)->screen.selection_time = event->xbutton.time; switch (eventMode) { case NORMAL : (void) SendMousePosition(w, event); break; case LEFTEXTENSION : case RIGHTEXTENSION : EndExtend(w, event, params, *num_params, use_cursor_loc); break; }}void HandleSelectEnd(w, event, params, num_params)Widget w;XEvent *event; /* must be XButtonEvent */String *params; /* selections */Cardinal *num_params;{ do_select_end (w, event, params, num_params, False);}void HandleKeyboardSelectEnd(w, event, params, num_params)Widget w;XEvent *event; /* must be XButtonEvent */String *params; /* selections */Cardinal *num_params;{ do_select_end (w, event, params, num_params, True);}struct _SelectionList { String *params; Cardinal count; Time time;};static void _GetSelection(w, time, params, num_params)Widget w;Time time;String *params; /* selections in precedence order */Cardinal num_params;{ Atom selection; int cutbuffer; XmuInternStrings(XtDisplay(w), params, (Cardinal)1, &selection); switch (selection) { case XA_CUT_BUFFER0: cutbuffer = 0; break; case XA_CUT_BUFFER1: cutbuffer = 1; break; case XA_CUT_BUFFER2: cutbuffer = 2; break; case XA_CUT_BUFFER3: cutbuffer = 3; break; case XA_CUT_BUFFER4: cutbuffer = 4; break; case XA_CUT_BUFFER5: cutbuffer = 5; break; case XA_CUT_BUFFER6: cutbuffer = 6; break; case XA_CUT_BUFFER7: cutbuffer = 7; break; default: cutbuffer = -1; } if (cutbuffer >= 0) { register TScreen *screen = &((XtermWidget)w)->screen; int inbytes; unsigned long nbytes; int fmt8 = 8; Atom type = XA_STRING; char *line = XFetchBuffer(screen->display, &inbytes, cutbuffer); nbytes = (unsigned long) inbytes; if (nbytes > 0) SelectionReceived(w, NULL, &selection, &type, (XtPointer)line, &nbytes, &fmt8); else if (num_params > 1) _GetSelection(w, time, params+1, num_params-1); } else { struct _SelectionList* list; if (--num_params) { list = XtNew(struct _SelectionList); list->params = params + 1; list->count = num_params; /* decremented above */ list->time = time; } else list = NULL; XtGetSelectionValue(w, selection, XA_STRING, SelectionReceived, (XtPointer)list, time); }}/* SelectionReceived: stuff received selection text into pty *//* ARGSUSED */static void SelectionReceived(w, client_data, selection, type, value, length, format)Widget w;XtPointer client_data;Atom *selection, *type;XtPointer value;unsigned long *length;int *format;{ int pty = ((XtermWidget)w)->screen.respond; /* file descriptor of pty */ register char *lag, *cp, *end; char *line = (char*)value; if (*type == 0 /*XT_CONVERT_FAIL*/ || *length == 0 || value == NULL) { /* could not get this selection, so see if there are more to try */ struct _SelectionList* list = (struct _SelectionList*)client_data; if (list != NULL) { _GetSelection(w, list->time, list->params, list->count); XtFree(client_data); } return; } /* Write data to pty a line at a time. */ /* Doing this one line at a time may no longer be necessary because v_write has been re-written. */ end = &line[*length]; lag = line; for (cp = line; cp != end; cp++) { if (*cp != '\n') continue; *cp = '\r'; v_write(pty, lag, cp - lag + 1); lag = cp + 1; } if (lag != end) v_write(pty, lag, end - lag); XtFree(client_data); XtFree(value);}voidHandleInsertSelection(w, event, params, num_params)Widget w;XEvent *event; /* assumed to be XButtonEvent* */String *params; /* selections in precedence order */Cardinal *num_params;{ if (SendMousePosition(w, event)) return; _GetSelection(w, event->xbutton.time, params, *num_params);}static voidSetSelectUnit(buttonDownTime, defaultUnit) unsigned long buttonDownTime; SelectUnit defaultUnit;{/* Do arithmetic as integers, but compare as unsigned solves clock wraparound */ if ((long unsigned)((long int)buttonDownTime - lastButtonUpTime) > term->screen.multiClickTime) { numberOfClicks = 1; selectUnit = defaultUnit; } else { ++numberOfClicks; selectUnit = ((selectUnit + 1) % NSELECTUNITS); }}static void do_select_start (w, event, startrow, startcol)Widget w;XEvent *event; /* must be XButtonEvent* */int startrow, startcol;{ if (SendMousePosition(w, event)) return; SetSelectUnit(event->xbutton.time, SELECTCHAR); replyToEmacs = FALSE; StartSelect(startrow, startcol);}/* ARGSUSED */voidHandleSelectStart(w, event, params, num_params)Widget w;XEvent *event; /* must be XButtonEvent* */String *params; /* unused */Cardinal *num_params; /* unused */{ register TScreen *screen = &((XtermWidget)w)->screen; int startrow, startcol; firstValidRow = 0; lastValidRow = screen->max_row; PointToRowCol(event->xbutton.y, event->xbutton.x, &startrow, &startcol); do_select_start (w, event, startrow, startcol);}/* ARGSUSED */voidHandleKeyboardSelectStart(w, event, params, num_params)Widget w;XEvent *event; /* must be XButtonEvent* */String *params; /* unused */Cardinal *num_params; /* unused */{ register TScreen *screen = &((XtermWidget)w)->screen; do_select_start (w, event, screen->cursor_row, screen->cursor_col);}static voidTrackDown(event) register XButtonEvent *event;{ int startrow, startcol; SetSelectUnit(event->time, SELECTCHAR); if (numberOfClicks > 1 ) { PointToRowCol(event->y, event->x, &startrow, &startcol); replyToEmacs = TRUE; StartSelect(startrow, startcol); } else { waitingForTrackInfo = 1; EditorButton(event); }}#define boundsCheck(x) if (x < 0) \ x = 0; \ else if (x >= screen->max_row) \ x = screen->max_row;TrackMouse(func, startrow, startcol, firstrow, lastrow)int func, startrow, startcol, firstrow, lastrow;{ TScreen *screen = &term->screen; if (!waitingForTrackInfo) { /* Timed out, so ignore */ return; } waitingForTrackInfo = 0; if (func == 0) return; boundsCheck (startrow) boundsCheck (firstrow) boundsCheck (lastrow) firstValidRow = firstrow; lastValidRow = lastrow; replyToEmacs = TRUE; StartSelect(startrow, startcol);}static voidStartSelect(startrow, startcol) int startrow, startcol;{ TScreen *screen = &term->screen; if (screen->cursor_state) HideCursor (); if (numberOfClicks == 1) { /* set start of selection */ rawRow = startrow;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -