[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.3

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:  */
1.3     ! millert    16: /* ARGSUSED */
1.1       deraadt    17: reposition(f, n)
                     18: {
                     19: #ifndef GOSREC
1.3     ! millert    20:        curwp->w_force = (f & FFARG) ? (n >= 0 ? n + 1 : n) : 0;
1.1       deraadt    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:  */
1.3     ! millert    44: /* ARGSUSED */
1.1       deraadt    45: refresh(f, n)
                     46: {
1.2       millert    47:        register MGWIN *wp;
1.3     ! millert    48:        register int    oldnrow;
        !            49:        register int    oldncol;
1.1       deraadt    50:
                     51:        oldnrow = nrow;
                     52:        oldncol = ncol;
                     53:        ttresize();
1.3     ! millert    54:        if (nrow != oldnrow || ncol != oldncol) {
        !            55:                wp = wheadp;    /* Find last.            */
1.1       deraadt    56:                while (wp->w_wndp != NULL)
                     57:                        wp = wp->w_wndp;
1.3     ! millert    58:                if (nrow < wp->w_toprow + 3) {  /* Check if too small.   */
1.1       deraadt    59:                        ewprintf("Display unusable");
                     60:                        return (FALSE);
                     61:                }
1.3     ! millert    62:                wp->w_ntrows = nrow - wp->w_toprow - 2;
1.1       deraadt    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:  */
1.3     ! millert    79: /* ARGSUSED */
1.1       deraadt    80: nextwind(f, n)
                     81: {
1.2       millert    82:        register MGWIN *wp;
1.1       deraadt    83:
1.3     ! millert    84:        if ((wp = curwp->w_wndp) == NULL)
1.1       deraadt    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:  */
1.3     ! millert   100: /* ARGSUSED */
1.1       deraadt   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:  */
1.3     ! millert   129: /* ARGSUSED */
1.1       deraadt   130: onlywind(f, n)
                    131: {
1.2       millert   132:        register MGWIN *wp;
1.3     ! millert   133:        register LINE  *lp;
        !           134:        register int    i;
1.1       deraadt   135:
                    136:        while (wheadp != curwp) {
                    137:                wp = wheadp;
                    138:                wheadp = wp->w_wndp;
                    139:                if (--wp->w_bufp->b_nwnd == 0) {
1.3     ! millert   140:                        wp->w_bufp->b_dotp = wp->w_dotp;
        !           141:                        wp->w_bufp->b_doto = wp->w_doto;
1.1       deraadt   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) {
1.3     ! millert   151:                        wp->w_bufp->b_dotp = wp->w_dotp;
        !           152:                        wp->w_bufp->b_doto = wp->w_doto;
1.1       deraadt   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;
1.3     ! millert   159:        i = curwp->w_toprow;
        !           160:        while (i != 0 && lback(lp) != curbp->b_linep) {
1.1       deraadt   161:                --i;
                    162:                lp = lback(lp);
                    163:        }
                    164:        curwp->w_toprow = 0;
1.3     ! millert   165:        curwp->w_ntrows = nrow - 2;     /* 2 = mode, echo.       */
        !           166:        curwp->w_linep = lp;
        !           167:        curwp->w_flag |= WFMODE | WFHARD;
1.1       deraadt   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:  */
1.3     ! millert   178: /* ARGSUSED */
1.1       deraadt   179: splitwind(f, n)
                    180: {
1.2       millert   181:        register MGWIN *wp;
1.3     ! millert   182:        register LINE  *lp;
        !           183:        register int    ntru;
        !           184:        register int    ntrd;
        !           185:        int             ntrl;
        !           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.3     ! millert   192:        if ((wp = (MGWIN *) malloc(sizeof(MGWIN))) == NULL) {
1.2       millert   193:                ewprintf("Can't get %d", sizeof(MGWIN));
1.1       deraadt   194:                return (FALSE);
                    195:        }
1.3     ! millert   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;
1.1       deraadt   200:        wp->w_markp = curwp->w_markp;
                    201:        wp->w_marko = curwp->w_marko;
1.3     ! millert   202:        wp->w_flag = 0;
1.1       deraadt   203:        wp->w_force = 0;
1.3     ! millert   204:        ntru = (curwp->w_ntrows - 1) / 2;       /* Upper size            */
        !           205:        ntrl = (curwp->w_ntrows - 1) - ntru;    /* Lower size            */
1.1       deraadt   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;
1.3     ! millert   213:        if (ntrd <= ntru) {     /* Old is upper window. */
        !           214:                if (ntrd == ntru)       /* Hit mode line.        */
1.1       deraadt   215:                        lp = lforw(lp);
                    216:                curwp->w_ntrows = ntru;
                    217:                wp->w_wndp = curwp->w_wndp;
                    218:                curwp->w_wndp = wp;
1.3     ! millert   219:                wp->w_toprow = curwp->w_toprow + ntru + 1;
1.1       deraadt   220:                wp->w_ntrows = ntrl;
1.3     ! millert   221:        } else {                /* Old is lower window   */
1.1       deraadt   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;
1.3     ! millert   232:                wp->w_wndp = curwp;
1.1       deraadt   233:                wp->w_toprow = curwp->w_toprow;
                    234:                wp->w_ntrows = ntru;
1.3     ! millert   235:                ++ntru;         /* Mode line.            */
1.1       deraadt   236:                curwp->w_toprow += ntru;
1.3     ! millert   237:                curwp->w_ntrows = ntrl;
1.1       deraadt   238:                while (ntru--)
                    239:                        lp = lforw(lp);
                    240:        }
1.3     ! millert   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;
1.1       deraadt   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:  */
1.3     ! millert   256: /* ARGSUSED */
1.1       deraadt   257: enlargewind(f, n)
                    258: {
1.2       millert   259:        register MGWIN *adjwp;
1.3     ! millert   260:        register LINE  *lp;
        !           261:        register int    i;
1.1       deraadt   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:        }
1.3     ! millert   269:        if ((adjwp = curwp->w_wndp) == NULL) {
1.1       deraadt   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:        }
1.3     ! millert   278:        if (curwp->w_wndp == adjwp) {   /* Shrink below.         */
1.1       deraadt   279:                lp = adjwp->w_linep;
1.3     ! millert   280:                for (i = 0; i < n && lp != adjwp->w_bufp->b_linep; ++i)
1.1       deraadt   281:                        lp = lforw(lp);
1.3     ! millert   282:                adjwp->w_linep = lp;
1.1       deraadt   283:                adjwp->w_toprow += n;
1.3     ! millert   284:        } else {                /* Shrink above.         */
1.1       deraadt   285:                lp = curwp->w_linep;
1.3     ! millert   286:                for (i = 0; i < n && lback(lp) != curbp->b_linep; ++i)
1.1       deraadt   287:                        lp = lback(lp);
1.3     ! millert   288:                curwp->w_linep = lp;
1.1       deraadt   289:                curwp->w_toprow -= n;
                    290:        }
                    291:        curwp->w_ntrows += n;
                    292:        adjwp->w_ntrows -= n;
1.3     ! millert   293:        curwp->w_flag |= WFMODE | WFHARD;
        !           294:        adjwp->w_flag |= WFMODE | WFHARD;
1.1       deraadt   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.3     ! millert   307:        register LINE  *lp;
        !           308:        register int    i;
1.1       deraadt   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:         */
1.3     ! millert   320:        if (!(f & FFRAND) && curwp->w_ntrows <= n) {
1.1       deraadt   321:                ewprintf("Impossible change");
                    322:                return (FALSE);
                    323:        }
1.3     ! millert   324:        if ((adjwp = curwp->w_wndp) == NULL) {
1.1       deraadt   325:                adjwp = wheadp;
                    326:                while (adjwp->w_wndp != curwp)
                    327:                        adjwp = adjwp->w_wndp;
                    328:        }
1.3     ! millert   329:        if (curwp->w_wndp == adjwp) {   /* Grow below.           */
1.1       deraadt   330:                lp = adjwp->w_linep;
1.3     ! millert   331:                for (i = 0; i < n && lback(lp) != adjwp->w_bufp->b_linep; ++i)
1.1       deraadt   332:                        lp = lback(lp);
1.3     ! millert   333:                adjwp->w_linep = lp;
1.1       deraadt   334:                adjwp->w_toprow -= n;
1.3     ! millert   335:        } else {                /* Grow above.           */
1.1       deraadt   336:                lp = curwp->w_linep;
1.3     ! millert   337:                for (i = 0; i < n && lp != curbp->b_linep; ++i)
1.1       deraadt   338:                        lp = lforw(lp);
1.3     ! millert   339:                curwp->w_linep = lp;
1.1       deraadt   340:                curwp->w_toprow += n;
                    341:        }
                    342:        curwp->w_ntrows -= n;
                    343:        adjwp->w_ntrows += n;
1.3     ! millert   344:        curwp->w_flag |= WFMODE | WFHARD;
        !           345:        adjwp->w_flag |= WFMODE | WFHARD;
1.1       deraadt   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:  */
1.3     ! millert   353: /* ARGSUSED */
1.1       deraadt   354: delwind(f, n)
                    355: {
1.2       millert   356:        register MGWIN *wp, *nwp;
1.1       deraadt   357:
1.3     ! millert   358:        wp = curwp;             /* Cheap...              */
1.1       deraadt   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) {
1.3     ! millert   363:                wp->w_bufp->b_dotp = wp->w_dotp;
        !           364:                wp->w_bufp->b_doto = wp->w_doto;
1.1       deraadt   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 */
1.3     ! millert   369:        if (wp == wheadp)
        !           370:                wheadp = curwp = wp->w_wndp;
        !           371:        else if ((curwp = wp->w_wndp) == NULL)
        !           372:                curwp = wheadp;
1.1       deraadt   373:        curbp = curwp->w_bufp;
                    374:        for (nwp = wheadp; nwp != NULL; nwp = nwp->w_wndp)
                    375:                if (nwp->w_wndp == wp) {
                    376:                        nwp->w_wndp = wp->w_wndp;
1.3     ! millert   377:                        break;
1.1       deraadt   378:                }
                    379:        free((char *) wp);
                    380:        return TRUE;
                    381: }
                    382: /*
                    383:  * Pick a window for a pop-up.
                    384:  * Split the screen if there is only
                    385:  * one window. Pick the uppermost window that
                    386:  * isn't the current window. An LRU algorithm
                    387:  * might be better. Return a pointer, or
                    388:  * NULL on error.
                    389:  */
1.3     ! millert   390: MGWIN *
        !           391: wpopup()
        !           392: {
1.2       millert   393:        register MGWIN *wp;
1.1       deraadt   394:
                    395:        if (wheadp->w_wndp == NULL
1.3     ! millert   396:            && splitwind(FFRAND, 0) == FALSE)
1.1       deraadt   397:                return NULL;
1.3     ! millert   398:        wp = wheadp;            /* Find window to use    */
        !           399:        while (wp != NULL && wp == curwp)
1.1       deraadt   400:                wp = wp->w_wndp;
                    401:        return wp;
                    402: }