~ubuntu-branches/ubuntu/hoary/kterm/hoary

« back to all changes in this revision

Viewing changes to button.c

  • Committer: Bazaar Package Importer
  • Author(s): ISHIKAWA Mutsumi
  • Date: 2002-02-15 00:30:40 UTC
  • Revision ID: james.westby@ubuntu.com-20020215003040-alhq02sirfiir6qy
Tags: upstream-6.2.0
ImportĀ upstreamĀ versionĀ 6.2.0

Show diffs side-by-side

added added

removed removed

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