GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/mg/window.c Lines: 0 207 0.0 %
Date: 2017-11-07 Branches: 0 100 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: window.c,v 1.36 2015/11/18 18:21:06 jasper Exp $	*/
2
3
/* This file is in the public domain. */
4
5
/*
6
 *		Window handling.
7
 */
8
9
#include <sys/queue.h>
10
#include <signal.h>
11
#include <stdio.h>
12
#include <stdlib.h>
13
14
#include "def.h"
15
16
struct mgwin *
17
new_window(struct buffer *bp)
18
{
19
	struct mgwin *wp;
20
21
	wp = calloc(1, sizeof(struct mgwin));
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;
30
	wp->w_rflag = 0;
31
	wp->w_frame = 0;
32
	wp->w_wrapline = NULL;
33
	wp->w_dotline = wp->w_markline = 1;
34
	if (bp)
35
		bp->b_nwnd++;
36
	return (wp);
37
}
38
39
/*
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).
44
 */
45
/* ARGSUSED */
46
int
47
reposition(int f, int n)
48
{
49
	curwp->w_frame = (f & FFARG) ? (n >= 0 ? n + 1 : n) : 0;
50
	curwp->w_rflag |= WFFRAME;
51
	sgarbf = TRUE;
52
	return (TRUE);
53
}
54
55
/*
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,
58
 * however, never be set outside of the NROW or NCOL range.  If the display
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. 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!
68
 */
69
int
70
redraw(int f, int n)
71
{
72
	return (do_redraw(f, n, FALSE));
73
}
74
75
/* ARGSUSED */
76
int
77
do_redraw(int f, int n, int force)
78
{
79
	struct mgwin	*wp;
80
	int		 oldnrow, oldncol;
81
82
	oldnrow = nrow;
83
	oldncol = ncol;
84
	ttresize();
85
	if (nrow != oldnrow || ncol != oldncol || force) {
86
87
		/* find last */
88
		wp = wheadp;
89
		while (wp->w_wndp != NULL)
90
			wp = wp->w_wndp;
91
92
		/* check if too small */
93
		if (nrow < wp->w_toprow + 3) {
94
			dobeep();
95
			ewprintf("Display unusable");
96
			return (FALSE);
97
		}
98
		wp->w_ntrows = nrow - wp->w_toprow - 2;
99
		sgarbf = TRUE;
100
		update(CMODE);
101
	} else
102
		sgarbf = TRUE;
103
	return (TRUE);
104
}
105
106
/*
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.
110
 */
111
/* ARGSUSED */
112
int
113
nextwind(int f, int n)
114
{
115
	struct mgwin	*wp;
116
117
	if ((wp = curwp->w_wndp) == NULL)
118
		wp = wheadp;
119
	curwp = wp;
120
	curbp = wp->w_bufp;
121
	return (TRUE);
122
}
123
124
/* not in GNU Emacs */
125
/*
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.
129
 */
130
/* ARGSUSED */
131
int
132
prevwind(int f, int n)
133
{
134
	struct mgwin	*wp1, *wp2;
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;
144
	return (TRUE);
145
}
146
147
/*
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
152
 * undisplayed.
153
 */
154
/* ARGSUSED */
155
int
156
onlywind(int f, int n)
157
{
158
	struct mgwin	*wp;
159
	struct line	*lp;
160
	int		 i;
161
162
	while (wheadp != curwp) {
163
		wp = wheadp;
164
		wheadp = wp->w_wndp;
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;
170
			wp->w_bufp->b_dotline = wp->w_dotline;
171
			wp->w_bufp->b_markline = wp->w_markline;
172
		}
173
		free(wp);
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) {
179
			wp->w_bufp->b_dotp = wp->w_dotp;
180
			wp->w_bufp->b_doto = wp->w_doto;
181
			wp->w_bufp->b_markp = wp->w_markp;
182
			wp->w_bufp->b_marko = wp->w_marko;
183
			wp->w_bufp->b_dotline = wp->w_dotline;
184
			wp->w_bufp->b_markline = wp->w_markline;
185
		}
186
		free(wp);
187
	}
188
	lp = curwp->w_linep;
189
	i = curwp->w_toprow;
190
	while (i != 0 && lback(lp) != curbp->b_headp) {
191
		--i;
192
		lp = lback(lp);
193
	}
194
	curwp->w_toprow = 0;
195
196
	/* 2 = mode, echo */
197
	curwp->w_ntrows = nrow - 2;
198
	curwp->w_linep = lp;
199
	curwp->w_rflag |= WFMODE | WFFULL;
200
	return (TRUE);
201
}
202
203
/*
204
 * Split the current window.  A window smaller than 3 lines cannot be split.
205
 * The only other error that is possible is a "malloc" failure allocating the
206
 * structure for the new window.
207
 * If called with a FFOTHARG, flags on the new window are set to 'n'.
208
 */
209
/* ARGSUSED */
210
int
211
splitwind(int f, int n)
212
{
213
	struct mgwin	*wp, *wp1, *wp2;
214
	struct line	*lp;
215
	int		 ntru, ntrd, ntrl;
216
217
	if (curwp->w_ntrows < 3) {
218
		dobeep();
219
		ewprintf("Cannot split a %d line window", curwp->w_ntrows);
220
		return (FALSE);
221
	}
222
	wp = new_window(curbp);
223
	if (wp == NULL) {
224
		dobeep();
225
		ewprintf("Unable to create a window");
226
		return (FALSE);
227
	}
228
229
	/* use the current dot and mark */
230
	wp->w_dotp = curwp->w_dotp;
231
	wp->w_doto = curwp->w_doto;
232
	wp->w_markp = curwp->w_markp;
233
	wp->w_marko = curwp->w_marko;
234
	wp->w_dotline = curwp->w_dotline;
235
	wp->w_markline = curwp->w_markline;
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
245
	lp = curwp->w_linep;
246
247
	/* old is upper window */
248
	if (ntrd <= ntru) {
249
		/* hit mode line */
250
		if (ntrd == ntru)
251
			lp = lforw(lp);
252
		curwp->w_ntrows = ntru;
253
		wp->w_wndp = curwp->w_wndp;
254
		curwp->w_wndp = wp;
255
		wp->w_toprow = curwp->w_toprow + ntru + 1;
256
		wp->w_ntrows = ntrl;
257
	/* old is lower window */
258
	} else {
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;
269
		wp->w_wndp = curwp;
270
		wp->w_toprow = curwp->w_toprow;
271
		wp->w_ntrows = ntru;
272
273
		/* mode line */
274
		++ntru;
275
		curwp->w_toprow += ntru;
276
		curwp->w_ntrows = ntrl;
277
		while (ntru--)
278
			lp = lforw(lp);
279
	}
280
281
	/* adjust the top lines if necessary */
282
	curwp->w_linep = lp;
283
	wp->w_linep = lp;
284
285
	curwp->w_rflag |= WFMODE | WFFULL;
286
	wp->w_rflag |= WFMODE | WFFULL;
287
	/* if FFOTHARG, set flags) */
288
	if (f & FFOTHARG)
289
		wp->w_flag = n;
290
291
	return (TRUE);
292
}
293
294
/*
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
298
 * would move.
299
 */
300
/* ARGSUSED */
301
int
302
enlargewind(int f, int n)
303
{
304
	struct mgwin	*adjwp;
305
	struct line	*lp;
306
	int		 i;
307
308
	if (n < 0)
309
		return (shrinkwind(f, -n));
310
	if (wheadp->w_wndp == NULL) {
311
		dobeep();
312
		ewprintf("Only one window");
313
		return (FALSE);
314
	}
315
	if ((adjwp = curwp->w_wndp) == NULL) {
316
		adjwp = wheadp;
317
		while (adjwp->w_wndp != curwp)
318
			adjwp = adjwp->w_wndp;
319
	}
320
	if (adjwp->w_ntrows <= n) {
321
		dobeep();
322
		ewprintf("Impossible change");
323
		return (FALSE);
324
	}
325
326
	/* shrink below */
327
	if (curwp->w_wndp == adjwp) {
328
		lp = adjwp->w_linep;
329
		for (i = 0; i < n && lp != adjwp->w_bufp->b_headp; ++i)
330
			lp = lforw(lp);
331
		adjwp->w_linep = lp;
332
		adjwp->w_toprow += n;
333
	/* shrink above */
334
	} else {
335
		lp = curwp->w_linep;
336
		for (i = 0; i < n && lback(lp) != curbp->b_headp; ++i)
337
			lp = lback(lp);
338
		curwp->w_linep = lp;
339
		curwp->w_toprow -= n;
340
	}
341
	curwp->w_ntrows += n;
342
	adjwp->w_ntrows -= n;
343
	curwp->w_rflag |= WFMODE | WFFULL;
344
	adjwp->w_rflag |= WFMODE | WFFULL;
345
	return (TRUE);
346
}
347
348
/*
349
 * Shrink the current window.  Find the window that gains space.  Hack at the
350
 * window descriptions. Ask the redisplay to do all the hard work.
351
 */
352
int
353
shrinkwind(int f, int n)
354
{
355
	struct mgwin	*adjwp;
356
	struct line	*lp;
357
	int		 i;
358
359
	if (n < 0)
360
		return (enlargewind(f, -n));
361
	if (wheadp->w_wndp == NULL) {
362
		dobeep();
363
		ewprintf("Only one window");
364
		return (FALSE);
365
	}
366
	/*
367
	 * Bit of flakiness - FFRAND means it was an internal call, and
368
	 * to be trusted implicitly about sizes.
369
	 */
370
	if (!(f & FFRAND) && curwp->w_ntrows <= n) {
371
		dobeep();
372
		ewprintf("Impossible change");
373
		return (FALSE);
374
	}
375
	if ((adjwp = curwp->w_wndp) == NULL) {
376
		adjwp = wheadp;
377
		while (adjwp->w_wndp != curwp)
378
			adjwp = adjwp->w_wndp;
379
	}
380
381
	/* grow below */
382
	if (curwp->w_wndp == adjwp) {
383
		lp = adjwp->w_linep;
384
		for (i = 0; i < n && lback(lp) != adjwp->w_bufp->b_headp; ++i)
385
			lp = lback(lp);
386
		adjwp->w_linep = lp;
387
		adjwp->w_toprow -= n;
388
	/* grow above */
389
	} else {
390
		lp = curwp->w_linep;
391
		for (i = 0; i < n && lp != curbp->b_headp; ++i)
392
			lp = lforw(lp);
393
		curwp->w_linep = lp;
394
		curwp->w_toprow += n;
395
	}
396
	curwp->w_ntrows -= n;
397
	adjwp->w_ntrows += n;
398
	curwp->w_rflag |= WFMODE | WFFULL;
399
	adjwp->w_rflag |= WFMODE | WFFULL;
400
	return (TRUE);
401
}
402
403
/*
404
 * Delete current window. Call shrink-window to do the screen updating, then
405
 * throw away the window.
406
 */
407
/* ARGSUSED */
408
int
409
delwind(int f, int n)
410
{
411
	struct mgwin	*wp, *nwp;
412
413
	wp = curwp;		/* Cheap...		 */
414
415
	/* shrinkwind returning false means only one window... */
416
	if (shrinkwind(FFRAND, wp->w_ntrows + 1) == FALSE)
417
		return (FALSE);
418
	if (--wp->w_bufp->b_nwnd == 0) {
419
		wp->w_bufp->b_dotp = wp->w_dotp;
420
		wp->w_bufp->b_doto = wp->w_doto;
421
		wp->w_bufp->b_markp = wp->w_markp;
422
		wp->w_bufp->b_marko = wp->w_marko;
423
		wp->w_bufp->b_dotline = wp->w_dotline;
424
		wp->w_bufp->b_markline = wp->w_markline;
425
	}
426
427
	/* since shrinkwind did't crap out, we know we have a second window */
428
	if (wp == wheadp)
429
		wheadp = curwp = wp->w_wndp;
430
	else if ((curwp = wp->w_wndp) == NULL)
431
		curwp = wheadp;
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;
436
			break;
437
		}
438
	free(wp);
439
	return (TRUE);
440
}