diff options
Diffstat (limited to 'nx-X11/programs/xterm/button.c')
-rw-r--r-- | nx-X11/programs/xterm/button.c | 3284 |
1 files changed, 0 insertions, 3284 deletions
diff --git a/nx-X11/programs/xterm/button.c b/nx-X11/programs/xterm/button.c deleted file mode 100644 index d8d0b32b3..000000000 --- a/nx-X11/programs/xterm/button.c +++ /dev/null @@ -1,3284 +0,0 @@ -/* $XTermId: button.c,v 1.197 2005/11/03 13:17:27 tom Exp $ */ - -/* $Xorg: button.c,v 1.3 2000/08/17 19:55:08 cpqbld Exp $ */ -/* - * Copyright 1999-2004,2005 by Thomas E. Dickey - * - * All Rights Reserved - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the name(s) of the above copyright - * holders shall not be used in advertising or otherwise to promote the - * sale, use or other dealings in this Software without prior written - * authorization. - * - * - * 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. - */ -/* $XFree86: xc/programs/xterm/button.c,v 3.82 2005/11/03 13:17:27 dickey Exp $ */ - -/* -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 <xterm.h> - -#include <stdio.h> - -#include <X11/Xatom.h> -#include <X11/Xmu/Atoms.h> -#include <X11/Xmu/StdSel.h> - -#include <xutf8.h> - -#include <data.h> -#include <error.h> -#include <menu.h> -#include <xcharmouse.h> -#include <charclass.h> - -#if OPT_WIDE_CHARS -#include <wcwidth.h> -#else -#define CharacterClass(value) \ - charClass[value & ((sizeof(charClass)/sizeof(charClass[0]))-1)] -#endif - -#define XTERM_CELL(row,col) getXtermCell(screen, row + screen->topline, col) -#define XTERM_CELL_C1(row,col) getXtermCellComb1(screen, row + screen->topline, col) -#define XTERM_CELL_C2(row,col) getXtermCellComb2(screen, row + screen->topline, col) - - /* - * We reserve shift modifier for cut/paste operations. In principle we - * can pass through control and meta modifiers, but in practice, the - * popup menu uses control, and the window manager is likely to use meta, - * so those events are not delivered to SendMousePosition. - */ -#define OurModifiers (ShiftMask | ControlMask | Mod1Mask) -#define AllModifiers (ShiftMask | LockMask | ControlMask | Mod1Mask | \ - Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask) - -#define KeyModifiers (event->xbutton.state & OurModifiers) - -#define KeyState(x) (((x) & (ShiftMask|ControlMask)) + (((x) & Mod1Mask) ? 2 : 0)) - /* adds together the bits: - shift key -> 1 - meta key -> 2 - control key -> 4 */ - -#define Coordinate(r,c) ((r) * MaxCols(&(term->screen)) + (c)) - -#if OPT_DEC_LOCATOR -static ANSI reply; -#endif - -/* 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; - -/* Saved value of WORD selection for LINE processing to restore to */ -static int saveStartWRow, saveStartWCol; - -/* Multi-click handling */ -static int numberOfClicks = 0; -static Time lastButtonUpTime = 0; - -#if OPT_READLINE -static Time lastButtonDownTime = 0; -static int ExtendingSelection = 0; -static Time lastButton3UpTime = 0; -static Time lastButton3DoubleDownTime = 0; -static int lastButton3row, lastButton3col; /* At the release time */ -#endif /* OPT_READLINE */ - -typedef int SelectUnit; - -#define SELECTCHAR 0 -#define SELECTWORD 1 -#define SELECTLINE 2 -#define NSELECTUNITS 3 -static SelectUnit selectUnit; - -/* Send emacs escape code when done selecting or extending? */ -static int replyToEmacs; - -static Char *SaveText(TScreen * screen, int row, int scol, int ecol, Char * - lp, int *eol); -static int Length(TScreen * screen, int row, int scol, int ecol); -static void ComputeSelect(int startRow, int startCol, int endRow, int - endCol, Bool extend); -static void EditorButton(XButtonEvent * event); -static void EndExtend(Widget w, XEvent * event, String * params, Cardinal - num_params, Bool use_cursor_loc); -static void ExtendExtend(int row, int col); -static void PointToRowCol(int y, int x, int *r, int *c); -static void ReHiliteText(int frow, int fcol, int trow, int tcol); -static void SaltTextAway(int crow, int ccol, int row, int col, String * - params, Cardinal num_params); -static void SelectSet(Widget w, XEvent * event, String * params, Cardinal num_params); -static void SelectionReceived PROTO_XT_SEL_CB_ARGS; -static void StartSelect(int startrow, int startcol); -static void TrackDown(XButtonEvent * event); -static void _OwnSelection(XtermWidget termw, String * selections, Cardinal count); -static void do_select_end(Widget w, XEvent * event, String * params, - Cardinal *num_params, Bool use_cursor_loc); - -Bool -SendMousePosition(Widget w, XEvent * event) -{ - TScreen *screen; - - if (!IsXtermWidget(w)) - return False; - - screen = &((XtermWidget) w)->screen; - - /* If send_mouse_pos mode isn't on, we shouldn't be here */ - if (screen->send_mouse_pos == MOUSE_OFF) - return False; - -#if OPT_DEC_LOCATOR - if (screen->send_mouse_pos == DEC_LOCATOR) { - return (SendLocatorPosition(w, event)); - } -#endif /* OPT_DEC_LOCATOR */ - - /* Make sure the event is an appropriate type */ - if ((screen->send_mouse_pos != BTN_EVENT_MOUSE) - && (screen->send_mouse_pos != ANY_EVENT_MOUSE) - && event->type != ButtonPress - && event->type != ButtonRelease) - return False; - - switch (screen->send_mouse_pos) { - case X10_MOUSE: /* X10 compatibility sequences */ - - if (KeyModifiers == 0) { - if (event->type == ButtonPress) - EditorButton((XButtonEvent *) event); - return True; - } - return False; - - case VT200_HIGHLIGHT_MOUSE: /* DEC vt200 hilite tracking */ - if (event->type == ButtonPress && - KeyModifiers == 0 && - event->xbutton.button == Button1) { - TrackDown((XButtonEvent *) event); - return True; - } - if (KeyModifiers == 0 || KeyModifiers == ControlMask) { - EditorButton((XButtonEvent *) event); - return True; - } - return False; - - case VT200_MOUSE: /* DEC vt200 compatible */ - - /* xterm extension for motion reporting. June 1998 */ - /* EditorButton() will distinguish between the modes */ - case BTN_EVENT_MOUSE: - case ANY_EVENT_MOUSE: - if (KeyModifiers == 0 || KeyModifiers == ControlMask) { - EditorButton((XButtonEvent *) event); - return True; - } - return False; - - default: - return False; - } -} - -#if OPT_DEC_LOCATOR - -#define LocatorCoords( row, col, x, y, oor ) \ - if( screen->locator_pixels ) { \ - (oor)=False; (row) = (y)+1; (col) = (x)+1; \ - /* Limit to screen dimensions */ \ - if ((row) < 1) (row) = 1,(oor)=True; \ - else if ((row) > screen->border*2+Height(screen)) \ - (row) = screen->border*2+Height(screen),(oor)=True; \ - if ((col) < 1) (col) = 1,(oor)=True; \ - else if ((col) > OriginX(screen)*2+Width(screen)) \ - (col) = OriginX(screen)*2+Width(screen),(oor)=True; \ - } else { \ - (oor)=False; \ - /* Compute character position of mouse pointer */ \ - (row) = ((y) - screen->border) / FontHeight(screen); \ - (col) = ((x) - OriginX(screen)) / FontWidth(screen); \ - /* Limit to screen dimensions */ \ - if ((row) < 0) (row) = 0,(oor)=True; \ - else if ((row) > screen->max_row) \ - (row) = screen->max_row,(oor)=True; \ - if ((col) < 0) (col) = 0,(oor)=True; \ - else if ((col) > screen->max_col) \ - (col) = screen->max_col,(oor)=True; \ - (row)++; (col)++; \ - } - -Bool -SendLocatorPosition(Widget w, XEvent * event) -{ - TScreen *screen = &((XtermWidget) w)->screen; - int row, col; - Bool oor; - int button; - int state; - - /* Make sure the event is an appropriate type */ - if ((event->type != ButtonPress && - event->type != ButtonRelease && - !screen->loc_filter) || - (KeyModifiers != 0 && KeyModifiers != ControlMask)) - return (False); - - if ((event->type == ButtonPress && - !(screen->locator_events & LOC_BTNS_DN)) || - (event->type == ButtonRelease && - !(screen->locator_events & LOC_BTNS_UP))) - return (True); - - if (event->type == MotionNotify) { - CheckLocatorPosition(w, event); - return (True); - } - - /* get button # */ - button = event->xbutton.button - 1; - - LocatorCoords(row, col, event->xbutton.x, event->xbutton.y, oor); - - /* - * DECterm mouse: - * - * ESCAPE '[' event ; mask ; row ; column '&' 'w' - */ - reply.a_type = CSI; - - if (oor) { - reply.a_nparam = 1; - reply.a_param[0] = 0; /* Event - 0 = locator unavailable */ - reply.a_inters = '&'; - reply.a_final = 'w'; - unparseseq(&reply, screen->respond); - - if (screen->locator_reset) { - MotionOff(screen, term); - screen->send_mouse_pos = MOUSE_OFF; - } - return (True); - } - - /* - * event: - * 1 no buttons - * 2 left button down - * 3 left button up - * 4 middle button down - * 5 middle button up - * 6 right button down - * 7 right button up - * 8 M4 down - * 9 M4 up - */ - reply.a_nparam = 4; - switch (event->type) { - case ButtonPress: - reply.a_param[0] = 2 + (button << 1); - break; - case ButtonRelease: - reply.a_param[0] = 3 + (button << 1); - break; - default: - return (True); - } - /* - * mask: - * bit 7 bit 6 bit 5 bit 4 bit 3 bit 2 bit 1 bit 0 - * M4 down left down middle down right down - * - * Notice that Button1 (left) and Button3 (right) are swapped in the mask. - * Also, mask should be the state after the button press/release, - * X provides the state not including the button press/release. - */ - state = (event->xbutton.state - & (Button1Mask | Button2Mask | Button3Mask | Button4Mask)) >> 8; - state ^= 1 << button; /* update mask to "after" state */ - state = (state & ~(4 | 1)) | ((state & 1) ? 4 : 0) | ((state & 4) ? 1 : 0); /* swap Button1 & Button3 */ - - reply.a_param[1] = state; - reply.a_param[2] = row; - reply.a_param[3] = col; - reply.a_inters = '&'; - reply.a_final = 'w'; - - unparseseq(&reply, screen->respond); - - if (screen->locator_reset) { - MotionOff(screen, term); - screen->send_mouse_pos = MOUSE_OFF; - } - - /* - * DECterm turns the Locator off if a button is pressed while a filter rectangle - * is active. This might be a bug, but I don't know, so I'll emulate it anyways. - */ - if (screen->loc_filter) { - screen->send_mouse_pos = MOUSE_OFF; - screen->loc_filter = False; - screen->locator_events = 0; - MotionOff(screen, term); - } - - return (True); -} - -/* - * mask: - * bit 7 bit 6 bit 5 bit 4 bit 3 bit 2 bit 1 bit 0 - * M4 down left down middle down right down - * - * Button1 (left) and Button3 (right) are swapped in the mask relative to X. - */ -#define ButtonState(state, mask) \ -{ (state) = ((mask) & (Button1Mask | Button2Mask | Button3Mask | Button4Mask)) >> 8; \ - /* swap Button1 & Button3 */ \ - (state) = ((state) & ~(4|1)) | (((state)&1)?4:0) | (((state)&4)?1:0); \ -} - -void -GetLocatorPosition(XtermWidget w) -{ - TScreen *screen = &w->screen; - Window root, child; - int rx, ry, x, y; - unsigned int mask; - int row = 0, col = 0; - Bool oor = False; - Bool ret = False; - int state; - - /* - * DECterm turns the Locator off if the position is requested while a filter rectangle - * is active. This might be a bug, but I don't know, so I'll emulate it anyways. - */ - if (screen->loc_filter) { - screen->send_mouse_pos = MOUSE_OFF; - screen->loc_filter = False; - screen->locator_events = 0; - MotionOff(screen, term); - } - - reply.a_type = CSI; - - if (screen->send_mouse_pos == DEC_LOCATOR) { - ret = XQueryPointer(screen->display, VWindow(screen), &root, - &child, &rx, &ry, &x, &y, &mask); - if (ret) { - LocatorCoords(row, col, x, y, oor); - } - } - if (ret == False || oor) { - reply.a_nparam = 1; - reply.a_param[0] = 0; /* Event - 0 = locator unavailable */ - reply.a_inters = '&'; - reply.a_final = 'w'; - unparseseq(&reply, screen->respond); - - if (screen->locator_reset) { - MotionOff(screen, term); - screen->send_mouse_pos = MOUSE_OFF; - } - return; - } - - ButtonState(state, mask); - - reply.a_nparam = 4; - reply.a_param[0] = 1; /* Event - 1 = response to locator request */ - reply.a_param[1] = state; - reply.a_param[2] = row; - reply.a_param[3] = col; - reply.a_inters = '&'; - reply.a_final = 'w'; - unparseseq(&reply, screen->respond); - - if (screen->locator_reset) { - MotionOff(screen, term); - screen->send_mouse_pos = MOUSE_OFF; - } -} - -void -InitLocatorFilter(XtermWidget w) -{ - TScreen *screen = &w->screen; - Window root, child; - int rx, ry, x, y; - unsigned int mask; - int row = 0, col = 0; - Bool oor = 0; - Bool ret; - int state; - - ret = XQueryPointer(screen->display, VWindow(screen), - &root, &child, &rx, &ry, &x, &y, &mask); - if (ret) { - LocatorCoords(row, col, x, y, oor); - } - if (ret == False || oor) { - /* Locator is unavailable */ - - if (screen->loc_filter_top != LOC_FILTER_POS || - screen->loc_filter_left != LOC_FILTER_POS || - screen->loc_filter_bottom != LOC_FILTER_POS || - screen->loc_filter_right != LOC_FILTER_POS) { - /* - * If any explicit coordinates were received, - * report immediately with no coordinates. - */ - reply.a_type = CSI; - reply.a_nparam = 1; - reply.a_param[0] = 0; /* Event - 0 = locator unavailable */ - reply.a_inters = '&'; - reply.a_final = 'w'; - unparseseq(&reply, screen->respond); - - if (screen->locator_reset) { - MotionOff(screen, term); - screen->send_mouse_pos = MOUSE_OFF; - } - } else { - /* - * No explicit coordinates were received, and the pointer is - * unavailable. Report when the pointer re-enters the window. - */ - screen->loc_filter = True; - MotionOn(screen, term); - } - return; - } - - /* - * Adjust rectangle coordinates: - * 1. Replace "LOC_FILTER_POS" with current coordinates - * 2. Limit coordinates to screen size - * 3. make sure top and left are less than bottom and right, resp. - */ - if (screen->locator_pixels) { - rx = OriginX(screen) * 2 + Width(screen); - ry = screen->border * 2 + Height(screen); - } else { - rx = screen->max_col; - ry = screen->max_row; - } - -#define Adjust( coord, def, max ) \ - if( (coord) == LOC_FILTER_POS ) (coord) = (def); \ - else if ((coord) < 1) (coord) = 1; \ - else if ((coord) > (max)) (coord) = (max) - - Adjust(screen->loc_filter_top, row, ry); - Adjust(screen->loc_filter_left, col, rx); - Adjust(screen->loc_filter_bottom, row, ry); - Adjust(screen->loc_filter_right, col, rx); - - if (screen->loc_filter_top > screen->loc_filter_bottom) { - ry = screen->loc_filter_top; - screen->loc_filter_top = screen->loc_filter_bottom; - screen->loc_filter_bottom = ry; - } - - if (screen->loc_filter_left > screen->loc_filter_right) { - rx = screen->loc_filter_left; - screen->loc_filter_left = screen->loc_filter_right; - screen->loc_filter_right = rx; - } - - if ((col < screen->loc_filter_left) || - (col > screen->loc_filter_right) || - (row < screen->loc_filter_top) || - (row > screen->loc_filter_bottom)) { - /* Pointer is already outside the rectangle - report immediately */ - ButtonState(state, mask); - - reply.a_type = CSI; - reply.a_nparam = 4; - reply.a_param[0] = 10; /* Event - 10 = locator outside filter */ - reply.a_param[1] = state; - reply.a_param[2] = row; - reply.a_param[3] = col; - reply.a_inters = '&'; - reply.a_final = 'w'; - unparseseq(&reply, screen->respond); - - if (screen->locator_reset) { - MotionOff(screen, term); - screen->send_mouse_pos = MOUSE_OFF; - } - return; - } - - /* - * Rectangle is set up. Allow pointer tracking - * to detect if the mouse leaves the rectangle. - */ - screen->loc_filter = True; - MotionOn(screen, term); -} - -void -CheckLocatorPosition(Widget w, XEvent * event) -{ - TScreen *screen = &((XtermWidget) w)->screen; - int row, col; - Bool oor; - int state; - - LocatorCoords(row, col, event->xbutton.x, event->xbutton.y, oor); - - /* - * Send report if the pointer left the filter rectangle, if - * the pointer left the window, or if the filter rectangle - * had no coordinates and the pointer re-entered the window. - */ - if (oor || (screen->loc_filter_top == LOC_FILTER_POS) || - (col < screen->loc_filter_left) || - (col > screen->loc_filter_right) || - (row < screen->loc_filter_top) || - (row > screen->loc_filter_bottom)) { - /* Filter triggered - disable it */ - screen->loc_filter = False; - MotionOff(screen, term); - - reply.a_type = CSI; - if (oor) { - reply.a_nparam = 1; - reply.a_param[0] = 0; /* Event - 0 = locator unavailable */ - } else { - ButtonState(state, event->xbutton.state); - - reply.a_nparam = 4; - reply.a_param[0] = 10; /* Event - 10 = locator outside filter */ - reply.a_param[1] = state; - reply.a_param[2] = row; - reply.a_param[3] = col; - } - - reply.a_inters = '&'; - reply.a_final = 'w'; - unparseseq(&reply, screen->respond); - - if (screen->locator_reset) { - MotionOff(screen, term); - screen->send_mouse_pos = MOUSE_OFF; - } - } -} -#endif /* OPT_DEC_LOCATOR */ - -#if OPT_READLINE -static int -isClick1_clean(XEvent * event) -{ - TScreen *screen = &term->screen; - int delta; - - if (!(event->type == ButtonPress || event->type == ButtonRelease) - /* Disable on Shift-Click-1, including the application-mouse modes */ - || (KeyModifiers & ShiftMask) - || (screen->send_mouse_pos != MOUSE_OFF) /* Kinda duplicate... */ - ||ExtendingSelection) /* Was moved */ - return 0; - if (event->type != ButtonRelease) - return 0; - if (lastButtonDownTime == (Time) 0) /* first time or once in a blue moon */ - delta = term->screen.multiClickTime + 1; - else if (event->xbutton.time > lastButtonDownTime) /* most of the time */ - delta = event->xbutton.time - lastButtonDownTime; - else /* time has rolled over since lastButtonUpTime */ - delta = (((Time) ~ 0) - lastButtonDownTime) + event->xbutton.time; - return delta <= term->screen.multiClickTime; -} - -static int -isDoubleClick3(XEvent * event) -{ - int delta; - - if (event->type != ButtonRelease - || (KeyModifiers & ShiftMask) - || event->xbutton.button != Button3) { - lastButton3UpTime = 0; /* Disable the cached info */ - return 0; - } - /* Process Btn3Release. */ - if (lastButton3DoubleDownTime == (Time) 0) /* No previous click - or once in a blue moon */ - delta = term->screen.multiClickTime + 1; - else if (event->xbutton.time > lastButton3DoubleDownTime) /* most of the time */ - delta = event->xbutton.time - lastButton3DoubleDownTime; - else /* time has rolled over since lastButton3DoubleDownTime */ - delta = (((Time) ~ 0) - lastButton3DoubleDownTime) + event->xbutton.time; - if (delta <= term->screen.multiClickTime) { - /* Double click */ - int row, col; - - /* Cannot check ExtendingSelection, since mouse-3 always sets it */ - PointToRowCol(event->xbutton.y, event->xbutton.x, &row, &col); - if (row == lastButton3row && col == lastButton3col) { - lastButton3DoubleDownTime = 0; /* Disable the third click */ - return 1; - } - } - /* Not a double click, memorize for future check. */ - lastButton3UpTime = event->xbutton.time; - PointToRowCol(event->xbutton.y, event->xbutton.x, - &lastButton3row, &lastButton3col); - return 0; -} - -static int -CheckSecondPress3(XEvent * event) -{ - int delta, row, col; - - if (event->type != ButtonPress - || (KeyModifiers & ShiftMask) - || event->xbutton.button != Button3) { - lastButton3DoubleDownTime = 0; /* Disable the cached info */ - return 0; - } - /* Process Btn3Press. */ - if (lastButton3UpTime == (Time) 0) /* No previous click - or once in a blue moon */ - delta = term->screen.multiClickTime + 1; - else if (event->xbutton.time > lastButton3UpTime) /* most of the time */ - delta = event->xbutton.time - lastButton3UpTime; - else /* time has rolled over since lastButton3UpTime */ - delta = (((Time) ~ 0) - lastButton3UpTime) + event->xbutton.time; - if (delta <= term->screen.multiClickTime) { - PointToRowCol(event->xbutton.y, event->xbutton.x, &row, &col); - if (row == lastButton3row && col == lastButton3col) { - /* A candidate for a double-click */ - lastButton3DoubleDownTime = event->xbutton.time; - PointToRowCol(event->xbutton.y, event->xbutton.x, - &lastButton3row, &lastButton3col); - return 1; - } - lastButton3UpTime = 0; /* Disable the info about the previous click */ - } - /* Either too long, or moved, disable. */ - lastButton3DoubleDownTime = 0; - return 0; -} - -static int -rowOnCurrentLine(int line, int *deltap) /* must be XButtonEvent */ -{ - TScreen *screen = &term->screen; - int l1, l2; - - *deltap = 0; - if (line == screen->cur_row) - return 1; - - if (line < screen->cur_row) - l1 = line, l2 = screen->cur_row; - else - l2 = line, l1 = screen->cur_row; - l1--; - while (++l1 < l2) - if (!ScrnTstWrapped(screen, l1)) - return 0; - /* Everything is on one "wrapped line" now */ - *deltap = line - screen->cur_row; - return 1; -} - -static int -eventRow(XEvent * event) /* must be XButtonEvent */ -{ - TScreen *screen = &term->screen; - - return (event->xbutton.y - screen->border) / FontHeight(screen); -} - -static int -eventColBetween(XEvent * event) /* must be XButtonEvent */ -{ - TScreen *screen = &term->screen; - - /* Correct by half a width - we are acting on a boundary, not on a cell. */ - return ((event->xbutton.x - OriginX(screen) + (FontWidth(screen) - 1) / 2) - / FontWidth(screen)); -} - -static int -ReadLineMovePoint(int col, int ldelta) -{ - TScreen *screen = &term->screen; - Char line[6]; - unsigned count = 0; - - col += ldelta * MaxCols(screen) - screen->cur_col; - if (col == 0) - return 0; - if (screen->control_eight_bits) { - line[count++] = CSI; - } else { - line[count++] = ESC; - line[count++] = '['; /* XXX maybe sometimes O is better? */ - } - line[count++] = (col > 0 ? 'C' : 'D'); - if (col < 0) - col = -col; - while (col--) - v_write(screen->respond, line, 3); - return 1; -} - -static int -ReadLineDelete(int r1, int c1, int r2, int c2) -{ - TScreen *screen = &term->screen; - int del; - - del = c2 - c1 + (r2 - r1) * MaxCols(screen); - if (del <= 0) /* Just in case... */ - return 0; - while (del--) - v_write(screen->respond, (Char *) "\177", 1); - return 1; -} -#endif /* OPT_READLINE */ - -/* ^XM-G<line+' '><col+' '> */ -void -DiredButton(Widget w GCC_UNUSED, - XEvent * event, /* must be XButtonEvent */ - String * params GCC_UNUSED, /* selections */ - Cardinal *num_params GCC_UNUSED) -{ - TScreen *screen = &term->screen; - Char Line[6]; - unsigned line, col; - - if (event->type == ButtonPress || event->type == ButtonRelease) { - line = (event->xbutton.y - screen->border) / FontHeight(screen); - col = (event->xbutton.x - OriginX(screen)) / FontWidth(screen); - Line[0] = CONTROL('X'); - Line[1] = ESC; - Line[2] = 'G'; - Line[3] = ' ' + col; - Line[4] = ' ' + line; - v_write(screen->respond, Line, 5); - } -} - -#if OPT_READLINE -void -ReadLineButton(Widget w GCC_UNUSED, - XEvent * event, /* must be XButtonEvent */ - String * params GCC_UNUSED, /* selections */ - Cardinal *num_params GCC_UNUSED) -{ - TScreen *screen = &term->screen; - Char Line[6]; - int line, col, ldelta = 0; - - if (!(event->type == ButtonPress || event->type == ButtonRelease) - || (screen->send_mouse_pos != MOUSE_OFF) || ExtendingSelection) - goto finish; - if (event->type == ButtonRelease) { - int delta; - - if (lastButtonDownTime == (Time) 0) /* first time and once in a blue moon */ - delta = screen->multiClickTime + 1; - else if (event->xbutton.time > lastButtonDownTime) /* most of the time */ - delta = event->xbutton.time - lastButtonDownTime; - else /* time has rolled over since lastButtonUpTime */ - delta = (((Time) ~ 0) - lastButtonDownTime) + event->xbutton.time; - if (delta > screen->multiClickTime) - goto finish; /* All this work for this... */ - } - line = (event->xbutton.y - screen->border) / FontHeight(screen); - if (line != screen->cur_row) { - int l1, l2; - - if (line < screen->cur_row) - l1 = line, l2 = screen->cur_row; - else - l2 = line, l1 = screen->cur_row; - l1--; - while (++l1 < l2) - if (!ScrnTstWrapped(screen, l1)) - goto finish; - /* Everything is on one "wrapped line" now */ - ldelta = line - screen->cur_row; - } - /* Correct by half a width - we are acting on a boundary, not on a cell. */ - col = (event->xbutton.x - OriginX(screen) + (FontWidth(screen) - 1) / 2) - / FontWidth(screen) - screen->cur_col + ldelta * MaxCols(screen); - if (col == 0) - goto finish; - Line[0] = ESC; - /* XXX: sometimes it is better to send '['? */ - Line[1] = 'O'; - Line[2] = (col > 0 ? 'C' : 'D'); - if (col < 0) - col = -col; - while (col--) - v_write(screen->respond, Line, 3); - finish: - if (event->type == ButtonRelease) - do_select_end(w, event, params, num_params, False); -} -#endif /* OPT_READLINE */ - -/* repeats <ESC>n or <ESC>p */ -void -ViButton(Widget w GCC_UNUSED, - XEvent * event, /* must be XButtonEvent */ - String * params GCC_UNUSED, /* selections */ - Cardinal *num_params GCC_UNUSED) -{ - TScreen *screen = &term->screen; - int pty = screen->respond; - Char Line[6]; - int line; - - if (event->type == ButtonPress || event->type == ButtonRelease) { - - line = screen->cur_row - - ((event->xbutton.y - screen->border) / FontHeight(screen)); - if (line != 0) { - Line[0] = ESC; /* force an exit from insert-mode */ - v_write(pty, Line, 1); - - if (line < 0) { - line = -line; - Line[0] = CONTROL('n'); - } else { - Line[0] = CONTROL('p'); - } - while (--line >= 0) - v_write(pty, Line, 1); - } - } -} - -/* - * This function handles button-motion events - */ -/*ARGSUSED*/ -void -HandleSelectExtend(Widget w, - XEvent * event, /* must be XMotionEvent */ - String * params GCC_UNUSED, - Cardinal *num_params GCC_UNUSED) -{ - TScreen *screen; - int row, col; - - if (!IsXtermWidget(w)) - return; - - screen = &((XtermWidget) w)->screen; - screen->selection_time = event->xmotion.time; - switch (eventMode) { - /* If not in one of the DEC mouse-reporting modes */ - case LEFTEXTENSION: - case RIGHTEXTENSION: - PointToRowCol(event->xmotion.y, event->xmotion.x, - &row, &col); - ExtendExtend(row, col); - break; - - /* If in motion reporting mode, send mouse position to - character process as a key sequence \E[M... */ - case NORMAL: - /* will get here if send_mouse_pos != MOUSE_OFF */ - if (screen->send_mouse_pos == BTN_EVENT_MOUSE - || screen->send_mouse_pos == ANY_EVENT_MOUSE) { - (void) SendMousePosition(w, event); - } - break; - } -} - -void -HandleKeyboardSelectExtend(Widget w, - XEvent * event GCC_UNUSED, /* must be XButtonEvent */ - String * params GCC_UNUSED, - Cardinal *num_params GCC_UNUSED) -{ - TScreen *screen; - - if (!IsXtermWidget(w)) - return; - - screen = &((XtermWidget) w)->screen; - ExtendExtend(screen->cursor_row, screen->cursor_col); -} - -static void -do_select_end(Widget w, - XEvent * event, /* must be XButtonEvent */ - String * params, /* selections */ - Cardinal *num_params, - Bool use_cursor_loc) -{ -#if OPT_READLINE - int ldelta1, ldelta2; - TScreen *screen = &term->screen; -#endif - - if (!IsXtermWidget(w)) { - return; - } - - ((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); -#if OPT_READLINE - if (isClick1_clean(event) - && SCREEN_FLAG(screen, click1_moves) - && rowOnCurrentLine(eventRow(event), &ldelta1)) { - ReadLineMovePoint(eventColBetween(event), ldelta1); - } - if (isDoubleClick3(event) - && SCREEN_FLAG(screen, dclick3_deletes) - && rowOnCurrentLine(startSRow, &ldelta1) - && rowOnCurrentLine(endSRow, &ldelta2)) { - ReadLineMovePoint(endSCol, ldelta2); - ReadLineDelete(startSRow, startSCol, endSRow, endSCol); - } -#endif /* OPT_READLINE */ - break; - } -} - -void -HandleSelectEnd(Widget w, - XEvent * event, /* must be XButtonEvent */ - String * params, /* selections */ - Cardinal *num_params) -{ - do_select_end(w, event, params, num_params, False); -} - -void -HandleKeyboardSelectEnd(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; - Atom *targets; - Time time; -}; - -/* convert a UTF-8 string to Latin-1, replacing non Latin-1 characters - * by `#'. */ - -#if OPT_WIDE_CHARS -static Char * -UTF8toLatin1(Char * s, unsigned len, unsigned long *result) -{ - static Char *buffer; - static size_t used; - - Char *p = s; - Char *q; - - if (used == 0) { - buffer = (Char *) XtMalloc(used = len); - } else if (len > used) { - buffer = (Char *) XtRealloc((char *) buffer, used = len); - } - q = buffer; - - /* We're assuming that the xterm widget never contains Unicode - control characters. */ - - while (p < s + len) { - if ((*p & 0x80) == 0) { - *q++ = *p++; - } else if ((*p & 0x7C) == 0x40 && p < s + len - 1) { - *q++ = ((*p & 0x03) << 6) | (p[1] & 0x3F); - p += 2; - } else if ((*p & 0x60) == 0x40) { - *q++ = '#'; - p += 2; - } else if ((*p & 0x50) == 0x40) { - *q++ = '#'; - p += 3; - } else { /* this cannot happen */ - *q++ = '#'; - p++; - } - } - *result = q - buffer; - return buffer; -} -#endif /* OPT_WIDE_CHARS */ - -static Atom * -_SelectionTargets(Widget w) -{ - static Atom *eightBitSelectionTargets = NULL; - TScreen *screen; - int n; - - if (!IsXtermWidget(w)) - return NULL; - - screen = &((XtermWidget) w)->screen; - -#if OPT_WIDE_CHARS - if (screen->wide_chars) { - static Atom *utf8SelectionTargets = NULL; - - if (utf8SelectionTargets == NULL) { - utf8SelectionTargets = (Atom *) XtMalloc(5 * sizeof(Atom)); - if (utf8SelectionTargets == NULL) { - TRACE(("Couldn't allocate utf8SelectionTargets\n")); - return NULL; - } - n = 0; - utf8SelectionTargets[n++] = XA_UTF8_STRING(XtDisplay(w)); -#ifdef X_HAVE_UTF8_STRING - if (screen->i18nSelections) { - utf8SelectionTargets[n++] = XA_TEXT(XtDisplay(w)); - utf8SelectionTargets[n++] = XA_COMPOUND_TEXT(XtDisplay(w)); - } -#endif - utf8SelectionTargets[n++] = XA_STRING; - utf8SelectionTargets[n] = None; - } - return utf8SelectionTargets; - } -#endif - - /* not screen->wide_chars */ - if (eightBitSelectionTargets == NULL) { - eightBitSelectionTargets = (Atom *) XtMalloc(5 * sizeof(Atom)); - if (eightBitSelectionTargets == NULL) { - TRACE(("Couldn't allocate eightBitSelectionTargets\n")); - return NULL; - } - n = 0; -#ifdef X_HAVE_UTF8_STRING - eightBitSelectionTargets[n++] = XA_UTF8_STRING(XtDisplay(w)); -#endif - if (screen->i18nSelections) { - eightBitSelectionTargets[n++] = XA_TEXT(XtDisplay(w)); - eightBitSelectionTargets[n++] = XA_COMPOUND_TEXT(XtDisplay(w)); - } - eightBitSelectionTargets[n++] = XA_STRING; - eightBitSelectionTargets[n] = None; - } - return eightBitSelectionTargets; -} - -/* - * Lookup the cut-buffer number, which will be in the range 0-7. - * If it is not a cut-buffer, it is the primary selection (-1). - */ -static int -CutBuffer(unsigned code) -{ - int cutbuffer; - switch (code) { - 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; - break; - } - return cutbuffer; -} - -#define ResetPaste64() term->screen.base64_paste = 0 - -#if !OPT_PASTE64 -static -#endif -void -xtermGetSelection(Widget w, - Time ev_time, - String * params, /* selections in precedence order */ - Cardinal num_params, - Atom * targets) -{ - Atom selection; - int cutbuffer; - Atom target; - - if (!IsXtermWidget(w)) - return; - -#if OPT_TRACE - TRACE(("xtermGetSelection\n")); - if (num_params > 0) { - Cardinal n; - for (n = 0; n < num_params; ++n) { - TRACE(("param[%d]:%s\n", n, params[n])); - } - } -#endif - - XmuInternStrings(XtDisplay(w), params, (Cardinal) 1, &selection); - cutbuffer = CutBuffer(selection); - TRACE(("Cutbuffer: %d, target: %lu\n", cutbuffer, - targets ? (unsigned long) targets[0] : 0)); - if (cutbuffer >= 0) { - int inbytes; - unsigned long nbytes; - int fmt8 = 8; - Atom type = XA_STRING; - char *line; - - /* 'line' is freed in SelectionReceived */ - line = XFetchBuffer(XtDisplay(w), &inbytes, cutbuffer); - nbytes = (unsigned long) inbytes; - - if (nbytes > 0) - SelectionReceived(w, NULL, &selection, &type, (XtPointer) line, - &nbytes, &fmt8); - else if (num_params > 1) - xtermGetSelection(w, ev_time, params + 1, num_params - 1, NULL); -#if OPT_PASTE64 - else - ResetPaste64(); -#endif - return; - } else { - struct _SelectionList *list; - - if (targets == NULL || targets[0] == None) { - targets = _SelectionTargets(w); - } - - if (targets != 0) { - target = targets[0]; - - if (targets[1] == None) { /* last target in list */ - params++; - num_params--; - targets = _SelectionTargets(w); - } else { - targets = &(targets[1]); - } - - if (num_params) { - /* 'list' is freed in SelectionReceived */ - list = XtNew(struct _SelectionList); - if (list != 0) { - list->params = params; - list->count = num_params; - list->targets = targets; - list->time = ev_time; - } - } else { - list = NULL; - } - - XtGetSelectionValue(w, selection, - target, - SelectionReceived, - (XtPointer) list, ev_time); - } - } -} - -#if OPT_TRACE && OPT_WIDE_CHARS -static void -GettingSelection(Display * dpy, Atom type, Char * line, unsigned long len) -{ - Char *cp; - char *name; - - name = XGetAtomName(dpy, type); - - TRACE(("Getting %s (%ld)\n", name, (long int) type)); - for (cp = line; cp < line + len; cp++) { - TRACE(("[%d:%lu]", cp + 1 - line, len)); - if (isprint(*cp)) { - TRACE(("%c\n", *cp)); - } else { - TRACE(("\\x%02x\n", *cp)); - } - } -} -#else -#define GettingSelection(dpy,type,line,len) /* nothing */ -#endif - -#ifdef VMS -# define tty_vwrite(pty,lag,l) tt_write(lag,l) -#else /* !( VMS ) */ -# define tty_vwrite(pty,lag,l) v_write(pty,lag,l) -#endif /* defined VMS */ - -#if OPT_PASTE64 -/* Return base64 code character given 6-bit number */ -static const char base64_code[] = "\ -ABCDEFGHIJKLMNOPQRSTUVWXYZ\ -abcdefghijklmnopqrstuvwxyz\ -0123456789+/"; -static void -base64_flush(TScreen * screen) -{ - Char x; - switch (screen->base64_count) { - case 0: - break; - case 2: - x = base64_code[screen->base64_accu << 4]; - tty_vwrite(screen->respond, &x, 1); - break; - case 4: - x = base64_code[screen->base64_accu << 2]; - tty_vwrite(screen->respond, &x, 1); - break; - } - if (screen->base64_pad & 3) - tty_vwrite(screen->respond, - (Char *) "===", - 4 - (screen->base64_pad & 3)); - screen->base64_count = 0; - screen->base64_accu = 0; - screen->base64_pad = 0; -} -#endif /* OPT_PASTE64 */ - -static void -_qWriteSelectionData(TScreen * screen, Char * lag, unsigned length) -{ -#if OPT_PASTE64 - if (screen->base64_paste) { - /* Send data as base64 */ - Char *p = lag; - Char buf[64]; - unsigned x = 0; - while (length--) { - switch (screen->base64_count) { - case 0: - buf[x++] = base64_code[*p >> 2]; - screen->base64_accu = (*p & 0x3); - screen->base64_count = 2; - ++p; - break; - case 2: - buf[x++] = base64_code[(screen->base64_accu << 4) + (*p >> 4)]; - screen->base64_accu = (*p & 0xF); - screen->base64_count = 4; - ++p; - break; - case 4: - buf[x++] = base64_code[(screen->base64_accu << 2) + (*p >> 6)]; - buf[x++] = base64_code[*p & 0x3F]; - screen->base64_accu = 0; - screen->base64_count = 0; - ++p; - break; - } - if (x >= 63) { - /* Write 63 or 64 characters */ - screen->base64_pad += x; - tty_vwrite(screen->respond, buf, x); - x = 0; - } - } - if (x != 0) { - screen->base64_pad += x; - tty_vwrite(screen->respond, buf, x); - } - } else -#endif /* OPT_PASTE64 */ -#if OPT_READLINE - if (SCREEN_FLAG(screen, paste_quotes)) { - while (length--) { - tty_vwrite(screen->respond, (Char *) "\026", 1); /* Control-V */ - tty_vwrite(screen->respond, lag++, 1); - } - } else -#endif - tty_vwrite(screen->respond, lag, length); -} - -static void -_WriteSelectionData(TScreen * screen, Char * line, int length) -{ - /* 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. */ - - Char *lag, *end; - - /* in the VMS version, if tt_pasting isn't set to True then qio - reads aren't blocked and an infinite loop is entered, where the - pasted text shows up as new input, goes in again, shows up - again, ad nauseum. */ -#ifdef VMS - tt_pasting = True; -#endif - - end = &line[length]; - lag = line; - -#if OPT_PASTE64 - if (screen->base64_paste) { - _qWriteSelectionData(screen, lag, (unsigned) (end - lag)); - base64_flush(screen); - } else -#endif - { - if (!SCREEN_FLAG(screen, paste_literal_nl)) { - Char *cp; - for (cp = line; cp != end; cp++) { - if (*cp == '\n') { - *cp = '\r'; - _qWriteSelectionData(screen, lag, (unsigned) (cp - lag + 1)); - lag = cp + 1; - } - } - } - - if (lag != end) { - _qWriteSelectionData(screen, lag, (unsigned) (end - lag)); - } - } -#ifdef VMS - tt_pasting = False; - tt_start_read(); /* reenable reads or a character may be lost */ -#endif -} - -#if OPT_READLINE -static void -_WriteKey(TScreen * screen, Char * in) -{ - Char line[16]; - unsigned count = 0; - unsigned length = strlen((char *) in); - - if (screen->control_eight_bits) { - line[count++] = CSI; - } else { - line[count++] = ESC; - line[count++] = '['; - } - while (length--) - line[count++] = *in++; - line[count++] = '~'; - tty_vwrite(screen->respond, line, count); -} -#endif /* OPT_READLINE */ - -/* SelectionReceived: stuff received selection text into pty */ - -/* ARGSUSED */ -static void -SelectionReceived(Widget w, - XtPointer client_data, - Atom * selection GCC_UNUSED, - Atom * type, - XtPointer value, - unsigned long *length, - int *format GCC_UNUSED) -{ - char **text_list = NULL; - int text_list_count; - XTextProperty text_prop; - TScreen *screen; - Display *dpy; -#if OPT_TRACE && OPT_WIDE_CHARS - Char *line = (Char *) value; -#endif - - if (!IsXtermWidget(w)) - return; - screen = &((XtermWidget) w)->screen; - dpy = XtDisplay(w); - - if (*type == 0 /*XT_CONVERT_FAIL */ - || *length == 0 - || value == NULL) - goto fail; - - text_prop.value = (unsigned char *) value; - text_prop.encoding = *type; - text_prop.format = *format; - text_prop.nitems = *length; - -#if OPT_WIDE_CHARS - if (screen->wide_chars) { - if (*type == XA_UTF8_STRING(XtDisplay(w)) || - *type == XA_STRING || - *type == XA_COMPOUND_TEXT(XtDisplay(w))) { - GettingSelection(dpy, *type, line, *length); - if (Xutf8TextPropertyToTextList(dpy, &text_prop, - &text_list, - &text_list_count) < 0) { - TRACE(("Conversion failed\n")); - text_list = NULL; - } - } - } else -#endif /* OPT_WIDE_CHARS */ - { - /* Convert the selection to locale's multibyte encoding. */ - - /* There's no need to special-case UTF8_STRING. If Xlib - doesn't know about it, we didn't request it. If a broken - selection holder sends it anyhow, the conversion function - will fail. */ - - if (*type == XA_UTF8_STRING(XtDisplay(w)) || - *type == XA_STRING || - *type == XA_COMPOUND_TEXT(XtDisplay(w))) { - Status rc; - GettingSelection(dpy, *type, line, *length); - if (*type == XA_STRING && screen->brokenSelections) { - rc = XTextPropertyToStringList(&text_prop, - &text_list, &text_list_count); - } else { - rc = XmbTextPropertyToTextList(dpy, &text_prop, - &text_list, - &text_list_count); - } - if (rc < 0) { - TRACE(("Conversion failed\n")); - text_list = NULL; - } - } - } - - if (text_list != NULL && text_list_count != 0) { - int i; - -#if OPT_PASTE64 - if (screen->base64_paste) { - ; - } else -#endif -#if OPT_READLINE - if (SCREEN_FLAG(screen, paste_brackets)) { - _WriteKey(screen, (Char *) "200"); - } -#endif - for (i = 0; i < text_list_count; i++) { - int len = strlen(text_list[i]); - _WriteSelectionData(screen, (Char *) text_list[i], len); - } -#if OPT_PASTE64 - if (screen->base64_paste) { - ResetPaste64(); - } else -#endif -#if OPT_READLINE - if (SCREEN_FLAG(screen, paste_brackets)) { - _WriteKey(screen, (Char *) "201"); - } -#endif - XFreeStringList(text_list); - } else - goto fail; - - XtFree((char *) client_data); - XtFree((char *) value); - - return; - - fail: - if (client_data != 0) { - struct _SelectionList *list = (struct _SelectionList *) client_data; - xtermGetSelection(w, list->time, - list->params, list->count, list->targets); - XtFree((char *) client_data); -#if OPT_PASTE64 - } else { - ResetPaste64(); -#endif - } - return; -} - -void -HandleInsertSelection(Widget w, - XEvent * event, /* assumed to be XButtonEvent* */ - String * params, /* selections in precedence order */ - Cardinal *num_params) -{ -#if OPT_READLINE - int ldelta; - TScreen *screen = &((XtermWidget) w)->screen; -#endif - - if (SendMousePosition(w, event)) - return; - -#if OPT_READLINE - if ((event->type == ButtonPress || event->type == ButtonRelease) - /* Disable on Shift-mouse, including the application-mouse modes */ - && !(KeyModifiers & ShiftMask) - && (screen->send_mouse_pos == MOUSE_OFF) - && SCREEN_FLAG(screen, paste_moves) - && rowOnCurrentLine(eventRow(event), &ldelta)) - ReadLineMovePoint(eventColBetween(event), ldelta); -#endif /* OPT_READLINE */ - - xtermGetSelection(w, event->xbutton.time, params, *num_params, NULL); -} - -static SelectUnit -EvalSelectUnit(Time buttonDownTime, SelectUnit defaultUnit) -{ - int delta; - - if (lastButtonUpTime == (Time) 0) /* first time and once in a blue moon */ - delta = term->screen.multiClickTime + 1; - else if (buttonDownTime > lastButtonUpTime) /* most of the time */ - delta = buttonDownTime - lastButtonUpTime; - else /* time has rolled over since lastButtonUpTime */ - delta = (((Time) ~ 0) - lastButtonUpTime) + buttonDownTime; - - if (delta > term->screen.multiClickTime) { - numberOfClicks = 1; - return defaultUnit; - } else { - ++numberOfClicks; - return ((selectUnit + 1) % NSELECTUNITS); - } -} - -static void -do_select_start(Widget w, - XEvent * event, /* must be XButtonEvent* */ - int startrow, - int startcol) -{ - if (SendMousePosition(w, event)) - return; - selectUnit = EvalSelectUnit(event->xbutton.time, SELECTCHAR); - replyToEmacs = False; - -#if OPT_READLINE - lastButtonDownTime = event->xbutton.time; -#endif - - StartSelect(startrow, startcol); -} - -/* ARGSUSED */ -void -HandleSelectStart(Widget w, - XEvent * event, /* must be XButtonEvent* */ - String * params GCC_UNUSED, - Cardinal *num_params GCC_UNUSED) -{ - TScreen *screen; - int startrow, startcol; - - if (!IsXtermWidget(w)) - return; - - screen = &((XtermWidget) w)->screen; - firstValidRow = 0; - lastValidRow = screen->max_row; - PointToRowCol(event->xbutton.y, event->xbutton.x, &startrow, &startcol); - -#if OPT_READLINE - ExtendingSelection = 0; -#endif - - do_select_start(w, event, startrow, startcol); -} - -/* ARGSUSED */ -void -HandleKeyboardSelectStart(Widget w, - XEvent * event, /* must be XButtonEvent* */ - String * params GCC_UNUSED, - Cardinal *num_params GCC_UNUSED) -{ - TScreen *screen; - - if (!IsXtermWidget(w)) - return; - - screen = &((XtermWidget) w)->screen; - do_select_start(w, event, screen->cursor_row, screen->cursor_col); -} - -static void -TrackDown(XButtonEvent * event) -{ - int startrow, startcol; - - selectUnit = EvalSelectUnit(event->time, SELECTCHAR); - if (numberOfClicks > 1) { - PointToRowCol(event->y, event->x, &startrow, &startcol); - replyToEmacs = True; - StartSelect(startrow, startcol); - } else { - waitingForTrackInfo = True; - EditorButton((XButtonEvent *) event); - } -} - -#define boundsCheck(x) if (x < 0) \ - x = 0; \ - else if (x >= screen->max_row) \ - x = screen->max_row - -void -TrackMouse(int func, int startrow, int startcol, int firstrow, int lastrow) -{ - TScreen *screen = &term->screen; - - if (!waitingForTrackInfo) { /* Timed out, so ignore */ - return; - } - waitingForTrackInfo = False; - if (func == 0) - return; - boundsCheck(startrow); - boundsCheck(firstrow); - boundsCheck(lastrow); - firstValidRow = firstrow; - lastValidRow = lastrow; - replyToEmacs = True; - StartSelect(startrow, startcol); -} - -static void -StartSelect(int startrow, int startcol) -{ - TScreen *screen = &term->screen; - - TRACE(("StartSelect row=%d, col=%d\n", startrow, startcol)); - if (screen->cursor_state) - HideCursor(); - if (numberOfClicks == 1) { - /* set start of selection */ - rawRow = startrow; - rawCol = startcol; - - } - /* else use old values in rawRow, Col */ - saveStartRRow = startERow = rawRow; - saveStartRCol = startECol = rawCol; - saveEndRRow = endERow = rawRow; - saveEndRCol = endECol = rawCol; - if (Coordinate(startrow, startcol) < Coordinate(rawRow, rawCol)) { - eventMode = LEFTEXTENSION; - startERow = startrow; - startECol = startcol; - } else { - eventMode = RIGHTEXTENSION; - endERow = startrow; - endECol = startcol; - } - ComputeSelect(startERow, startECol, endERow, endECol, False); -} - -static void -EndExtend(Widget w, - XEvent * event, /* must be XButtonEvent */ - String * params, /* selections */ - Cardinal num_params, - Bool use_cursor_loc) -{ - int row, col; - unsigned count; - TScreen *screen = &term->screen; - Char line[9]; - - if (use_cursor_loc) { - row = screen->cursor_row; - col = screen->cursor_col; - } else { - PointToRowCol(event->xbutton.y, event->xbutton.x, &row, &col); - } - ExtendExtend(row, col); - lastButtonUpTime = event->xbutton.time; - if (startSRow != endSRow || startSCol != endSCol) { - if (replyToEmacs) { - count = 0; - if (screen->control_eight_bits) { - line[count++] = CSI; - } else { - line[count++] = ESC; - line[count++] = '['; - } - if (rawRow == startSRow && rawCol == startSCol - && row == endSRow && col == endSCol) { - /* Use short-form emacs select */ - line[count++] = 't'; - line[count++] = ' ' + endSCol + 1; - line[count++] = ' ' + endSRow + 1; - } else { - /* long-form, specify everything */ - line[count++] = 'T'; - line[count++] = ' ' + startSCol + 1; - line[count++] = ' ' + startSRow + 1; - line[count++] = ' ' + endSCol + 1; - line[count++] = ' ' + endSRow + 1; - line[count++] = ' ' + col + 1; - line[count++] = ' ' + row + 1; - } - v_write(screen->respond, line, count); - TrackText(0, 0, 0, 0); - } - } - SelectSet(w, event, params, num_params); - eventMode = NORMAL; -} - -void -HandleSelectSet(Widget w, - XEvent * event, - String * params, - Cardinal *num_params) -{ - SelectSet(w, event, params, *num_params); -} - -/* ARGSUSED */ -static void -SelectSet(Widget w GCC_UNUSED, - XEvent * event GCC_UNUSED, - String * params, - Cardinal num_params) -{ - TRACE(("SelectSet\n")); - /* Only do select stuff if non-null select */ - if (startSRow != endSRow || startSCol != endSCol) { - SaltTextAway(startSRow, startSCol, endSRow, endSCol, - params, num_params); - } else { - DisownSelection(term); - } -} - -#define Abs(x) ((x) < 0 ? -(x) : (x)) - -/* ARGSUSED */ -static void -do_start_extend(Widget w, - XEvent * event, /* must be XButtonEvent* */ - String * params GCC_UNUSED, - Cardinal *num_params GCC_UNUSED, - Bool use_cursor_loc) -{ - TScreen *screen; - int row, col, coord; - - if (!IsXtermWidget(w)) - return; - - screen = &((XtermWidget) w)->screen; - if (SendMousePosition(w, event)) - return; - firstValidRow = 0; - lastValidRow = screen->max_row; -#if OPT_READLINE - if ((KeyModifiers & ShiftMask) - || event->xbutton.button != Button3 - || !(SCREEN_FLAG(screen, dclick3_deletes))) -#endif - selectUnit = EvalSelectUnit(event->xbutton.time, selectUnit); - replyToEmacs = False; - -#if OPT_READLINE - CheckSecondPress3(event); -#endif - - if (numberOfClicks == 1 - || (SCREEN_FLAG(screen, dclick3_deletes) /* Dclick special */ - &&!(KeyModifiers & ShiftMask))) { - /* Save existing selection so we can reestablish it if the guy - extends past the other end of the selection */ - saveStartRRow = startERow = startRRow; - saveStartRCol = startECol = startRCol; - saveEndRRow = endERow = endRRow; - saveEndRCol = endECol = endRCol; - } else { - /* He just needed the selection mode changed, use old values. */ - startERow = startRRow = saveStartRRow; - startECol = startRCol = saveStartRCol; - endERow = endRRow = saveEndRRow; - endECol = endRCol = saveEndRCol; - - } - if (use_cursor_loc) { - row = screen->cursor_row; - col = screen->cursor_col; - } else { - PointToRowCol(event->xbutton.y, event->xbutton.x, &row, &col); - } - coord = Coordinate(row, col); - - if (Abs(coord - Coordinate(startSRow, startSCol)) - < Abs(coord - Coordinate(endSRow, endSCol)) - || coord < Coordinate(startSRow, startSCol)) { - /* point is close to left side of selection */ - eventMode = LEFTEXTENSION; - startERow = row; - startECol = col; - } else { - /* point is close to left side of selection */ - eventMode = RIGHTEXTENSION; - endERow = row; - endECol = col; - } - ComputeSelect(startERow, startECol, endERow, endECol, True); - -#if OPT_READLINE - if (startSRow != endSRow || startSCol != endSCol) - ExtendingSelection = 1; -#endif -} - -static void -ExtendExtend(int row, int col) -{ - int coord = Coordinate(row, col); - - TRACE(("ExtendExtend row=%d, col=%d\n", row, col)); - if (eventMode == LEFTEXTENSION - && (coord + (selectUnit != SELECTCHAR)) > Coordinate(endSRow, endSCol)) { - /* Whoops, he's changed his mind. Do RIGHTEXTENSION */ - eventMode = RIGHTEXTENSION; - startERow = saveStartRRow; - startECol = saveStartRCol; - } else if (eventMode == RIGHTEXTENSION - && coord < Coordinate(startSRow, startSCol)) { - /* Whoops, he's changed his mind. Do LEFTEXTENSION */ - eventMode = LEFTEXTENSION; - endERow = saveEndRRow; - endECol = saveEndRCol; - } - if (eventMode == LEFTEXTENSION) { - startERow = row; - startECol = col; - } else { - endERow = row; - endECol = col; - } - ComputeSelect(startERow, startECol, endERow, endECol, False); - -#if OPT_READLINE - if (startSRow != endSRow || startSCol != endSCol) - ExtendingSelection = 1; -#endif -} - -void -HandleStartExtend(Widget w, - XEvent * event, /* must be XButtonEvent* */ - String * params, /* unused */ - Cardinal *num_params) /* unused */ -{ - do_start_extend(w, event, params, num_params, False); -} - -void -HandleKeyboardStartExtend(Widget w, - XEvent * event, /* must be XButtonEvent* */ - String * params, /* unused */ - Cardinal *num_params) /* unused */ -{ - do_start_extend(w, event, params, num_params, True); -} - -void -ScrollSelection(TScreen * screen, int amount, Bool always) -{ - int minrow = -screen->savedlines - screen->topline; - int maxrow = screen->max_row - screen->topline; - int maxcol = screen->max_col; - -#define scroll_update_one(row, col) \ - row += amount; \ - if (row < minrow) { \ - row = minrow; \ - col = 0; \ - } \ - if (row > maxrow) { \ - row = maxrow; \ - col = maxcol; \ - } - - scroll_update_one(startRRow, startRCol); - scroll_update_one(endRRow, endRCol); - scroll_update_one(startSRow, startSCol); - scroll_update_one(endSRow, endSCol); - - scroll_update_one(rawRow, rawCol); - - /* - * If we are told to scroll the selection but it lies outside the scrolling - * margins, then that could cause the selection to move (bad). It is not - * simple to fix, because this function is called both for the scrollbar - * actions as well as application scrolling. The 'always' flag is set in - * the former case. The rest of the logic handles the latter. - */ - if (ScrnHaveSelection(screen)) { - int adjust; - - adjust = screen->startHRow + screen->topline; - if (always - || !ScrnHaveLineMargins(screen) - || ScrnIsLineInMargins(screen, adjust)) { - scroll_update_one(screen->startHRow, screen->startHCol); - } - adjust = screen->endHRow + screen->topline; - if (always - || !ScrnHaveLineMargins(screen) - || ScrnIsLineInMargins(screen, adjust)) { - scroll_update_one(screen->endHRow, screen->endHCol); - } - } - - screen->startHCoord = Coordinate(screen->startHRow, screen->startHCol); - screen->endHCoord = Coordinate(screen->endHRow, screen->endHCol); -} - -/*ARGSUSED*/ -void -ResizeSelection(TScreen * screen GCC_UNUSED, int rows, int cols) -{ - rows--; /* decr to get 0-max */ - cols--; - - if (startRRow > rows) - startRRow = rows; - if (startSRow > rows) - startSRow = rows; - if (endRRow > rows) - endRRow = rows; - if (endSRow > rows) - endSRow = rows; - if (rawRow > rows) - rawRow = rows; - - if (startRCol > cols) - startRCol = cols; - if (startSCol > cols) - startSCol = cols; - if (endRCol > cols) - endRCol = cols; - if (endSCol > cols) - endSCol = cols; - if (rawCol > cols) - rawCol = cols; -} - -#if OPT_WIDE_CHARS -Bool -iswide(int i) -{ - return (i == HIDDEN_CHAR) || (my_wcwidth(i) == 2); -} - -#define isWideCell(row, col) iswide((int)XTERM_CELL(row, col)) -#endif - -static void -PointToRowCol(int y, - int x, - int *r, - int *c) -/* Convert pixel coordinates to character coordinates. - Rows are clipped between firstValidRow and lastValidRow. - Columns are clipped between to be 0 or greater, but are not clipped to some - maximum value. */ -{ - TScreen *screen = &term->screen; - int row, col; - - row = (y - screen->border) / FontHeight(screen); - if (row < firstValidRow) - row = firstValidRow; - else if (row > lastValidRow) - row = lastValidRow; - col = (x - OriginX(screen)) / FontWidth(screen); - if (col < 0) - col = 0; - else if (col > MaxCols(screen)) { - col = MaxCols(screen); - } -#if OPT_WIDE_CHARS - /* - * If we got a click on the right half of a doublewidth character, - * pretend it happened on the left half. - */ - if (col > 0 - && isWideCell(row, col - 1) - && (XTERM_CELL(row, col) == HIDDEN_CHAR)) { - col -= 1; - } -#endif - *r = row; - *c = col; -} - -static int -LastTextCol(int row) -{ - TScreen *screen = &term->screen; - int i; - Char *ch; - - if ((row += screen->topline) + screen->savedlines >= 0) { - for (i = screen->max_col, - ch = SCRN_BUF_ATTRS(screen, row) + i; - i >= 0 && !(*ch & CHARDRAWN); - ch--, i--) ; -#if OPT_DEC_CHRSET - if (CSET_DOUBLE(SCRN_BUF_CSETS(screen, row)[0])) { - i *= 2; - } -#endif - } else { - i = -1; - } - return (i); -} - -#if !OPT_WIDE_CHARS -/* -** double click table for cut and paste in 8 bits -** -** This table is divided in four parts : -** -** - control characters [0,0x1f] U [0x80,0x9f] -** - separators [0x20,0x3f] U [0xa0,0xb9] -** - binding characters [0x40,0x7f] U [0xc0,0xff] -** - exceptions -*/ -/* *INDENT-OFF* */ -static int charClass[256] = -{ -/* NUL SOH STX ETX EOT ENQ ACK BEL */ - 32, 1, 1, 1, 1, 1, 1, 1, -/* BS HT NL VT NP CR SO SI */ - 1, 32, 1, 1, 1, 1, 1, 1, -/* DLE DC1 DC2 DC3 DC4 NAK SYN ETB */ - 1, 1, 1, 1, 1, 1, 1, 1, -/* CAN EM SUB ESC FS GS RS US */ - 1, 1, 1, 1, 1, 1, 1, 1, -/* SP ! " # $ % & ' */ - 32, 33, 34, 35, 36, 37, 38, 39, -/* ( ) * + , - . / */ - 40, 41, 42, 43, 44, 45, 46, 47, -/* 0 1 2 3 4 5 6 7 */ - 48, 48, 48, 48, 48, 48, 48, 48, -/* 8 9 : ; < = > ? */ - 48, 48, 58, 59, 60, 61, 62, 63, -/* @ A B C D E F G */ - 64, 48, 48, 48, 48, 48, 48, 48, -/* H I J K L M N O */ - 48, 48, 48, 48, 48, 48, 48, 48, -/* P Q R S T U V W */ - 48, 48, 48, 48, 48, 48, 48, 48, -/* X Y Z [ \ ] ^ _ */ - 48, 48, 48, 91, 92, 93, 94, 48, -/* ` a b c d e f g */ - 96, 48, 48, 48, 48, 48, 48, 48, -/* h i j k l m n o */ - 48, 48, 48, 48, 48, 48, 48, 48, -/* p q r s t u v w */ - 48, 48, 48, 48, 48, 48, 48, 48, -/* x y z { | } ~ DEL */ - 48, 48, 48, 123, 124, 125, 126, 1, -/* x80 x81 x82 x83 IND NEL SSA ESA */ - 1, 1, 1, 1, 1, 1, 1, 1, -/* HTS HTJ VTS PLD PLU RI SS2 SS3 */ - 1, 1, 1, 1, 1, 1, 1, 1, -/* DCS PU1 PU2 STS CCH MW SPA EPA */ - 1, 1, 1, 1, 1, 1, 1, 1, -/* x98 x99 x9A CSI ST OSC PM APC */ - 1, 1, 1, 1, 1, 1, 1, 1, -/* - i c/ L ox Y- | So */ - 160, 161, 162, 163, 164, 165, 166, 167, -/* .. c0 ip << _ R0 - */ - 168, 169, 170, 171, 172, 173, 174, 175, -/* o +- 2 3 ' u q| . */ - 176, 177, 178, 179, 180, 181, 182, 183, -/* , 1 2 >> 1/4 1/2 3/4 ? */ - 184, 185, 186, 187, 188, 189, 190, 191, -/* A` A' A^ A~ A: Ao AE C, */ - 48, 48, 48, 48, 48, 48, 48, 48, -/* E` E' E^ E: I` I' I^ I: */ - 48, 48, 48, 48, 48, 48, 48, 48, -/* D- N~ O` O' O^ O~ O: X */ - 48, 48, 48, 48, 48, 48, 48, 215, -/* O/ U` U' U^ U: Y' P B */ - 48, 48, 48, 48, 48, 48, 48, 48, -/* a` a' a^ a~ a: ao ae c, */ - 48, 48, 48, 48, 48, 48, 48, 48, -/* e` e' e^ e: i` i' i^ i: */ - 48, 48, 48, 48, 48, 48, 48, 48, -/* d n~ o` o' o^ o~ o: -: */ - 48, 48, 48, 48, 48, 48, 48, 247, -/* o/ u` u' u^ u: y' P y: */ - 48, 48, 48, 48, 48, 48, 48, 48}; -/* *INDENT-ON* */ - -int -SetCharacterClassRange(int low, /* in range of [0..255] */ - int high, - int value) /* arbitrary */ -{ - - if (low < 0 || high > 255 || high < low) - return (-1); - - for (; low <= high; low++) - charClass[low] = value; - - return (0); -} -#endif - -#if OPT_WIDE_CHARS -static int -class_of(TScreen * screen, int row, int col) -{ - int value; -#if OPT_DEC_CHRSET - if (CSET_DOUBLE(SCRN_BUF_CSETS(screen, row + screen->topline)[0])) { - col /= 2; - } -#endif - value = XTERM_CELL(row, col); - if_OPT_WIDE_CHARS(screen, { - return CharacterClass(value); - }); - return CharacterClass(value); -} -#define ClassSelects(screen, row, col, cclass) \ - (class_of(screen, row, col) == cclass \ - || XTERM_CELL(row, col) == HIDDEN_CHAR) -#else -#define class_of(screen,row,col) charClass[XTERM_CELL(row, col)] -#define ClassSelects(screen, row, col, cclass) \ - (class_of(screen,row, col) == cclass) -#endif - -/* - * sets startSRow startSCol endSRow endSCol - * ensuring that they have legal values - */ -static void -ComputeSelect(int startRow, - int startCol, - int endRow, - int endCol, - Bool extend) -{ - TScreen *screen = &term->screen; - int length; - int cclass; - - TRACE(("ComputeSelect(startRow=%d, startCol=%d, endRow=%d, endCol=%d, %sextend)\n", - startRow, startCol, endRow, endCol, extend ? "" : "no")); - -#if OPT_WIDE_CHARS - if (startCol > 1 - && isWideCell(startRow, startCol - 1) - && XTERM_CELL(startRow, startCol - 0) == HIDDEN_CHAR) { - fprintf(stderr, "Adjusting start. Changing downwards from %i.\n", startCol); - startCol -= 1; - if (endCol == (startCol + 1)) - endCol--; - } - - if (endCol > 1 - && isWideCell(endRow, endCol - 1) - && XTERM_CELL(endRow, endCol) == HIDDEN_CHAR) { - endCol += 1; - } -#endif - - if (Coordinate(startRow, startCol) <= Coordinate(endRow, endCol)) { - startSRow = startRRow = startRow; - startSCol = startRCol = startCol; - endSRow = endRRow = endRow; - endSCol = endRCol = endCol; - } else { /* Swap them */ - startSRow = startRRow = endRow; - startSCol = startRCol = endCol; - endSRow = endRRow = startRow; - endSCol = endRCol = startCol; - } - - switch (selectUnit) { - case SELECTCHAR: - if (startSCol > (LastTextCol(startSRow) + 1)) { - startSCol = 0; - startSRow++; - } - if (endSCol > (LastTextCol(endSRow) + 1)) { - endSCol = 0; - endSRow++; - } - break; - case SELECTWORD: - if (startSCol > (LastTextCol(startSRow) + 1)) { - startSCol = 0; - startSRow++; - } else { - cclass = class_of(screen, startSRow, startSCol); - do { - --startSCol; - if (startSCol < 0 - && ScrnTstWrapped(screen, startSRow - 1)) { - --startSRow; - startSCol = LastTextCol(startSRow); - } - } while (startSCol >= 0 - && ClassSelects(screen, startSRow, startSCol, cclass)); - ++startSCol; - } - -#if OPT_WIDE_CHARS - if (startSCol && XTERM_CELL(startSRow, startSCol) == HIDDEN_CHAR) - startSCol++; -#endif - - if (endSCol > (LastTextCol(endSRow) + 1)) { - endSCol = 0; - endSRow++; - } else { - length = LastTextCol(endSRow); - cclass = class_of(screen, endSRow, endSCol); - do { - ++endSCol; - if (endSCol > length - && ScrnTstWrapped(screen, endSRow)) { - endSCol = 0; - ++endSRow; - length = LastTextCol(endSRow); - } - } while (endSCol <= length - && ClassSelects(screen, endSRow, endSCol, cclass)); - /* Word select selects if pointing to any char - in "word", especially in that it includes - the last character in a word. So no --endSCol - and do special eol handling */ - if (endSCol > length + 1) { - endSCol = 0; - ++endSRow; - } - } - -#if OPT_WIDE_CHARS - if (endSCol && XTERM_CELL(endSRow, endSCol) == HIDDEN_CHAR) - endSCol++; -#endif - - saveStartWRow = startSRow; - saveStartWCol = startSCol; - break; - case SELECTLINE: - while (ScrnTstWrapped(screen, endSRow)) { - ++endSRow; - } - if (term->screen.cutToBeginningOfLine - || startSRow < saveStartWRow) { - startSCol = 0; - while (ScrnTstWrapped(screen, startSRow - 1)) { - --startSRow; - } - } else if (!extend) { - if ((startRow < saveStartWRow) - || (startRow == saveStartWRow - && startCol < saveStartWCol)) { - startSCol = 0; - while (ScrnTstWrapped(screen, startSRow - 1)) { - --startSRow; - } - } else { - startSRow = saveStartWRow; - startSCol = saveStartWCol; - } - } - if (term->screen.cutNewline) { - endSCol = 0; - ++endSRow; - } else { - endSCol = LastTextCol(endSRow) + 1; - } - break; - } - - /* check boundaries */ - ScrollSelection(screen, 0, False); - - TrackText(startSRow, startSCol, endSRow, endSCol); - return; -} - -void -TrackText(int frow, - int fcol, - int trow, - int tcol) - /* Guaranteed (frow, fcol) <= (trow, tcol) */ -{ - int from, to; - TScreen *screen = &term->screen; - int old_startrow, old_startcol, old_endrow, old_endcol; - - TRACE(("TrackText(frow=%d, fcol=%d, trow=%d, tcol=%d)\n", - frow, fcol, trow, tcol)); - - old_startrow = screen->startHRow; - old_startcol = screen->startHCol; - old_endrow = screen->endHRow; - old_endcol = screen->endHCol; - if (frow == old_startrow && fcol == old_startcol && - trow == old_endrow && tcol == old_endcol) - return; - screen->startHRow = frow; - screen->startHCol = fcol; - screen->endHRow = trow; - screen->endHCol = tcol; - from = Coordinate(frow, fcol); - to = Coordinate(trow, tcol); - if (to <= screen->startHCoord || from > screen->endHCoord) { - /* No overlap whatsoever between old and new hilite */ - ReHiliteText(old_startrow, old_startcol, old_endrow, old_endcol); - ReHiliteText(frow, fcol, trow, tcol); - } else { - if (from < screen->startHCoord) { - /* Extend left end */ - ReHiliteText(frow, fcol, old_startrow, old_startcol); - } else if (from > screen->startHCoord) { - /* Shorten left end */ - ReHiliteText(old_startrow, old_startcol, frow, fcol); - } - if (to > screen->endHCoord) { - /* Extend right end */ - ReHiliteText(old_endrow, old_endcol, trow, tcol); - } else if (to < screen->endHCoord) { - /* Shorten right end */ - ReHiliteText(trow, tcol, old_endrow, old_endcol); - } - } - screen->startHCoord = from; - screen->endHCoord = to; -} - -static void -ReHiliteText(int frow, - int fcol, - int trow, - int tcol) - /* Guaranteed that (frow, fcol) <= (trow, tcol) */ -{ - TScreen *screen = &term->screen; - int i; - - TRACE(("ReHiliteText from %d.%d to %d.%d\n", frow, fcol, trow, tcol)); - - if (frow < 0) - frow = fcol = 0; - else if (frow > screen->max_row) - return; /* nothing to do, since trow >= frow */ - - if (trow < 0) - return; /* nothing to do, since frow <= trow */ - else if (trow > screen->max_row) { - trow = screen->max_row; - tcol = MaxCols(screen); - } - if (frow == trow && fcol == tcol) - return; - - if (frow != trow) { /* do multiple rows */ - if ((i = screen->max_col - fcol + 1) > 0) { /* first row */ - ScrnRefresh(screen, frow, fcol, 1, i, True); - } - if ((i = trow - frow - 1) > 0) { /* middle rows */ - ScrnRefresh(screen, frow + 1, 0, i, MaxCols(screen), True); - } - if (tcol > 0 && trow <= screen->max_row) { /* last row */ - ScrnRefresh(screen, trow, 0, 1, tcol, True); - } - } else { /* do single row */ - ScrnRefresh(screen, frow, fcol, 1, tcol - fcol, True); - } -} - -static void -SaltTextAway(int crow, int ccol, int row, int col, - String * params, /* selections */ - Cardinal num_params) - /* Guaranteed that (crow, ccol) <= (row, col), and that both points are valid - (may have row = screen->max_row+1, col = 0) */ -{ - TScreen *screen = &term->screen; - int i, j = 0; - int eol; - Char *line; - Char *lp; - - if (crow == row && ccol > col) { - int tmp = ccol; - ccol = col; - col = tmp; - } - - --col; - /* first we need to know how long the string is before we can save it */ - - if (row == crow) { - j = Length(screen, crow, ccol, col); - } else { /* two cases, cut is on same line, cut spans multiple lines */ - j += Length(screen, crow, ccol, screen->max_col) + 1; - for (i = crow + 1; i < row; i++) - j += Length(screen, i, 0, screen->max_col) + 1; - if (col >= 0) - j += Length(screen, row, 0, col); - } - - /* UTF-8 may require more space */ - if_OPT_WIDE_CHARS(screen, { - j *= 4; - }); - - /* now get some memory to save it in */ - - if (screen->selection_size <= j) { - if ((line = (Char *) malloc((unsigned) j + 1)) == 0) - SysError(ERROR_BMALLOC2); - XtFree((char *) screen->selection_data); - screen->selection_data = line; - screen->selection_size = j + 1; - } else { - line = screen->selection_data; - } - - if ((line == 0) - || (j < 0)) - return; - - line[j] = '\0'; /* make sure it is null terminated */ - lp = line; /* lp points to where to save the text */ - if (row == crow) { - lp = SaveText(screen, row, ccol, col, lp, &eol); - } else { - lp = SaveText(screen, crow, ccol, screen->max_col, lp, &eol); - if (eol) - *lp++ = '\n'; /* put in newline at end of line */ - for (i = crow + 1; i < row; i++) { - lp = SaveText(screen, i, 0, screen->max_col, lp, &eol); - if (eol) - *lp++ = '\n'; - } - if (col >= 0) - lp = SaveText(screen, row, 0, col, lp, &eol); - } - *lp = '\0'; /* make sure we have end marked */ - - TRACE(("Salted TEXT:%d:%.*s\n", lp - line, lp - line, line)); - screen->selection_length = (lp - line); - _OwnSelection(term, params, num_params); -} - -#if OPT_PASTE64 -void -ClearSelectionBuffer() -{ - TScreen *screen = &term->screen; - screen->selection_length = 0; - screen->base64_count = 0; -} - -static void -AppendStrToSelectionBuffer(Char * text, int len) -{ - TScreen *screen = &term->screen; - if (len != 0) { - int j = screen->selection_length + len; /* New length */ - int k = j + (j >> 2) + 80; /* New size if we grow buffer: grow by ~50% */ - if (j + 1 >= screen->selection_size) { - if (!screen->selection_length) { - /* New buffer */ - Char *line; - if ((line = (Char *) malloc((unsigned) k)) == 0) - SysError(ERROR_BMALLOC2); - XtFree((char *) screen->selection_data); - screen->selection_data = line; - } else { - /* Realloc buffer */ - screen->selection_data = (Char *) - realloc(screen->selection_data, - (unsigned) k); - if (screen->selection_data == 0) - SysError(ERROR_BMALLOC2); - } - screen->selection_size = k; - } - memcpy(screen->selection_data + screen->selection_length, text, len); - screen->selection_length += len; - screen->selection_data[screen->selection_length] = 0; - } -} - -void -AppendToSelectionBuffer(TScreen * screen, unsigned c) -{ - int six; - Char ch; - - /* Decode base64 character */ - if (c >= 'A' && c <= 'Z') - six = c - 'A'; - else if (c >= 'a' && c <= 'z') - six = c - 'a' + 26; - else if (c >= '0' && c <= '9') - six = c - '0' + 52; - else if (c == '+') - six = 62; - else if (c == '/') - six = 63; - else - return; - - /* Accumulate bytes */ - switch (screen->base64_count) { - case 0: - screen->base64_accu = six; - screen->base64_count = 6; - break; - - case 2: - ch = (screen->base64_accu << 6) + six; - screen->base64_count = 0; - AppendStrToSelectionBuffer(&ch, 1); - break; - - case 4: - ch = (screen->base64_accu << 4) + (six >> 2); - screen->base64_accu = (six & 0x3); - screen->base64_count = 2; - AppendStrToSelectionBuffer(&ch, 1); - break; - - case 6: - ch = (screen->base64_accu << 2) + (six >> 4); - screen->base64_accu = (six & 0xF); - screen->base64_count = 4; - AppendStrToSelectionBuffer(&ch, 1); - break; - } -} - -void -CompleteSelection(char **args, Cardinal len) -{ - term->screen.base64_count = 0; - term->screen.base64_accu = 0; - _OwnSelection(term, args, len); -} -#endif /* OPT_PASTE64 */ - -static Bool -_ConvertSelectionHelper(Widget w, - Atom * type, XtPointer *value, - unsigned long *length, int *format, - int (*conversion_function) (Display *, - char **, int, - XICCEncodingStyle, - XTextProperty *), - XICCEncodingStyle conversion_style) -{ - Display *d = XtDisplay(w); - TScreen *screen; - XTextProperty textprop; - - if (!IsXtermWidget(w)) - return False; - - screen = &((XtermWidget) w)->screen; - - if (conversion_function(d, (char **) &screen->selection_data, 1, - conversion_style, - &textprop) < Success) - return False; - *value = (XtPointer) textprop.value; - *length = textprop.nitems; - *type = textprop.encoding; - *format = textprop.format; - return True; -} - -static Boolean -ConvertSelection(Widget w, - Atom * selection, - Atom * target, - Atom * type, - XtPointer *value, - unsigned long *length, - int *format) -{ - Display *d = XtDisplay(w); - TScreen *screen; - Bool result = False; - - if (!IsXtermWidget(w)) - return False; - - screen = &((XtermWidget) w)->screen; - - if (screen->selection_data == NULL) - return False; /* can this happen? */ - - if (*target == XA_TARGETS(d)) { - Atom *targetP; - Atom *std_targets; - XPointer std_return = 0; - unsigned long std_length; - if (XmuConvertStandardSelection(w, screen->selection_time, selection, - target, type, &std_return, - &std_length, format)) { - std_targets = (Atom *) (std_return); - *length = std_length + 6; - targetP = (Atom *) XtMalloc(sizeof(Atom) * (*length)); - *value = (XtPointer) targetP; - *targetP++ = XA_STRING; - *targetP++ = XA_TEXT(d); -#ifdef X_HAVE_UTF8_STRING - *targetP++ = XA_COMPOUND_TEXT(d); - *targetP++ = XA_UTF8_STRING(d); -#else - *targetP = XA_COMPOUND_TEXT(d); - if_OPT_WIDE_CHARS(screen, { - *targetP = XA_UTF8_STRING(d); - }); - targetP++; -#endif - *targetP++ = XA_LENGTH(d); - *targetP++ = XA_LIST_LENGTH(d); - memcpy(targetP, std_targets, sizeof(Atom) * std_length); - XtFree((char *) std_targets); - *type = XA_ATOM; - *format = 32; - result = True; - } - } -#if OPT_WIDE_CHARS - else if (screen->wide_chars && *target == XA_STRING) { - result = - _ConvertSelectionHelper(w, - type, value, length, format, - Xutf8TextListToTextProperty, - XStringStyle); - } else if (screen->wide_chars && *target == XA_UTF8_STRING(d)) { - result = - _ConvertSelectionHelper(w, - type, value, length, format, - Xutf8TextListToTextProperty, - XUTF8StringStyle); - } else if (screen->wide_chars && *target == XA_TEXT(d)) { - result = - _ConvertSelectionHelper(w, - type, value, length, format, - Xutf8TextListToTextProperty, - XStdICCTextStyle); - } else if (screen->wide_chars && *target == XA_COMPOUND_TEXT(d)) { - result = - _ConvertSelectionHelper(w, - type, value, length, format, - Xutf8TextListToTextProperty, - XCompoundTextStyle); - } -#endif - - else if (*target == XA_STRING) { /* not wide_chars */ - /* We can only reach this point if the selection requestor - requested STRING before any of TEXT, COMPOUND_TEXT or - UTF8_STRING. We therefore assume that the requestor is not - properly internationalised, and dump raw eight-bit data - with no conversion into the selection. Yes, this breaks - the ICCCM in non-Latin-1 locales. */ - *type = XA_STRING; - *value = (XtPointer) screen->selection_data; - *length = screen->selection_length; - *format = 8; - result = True; - } else if (*target == XA_TEXT(d)) { /* not wide_chars */ - result = - _ConvertSelectionHelper(w, - type, value, length, format, - XmbTextListToTextProperty, - XStdICCTextStyle); - } else if (*target == XA_COMPOUND_TEXT(d)) { /* not wide_chars */ - result = - _ConvertSelectionHelper(w, - type, value, length, format, - XmbTextListToTextProperty, - XCompoundTextStyle); - } -#ifdef X_HAVE_UTF8_STRING - else if (*target == XA_UTF8_STRING(d)) { /* not wide_chars */ - result = - _ConvertSelectionHelper(w, - type, value, length, format, - XmbTextListToTextProperty, - XUTF8StringStyle); - } -#endif - else if (*target == XA_LIST_LENGTH(d)) { - *value = XtMalloc(4); - if (sizeof(long) == 4) - *(long *) *value = 1; - else { - long temp = 1; - memcpy((char *) *value, ((char *) &temp) + sizeof(long) - 4, 4); - } - *type = XA_INTEGER; - *length = 1; - *format = 32; - result = True; - } else if (*target == XA_LENGTH(d)) { - /* This value is wrong if we have UTF-8 text */ - *value = XtMalloc(4); - if (sizeof(long) == 4) { - *(long *) *value = screen->selection_length; - } else { - long temp = screen->selection_length; - memcpy((char *) *value, ((char *) &temp) + sizeof(long) - 4, 4); - } - *type = XA_INTEGER; - *length = 1; - *format = 32; - result = True; - } else if (XmuConvertStandardSelection(w, - screen->selection_time, selection, - target, type, (XPointer *) value, - length, format)) { - result = True; - } - - /* else */ - return result; -} - -static void -LoseSelection(Widget w, Atom * selection) -{ - TScreen *screen; - Atom *atomP; - Cardinal i; - - if (!IsXtermWidget(w)) - return; - - screen = &((XtermWidget) w)->screen; - for (i = 0, atomP = screen->selection_atoms; - i < screen->selection_count; i++, atomP++) { - if (*selection == *atomP) - *atomP = (Atom) 0; - if (CutBuffer(*atomP) >= 0) { - *atomP = (Atom) 0; - } - } - - for (i = screen->selection_count; i; i--) { - if (screen->selection_atoms[i - 1] != 0) - break; - } - screen->selection_count = i; - - for (i = 0, atomP = screen->selection_atoms; - i < screen->selection_count; i++, atomP++) { - if (*atomP == (Atom) 0) { - *atomP = screen->selection_atoms[--screen->selection_count]; - } - } - - if (screen->selection_count == 0) - TrackText(0, 0, 0, 0); -} - -/* ARGSUSED */ -static void -SelectionDone(Widget w GCC_UNUSED, - Atom * selection GCC_UNUSED, - Atom * target GCC_UNUSED) -{ - /* empty proc so Intrinsics know we want to keep storage */ -} - -static void -_OwnSelection(XtermWidget termw, - String * selections, - Cardinal count) -{ - Atom *atoms = termw->screen.selection_atoms; - Cardinal i; - Bool have_selection = False; - - if (termw->screen.selection_length < 0) - return; - - if (count > termw->screen.sel_atoms_size) { - XtFree((char *) atoms); - atoms = (Atom *) XtMalloc(count * sizeof(Atom)); - termw->screen.selection_atoms = atoms; - termw->screen.sel_atoms_size = count; - } - XmuInternStrings(XtDisplay((Widget) termw), selections, count, atoms); - for (i = 0; i < count; i++) { - int cutbuffer = CutBuffer(atoms[i]); - if (cutbuffer >= 0) { - if (termw->screen.selection_length > - 4 * XMaxRequestSize(XtDisplay((Widget) termw)) - 32) { - fprintf(stderr, - "%s: selection too big (%d bytes), not storing in CUT_BUFFER%d\n", - xterm_name, termw->screen.selection_length, cutbuffer); - } else { - /* This used to just use the UTF-8 data, which was totally - * broken as not even the corresponding paste code in Xterm - * understood this! So now it converts to Latin1 first. - * Robert Brady, 2000-09-05 - */ - unsigned long length = termw->screen.selection_length; - Char *data = termw->screen.selection_data; - if_OPT_WIDE_CHARS((&(termw->screen)), { - data = UTF8toLatin1(data, length, &length); - }); - TRACE(("XStoreBuffer(%d)\n", cutbuffer)); - XStoreBuffer(XtDisplay((Widget) termw), - (char *) data, - (int) length, - cutbuffer); - } - } else if (!replyToEmacs) { - have_selection |= - XtOwnSelection((Widget) termw, atoms[i], - termw->screen.selection_time, - ConvertSelection, LoseSelection, SelectionDone); - } - } - if (!replyToEmacs) - termw->screen.selection_count = count; - if (!have_selection) - TrackText(0, 0, 0, 0); -} - -static void -ResetSelectionState(TScreen * screen) -{ - screen->selection_count = 0; - screen->startHRow = screen->startHCol = 0; - screen->endHRow = screen->endHCol = 0; -} - -void -DisownSelection(XtermWidget termw) -{ - TScreen *screen = &(termw->screen); - Atom *atoms = screen->selection_atoms; - Cardinal count = screen->selection_count; - Cardinal i; - - TRACE(("DisownSelection count %d, start %d.%d, end %d.%d\n", - count, - screen->startHRow, - screen->startHCol, - screen->endHRow, - screen->endHCol)); - - for (i = 0; i < count; i++) { - int cutbuffer = CutBuffer(atoms[i]); - if (cutbuffer < 0) { - XtDisownSelection((Widget) termw, atoms[i], - screen->selection_time); - } - } - /* - * If none of the callbacks via XtDisownSelection() reset highlighting - * do it now. - */ - if (ScrnHaveSelection(screen)) { - /* save data which will be reset */ - int start_row = screen->startHRow; - int start_col = screen->startHCol; - int end_row = screen->endHRow; - int end_col = screen->endHCol; - - ResetSelectionState(screen); - ReHiliteText(start_row, start_col, end_row, end_col); - } else { - ResetSelectionState(screen); - } -} - -/* returns number of chars in line from scol to ecol out */ -/* ARGSUSED */ -static int -Length(TScreen * screen GCC_UNUSED, - int row, - int scol, - int ecol) -{ - int lastcol = LastTextCol(row); - - if (ecol > lastcol) - ecol = lastcol; - return (ecol - scol + 1); -} - -/* copies text into line, preallocated */ -static Char * -SaveText(TScreen * screen, - int row, - int scol, - int ecol, - Char * lp, /* pointer to where to put the text */ - int *eol) -{ - int i = 0; - unsigned c; - Char *result = lp; -#if OPT_WIDE_CHARS - int previous = 0; - unsigned c_1 = 0, c_2 = 0; -#endif - - i = Length(screen, row, scol, ecol); - ecol = scol + i; -#if OPT_DEC_CHRSET - if (CSET_DOUBLE(SCRN_BUF_CSETS(screen, row + screen->topline)[0])) { - scol = (scol + 0) / 2; - ecol = (ecol + 1) / 2; - } -#endif - *eol = !ScrnTstWrapped(screen, row); - for (i = scol; i < ecol; i++) { - c = E2A(XTERM_CELL(row, i)); -#if OPT_WIDE_CHARS - if (screen->utf8_mode != uFalse) { - c_1 = E2A(XTERM_CELL_C1(row, i)); - c_2 = E2A(XTERM_CELL_C2(row, i)); - } - - /* We want to strip out every occurrence of HIDDEN_CHAR AFTER a - * wide character. - */ - if (c == HIDDEN_CHAR && iswide(previous)) { - previous = c; - /* Combining characters attached to double-width characters - are in memory attached to the HIDDEN_CHAR */ - if (c_1) { - lp = convertToUTF8(lp, c_1); - if (c_2) - lp = convertToUTF8(lp, c_2); - } - continue; - } - previous = c; - if (screen->utf8_mode != uFalse) { - lp = convertToUTF8(lp, (c != 0) ? c : ' '); - if (c_1) { - lp = convertToUTF8(lp, c_1); - if (c_2) - lp = convertToUTF8(lp, c_2); - } - } else -#endif - { - if (c == 0) { - c = E2A(' '); - } else if (c < E2A(' ')) { - if (c == XPOUND) - c = 0x23; /* char on screen is pound sterling */ - else - c += 0x5f; /* char is from DEC drawing set */ - } else if (c == 0x7f) { - c = 0x5f; - } - *lp++ = A2E(c); - } - if (c != E2A(' ')) - result = lp; - } - - /* - * If requested, trim trailing blanks from selected lines. Do not do this - * if the line is wrapped. - */ - if (!*eol || !screen->trim_selection) - result = lp; - - return (result); -} - -/* 32 + following 7-bit word: - - 1:0 Button no: 0, 1, 2. 3=release. - 2 shift - 3 meta - 4 ctrl - 5 set for motion notify - 6 set for wheel -*/ - -/* Position: 32 - 255. */ - -static int -BtnCode(XButtonEvent * event, int button) -{ - int result = 32 + (KeyState(event->state) << 2); - - if (button < 0 || button > 5) { - result += 3; - } else { - if (button > 3) - result += (64 - 4); - if (event->type == MotionNotify) - result += 32; - result += button; - } - return result; -} - -#define MOUSE_LIMIT (255 - 32) - -static void -EditorButton(XButtonEvent * event) -{ - TScreen *screen = &term->screen; - int pty = screen->respond; - Char line[6]; - int row, col; - int button; - unsigned count = 0; - - /* If button event, get button # adjusted for DEC compatibility */ - button = event->button - 1; - if (button >= 3) - button++; - - /* Compute character position of mouse pointer */ - row = (event->y - screen->border) / FontHeight(screen); - col = (event->x - OriginX(screen)) / FontWidth(screen); - - /* Limit to screen dimensions */ - if (row < 0) - row = 0; - else if (row > screen->max_row) - row = screen->max_row; - else if (row > MOUSE_LIMIT) - row = MOUSE_LIMIT; - - if (col < 0) - col = 0; - else if (col > screen->max_col) - col = screen->max_col; - else if (col > MOUSE_LIMIT) - col = MOUSE_LIMIT; - - /* Build key sequence starting with \E[M */ - if (screen->control_eight_bits) { - line[count++] = CSI; - } else { - line[count++] = ESC; - line[count++] = '['; - } - line[count++] = 'M'; - - /* Add event code to key sequence */ - if (screen->send_mouse_pos == X10_MOUSE) { - line[count++] = ' ' + button; - } else { - /* Button-Motion events */ - switch (event->type) { - case ButtonPress: - line[count++] = BtnCode(event, screen->mouse_button = button); - break; - case ButtonRelease: - /* - * Wheel mouse interface generates release-events for buttons - * 4 and 5, coded here as 3 and 4 respectively. We change the - * release for buttons 1..3 to a -1. - */ - if (button < 3) - button = -1; - line[count++] = BtnCode(event, screen->mouse_button = button); - break; - case MotionNotify: - /* BTN_EVENT_MOUSE and ANY_EVENT_MOUSE modes send motion - * events only if character cell has changed. - */ - if ((row == screen->mouse_row) - && (col == screen->mouse_col)) - return; - line[count++] = BtnCode(event, screen->mouse_button); - break; - default: - return; - } - } - - screen->mouse_row = row; - screen->mouse_col = col; - - /* Add pointer position to key sequence */ - line[count++] = ' ' + col + 1; - line[count++] = ' ' + row + 1; - - TRACE(("mouse at %d,%d button+mask = %#x\n", row, col, - (screen->control_eight_bits) ? line[2] : line[3])); - - /* Transmit key sequence to process running under xterm */ - v_write(pty, line, count); -} - -/*ARGSUSED*/ -#if OPT_TEK4014 -void -HandleGINInput(Widget w GCC_UNUSED, - XEvent * event GCC_UNUSED, - String * param_list, - Cardinal *nparamsp) -{ - if (term->screen.TekGIN && *nparamsp == 1) { - int c = param_list[0][0]; - switch (c) { - case 'l': - case 'm': - case 'r': - case 'L': - case 'M': - case 'R': - break; - default: - Bell(XkbBI_MinorError, 0); /* let them know they goofed */ - c = 'l'; /* provide a default */ - } - TekEnqMouse(c | 0x80); - TekGINoff(); - } else { - Bell(XkbBI_MinorError, 0); - } -} -#endif /* OPT_TEK4014 */ - -/* ARGSUSED */ -void -HandleSecure(Widget w GCC_UNUSED, - XEvent * event, /* unused */ - String * params GCC_UNUSED, /* [0] = volume */ - Cardinal *param_count GCC_UNUSED) /* 0 or 1 */ -{ - Time ev_time = CurrentTime; - - if ((event->xany.type == KeyPress) || - (event->xany.type == KeyRelease)) - ev_time = event->xkey.time; - else if ((event->xany.type == ButtonPress) || - (event->xany.type == ButtonRelease)) - ev_time = event->xbutton.time; - DoSecureKeyboard(ev_time); -} |