Annotation of 43BSD/contrib/X/xterm/button.c, revision 1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.