1 /*	SCREEN.C:	Screen manipulation commands
2 			for MicroEMACS 4.00
3 			written by Daniel Lawrence
4 */
5 
6 #include	<stdio.h>
7 #include	"estruct.h"
8 #include	"eproto.h"
9 #include        "edef.h"
10 #include	"elang.h"
11 
12 #if	0
13 dumpscreens(msg)
14 
15 char *msg;
16 
17 {
18 	SCREEN *sp;
19 
20 	printf("<%s>\n", msg);
21 	sp = first_screen;
22 	while (sp != (SCREEN *)NULL) {
23 		printf("%lu - [%s] %d/%d to %d/%d \n", sp, sp->s_screen_name,
24 		sp->s_roworg, sp->s_colorg, sp->s_nrow, sp->s_ncol);
25 		sp = sp->s_next_screen;
26 	}
27 	printf("   0     -   [EOL]\n");
28 	tgetc();
29 }
30 #endif
31 
32 #if	WINDOW_TEXT
33 /* Redraw given screen and all screens behind it */
34 
refresh_screen(sp)35 VOID PASCAL NEAR refresh_screen(sp)
36 
37 SCREEN *sp;	/* screen image to refresh */
38 
39 {
40 	/* if we are suppressing redraws */
41 	if (gflags & GFSDRAW)
42 		return;
43 
44 	/* at end of list, do nothing */
45 	if (sp == (SCREEN *)NULL)
46 		return;
47 
48 	/* if first refresh, erase the page */
49 	if (sp == first_screen) {
50 		(*term.t_clrdesk)();
51 		if (sp->s_next_screen == (SCREEN *)NULL)
52 			sgarbf = TRUE;
53 	}
54 
55 	/* if there are others below, defer to them first */
56 	if (sp->s_next_screen)
57 		refresh_screen(sp->s_next_screen);
58 
59 	select_screen(sp, FALSE);
60 	update(TRUE);
61 }
62 #endif
63 
64 /*	This command takes the last window in the linked window list,
65 	which is visibly rearmost, and brings it to front. It is bound
66 	to A-N on machines with an ALT key
67 */
68 
cycle_screens(f,n)69 PASCAL NEAR cycle_screens(f, n)
70 
71 int f,n;	/* prefix flag and argument */
72 
73 {
74 	SCREEN *sp;		/* ptr to screen to switch to */
75 
76 	/* find the last screen */
77 	sp = first_screen;
78 	while (sp->s_next_screen != (SCREEN *)NULL)
79 		sp = sp->s_next_screen;
80 
81 	/* and make this screen current */
82 	return(select_screen(sp, TRUE));
83 }
84 
find_screen(f,n)85 PASCAL NEAR find_screen(f, n)
86 
87 int f,n;	/* prefix flag and argument */
88 
89 {
90 	char scr_name[NSTRING];	/* buffer to hold screen name */
91 	SCREEN *sp;		/* ptr to screen to switch to */
92 	int result;
93 
94 	/* get the name of the screen to switch to */
95 	if ((result = mlreply(TEXT242, scr_name, NSTRING)) != TRUE) {
96 	    /* "Find Screen: " */
97             return result;
98         }
99 	sp = lookup_screen(scr_name);
100 
101 	if (sp == (SCREEN *)NULL) {
102 
103 		/* save the current dot position in the buffer info
104 		   so the new screen will start there! */
105 		curbp->b_dotp = curwp->w_dotp;
106 		curbp->b_doto = curwp->w_doto;
107 
108 		/* screen does not exist, create it */
109 		sp = init_screen(scr_name, curbp);
110 	}
111 
112 	/* and make this screen current */
113 	return(select_screen(sp, TRUE));
114 }
115 
free_screen(sp)116 PASCAL NEAR free_screen(sp)	/* free all resouces associated with a screen */
117 
118 SCREEN *sp;	/* screen to dump */
119 
120 {
121 	register int cmark;	/* mark ordinal index */
122 	register EWINDOW *wp;	/* ptr to window to free */
123 	register EWINDOW *tp;	/* temp window pointer */
124 
125 	/* first, free the screen's windows */
126 	wp = sp->s_first_window;
127 	while (wp) {
128 		if (--wp->w_bufp->b_nwnd == 0) {
129 			wp->w_bufp->b_dotp  = wp->w_dotp;
130 			wp->w_bufp->b_doto  = wp->w_doto;
131 			for (cmark = 0; cmark < NMARKS; cmark++) {
132 				wp->w_bufp->b_markp[cmark] = wp->w_markp[cmark];
133 				wp->w_bufp->b_marko[cmark] = wp->w_marko[cmark];
134 			}
135 			wp->w_bufp->b_fcol  = wp->w_fcol;
136 		}
137 
138 		/* on to the next window, free this one */
139 		tp = wp->w_wndp;
140 		free((char *) wp);
141 		wp = tp;
142 	}
143 
144 #if	WINDOW_MSWIN
145 	term.t_delscr(sp);
146 #endif
147 	/* and now, free the screen struct itself */
148 	free(sp->s_screen_name);
149 	free((char *) sp);
150 }
151 
unlist_screen(sp)152 int PASCAL NEAR unlist_screen(sp)
153 
154 SCREEN *sp;         /* screen to remove from the list */
155 {
156 	SCREEN *last_scr;	/* screen previous to one to delete */
157 
158 	last_scr = first_screen;
159 	while (last_scr) {
160 		if (last_scr->s_next_screen == sp)
161 			break;
162 		last_scr = last_scr->s_next_screen;
163 	}
164 	last_scr->s_next_screen = sp->s_next_screen;
165 }
166 
delete_screen(f,n)167 PASCAL NEAR delete_screen(f, n)
168 
169 int f,n;	/* prefix flag and argument */
170 
171 {
172 	char scr_name[NSTRING];	/* buffer to hold screen name */
173 	SCREEN *sp;		/* ptr to screen to switch to */
174 	int result;
175 
176 	/* get the name of the screen to delete */
177 	if ((result = mlreply(TEXT243, scr_name, NSTRING)) != TRUE) {
178 	    /* "Delete Screen: " */
179             return result;
180 	}
181 	sp = lookup_screen(scr_name);
182 
183 	/* make sure it exists... */
184 	if (sp == (SCREEN *)NULL) {
185 		mlwrite(TEXT240);   /* "[No such screen]" */
186 		return(FALSE);
187 	}
188 
189 	/* it can't be current... */
190 	if (sp == first_screen) {
191 		mlwrite(TEXT241);   /* "%%Can't delete current screen" */
192 		return(FALSE);
193 	}
194 
195 	unlist_screen(sp);
196 	free_screen(sp);
197 #if	WINDOW_TEXT
198 	refresh_screen(first_screen);
199 #endif
200 	return(TRUE);
201 }
202 
203 /* this function initializes a new screen.... */
204 
init_screen(scr_name,scr_buf)205 SCREEN *PASCAL NEAR init_screen(scr_name, scr_buf)
206 
207 char *scr_name;		/* screen name */
208 BUFFER *scr_buf;	/* buffer to place in first window of screen */
209 
210 {
211 	int cmark;		/* current mark to initialize */
212 	SCREEN *sp;		/* pointer to allocated screen */
213 	SCREEN *last_sp;	/* pointer to last screen */
214 	EWINDOW *wp;		/* ptr to first window of new screen */
215 
216 	/* allocate memory for this screen */
217 	sp = (SCREEN *)room(sizeof(SCREEN));
218 	if (sp == (SCREEN *)NULL)
219 		return(sp);
220 
221 	/* set up this new screens fields! */
222 	sp->s_next_screen = (SCREEN *)NULL;
223 	sp->s_screen_name = copystr(scr_name);
224 #if     WINDOW_MSWIN
225 	if (term.t_newscr (sp) != TRUE) {       /* failed */
226 	    free ((void *)sp);
227 	    return ((SCREEN *)NULL);
228 	}
229 	/* ... in MSWIN, the s_nrow/ncol etc... values are kept up to
230 	   date by vtinitscr; besides, term entries may actually match
231 	   the first_screen instead of the new screen */
232 	term.t_roworg = sp->s_roworg;
233 	term.t_colorg = sp->s_colorg;
234 	term.t_nrow = sp->s_nrow;
235 	term.t_ncol = sp->s_ncol;
236 #else
237 	sp->s_roworg = term.t_roworg;
238 	sp->s_colorg = term.t_colorg;
239 	sp->s_nrow = term.t_nrow;
240 	sp->s_ncol = term.t_ncol;
241 #endif
242 
243 	/* allocate its first window */
244 	wp = (EWINDOW *)room(sizeof(EWINDOW));
245 	if (wp == (EWINDOW *)NULL) {
246 		free((char *)sp);
247 		return((SCREEN *)NULL);
248 	}
249 	sp->s_first_window = sp->s_cur_window = wp;
250 
251 	/* and setup the windows info */
252 	wp->w_wndp = NULL;
253 	wp->w_bufp = scr_buf;
254 	scr_buf->b_nwnd += 1;
255 	wp->w_linep = scr_buf->b_linep;
256 
257 	/* position us at the buffers dot */
258 	wp->w_dotp  = scr_buf->b_dotp;
259 	wp->w_doto  = scr_buf->b_doto;
260 
261 	/* set all the marks to UNSET */
262 	for (cmark = 0; cmark < NMARKS; cmark++) {
263 		wp->w_markp[cmark] = NULL;
264 		wp->w_marko[cmark] = 0;
265 	}
266 	wp->w_toprow = 0;
267 #if	COLOR
268 	/* initalize colors to global defaults */
269 	wp->w_fcolor = gfcolor;
270 	wp->w_bcolor = gbcolor;
271 #endif
272 	wp->w_fcol = 0;
273 #if WINDOW_MSWIN
274 	wp->w_ntrows = sp->s_nrow-1;
275 #else
276 	wp->w_ntrows = term.t_nrow-1;		/* "-1" for mode line.	*/
277 #endif
278 	wp->w_force = 0;
279 	wp->w_flag  = WFMODE|WFHARD;		/* Full.		*/
280 
281 	/* first screen? */
282 	if (first_screen == (SCREEN *)NULL) {
283 		first_screen = sp;
284 		return(sp);
285 	}
286 
287 	/* insert it at the tail of the screen list */
288 	last_sp = first_screen;
289 	while (last_sp->s_next_screen != (SCREEN *)NULL)
290 		last_sp = last_sp->s_next_screen;
291 	last_sp->s_next_screen = sp;
292 
293 	/* and return the new screen pointer */
294 	return(sp);
295 }
296 
lookup_screen(scr_name)297 SCREEN *PASCAL NEAR lookup_screen(scr_name)
298 
299 char *scr_name;		/* named screen to find */
300 
301 {
302 	SCREEN *result;
303 
304 	/* scan the screen list */
305 	result = first_screen;
306 	while (result) {
307 
308 		/* if this is it, return its handle! */
309 		if (strcmp(scr_name, result->s_screen_name) == 0)
310 			return(result);
311 
312 		/* on to the next screen */
313 		result = result->s_next_screen;
314 	}
315 
316 	/* we didn't find it..... */
317 	return((SCREEN *)NULL);
318 }
319 
select_screen(sp,announce)320 int PASCAL NEAR select_screen(sp, announce)
321 
322 SCREEN *sp;	/* ptr to screen to switch to */
323 int announce;	/* announce the selection? */
324 
325 {
326 	EWINDOW *temp_wp;	/* backup of current window ptr (curwp) */
327 	SCREEN *temp_screen;	/* temp ptr into screen list */
328 
329 	/* make sure there is something here to set to! */
330 	if (sp == (SCREEN *)NULL)
331 		return(FALSE);
332 
333 	/* nothing to do, it is already current */
334 	if (sp == first_screen)
335 		return(TRUE);
336 
337 	/* deselect the current window */
338 #if     WINDOW_MSWIN
339         curwp->w_flag |= WFMODE;
340 #else
341 	temp_wp = curwp;
342 	curwp = (EWINDOW *)NULL;
343 	modeline(temp_wp);
344 	updupd(TRUE);
345 	curwp = temp_wp;
346 #endif
347 
348 	/* save the current screens concept of current window */
349 	first_screen->s_cur_window = curwp;
350 #if     WINDOW_MSWIN
351         /* in MSWIN, the term entries may (but not always) already
352 	   reflect the new screen's size and the s_n... stuff is always
353 	   kept up to date by vtinitscr */
354 	vtscreen (sp);
355 #else
356 	first_screen->s_roworg = term.t_roworg;
357 	first_screen->s_colorg = term.t_colorg;
358 	first_screen->s_nrow = term.t_nrow;
359 	first_screen->s_ncol = term.t_ncol;
360 #endif
361 
362 	/* re-order the screen list */
363 	temp_screen = first_screen;
364 	while (temp_screen->s_next_screen != (SCREEN *)NULL) {
365 		if (temp_screen->s_next_screen == sp) {
366 			temp_screen->s_next_screen = sp->s_next_screen;
367 			break;
368 		}
369 		temp_screen = temp_screen->s_next_screen;
370 	}
371 	sp->s_next_screen = first_screen;
372 	first_screen = sp;
373 
374 	/* reset the current screen, window and buffer */
375 	wheadp = first_screen->s_first_window;
376 	curwp = first_screen->s_cur_window;
377 	curbp = curwp->w_bufp;
378 
379 	/* let the display driver know we need a full screen update */
380 #if     WINDOW_MSWIN
381         term.t_topscr (first_screen);
382         curwp->w_flag |= WFMODE;
383         update(FALSE);
384 #else
385 	update_size();
386 	upwind();
387 #endif
388 	if (announce) {
389 		mlwrite(TEXT225, first_screen->s_screen_name);
390 /*			"[Switched to screen %s]" */
391 	}
392 	return(TRUE);
393 }
394 
395 /*	Build and popup a buffer containing the list of all screens.
396 	Bound to "A-B".
397 */
398 
list_screens(f,n)399 PASCAL NEAR list_screens(f, n)
400 
401 int f,n;	/* prefix flag and argument */
402 
403 {
404 	register int status;	/* stutus return */
405 
406 	if ((status = screenlist(f)) != TRUE)
407 		return(status);
408 	return(wpopup(slistp));
409 }
410 
411 
412 /*
413  * This routine rebuilds the
414  * text in the special secret buffer
415  * that holds the screen list. It is called
416  * by the list screens command. Return TRUE
417  * if everything works. Return FALSE if there
418  * is an error (if there is no memory). Iflag
419  * indicates whether to list hidden screens.
420  */
screenlist(iflag)421 PASCAL NEAR screenlist(iflag)
422 
423 int iflag;	/* list hidden screen flag */
424 
425 {
426 	SCREEN *sp;		/* ptr to current screen to list */
427 	EWINDOW *wp;		/* ptr into current screens window list */
428 	int status;		/* return status from functions */
429 	char line[NSTRING];	/* buffer to construct list lines */
430 	char bname[NSTRING];	/* name of next buffer */
431 
432 	/* mark this buffer as unchanged so... */
433 	slistp->b_flag &= ~BFCHG;
434 
435 	/* we can dump it's old contents without complaint */
436 	if ((status = bclear(slistp)) != TRUE)
437 		return(status);
438 
439 	/* there is no file connected with this buffer */
440 	strcpy(slistp->b_fname, "");
441 
442 	/* construct the header of this list */
443 	if (addline(slistp, "Screen         Buffers") == FALSE
444 	 || addline(slistp, "------         -------") == FALSE)
445 		return(FALSE);
446 
447 	/* starting from the first screen */
448 	sp = first_screen;
449 
450 	/* scan all the screens */
451 	while (sp) {
452 
453 		/* construct the screen name */
454 		strcpy(line, sp->s_screen_name);
455 		strcat(line, "                ");
456 		line[15] = 0;
457 
458 		/* list this screens windows's buffer names */
459 		wp = sp->s_first_window;
460 		while (wp) {
461 
462 			/* grab this window's buffer name */
463 			strcpy(bname, wp->w_bufp->b_bname);
464 
465 			/* handle full lines */
466 			if (strlen(line) + strlen(bname) + 1 > 78) {
467 				if (addline(slistp, line) == FALSE)
468 					return(FALSE);
469 				strcpy(line, "               ");
470 			}
471 
472 			/* append this buffer name */
473 			if (strlen(line) > 15)
474 				strcat(line, " ");
475 			strcat(line, bname);
476 
477 			/* on to the next window */
478 			wp = wp->w_wndp;
479 		}
480 
481 		/* and add the line to the buffer */
482 		if (addline(slistp, line) == FALSE)
483 			return(FALSE);
484 
485 		/* on to the next screen */
486 		sp = sp->s_next_screen;
487 	}
488 
489 	/* all constructed! */
490 	return(TRUE);
491 }
492 
493 /* rename_screen:    change the current screen's name	*/
494 
rename_screen(f,n)495 int PASCAL NEAR rename_screen(f, n)
496 
497 int f, n;	/* default number and arguments */
498 
499 {
500 	char scr_name[NSTRING];  /* buffer to hold screen name */
501 	int result;
502 
503 	/* get the new name of the screen */
504 	if ((result = mlreply(TEXT335, scr_name, NSTRING)) != TRUE) {
505 /*			      "Change screen name to: " */
506 		return(result);
507 	}
508 
509 	if (lookup_screen(scr_name) != (SCREEN*)NULL) {
510 		mlwrite(TEXT336);
511 /*			"[Screen name already in use]" */
512 		return(FALSE);
513 	}
514 
515 	/* replace the old screen name with the new */
516 	free(first_screen->s_screen_name);
517 	first_screen->s_screen_name = copystr(scr_name);
518 #if	WINDOW_MSWIN
519 	SetWindowText(first_screen->s_drvhandle, scr_name);
520 #endif
521 	return(TRUE);
522 
523 }
524 
525 
526