|
|
1.1 ! root 1: #include <X/mit-copyright.h> ! 2: ! 3: /* Copyright Massachusetts Institute of Technology 1984, 1985 */ ! 4: /* ! 5: button.c Handles button events in the terminal emulator. ! 6: does cut/paste operations, change modes via menu, ! 7: passes button events through to some applications. ! 8: J. Gettys. ! 9: */ ! 10: #ifndef lint ! 11: static char *rcsid_window_c = "$Header: button.c,v 10.11 86/02/01 16:05:41 tony Rel $"; ! 12: #endif lint ! 13: #include <stdio.h> ! 14: #include <X/Xlib.h> ! 15: #include "ptyx.h" ! 16: #ifdef MODEMENU ! 17: #include <X/XMenu.h> ! 18: #endif ! 19: ! 20: #define NBUTS 3 ! 21: #define DIRS 2 ! 22: #define UP 1 ! 23: #define DOWN 0 ! 24: #define SHIFTS 8 /* three keys, so eight combinations */ ! 25: char *GetRestOfLine(); ! 26: char *SaveText(); ! 27: extern UnSaltText(); ! 28: extern SaltTextAway(); ! 29: extern StartCut(); ! 30: extern ReExecute(); ! 31: extern EditorDown(); ! 32: #ifdef MODEMENU ! 33: extern ModeMenu(); ! 34: extern char *xterm_name; ! 35: #else ! 36: #define ModeMenu Bogus ! 37: #endif MODEMENU ! 38: extern Bogus(), Silence(); ! 39: /* due to LK201 limitations, not all of the below are actually possible */ ! 40: int (*bfunc[SHIFTS][DIRS][NBUTS])() = { ! 41: /* left middle right */ ! 42: EditorDown, EditorDown, EditorDown, /* down | */ ! 43: Silence, Silence, Silence, /* up |no shift */ ! 44: ! 45: Silence, StartCut, Silence, /* down | */ ! 46: ReExecute, SaltTextAway, UnSaltText, /* up |shift */ ! 47: ! 48: Bogus, Bogus, Bogus, /* down | */ ! 49: Silence, Silence, Silence, /* up |meta */ ! 50: ! 51: Bogus, Bogus, Bogus, /* down | */ ! 52: Silence, Silence, Silence, /* up |meta shift */ ! 53: ! 54: Bogus, ModeMenu, Bogus, /* down | */ ! 55: Silence, Silence, Silence, /* up |control */ ! 56: ! 57: Bogus, Bogus, Bogus, /* down | */ ! 58: Silence, Silence, Silence, /* up |ctl shift */ ! 59: ! 60: Bogus, Bogus, Bogus, /* down | */ ! 61: Silence, Silence, Silence, /* up |no shift */ ! 62: ! 63: Bogus, Bogus, Bogus, /* down | control */ ! 64: Silence, Silence, Silence /* up |meta shift*/ ! 65: ! 66: }; /* button, shift keys, and direction */ ! 67: ! 68: static crow, ccol; /* cut row and column */ ! 69: ! 70: HandleButtons(term, reply, pty) ! 71: register Terminal *term; ! 72: register XEvent *reply; ! 73: int pty; /* file descriptor of pty */ ! 74: { ! 75: int (*bp)(); ! 76: int dir = DOWN; ! 77: /* so table above will be nice, we change left to right */ ! 78: int button = 2 - ((XKeyOrButtonEvent *)reply)->detail & 0177; ! 79: int shift = KeyState(((XKeyOrButtonEvent *)reply)->detail); ! 80: switch (reply->type) { ! 81: case ButtonPressed: ! 82: dir = DOWN; ! 83: break; ! 84: case ButtonReleased: ! 85: dir = UP; ! 86: break; ! 87: default: ! 88: break; ! 89: } ! 90: bp = bfunc[shift][dir][button]; ! 91: if (bp != NULL) return ((*bp)(term, reply, pty)); ! 92: XFeep(0); ! 93: return(0); ! 94: } ! 95: ! 96: UnSaltText(term, reply, pty) ! 97: register Terminal *term; ! 98: register XKeyOrButtonEvent *reply; ! 99: int pty; /* file descriptor of pty */ ! 100: { ! 101: char *line; ! 102: int nbytes; ! 103: register char *lag, *cp, *end; ! 104: ! 105: line = XFetchBytes(&nbytes); ! 106: end = &line[nbytes]; ! 107: lag = line; ! 108: for (cp = line; cp != end; cp++) ! 109: { ! 110: if (*cp != '\n') continue; ! 111: *cp = '\r'; ! 112: write(pty, lag, cp - lag + 1); ! 113: lag = cp + 1; ! 114: } ! 115: if (lag != end) ! 116: write(pty, lag, end - lag); ! 117: free (line); /* free text from fetch */ ! 118: return(0); ! 119: } ! 120: ! 121: ReExecute(term, reply, pty) ! 122: register Terminal *term; ! 123: register XKeyOrButtonEvent *reply; ! 124: int pty; /* file descriptor of pty */ ! 125: { ! 126: char *line = GetRestOfLine(&term->screen, reply); ! 127: register int nbytes = strlen(line); ! 128: ! 129: write(pty, line, nbytes); ! 130: line[nbytes] = '\n'; ! 131: XStoreBytes(line, nbytes); ! 132: free (line); /* free text from fetch */ ! 133: return(0); ! 134: } ! 135: ! 136: char *GetRestOfLine(screen, reply) ! 137: register XKeyOrButtonEvent *reply; ! 138: register Screen *screen; ! 139: { ! 140: char *line; ! 141: int i; ! 142: register int row, col; ! 143: row = (reply->y - screen->border) / screen->f_height; ! 144: col = (reply->x - screen->border) / screen->f_width; ! 145: if ( row < 0 ) row = 0; ! 146: else if ( row > screen->max_row ) row = screen->max_row; ! 147: if ( col < 0 ) col = 0; ! 148: else if ( col > screen->max_col ) col = screen->max_col; ! 149: i = Length(screen, row, col, screen->max_col); ! 150: if((line = (char *)malloc(i + 2)) == NULL) Error(); ! 151: SaveText(screen, row, col, screen->max_col, line); ! 152: line[i] = '\r'; ! 153: line[i+1] = '\0'; ! 154: return(line); ! 155: } ! 156: ! 157: StartCut(term, reply, pty) ! 158: register XKeyOrButtonEvent *reply; ! 159: Terminal *term; ! 160: int pty; ! 161: { ! 162: register Screen *screen = &term->screen; ! 163: crow = (reply->y - screen->border) / screen->f_height; ! 164: ccol = (reply->x - screen->border) / screen->f_width; ! 165: return(0); ! 166: } ! 167: ! 168: SaltTextAway(term, reply, pty) ! 169: register XKeyOrButtonEvent *reply; ! 170: Terminal *term; ! 171: int pty; ! 172: { ! 173: register Screen *screen = &term->screen; ! 174: register int i, j = 0; ! 175: register row, col; ! 176: register char *str; /* string to be saved */ ! 177: char *line, *lp; ! 178: row = (reply->y - screen->border) / screen->f_height; ! 179: col = (reply->x - screen->border) / screen->f_width; ! 180: ! 181: /* first order of business is to guarantee that crow,ccol is before */ ! 182: /* row,col. */ ! 183: if ( row == crow ) { /* must exchange as pairs */ ! 184: if ( ccol > col ) { /* may have to exchange columns */ ! 185: register int tmp; ! 186: tmp = ccol; ccol = col; col = tmp; ! 187: } ! 188: } ! 189: else { ! 190: if ( crow > row ) { /* may have to exchange row and col */ ! 191: register int tmp; ! 192: tmp = ccol; ccol = col; col = tmp; ! 193: tmp = crow; crow = row; row = tmp; ! 194: } ! 195: } ! 196: ! 197: if (ccol < 0) ccol = 0; ! 198: else if (ccol > screen->max_col) { crow++; ccol = 0; } ! 199: if (crow < 0) crow = ccol = 0; ! 200: else if (crow > screen->max_row) { crow = screen->max_row; ccol = 0; } ! 201: ! 202: if (row > screen->max_row) { row = screen->max_row + 1 ; col = 0; } ! 203: else if (--col > screen->max_col) col = screen->max_col; ! 204: ! 205: /* first we need to know how long the string is before we can save it*/ ! 206: ! 207: if ( row == crow ) j = Length(screen, crow, ccol, col); ! 208: else { /* two cases, cut is on same line, cut spans multiple lines */ ! 209: j += Length(screen, crow, ccol, screen->max_col) + 1; ! 210: for(i = crow + 1; i < row; i++) ! 211: j += Length(screen, i, 0, screen->max_col) + 1; ! 212: if (col >= 0) ! 213: j += Length(screen, row, 0, col); ! 214: } ! 215: ! 216: /* now get some memory to save it in */ ! 217: ! 218: if((line = (char *)malloc(j + 1)) == NULL) Error(); ! 219: line[j] = '\0'; /* make sure it is null terminated */ ! 220: lp = line; /* lp points to where to save the text */ ! 221: if ( row == crow ) lp = SaveText(screen, row, ccol, col, lp); ! 222: else { ! 223: lp = SaveText(screen, crow, ccol, screen->max_col, lp); ! 224: *lp ++ = '\n'; /* put in newline at end of line */ ! 225: for(i = crow +1; i < row; i++) { ! 226: lp = SaveText(screen, i, 0, screen->max_col, lp); ! 227: *lp ++ = '\n'; ! 228: } ! 229: if (col >= 0) ! 230: lp = SaveText(screen, row, 0, col, lp); ! 231: } ! 232: *lp = '\0'; /* make sure we have end marked */ ! 233: ! 234: XStoreBytes(line, j); ! 235: free(line); ! 236: return(0); ! 237: } ! 238: ! 239: /* returns number of chars in line from scol to ecol out */ ! 240: int Length(screen, row, scol, ecol) ! 241: register int row, scol, ecol; ! 242: register Screen *screen; ! 243: { ! 244: register short *ch; ! 245: int end = 0; ! 246: ch = screen->buf[row]; ! 247: while (ecol >= scol && ! 248: ((ch[ecol] & CHAR) == 0 || (ch[ecol] & CHAR) == ' ')) ! 249: ecol--; ! 250: return (ecol - scol + 1); ! 251: } ! 252: ! 253: /* copies text into line, preallocated */ ! 254: char *SaveText(screen, row, scol, ecol, lp) ! 255: int row; ! 256: int scol, ecol; ! 257: Screen *screen; ! 258: register char *lp; /* pointer to where to put the text */ ! 259: { ! 260: register int i = 0; ! 261: register short *ch = screen->buf[row]; ! 262: register int c; ! 263: if ((i = Length(screen, row, scol, ecol)) == 0) return(lp); ! 264: ecol = scol + i; ! 265: for (i = scol; i < ecol; i++) ! 266: { ! 267: c = ch[i] & CHAR; ! 268: if (c == 0) c = ' '; ! 269: *lp++ = c; ! 270: } ! 271: return(lp); ! 272: } ! 273: ! 274: EditorDown (term, reply, pty) ! 275: Terminal *term; ! 276: register XKeyOrButtonEvent *reply; ! 277: int pty; /* file descriptor of pty */ ! 278: { ! 279: register Screen *screen = &term->screen; ! 280: char line[6]; ! 281: register unsigned row, col; ! 282: int button = 2 - reply->detail & 0177; ! 283: if (!screen->send_mouse_pos) { ! 284: XFeep(0); ! 285: return(0); ! 286: } ! 287: row = (reply->y - screen->border) / screen->f_height; ! 288: col = (reply->x - screen->border) / screen->f_width; ! 289: strcpy(line, "\033[M"); ! 290: line[3] = ' ' + button; ! 291: line[4] = ' '+col+1; ! 292: line[5] = ' '+row+1; ! 293: write(pty, line, 6); ! 294: return(0); ! 295: } ! 296: ! 297: #ifdef MODEMENU ! 298: ! 299: static int menutoggled; ! 300: static Terminal *menuterm; ! 301: ! 302: HandleMenuEvent (rep) ! 303: XEvent *rep; ! 304: { ! 305: register Screen *screen = &menuterm->screen; ! 306: ! 307: switch (rep->type) ! 308: { ! 309: case ExposeWindow: ! 310: menutoggled = 1; ! 311: if (ScreenResize (screen, ! 312: ((XExposeWindowEvent *)rep)->width, ! 313: ((XExposeWindowEvent *)rep)->height, ! 314: menuterm->flags) != -1) ! 315: { ! 316: TabReset (menuterm->tabs); ! 317: XClear (screen->window); ! 318: ScrnRefresh (screen, 0, 0, ! 319: screen->max_row + 1, ! 320: screen->max_col + 1); ! 321: ! 322: if (screen->TekEmu) TekRefresh (menuterm); ! 323: } ! 324: break; ! 325: ! 326: case ExposeRegion: ! 327: if (HandleExposure (screen, rep)) ! 328: menutoggled = 1; ! 329: break; ! 330: } ! 331: } ! 332: ! 333: #define MMENU_SCROLL 1 ! 334: #define MMENU_VIDEO 2 ! 335: #define MMENU_WRAP 3 ! 336: #define MMENU_NLM 4 ! 337: #define MMENU_CURSOR 5 ! 338: #define MMENU_PAD 6 ! 339: #define MMENU_RESET 7 ! 340: #define MMENU_FULLRESET 8 ! 341: ! 342: static XMenu *menu = NULL; ! 343: static int menutermflags = 0; ! 344: static int menukbdflags = 0; ! 345: static int lastmenupane = 0; ! 346: static int lastmenusel = 0; ! 347: ! 348: ModeMenu(term, reply, pty) ! 349: Terminal *term; ! 350: register XKeyOrButtonEvent *reply; ! 351: int pty; /* file descriptor of pty */ ! 352: { ! 353: register Screen *screen = &term->screen; ! 354: register char **ptr; ! 355: int x, y; ! 356: int ulx, uly; ! 357: int menuw, menuh; ! 358: int pnum = lastmenupane, snum = lastmenusel; ! 359: int status, val; ! 360: ! 361: if (menu == NULL) { ! 362: if ((menu = (XMenu *)XMenuCreate(RootWindow, xterm_name)) == NULL) ! 363: return(0); ! 364: XMenuAddPane(menu, "Modes", 1); ! 365: #ifdef JUMPSCROLL ! 366: XMenuAddSelection(menu, 0, MMENU_SCROLL, ! 367: (term->flags & SMOOTHSCROLL) ? "jump scroll" : "smooth scroll", ! 368: 1); ! 369: #endif ! 370: XMenuAddSelection(menu, 0, MMENU_VIDEO, ! 371: (term->flags & REVERSE_VIDEO) ? "normal video" : "reverse video", ! 372: 1); ! 373: XMenuAddSelection(menu, 0, MMENU_WRAP, ! 374: (term->flags & WRAPAROUND) ? "no wrap" : "auto wrap", ! 375: 1); ! 376: XMenuAddSelection(menu, 0, MMENU_NLM, ! 377: (term->flags & LINEFEED) ? "normal linefeed" : "auto linefeed", ! 378: 1); ! 379: XMenuAddSelection(menu, 0, MMENU_CURSOR, ! 380: (term->keyboard.flags & CURSOR_APL) ? "normal cursors" : "application cursors", ! 381: 1); ! 382: XMenuAddSelection(menu, 0, MMENU_PAD, ! 383: (term->keyboard.flags & KYPD_APL) ? "numeric pad" : "application pad", ! 384: 1); ! 385: XMenuAddSelection(menu, 0, MMENU_RESET, "soft reset", 1); ! 386: XMenuAddSelection(menu, 0, MMENU_FULLRESET, "full reset", 1); ! 387: menuterm = term; ! 388: menutermflags = term->flags; ! 389: menukbdflags = term->keyboard.flags; ! 390: } ! 391: #ifdef JUMPSCROLL ! 392: if ((menutermflags ^ term->flags) & SMOOTHSCROLL) { ! 393: XMenuChangeSelection(menu, 0, MMENU_SCROLL-1, MMENU_SCROLL, 1, ! 394: (term->flags & SMOOTHSCROLL) ? "jump scroll" : "smooth scroll", ! 395: 1); ! 396: } ! 397: #endif ! 398: if ((menutermflags ^ term->flags) & REVERSE_VIDEO) { ! 399: XMenuChangeSelection(menu, 0, MMENU_VIDEO-1, MMENU_VIDEO, 1, ! 400: (term->flags & REVERSE_VIDEO) ? "normal video" : "reverse video", ! 401: 1); ! 402: } ! 403: if ((menutermflags ^ term->flags) & WRAPAROUND) { ! 404: XMenuChangeSelection(menu, 0, MMENU_WRAP-1, MMENU_WRAP, 1, ! 405: (term->flags & WRAPAROUND) ? "no wrap" : "auto wrap", ! 406: 1); ! 407: } ! 408: if ((menutermflags ^ term->flags) & LINEFEED) { ! 409: XMenuChangeSelection(menu, 0, MMENU_NLM-1, MMENU_NLM, 1, ! 410: (term->flags & LINEFEED) ? "normal linefeed" : "auto linefeed", ! 411: 1); ! 412: } ! 413: if ((menukbdflags ^ term->keyboard.flags) & CURSOR_APL) { ! 414: XMenuChangeSelection(menu, 0, MMENU_CURSOR-1, MMENU_CURSOR, 1, ! 415: (term->keyboard.flags & CURSOR_APL) ? "normal cursors" : "application cursors", ! 416: 1); ! 417: } ! 418: if ((menukbdflags ^ term->keyboard.flags) & KYPD_APL) { ! 419: XMenuChangeSelection(menu, 0, MMENU_PAD-1, MMENU_PAD, 1, ! 420: (term->keyboard.flags & KYPD_APL) ? "numeric pad" : "application pad", ! 421: 1); ! 422: } ! 423: XMenuRecompute(menu); ! 424: menutermflags = term->flags; ! 425: menukbdflags = term->keyboard.flags; ! 426: x = (reply->location >> 16) & 0xffff; ! 427: y = reply->location & 0xffff; ! 428: XMenuLocate(menu, pnum, snum, x, y, &ulx, &uly, &menuw, &menuh); ! 429: if ((ulx + menuw) > DisplayWidth()) ! 430: x -= ((ulx + menuw) - DisplayWidth()); ! 431: if (ulx < 0) ! 432: x -= ulx; ! 433: if ((uly + menuh) > DisplayHeight()) ! 434: y -= ((uly + menuh) - DisplayHeight()); ! 435: if (uly < 0) ! 436: y -= uly; ! 437: XMenuEventHandler(HandleMenuEvent); ! 438: menutoggled = 0; ! 439: status = XMenuActivate( ! 440: menu, ! 441: &pnum, &snum, ! 442: x, y, ! 443: MiddleMask|ButtonReleased, ! 444: (char **)&val ! 445: ); ! 446: if (status == XM_FAILURE) return(menutoggled); ! 447: if (status == XM_NO_SELECT) return(menutoggled); ! 448: else { ! 449: lastmenupane = pnum; ! 450: lastmenusel = snum; ! 451: } ! 452: switch (val) { ! 453: #ifdef JUMPSCROLL ! 454: case MMENU_SCROLL: ! 455: term->flags ^= SMOOTHSCROLL; ! 456: if (term->flags & SMOOTHSCROLL) { ! 457: screen->jumpscroll = 0; ! 458: if (screen->scroll_amt) FlushScroll(screen); ! 459: } else if (!screen->TekEmu) screen->jumpscroll = 1; ! 460: break; ! 461: #endif ! 462: case MMENU_VIDEO: ! 463: term->flags ^= REVERSE_VIDEO; ! 464: ReverseVideo(term); ! 465: menutoggled = 1; ! 466: break; ! 467: case MMENU_WRAP: ! 468: term->flags ^= WRAPAROUND; ! 469: case MMENU_NLM: ! 470: term->flags ^= LINEFEED; ! 471: case MMENU_CURSOR: ! 472: term->keyboard.flags ^= CURSOR_APL; ! 473: break; ! 474: case MMENU_PAD: ! 475: term->keyboard.flags ^= KYPD_APL; ! 476: break; ! 477: case MMENU_FULLRESET: ! 478: TabReset (term->tabs); ! 479: term->keyboard.flags = NULL; ! 480: screen->mode = ANSInormal; ! 481: /* Reset Tektronix alpha mode */ ! 482: screen->TekGMode = 0; ! 483: screen->TekAMode = 0; ! 484: screen->gsets[0] = 'B'; ! 485: screen->gsets[1] = 'B'; ! 486: screen->gsets[2] = '<'; ! 487: screen->gsets[3] = '<'; ! 488: screen->curgl = 0; ! 489: screen->curgr = 2; ! 490: screen->cur_x = screen->cur_y = 0; ! 491: screen->cur_X = screen->cur_Y = 0; ! 492: if (term->flags & REVERSE_VIDEO) ReverseVideo(term); ! 493: term->flags &= ~REVERSE_VIDEO; ! 494: menutoggled = 1; ! 495: CursorSet(screen, 0, 0, term->flags); ! 496: ClearScreen(screen); ! 497: term->flags = WRAPAROUND|SMOOTHSCROLL; ! 498: case MMENU_RESET: ! 499: /* reset scrolling region */ ! 500: screen->top_marg = 0; ! 501: screen->bot_marg = screen->max_row; ! 502: term->flags &= ~ORIGIN; ! 503: break; ! 504: } ! 505: return(menutoggled); ! 506: } ! 507: #endif MODEMENU ! 508: ! 509: Bogus(term, reply, pty) ! 510: Terminal *term; ! 511: XKeyOrButtonEvent *reply; ! 512: int pty; /* file descriptor of pty */ ! 513: { ! 514: XFeep(0); ! 515: return(0); ! 516: } ! 517: ! 518: Silence(term, reply, pty) ! 519: Terminal *term; ! 520: XKeyOrButtonEvent *reply; ! 521: int pty; /* file descriptor of pty */ ! 522: { ! 523: return(0); ! 524: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.