[BACK]Return to window.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / mg

Annotation of src/usr.bin/mg/window.c, Revision 1.2

1.1       deraadt     1: /*
                      2:  *             Window handling.
                      3:  */
                      4: #include       "def.h"
                      5:
                      6: /*
                      7:  * Reposition dot in the current
                      8:  * window to line "n". If the argument is
                      9:  * positive, it is that line. If it is negative it
                     10:  * is that line from the bottom. If it is 0 the window
                     11:  * is centered (this is what the standard redisplay code
                     12:  * does).  If GOSREC is undefined, default is 0, so it acts like GNU.
                     13:  * If GOSREC is defined, with no argument it defaults to 1
                     14:  * and works like in Gosling.
                     15:  */
                     16: /*ARGSUSED*/
                     17: reposition(f, n)
                     18: {
                     19: #ifndef GOSREC
                     20:        curwp->w_force = (f & FFARG) ? (n>=0 ? n+1 : n) : 0;
                     21: #else
                     22:        curwp->w_force = n;
                     23: #endif
                     24:        curwp->w_flag |= WFFORCE;
                     25:        sgarbf = TRUE;
                     26:        return TRUE;
                     27: }
                     28:
                     29: /*
                     30:  * Refresh the display. A call is made to the
                     31:  * "ttresize" entry in the terminal handler, which tries
                     32:  * to reset "nrow" and "ncol". They will, however, never
                     33:  * be set outside of the NROW or NCOL range. If the display
                     34:  * changed size, arrange that everything is redone, then
                     35:  * call "update" to fix the display. We do this so the
                     36:  * new size can be displayed. In the normal case the
                     37:  * call to "update" in "main.c" refreshes the screen,
                     38:  * and all of the windows need not be recomputed.
                     39:  * Note that when you get to the "display unusable"
                     40:  * message, the screen will be messed up. If you make
                     41:  * the window bigger again, and send another command,
                     42:  * everything will get fixed!
                     43:  */
                     44: /*ARGSUSED*/
                     45: refresh(f, n)
                     46: {
1.2     ! millert    47:        register MGWIN *wp;
1.1       deraadt    48:        register int    oldnrow;
                     49:        register int    oldncol;
                     50:
                     51:        oldnrow = nrow;
                     52:        oldncol = ncol;
                     53:        ttresize();
                     54:        if (nrow!=oldnrow || ncol!=oldncol) {
                     55:                wp = wheadp;                    /* Find last.           */
                     56:                while (wp->w_wndp != NULL)
                     57:                        wp = wp->w_wndp;
                     58:                if (nrow < wp->w_toprow+3) {    /* Check if too small.  */
                     59:                        ewprintf("Display unusable");
                     60:                        return (FALSE);
                     61:                }
                     62:                wp->w_ntrows = nrow-wp->w_toprow-2;
                     63:                sgarbf = TRUE;
                     64:                update();
                     65:                ewprintf("New size %d by %d", nrow, ncol);
                     66:        } else
                     67:                sgarbf = TRUE;
                     68:        return TRUE;
                     69: }
                     70:
                     71: /*
                     72:  * The command to make the next
                     73:  * window (next => down the screen)
                     74:  * the current window. There are no real
                     75:  * errors, although the command does
                     76:  * nothing if there is only 1 window on
                     77:  * the screen.
                     78:  */
                     79: /*ARGSUSED*/
                     80: nextwind(f, n)
                     81: {
1.2     ! millert    82:        register MGWIN *wp;
1.1       deraadt    83:
                     84:        if ((wp=curwp->w_wndp) == NULL)
                     85:                wp = wheadp;
                     86:        curwp = wp;
                     87:        curbp = wp->w_bufp;
                     88:        return TRUE;
                     89: }
                     90:
                     91: #ifdef GOSMACS
                     92: /* not in Gnu Emacs */
                     93: /*
                     94:  * This command makes the previous
                     95:  * window (previous => up the screen) the
                     96:  * current window. There arn't any errors,
                     97:  * although the command does not do a lot
                     98:  * if there is 1 window.
                     99:  */
                    100: /*ARGSUSED*/
                    101: prevwind(f, n)
                    102: {
1.2     ! millert   103:        register MGWIN *wp1;
        !           104:        register MGWIN *wp2;
1.1       deraadt   105:
                    106:        wp1 = wheadp;
                    107:        wp2 = curwp;
                    108:        if (wp1 == wp2)
                    109:                wp2 = NULL;
                    110:        while (wp1->w_wndp != wp2)
                    111:                wp1 = wp1->w_wndp;
                    112:        curwp = wp1;
                    113:        curbp = wp1->w_bufp;
                    114:        return TRUE;
                    115: }
                    116: #endif
                    117:
                    118: /*
                    119:  * This command makes the current
                    120:  * window the only window on the screen.
                    121:  * Try to set the framing
                    122:  * so that "." does not have to move on
                    123:  * the display. Some care has to be taken
                    124:  * to keep the values of dot and mark
                    125:  * in the buffer structures right if the
                    126:  * distruction of a window makes a buffer
                    127:  * become undisplayed.
                    128:  */
                    129: /*ARGSUSED*/
                    130: onlywind(f, n)
                    131: {
1.2     ! millert   132:        register MGWIN *wp;
1.1       deraadt   133:        register LINE   *lp;
                    134:        register int    i;
                    135:
                    136:        while (wheadp != curwp) {
                    137:                wp = wheadp;
                    138:                wheadp = wp->w_wndp;
                    139:                if (--wp->w_bufp->b_nwnd == 0) {
                    140:                        wp->w_bufp->b_dotp  = wp->w_dotp;
                    141:                        wp->w_bufp->b_doto  = wp->w_doto;
                    142:                        wp->w_bufp->b_markp = wp->w_markp;
                    143:                        wp->w_bufp->b_marko = wp->w_marko;
                    144:                }
                    145:                free((char *) wp);
                    146:        }
                    147:        while (curwp->w_wndp != NULL) {
                    148:                wp = curwp->w_wndp;
                    149:                curwp->w_wndp = wp->w_wndp;
                    150:                if (--wp->w_bufp->b_nwnd == 0) {
                    151:                        wp->w_bufp->b_dotp  = wp->w_dotp;
                    152:                        wp->w_bufp->b_doto  = wp->w_doto;
                    153:                        wp->w_bufp->b_markp = wp->w_markp;
                    154:                        wp->w_bufp->b_marko = wp->w_marko;
                    155:                }
                    156:                free((char *) wp);
                    157:        }
                    158:        lp = curwp->w_linep;
                    159:        i  = curwp->w_toprow;
                    160:        while (i!=0 && lback(lp)!=curbp->b_linep) {
                    161:                --i;
                    162:                lp = lback(lp);
                    163:        }
                    164:        curwp->w_toprow = 0;
                    165:        curwp->w_ntrows = nrow-2;               /* 2 = mode, echo.      */
                    166:        curwp->w_linep  = lp;
                    167:        curwp->w_flag  |= WFMODE|WFHARD;
                    168:        return TRUE;
                    169: }
                    170:
                    171: /*
                    172:  * Split the current window. A window
                    173:  * smaller than 3 lines cannot be split.
                    174:  * The only other error that is possible is
                    175:  * a "malloc" failure allocating the structure
                    176:  * for the new window.
                    177:  */
                    178: /*ARGSUSED*/
                    179: splitwind(f, n)
                    180: {
1.2     ! millert   181:        register MGWIN *wp;
1.1       deraadt   182:        register LINE   *lp;
                    183:        register int    ntru;
                    184:        register int    ntrd;
                    185:        int             ntrl;
1.2     ! millert   186:        MGWIN           *wp1, *wp2;
1.1       deraadt   187:
                    188:        if (curwp->w_ntrows < 3) {
                    189:                ewprintf("Cannot split a %d line window", curwp->w_ntrows);
                    190:                return (FALSE);
                    191:        }
1.2     ! millert   192:        if ((wp = (MGWIN *)malloc(sizeof(MGWIN))) == NULL) {
        !           193:                ewprintf("Can't get %d", sizeof(MGWIN));
1.1       deraadt   194:                return (FALSE);
                    195:        }
                    196:        ++curbp->b_nwnd;                        /* Displayed twice.     */
                    197:        wp->w_bufp  = curbp;
                    198:        wp->w_dotp  = curwp->w_dotp;
                    199:        wp->w_doto  = curwp->w_doto;
                    200:        wp->w_markp = curwp->w_markp;
                    201:        wp->w_marko = curwp->w_marko;
                    202:        wp->w_flag  = 0;
                    203:        wp->w_force = 0;
                    204:        ntru = (curwp->w_ntrows-1) / 2;         /* Upper size           */
                    205:        ntrl = (curwp->w_ntrows-1) - ntru;      /* Lower size           */
                    206:        lp = curwp->w_linep;
                    207:        ntrd = 0;
                    208:        while (lp != curwp->w_dotp) {
                    209:                ++ntrd;
                    210:                lp = lforw(lp);
                    211:        }
                    212:        lp = curwp->w_linep;
                    213:        if (ntrd <= ntru) {                     /* Old is upper window. */
                    214:                if (ntrd == ntru)               /* Hit mode line.       */
                    215:                        lp = lforw(lp);
                    216:                curwp->w_ntrows = ntru;
                    217:                wp->w_wndp = curwp->w_wndp;
                    218:                curwp->w_wndp = wp;
                    219:                wp->w_toprow = curwp->w_toprow+ntru+1;
                    220:                wp->w_ntrows = ntrl;
                    221:        } else {                                /* Old is lower window  */
                    222:                wp1 = NULL;
                    223:                wp2 = wheadp;
                    224:                while (wp2 != curwp) {
                    225:                        wp1 = wp2;
                    226:                        wp2 = wp2->w_wndp;
                    227:                }
                    228:                if (wp1 == NULL)
                    229:                        wheadp = wp;
                    230:                else
                    231:                        wp1->w_wndp = wp;
                    232:                wp->w_wndp   = curwp;
                    233:                wp->w_toprow = curwp->w_toprow;
                    234:                wp->w_ntrows = ntru;
                    235:                ++ntru;                         /* Mode line.           */
                    236:                curwp->w_toprow += ntru;
                    237:                curwp->w_ntrows  = ntrl;
                    238:                while (ntru--)
                    239:                        lp = lforw(lp);
                    240:        }
                    241:        curwp->w_linep = lp;                    /* Adjust the top lines */
                    242:        wp->w_linep = lp;                       /* if necessary.        */
                    243:        curwp->w_flag |= WFMODE|WFHARD;
                    244:        wp->w_flag |= WFMODE|WFHARD;
                    245:        return TRUE;
                    246: }
                    247:
                    248: /*
                    249:  * Enlarge the current window.
                    250:  * Find the window that loses space. Make
                    251:  * sure it is big enough. If so, hack the window
                    252:  * descriptions, and ask redisplay to do all the
                    253:  * hard work. You don't just set "force reframe"
                    254:  * because dot would move.
                    255:  */
                    256: /*ARGSUSED*/
                    257: enlargewind(f, n)
                    258: {
1.2     ! millert   259:        register MGWIN *adjwp;
1.1       deraadt   260:        register LINE   *lp;
                    261:        register int    i;
                    262:
                    263:        if (n < 0)
                    264:                return shrinkwind(f, -n);
                    265:        if (wheadp->w_wndp == NULL) {
                    266:                ewprintf("Only one window");
                    267:                return FALSE;
                    268:        }
                    269:        if ((adjwp=curwp->w_wndp) == NULL) {
                    270:                adjwp = wheadp;
                    271:                while (adjwp->w_wndp != curwp)
                    272:                        adjwp = adjwp->w_wndp;
                    273:        }
                    274:        if (adjwp->w_ntrows <= n) {
                    275:                ewprintf("Impossible change");
                    276:                return FALSE;
                    277:        }
                    278:        if (curwp->w_wndp == adjwp) {           /* Shrink below.        */
                    279:                lp = adjwp->w_linep;
                    280:                for (i=0; i<n && lp!=adjwp->w_bufp->b_linep; ++i)
                    281:                        lp = lforw(lp);
                    282:                adjwp->w_linep  = lp;
                    283:                adjwp->w_toprow += n;
                    284:        } else {                                /* Shrink above.        */
                    285:                lp = curwp->w_linep;
                    286:                for (i=0; i<n && lback(lp)!=curbp->b_linep; ++i)
                    287:                        lp = lback(lp);
                    288:                curwp->w_linep  = lp;
                    289:                curwp->w_toprow -= n;
                    290:        }
                    291:        curwp->w_ntrows += n;
                    292:        adjwp->w_ntrows -= n;
                    293:        curwp->w_flag |= WFMODE|WFHARD;
                    294:        adjwp->w_flag |= WFMODE|WFHARD;
                    295:        return TRUE;
                    296: }
                    297:
                    298: /*
                    299:  * Shrink the current window.
                    300:  * Find the window that gains space. Hack at
                    301:  * the window descriptions. Ask the redisplay to
                    302:  * do all the hard work.
                    303:  */
                    304: shrinkwind(f, n)
                    305: {
1.2     ! millert   306:        register MGWIN *adjwp;
1.1       deraadt   307:        register LINE   *lp;
                    308:        register int    i;
                    309:
                    310:        if (n < 0)
                    311:                return enlargewind(f, -n);
                    312:        if (wheadp->w_wndp == NULL) {
                    313:                ewprintf("Only one window");
                    314:                return FALSE;
                    315:        }
                    316:        /*
                    317:         * Bit of flakiness - KRANDOM means it was an internal call, and
                    318:         * to be trusted implicitly about sizes.
                    319:         */
                    320:        if ( !(f & FFRAND) && curwp->w_ntrows <= n) {
                    321:                ewprintf("Impossible change");
                    322:                return (FALSE);
                    323:        }
                    324:        if ((adjwp=curwp->w_wndp) == NULL) {
                    325:                adjwp = wheadp;
                    326:                while (adjwp->w_wndp != curwp)
                    327:                        adjwp = adjwp->w_wndp;
                    328:        }
                    329:        if (curwp->w_wndp == adjwp) {           /* Grow below.          */
                    330:                lp = adjwp->w_linep;
                    331:                for (i=0; i<n && lback(lp)!=adjwp->w_bufp->b_linep; ++i)
                    332:                        lp = lback(lp);
                    333:                adjwp->w_linep  = lp;
                    334:                adjwp->w_toprow -= n;
                    335:        } else {                                /* Grow above.          */
                    336:                lp = curwp->w_linep;
                    337:                for (i=0; i<n && lp!=curbp->b_linep; ++i)
                    338:                        lp = lforw(lp);
                    339:                curwp->w_linep  = lp;
                    340:                curwp->w_toprow += n;
                    341:        }
                    342:        curwp->w_ntrows -= n;
                    343:        adjwp->w_ntrows += n;
                    344:        curwp->w_flag |= WFMODE|WFHARD;
                    345:        adjwp->w_flag |= WFMODE|WFHARD;
                    346:        return (TRUE);
                    347: }
                    348:
                    349: /*
                    350:  * Delete current window. Call shrink-window to do the screen
                    351:  * updating, then throw away the window.
                    352:  */
                    353: /*ARGSUSED*/
                    354: delwind(f, n)
                    355: {
1.2     ! millert   356:        register MGWIN *wp, *nwp;
1.1       deraadt   357:
                    358:        wp = curwp;                     /* Cheap...             */
                    359:        /* shrinkwind returning false means only one window... */
                    360:        if (shrinkwind(FFRAND, wp->w_ntrows + 1) == FALSE)
                    361:                return FALSE;
                    362:        if (--wp->w_bufp->b_nwnd == 0) {
                    363:                wp->w_bufp->b_dotp  = wp->w_dotp;
                    364:                wp->w_bufp->b_doto  = wp->w_doto;
                    365:                wp->w_bufp->b_markp = wp->w_markp;
                    366:                wp->w_bufp->b_marko = wp->w_marko;
                    367:        }
                    368:        /* since shrinkwind did't crap out, we know we have a second window */
                    369:        if (wp == wheadp) wheadp = curwp = wp->w_wndp;
                    370:        else if ((curwp = wp->w_wndp) == NULL) curwp = wheadp;
                    371:        curbp = curwp->w_bufp;
                    372:        for (nwp = wheadp; nwp != NULL; nwp = nwp->w_wndp)
                    373:                if (nwp->w_wndp == wp) {
                    374:                        nwp->w_wndp = wp->w_wndp;
                    375:                        break ;
                    376:                }
                    377:        free((char *) wp);
                    378:        return TRUE;
                    379: }
                    380: /*
                    381:  * Pick a window for a pop-up.
                    382:  * Split the screen if there is only
                    383:  * one window. Pick the uppermost window that
                    384:  * isn't the current window. An LRU algorithm
                    385:  * might be better. Return a pointer, or
                    386:  * NULL on error.
                    387:  */
1.2     ! millert   388: MGWIN  *
1.1       deraadt   389: wpopup() {
1.2     ! millert   390:        register MGWIN *wp;
1.1       deraadt   391:
                    392:        if (wheadp->w_wndp == NULL
                    393:        && splitwind(FFRAND, 0) == FALSE)
                    394:                return NULL;
                    395:        wp = wheadp;                            /* Find window to use   */
                    396:        while (wp!=NULL && wp==curwp)
                    397:                wp = wp->w_wndp;
                    398:        return wp;
                    399: }