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: }