source: trunk/minix/commands/elle/eefill.c@ 15

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

Minix 3.1.2a

File size: 15.1 KB
RevLine 
[9]1/* ELLE - Copyright 1982, 1985, 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 * EEFILL Fill Mode functions
8 */
9
10#include "elle.h"
11
12extern int ev_fcolumn; /* Fill Column variable (defined in EEVINI) */
13#if FX_SFPREF
14char *fill_prefix; /* Fill Prefix variable */
15int fill_plen; /* Length of Fill Prefix (0 = no prefix) */
16#endif /*FX_SFPREF*/
17
18#if FX_FILLMODE
19int fill_mode = 0; /* TRUE when Auto Fill Mode is on */
20int *fill_trig; /* Pointer to fill-trigger chbit array */
21static char *fill_initrig = " \t.,;:)!";
22#endif /*FX_FILLMODE*/
23
24/* Following stuff for testing routines on */
25/*
26
27 1 2 3 4 5 6 7
280123456789012345678901234567890123456789012345678901234567890123456789012345
29
30Okay... more stuff to hack. Okay. a b c d e f g h i j k l m
31n o p q r s t u v w x y z dfsd stuff to hack 01234 Okay testing
32more stuff to hack. Okay... more stuff to hack more stuff to
33hack. Okay... more stuff to line long stuff to hack. Okay...
34even more gap and. period. okay, end of stuff.
35 This is another fence.
36*/
37
38
39
40#if FX_SFCOL
41/* EFUN: "Set Fill Column" */
42f_sfcol()
43{ register int linel;
44 char temp[20];
45
46 linel = exp_p ? exp : d_curind();
47 if(linel < 0) linel = 0;
48 say("Fill column = ");
49 dottoa(temp,(chroff)linel);
50 saytoo(temp);
51 ev_fcolumn = linel;
52}
53#endif /*FX_SFCOL*/
54
55
56#if FX_SFPREF
57/* EFUN: "Set Fill Prefix" */
58f_sfpref()
59{ register int i;
60 register char *cp;
61
62 if((i = cur_dot - e_boldot()) > MAXLINE)
63 { ding("Absurd Fill Prefix");
64 return;
65 }
66 if(fill_prefix)
67 { chkfree(fill_prefix);
68 fill_plen = 0;
69 }
70 if(i <= 0)
71 { fill_prefix = 0;
72 cp = "";
73 }
74 else
75 { fill_prefix = cp = memalloc((SBMO)(i+1));
76 fill_plen = i;
77 e_gobol();
78 do { *cp++ = e_getc(); }
79 while(--i);
80 *cp = 0;
81 cp = fill_prefix;
82 }
83 say("Fill Prefix = \"");
84 saytoo(cp);
85 saytoo("\"");
86}
87
88
89/* TSTFILLP(lim) - Check for existence of Fill Prefix at current dot. If
90 * not there, returns 0 without changing dot. If there, returns
91 * 1 and leaves dot immediately after the Fill Prefix.
92 * Lim = # of chars allowed to scan from buffer.
93 */
94tstfillp(lim)
95int lim;
96{ register int i, c;
97 register char *cp;
98 chroff savdot;
99
100 if(!(i = fill_plen) || (i > lim))
101 return(0);
102 savdot = e_dot();
103 cp = fill_prefix;
104 do { if(*cp++ != e_getc())
105 { e_go(savdot);
106 return(0);
107 }
108 } while(--i);
109 return(1);
110}
111#endif /*FX_SFPREF*/
112
113
114#if FX_FILLREG || FX_FILLPARA
115
116/* ED_FILL(start, end, flag) - Fill a region.
117 * Flag 0 for full filling; extra whitespace is flushed. First
118 * word is always retained.
119 * 1 for skimpy filling such as Auto-Fill likes.
120 * Extra whitespace is NOT flushed, except at
121 * beginning of a newly created line.
122 * This is not yet implemented however.
123 * Note: updates cur_dot to compensate for changes in buffer, and returns
124 * there when done!
125 * Note: Checks for Fill Prefix when it exists.
126 */
127ed_fill(begloc, endloc, flag)
128chroff begloc, endloc;
129int flag;
130{ register int c;
131 register int len, lastc;
132 chroff savloc;
133 int lastbrk;
134 int parlen;
135
136 parlen = endloc - begloc;
137 if(parlen < 0)
138 { begloc = endloc;
139 parlen = -parlen;
140 }
141 e_go(begloc);
142 len = d_curind(); /* Set up current col */
143
144#if FX_SFPREF
145 /* If at beg of line, check for fill prefix and skip over it */
146 if((len == 0) && tstfillp(parlen))
147 { parlen -= fill_plen;
148 len = d_curind();
149 }
150#endif /*FX_SFPREF*/
151 lastbrk = 0; /* Put next word on no matter what. */
152 c = 0;
153 for(;;)
154 {
155#if ICONOGRAPHICS
156 if (c != ')' && c != '"') /* allow for two sp after .) or ." */
157#endif /*ICONOGRAPHICS*/
158 lastc = c;
159 if(--parlen < 0) break;
160 c = e_getc();
161 if(c == EOF)
162 break;
163#if FX_SFPREF
164 /* If at beg of line, check for fill prefix and flush it */
165 if((c == LF) && tstfillp(parlen))
166 { e_igoff(-(fill_plen+1));
167 e_ovwc(c = SP);
168 e_deln((chroff)fill_plen);
169 parlen -= fill_plen;
170 if(cur_dot >= e_dot())
171 cur_dot -= fill_plen;
172 }
173#endif /*FX_SFPREF*/
174 if(c == TAB || c == LF) /* Replace tabs+eols by sps */
175 { e_backc(); /* Back up 1 */
176 e_ovwc(c = SP);
177 }
178 if(c == SP)
179 { if(lastc == SP)
180 { e_rdelc();
181 if(cur_dot > e_dot()) --cur_dot;
182 continue;
183 }
184 lastbrk = len;
185 if(lastc == '.' || lastc == '!' || lastc == '?'
186#if ICONOGRAPHICS
187 || lastc == ':'
188#endif /*ICONOGRAPHICS*/
189 )
190 { if(--parlen < 0) goto done;
191 if((c = e_getc()) == EOF)
192 goto done;
193 len++;
194 if(c != SP)
195 { e_backc();
196 e_putc(c = SP);
197 if(cur_dot >= e_dot()) ++cur_dot;
198 }
199 }
200 }
201#if ICONOGRAPHICS
202 if (c == BS) /* adjust for backspaces */
203 if ((len -= 2) < 0) len = 0;
204#endif /*ICONOGRAPHICS*/
205 /* Normal char */
206 if(++len > ev_fcolumn && lastbrk) /* If went too far */
207 { c = lastbrk - len; /* Must put EOL at last SP */
208 e_igoff(c);
209 parlen -= c; /* C is negative, actually adding */
210 parlen--;
211 e_ovwc(LF);
212 lastbrk = 0;
213 len = 0;
214 c = SP; /* Pretend this char was space */
215#if FX_SFPREF
216 if(fill_plen)
217 { if(cur_dot >= e_dot())
218 cur_dot += fill_plen;
219 /* Better hope no nulls in prefix! */
220 e_sputz(fill_prefix);
221 len = d_curind();
222 }
223#endif /*FX_SFPREF*/
224 }
225 }
226done: savloc = cur_dot;
227 e_setcur(); /* Reached paragraph end, set cur_dot temporarily */
228 buf_tmod(begloc-cur_dot); /* So that proper range is marked */
229 e_gosetcur(savloc); /* Then restore original cur_dot */
230}
231#endif /*FX_FILLREG || FX_FILLPARA*/
232
233
234#if FX_FILLMODE
235
236/* EFUN: "Auto Fill Mode" */
237/* Toggles Auto Fill Mode (a minor mode). */
238f_fillmode()
239{ register char *cp;
240 int *chballoc();
241
242 fill_mode = fill_mode ? 0 : 1;
243 if(!fill_trig)
244 { fill_trig = chballoc(128);
245 for(cp = fill_initrig; *cp; ++cp)
246 chbis(fill_trig, *cp);
247 }
248 redp(RD_MODE);
249}
250
251/* Called by F_INSSELF to handle char insertion in Auto Fill mode */
252fx_insfill(c)
253int c;
254{
255 ed_insn(c,exp);
256 if(chbit(fill_trig, c))
257 { fill_cur_line();
258
259 }
260}
261
262
263fill_cur_line()
264{
265 register int foundit, i;
266 chroff lastbrkdot, boldot, eoldot;
267
268 boldot = e_boldot();
269
270 /* First back up to find place to make first break. */
271 e_bwsp();
272 lastbrkdot = e_dot();
273 foundit = 0;
274 for(foundit = 0; foundit >= 0;)
275 { if((i = d_curind()) <= ev_fcolumn)
276 { if(foundit)
277 foundit = -1;
278 else break;
279 }
280 else ++foundit;
281 while (!c_wsp (e_rgetc ())) ;
282 e_bwsp();
283 lastbrkdot = e_dot();
284 if(lastbrkdot <= boldot)
285 { lastbrkdot = boldot;
286 break;
287 }
288 }
289
290 if(foundit)
291 ed_fill(lastbrkdot, e_eoldot(), 1);
292}
293#endif /*FX_FILLMODE*/
294
295
296#if IMAGEN
297
298#if FX_TEXTMODE
299/* EFUN: "Text Mode Toggle" (not EMACS) */
300f_textmode()
301{
302 cur_buf->b_flags ^= B_TEXTMODE;
303 redp(RD_MODE);
304}
305#endif /*FX_TEXTMODE*/
306
307int curr_indent = -1; /* Current indent (for text mode autowrap) */
308 /* (misnomered: actually current column) */
309chroff best_break; /* Best break point so far */
310
311
312/* Fill-mode version of "Insert Self" */
313
314fim_insself(c)
315int c;
316{
317 register int ind, flags = cur_buf->b_flags;
318
319 /* In Text mode, auto-wrap happens at spaces after fill column */
320 if (c == SP && flags & B_TEXTMODE && exp == 1 && magic_wrap(c))
321 return;
322
323 /* In C-mode, tab stops are every 4 columns */
324 else if (c == TAB && flags & B_CMODE &&
325 (ind = magic_backto_bol()) >= 0)
326 ed_indto((ind + 4) & ~3);
327 else
328 { ed_insn(c, exp);
329
330 /* Keep track of indent, once we have a grip on it */
331 if (last_cmd == INSCMD && curr_indent != -1)
332 { this_cmd = INSCMD; /* Keep the ball rolling */
333 if (c == TAB)
334 curr_indent = ((curr_indent + 8) & ~7)
335 + 8 * (exp - 1);
336 else if (c == '\n')
337 curr_indent = 0;
338 else if (c < SP || c > 0176)
339 curr_indent += (2 * exp);
340 else
341 curr_indent += exp;
342 }
343 }
344}
345
346/* Fill-mode version of "Delete Character" */
347
348fim_dchar()
349{ /* In C mode, deleting at BOL should do fake TAB preservation */
350 if (cur_buf->b_flags & B_CMODE)
351 { chroff savdot;
352 register int c, indent;
353
354 if (e_rgetc() != LF)
355 { /* Only hack this at BOL */
356 e_getc();
357 goto normal;
358 }
359 e_getc();
360 savdot = e_dot();
361 indent = 0;
362 while ((c = e_getc()) == SP || c == TAB)
363 if (c == SP)
364 ++indent;
365 else
366 indent = (indent + 8) & ~7;
367 e_rgetc();
368 if (indent >= 4)
369 { ed_delete(savdot, e_dot());
370 ed_indto((indent - 4) & ~3);
371 f_begline(); /* HACK!!!! */
372 }
373 else
374 { e_go(savdot);
375 ef_deln(exp);
376 }
377 }
378 else
379 normal: return (ef_deln(exp));
380}
381
382/* Fill-mode version of "Backward Delete Character" */
383
384fim_bdchar()
385{ register int ind;
386
387 /* If in C mode, and deleting into white space at BOL, hack tabs */
388 if (exp == 1 && cur_buf->b_flags & B_CMODE &&
389 (ind = magic_backto_bol()) > 0)
390 ed_indto(ind < 4 ? ind - 1 : ((ind - 4) & ~3));
391 else
392 return (ef_deln (-exp));
393}
394
395/* Fill-mode version of "CRLF" */
396fim_crlf()
397{ register int i;
398
399 if(e_getc() == LF
400 && exp == 1
401 && e_lblankp() && e_lblankp())
402 { e_gocur();
403 e_gonl();
404 e_setcur();
405 ed_delete(e_dot(), e_eoldot());
406 }
407 else
408 { e_gocur();
409#if IMAGEN
410 if (cur_buf->b_flags & B_TEXTMODE && exp == 1 &&
411 magic_wrap('\n'))
412 return;
413 else
414#endif /*IMAGEN*/
415 if((i = exp) > 0)
416 do ed_crins();
417 while(--i);
418 }
419}
420
421
422/* Do all magic for auto-wrap in Text mode:
423 * return as did wrap (i.e., everything is taken care of)
424 */
425magic_wrap(tc)
426int tc; /* "trigger char" */
427{
428 register int c, indent, i, nc;
429 chroff savdot, modstart, breakdot;
430
431 savdot = e_dot();
432 nc = 0;
433 if (last_cmd == INSCMD && curr_indent != -1)
434 { indent = curr_indent; /* Already know our indent */
435 breakdot = best_break;
436 }
437 else
438 {
439#ifdef INDENTDEBUG
440 barf2("Full indent calculation");
441#endif
442 for (nc = 0; (c = e_rgetc()) != EOF && c != '\n'; ++nc)
443 ; /* nc: # chars to look at */
444 if (c == '\n') /* Go back over NL */
445 e_getc();
446 indent = 0;
447
448 /* Search for last line break point, leaving it in breakdot */
449 breakdot = (chroff)0;
450 while (--nc >= 0)
451 { c = e_getc();
452 if (c == TAB)
453 indent = (indent + 8) & ~7;
454 else if (c < SP || c > 0176)
455 indent += 2;
456 else
457 ++indent;
458 if ((c == SP || c == TAB) &&
459 (breakdot == (chroff)0 || (indent <= ev_fcolumn)))
460 breakdot = e_dot();
461 }
462 }
463
464 /* If there is nothing to do, get out */
465 if (indent <= ev_fcolumn)
466 { e_go(savdot);
467 if (tc == SP)
468 { curr_indent = indent;
469 best_break = (chroff)(savdot + 1); /* Remember here, also */
470 this_cmd = INSCMD; /* We do know current indent */
471 }
472 else if (tc == '\n')
473 { curr_indent = 0;
474 best_break = (chroff)0;
475 this_cmd = INSCMD;
476 }
477 else
478 errbarf("bad trigger");
479 return(0);
480 }
481
482 if (breakdot == (chroff)0)
483 {
484 /* No breakpoint found or none needed, just break line at end
485 */
486 e_go(savdot);
487 modstart = savdot;
488 e_putc('\n');
489 }
490 else
491 {
492 /* Get to breakpoint and replace with newline
493 */
494 e_go(breakdot);
495 e_rdelc();
496 modstart = e_dot(); /* Remember where changes start */
497 e_putc('\n'); /* Insert line break */
498 e_go(savdot); /* Get back to trigger point */
499 }
500 if (e_rgetc() != '\n')
501 { /* If not at line start, */
502 e_getc();
503 e_putc(tc); /* insert trigger character */
504
505 /* Once again, compute new indent by backing up to BOL */
506 for (nc = 0; (c = e_rgetc()) != EOF && c != '\n'; ++nc)
507 ;
508 if (c == '\n') /* Go back over NL */
509 e_getc();
510 indent = 0;
511 breakdot = (chroff)0;
512 while (--nc >= 0)
513 { /* Get back to current dot */
514 c = e_getc();
515 if (c == TAB)
516 indent = (indent + 8) & ~7;
517 else if (c < SP || c > 0176)
518 indent += 2;
519 else
520 ++indent;
521 if ((c == SP || c == TAB) &&
522 (breakdot == (chroff)0 || (indent <= ev_fcolumn)))
523 breakdot = e_dot();
524 }
525 if (breakdot == (chroff)0) /* If no good break found, use dot */
526 breakdot = e_dot();
527 curr_indent = indent; /* Now we know where we are */
528 if (tc == '\n') /* If trigger was NL */
529 best_break = (chroff)0; /* indent is 0, and no best break */
530 else
531 best_break = breakdot; /* This is best break so far */
532 }
533 else
534 { e_getc();
535 curr_indent = 0; /* At line start, no indent */
536 best_break = (chroff)0; /* Do not have a best break so far */
537 }
538 ed_setcur();
539 buf_tmat(modstart); /* Alert to potential changes */
540 this_cmd = INSCMD; /* Say we know where we are */
541 return(1);
542}
543
544/* Do lots of magic things for C-mode indent:
545 * erase back to BOL iff we are looking back at white space only,
546 * returning the indent level of the original dot
547 * (< 0 means no erasure done)
548 */
549/*#define MYDEBUG /* */
550#ifdef MYDEBUG
551reveal(msg, v1, v2, v3)
552char *msg;
553{
554 char ahint[128];
555 sprintf(ahint, msg, v1, v2, v3);
556 barf2(ahint);
557}
558#endif
559
560magic_backto_bol()
561{
562 chroff savdot;
563 register int c, indent, nc, i;
564
565 savdot = e_dot();
566 nc = 0;
567 while ((c = e_rgetc()) != EOF && c != LF)
568 { ++nc; /* Count # chars */
569 if (c != SP && c != TAB)
570 { e_go(savdot);
571#ifdef MYDEBUG
572 reveal("fail: nc: %d", nc);
573#endif
574 return -1;
575 }
576 }
577 if (c == LF) /* Go back over the LF */
578 e_getc();
579 indent = 0; /* (zero-based indent) */
580 savdot = e_dot(); /* BOL is now origin for delete */
581 for (i = 1; i <= nc; ++i)
582 if ((c = e_getc()) == SP)
583 ++indent;
584 else /* (tab) */
585 indent = (indent + 8) & ~7;
586 if (nc > 0) /* Don't bother deleting nothing */
587 ed_delete(savdot, e_dot());
588#ifdef MYDEBUG
589 reveal("indent: %d, nc: %d, foo: %d", indent, nc, 234);
590#endif
591 return(indent);
592}
593#endif /*IMAGEN*/
594
595
596#if ICONOGRAPHICS
597/* Iconographics hack for Auto-Fill mode. Too big and clumsy, but
598 * retained for posterity in case it has some obscure feature.
599 */
600
601fill_current_line ()
602{
603 chroff startpos, endpos, savepos, limitpos;
604 int i, foundit;
605 SBSTR *savep;
606
607 foundit = 0;
608 while (d_curind() > ev_fcolumn)
609 {
610 foundit = 1;
611 startpos = e_dot ();
612 e_bwsp ();
613 while (d_curind() > ev_fcolumn) /* back up to ends of wds*/
614 { /* until <= fill column */
615 while (!c_wsp (e_rgetc ())) ;
616 e_bwsp ();
617 }
618 if (e_dot () == e_boldot ())
619 { /* ding ("Word does not fit in fill column"); */
620 return(0);
621 }
622 savep = e_copyn (startpos - e_dot ());
623 e_setcur (); /* ed_delete does gocur */
624 ed_delete (savepos = e_dot (), startpos);
625
626 f_crlf(); /* Now insert newline */
627 e_sputz(fill_prefix); /* With fill prefix */
628 startpos += e_dot () - savepos;
629 if (d_curind() > ev_fcolumn)
630 { ed_delete (savepos, e_dot ());
631 sb_sins (cur_buf, savep);
632 e_setcur ();
633 ding ("Fill prefix > fill column???");
634 return(0);
635 }
636 savepos = e_dot (); /* gun inherited initial whitespace */
637 sb_sins (cur_buf, savep);
638 e_go (savepos);
639 e_fwsp ();
640 if ((limitpos = e_dot ()) > startpos) limitpos = startpos;
641 /* in case rest of line was white */
642 ed_delete (savepos, limitpos);
643 e_gosetcur (startpos + savepos - limitpos);
644 }
645
646 return foundit;
647 }
648#endif /*ICONOGRAPHICS*/
Note: See TracBrowser for help on using the repository browser.