|
|
1.1 ! root 1: /* ! 2: * $Source: /u1/X/xterm/RCS/button.c,v $ ! 3: * $Header: button.c,v 10.103 86/12/02 09:49:20 swick Exp $ ! 4: */ ! 5: ! 6: #include <X/mit-copyright.h> ! 7: ! 8: /* Copyright Massachusetts Institute of Technology 1984, 1985 */ ! 9: /* ! 10: button.c Handles button events in the terminal emulator. ! 11: does cut/paste operations, change modes via menu, ! 12: passes button events through to some applications. ! 13: J. Gettys. ! 14: */ ! 15: #ifndef lint ! 16: static char csrg_id[] = "@(#)button.c 1.6\t(Berkeley/CSRG)\t9/18/87"; ! 17: static char sccs_id[] = "@(#)button.c\tX10/6.6B\t12/26/86"; ! 18: #endif lint ! 19: #include <stdio.h> ! 20: #include <signal.h> ! 21: #include <setjmp.h> ! 22: #include <ctype.h> ! 23: #include <X/Xlib.h> ! 24: #include "scrollbar.h" ! 25: #include "ptyx.h" ! 26: #include "data.h" ! 27: #include "error.h" ! 28: #ifdef MODEMENU ! 29: #include "menu.h" ! 30: #endif MODEMENU ! 31: ! 32: #define NBUTS 3 ! 33: #define DIRS 2 ! 34: #define UP 1 ! 35: #define DOWN 0 ! 36: #define SHIFTS 8 /* three keys, so eight combinations */ ! 37: #define Coordinate(r,c) ((r) * ncols + (c)) ! 38: ! 39: char *GetRestOfLine(); ! 40: char *SaveText(); ! 41: extern UnSaltText(); ! 42: extern StartCut(); ! 43: extern ReExecute(); ! 44: extern EditorDown(); ! 45: ! 46: extern ButtonUp(); ! 47: extern DownButtonDown(); ! 48: extern MiddleButtonDown(); ! 49: extern UpButtonDown(); ! 50: extern ModeMenu(); ! 51: extern char *xterm_name; ! 52: extern Bogus(), Silence(); ! 53: extern GINbutton(); ! 54: /* due to LK201 limitations, not all of the below are actually possible */ ! 55: static int (*bfunc[SHIFTS][DIRS][NBUTS])() = { ! 56: /* left middle right */ ! 57: EditorDown, EditorDown, EditorDown, /* down | */ ! 58: Silence, Silence, Silence, /* up |no shift */ ! 59: ! 60: ReExecute, StartCut, Silence, /* down | */ ! 61: Silence, Silence, UnSaltText, /* up |shift */ ! 62: ! 63: EditorDown, EditorDown, EditorDown, /* down | */ ! 64: Silence, Silence, Silence, /* up |meta */ ! 65: ! 66: EditorDown, EditorDown, EditorDown, /* down | */ ! 67: Silence, Silence, Silence, /* up |meta shift */ ! 68: ! 69: ModeMenu, ModeMenu, ModeMenu, /* down | */ ! 70: Silence, Silence, Silence, /* up |control */ ! 71: ! 72: EditorDown, EditorDown, EditorDown, /* down | */ ! 73: Silence, Silence, Silence, /* up |ctl shift */ ! 74: ! 75: EditorDown, EditorDown, EditorDown, /* down | */ ! 76: Silence, Silence, Silence, /* up |no shift */ ! 77: ! 78: EditorDown, EditorDown, EditorDown, /* down | control */ ! 79: Silence, Silence, Silence /* up |meta shift*/ ! 80: ! 81: }; /* button, shift keys, and direction */ ! 82: static int (*tfunc[SHIFTS][DIRS][NBUTS])() = { ! 83: /* left middle right */ ! 84: ModeMenu, ModeMenu, ModeMenu, /* down | */ ! 85: Silence, Silence, Silence, /* up |no shift */ ! 86: ! 87: ModeMenu, ModeMenu, ModeMenu, /* down | */ ! 88: Silence, Silence, Silence, /* up |shift */ ! 89: ! 90: Bogus, Bogus, Bogus, /* down | */ ! 91: Silence, Silence, Silence, /* up |meta */ ! 92: ! 93: Bogus, Bogus, Bogus, /* down | */ ! 94: Silence, Silence, Silence, /* up |meta shift */ ! 95: ! 96: ModeMenu, ModeMenu, ModeMenu, /* down | */ ! 97: Silence, Silence, Silence, /* up |control */ ! 98: ! 99: ModeMenu, ModeMenu, ModeMenu, /* down | */ ! 100: Silence, Silence, Silence, /* up |ctl shift */ ! 101: ! 102: Bogus, Bogus, Bogus, /* down | */ ! 103: Silence, Silence, Silence, /* up |no shift */ ! 104: ! 105: Bogus, Bogus, Bogus, /* down | control */ ! 106: Silence, Silence, Silence /* up |meta shift*/ ! 107: ! 108: }; /* button, shift keys, and direction */ ! 109: static int (*scrollfunc[SHIFTS][DIRS][NBUTS])() = { ! 110: /* left middle right */ ! 111: DownButtonDown, ModeMenu, UpButtonDown, /* down | */ ! 112: ButtonUp, Silence, ButtonUp, /* up |no shift */ ! 113: ! 114: DownButtonDown, ModeMenu, UpButtonDown, /* down | */ ! 115: ButtonUp, Silence, ButtonUp, /* up |shift */ ! 116: ! 117: Bogus, Bogus, Bogus, /* down | */ ! 118: Silence, Silence, Silence, /* up |meta */ ! 119: ! 120: Bogus, Bogus, Bogus, /* down | */ ! 121: Silence, Silence, Silence, /* up |meta shift */ ! 122: ! 123: DownButtonDown, ModeMenu, UpButtonDown, /* down | */ ! 124: ButtonUp, Silence, ButtonUp, /* up |control */ ! 125: ! 126: Bogus, Bogus, Bogus, /* down | */ ! 127: Silence, Silence, Silence, /* up |ctl shift */ ! 128: ! 129: Bogus, Bogus, Bogus, /* down | */ ! 130: Silence, Silence, Silence, /* up |no shift */ ! 131: ! 132: Bogus, Bogus, Bogus, /* down | control */ ! 133: Silence, Silence, Silence /* up |meta shift*/ ! 134: ! 135: }; /* button, shift keys, and direction */ ! 136: static int (*Tbfunc[SHIFTS][DIRS][NBUTS])() = { ! 137: /* left middle right */ ! 138: GINbutton, GINbutton, GINbutton, /* down | */ ! 139: Silence, Silence, Silence, /* up |no shift */ ! 140: ! 141: GINbutton, GINbutton, GINbutton, /* down | */ ! 142: Silence, Silence, Silence, /* up |shift */ ! 143: ! 144: Bogus, Bogus, Bogus, /* down | */ ! 145: Silence, Silence, Silence, /* up |meta */ ! 146: ! 147: Bogus, Bogus, Bogus, /* down | */ ! 148: Silence, Silence, Silence, /* up |meta shift */ ! 149: ! 150: ModeMenu, ModeMenu, ModeMenu, /* down | */ ! 151: Silence, Silence, Silence, /* up |control */ ! 152: ! 153: Bogus, Bogus, Bogus, /* down | */ ! 154: Silence, Silence, Silence, /* up |ctl shift */ ! 155: ! 156: Bogus, Bogus, Bogus, /* down | */ ! 157: Silence, Silence, Silence, /* up |no shift */ ! 158: ! 159: Bogus, Bogus, Bogus, /* down | control */ ! 160: Silence, Silence, Silence /* up |meta shift*/ ! 161: ! 162: }; /* button, shift keys, and direction */ ! 163: ! 164: extern Terminal term; ! 165: ! 166: static int crow, ccol; /* cut row and column */ ! 167: static int ccoord; ! 168: static int ncols; ! 169: ! 170: HandleButtons(term, reply, pty) ! 171: register Terminal *term; ! 172: register XEvent *reply; ! 173: int pty; /* file descriptor of pty */ ! 174: { ! 175: register Screen *screen = &term->screen; ! 176: int (*bp)(); ! 177: int dir = DOWN; ! 178: /* so table above will be nice, we change left to right */ ! 179: int button = 2 - ((XKeyOrButtonEvent *)reply)->detail & 0177; ! 180: int shift = KeyState(((XKeyOrButtonEvent *)reply)->detail); ! 181: ! 182: switch (reply->type) { ! 183: case ButtonPressed: ! 184: dir = DOWN; ! 185: break; ! 186: case ButtonReleased: ! 187: dir = UP; ! 188: break; ! 189: default: ! 190: break; ! 191: } ! 192: if(L_flag && !checklogin()) { /* if login window, check for login */ ! 193: if(dir == DOWN) ! 194: Bell(); ! 195: return; ! 196: } ! 197: bp = (screen->sb && (reply->window == screen->sb->bar || ! 198: GetButtonState(screen->sb) != BUTTON_NORMAL)) ? ! 199: scrollfunc[shift][dir][button] : ! 200: ((Titlebar(screen) && (reply->window == screen->title.tbar || ! 201: reply->window == screen->Ttitle.tbar)) ? tfunc[shift][dir][button] : ! 202: ((reply->window == TWindow(screen)) ? Tbfunc[shift][dir][button] : ! 203: bfunc[shift][dir][button])); ! 204: if (bp != NULL) ! 205: (*bp)(term, reply, pty); ! 206: else ! 207: Bell(); ! 208: } ! 209: ! 210: UnSaltText(term, reply, pty) ! 211: register Terminal *term; ! 212: register XKeyOrButtonEvent *reply; ! 213: int pty; /* file descriptor of pty */ ! 214: { ! 215: char *line; ! 216: int nbytes; ! 217: register char *lag, *cp, *end; ! 218: ! 219: line = XFetchBytes(&nbytes); ! 220: end = &line[nbytes]; ! 221: lag = line; ! 222: for (cp = line; cp != end; cp++) ! 223: { ! 224: if (*cp != '\n') continue; ! 225: *cp = '\r'; ! 226: write(pty, lag, cp - lag + 1); ! 227: lag = cp + 1; ! 228: } ! 229: if (lag != end) ! 230: write(pty, lag, end - lag); ! 231: free (line); /* free text from fetch */ ! 232: } ! 233: ! 234: ReExecute(term, reply, pty) ! 235: register XKeyOrButtonEvent *reply; ! 236: Terminal *term; ! 237: int pty; ! 238: { ! 239: XKeyOrButtonEvent xevent; ! 240: register XKeyOrButtonEvent *ev = &xevent; ! 241: register Screen *screen = &term->screen; ! 242: register int xrow, xcol, mask, cursor, ignore; ! 243: register char *line; ! 244: int row, col; ! 245: ! 246: cursor = screen->curs; ! 247: if(!XGrabMouse(VWindow(screen), cursor, ! 248: mask = ButtonReleased | EnterWindow | LeaveWindow | MouseMoved)) { ! 249: Bell(); ! 250: return; ! 251: } ! 252: ncols = screen->max_col + 1; /* needed by Coordinate() define */ ! 253: if(NearestRowCol(reply->y, reply->x, &crow, &ccol) || ! 254: crow > screen->max_row) { ! 255: Bell(); ! 256: XUngrabMouse(); ! 257: return; ! 258: } ! 259: xrow = crow; ! 260: xcol = ccol; ! 261: crow++; ! 262: ccol = 0; ! 263: ccoord = Coordinate(crow, ccol); ! 264: if (screen->cursor_state) ! 265: HideCursor (); ! 266: HiliteText(xrow, xcol, crow, 0, TRUE); ! 267: ignore = FALSE; ! 268: for( ; ; ) { ! 269: XMaskEvent(mask, ev); ! 270: switch(ev->type) { ! 271: case ButtonReleased: ! 272: if(xrow == crow - 1) { ! 273: line = GetRestOfLine(screen, xrow, xcol); ! 274: row = strlen(line); ! 275: write(pty, line, row); ! 276: line[row] = '\n'; ! 277: XStoreBytes(line, row); ! 278: free (line); /* free text from fetch */ ! 279: HiliteText(xrow, xcol, crow, 0, FALSE); ! 280: } ! 281: XUngrabMouse(); ! 282: if (screen->cursor_set && !screen->cursor_state) ! 283: ShowCursor (); ! 284: return; ! 285: case LeaveWindow: ! 286: if(ev->window != VWindow(screen)) ! 287: break; ! 288: if(xrow == crow - 1) ! 289: HiliteText(xrow, xcol, crow, 0, FALSE); ! 290: xrow = crow; ! 291: xcol = 0; ! 292: XGrabMouse(VWindow(screen), cursor, mask & ~MouseMoved); ! 293: ignore = TRUE; ! 294: break; ! 295: case EnterWindow: ! 296: if(ev->window != VWindow(screen)) ! 297: break; ! 298: XGrabMouse(VWindow(screen), cursor, mask); ! 299: ignore = FALSE; ! 300: /* drop through */ ! 301: case MouseMoved: ! 302: if(ignore) ! 303: break; ! 304: NearestRowCol(ev->y, ev->x, &row, &col); ! 305: if(row != crow - 1) { ! 306: if(xrow == crow - 1) ! 307: HiliteText(xrow, xcol, crow, 0, FALSE); ! 308: } else if(xrow == row) ! 309: TrackText(xrow, xcol, row, col); ! 310: else ! 311: HiliteText(row, col, crow, 0, TRUE); ! 312: xrow = row; ! 313: xcol = col; ! 314: break; ! 315: } ! 316: } ! 317: } ! 318: ! 319: char *GetRestOfLine(screen, row, col) ! 320: register Screen *screen; ! 321: register int row, col; ! 322: { ! 323: char *line; ! 324: int i; ! 325: ! 326: i = Length(screen, row, col, screen->max_col); ! 327: if((line = (char *)malloc(i + 2)) == NULL) ! 328: SysError(ERROR_BMALLOC); ! 329: SaveText(screen, row, col, screen->max_col, line); ! 330: line[i] = '\r'; ! 331: line[i+1] = '\0'; ! 332: return(line); ! 333: } ! 334: ! 335: StartCut(term, reply, pty) ! 336: register XKeyOrButtonEvent *reply; ! 337: Terminal *term; ! 338: int pty; ! 339: { ! 340: XKeyOrButtonEvent xevent; ! 341: register XKeyOrButtonEvent *ev = &xevent; ! 342: register Screen *screen = &term->screen; ! 343: register int xrow, xcol, mask, cursor, ignore; ! 344: int row, col; ! 345: ! 346: cursor = screen->curs; ! 347: if(!XGrabMouse(VWindow(screen), cursor, ! 348: mask = ButtonReleased | EnterWindow | LeaveWindow | MouseMoved)) { ! 349: Bell(); ! 350: return; ! 351: } ! 352: ncols = screen->max_col + 1; /* needed by Coordinate() define */ ! 353: NearestRowCol(reply->y, reply->x, &crow, &ccol); ! 354: ccoord = Coordinate(crow, ccol); ! 355: xrow = crow; ! 356: xcol = ccol; ! 357: ignore = FALSE; ! 358: if (screen->cursor_state) ! 359: HideCursor (); ! 360: for( ; ; ) { ! 361: XMaskEvent(mask, ev); ! 362: switch(ev->type) { ! 363: case ButtonReleased: ! 364: if(!ignore) { ! 365: row = crow; ! 366: col = ccol; /* SaltTextAway may alter these */ ! 367: SaltTextAway(term, xrow, xcol, pty); ! 368: } ! 369: HiliteText(row, col, xrow, xcol, FALSE); ! 370: XUngrabMouse(); ! 371: if (screen->cursor_set && !screen->cursor_state) ! 372: ShowCursor (); ! 373: return; ! 374: case LeaveWindow: ! 375: if(ev->window != VWindow(screen)) ! 376: break; ! 377: HiliteText(crow, ccol, xrow, xcol, FALSE); ! 378: xrow = crow; ! 379: xcol = ccol; ! 380: XGrabMouse(VWindow(screen), cursor, mask & ~MouseMoved); ! 381: ignore = TRUE; ! 382: break; ! 383: case EnterWindow: ! 384: if(ev->window != VWindow(screen)) ! 385: break; ! 386: XGrabMouse(VWindow(screen), cursor, mask); ! 387: ignore = FALSE; ! 388: /* drop through */ ! 389: case MouseMoved: ! 390: if(ignore) ! 391: break; ! 392: NearestRowCol(ev->y, ev->x, &row, &col); ! 393: if(row != xrow || col != xcol) { ! 394: TrackText(xrow, xcol, row, col); ! 395: xrow = row; ! 396: xcol = col; ! 397: } ! 398: break; ! 399: } ! 400: } ! 401: } ! 402: ! 403: int NearestRowCol(y, x, r, c) ! 404: register int y, x; ! 405: int *r, *c; ! 406: { ! 407: register Screen *screen = &term.screen; ! 408: register row, col, i; ! 409: register char *ch; ! 410: register int passed_eol = FALSE; ! 411: ! 412: if((row = (y - screen->border - Titlebar(screen)) / FontHeight(screen)) ! 413: < 0) ! 414: row = 0; ! 415: else if(row > screen->max_row) ! 416: row = screen->max_row; ! 417: i = FontWidth(screen); ! 418: if((col = (x - screen->border + (i / 3)) / i) < 0) ! 419: col = 0; ! 420: else if(col > screen->max_col) { ! 421: col = 0; ! 422: row++; /* this can be screen->max_row + 1 */ ! 423: passed_eol = TRUE; ! 424: } ! 425: if(col > 0) { ! 426: for(i = screen->max_col, ! 427: ch = screen->buf[2 * (row + screen->topline)] + i ; ! 428: i > 0 && *ch == 0 ; ch--, i--); ! 429: if(col > i + 1) { ! 430: col = 0; ! 431: row++; ! 432: passed_eol = TRUE; ! 433: } ! 434: } ! 435: *r = row; ! 436: *c = col; ! 437: return(passed_eol); ! 438: } ! 439: ! 440: TrackText(frow, fcol, trow, tcol) ! 441: register int frow, fcol, trow, tcol; ! 442: { ! 443: register int f, t; ! 444: ! 445: f = Coordinate(frow, fcol); ! 446: t = Coordinate(trow, tcol); ! 447: if(f == t) ! 448: return; ! 449: if(f > ccoord) { ! 450: if(t < ccoord) { ! 451: HiliteText(crow, ccol, frow, fcol, FALSE); ! 452: HiliteText(trow, tcol, crow, ccol, TRUE); ! 453: } else if(t > f) ! 454: HiliteText(frow, fcol, trow, tcol, TRUE); ! 455: else ! 456: HiliteText(trow, tcol, frow, fcol, FALSE); ! 457: } else { ! 458: if(t > ccoord) { ! 459: HiliteText(frow, fcol, crow, ccol, FALSE); ! 460: HiliteText(crow, ccol, trow, tcol, TRUE); ! 461: } else if(t < f) ! 462: HiliteText(trow, tcol, frow, fcol, TRUE); ! 463: else ! 464: HiliteText(frow, fcol, trow, tcol, FALSE); ! 465: } ! 466: } ! 467: ! 468: HiliteText(frow, fcol, trow, tcol, hilite) ! 469: register int frow, fcol, trow, tcol; ! 470: int hilite; ! 471: { ! 472: register Screen *screen = &term.screen; ! 473: register int i, j; ! 474: ! 475: if((i = Coordinate(frow, fcol)) == (j = Coordinate(trow, tcol))) ! 476: return; ! 477: else if(i > j) { ! 478: i = frow; ! 479: j = fcol; ! 480: frow = trow; ! 481: fcol = tcol; ! 482: trow = i; ! 483: tcol = j; ! 484: } ! 485: if(hilite) { ! 486: i = screen->foreground; ! 487: screen->foreground = screen->background; ! 488: screen->background = i; ! 489: } ! 490: if(frow != trow) { /* do multiple rows */ ! 491: if((i = screen->max_col - fcol + 1) > 0) { /* first row */ ! 492: XPixSet(VWindow(screen), fcol * FontWidth(screen) + ! 493: screen->border, frow * FontHeight(screen) + ! 494: screen->border + Titlebar(screen), i * FontWidth(screen), ! 495: FontHeight(screen), screen->background); ! 496: ScrnRefresh(screen, frow, fcol, 1, i); ! 497: } ! 498: if((i = trow - frow - 1) > 0) { /* middle rows*/ ! 499: j = screen->max_col + 1; ! 500: XPixSet(VWindow(screen), screen->border, (frow + 1) * ! 501: FontHeight(screen) + screen->border + Titlebar(screen), ! 502: j * FontWidth(screen), i * FontHeight(screen), ! 503: screen->background); ! 504: ScrnRefresh(screen, frow + 1, 0, i, j); ! 505: } ! 506: if(tcol > 0 && trow <= screen->max_row) { /* last row */ ! 507: XPixSet(VWindow(screen), screen->border, trow * ! 508: FontHeight(screen) + screen->border + Titlebar(screen), ! 509: tcol * FontWidth(screen), FontHeight(screen), ! 510: screen->background); ! 511: ScrnRefresh(screen, trow, 0, 1, tcol); ! 512: } ! 513: } else { /* do single row */ ! 514: i = tcol - fcol; ! 515: XPixSet(VWindow(screen), fcol* FontWidth(screen) + screen->border, ! 516: frow * FontHeight(screen) + screen->border + Titlebar(screen), ! 517: i * FontWidth(screen), FontHeight(screen), screen->background); ! 518: ScrnRefresh(screen, frow, fcol, 1, tcol - fcol); ! 519: } ! 520: if(hilite) { ! 521: i = screen->foreground; ! 522: screen->foreground = screen->background; ! 523: screen->background = i; ! 524: } ! 525: } ! 526: ! 527: SaltTextAway(term, row, col, pty) ! 528: Terminal *term; ! 529: register row, col; ! 530: int pty; ! 531: { ! 532: register Screen *screen = &term->screen; ! 533: register int i, j = 0; ! 534: register char *str; /* string to be saved */ ! 535: char *line, *lp; ! 536: ! 537: /* first order of business is to guarantee that crow,ccol is before */ ! 538: /* row,col. */ ! 539: if ( row == crow ) { /* must exchange as pairs */ ! 540: if ( ccol > col ) { /* may have to exchange columns */ ! 541: register int tmp; ! 542: tmp = ccol; ccol = col; col = tmp; ! 543: } ! 544: } ! 545: else { ! 546: if ( crow > row ) { /* may have to exchange row and col */ ! 547: register int tmp; ! 548: tmp = ccol; ccol = col; col = tmp; ! 549: tmp = crow; crow = row; row = tmp; ! 550: } ! 551: } ! 552: ! 553: if (ccol < 0) ccol = 0; ! 554: else if (ccol > screen->max_col) { crow++; ccol = 0; } ! 555: if (crow < 0) crow = ccol = 0; ! 556: else if (crow > screen->max_row) { crow = screen->max_row; ccol = 0; } ! 557: ! 558: if (row > screen->max_row) { row = screen->max_row + 1 ; col = 0; } ! 559: else if (--col > screen->max_col) col = screen->max_col; ! 560: ! 561: /* first we need to know how long the string is before we can save it*/ ! 562: ! 563: if ( row == crow ) j = Length(screen, crow, ccol, col); ! 564: else { /* two cases, cut is on same line, cut spans multiple lines */ ! 565: j += Length(screen, crow, ccol, screen->max_col) + 1; ! 566: for(i = crow + 1; i < row; i++) ! 567: j += Length(screen, i, 0, screen->max_col) + 1; ! 568: if (col >= 0) ! 569: j += Length(screen, row, 0, col); ! 570: } ! 571: ! 572: /* now get some memory to save it in */ ! 573: ! 574: if((line = (char *)malloc(j + 1)) == NULL) ! 575: SysError(ERROR_BMALLOC2); ! 576: line[j] = '\0'; /* make sure it is null terminated */ ! 577: lp = line; /* lp points to where to save the text */ ! 578: if ( row == crow ) lp = SaveText(screen, row, ccol, col, lp); ! 579: else { ! 580: lp = SaveText(screen, crow, ccol, screen->max_col, lp); ! 581: *lp ++ = '\n'; /* put in newline at end of line */ ! 582: for(i = crow +1; i < row; i++) { ! 583: lp = SaveText(screen, i, 0, screen->max_col, lp); ! 584: *lp ++ = '\n'; ! 585: } ! 586: if (col >= 0) ! 587: lp = SaveText(screen, row, 0, col, lp); ! 588: } ! 589: *lp = '\0'; /* make sure we have end marked */ ! 590: ! 591: XStoreBytes(line, j); ! 592: free(line); ! 593: } ! 594: ! 595: /* returns number of chars in line from scol to ecol out */ ! 596: int Length(screen, row, scol, ecol) ! 597: register int row, scol, ecol; ! 598: register Screen *screen; ! 599: { ! 600: register char *ch; ! 601: int end = 0; ! 602: ! 603: ch = screen->buf[2 * (row + screen->topline)]; ! 604: while (ecol >= scol && ch[ecol] == 0) ! 605: ecol--; ! 606: return (ecol - scol + 1); ! 607: } ! 608: ! 609: /* copies text into line, preallocated */ ! 610: char *SaveText(screen, row, scol, ecol, lp) ! 611: int row; ! 612: int scol, ecol; ! 613: Screen *screen; ! 614: register char *lp; /* pointer to where to put the text */ ! 615: { ! 616: register int i = 0; ! 617: register char *ch = screen->buf[2 * (row + screen->topline)]; ! 618: register int c; ! 619: ! 620: if ((i = Length(screen, row, scol, ecol)) == 0) return(lp); ! 621: ecol = scol + i; ! 622: for (i = scol; i < ecol; i++) { ! 623: if ((c = ch[i]) == 0) ! 624: c = ' '; ! 625: else if(c < ' ') { ! 626: if(c == '\036') ! 627: c = '#'; ! 628: else ! 629: c += 0x5f; ! 630: } else if(c == 0x7f) ! 631: c = 0x5f; ! 632: *lp++ = c; ! 633: } ! 634: return(lp); ! 635: } ! 636: ! 637: EditorDown (term, reply, pty) ! 638: Terminal *term; ! 639: register XKeyOrButtonEvent *reply; ! 640: int pty; /* file descriptor of pty */ ! 641: { ! 642: register Screen *screen = &term->screen; ! 643: char line[6]; ! 644: register unsigned row, col; ! 645: int button; ! 646: ! 647: if (!screen->send_mouse_pos) { ! 648: Bell(); ! 649: return; ! 650: } ! 651: button = 2 - reply->detail & 0177; ! 652: row = (reply->y - screen->border - Titlebar(screen)) / FontHeight(screen); ! 653: col = (reply->x - screen->border) / FontWidth(screen); ! 654: strcpy(line, "\033[M"); ! 655: line[3] = ' ' + button; ! 656: line[4] = ' ' + col + 1; ! 657: line[5] = ' ' + row + 1; ! 658: write(pty, line, 6); ! 659: } ! 660: ! 661: #ifdef ALLOWUNSHIFTEDSELECTION ! 662: UnshiftedSelectionInit() ! 663: { ! 664: register int i, j; ! 665: ! 666: /* copy table for shifted actions to table for unshifted ! 667: * actions. We assume the shifted actions are in bfunc[1] ! 668: * and the unshifted ones go in bfunc[0]. ! 669: */ ! 670: for (i = 0; i < DIRS; i++) ! 671: for (j = 0; j < NBUTS; j++) ! 672: bfunc[0][i][j] = bfunc[1][i][j]; ! 673: } ! 674: #endif ! 675: ! 676: #ifdef MODEMENU ! 677: #define MAXWINDOWMENU 64 ! 678: #define XTERMMENU 0 ! 679: #define VTMENU 1 ! 680: #define TEKMENU 2 ! 681: #define SCROLLBARMENU 3 ! 682: #ifndef NOWINDOWMENU ! 683: #define WINDOWMENU 4 ! 684: #define NMENUS 5 ! 685: #else NOWINDOWMENU ! 686: #define NMENUS 4 ! 687: #endif NOWINDOWMENU ! 688: ! 689: static Menu *menus[NMENUS]; ! 690: #ifndef NOWINDOWMENU ! 691: static char *namebuf[MAXWINDOWMENU + 1]; ! 692: static char *wname; ! 693: static Window windows[MAXWINDOWMENU]; ! 694: #endif NOWINDOWMENU ! 695: ! 696: ModeMenu(term, reply, pty) ! 697: Terminal *term; ! 698: register XKeyOrButtonEvent *reply; ! 699: int pty; /* file descriptor of pty */ ! 700: { ! 701: register Screen *screen = &term->screen; ! 702: register Menu *menu; ! 703: register int type, item; ! 704: static int inited; ! 705: extern TekLink *TekRefresh; ! 706: extern int xeventpass(); ! 707: extern Menu *setupmenu(), *Tsetupmenu(), *xsetupmenu(); ! 708: #ifndef NOWINDOWMENU ! 709: extern Menu *wsetupmenu(); ! 710: #endif NOWINDOWMENU ! 711: extern Menu *ssetupmenu(); ! 712: ! 713: if((reply->window == screen->title.tbar || reply->window == ! 714: screen->Ttitle.tbar) && InTitle(screen, reply->window, ! 715: reply->x)) ! 716: return; ! 717: if(!inited) { ! 718: extern Pixmap Gray_Tile; ! 719: extern Cursor Menu_DefaultCursor; ! 720: extern char *Menu_DefaultFont; ! 721: extern FontInfo *Menu_DefaultFontInfo; ! 722: ! 723: inited++; ! 724: Gray_Tile = screen->graybordertile; ! 725: InitMenu(xterm_name); ! 726: Menu_DefaultCursor = screen->arrow; ! 727: if(strcmp(Menu_DefaultFont, f_t) == 0) ! 728: Menu_DefaultFontInfo = screen->titlefont; ! 729: } ! 730: if((reply->detail & 0177) == LeftButton) ! 731: type = XTERMMENU; ! 732: else if((reply->detail & 0177) == RightButton) ! 733: #ifndef NOWINDOWMENU ! 734: type = WINDOWMENU; ! 735: #else NOWINDOWMENU ! 736: { ! 737: Bell(); ! 738: return; ! 739: } ! 740: #endif NOWINDOWMENU ! 741: else if(reply->window == VWindow(screen) || reply->window == ! 742: screen->title.tbar) ! 743: type = VTMENU; ! 744: else if(reply->window == TWindow(screen) || reply->window == ! 745: screen->Ttitle.tbar) ! 746: type = TEKMENU; ! 747: else ! 748: type = SCROLLBARMENU; ! 749: switch(type) { ! 750: case XTERMMENU: ! 751: if((menu = xsetupmenu(&menus[XTERMMENU])) == NULL) ! 752: return; ! 753: break; ! 754: case VTMENU: ! 755: if((menu = setupmenu(&menus[VTMENU])) == NULL) ! 756: return; ! 757: break; ! 758: #ifndef NOWINDOWMENU ! 759: case WINDOWMENU: ! 760: wname = (reply->window == screen->title.tbar || reply->window ! 761: == VWindow(screen)) ? screen->winname : screen->Twinname; ! 762: if((menu = wsetupmenu(&menus[WINDOWMENU])) == NULL) ! 763: return; ! 764: break; ! 765: #endif NOWINDOWMENU ! 766: case TEKMENU: ! 767: if((menu = Tsetupmenu(&menus[TEKMENU])) == NULL) ! 768: return; ! 769: screen->waitrefresh = TRUE; ! 770: break; ! 771: case SCROLLBARMENU: ! 772: if((menu = ssetupmenu(&menus[SCROLLBARMENU])) == NULL) ! 773: return; ! 774: break; ! 775: } ! 776: /* ! 777: * Make the window entry and leaving routines holdoff on setting ! 778: * the timer and on selecting or unselecting any windows. Then ! 779: * set the select mode manually. ! 780: */ ! 781: screen->holdoff = TRUE; ! 782: SetMenuEventHandler(menu, xeventpass); ! 783: item = TrackMenu(menu, reply); ! 784: menusync(); ! 785: screen->waitrefresh = FALSE; ! 786: screen->timer = 0; ! 787: screen->holdoff = FALSE; ! 788: reselectwindow(screen); ! 789: ! 790: if (item < 0) { ! 791: if(type == TEKMENU && TekRefresh) ! 792: dorefresh(); ! 793: #ifndef NOWINDOWMENU ! 794: else if(type == WINDOWMENU) ! 795: wfree(menu); ! 796: #endif NOWINDOWMENU ! 797: return; ! 798: } ! 799: switch(type) { ! 800: case XTERMMENU: ! 801: xdomenufunc(item); ! 802: break; ! 803: case VTMENU: ! 804: domenufunc(item); ! 805: break; ! 806: #ifndef NOWINDOWMENU ! 807: case WINDOWMENU: ! 808: wdomenufunc(item); ! 809: wfree(menu); ! 810: break; ! 811: #endif NOWINDOWMENU ! 812: case TEKMENU: ! 813: Tdomenufunc(item); ! 814: break; ! 815: case SCROLLBARMENU: ! 816: sdomenufunc(item); ! 817: break; ! 818: } ! 819: } ! 820: ! 821: menusync() ! 822: { ! 823: XEvent ev; ! 824: ! 825: XSync(0); ! 826: while(QLength() > 0) { ! 827: XNextEvent(&ev); ! 828: xeventpass(&ev); ! 829: } ! 830: } ! 831: ! 832: #define XMENU_TITLE 0 ! 833: #define XMENU_ACTIVEICON (XMENU_TITLE+1) ! 834: #define XMENU_ALLOWICONINPUT (XMENU_ACTIVEICON+1) ! 835: #define XMENU_AUTORAISE (XMENU_ALLOWICONINPUT+1) ! 836: #define XMENU_AUDIBLEBELL (XMENU_AUTORAISE+1) ! 837: #define XMENU_VISUALBELL (XMENU_AUDIBLEBELL+1) ! 838: #define XMENU_DEICONWARP (XMENU_VISUALBELL+1) ! 839: #define XMENU_SENDMOUSE (XMENU_DEICONWARP+1) ! 840: #define XMENU_LOG (XMENU_SENDMOUSE+1) ! 841: #define XMENU_LINE (XMENU_LOG+1) ! 842: #define XMENU_REDRAW (XMENU_LINE+1) ! 843: #define XMENU_RESUME (XMENU_REDRAW+1) ! 844: #define XMENU_SUSPEND (XMENU_RESUME+1) ! 845: #define XMENU_INTR (XMENU_SUSPEND+1) ! 846: #define XMENU_HANGUP (XMENU_INTR+1) ! 847: #define XMENU_TERM (XMENU_HANGUP+1) ! 848: #define XMENU_KILL (XMENU_TERM+1) ! 849: ! 850: static char *xtext[] = { ! 851: "Title Bar(s)", ! 852: "Active Icon", ! 853: "Allow Icon Input", ! 854: "Auto Raise", ! 855: "Audible Bell", ! 856: "Visual Bell", ! 857: "Deiconify Warp", ! 858: "Send Mouse Pos", ! 859: "Logging", ! 860: "-", ! 861: "Redraw", ! 862: "Continue", ! 863: "Suspend", ! 864: "Interrupt", ! 865: "Hangup", ! 866: "Terminate", ! 867: "Kill", ! 868: 0, ! 869: }; ! 870: ! 871: static int xauto; ! 872: static int xabell; ! 873: static int xvbell; ! 874: static int xdeiconwarp; ! 875: static int xsendmouse; ! 876: static int xlog; ! 877: static int xtbar; ! 878: static int xactive_icon; ! 879: static int xallow_iconinput; ! 880: ! 881: Menu *xsetupmenu(menu) ! 882: register Menu **menu; ! 883: { ! 884: register Screen *screen = &term.screen; ! 885: register char **cp; ! 886: register int i; ! 887: ! 888: if (*menu == NULL) { ! 889: if ((*menu = NewMenu("xterm X10/6.6B", re_verse)) == NULL) ! 890: return(NULL); ! 891: for(cp = xtext ; *cp ; cp++) ! 892: AddMenuItem(*menu, *cp); ! 893: if(xtbar = (Titlebar(screen) > 0)) ! 894: CheckItem(*menu, XMENU_TITLE); ! 895: if(xactive_icon = screen->active_icon) ! 896: CheckItem(*menu, XMENU_ACTIVEICON); ! 897: if(xallow_iconinput = (term.flags & ICONINPUT)) ! 898: CheckItem(*menu, XMENU_ALLOWICONINPUT); ! 899: SetItemDisable(*menu, XMENU_ALLOWICONINPUT, !xactive_icon); ! 900: if(xauto = screen->autoraise) ! 901: CheckItem(*menu, XMENU_AUTORAISE); ! 902: if(xabell = screen->audiblebell) ! 903: CheckItem(*menu, XMENU_AUDIBLEBELL); ! 904: if(xvbell = screen->visualbell) ! 905: CheckItem(*menu, XMENU_VISUALBELL); ! 906: if(xdeiconwarp = screen->deiconwarp) ! 907: CheckItem(*menu, XMENU_DEICONWARP); ! 908: if(xlog = screen->logging) ! 909: CheckItem(*menu, XMENU_LOG); ! 910: if(xsendmouse = screen->send_mouse_pos) ! 911: CheckItem(*menu, XMENU_SENDMOUSE); ! 912: DisableItem(*menu, XMENU_LINE); ! 913: if(screen->inhibit & I_LOG) ! 914: DisableItem(*menu, XMENU_LOG); ! 915: if(screen->inhibit & I_SIGNAL) ! 916: for(i = XMENU_SUSPEND ; i <= XMENU_KILL ; i++) ! 917: DisableItem(*menu, i); ! 918: return(*menu); ! 919: } ! 920: if (xtbar != (Titlebar(screen) > 0)) ! 921: SetItemCheck(*menu, XMENU_TITLE, (xtbar = ! 922: (Titlebar(screen) > 0))); ! 923: if (xactive_icon != screen->active_icon) { ! 924: SetItemCheck(*menu, XMENU_ACTIVEICON, ! 925: (xactive_icon = screen->active_icon)); ! 926: SetItemDisable(*menu, XMENU_ALLOWICONINPUT, !xactive_icon); ! 927: } ! 928: if (xallow_iconinput != (term.flags & ICONINPUT)) ! 929: SetItemCheck(*menu, XMENU_ALLOWICONINPUT, ! 930: (xallow_iconinput = (term.flags & ICONINPUT))); ! 931: if (xauto != screen->autoraise) ! 932: SetItemCheck(*menu, XMENU_AUTORAISE, (xauto = ! 933: screen->autoraise)); ! 934: if (xabell != screen->audiblebell) ! 935: SetItemCheck(*menu, XMENU_AUDIBLEBELL, (xabell = ! 936: screen->audiblebell)); ! 937: if (xvbell != screen->visualbell) ! 938: SetItemCheck(*menu, XMENU_VISUALBELL, (xvbell = ! 939: screen->visualbell)); ! 940: if (xdeiconwarp != screen->deiconwarp) ! 941: SetItemCheck(*menu, XMENU_DEICONWARP, (xdeiconwarp = ! 942: screen->deiconwarp)); ! 943: if (xsendmouse != screen->send_mouse_pos) ! 944: SetItemCheck(*menu, XMENU_SENDMOUSE, ! 945: (xsendmouse = screen->send_mouse_pos)); ! 946: if (xlog != screen->logging) ! 947: SetItemCheck(*menu, XMENU_LOG, (xlog = screen->logging)); ! 948: return(*menu); ! 949: } ! 950: ! 951: xdomenufunc(item) ! 952: int item; ! 953: { ! 954: register Screen *screen = &term.screen; ! 955: ! 956: switch (item) { ! 957: case XMENU_TITLE: ! 958: if(Titlebar(screen)) { ! 959: screen->fullVwin.titlebar = ! 960: screen->fullTwin.titlebar = 0; ! 961: if(VWindow(screen)) ! 962: VTTitleHide(); ! 963: if(TWindow(screen)) ! 964: TekTitleHide(); ! 965: } else { ! 966: screen->fullVwin.titlebar = ! 967: screen->fullTwin.titlebar = screen->titleheight; ! 968: if(VWindow(screen)) ! 969: VTTitleShow(FALSE); ! 970: if(TWindow(screen)) ! 971: TekTitleShow(FALSE); ! 972: } ! 973: break; ! 974: ! 975: case XMENU_ACTIVEICON: ! 976: screen->active_icon = !screen->active_icon; ! 977: if (screen->active_icon && !screen->fnt_icon) { ! 978: FontInfo *fInfo = XOpenFont( f_i ); ! 979: screen->fnt_icon = fInfo->id; ! 980: screen->iconVwin.f_width = fInfo->width; ! 981: screen->iconVwin.f_height = fInfo->height; ! 982: } ! 983: ! 984: if (screen->iconVwin.window) { ! 985: SetIconSize( screen ); ! 986: XSelectInput( screen->iconVwin.window, ! 987: screen->active_icon ! 988: && (term.flags & ICONINPUT) ! 989: ? ICONWINDOWEVENTS | ICONINPUTEVENTS ! 990: : ICONWINDOWEVENTS ); ! 991: } ! 992: ! 993: if (screen->iconTwin.window) { ! 994: TSetIconSize( screen ); ! 995: XSelectInput( screen->iconTwin.window, ! 996: screen->active_icon ! 997: && (term.flags & ICONINPUT) ! 998: ? TICONWINDOWEVENTS | ICONINPUTEVENTS ! 999: : TICONWINDOWEVENTS ); ! 1000: } ! 1001: ! 1002: break; ! 1003: ! 1004: case XMENU_ALLOWICONINPUT: ! 1005: term.flags ^= ICONINPUT; ! 1006: if (screen->iconVwin.window) ! 1007: XSelectInput( screen->iconVwin.window, ! 1008: screen->active_icon ! 1009: && (term.flags & ICONINPUT) ! 1010: ? ICONWINDOWEVENTS | ICONINPUTEVENTS ! 1011: : ICONWINDOWEVENTS ); ! 1012: ! 1013: if (screen->iconTwin.window) ! 1014: XSelectInput( screen->iconTwin.window, ! 1015: screen->active_icon ! 1016: && (term.flags & ICONINPUT) ! 1017: ? TICONWINDOWEVENTS | ICONINPUTEVENTS ! 1018: : TICONWINDOWEVENTS ); ! 1019: ! 1020: break; ! 1021: ! 1022: case XMENU_AUTORAISE: ! 1023: screen->autoraise = !screen->autoraise; ! 1024: break; ! 1025: ! 1026: case XMENU_DEICONWARP: ! 1027: screen->deiconwarp = !screen->deiconwarp; ! 1028: break; ! 1029: ! 1030: case XMENU_AUDIBLEBELL: ! 1031: screen->audiblebell = !screen->audiblebell; ! 1032: break; ! 1033: ! 1034: case XMENU_VISUALBELL: ! 1035: screen->visualbell = !screen->visualbell; ! 1036: break; ! 1037: ! 1038: case XMENU_SENDMOUSE: ! 1039: screen->send_mouse_pos = !screen->send_mouse_pos; ! 1040: break; ! 1041: ! 1042: case XMENU_LOG: ! 1043: if(screen->logging) ! 1044: CloseLog(screen); ! 1045: else ! 1046: StartLog(screen); ! 1047: break; ! 1048: ! 1049: case XMENU_REDRAW: ! 1050: Redraw(); ! 1051: break; ! 1052: ! 1053: case XMENU_RESUME: ! 1054: if(screen->pid > 1) ! 1055: killpg(getpgrp(screen->pid), SIGCONT); ! 1056: break; ! 1057: ! 1058: case XMENU_SUSPEND: ! 1059: if(screen->pid > 1) ! 1060: killpg(getpgrp(screen->pid), SIGTSTP); ! 1061: break; ! 1062: ! 1063: case XMENU_INTR: ! 1064: if(screen->pid > 1) ! 1065: killpg(getpgrp(screen->pid), SIGINT); ! 1066: break; ! 1067: ! 1068: case XMENU_HANGUP: ! 1069: if(screen->pid > 1) ! 1070: killpg(getpgrp(screen->pid), SIGHUP); ! 1071: break; ! 1072: ! 1073: case XMENU_TERM: ! 1074: if(screen->pid > 1) ! 1075: killpg(getpgrp(screen->pid), SIGTERM); ! 1076: break; ! 1077: ! 1078: case XMENU_KILL: ! 1079: if(screen->pid > 1) ! 1080: killpg(getpgrp(screen->pid), SIGKILL); ! 1081: break; ! 1082: } ! 1083: } ! 1084: ! 1085: #ifndef NOWINDOWMENU ! 1086: Menu *wsetupmenu(menu) ! 1087: register Menu **menu; ! 1088: { ! 1089: register Window *cp, *wp; ! 1090: register char **np; ! 1091: register int i, j; ! 1092: Window win, *children; ! 1093: int nchildren; ! 1094: char *name; ! 1095: WindowInfo winfo; ! 1096: ! 1097: if(!XQueryTree(RootWindow, &win, &nchildren, &children)) ! 1098: return(NULL); ! 1099: if(nchildren > MAXWINDOWMENU) ! 1100: nchildren = MAXWINDOWMENU; ! 1101: if ((*menu = NewMenu("Windows", re_verse)) == NULL) { ! 1102: free((char *)children); ! 1103: return(NULL); ! 1104: } ! 1105: np = namebuf; ! 1106: wp = windows; ! 1107: for(i = nchildren, j = 0, cp = children ; i > 0 ; cp++, i--) { ! 1108: if(!XQueryWindow(*cp, &winfo)) ! 1109: goto failed; ! 1110: if(winfo.mapped != IsMapped) ! 1111: continue; ! 1112: if(!XFetchName(*cp, &name)) { ! 1113: failed: ! 1114: free((char *)children); ! 1115: *np = NULL; ! 1116: wfree(*menu); ! 1117: return(NULL); ! 1118: } ! 1119: if(name == NULL) ! 1120: continue; ! 1121: AddMenuItem(*menu, *np++ = name); ! 1122: *wp++ = *cp; ! 1123: if(strcmp(wname, name) == 0) ! 1124: CheckItem(*menu, j); ! 1125: j++; ! 1126: } ! 1127: *np = NULL; ! 1128: free((char *)children); ! 1129: if(np > namebuf) ! 1130: return(*menu); ! 1131: DisposeMenu(*menu); ! 1132: return(NULL); ! 1133: } ! 1134: ! 1135: wdomenufunc(item) ! 1136: int item; ! 1137: { ! 1138: register Window w; ! 1139: ! 1140: if((w = windows[item]) != NULL) ! 1141: XRaiseWindow(w); ! 1142: } ! 1143: ! 1144: wfree(menu) ! 1145: Menu *menu; ! 1146: { ! 1147: register char **np; ! 1148: ! 1149: for(np = namebuf ; *np ; np++) ! 1150: free(*np); ! 1151: DisposeMenu(menu); ! 1152: } ! 1153: #endif NOWINDOWMENU ! 1154: ! 1155: MenuNewCursor(cur) ! 1156: register Cursor cur; ! 1157: { ! 1158: register Menu **menu; ! 1159: register int i; ! 1160: extern Cursor Menu_DefaultCursor; ! 1161: ! 1162: Menu_DefaultCursor = cur; ! 1163: for(i = XTERMMENU, menu = menus ; i <= TEKMENU ; menu++, i++) { ! 1164: if(!*menu) ! 1165: continue; ! 1166: (*menu)->menuCursor = cur; ! 1167: if((*menu)->menuWindow) ! 1168: XDefineCursor((*menu)->menuWindow, cur); ! 1169: } ! 1170: } ! 1171: #else MODEMENU ! 1172: ! 1173: ModeMenu(term, reply, pty) ! 1174: Terminal *term; ! 1175: register XKeyOrButtonEvent *reply; ! 1176: int pty; /* file descriptor of pty */ ! 1177: { ! 1178: register Screen *screen = &term->screen; ! 1179: ! 1180: if((reply->window == screen->title.tbar || reply->window == ! 1181: screen->Ttitle.tbar) && InTitle(screen, reply->window, ! 1182: reply->x)) ! 1183: return; ! 1184: Bell(); ! 1185: } ! 1186: #endif MODEMENU ! 1187: ! 1188: GINbutton(term, reply, pty) ! 1189: Terminal *term; ! 1190: XKeyOrButtonEvent *reply; ! 1191: int pty; /* file descriptor of pty */ ! 1192: { ! 1193: register Screen *screen = &term->screen; ! 1194: register int i; ! 1195: ! 1196: if(screen->TekGIN) { ! 1197: i = "rml"[reply->detail & 0xff]; ! 1198: if(reply->detail & ShiftMask) ! 1199: i = toupper(i); ! 1200: TekEnqMouse(i | 0x80); /* set high bit */ ! 1201: TekGINoff(); ! 1202: } else ! 1203: Bell(); ! 1204: } ! 1205: ! 1206: Bogus(term, reply, pty) ! 1207: Terminal *term; ! 1208: XKeyOrButtonEvent *reply; ! 1209: int pty; /* file descriptor of pty */ ! 1210: { ! 1211: Bell(); ! 1212: } ! 1213: ! 1214: Silence(term, reply, pty) ! 1215: Terminal *term; ! 1216: XKeyOrButtonEvent *reply; ! 1217: int pty; /* file descriptor of pty */ ! 1218: { ! 1219: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.