source: trunk/minix/commands/elle/eebuff.c@ 9

Last change on this file since 9 was 9, checked in by Mattia Monga, 13 years ago

Minix 3.1.2a

File size: 25.6 KB
Line 
1/* ELLE - Copyright 1982, 1984, 1987 by Ken Harrenstien, SRI International
2 * This software is quasi-public; it may be used freely with
3 * like software, but may NOT be sold or made part of licensed
4 * products without permission of the author.
5 */
6
7/* EEBUFF Buffer and Window functions.
8 * Each buffer is an independent SB-string described by a
9 * buffer structure. All buffer structures are allocated dynamically
10 * and chained together starting from buf_head.
11 */
12
13#include "elle.h"
14
15#if FX_FILLMODE
16extern int fill_mode;
17#endif
18#if FX_SKMAC
19extern int kdef_mode;
20#endif
21
22struct buffer *make_buf(), *find_buf(), *sel_mbuf(), *sel_nbuf();
23struct window *make_win();
24
25/* EFUN: "Select Buffer" */
26/* Select old buffer or create a new one. Defaults to previously
27 * used buffer.
28 */
29f_selbuffer()
30{ register char *ans;
31 register struct buffer *b;
32
33 if((b = last_buf) == cur_buf) /* If default same as current, */
34 if(!(b = sel_mbuf(b))) /* try to pick a more useful one. */
35 b = sel_nbuf(cur_buf);
36
37 ans = ask("Select buffer (%s): ",b->b_name);
38 if (ans == 0) /* he aborted */
39 return;
40 if (*ans != '\0') /* Null string => use last buff */
41 { b = find_buf (ans); /* Else find/create one */
42 if (b == 0)
43 b = make_buf (ans);
44 }
45 sel_buf(b);
46 chkfree(ans);
47}
48
49#if FX_SELXBUFFER
50/* EFUN: "Select Existing Buffer" (not EMACS) - from IMAGEN config */
51
52static int findstr();
53
54f_selxbuffer()
55{ register char *ans;
56 register struct buffer *b;
57
58 b = last_buf; /* This is default */
59 ans = ask("Select existing buffer (%s): ", b->b_name);
60 if (ans == 0) /* Aborted */
61 return;
62 if (*ans != 0)
63 { for (b = buf_head; b != 0; b = b->b_next)
64 if (findstr(ans, b->b_name))
65 break;
66 if (b == 0)
67 ding("That isn't a substring of any buffer name!");
68 }
69 chkfree(ans);
70 if (b != 0)
71 { saytoo(" => ");
72 sayntoo(b->b_name);
73 sel_buf(b);
74 }
75}
76
77static int
78findstr(str, instr) /* Find "str" in string "instr" */
79register char *str, *instr;
80{ register char *sp, *isp;
81
82 while (*instr)
83 { sp = str;
84 isp = instr;
85 while (*sp)
86 if (*sp++ != *isp++)
87 goto next;
88 return(1);
89next: ++instr;
90 }
91 return(0);
92}
93#endif /*FX_SELXBUFFER*/
94
95
96/* EFUN: "Kill Buffer" */
97/* Kill specified buffer - defaults to current buffer.
98 * This code assumes a killed buffer will never be on a window list unless it
99 * is pointed to by cur_buf or oth_win->w_buf!!!!
100 */
101f_kbuffer()
102{ register struct buffer *b, *ob;
103 register char *ans;
104
105 if((ans = ask("Kill buffer: ")) == 0)
106 return;
107 if(*ans == 0) b = cur_buf;
108 else if(*ans == SP) b = 0;
109 else b = find_buf(ans);
110
111 chkfree(ans);
112 if(!b)
113 { ding("No such buffer");
114 return;
115 }
116#if IMAGEN
117 if (b->b_flags & B_PERMANENT)
118 { ding("Permanent buffer--cannot kill!");
119 return;
120 }
121 if (b->b_flags & B_MODIFIED)
122 { if ((ans == ask("Buffer is modified; are you sure? ")) == 0)
123 return;
124 if(upcase(*ans) != 'Y')
125 { chkfree(ans);
126 return;
127 }
128 chkfree(ans);
129 }
130#endif /*IMAGEN*/
131 if(b == cur_buf || (oth_win && (oth_win->w_buf == b)))
132 { ob = last_buf;
133 do
134 {
135 /* If default same as doomed buffer, try to pick
136 * a more useful alternative. */
137 if((b == ob) && !(ob = sel_mbuf(b)))
138 ob = sel_nbuf(b);
139
140 ans = ask("Killing in-use buffer; select which other buffer (%s): ",
141 ob->b_name);
142 if(ans == 0) return;
143 if(*ans)
144 { if(*ans == SP) ob = 0;
145 else ob = find_buf(ans);
146 }
147 chkfree(ans);
148 if(!ob)
149 { ding("No such buffer");
150 return;
151 }
152 } while (b == ob);
153
154 /* B is buffer to kill, OB is buffer to replace it with */
155 if(oth_win && (oth_win->w_buf == b))
156 { f_othwind(); /* Select other one */
157 chg_buf(ob); /* Change to new buffer */
158 f_othwind();
159 }
160 if(cur_buf == b)
161 chg_buf(ob);
162 }
163
164 kill_buf(b); /* Die!!!! */
165 if(last_buf == b)
166 last_buf = cur_buf;
167}
168
169/* EFUN: "List Buffers" */
170/* Display a list of all user buffers. Internal buffers, whose names
171 * start with a space, are not shown.
172 */
173f_listbufs()
174{
175 register struct buffer *b;
176 register char *cp;
177 register int i;
178 struct buffer *tbuf, *savbuf;
179 char temp[20];
180
181 /* First must set up special buffer... */
182 savbuf = cur_buf;
183 chg_buf(tbuf = make_buf(" **SHOW**"));
184 e_sputz("Buffers in this ELLE:\n\n");
185 for(b = buf_head; b; b = b->b_next)
186 { cp = b->b_name;
187 if(*cp == SP) continue; /* Ignore internal buffs */
188 e_sputz((b->b_flags&B_MODIFIED) ? "* " : " ");
189 e_sputz(cp); /* Insert buffer name */
190 dottoa(temp,ex_blen(b)); /* Get buff-length string */
191 if((i = ((FNAMELEN > 14) ? 30 : 20)
192 - strlen(cp) - strlen(temp)) > 0)
193 e_insn(SP, i);
194 e_sputz(" (");
195 e_sputz(temp);
196 e_sputz(") ");
197 if(cp = b->b_fn)
198 e_sputz(cp);
199#if IMAGEN
200 if (b->b_flags & B_CMODE)
201 e_sputz(" (C)");
202 else if (b->b_flags & B_TEXTMODE)
203 e_sputz(" (Text)");
204 else
205 e_sputz(" (Fundamental)");
206#endif /*IMAGEN*/
207 e_putc(LF);
208 }
209 mk_showin(tbuf); /* Show this buffer in temp window */
210 chg_buf(savbuf); /* Return to real current buffer */
211 kill_buf(tbuf);
212}
213
214
215/* EFUN: "Buffer Not Modified" */
216/* Mark the current buffer as not modified.
217 */
218f_bufnotmod()
219{
220 cur_buf -> b_flags &= ~B_MODIFIED;
221 redp(RD_MODE);
222}
223
224#if FX_EOLMODE
225/* EFUN: "EOL CRLF Mode" (not EMACS) */
226/* Toggle the EOL mode of the current buffer.
227** LF EOL Mode means LF alone is an EOL.
228** CRLF EOL Mode means CRLF together is an EOL.
229*/
230f_eolmode()
231{
232 cur_buf->b_flags ^= B_EOLCRLF; /* Flip this bit */
233 say((cur_buf->b_flags & B_EOLCRLF)
234 ? "EOL Mode is CRLF" /* If now on */
235 : "EOL Mode is LF"); /* If now off */
236
237 redp(RD_WINRES); /* Redo window for this buf */
238}
239#endif /*FX_EOLMODE*/
240
241
242#if FX_GOBEG
243/* EFUN: "Goto Beginning" */
244f_gobeg()
245{ e_gobob();
246 ed_setcur();
247}
248#endif /*FX_GOBEG*/
249
250#if FX_GOEND
251/* EFUN: "Goto End" */
252f_goend()
253{ e_goeob();
254 ed_setcur();
255}
256#endif /*FX_GOEND*/
257
258#if FX_WHATPAGE
259/* EFUN: "What Page" */
260/* Extra info added as per earlier ICONOGRAPHICS "What Buffer Position"
261** Reports on current position as follows:
262** Dot=<n>, Page <n> Line <n> (line <n> of <m>)
263*/
264f_whatpage()
265{
266 register chroff cnt;
267 register int c;
268 register int page, line;
269 int lineatp;
270 char tempstr[12], *dottoa ();
271
272 saynow("Dot=");
273 dottoa(tempstr, cur_dot);
274 sayntoo(tempstr);
275
276 e_gobob();
277 page = line = lineatp = 1;
278 for (cnt = cur_dot; --cnt >= 0;)
279 if ((c = e_getc()) == LF)
280 ++line;
281 else if (c == FF)
282 { ++page;
283 lineatp = line;
284 }
285
286 saytoo(", Page ");
287 dottoa(tempstr, (chroff)page);
288 saytoo(tempstr);
289 saytoo(" Line ");
290 dottoa(tempstr, (chroff)(1 + line - lineatp));
291 saytoo(tempstr);
292 saytoo(" Col ");
293 dottoa(tempstr, (chroff)indtion(cur_dot));
294 saytoo(tempstr);
295 saytoo(" [line ");
296 dottoa(tempstr, (chroff)line);
297 saytoo(tempstr);
298 sayntoo(" of "); /* Force out while scan rest */
299
300 for(e_gocur(); e_gonl() ; ++line) ; /* Count lines until EOF */
301 c = e_rgetc(); /* Remember what last char is */
302 dottoa(tempstr, (chroff)line);
303 saytoo(tempstr);
304 if (c != LF) /* Check last char */
305 saytoo(" (no EOL at EOF!)");
306 sayntoo("]");
307 e_gocur(); /* Back to original position */
308}
309#endif /*FX_WHATPAGE*/
310
311
312init_buf () /* init buffer stuff */
313{
314 buf_head = 0;
315 lines_buf = cur_buf = make_buf(" **LINES**"); /* For sep_win */
316 e_insn('-',scr_wid-2); /* Fill with dashes */
317 last_buf = cur_buf = make_buf ("Main"); /* Make Main buffer */
318 init_win(); /* Now can init windows */
319}
320
321struct buffer *
322make_buf(bname) /* create buffer "bname" if it doesn't exist */
323char *bname;
324{ register struct buffer *b;
325 register char *name;
326
327 b = find_buf(name = bname);
328 if (b) /* if it exists already */
329 return(b);
330 b = (struct buffer *) memalloc(sizeof (struct buffer));
331 b -> b_next = buf_head; /* link it in */
332 buf_head = b;
333 b->b_name = strdup(name); /* Allocate copy of name string */
334 b->b_dot = 0; /* Set dot to beg */
335 sb_open(b,(SBSTR *)0); /* Open buffer with null initial sbstring */
336 b->b_fn = 0;
337 b->b_flags = 0;
338 b->b_mode = cur_mode; /* Inherit current mode */
339 return(b);
340}
341
342
343struct buffer *
344find_buf(name) /* returns pointer to buffer of that name or 0 */
345char *name;
346{ register struct buffer *b = buf_head;
347
348 while (b && strcmp(b->b_name, name))
349 b = b -> b_next;
350 return(b);
351}
352
353sel_buf(b) /* select buffer, saving last */
354struct buffer *b;
355{
356 if(b != cur_buf) last_buf = cur_buf;
357 chg_buf(b);
358}
359
360chg_buf (newbuf) /* change current buffer to newbuf */
361struct buffer *newbuf;
362{ register struct buffer *obuf, *nbuf;
363
364 if ((nbuf = newbuf) == (obuf = cur_buf))
365 return; /* Do nothing if same buffers */
366 obuf->b_dot = cur_dot;
367 cur_buf = nbuf;
368 cur_mode = nbuf->b_mode;
369 e_gosetcur(nbuf->b_dot); /* Set cur_dot and go there */
370 cur_win->w_buf = nbuf;
371 cur_win->w_dot = cur_dot;
372#if IMAGEN
373 cur_win->w_redp = RD_WINRES|RD_REDO;
374#else
375 cur_win->w_redp = RD_WINRES; /* Reset flags - do complete update */
376#endif /*-IMAGEN*/
377 unlk_buf(obuf); /* Unlock previous buffer if can */
378 mark_p = 0; /* this is lazy */
379 redp(RD_MODE|RD_WINRES);
380}
381
382/* See if specified buffer belongs to any active window, and
383 * if not then get it into an idle, unlocked state; this helps the
384 * edit package compact and swap stuff out while it's not being used.
385 * Assumes proper state of dot has been stored into b_dot.
386 */
387unlk_buf(bufp)
388struct buffer *bufp;
389{ register struct buffer *b;
390 register struct window *w;
391
392 b = bufp;
393 for(w = win_head; w; w = w->w_next)
394 if(b == w->w_buf)
395 return; /* Buffer is actively being shown */
396 sb_rewind((SBBUF *)b); /* Return to idle state */
397}
398
399/* SEL_NBUF(buf) - Select next user buffer. Ignores internal buffers.
400 * Arg of 0 starts at beg of buffer list. Always returns
401 * a buffer pointer - returns argument (which may be 0)
402 * if found no other user buffers.
403 *
404 * SEL_MBUF(buf) - Select next modified buffer.
405 * Returns buffer ptr to "next" modified buffer, if any.
406 * Arg of 0 starts at beg of buffer list and scans all of them.
407 * Returns 0 if no other modified buffers exist (unlike SEL_NBUF!)
408 * Ignores internal buffers, whose names start with a space.
409 */
410/* struct buffer *buf_mptr; */
411#if 0
412struct buffer *
413sel_mbuf(buf)
414struct buffer *buf;
415{ register struct buffer *b;
416 register int sweep;
417
418 sweep = 0; /* Make 2 sweeps only */
419 if(b = buf) b = b->b_next;
420 do {
421 if(b == 0) /* Initialize if needed */
422 b = buf_head;
423 for(; b; b = b->b_next)
424 if((b->b_flags & B_MODIFIED) && (*b->b_name != SP))
425 return((b == buf) ? 0 : b);
426 } while(sweep++ != 0);
427 return(0);
428}
429#endif /*COMMENT*/
430
431struct buffer *
432sel_mbuf(buf)
433register struct buffer *buf;
434{ register struct buffer *b, *b2;
435 b = b2 = sel_nbuf(buf);
436 do { if(b == buf) break;
437 if(b->b_flags & B_MODIFIED)
438 return(b);
439 } while((b = sel_nbuf(b)) != b2);
440
441 return(0);
442}
443
444struct buffer *
445sel_nbuf(buf)
446register struct buffer *buf;
447{ register struct buffer *b;
448
449 b = buf;
450 do {
451 if(!b || !(b = b->b_next))
452 b = buf_head;
453 if(*b->b_name != SP)
454 break;
455 } while (b != buf);
456 return(b);
457}
458
459
460kill_buf(buf)
461struct buffer *buf;
462{ register struct buffer *b, *b1, *bt;
463
464 b = buf;
465 b1 = 0;
466 for(bt = buf_head; bt && bt != b; bt = bt -> b_next)
467 b1 = bt;
468 if(bt == 0)
469 { ring_bell();
470 errbarf("No such buffer"); /* Internal error */
471 return;
472 }
473 if (b1 == 0)
474 buf_head = b->b_next;
475 else
476 b1->b_next = b->b_next;
477 sbs_del(sb_close((SBBUF *)b)); /* Close buffer & delete sbstring */
478 sb_fdcls(-1); /* Make sweep for unused FD's */
479 if(b->b_fn)
480 chkfree(b->b_fn); /* Flush filename if one */
481 chkfree(b->b_name); /* Flush name */
482 chkfree((char *)b); /* Flush buffer */
483}
484
485
486/* ZAP_BUFFER - Delete all of the buffer, but if it's been modified,
487 * ask first. Returns 0 if user aborts.
488 */
489zap_buffer()
490{
491#if IMAGEN
492 extern struct buffer *exec_buf; /* in e_make.c */
493
494 if(cur_buf != exec_buf && cur_buf -> b_flags & B_MODIFIED)
495#else
496 if(cur_buf -> b_flags & B_MODIFIED)
497#endif /*-IMAGEN*/
498 if(ask_kbuf(cur_buf) <= 0)
499 return(0); /* Aborted */
500 ed_reset(); /* This takes care of redisplay too */
501 mark_p = 0;
502#if IMAGEN
503 cur_buf->b_flags &= ~B_BACKEDUP; /* Clear backed-up flag */
504#endif
505 return(1);
506}
507
508
509
510
511/* ASK_KBUF - Ask user "are you sure?" before killing a buffer.
512 * Returns +1 if user says "yes" - OK to kill.
513 * 0 if user aborts (^G)
514 * -1 if user says "no".
515 */
516ask_kbuf(buf)
517struct buffer *buf;
518{ register struct buffer *b;
519 register char *s;
520 register int ans;
521
522 b = buf;
523 s = ask("Buffer %s contains changes - forget them? ", b->b_name);
524 if(s == 0) return(0);
525 ans = (upcase(*s) == 'Y') ? 1 : -1;
526 chkfree(s);
527 return(ans);
528}
529
530
531/* Window stuff */
532
533/* Like EMACS, ELLE only provides at most two user windows.
534 * The current user window is pointed to by user_win;
535 * the "other" one is oth_win. If oth_win == 0, there is only one user
536 * window.
537 */
538
539#if FX_2MODEWINDS
540int sepmode_p = 0; /* Set true if separator window is a 2nd mode win */
541#endif
542
543/* EFUN: "Two Windows" */
544/* Divide the current window in half, put the current buffer in the
545 * other window, and go to the new window.
546 */
547f_2winds()
548{ register int h, t;
549 register struct window *w;
550
551 if (oth_win)
552 {
553#if !(IMAGEN)
554 ding("Already 2 windows");
555#endif /*-IMAGEN*/
556 return;
557 }
558 w = cur_win;
559 d_fixcur(); /* Stabilize current window */
560 h = (w->w_ht) / 2;
561 t = w->w_pos + h; /* Pos of dividing window */
562 sep_win = make_win(t, 1, lines_buf);
563 /* assume using dashes to separate */
564 oth_win = make_win(t + 1, w->w_ht - (h + 1), cur_buf);
565 /* Other window has balance */
566#if FX_SOWIND
567 oth_win->w_flags |= cur_win->w_flags&W_STANDOUT;
568 sep_win->w_flags |= mode_win->w_flags&W_STANDOUT;
569#endif
570#if FX_2MODEWINDS
571 chk2modws(); /* Update 2-mode-wind status */
572#endif
573 w->w_ht = h; /* Decrease current window to half */
574
575 /* Minimize redisplay by moving each window's dot into
576 * a currently displayed area */
577 if(cur_dot < (oth_win->w_topldot = scr[t+1]->sl_boff))
578 oth_win->w_dot = oth_win->w_topldot; /* Adj bottom win */
579 else /* Adjust top window */
580 { oth_win->w_dot = cur_dot; /* Bottom keeps dot */
581 cur_dot = scr[t-1]->sl_boff; /* but top needs new one. */
582 }
583 f_othwind(); /* switch to other window */
584 redp(RD_WINDS); /* Update all windows */
585}
586
587
588/* EFUN: "One Window" */
589/* Revert to using only one window; use the current buffer (unlike
590 * EMACS which always selects the top window's buffer)
591 * Ensures that current window's vars are correctly set for
592 * new dimensions (w_pos, w_ht, plus w_topldot to minimize redisplay),
593 * then kills unneeded windows.
594 */
595f_1wind()
596{ register struct window *w;
597
598 if (oth_win == 0)
599 {
600#if (!IMAGEN)
601 ding("Only 1 window");
602#endif /*-IMAGEN*/
603 return;
604 }
605 w = cur_win;
606 if(w->w_pos) /* If not top window */
607 { d_fixcur(); /* Ensure screen-line data correct */
608 e_go(w->w_topldot); /* Beginning from top of window, */
609 d_fgoloff(-w->w_pos); /* Move back enough lines */
610 w->w_topldot = e_dot(); /* To set new start of window */
611 e_gocur(); /* Then move back to orig place */
612 w->w_pos = 0;
613 }
614 w->w_ht += oth_win -> w_ht + 1;
615 kill_win (oth_win);
616 kill_win (sep_win);
617 oth_win = sep_win = 0;
618#if FX_2MODEWINDS
619 chk2modws(); /* Update notion of whether have 2 mode winds */
620#endif
621 redp(RD_FIXWIN|RD_WINDS|RD_MODE); /* New topldot for this window,
622 * and check all remaining windows */
623}
624
625/* EFUN: "Other Window" */
626/* Move to the "other" user window.
627 */
628f_othwind ()
629{ if (oth_win == 0)
630 {
631#if !(IMAGEN)
632 ding("Only 1 window");
633#endif /*-IMAGEN*/
634 return;
635 }
636 chg_win(oth_win);
637 oth_win = user_win;
638 user_win = cur_win;
639 redp(RD_MODE);
640}
641
642/* EFUN: "Grow Window" */
643/* Grow the current window - while in two window mode,
644 * increase the size of the current window by the arg
645 * and decrease the other accordingly
646 */
647f_growind()
648{ register struct window *cw, *ow;
649 register int e;
650
651 if ((ow = oth_win) == 0)
652 {
653#if !(IMAGEN)
654 ding("Only 1 window");
655#endif /*-IMAGEN*/
656 return;
657 }
658 e = exp;
659 if((cw = cur_win)->w_pos != 0) /* If current window is on bottom */
660 { cw = ow; /* Then fake code to think it's top */
661 ow = cur_win;
662 e = -e;
663 }
664 if( cw->w_ht + e < 1
665 || ow->w_ht + e < 1)
666 { ding("Too much");
667 return;
668 }
669 cw -> w_ht += e;
670 ow -> w_pos += e;
671 ow -> w_ht -= e;
672 sep_win -> w_pos += e;
673 redp(RD_WINDS | RD_MODE); /* Update all windows */
674}
675
676#if FX_SHRINKWIND
677/* EFUN: "Shrink Window" (not EMACS) - from IMAGEN config */
678f_shrinkwind()
679{
680 if (! oth_win)
681 return;
682 f_othwind();
683 f_growind();
684 f_othwind();
685}
686#endif /*FX_SHRINKWIND*/
687
688#if FX_DELWIND
689/* EFUN: "Delete Window" (not EMACS) - from IMAGEN config */
690f_delwind()
691{
692 if(!oth_win)
693 return;
694 f_othwind();
695 f_1wind();
696}
697#endif /*FX_DELWIND*/
698
699#if FX_SOWIND
700/* EFUN: "Standout Window" (not EMACS) */
701/* Toggles the display standout mode for the current window.
702** With argument of 4, toggles the standout mode for the non-buffer
703** parts of the screen, such as the ELLE mode line.
704** (This corresponds to FS INVMOD$ in EMACS)
705** With argument of 0, turns standout mode off for all windows.
706*/
707/* It suffices to set the window flag bit and force a RD_WINRES for that
708 * window; the redisplay code will do the rest.
709*/
710static void tgso_wind();
711
712f_sowind()
713{
714 register struct window *w;
715 switch(exp)
716 { default: /* Toggle current window */
717 tgso_wind(cur_win);
718 break;
719 case 4: /* Toggle mode & separator windows */
720 tgso_wind(mode_win);
721 tgso_wind(sep_win); /* This may not exist */
722 break;
723 case 0: /* Turn off standout for all winds */
724 for(w = win_head; w; w = w->w_next)
725 if(w->w_flags&W_STANDOUT)
726 tgso_wind(w);
727 }
728#if FX_2MODEWINDS
729 chk2modws(); /* Update notion of whether have 2 mode winds */
730#endif
731}
732
733static void
734tgso_wind(w) /* Toggle standout mode for given window */
735register struct window *w;
736{
737 if (w == 0) return; /* For case of no sep_win */
738 if (w->w_flags & W_STANDOUT)
739 w->w_flags &= ~W_STANDOUT;
740 else w->w_flags |= W_STANDOUT;
741 w->w_redp |= RD_WINRES; /* Re-do this particular window */
742 redp(RD_CHKALL); /* Check all windows for changes */
743}
744#endif /*FX_SOWIND*/
745
746
747#if FX_2MODEWINDS
748/* EFUN: "Two Mode Windows" (not EMACS) */
749/* With arg, sets ev_2modws to that value (0, 1, or 2).
750** No arg, toggles current setting between 0 and 2.
751*/
752
753f_2modewinds()
754{
755 ev_2modws = exp_p ? exp : (ev_2modws ? 0 : 2);
756 chk2modws();
757}
758
759/* CHK2MODWS - Called after anything changes which might affect
760** whether 2 mode windows are in effect or not. Fixes up
761** sep_win to either be or not be a mode window.
762*/
763chk2modws()
764{ register struct window *w;
765 static struct buffer *sep_buf = 0;
766
767 if(!(w = sep_win))
768 { sepmode_p = 0; /* Don't have 2 windows at all */
769 return;
770 }
771 sepmode_p = (ev_2modws == 1)
772 ? (mode_win->w_flags&W_STANDOUT)
773 : ev_2modws;
774
775 if(sepmode_p) /* Turn 2-mode-winds on? */
776 {
777 if(!sep_buf)
778 sep_buf = make_buf(" **SEPMODE**");
779 w->w_buf = sep_buf;
780 w->w_flags |= W_MODE;
781 }
782 else /* Turn 2-mode-winds off */
783 { w->w_buf = lines_buf;
784 w->w_flags &= ~W_MODE;
785 redp(RD_CHKALL); /* No longer a mode win, so must */
786 /* check all to ensure it's updated */
787 }
788 w->w_redp |= RD_WINRES;
789 redp(RD_MODE);
790}
791#endif /*FX_2MODEWINDS*/
792
793
794init_win ()
795{
796 win_head = 0;
797 oth_win = 0;
798 user_win = make_win(0, scr_ht - (ECHOLINES+1), cur_buf); /* Main */
799 mode_win = make_win(scr_ht - (ECHOLINES+1), 1, make_buf(" **MODE**"));
800 ask_win = make_win(scr_ht - ECHOLINES, 1, make_buf(" **ASK**"));
801#if FX_SOWIND
802 if(ev_modwso)
803 mode_win->w_flags |= W_STANDOUT;
804#endif
805
806 cur_win = user_win;
807}
808
809chg_win(newwin) /* change current window to newwin */
810struct window *newwin;
811{
812 cur_win->w_dot = cur_dot; /* Save window's current dot */
813 cur_win->w_redp |= rd_type&RDS_WINFLGS; /* and its redisplay flags */
814 cur_win = newwin; /* OK, switch to new current window */
815 cur_buf = newwin->w_buf; /* Set new buffer from win */
816 e_gosetcur(newwin->w_dot); /* Set new cur_dot from win too */
817 /* Note done this way to canonicalize the location
818 ** (may be past new EOB) and ensure SB buffer
819 ** internals agree with cur_dot.
820 */
821 rd_type &= ~RDS_WINFLGS; /* Remove old per-window flags */
822 redp(RD_WINRES|RD_MODE); /* Maybe caller shd handle? */
823 /* Note WINRES must be set in case we are pointing
824 * to a buffer that was modified while we were in
825 * the other window!
826 */
827}
828
829
830struct window *
831make_win (pos, ht, buf)
832int pos, ht;
833struct buffer *buf;
834{ register struct window *w;
835 register struct buffer *b;
836
837 b = buf;
838 w = (struct window *) memalloc(sizeof (struct window));
839 w->w_flags = 0;
840 w->w_pos = pos;
841 w->w_ht = ht;
842 w->w_buf = b;
843 w->w_dot = b->b_dot; /* Set dot from buffer value */
844 w->w_topldot = 0; /* Set top of window to beg of buffer */
845 w->w_pct = 200; /* Assume "ALL" */
846 w->w_bmod = 0;
847 w->w_emod = 0;
848 w->w_oldz = 0;
849 w->w_redp = RD_WINRES; /* Window will need complete update */
850 w->w_next = win_head; /* Done, now link it in */
851 win_head = w;
852 return (w);
853}
854
855kill_win (win)
856struct window *win;
857{ register struct window *w, *w1, *kw;
858
859 kw = win;
860 w1 = 0;
861 for (w = win_head; w && w != kw; w = w -> w_next)
862 w1 = w;
863 if (w == 0)
864 { ring_bell();
865 errbarf("No such window"); /* Internal error */
866 return;
867 }
868 if (w1 == 0)
869 win_head = w -> w_next;
870 else
871 w1 -> w_next = w -> w_next;
872 kw->w_buf->b_dot = (kw == cur_win) ? cur_dot : kw->w_dot;
873 chkfree (kw);
874#if IMAGEN /* Not needed? */
875 redp (RD_WINRES|RD_WINDS|RD_REDO);
876#endif /*IMAGEN*/
877}
878
879
880/*
881 * "Show-window" routines, used to set up, step through, and close a
882 * temporary "show" window.
883 * MK_SHOWIN(bufp)
884 * UP_SHOWIN()
885 * KL_SHOWIN()
886 */
887
888/* MK_SHOWIN(bufp) - Temporarily display a buffer
889 */
890mk_showin(b)
891struct buffer *b;
892{ register struct window *w;
893 register int i;
894 int moreflg, intflg; /* Interrupt flag */
895 struct window *savwin;
896
897 /* First must set up special window... */
898 savwin = cur_win;
899 chg_win(w = make_win(0, scr_ht-(ECHOLINES+3), b));
900 redo:
901 d_fixcur(); /* Fix up screen image of current window */
902
903 /* Find how many lines actually used, and reduce size to that */
904 i = w->w_ht;
905 while(--i >= 0)
906 {
907 if(scr[i]->sl_boff != w->w_oldz) break;
908 }
909 if(++i <= 0)
910 goto skipit; /* Punt the whole thing */
911 if(!(moreflg = (i >= w->w_ht)))
912 w->w_ht = i; /* Reduce size of window */
913
914 intflg = upd_wind(w); /* Update the window! */
915 if(!intflg) /* Unless input waiting, add prompt. */
916 {
917 yellat( moreflg ?
918 "--MORE-- (type Space for more, or type any command to flush)" :
919 "------------------------------------------------ (Hit space to continue)--",
920 w->w_ht);
921
922 }
923 tbufls(); /* Ensure all output forced out */
924 i = cmd_read(); /* then wait for user to input a char */
925 if(i == SP)
926 { if(moreflg)
927 { yellat("", w->w_ht);
928 d_screen(1);
929 w->w_redp |= RD_WINRES;
930 goto redo;
931 }
932 }
933#if !(IMAGEN) /* IMAGEN - always ignore what was typed */
934 else unrchf = i;
935#endif /*-IMAGEN*/
936skipit: chg_win(savwin);
937 kill_win(w);
938 redp(RD_WINDS); /* Update all remaining windows */
939}
940
941
942/* Mode Line generation */
943
944struct window *
945make_mode(bw)
946register struct window *bw; /* Base window we are reporting status of */
947{
948 register struct buffer *b; /* Buffer of this window */
949 struct window *mw, *savew; /* Save current window */
950 struct buffer *saveb; /* and current buffer (in case different) */
951 char temp[20];
952
953 saveb = cur_buf; /* Save values prior to context switch */
954 savew = cur_win;
955 b = bw->w_buf; /* Get buffer for that window */
956
957#if FX_2MODEWINDS
958 if((mw = sep_win) && (mw->w_flags&W_MODE) &&
959 (bw->w_pos == 0)) /* Base window is top window? */
960 { /* Use sep_win as mode wind */
961 }
962 else
963#endif
964 mw = mode_win; /* Default is normal mode window */
965 chg_win(mw); /* Go to mode line window */
966 e_gobob(); /* go to beginning */
967 e_reset(); /* Flush buffer */
968#if IMAGEN
969 e_sputz(" ");
970 e_sputz(b->b_name);
971 if (b -> b_flags & B_MODIFIED)
972 e_sputz("*");
973 e_sputz(" (");
974 if (b->b_flags & B_QUERYREP)
975 e_sputz("[Query Replace] ");
976 if (b->b_flags & B_CMODE)
977 e_sputz("C");
978 else if (b->b_flags & B_TEXTMODE)
979 e_sputz("Text");
980 else
981 e_sputz("Fundamental");
982 e_sputz(") ");
983 if (b->b_fn)
984 e_sputz(b->b_fn);
985 e_sputz(" ");
986#else
987 e_sputz(ev_verstr); /* Editor name/version */
988 e_sputz(" (");
989 e_sputz(cur_mode->mjm_name); /* insert major mode name */
990#if FX_FILLMODE
991 if(fill_mode) e_sputz(" Fill");
992#endif /*FX_FILLMODE*/
993#if FX_SKMAC
994 if(kdef_mode) e_sputz(" MacroDef");
995#endif /*FX_SKMAC*/
996 e_sputz(") ");
997 e_sputz(b->b_name); /* buffer name */
998 e_sputz(": ");
999 if (b->b_fn)
1000 e_sputz(b->b_fn); /* file name */
1001 if (b->b_flags & B_MODIFIED)
1002 e_sputz(" *");
1003 else e_sputz(" ");
1004#endif /*-IMAGEN*/
1005 if(bw->w_pct < 200) /* Not ALL? */
1006 { e_sputz(" --");
1007 switch(bw->w_pct)
1008 { case -1:
1009 e_sputz("TOP");
1010 break;
1011 case 150:
1012 e_sputz("BOT");
1013 break;
1014 default:
1015 dottoa(&temp[0],(chroff)bw->w_pct);
1016 e_sputz(&temp[0]);
1017 e_putc('%');
1018 }
1019 e_sputz("--");
1020 }
1021#if FX_SOWIND
1022 if(mw->w_flags&W_STANDOUT)
1023 e_insn(SP, (int)(scr_wd0 - e_blen())); /* Stuff out with spaces */
1024#endif
1025
1026 redp(RD_WINRES);
1027 chg_win(savew); /* Restore context */
1028 chg_buf(saveb);
1029 return(mw); /* Return mode window */
1030}
1031
1032
1033buf_mod()
1034{ register struct buffer *b;
1035
1036 b = cur_buf;
1037 if((b->b_flags & B_MODIFIED) == 0)
1038 { b->b_flags |= B_MODIFIED;
1039 redp(RD_MODE);
1040 }
1041}
1042
1043/* BUF_TMOD - called when text modified in buffer, to set all
1044 * the appropriate indicators so that redisplay works right.
1045 * Changed text is everything from CUR_DOT to the given offset
1046 * from same. If stuff was deleted, offset should be 0.
1047 * BUF_TMAT - similar but argument is location of other end of range,
1048 * when caller knows that and wants life easy.
1049 */
1050
1051buf_tmat(dot)
1052chroff dot;
1053{ buf_tmod(dot - cur_dot); /* Convert to offset */
1054}
1055buf_tmod(offset)
1056chroff offset;
1057{ register struct window *w;
1058 chroff a, b, tmp;
1059
1060 w = cur_win;
1061 a = cur_dot;
1062 b = a + offset;
1063 if(a > b) /* Get into right order */
1064 { tmp = a;
1065 a = b;
1066 b = tmp;
1067 }
1068 b = e_blen() - b; /* Make upper bound relative to EOB */
1069 if(w->w_bmod < 0) /* Have range vars been set yet? */
1070 { w->w_bmod = a; /* Nope, so can just set 'em now. */
1071 w->w_emod = b;
1072 }
1073 else
1074 { if(a < w->w_bmod)
1075 w->w_bmod = a;
1076 if(b < w->w_emod)
1077 w->w_emod = b;
1078 }
1079 buf_mod(); /* Maybe later just insert here? */
1080 redp(RD_TMOD);
1081}
Note: See TracBrowser for help on using the repository browser.