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

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