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