home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / m / mxterm.zip / mxterm / button.c next >
C/C++ Source or Header  |  1992-10-17  |  39KB  |  1,462 lines

  1. /* $XConsortium: button.c,v 1.66 91/05/31 17:00:03 gildea Exp $ */
  2. /*
  3.  * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
  4.  *
  5.  *                         All Rights Reserved
  6.  *
  7.  * Permission to use, copy, modify, and distribute this software and its
  8.  * documentation for any purpose and without fee is hereby granted,
  9.  * provided that the above copyright notice appear in all copies and that
  10.  * both that copyright notice and this permission notice appear in
  11.  * supporting documentation, and that the name of Digital Equipment
  12.  * Corporation not be used in advertising or publicity pertaining to
  13.  * distribution of the software without specific, written prior permission.
  14.  *
  15.  *
  16.  * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  17.  * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  18.  * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  19.  * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  20.  * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  21.  * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  22.  * SOFTWARE.
  23.  */
  24.  
  25. /*
  26. button.c    Handles button events in the terminal emulator.
  27.         does cut/paste operations, change modes via menu,
  28.         passes button events through to some applications.
  29.                 J. Gettys.
  30. */
  31.  
  32. #include "ptyx.h"        /* Xlib headers included here. */
  33. #include <X11/Xatom.h>
  34. #include <stdio.h>
  35.  
  36. #include <X11/Xmu/Atoms.h>
  37. #include <X11/Xmu/StdSel.h>
  38.  
  39. #include "data.h"
  40. #include "error.h"
  41. #include "menu.h"
  42.  
  43. extern char *malloc();
  44.  
  45. extern void DoSecureKeyboard();
  46.  
  47. #define KeyState(x) (((x) & (ShiftMask|ControlMask)) + (((x) & Mod1Mask) ? 2 : 0))
  48.     /* adds together the bits:
  49.         shift key -> 1
  50.         meta key  -> 2
  51.         control key -> 4 */
  52.   
  53. #define TEXTMODES 4
  54. #define NBUTS 3
  55. #define DIRS 2
  56. #define UP 1
  57. #define DOWN 0
  58. #define SHIFTS 8        /* three keys, so eight combinations */
  59. #define    Coordinate(r,c)        ((r) * (term->screen.max_col+1) + (c))
  60.  
  61. extern char *xterm_name;
  62.  
  63. static void PointToRowCol();
  64. static void SelectionReceived();
  65. static void TrackDown();
  66. static void ComputeSelect();
  67. static void EditorButton();
  68. static void ExtendExtend();
  69. static void ReHiliteText();
  70. static void SelectSet();
  71. static void StartSelect();
  72. static int Length();
  73. static char *SaveText();
  74.  
  75. extern XtermWidget term;
  76.  
  77. /* Selection/extension variables */
  78.  
  79. /* Raw char position where the selection started */
  80. static int rawRow, rawCol;
  81.  
  82. /* Selected area before CHAR, WORD, LINE selectUnit processing */
  83. static int startRRow, startRCol, endRRow, endRCol = 0;
  84.  
  85. /* Selected area after CHAR, WORD, LINE selectUnit processing */
  86. static int startSRow, startSCol, endSRow, endSCol = 0;
  87.  
  88. /* Valid rows for selection clipping */
  89. static int firstValidRow, lastValidRow;
  90.  
  91. /* Start, end of extension */
  92. static int startERow, startECol, endERow, endECol;
  93.  
  94. /* Saved values of raw selection for extend to restore to */
  95. static int saveStartRRow, saveStartRCol, saveEndRRow, saveEndRCol;
  96.  
  97. /* Multi-click handling */
  98. static int numberOfClicks = 0;
  99. static long int lastButtonUpTime = 0;
  100. typedef int SelectUnit;
  101. #define SELECTCHAR 0
  102. #define SELECTWORD 1
  103. #define SELECTLINE 2
  104. #define NSELECTUNITS 3
  105. static SelectUnit selectUnit;
  106.  
  107. /* Send emacs escape code when done selecting or extending? */
  108. static int replyToEmacs;
  109.  
  110.  
  111. Boolean SendMousePosition(w, event)
  112. Widget w;
  113. XEvent* event;
  114. {
  115.     register TScreen *screen = &((XtermWidget)w)->screen;
  116.     
  117.     if (screen->send_mouse_pos == 0) return False;
  118.  
  119.     if (event->type != ButtonPress && event->type != ButtonRelease)
  120.     return False;
  121.  
  122. #define KeyModifiers \
  123.     (event->xbutton.state & (ShiftMask | LockMask | ControlMask | Mod1Mask | \
  124.                  Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask ))
  125.  
  126. #define ButtonModifiers \
  127.     (event->xbutton.state & (ShiftMask | LockMask | ControlMask | Mod1Mask | \
  128.                  Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask ))
  129.  
  130.     switch (screen->send_mouse_pos) {
  131.       case 1: /* X10 compatibility sequences */
  132.  
  133.     if (KeyModifiers == 0) {
  134.         if (event->type == ButtonPress)
  135.         EditorButton(event);
  136.         return True;
  137.     }
  138.     return False;
  139.  
  140.       case 2: /* DEC vt200 compatible */
  141.  
  142.     if (KeyModifiers == 0 || KeyModifiers == ControlMask) {
  143.         EditorButton(event);
  144.         return True;
  145.     }
  146.     return False;
  147.  
  148.       case 3: /* DEC vt200 hilite tracking */
  149.     if (  event->type == ButtonPress &&
  150.           KeyModifiers == 0 &&
  151.           event->xbutton.button == Button1 ) {
  152.         TrackDown(event);
  153.         return True;
  154.     }
  155.     if (KeyModifiers == 0 || KeyModifiers == ControlMask) {
  156.         EditorButton(event);
  157.         return True;
  158.     }
  159.     /* fall through */
  160.  
  161.       default:
  162.     return False;
  163.     }
  164. #undef KeyModifiers
  165. }
  166.  
  167.  
  168. /*ARGSUSED*/
  169. void HandleSelectExtend(w, event, params, num_params)
  170. Widget w;
  171. XEvent *event;            /* must be XMotionEvent */
  172. String *params;            /* unused */
  173. Cardinal *num_params;        /* unused */
  174. {
  175.     register TScreen *screen = &((XtermWidget)w)->screen;
  176.     int row, col;
  177.  
  178.     screen->selection_time = event->xmotion.time;
  179.     switch (eventMode) {
  180.         case LEFTEXTENSION :
  181.         case RIGHTEXTENSION :
  182.             PointToRowCol (event->xmotion.y, event->xmotion.x, 
  183.                        &row, &col);
  184.             ExtendExtend (row, col);
  185.             break;
  186.         case NORMAL :
  187.             /* will get here if send_mouse_pos != 0 */
  188.                 break;
  189.     }
  190. }
  191.  
  192. static void EndExtend();
  193.  
  194. static void do_select_end (w, event, params, num_params, use_cursor_loc)
  195. Widget w;
  196. XEvent *event;            /* must be XButtonEvent */
  197. String *params;            /* selections */
  198. Cardinal *num_params;
  199. Bool use_cursor_loc;
  200. {
  201.     ((XtermWidget)w)->screen.selection_time = event->xbutton.time;
  202.     switch (eventMode) {
  203.         case NORMAL :
  204.             (void) SendMousePosition(w, event);
  205.             break;
  206.         case LEFTEXTENSION :
  207.         case RIGHTEXTENSION :
  208.             EndExtend(w, event, params, *num_params, use_cursor_loc);
  209.             break;
  210.     }
  211. }
  212.  
  213.  
  214. void HandleSelectEnd(w, event, params, num_params)
  215. Widget w;
  216. XEvent *event;            /* must be XButtonEvent */
  217. String *params;            /* selections */
  218. Cardinal *num_params;
  219. {
  220.     do_select_end (w, event, params, num_params, False);
  221. }
  222.  
  223.  
  224. void HandleKeyboardSelectEnd(w, event, params, num_params)
  225. Widget w;
  226. XEvent *event;            /* must be XButtonEvent */
  227. String *params;            /* selections */
  228. Cardinal *num_params;
  229. {
  230.     do_select_end (w, event, params, num_params, True);
  231. }
  232.  
  233.  
  234.  
  235.  
  236. struct _SelectionList {
  237.     String *params;
  238.     Cardinal count;
  239.     Time time;
  240. };
  241.  
  242.  
  243. static void _GetSelection(w, time, params, num_params)
  244. Widget w;
  245. Time time;
  246. String *params;            /* selections in precedence order */
  247. Cardinal num_params;
  248. {
  249.     Atom selection;
  250.     int cutbuffer;
  251.  
  252.     XmuInternStrings(XtDisplay(w), params, (Cardinal)1, &selection);
  253.     switch (selection) {
  254.       case XA_CUT_BUFFER0: cutbuffer = 0; break;
  255.       case XA_CUT_BUFFER1: cutbuffer = 1; break;
  256.       case XA_CUT_BUFFER2: cutbuffer = 2; break;
  257.       case XA_CUT_BUFFER3: cutbuffer = 3; break;
  258.       case XA_CUT_BUFFER4: cutbuffer = 4; break;
  259.       case XA_CUT_BUFFER5: cutbuffer = 5; break;
  260.       case XA_CUT_BUFFER6: cutbuffer = 6; break;
  261.       case XA_CUT_BUFFER7: cutbuffer = 7; break;
  262.       default:           cutbuffer = -1;
  263.     }
  264.     if (cutbuffer >= 0) {
  265.     register TScreen *screen = &((XtermWidget)w)->screen;
  266.     int inbytes;
  267.     unsigned long nbytes;
  268.     int fmt8 = 8;
  269.     Atom type = XA_STRING;
  270.     char *line = XFetchBuffer(screen->display, &inbytes, cutbuffer);
  271.     nbytes = (unsigned long) inbytes;
  272.     if (nbytes > 0)
  273.         SelectionReceived(w, NULL, &selection, &type, (XtPointer)line,
  274.                   &nbytes, &fmt8);
  275.     else if (num_params > 1)
  276.         _GetSelection(w, time, params+1, num_params-1);
  277.     } else {
  278.     struct _SelectionList* list;
  279.     if (--num_params) {
  280.         list = XtNew(struct _SelectionList);
  281.         list->params = params + 1;
  282.         list->count = num_params; /* decremented above */
  283.         list->time = time;
  284.     } else list = NULL;
  285.     XtGetSelectionValue(w, selection, XA_STRING, SelectionReceived,
  286.                 (XtPointer)list, time);
  287.     }
  288. }
  289.  
  290. /* SelectionReceived: stuff received selection text into pty */
  291.  
  292. /* ARGSUSED */
  293. static void SelectionReceived(w, client_data, selection, type,
  294.                   value, length, format)
  295. Widget w;
  296. XtPointer client_data;
  297. Atom *selection, *type;
  298. XtPointer value;
  299. unsigned long *length;
  300. int *format;
  301. {
  302.     int pty = ((XtermWidget)w)->screen.respond;    /* file descriptor of pty */
  303.     register char *lag, *cp, *end;
  304.     char *line = (char*)value;
  305.                   
  306.     if (*type == 0 /*XT_CONVERT_FAIL*/ || *length == 0 || value == NULL) {
  307.     /* could not get this selection, so see if there are more to try */
  308.     struct _SelectionList* list = (struct _SelectionList*)client_data;
  309.     if (list != NULL) {
  310.         _GetSelection(w, list->time, list->params, list->count);
  311.         XtFree(client_data);
  312.     }
  313.     return;
  314.     }
  315.  
  316.     /* Write data to pty a line at a time. */
  317.     /* Doing this one line at a time may no longer be necessary
  318.        because v_write has been re-written. */
  319.  
  320.     end = &line[*length];
  321.     lag = line;
  322.     for (cp = line; cp != end; cp++)
  323.     {
  324.         if (*cp != '\n') continue;
  325.         *cp = '\r';
  326.         v_write(pty, lag, cp - lag + 1);
  327.         lag = cp + 1;
  328.     }
  329.     if (lag != end)
  330.     v_write(pty, lag, end - lag);
  331.  
  332.     XtFree(client_data);
  333.     XtFree(value);
  334. }
  335.  
  336.  
  337. void
  338. HandleInsertSelection(w, event, params, num_params)
  339. Widget w;
  340. XEvent *event;            /* assumed to be XButtonEvent* */
  341. String *params;            /* selections in precedence order */
  342. Cardinal *num_params;
  343. {
  344.     if (SendMousePosition(w, event)) return;
  345.     _GetSelection(w, event->xbutton.time, params, *num_params);
  346. }
  347.  
  348.  
  349. static void
  350. SetSelectUnit(buttonDownTime, defaultUnit)
  351.     unsigned long buttonDownTime;
  352.     SelectUnit defaultUnit;
  353. {
  354. /* Do arithmetic as integers, but compare as unsigned solves clock wraparound */
  355.     if ((long unsigned)((long int)buttonDownTime - lastButtonUpTime)
  356.      > term->screen.multiClickTime) {
  357.         numberOfClicks = 1;
  358.         selectUnit = defaultUnit;
  359.     } else {
  360.         ++numberOfClicks;
  361.         selectUnit = ((selectUnit + 1) % NSELECTUNITS);
  362.     }
  363. }
  364.  
  365. static void do_select_start (w, event, startrow, startcol)
  366. Widget w;
  367. XEvent *event;            /* must be XButtonEvent* */
  368. int startrow, startcol;
  369. {
  370.     if (SendMousePosition(w, event)) return;
  371.     SetSelectUnit(event->xbutton.time, SELECTCHAR);
  372.     replyToEmacs = FALSE;
  373.     StartSelect(startrow, startcol);
  374. }
  375.  
  376. /* ARGSUSED */
  377. void
  378. HandleSelectStart(w, event, params, num_params)
  379. Widget w;
  380. XEvent *event;            /* must be XButtonEvent* */
  381. String *params;            /* unused */
  382. Cardinal *num_params;        /* unused */
  383. {
  384.     register TScreen *screen = &((XtermWidget)w)->screen;
  385.     int startrow, startcol;
  386.  
  387.     firstValidRow = 0;
  388.     lastValidRow  = screen->max_row;
  389.     PointToRowCol(event->xbutton.y, event->xbutton.x, &startrow, &startcol);
  390.     do_select_start (w, event, startrow, startcol);
  391. }
  392.  
  393.  
  394. /* ARGSUSED */
  395. void
  396. HandleKeyboardSelectStart(w, event, params, num_params)
  397. Widget w;
  398. XEvent *event;            /* must be XButtonEvent* */
  399. String *params;            /* unused */
  400. Cardinal *num_params;        /* unused */
  401. {
  402.     register TScreen *screen = &((XtermWidget)w)->screen;
  403.  
  404.     do_select_start (w, event, screen->cursor_row, screen->cursor_col);
  405. }
  406.  
  407.  
  408. static void
  409. TrackDown(event)
  410.     register XButtonEvent *event;
  411. {
  412.     int startrow, startcol;
  413.  
  414.     SetSelectUnit(event->time, SELECTCHAR);
  415.     if (numberOfClicks > 1 ) {
  416.         PointToRowCol(event->y, event->x, &startrow, &startcol);
  417.         replyToEmacs = TRUE;
  418.         StartSelect(startrow, startcol);
  419.     } else {
  420.         waitingForTrackInfo = 1;
  421.         EditorButton(event);
  422.     }
  423. }
  424.  
  425.  
  426. #define boundsCheck(x)    if (x < 0) \
  427.                 x = 0; \
  428.             else if (x >= screen->max_row) \
  429.                 x = screen->max_row;
  430.  
  431. TrackMouse(func, startrow, startcol, firstrow, lastrow)
  432. int func, startrow, startcol, firstrow, lastrow;
  433. {
  434.     TScreen *screen = &term->screen;
  435.  
  436.     if (!waitingForTrackInfo) {    /* Timed out, so ignore */
  437.         return;
  438.     }
  439.     waitingForTrackInfo = 0;
  440.     if (func == 0) return;
  441.     boundsCheck (startrow)
  442.     boundsCheck (firstrow)
  443.     boundsCheck (lastrow)
  444.     firstValidRow = firstrow;
  445.     lastValidRow  = lastrow;
  446.     replyToEmacs = TRUE;
  447.     StartSelect(startrow, startcol);
  448. }
  449.  
  450. static void
  451. StartSelect(startrow, startcol)
  452.     int startrow, startcol;
  453. {
  454.     TScreen *screen = &term->screen;
  455.  
  456.     if (screen->cursor_state)
  457.         HideCursor ();
  458.     if (numberOfClicks == 1) {
  459.         /* set start of selection */
  460.         rawRow = startrow;
  461.         rawCol = startcol;
  462.         
  463.     } /* else use old values in rawRow, Col */
  464.  
  465.     saveStartRRow = startERow = rawRow;
  466.     saveStartRCol = startECol = rawCol;
  467.     saveEndRRow   = endERow   = rawRow;
  468.     saveEndRCol   = endECol   = rawCol;
  469.     if (Coordinate(startrow, startcol) < Coordinate(rawRow, rawCol)) {
  470.         eventMode = LEFTEXTENSION;
  471.         startERow = startrow;
  472.         startECol = startcol;
  473.     } else {
  474.         eventMode = RIGHTEXTENSION;
  475.         endERow = startrow;
  476.         endECol = startcol;
  477.     }
  478.     ComputeSelect(startERow, startECol, endERow, endECol, False);
  479.  
  480. }
  481.  
  482. static void
  483. EndExtend(w, event, params, num_params, use_cursor_loc)
  484.     Widget w;
  485.     XEvent *event;            /* must be XButtonEvent */
  486.     String *params;            /* selections */
  487.     Cardinal num_params;
  488.     Bool use_cursor_loc;
  489. {
  490.     int    row, col;
  491.     TScreen *screen = &term->screen;
  492.     char line[9];
  493.  
  494.     if (use_cursor_loc) {
  495.         row = screen->cursor_row;
  496.         col = screen->cursor_col;
  497.     } else {
  498.         PointToRowCol(event->xbutton.y, event->xbutton.x, &row, &col);
  499.     }
  500.     ExtendExtend (row, col);
  501.     lastButtonUpTime = event->xbutton.time;
  502.     if (startSRow != endSRow || startSCol != endSCol) {
  503.         if (replyToEmacs) {
  504.             if (rawRow == startSRow && rawCol == startSCol 
  505.                 && row == endSRow && col == endSCol) {
  506.                  /* Use short-form emacs select */
  507.                 strcpy(line, "\033[t");
  508.                 line[3] = ' ' + endSCol + 1;
  509.                 line[4] = ' ' + endSRow + 1;
  510.                 v_write(screen->respond, line, 5);
  511.             } else {
  512.                 /* long-form, specify everything */
  513.                 strcpy(line, "\033[T");
  514.                 line[3] = ' ' + startSCol + 1;
  515.                 line[4] = ' ' + startSRow + 1;
  516.                 line[5] = ' ' + endSCol + 1;
  517.                 line[6] = ' ' + endSRow + 1;
  518.                 line[7] = ' ' + col + 1;
  519.                 line[8] = ' ' + row + 1;
  520.                 v_write(screen->respond, line, 9);
  521.             }
  522.             TrackText(0, 0, 0, 0);
  523.         }
  524.     }
  525.     SelectSet(w, event, params, num_params);
  526.     eventMode = NORMAL;
  527. }
  528.  
  529. void
  530. HandleSelectSet(w, event, params, num_params)
  531.     Widget w;
  532.     XEvent *event;
  533.     String *params;
  534.     Cardinal *num_params;
  535. {
  536.     SelectSet (w, event, params, *num_params);
  537. }
  538.  
  539. static void SaltTextAway();
  540.  
  541. /* ARGSUSED */
  542. static void
  543. SelectSet (w, event, params, num_params)
  544.     Widget    w;
  545.     XEvent    *event;
  546.     String    *params;
  547.     Cardinal    num_params;
  548. {
  549.     /* Only do select stuff if non-null select */
  550.     if (startSRow != endSRow || startSCol != endSCol) {
  551.         SaltTextAway(startSRow, startSCol, endSRow, endSCol,
  552.                  params, num_params);
  553.     } else
  554.         DisownSelection(term);
  555. }
  556.  
  557. #define Abs(x)        ((x) < 0 ? -(x) : (x))
  558.  
  559. /* ARGSUSED */
  560. static void do_start_extend (w, event, params, num_params, use_cursor_loc)
  561. Widget w;
  562. XEvent *event;            /* must be XButtonEvent* */
  563. String *params;            /* unused */
  564. Cardinal *num_params;        /* unused */
  565. Bool use_cursor_loc;
  566. {
  567.     TScreen *screen = &((XtermWidget)w)->screen;
  568.     int row, col, coord;
  569.  
  570.     if (SendMousePosition(w, event)) return;
  571.     firstValidRow = 0;
  572.     lastValidRow  = screen->max_row;
  573.     SetSelectUnit(event->xbutton.time, selectUnit);
  574.     replyToEmacs = FALSE;
  575.  
  576.     if (numberOfClicks == 1) {
  577.         /* Save existing selection so we can reestablish it if the guy
  578.            extends past the other end of the selection */
  579.         saveStartRRow = startERow = startRRow;
  580.         saveStartRCol = startECol = startRCol;
  581.         saveEndRRow   = endERow   = endRRow;
  582.         saveEndRCol   = endECol   = endRCol;
  583.     } else {
  584.         /* He just needed the selection mode changed, use old values. */
  585.         startERow = startRRow = saveStartRRow;
  586.         startECol = startRCol = saveStartRCol;
  587.         endERow   = endRRow   = saveEndRRow;
  588.         endECol   = endRCol   = saveEndRCol;
  589.  
  590.     }
  591.     if (use_cursor_loc) {
  592.         row = screen->cursor_row;
  593.         col = screen->cursor_col;
  594.     } else {
  595.         PointToRowCol(event->xbutton.y, event->xbutton.x, &row, &col);
  596.     }
  597.     coord = Coordinate(row, col);
  598.  
  599.     if (Abs(coord - Coordinate(startSRow, startSCol))
  600.          < Abs(coord - Coordinate(endSRow, endSCol))
  601.         || coord < Coordinate(startSRow, startSCol)) {
  602.          /* point is close to left side of selection */
  603.         eventMode = LEFTEXTENSION;
  604.         startERow = row;
  605.         startECol = col;
  606.     } else {
  607.          /* point is close to left side of selection */
  608.         eventMode = RIGHTEXTENSION;
  609.         endERow = row;
  610.         endECol = col;
  611.     }
  612.     ComputeSelect(startERow, startECol, endERow, endECol, True);
  613. }
  614.  
  615. static void
  616. ExtendExtend (row, col)
  617.     int row, col;
  618. {
  619.     int coord = Coordinate(row, col);
  620.     
  621.     if (eventMode == LEFTEXTENSION 
  622.      && (coord + (selectUnit!=SELECTCHAR)) > Coordinate(endSRow, endSCol)) {
  623.         /* Whoops, he's changed his mind.  Do RIGHTEXTENSION */
  624.         eventMode = RIGHTEXTENSION;
  625.         startERow = saveStartRRow;
  626.         startECol = saveStartRCol;
  627.     } else if (eventMode == RIGHTEXTENSION
  628.      && coord < Coordinate(startSRow, startSCol)) {
  629.          /* Whoops, he's changed his mind.  Do LEFTEXTENSION */
  630.         eventMode = LEFTEXTENSION;
  631.         endERow   = saveEndRRow;
  632.         endECol   = saveEndRCol;
  633.     }
  634.     if (eventMode == LEFTEXTENSION) {
  635.         startERow = row;
  636.         startECol = col;
  637.     } else {
  638.         endERow = row;
  639.         endECol = col;
  640.     }
  641.     ComputeSelect(startERow, startECol, endERow, endECol, False);
  642. }
  643.  
  644.  
  645. void HandleStartExtend(w, event, params, num_params)
  646. Widget w;
  647. XEvent *event;            /* must be XButtonEvent* */
  648. String *params;            /* unused */
  649. Cardinal *num_params;        /* unused */
  650. {
  651.     do_start_extend (w, event, params, num_params, False);
  652. }
  653.  
  654. void HandleKeyboardStartExtend(w, event, params, num_params)
  655. Widget w;
  656. XEvent *event;            /* must be XButtonEvent* */
  657. String *params;            /* unused */
  658. Cardinal *num_params;        /* unused */
  659. {
  660.     do_start_extend (w, event, params, num_params, True);
  661. }
  662.  
  663.  
  664.  
  665.  
  666.  
  667. ScrollSelection(screen, amount)
  668. register TScreen* screen;
  669. register int amount;
  670. {
  671.     register int minrow = -screen->savedlines;
  672.  
  673.     /* Sent by scrollbar stuff, so amount never takes selection out of
  674.        saved text */
  675.  
  676.     /* XXX - the preceeding is false; cat /etc/termcap (or anything
  677.        larger than the number of saved lines plus the screen height) and then
  678.        hit extend select */
  679.  
  680.     startRRow += amount; endRRow += amount;
  681.     startSRow += amount; endSRow += amount;
  682.     rawRow += amount;
  683.     screen->startHRow += amount;
  684.     screen->endHRow += amount;
  685.  
  686.     if (startRRow < minrow) {
  687.     startRRow = minrow;
  688.     startRCol = 0;
  689.     }
  690.     if (endRRow < minrow) {
  691.     endRRow = minrow;
  692.         endRCol = 0;
  693.     }
  694.     if (startSRow < minrow) {
  695.     startSRow = minrow;
  696.     startSCol = 0;
  697.     }
  698.     if (endSRow < minrow) {
  699.     endSRow = minrow;
  700.     endSCol = 0;
  701.     }
  702.     if (rawRow < minrow) {
  703.     rawRow = minrow;
  704.     rawCol = 0;
  705.     }
  706.     if (screen->startHRow < minrow) {
  707.     screen->startHRow = minrow;
  708.     screen->startHCol = 0;
  709.     }
  710.     if (screen->endHRow < minrow) {
  711.     screen->endHRow = minrow;
  712.     screen->endHCol = 0;
  713.     }
  714.     screen->startHCoord = Coordinate (screen->startHRow, screen->startHCol);
  715.     screen->endHCoord = Coordinate (screen->endHRow, screen->endHCol);
  716. }
  717.  
  718.  
  719. /*ARGSUSED*/
  720. ResizeSelection (screen, rows, cols)
  721.     TScreen *screen;
  722.     int rows, cols;
  723. {
  724.     rows--;                /* decr to get 0-max */
  725.     cols--;
  726.  
  727.     if (startRRow > rows) startRRow = rows;
  728.     if (startSRow > rows) startSRow = rows;
  729.     if (endRRow > rows) endRRow = rows;
  730.     if (endSRow > rows) endSRow = rows;
  731.     if (rawRow > rows) rawRow = rows;
  732.  
  733.     if (startRCol > cols) startRCol = cols;
  734.     if (startSCol > cols) startSCol = cols;
  735.     if (endRCol > cols) endRCol = cols;
  736.     if (endSCol > cols) endSCol = cols;
  737.     if (rawCol > cols) rawCol = cols;
  738. }
  739.  
  740. static void
  741. PointToRowCol(y, x, r, c)
  742.     register int y, x;
  743.     int *r, *c;
  744. /* Convert pixel coordinates to character coordinates.
  745.    Rows are clipped between firstValidRow and lastValidRow.
  746.    Columns are clipped between to be 0 or greater, but are not clipped to some
  747.        maximum value. */
  748. {
  749.     register TScreen *screen = &term->screen;
  750.     register row, col;
  751.  
  752.     row = (y - screen->border) / FontHeight(screen);
  753.     if(row < firstValidRow)
  754.         row = firstValidRow;
  755.     else if(row > lastValidRow)
  756.         row = lastValidRow;
  757.     col = (x - screen->border - screen->scrollbar) / FontWidth(screen);
  758.     if(col < 0)
  759.         col = 0;
  760.     else if(col > screen->max_col+1) {
  761.         col = screen->max_col+1;
  762.     }
  763.     *r = row;
  764.     *c = col;
  765. }
  766.  
  767. static int
  768. LastTextCol(row)
  769.     register int row;
  770. {
  771.     register TScreen *screen =  &term->screen;
  772.     register int i;
  773.     register Char *ch;
  774.  
  775.     for ( i = screen->max_col,
  776.             ch = screen->buf[2 * (row + screen->topline) + 1] + i ;
  777.           i >= 0 && !(*ch & CHARDRAWN) ;
  778.           ch--, i--)
  779.         ;
  780.     return(i);
  781. }    
  782.  
  783. /*
  784. ** double click table for cut and paste in 8 bits
  785. **
  786. ** This table is divided in four parts :
  787. **
  788. **    - control characters    [0,0x1f] U [0x80,0x9f]
  789. **    - separators        [0x20,0x3f] U [0xa0,0xb9]
  790. **    - binding characters    [0x40,0x7f] U [0xc0,0xff]
  791. **      - execeptions
  792. */
  793. static int charClass[256] = {
  794. /* NUL  SOH  STX  ETX  EOT  ENQ  ACK  BEL */
  795.     32,   1,   1,   1,   1,   1,   1,   1,
  796. /*  BS   HT   NL   VT   NP   CR   SO   SI */
  797.      1,  32,   1,   1,   1,   1,   1,   1,
  798. /* DLE  DC1  DC2  DC3  DC4  NAK  SYN  ETB */
  799.      1,   1,   1,   1,   1,   1,   1,   1,
  800. /* CAN   EM  SUB  ESC   FS   GS   RS   US */
  801.      1,   1,   1,   1,   1,   1,   1,   1,
  802. /*  SP    !    "    #    $    %    &    ' */
  803.     32,  33,  34,  35,  36,  37,  38,  39,
  804. /*   (    )    *    +    ,    -    .    / */
  805.     40,  41,  42,  43,  44,  45,  46,  47,
  806. /*   0    1    2    3    4    5    6    7 */
  807.     48,  48,  48,  48,  48,  48,  48,  48,
  808. /*   8    9    :    ;    <    =    >    ? */
  809.     48,  48,  58,  59,  60,  61,  62,  63,
  810. /*   @    A    B    C    D    E    F    G */
  811.     64,  48,  48,  48,  48,  48,  48,  48,
  812. /*   H    I    J    K    L    M    N    O */
  813.     48,  48,  48,  48,  48,  48,  48,  48,
  814. /*   P    Q    R    S    T    U    V    W */ 
  815.     48,  48,  48,  48,  48,  48,  48,  48,
  816. /*   X    Y    Z    [    \    ]    ^    _ */
  817.     48,  48,  48,  91,  92,  93,  94,  48,
  818. /*   `    a    b    c    d    e    f    g */
  819.     96,  48,  48,  48,  48,  48,  48,  48,
  820. /*   h    i    j    k    l    m    n    o */
  821.     48,  48,  48,  48,  48,  48,  48,  48,
  822. /*   p    q    r    s    t    u    v    w */
  823.     48,  48,  48,  48,  48,  48,  48,  48,
  824. /*   x    y    z    {    |    }    ~  DEL */
  825.     48,  48,  48, 123, 124, 125, 126,   1,
  826. /* x80  x81  x82  x83  IND  NEL  SSA  ESA */
  827.      1,   1,   1,   1,   1,   1,   1,   1,
  828. /* HTS  HTJ  VTS  PLD  PLU   RI  SS2  SS3 */
  829.      1,   1,   1,   1,   1,   1,   1,   1,
  830. /* DCS  PU1  PU2  STS  CCH   MW  SPA  EPA */
  831.      1,   1,   1,   1,   1,   1,   1,   1,
  832. /* x98  x99  x9A  CSI   ST  OSC   PM  APC */
  833.      1,   1,   1,   1,   1,   1,   1,   1,
  834. /*   -    i   c/    L   ox   Y-    |   So */
  835.    160, 161, 162, 163, 164, 165, 166, 167,
  836. /*  ..   c0   ip   <<    _        R0    - */
  837.    168, 169, 170, 171, 172, 173, 174, 175,
  838. /*   o   +-    2    3    '    u   q|    . */
  839.    176, 177, 178, 179, 180, 181, 182, 183,
  840. /*   ,    1    2   >>  1/4  1/2  3/4    ? */
  841.    184, 185, 186, 187, 188, 189, 190, 191,
  842. /*  A`   A'   A^   A~   A:   Ao   AE   C, */
  843.     48,  48,  48,  48,  48,  48,  48,  48,
  844. /*  E`   E'   E^   E:   I`   I'   I^   I: */
  845.     48,  48,  48,  48,  48,  48,  48,  48,
  846. /*  D-   N~   O`   O'   O^   O~   O:    X */ 
  847.     48,  48,  48,  48,  48,  48,  48, 216,
  848. /*  O/   U`   U'   U^   U:   Y'    P    B */
  849.     48,  48,  48,  48,  48,  48,  48,  48,
  850. /*  a`   a'   a^   a~   a:   ao   ae   c, */
  851.     48,  48,  48,  48,  48,  48,  48,  48,
  852. /*  e`   e'   e^   e:    i`  i'   i^   i: */
  853.     48,  48,  48,  48,  48,  48,  48,  48,
  854. /*   d   n~   o`   o'   o^   o~   o:   -: */
  855.     48,  48,  48,  48,  48,  48,  48,  248,
  856. /*  o/   u`   u'   u^   u:   y'    P   y: */
  857.     48,  48,  48,  48,  48,  48,  48,  48};
  858.  
  859. int SetCharacterClassRange (low, high, value)
  860.     register int low, high;        /* in range of [0..255] */
  861.     register int value;            /* arbitrary */
  862. {
  863.  
  864.     if (low < 0 || high > 255 || high < low) return (-1);
  865.  
  866.     for (; low <= high; low++) charClass[low] = value;
  867.  
  868.     return (0);
  869. }
  870.  
  871. /*
  872.  * sets startSRow startSCol endSRow endSCol
  873.  * ensuring that they have legal values
  874.  */
  875.  
  876. static void
  877. ComputeSelect(startRow, startCol, endRow, endCol, extend)
  878.     int startRow, startCol, endRow, endCol;
  879.     Bool extend;
  880. {
  881.     register TScreen *screen = &term->screen;
  882.     register Char *ptr;
  883.     register int length;
  884.     register int class;
  885.     int osc = startSCol;
  886.  
  887.     if (Coordinate(startRow, startCol) <= Coordinate(endRow, endCol)) {
  888.         startSRow = startRRow = startRow;
  889.         startSCol = startRCol = startCol;
  890.         endSRow   = endRRow   = endRow;
  891.         endSCol   = endRCol   = endCol;
  892.     } else {    /* Swap them */
  893.         startSRow = startRRow = endRow;
  894.         startSCol = startRCol = endCol;
  895.         endSRow   = endRRow   = startRow;
  896.         endSCol   = endRCol   = startCol;
  897.     }    
  898.  
  899.     switch (selectUnit) {
  900.         case SELECTCHAR :
  901.             if (startSCol > (LastTextCol(startSRow) + 1)) {
  902.                 startSCol = 0;
  903.                 startSRow++;
  904.             }
  905.             if (endSCol > (LastTextCol(endSRow) + 1)) {
  906.                 endSCol = 0;
  907.                 endSRow++;
  908.             }
  909.             break;
  910.         case SELECTWORD :
  911.             if (startSCol > (LastTextCol(startSRow) + 1)) {
  912.                 startSCol = 0;
  913.                 startSRow++;
  914.             } else {
  915.                 ptr = screen->buf[2*(startSRow+screen->topline)]
  916.                  + startSCol;
  917.                 class = charClass[*ptr];
  918.                 do {
  919.                     --startSCol;
  920.                     --ptr;
  921.                 } while (startSCol >= 0
  922.                  && charClass[*ptr] == class);
  923.                 ++startSCol;
  924.             }
  925.             if (endSCol > (LastTextCol(endSRow) + 1)) {
  926.                 endSCol = 0;
  927.                 endSRow++;
  928.             } else {
  929.                 length = LastTextCol(endSRow);
  930.                 ptr = screen->buf[2*(endSRow+screen->topline)]
  931.                  + endSCol;
  932.                 class = charClass[*ptr];
  933.                 do {
  934.                     ++endSCol;
  935.                     ++ptr;
  936.                 } while (endSCol <= length
  937.                  && charClass[*ptr] == class);
  938.                 /* Word select selects if pointing to any char
  939.                    in "word", especially in that it includes
  940.                    the last character in a word.  So no --endSCol
  941.                    and do special eol handling */
  942.                 if (endSCol > length+1) {
  943.                     endSCol = 0;
  944.                     ++endSRow;
  945.                 }
  946.             }
  947.             break;
  948.         case SELECTLINE :
  949.             if (term->screen.cutToBeginningOfLine) {
  950.                 startSCol = 0;
  951.             } else if (!extend) {
  952.                 startSCol = osc;
  953.             }
  954.             if (term->screen.cutNewline) {
  955.                 endSCol = 0;
  956.                 ++endSRow;
  957.             } else {
  958.                 endSCol = LastTextCol(endSRow) + 1;
  959.             }
  960.             break;
  961.     }
  962.  
  963.     TrackText(startSRow, startSCol, endSRow, endSCol);
  964.     return;
  965. }
  966.  
  967.  
  968. TrackText(frow, fcol, trow, tcol)
  969.     register int frow, fcol, trow, tcol;
  970.     /* Guaranteed (frow, fcol) <= (trow, tcol) */
  971. {
  972.     register int from, to;
  973.     register TScreen *screen = &term->screen;
  974.     int old_startrow, old_startcol, old_endrow, old_endcol;
  975.  
  976.     old_startrow = screen->startHRow;
  977.     old_startcol = screen->startHCol;
  978.     old_endrow = screen->endHRow;
  979.     old_endcol = screen->endHCol;
  980.     if (frow == old_startrow && fcol == old_startcol &&
  981.         trow == old_endrow   && tcol == old_endcol) return;
  982.     screen->startHRow = frow;
  983.     screen->startHCol = fcol;
  984.     screen->endHRow   = trow;
  985.     screen->endHCol   = tcol;
  986.     from = Coordinate(frow, fcol);
  987.     to = Coordinate(trow, tcol);
  988.     if (to <= screen->startHCoord || from > screen->endHCoord) {
  989.         /* No overlap whatsoever between old and new hilite */
  990.         ReHiliteText(old_startrow, old_startcol, old_endrow, old_endcol);
  991.         ReHiliteText(frow, fcol, trow, tcol);
  992.     } else {
  993.         if (from < screen->startHCoord) {
  994.             /* Extend left end */
  995.             ReHiliteText(frow, fcol, old_startrow, old_startcol);
  996.         } else if (from > screen->startHCoord) {
  997.             /* Shorten left end */
  998.             ReHiliteText(old_startrow, old_startcol, frow, fcol);
  999.         }
  1000.         if (to > screen->endHCoord) {
  1001.             /* Extend right end */
  1002.             ReHiliteText(old_endrow, old_endcol, trow, tcol);
  1003.         } else if (to < screen->endHCoord) {
  1004.             /* Shorten right end */
  1005.             ReHiliteText(trow, tcol, old_endrow, old_endcol);
  1006.         }
  1007.     }
  1008.     screen->startHCoord = from;
  1009.     screen->endHCoord = to;
  1010. }
  1011.  
  1012. static void
  1013. ReHiliteText(frow, fcol, trow, tcol)
  1014.     register int frow, fcol, trow, tcol;
  1015.     /* Guaranteed that (frow, fcol) <= (trow, tcol) */
  1016. {
  1017.     register TScreen *screen = &term->screen;
  1018.     register int i;
  1019.  
  1020.     if (frow < 0)
  1021.         frow = fcol = 0;
  1022.     else if (frow > screen->max_row)
  1023.         return;        /* nothing to do, since trow >= frow */
  1024.  
  1025.     if (trow < 0)
  1026.         return;        /* nothing to do, since frow <= trow */
  1027.     else if (trow > screen->max_row) {
  1028.         trow = screen->max_row;
  1029.         tcol = screen->max_col+1;
  1030.     }
  1031.     if (frow == trow && fcol == tcol)
  1032.         return;
  1033.  
  1034.     if(frow != trow) {    /* do multiple rows */
  1035.         if((i = screen->max_col - fcol + 1) > 0) {     /* first row */
  1036.             ScrnRefresh(screen, frow, fcol, 1, i, True);
  1037.         }
  1038.         if((i = trow - frow - 1) > 0) {               /* middle rows*/
  1039.             ScrnRefresh(screen, frow+1, 0,i, screen->max_col+1, True);
  1040.         }
  1041.         if(tcol > 0 && trow <= screen->max_row) {      /* last row */
  1042.             ScrnRefresh(screen, trow, 0, 1, tcol, True);
  1043.         }
  1044.     } else {        /* do single row */
  1045.         ScrnRefresh(screen, frow, fcol, 1, tcol - fcol, True);
  1046.     }
  1047. }
  1048.  
  1049. static _OwnSelection();
  1050.  
  1051. static void
  1052. SaltTextAway(crow, ccol, row, col, params, num_params)
  1053.     /*register*/ int crow, ccol, row, col;
  1054.     String *params;            /* selections */
  1055.     Cardinal num_params;
  1056.     /* Guaranteed that (crow, ccol) <= (row, col), and that both points are valid
  1057.        (may have row = screen->max_row+1, col = 0) */
  1058. {
  1059.     register TScreen *screen = &term->screen;
  1060.     register int i, j = 0;
  1061.     int eol;
  1062.     char *line, *lp;
  1063.  
  1064.     if (crow == row && ccol > col) {
  1065.         int tmp = ccol;
  1066.         ccol = col;
  1067.         col = tmp;
  1068.     }
  1069.  
  1070.     --col;
  1071.     /* first we need to know how long the string is before we can save it*/
  1072.  
  1073.     if ( row == crow ) j = Length(screen, crow, ccol, col);
  1074.     else {    /* two cases, cut is on same line, cut spans multiple lines */
  1075.         j += Length(screen, crow, ccol, screen->max_col) + 1;
  1076.         for(i = crow + 1; i < row; i++) 
  1077.             j += Length(screen, i, 0, screen->max_col) + 1;
  1078.         if (col >= 0)
  1079.             j += Length(screen, row, 0, col);
  1080.     }
  1081.     
  1082.     /* now get some memory to save it in */
  1083.  
  1084.     if (screen->selection_size <= j) {
  1085.         if((line = malloc((unsigned) j + 1)) == (char *)NULL)
  1086.         SysError(ERROR_BMALLOC2);
  1087.         XtFree(screen->selection);
  1088.         screen->selection = line;
  1089.         screen->selection_size = j + 1;
  1090.     } else line = screen->selection;
  1091.     if (!line || j < 0) return;
  1092.  
  1093.     line[j] = '\0';        /* make sure it is null terminated */
  1094.     lp = line;        /* lp points to where to save the text */
  1095.     if ( row == crow ) lp = SaveText(screen, row, ccol, col, lp, &eol);
  1096.     else {
  1097.         lp = SaveText(screen, crow, ccol, screen->max_col, lp, &eol);
  1098.         if (eol)
  1099.             *lp ++ = '\n';    /* put in newline at end of line */
  1100.         for(i = crow +1; i < row; i++) {
  1101.             lp = SaveText(screen, i, 0, screen->max_col, lp, &eol);
  1102.             if (eol)
  1103.                 *lp ++ = '\n';
  1104.             }
  1105.         if (col >= 0)
  1106.             lp = SaveText(screen, row, 0, col, lp, &eol);
  1107.     }
  1108.     *lp = '\0';        /* make sure we have end marked */
  1109.     
  1110.     screen->selection_length = (lp - line);
  1111.     _OwnSelection(term, params, num_params);
  1112. }
  1113.  
  1114. static Boolean ConvertSelection(w, selection, target,
  1115.                 type, value, length, format)
  1116. Widget w;
  1117. Atom *selection, *target, *type;
  1118. XtPointer *value;
  1119. unsigned long *length;
  1120. int *format;
  1121. {
  1122.     Display* d = XtDisplay(w);
  1123.     XtermWidget xterm = (XtermWidget)w;
  1124.  
  1125.     if (xterm->screen.selection == NULL) return False; /* can this happen? */
  1126.  
  1127.     if (*target == XA_TARGETS(d)) {
  1128.     Atom* targetP;
  1129.     Atom* std_targets;
  1130.     unsigned long std_length;
  1131.     XmuConvertStandardSelection(
  1132.             w, xterm->screen.selection_time, selection,
  1133.             target, type, (caddr_t*)&std_targets, &std_length, format
  1134.            );
  1135.     *length = std_length + 5;
  1136.     *value = (XtPointer)XtMalloc(sizeof(Atom)*(*length));
  1137.     targetP = *(Atom**)value;
  1138.     *targetP++ = XA_STRING;
  1139.     *targetP++ = XA_TEXT(d);
  1140.     *targetP++ = XA_COMPOUND_TEXT(d);
  1141.     *targetP++ = XA_LENGTH(d);
  1142.     *targetP++ = XA_LIST_LENGTH(d);
  1143.     bcopy((char*)std_targets, (char*)targetP, sizeof(Atom)*std_length);
  1144.     XtFree((char*)std_targets);
  1145.     *type = XA_ATOM;
  1146.     *format = 32;
  1147.     return True;
  1148.     }
  1149.  
  1150.     if (*target == XA_STRING ||
  1151.     *target == XA_TEXT(d) ||
  1152.     *target == XA_COMPOUND_TEXT(d)) {
  1153.     if (*target == XA_COMPOUND_TEXT(d))
  1154.         *type = *target;
  1155.     else
  1156.         *type = XA_STRING;
  1157.     *value = xterm->screen.selection;
  1158.     *length = xterm->screen.selection_length;
  1159.     *format = 8;
  1160.     return True;
  1161.     }
  1162.     if (*target == XA_LIST_LENGTH(d)) {
  1163.     *value = XtMalloc(4);
  1164.     if (sizeof(long) == 4)
  1165.         *(long*)*value = 1;
  1166.     else {
  1167.         long temp = 1;
  1168.         bcopy( ((char*)&temp)+sizeof(long)-4, (char*)*value, 4);
  1169.     }
  1170.     *type = XA_INTEGER;
  1171.     *length = 1;
  1172.     *format = 32;
  1173.     return True;
  1174.     }
  1175.     if (*target == XA_LENGTH(d)) {
  1176.     *value = XtMalloc(4);
  1177.     if (sizeof(long) == 4)
  1178.         *(long*)*value = xterm->screen.selection_length;
  1179.     else {
  1180.         long temp = xterm->screen.selection_length;
  1181.         bcopy( ((char*)&temp)+sizeof(long)-4, (char*)*value, 4);
  1182.     }
  1183.     *type = XA_INTEGER;
  1184.     *length = 1;
  1185.     *format = 32;
  1186.     return True;
  1187.     }
  1188.     if (XmuConvertStandardSelection(w, xterm->screen.selection_time, selection,
  1189.                     target, type,
  1190.                     (caddr_t *)value, length, format))
  1191.     return True;
  1192.  
  1193.     /* else */
  1194.     return False;
  1195.  
  1196. }
  1197.  
  1198.  
  1199. static void LoseSelection(w, selection)
  1200.   Widget w;
  1201.   Atom *selection;
  1202. {
  1203.     register TScreen* screen = &((XtermWidget)w)->screen;
  1204.     register Atom* atomP;
  1205.     int i;
  1206.     for (i = 0, atomP = screen->selection_atoms;
  1207.      i < screen->selection_count; i++, atomP++)
  1208.     {
  1209.     if (*selection == *atomP) *atomP = (Atom)0;
  1210.     switch (*atomP) {
  1211.       case XA_CUT_BUFFER0:
  1212.       case XA_CUT_BUFFER1:
  1213.       case XA_CUT_BUFFER2:
  1214.       case XA_CUT_BUFFER3:
  1215.       case XA_CUT_BUFFER4:
  1216.       case XA_CUT_BUFFER5:
  1217.       case XA_CUT_BUFFER6:
  1218.       case XA_CUT_BUFFER7:    *atomP = (Atom)0;
  1219.     }
  1220.     }
  1221.  
  1222.     for (i = screen->selection_count; i; i--) {
  1223.     if (screen->selection_atoms[i-1] != 0) break;
  1224.     }
  1225.     screen->selection_count = i;
  1226.  
  1227.     for (i = 0, atomP = screen->selection_atoms;
  1228.      i < screen->selection_count; i++, atomP++)
  1229.     {
  1230.     if (*atomP == (Atom)0) {
  1231.         *atomP = screen->selection_atoms[--screen->selection_count];
  1232.     }
  1233.     }
  1234.  
  1235.     if (screen->selection_count == 0)
  1236.     TrackText(0, 0, 0, 0);
  1237. }
  1238.  
  1239.  
  1240. /* ARGSUSED */
  1241. static void SelectionDone(w, selection, target)
  1242. Widget w;
  1243. Atom *selection, *target;
  1244. {
  1245.     /* empty proc so Intrinsics know we want to keep storage */
  1246. }
  1247.  
  1248.  
  1249. static /* void */ _OwnSelection(termw, selections, count)
  1250.     register XtermWidget termw;
  1251.     String *selections;
  1252.     Cardinal count;
  1253. {
  1254.     Atom* atoms = termw->screen.selection_atoms;
  1255.     int i;
  1256.     Boolean have_selection = False;
  1257.  
  1258.     if (termw->screen.selection_length < 0) return;
  1259.  
  1260.     if (count > termw->screen.sel_atoms_size) {
  1261.     XtFree((char*)atoms);
  1262.     atoms = (Atom*)XtMalloc(count*sizeof(Atom));
  1263.     termw->screen.selection_atoms = atoms;
  1264.     termw->screen.sel_atoms_size = count;
  1265.     }
  1266.     XmuInternStrings( XtDisplay((Widget)termw), selections, count, atoms );
  1267.     for (i = 0; i < count; i++) {
  1268.     int cutbuffer;
  1269.     switch (atoms[i]) {
  1270.       case XA_CUT_BUFFER0: cutbuffer = 0; break;
  1271.       case XA_CUT_BUFFER1: cutbuffer = 1; break;
  1272.       case XA_CUT_BUFFER2: cutbuffer = 2; break;
  1273.       case XA_CUT_BUFFER3: cutbuffer = 3; break;
  1274.       case XA_CUT_BUFFER4: cutbuffer = 4; break;
  1275.       case XA_CUT_BUFFER5: cutbuffer = 5; break;
  1276.       case XA_CUT_BUFFER6: cutbuffer = 6; break;
  1277.       case XA_CUT_BUFFER7: cutbuffer = 7; break;
  1278.       default:           cutbuffer = -1;
  1279.     }
  1280.     if (cutbuffer >= 0)
  1281.         if ( termw->screen.selection_length >
  1282.          4*XMaxRequestSize(XtDisplay((Widget)termw))-32)
  1283.         fprintf(stderr,
  1284.             "%s: selection too big (%d bytes), not storing in CUT_BUFFER%d\n",
  1285.             xterm_name, termw->screen.selection_length, cutbuffer);
  1286.         else
  1287.         XStoreBuffer( XtDisplay((Widget)termw), termw->screen.selection,
  1288.                   termw->screen.selection_length, cutbuffer );
  1289.     else if (!replyToEmacs) {
  1290.         have_selection |=
  1291.         XtOwnSelection( (Widget)termw, atoms[i],
  1292.                 termw->screen.selection_time,
  1293.                 ConvertSelection, LoseSelection, SelectionDone );
  1294.     }
  1295.     }
  1296.     if (!replyToEmacs)
  1297.     termw->screen.selection_count = count;
  1298.     if (!have_selection)
  1299.     TrackText(0, 0, 0, 0);
  1300. }
  1301.  
  1302. /* void */
  1303. DisownSelection(termw)
  1304.     register XtermWidget termw;
  1305. {
  1306.     Atom* atoms = termw->screen.selection_atoms;
  1307.     Cardinal count = termw->screen.selection_count;
  1308.     int i;
  1309.  
  1310.     for (i = 0; i < count; i++) {
  1311.     int cutbuffer;
  1312.     switch (atoms[i]) {
  1313.       case XA_CUT_BUFFER0: cutbuffer = 0; break;
  1314.       case XA_CUT_BUFFER1: cutbuffer = 1; break;
  1315.       case XA_CUT_BUFFER2: cutbuffer = 2; break;
  1316.       case XA_CUT_BUFFER3: cutbuffer = 3; break;
  1317.       case XA_CUT_BUFFER4: cutbuffer = 4; break;
  1318.       case XA_CUT_BUFFER5: cutbuffer = 5; break;
  1319.       case XA_CUT_BUFFER6: cutbuffer = 6; break;
  1320.       case XA_CUT_BUFFER7: cutbuffer = 7; break;
  1321.       default:           cutbuffer = -1;
  1322.     }
  1323.     if (cutbuffer < 0)
  1324.         XtDisownSelection( (Widget)termw, atoms[i],
  1325.                    termw->screen.selection_time );
  1326.     }
  1327.     termw->screen.selection_count = 0;
  1328.     termw->screen.startHRow = termw->screen.startHCol = 0;
  1329.     termw->screen.endHRow = termw->screen.endHCol = 0;
  1330. }
  1331.  
  1332.  
  1333. /* returns number of chars in line from scol to ecol out */
  1334. /* ARGSUSED */
  1335. static int
  1336. Length(screen, row, scol, ecol)
  1337.     register int row, scol, ecol;
  1338.     register TScreen *screen;
  1339. {
  1340.         register int lastcol = LastTextCol(row);
  1341.  
  1342.     if (ecol > lastcol)
  1343.         ecol = lastcol;
  1344.     return (ecol - scol + 1);
  1345. }
  1346.  
  1347. /* copies text into line, preallocated */
  1348. static char *
  1349. SaveText(screen, row, scol, ecol, lp, eol)
  1350.     int row;
  1351.     int scol, ecol;
  1352.     TScreen *screen;
  1353.     register char *lp;        /* pointer to where to put the text */
  1354.     int *eol;
  1355. {
  1356.     register int i = 0;
  1357.     register Char *ch = screen->buf[2 * (row + screen->topline)];
  1358.     Char attr;
  1359.     register int c;
  1360.  
  1361.     *eol = 0;
  1362.     i = Length(screen, row, scol, ecol);
  1363.     ecol = scol + i;
  1364.     if (*eol == 0) {
  1365.         if(ScrnGetAttributes(screen, row + screen->topline, 0, &attr, 1) == 1) {
  1366.             *eol = (attr & LINEWRAPPED) ? 0 : 1;
  1367.         } else {
  1368.             /* If we can't get the attributes, assume no wrap */
  1369.             /* CANTHAPPEN */
  1370.             (void)fprintf(stderr, "%s: no attributes for %d, %d\n",
  1371.                 xterm_name, row, ecol - 1);
  1372.             *eol = 1;
  1373.         }
  1374.     }
  1375.     for (i = scol; i < ecol; i++) {
  1376.             c = ch[i];
  1377.         if (c == 0)
  1378.             c = ' ';
  1379.         else if(c < ' ') {
  1380.             if(c == '\036')
  1381.                 c = '#'; /* char on screen is pound sterling */
  1382.             else
  1383.                 c += 0x5f; /* char is from DEC drawing set */
  1384.         } else if(c == 0x7f)
  1385.             c = 0x5f;
  1386.         *lp++ = c;
  1387.     }
  1388.     return(lp);
  1389. }
  1390.  
  1391. static void
  1392. EditorButton(event)
  1393.     register XButtonEvent *event;
  1394. {
  1395.     register TScreen *screen = &term->screen;
  1396.     int pty = screen->respond;
  1397.     char line[6];
  1398.     register unsigned row, col;
  1399.     int button; 
  1400.  
  1401.     button = event->button - 1; 
  1402.  
  1403.     row = (event->y - screen->border) 
  1404.      / FontHeight(screen);
  1405.     col = (event->x - screen->border - screen->scrollbar)
  1406.      / FontWidth(screen);
  1407.     (void) strcpy(line, "\033[M");
  1408.     if (screen->send_mouse_pos == 1) {
  1409.         line[3] = ' ' + button;
  1410.     } else {
  1411.         line[3] = ' ' + (KeyState(event->state) << 2) + 
  1412.             ((event->type == ButtonPress)? button:3);
  1413.     }
  1414.     line[4] = ' ' + col + 1;
  1415.     line[5] = ' ' + row + 1;
  1416.     v_write(pty, line, 6);
  1417. }
  1418.  
  1419.  
  1420. /*ARGSUSED*/
  1421. void HandleGINInput (w, event, param_list, nparamsp)
  1422.     Widget w;
  1423.     XEvent *event;
  1424.     String *param_list;
  1425.     Cardinal *nparamsp;
  1426. {
  1427.     if (term->screen.TekGIN && *nparamsp == 1) {
  1428.     int c = param_list[0][0];
  1429.     switch (c) {
  1430.       case 'l': case 'm': case 'r':
  1431.       case 'L': case 'M': case 'R':
  1432.         break;
  1433.       default:
  1434.         Bell ();            /* let them know they goofed */
  1435.         c = 'l';            /* provide a default */
  1436.     }
  1437.     TekEnqMouse (c | 0x80);
  1438.     TekGINoff();
  1439.     } else {
  1440.     Bell ();
  1441.     }
  1442. }
  1443.  
  1444.  
  1445. /* ARGSUSED */
  1446. void HandleSecure(w, event, params, param_count)
  1447.     Widget w;
  1448.     XEvent *event;        /* unused */
  1449.     String *params;        /* [0] = volume */
  1450.     Cardinal *param_count;    /* 0 or 1 */
  1451. {
  1452.     Time time = CurrentTime;
  1453.  
  1454.     if ((event->xany.type == KeyPress) ||
  1455.     (event->xany.type == KeyRelease))
  1456.     time = event->xkey.time;
  1457.     else if ((event->xany.type == ButtonPress) ||
  1458.          (event->xany.type == ButtonRelease))
  1459.       time = event->xbutton.time;
  1460.     DoSecureKeyboard (time);
  1461. }
  1462.