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

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