1 /* $OpenBSD: window.c,v 1.28 2011/08/01 12:15:23 lum Exp $ */
3 /* This file is in the public domain. */
12 new_window(struct buffer *bp)
16 wp = calloc(1, sizeof(struct mgwin));
27 wp->w_wrapline = NULL;
28 wp->w_dotline = wp->w_markline = 1;
35 * Reposition dot in the current window to line "n". If the argument is
36 * positive, it is that line. If it is negative it is that line from the
37 * bottom. If it is 0 the window is centered (this is what the standard
38 * redisplay code does). If GOSREC is undefined, default is 0, so it acts
39 * like GNU. If GOSREC is defined, with no argument it defaults to 1 and
40 * works like in Gosling.
44 reposition(int f, int n)
47 curwp->w_frame = (f & FFARG) ? (n >= 0 ? n + 1 : n) : 0;
51 curwp->w_rflag |= WFFRAME;
57 * Refresh the display. A call is made to the "ttresize" entry in the
58 * terminal handler, which tries to reset "nrow" and "ncol". They will,
59 * however, never be set outside of the NROW or NCOL range. If the display
60 * changed size, arrange that everything is redone, then call "update" to
61 * fix the display. We do this so the new size can be displayed. In the
62 * normal case the call to "update" in "main.c" refreshes the screen, and
63 * all of the windows need not be recomputed. This call includes a
64 * 'force' parameter to ensure that the redraw is done, even after a
65 * a suspend/continue (where the window size parameters will already
66 * be updated). Note that when you get to the "display unusable"
67 * message, the screen will be messed up. If you make the window bigger
68 * again, and send another command, everything will get fixed!
73 return (do_redraw(f, n, FALSE));
78 do_redraw(int f, int n, int force)
86 if (nrow != oldnrow || ncol != oldncol || force) {
90 while (wp->w_wndp != NULL)
93 /* check if too small */
94 if (nrow < wp->w_toprow + 3) {
95 ewprintf("Display unusable");
98 wp->w_ntrows = nrow - wp->w_toprow - 2;
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
109 * there is only 1 window on the screen.
113 nextwind(int f, int n)
117 if ((wp = curwp->w_wndp) == NULL)
124 /* not in GNU Emacs */
126 * This command makes the previous window (previous => up the screen) the
127 * current window. There are no errors, although the command does not do
128 * a lot if there is only 1 window.
132 prevwind(int f, int n)
134 struct mgwin *wp1, *wp2;
140 while (wp1->w_wndp != wp2)
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
151 * structures right if the destruction of a window makes a buffer become
156 onlywind(int f, int n)
162 while (wheadp != curwp) {
165 if (--wp->w_bufp->b_nwnd == 0) {
166 wp->w_bufp->b_dotp = wp->w_dotp;
167 wp->w_bufp->b_doto = wp->w_doto;
168 wp->w_bufp->b_markp = wp->w_markp;
169 wp->w_bufp->b_marko = wp->w_marko;
173 while (curwp->w_wndp != NULL) {
175 curwp->w_wndp = wp->w_wndp;
176 if (--wp->w_bufp->b_nwnd == 0) {
177 wp->w_bufp->b_dotp = wp->w_dotp;
178 wp->w_bufp->b_doto = wp->w_doto;
179 wp->w_bufp->b_markp = wp->w_markp;
180 wp->w_bufp->b_marko = wp->w_marko;
186 while (i != 0 && lback(lp) != curbp->b_headp) {
193 curwp->w_ntrows = nrow - 2;
195 curwp->w_rflag |= WFMODE | WFFULL;
200 * Split the current window. A window smaller than 3 lines cannot be split.
201 * The only other error that is possible is a "malloc" failure allocating the
202 * structure for the new window.
203 * If called with a FFOTHARG, flags on the new window are set to 'n'.
207 splitwind(int f, int n)
209 struct mgwin *wp, *wp1, *wp2;
211 int ntru, ntrd, ntrl;
213 if (curwp->w_ntrows < 3) {
214 ewprintf("Cannot split a %d line window", curwp->w_ntrows);
217 wp = new_window(curbp);
219 ewprintf("Unable to create a window");
223 /* use the current dot and mark */
224 wp->w_dotp = curwp->w_dotp;
225 wp->w_doto = curwp->w_doto;
226 wp->w_markp = curwp->w_markp;
227 wp->w_marko = curwp->w_marko;
228 wp->w_dotline = curwp->w_dotline;
229 wp->w_markline = curwp->w_markline;
231 /* figure out which half of the screen we're in */
232 ntru = (curwp->w_ntrows - 1) / 2; /* Upper size */
233 ntrl = (curwp->w_ntrows - 1) - ntru; /* Lower size */
235 for (lp = curwp->w_linep, ntrd = 0; lp != curwp->w_dotp;
241 /* old is upper window */
246 curwp->w_ntrows = ntru;
247 wp->w_wndp = curwp->w_wndp;
249 wp->w_toprow = curwp->w_toprow + ntru + 1;
251 /* old is lower window */
255 while (wp2 != curwp) {
264 wp->w_toprow = curwp->w_toprow;
269 curwp->w_toprow += ntru;
270 curwp->w_ntrows = ntrl;
275 /* adjust the top lines if necessary */
279 curwp->w_rflag |= WFMODE | WFFULL;
280 wp->w_rflag |= WFMODE | WFFULL;
281 /* if FFOTHARG, set flags) */
289 * Enlarge the current window. Find the window that loses space. Make sure
290 * it is big enough. If so, hack the window descriptions, and ask redisplay
291 * to do all the hard work. You don't just set "force reframe" because dot
296 enlargewind(int f, int n)
303 return (shrinkwind(f, -n));
304 if (wheadp->w_wndp == NULL) {
305 ewprintf("Only one window");
308 if ((adjwp = curwp->w_wndp) == NULL) {
310 while (adjwp->w_wndp != curwp)
311 adjwp = adjwp->w_wndp;
313 if (adjwp->w_ntrows <= n) {
314 ewprintf("Impossible change");
319 if (curwp->w_wndp == adjwp) {
321 for (i = 0; i < n && lp != adjwp->w_bufp->b_headp; ++i)
324 adjwp->w_toprow += n;
328 for (i = 0; i < n && lback(lp) != curbp->b_headp; ++i)
331 curwp->w_toprow -= n;
333 curwp->w_ntrows += n;
334 adjwp->w_ntrows -= n;
335 curwp->w_rflag |= WFMODE | WFFULL;
336 adjwp->w_rflag |= WFMODE | WFFULL;
341 * Shrink the current window. Find the window that gains space. Hack at the
342 * window descriptions. Ask the redisplay to do all the hard work.
345 shrinkwind(int f, int n)
352 return (enlargewind(f, -n));
353 if (wheadp->w_wndp == NULL) {
354 ewprintf("Only one window");
358 * Bit of flakiness - KRANDOM means it was an internal call, and
359 * to be trusted implicitly about sizes.
361 if (!(f & FFRAND) && curwp->w_ntrows <= n) {
362 ewprintf("Impossible change");
365 if ((adjwp = curwp->w_wndp) == NULL) {
367 while (adjwp->w_wndp != curwp)
368 adjwp = adjwp->w_wndp;
372 if (curwp->w_wndp == adjwp) {
374 for (i = 0; i < n && lback(lp) != adjwp->w_bufp->b_headp; ++i)
377 adjwp->w_toprow -= n;
381 for (i = 0; i < n && lp != curbp->b_headp; ++i)
384 curwp->w_toprow += n;
386 curwp->w_ntrows -= n;
387 adjwp->w_ntrows += n;
388 curwp->w_rflag |= WFMODE | WFFULL;
389 adjwp->w_rflag |= WFMODE | WFFULL;
394 * Delete current window. Call shrink-window to do the screen updating, then
395 * throw away the window.
399 delwind(int f, int n)
401 struct mgwin *wp, *nwp;
403 wp = curwp; /* Cheap... */
405 /* shrinkwind returning false means only one window... */
406 if (shrinkwind(FFRAND, wp->w_ntrows + 1) == FALSE)
408 if (--wp->w_bufp->b_nwnd == 0) {
409 wp->w_bufp->b_dotp = wp->w_dotp;
410 wp->w_bufp->b_doto = wp->w_doto;
411 wp->w_bufp->b_markp = wp->w_markp;
412 wp->w_bufp->b_marko = wp->w_marko;
415 /* since shrinkwind did't crap out, we know we have a second window */
417 wheadp = curwp = wp->w_wndp;
418 else if ((curwp = wp->w_wndp) == NULL)
420 curbp = curwp->w_bufp;
421 for (nwp = wheadp; nwp != NULL; nwp = nwp->w_wndp)
422 if (nwp->w_wndp == wp) {
423 nwp->w_wndp = wp->w_wndp;