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