]> diplodocus.org Git - nmh/blob - docs/historical/mh-6.8.5/uip/RCS/wmh.c,v
sbr/mts.c: Delete mmdlm2; use same-valued mmdlm1 instead.
[nmh] / docs / historical / mh-6.8.5 / uip / RCS / wmh.c,v
1 head 1.5;
2 access;
3 symbols;
4 locks; strict;
5 comment @ * @;
6
7
8 1.5
9 date 93.08.25.17.29.59; author jromine; state Exp;
10 branches;
11 next 1.4;
12
13 1.4
14 date 92.11.04.02.29.30; author jromine; state Exp;
15 branches;
16 next 1.3;
17
18 1.3
19 date 90.04.05.15.03.31; author sources; state Exp;
20 branches;
21 next 1.2;
22
23 1.2
24 date 90.03.12.14.01.46; author sources; state Exp;
25 branches;
26 next 1.1;
27
28 1.1
29 date 90.03.12.14.00.55; author sources; state Exp;
30 branches;
31 next ;
32
33
34 desc
35 @@
36
37
38 1.5
39 log
40 @off_t fixes for BSD44
41 @
42 text
43 @/* wmh.c - window front-end to mh */
44 #ifndef lint
45 static char ident[] = "@@(#)$Id: wmh.c,v 1.4 1992/11/04 02:29:30 jromine Exp jromine $";
46 #endif lint
47
48 /* TODO:
49 Pass signals to client during execution
50
51 Figure out a way for the user to say how big the Scan/Display
52 windows should be, and where all the windows should be.
53 */
54
55 #include <stdio.h>
56 #include "../h/mh.h"
57 #include "../h/vmhsbr.h"
58 #include <ctype.h>
59 #include <errno.h>
60 #include <setjmp.h>
61 #include <signal.h>
62 #ifndef sigmask
63 #define sigmask(s) (1 << ((s) - 1))
64 #endif not sigmask
65 #include <sys/types.h>
66 #include <sys/uio.h>
67 #include <vt.h>
68 #include <bitmap.h>
69 #include <tools.h>
70 #ifdef LOCALE
71 #include <locale.h>
72 #endif
73
74
75 #define ALARM ((unsigned int) 10)
76 #define PAUSE ((unsigned int) 2)
77
78 #define abs(a) ((a) > 0 ? (a) : -(a))
79
80 #define SZ(a) (sizeof a / sizeof a[0])
81
82 /* \f */
83
84 static struct swit switches[] = {
85 #define PRMPTSW 0
86 "prompt string", 6,
87
88 #define PROGSW 1
89 "vmhproc program", 7,
90 #define NPROGSW 2
91 "novmhproc", 9,
92
93 #define HELPSW 3
94 "help", 4,
95
96 NULL, NULL
97 };
98
99 /* \f */
100 /* PEERS */
101 static int PEERpid = NOTOK;
102
103 static jmp_buf PEERctx;
104
105
106
107 /* WINDOWS */
108 static int dfd = NOTOK;
109
110 static int twd = NOTOK;
111
112 static char *myprompt = "(%s) ";
113
114
115 struct line {
116 int l_no;
117 char *l_buf;
118 struct line *l_prev;
119 struct line *l_next;
120 };
121
122
123 typedef struct {
124 int w_fd;
125
126 int w_flags;
127 #define W_NULL 0x00
128 #define W_CMND 0x01
129 #define W_FAKE 0x02
130 #define W_EBAR 0x04
131
132 int w_wd;
133
134 struct wstate w_ws;
135
136 char *w_eb;
137 int w_ebloc;
138 int w_ebsize;
139
140 int w_cbase;
141 int w_height;
142 int w_cheight;
143 int w_width;
144 int w_cwidth;
145
146 struct line *w_head;
147 struct line *w_top;
148 struct line *w_bottom;
149 struct line *w_tail;
150
151 char w_buffer[BUFSIZ];
152 int w_bufpos;
153 } WINDOW;
154
155
156 static WINDOW *Scan;
157 static WINDOW *Status;
158 static WINDOW *Display;
159 static WINDOW *Command;
160
161
162 #define NWIN 4
163 static int numwins;
164 WINDOW *windows[NWIN + 1];
165
166
167 WINDOW *WINnew ();
168
169
170 /* SIGNALS */
171 #define ERASE sg.sg_erase
172 #define KILL sg.sg_kill
173 static struct sgttyb sg;
174
175 #define EOFC tc.t_eofc
176 #define INTR tc.t_intrc
177 static struct tchars tc;
178
179 #define WERASC ltc.t_werasc
180 static struct ltchars ltc;
181
182
183 int ALRMser (), PIPEser (), SIGser ();
184 int ADJser (), REFser ();
185
186
187 /* MISCELLANY */
188 extern int errno;
189 #ifndef BSD44
190 extern int sys_nerr;
191 extern char *sys_errlist[];
192 #endif
193
194 void adorn ();
195
196 /* \f */
197
198 /* ARGSUSED */
199
200 main (argc, argv)
201 int argc;
202 char *argv[];
203 {
204 int vecp = 1,
205 nprog = 0;
206 char *cp,
207 buffer[BUFSIZ],
208 **ap,
209 **argp,
210 *arguments[MAXARGS],
211 *vec[MAXARGS];
212
213 #ifdef LOCALE
214 setlocale(LC_ALL, "");
215 #endif
216 invo_name = r1bindex (argv[0], '/');
217 if ((cp = m_find (invo_name)) != NULL) {
218 ap = brkstring (cp = getcpy (cp), " ", "\n");
219 ap = copyip (ap, arguments);
220 }
221 else
222 ap = arguments;
223 (void) copyip (argv + 1, ap);
224 argp = arguments;
225
226 /* \f */
227
228 while (cp = *argp++)
229 if (*cp == '-')
230 switch (smatch (++cp, switches)) {
231 case AMBIGSW:
232 ambigsw (cp, switches);
233 done (1);
234 case UNKWNSW:
235 vec[vecp++] = --cp;
236 continue;
237 case HELPSW:
238 (void) sprintf (buffer, "%s [switches for vmhproc]",
239 invo_name);
240 help (buffer, switches);
241 done (1);
242
243 case PRMPTSW:
244 if (!(myprompt = *argp++) || *myprompt == '-')
245 adios (NULLCP, "missing argument to %s", argp[-2]);
246 continue;
247
248 case PROGSW:
249 if (!(vmhproc = *argp++) || *vmhproc == '-')
250 adios (NULLCP, "missing argument to %s", argp[-2]);
251 continue;
252 case NPROGSW:
253 nprog++;
254 continue;
255 }
256 else
257 vec[vecp++] = cp;
258
259 /* \f */
260
261 (void) SIGinit ();
262 if (WINinit (nprog) == NOTOK) {
263 vec[vecp] = NULL;
264
265 vec[0] = r1bindex (vmhproc, '/');
266 execvp (vmhproc, vec);
267 adios (vmhproc, "unable to exec");
268 }
269 (void) PEERinit (vecp, vec);
270
271 vmh ();
272
273 done (0);
274 }
275
276 /* \f */
277
278 static vmh () {
279 char buffer[BUFSIZ],
280 prompt[BUFSIZ];
281
282 for (;;) {
283 (void) pLOOP (RC_QRY, NULLCP);
284
285 (void) sprintf (prompt, myprompt, invo_name);
286
287 switch (WINgetstr (Command, prompt, buffer)) {
288 case NOTOK:
289 break;
290
291 case OK:
292 done (0); /* NOTREACHED */
293
294 default:
295 if (*buffer)
296 (void) pLOOP (RC_CMD, buffer);
297 break;
298 }
299 }
300 }
301
302 /* \f PEERS */
303
304 static int PEERinit (vecp, vec)
305 int vecp;
306 char *vec[];
307 {
308 int pfd0[2],
309 pfd1[2];
310 char buf1[BUFSIZ],
311 buf2[BUFSIZ];
312 register WINDOW **w;
313
314 (void) signal (SIGPIPE, PIPEser);
315
316 if (pipe (pfd0) == NOTOK || pipe (pfd1) == NOTOK)
317 adios ("pipe", "unable to");
318 switch (PEERpid = vfork ()) {
319 case NOTOK:
320 adios ("vfork", "unable to");/* NOTREACHED */
321
322 case OK:
323 for (w = windows; *w; w++)
324 if ((*w) -> w_fd != NOTOK)
325 (void) close ((*w) -> w_fd);
326 (void) close (pfd0[0]);
327 (void) close (pfd1[1]);
328
329 vec[vecp++] = "-vmhread";
330 (void) sprintf (buf1, "%d", pfd1[0]);
331 vec[vecp++] = buf1;
332 vec[vecp++] = "-vmhwrite";
333 (void) sprintf (buf2, "%d", pfd0[1]);
334 vec[vecp++] = buf2;
335 vec[vecp] = NULL;
336
337 (void) signal (SIGINT, SIG_DFL);
338 (void) signal (SIGQUIT, SIG_DFL);
339 (void) signal (SIGTERM, SIG_DFL);
340
341 vec[0] = r1bindex (vmhproc, '/');
342 execvp (vmhproc, vec);
343 perror (vmhproc);
344 _exit (-1); /* NOTREACHED */
345
346 default:
347 (void) close (pfd0[1]);
348 (void) close (pfd1[0]);
349
350 (void) rcinit (pfd0[0], pfd1[1]);
351 return pINI ();
352 }
353 }
354
355 /* \f */
356
357 static int pINI () {
358 register char *bp;
359 char buffer[BUFSIZ];
360 struct record rcs;
361 register struct record *rc = &rcs;
362 register WINDOW **w;
363
364 initrc (rc);
365
366 bp = buffer;
367 (void) sprintf (bp, "%d %d", RC_VRSN, numwins);
368 bp += strlen (bp);
369 for (w = windows; *w; w++) {
370 (void) sprintf (bp, " %d", (*w) -> w_height);
371 bp += strlen (bp);
372 }
373
374 switch (str2rc (RC_INI, buffer, rc)) {
375 case RC_ACK:
376 return OK;
377
378 case RC_ERR:
379 if (rc -> rc_len)
380 adios (NULLCP, "%s", rc -> rc_data);
381 else
382 adios (NULLCP, "pINI peer error");
383
384 case RC_XXX:
385 adios (NULLCP, "%s", rc -> rc_data);
386
387 default:
388 adios (NULLCP, "pINI protocol screw-up");
389 }
390 /* NOTREACHED */
391 }
392
393 /* \f */
394
395 static int pLOOP (code, str)
396 char code,
397 *str;
398 {
399 int i;
400 struct record rcs;
401 register struct record *rc = &rcs;
402 WINDOW *w;
403
404 initrc (rc);
405
406 (void) str2peer (code, str);
407 for (;;)
408 switch (peer2rc (rc)) {
409 case RC_TTY:
410 if (pTTY () == NOTOK)
411 return NOTOK;
412 break;
413
414 case RC_WIN:
415 if (sscanf (rc -> rc_data, "%d", &i) != 1
416 || i <= 0
417 || i > numwins) {
418 (void) fmt2peer (RC_ERR, "no such window \"%s\"",
419 rc -> rc_data);
420 return NOTOK;
421 }
422 if ((w = windows[i - 1]) -> w_flags & W_CMND) {
423 (void) fmt2peer (RC_ERR, "not a display window \"%s\"",
424 rc -> rc_data);
425 return NOTOK;
426 }
427 if (pWIN (w) == NOTOK)
428 return NOTOK;
429 break;
430
431 case RC_EOF:
432 return OK;
433
434 case RC_ERR:
435 if (rc -> rc_len)
436 adorn (NULLCP, "%s", rc -> rc_data);
437 else
438 adorn (NULLCP, "pLOOP(%s) peer error",
439 code == RC_QRY ? "QRY" : "CMD");
440 return NOTOK;
441
442 case RC_FIN:
443 if (rc -> rc_len)
444 adorn (NULLCP, "%s", rc -> rc_data);
445 (void) rcdone ();
446 i = pidwait (PEERpid, OK);
447 PEERpid = NOTOK;
448 done (i);
449
450 case RC_XXX:
451 adios (NULLCP, "%s", rc -> rc_data);
452
453 default:
454 adios (NULLCP, "pLOOP(%s) protocol screw-up",
455 code == RC_QRY ? "QRY" : "CMD");
456 }
457 }
458
459 /* \f */
460
461 static int pTTY () {
462 TYPESIG (*hstat) (), (*istat) (), (*qstat) (), (*tstat) ();
463 struct record rcs;
464 register struct record *rc = &rcs;
465
466 initrc (rc);
467
468 if (ChangeWindowDepth (dfd, twd, 0) == NOTOK)
469 adios ("failed", "ChangeWindowDepth");
470
471 hstat = signal (SIGHUP, SIG_IGN);
472 istat = signal (SIGINT, SIG_IGN);
473 qstat = signal (SIGQUIT, SIG_IGN);
474 tstat = signal (SIGTERM, SIG_IGN);
475
476 (void) rc2rc (RC_ACK, 0, NULLCP, rc);
477
478 (void) signal (SIGHUP, hstat);
479 (void) signal (SIGINT, istat);
480 (void) signal (SIGQUIT, qstat);
481 (void) signal (SIGTERM, tstat);
482
483 switch (rc -> rc_type) {
484 case RC_EOF:
485 (void) rc2peer (RC_ACK, 0, NULLCP);
486 return OK;
487
488 case RC_ERR:
489 if (rc -> rc_len)
490 adorn (NULLCP, "%s", rc -> rc_data);
491 else
492 adorn (NULLCP, "pTTY peer error");
493 return NOTOK;
494
495 case RC_XXX:
496 adios (NULLCP, "%s", rc -> rc_data);
497
498 default:
499 adios (NULLCP, "pTTY protocol screw-up");
500 }
501 /* NOTREACHED */
502 }
503
504 /* \f */
505
506 static int pWIN (w)
507 register WINDOW *w;
508 {
509 int i;
510
511 if ((i = pWINaux (w)) == OK)
512 WINless (w);
513
514 return i;
515 }
516
517 /* \f */
518
519 static int pWINaux (w)
520 register WINDOW *w;
521 {
522 register int n;
523 register char *bp;
524 register struct line *lp,
525 *mp;
526 struct record rcs;
527 register struct record *rc = &rcs;
528
529 initrc (rc);
530
531 for (lp = w -> w_head; lp; lp = mp) {
532 mp = lp -> l_next;
533 free (lp -> l_buf);
534 free ((char *) lp);
535 }
536 w -> w_head = w -> w_top = w -> w_bottom = w -> w_tail = NULL;
537 w -> w_bufpos = 0;
538
539 for (;;)
540 switch (rc2rc (RC_ACK, 0, NULLCP, rc)) {
541 case RC_DATA:
542 for (bp = rc -> rc_data, n = rc -> rc_len; n-- > 0; )
543 (void) WINputc (w, *bp++);
544 break;
545
546 case RC_EOF:
547 (void) rc2peer (RC_ACK, 0, NULLCP);
548 if (w -> w_bufpos)
549 (void) WINputc (w, '\n');
550 return OK;
551
552 case RC_ERR:
553 if (rc -> rc_len)
554 adorn (NULLCP, "%s", rc -> rc_data);
555 else
556 adorn (NULLCP, "pWIN peer error");
557 return NOTOK;
558
559 case RC_XXX:
560 adios (NULLCP, "%s", rc -> rc_data);
561
562 default:
563 adios (NULLCP, "pWIN protocol screw-up");
564 }
565 /* NOTREACHED */
566 }
567
568 /* \f */
569
570 static int pFIN () {
571 int status;
572
573 if (PEERpid <= OK)
574 return OK;
575
576 (void) rc2peer (RC_FIN, 0, NULLCP);
577 (void) rcdone ();
578
579 switch (setjmp (PEERctx)) {
580 case OK:
581 (void) signal (SIGALRM, ALRMser);
582 (void) alarm (ALARM);
583
584 status = pidwait (PEERpid, OK);
585
586 (void) alarm (0);
587 break;
588
589 default:
590 (void) kill (PEERpid, SIGKILL);
591 status = NOTOK;
592 break;
593 }
594 PEERpid = NOTOK;
595
596 return status;
597 }
598
599 /* \f WINDOWS */
600
601 /* should dynamically determine all this stuff from gconfig... */
602
603 #define MyX 20 /* anchored hpos */
604 #define MyY 40 /* .. vpos */
605 #define MyW 800 /* .. width */
606 #define MyH 500 /* .. height */
607 #define MyS 30 /* .. height for Status, about one line */
608
609
610 #define MySlop 45 /* slop */
611
612 #define EWIDTH 25 /* Width of vertical EBAR */
613 #define ESLOP 5 /* .. slop */
614
615
616 static int WINinit (nprog) {
617 short wx,
618 wy,
619 wh,
620 sy;
621 struct gconfig gc;
622
623 if (GetGraphicsConfig (fileno (stderr), &gc) == NOTOK)
624 if (nprog)
625 return NOTOK;
626 else
627 adios (NULLCP, "not a window");
628
629 if ((dfd = open ("/dev/ttyw0", 2)) == NOTOK)
630 adios ("/dev/ttyw0", "unable to open");
631
632 if ((twd = GetTopWindow (dfd)) == NOTOK)
633 adios ("failed", "GetTopWindow");
634
635 (void) BlockRefreshAdjust (1);
636
637 numwins = 0;
638
639 wx = gc.w - (MyX + MyW + EWIDTH + ESLOP);
640 Scan = WINnew (wx, wy = MyY, MyW, wh = MyH * 2 / 3, "Scan", W_EBAR);
641
642 wy += wh + MySlop;
643 Status = WINnew (wx, sy = wy, MyW, wh = MyS, "Status", W_FAKE);
644
645 wy += wh + MySlop;
646 Display = WINnew (wx, wy, MyW, MyH, "Display", W_EBAR);
647
648 Command = WINnew (wx, sy, MyW, MyS, invo_name, W_CMND);
649
650 windows[numwins] = NULL;
651
652 return OK;
653 }
654
655 /* \f */
656
657 WINDOW *WINnew (wx, wy, ww, wh, name, flags)
658 short wx,
659 wy,
660 ww,
661 wh;
662 char *name;
663 int flags;
664 {
665 register WINDOW *w;
666
667 if ((w = (WINDOW *) calloc (1, sizeof *w)) == NULL)
668 adios (NULLCP, "unable to allocate window");
669
670 if ((w -> w_flags = flags) & W_FAKE) {
671 w -> w_fd = NOTOK;
672 w -> w_height = 1;
673
674 goto out;
675 }
676
677 if (w -> w_flags & W_EBAR)
678 ww += EWIDTH + ESLOP;
679 else
680 wx += EWIDTH + ESLOP;
681
682 if ((w -> w_fd = OpenWindow (wx, wy, ww, wh, name)) == NOTOK)
683 adios ("failed", "OpenWindow");
684 if ((w -> w_wd = GetTopWindow (dfd)) == NOTOK)
685 adios ("failed", "GetTopWindow");
686 if (GetWindowState (w -> w_fd, &w -> w_ws) == NOTOK)
687 adios ("failed", "GetWindowState");
688 if (SetLineDisc (w -> w_fd, TWSDISC) == NOTOK)
689 adios ("failed", "SetLineDisc");
690
691 SetBuf (w -> w_fd, 1024);
692 (void) SetAdjust (w -> w_fd, numwins, ADJser);
693 (void) SetRefresh (w -> w_fd, numwins, REFser);
694
695 SetAddressing (w -> w_fd, VT_ABSOLUTE);
696
697 if (w -> w_flags & W_EBAR) {
698 w -> w_eb = CreateElevatorBar (w -> w_fd, 0, 0, EWIDTH,
699 w -> w_ws.height, VT_Gray50, 1, EB_VERTICAL,
700 EB_ARROWS, w -> w_ebloc = 0, w -> w_ebsize = EB_MAX,
701 VT_White);
702 if (w -> w_eb == NULL)
703 adios (NULLCP, "CreateElevatorBar failed");
704 RefreshElevatorBar (w -> w_eb);
705 }
706
707 if ((w -> w_cbase = CharacterBaseline (w -> w_ws.font)) <= 0)
708 w -> w_cbase = 14;
709
710 if ((w -> w_cheight = CharacterHeight (w -> w_ws.font)) <= 0)
711 w -> w_cheight = 20;
712 w -> w_height = w -> w_ws.height / w -> w_cheight;
713 if (w -> w_height < 1)
714 w -> w_height = 1;
715
716 /* 1 em */
717 if ((w -> w_cwidth = CharacterWidth (w -> w_ws.font, 'm')) <= 0)
718 w -> w_cwidth = 10;
719 w -> w_width = (w -> w_ws.width - (w -> w_eb ? (EWIDTH + ESLOP) : 0))
720 / w -> w_cwidth;
721 if (w -> w_width < 1)
722 w -> w_width = 1;
723
724 out: ;
725 windows[numwins++] = w;
726
727 return w;
728 }
729
730 /* \f */
731
732 static int WINgetstr (w, prompt, buffer)
733 register WINDOW *w;
734 char *prompt,
735 *buffer;
736 {
737 register int c;
738 register char *bp,
739 *ip;
740 char image[BUFSIZ];
741 struct vtseq vts;
742 register struct vtseq *vt = &vts;
743
744 if (w -> w_eb != NULL)
745 adios (NULLCP, "internal error--elevator bar found");
746
747 if (w -> w_head == NULL
748 && (w -> w_head = (struct line *) calloc (1, sizeof *w -> w_head))
749 == NULL)
750 adios (NULLCP, "unable to allocate line storage");
751 w -> w_head -> l_buf = image;
752 w -> w_top = w -> w_bottom = w -> w_tail = w -> w_head;
753
754 if (ChangeWindowDepth (dfd, w -> w_wd, 0) == NOTOK)
755 adios ("failed", "ChangeWindowDepth");
756
757 (void) strcpy (image, prompt);
758 bp = ip = image + strlen (image);
759
760 Redisplay (w, 0);
761
762 for (;;)
763 switch (getvtseq (w -> w_fd, vt)) {
764 case VT_HARDKEY:
765 DisplayStatus (w -> w_fd, "no hardkeys, please");
766 break;
767
768 case VT_ASCII:
769 switch (c = toascii (vt -> u.ascii)) {
770 case '\f': /* refresh? */
771 break;
772
773 case '\r':
774 case '\n':
775 (void) strcpy (buffer, ip);
776 return DONE;
777
778 default:
779 if (c == INTR) {
780 adorn (NULLCP, "Interrupt");
781 return NOTOK;
782 }
783
784 if (c == EOFC) {
785 if (bp <= ip)
786 return OK;
787 break;
788 }
789
790 if (c == ERASE) {
791 if (bp <= ip)
792 continue;
793 bp--;
794 break;
795 }
796
797 if (c == KILL) {
798 if (bp <= ip)
799 continue;
800 bp = ip;
801 break;
802 }
803
804 if (c == WERASC) {
805 if (bp <= ip)
806 continue;
807 do {
808 bp--;
809 } while (isspace (*bp) && bp > ip);
810 if (bp > ip) {
811 do {
812 bp--;
813 } while (!isspace (*bp) && bp > buffer);
814 if (isspace (*bp))
815 bp++;
816 }
817 break;
818 }
819
820 if (c < ' ' || c >= '\177')
821 continue;
822 *bp++ = c;
823 break;
824 }
825 *bp = NULL;
826 Redisplay (w, 0);
827 break;
828
829 case VT_MOUSE:
830 switch (vt -> u.mouse.buttons
831 & (VT_MOUSE_LEFT | VT_MOUSE_MIDDLE | VT_MOUSE_RIGHT)) {
832 case VT_MOUSE_LEFT:
833 DisplayStatus (w -> w_fd, "use middle or right button");
834 break;
835
836 #define WPOP "WMH\0Advance\0Burst\0Exit\0EOF\0"
837 case VT_MOUSE_MIDDLE:
838 SetPosition (w -> w_fd, vt -> u.mouse.x,
839 vt -> u.mouse.y);
840 switch (DisplayPopUp (w -> w_fd, WPOP)) {
841 case 1: /* Advance */
842 do_advance: ;
843 (void) strcpy (buffer, "advance");
844 return DONE;
845
846 case 2: /* Burst */
847 (void) strcpy (buffer, "burst");
848 return DONE;
849
850 case 3: /* Exit */
851 (void) strcpy (buffer, "exit");
852 return DONE;
853
854 case 4: /* EOF */
855 return OK;
856
857 default: /* failed or none taken */
858 break;
859 }
860 break;
861 #undef WPOP
862
863 case VT_MOUSE_RIGHT:
864 goto do_advance;
865 }
866 break;
867
868 case VT_EOF:
869 adios (NULLCP, "end-of-file on window");/* NOTREACHED */
870
871 default:
872 DisplayStatus (w -> w_fd, "unknown VT sequence");
873 break;
874 }
875 }
876
877 /* \f */
878
879 static int WINputc (w, c)
880 register WINDOW *w;
881 register char c;
882 {
883 register int i;
884 register char *cp;
885 register struct line *lp;
886
887 switch (c) {
888 default:
889 if (!isascii (c)) {
890 if (WINputc (w, 'M') == NOTOK || WINputc (w, '-') == NOTOK)
891 return NOTOK;
892 c = toascii (c);
893 }
894 else
895 if (c < ' ' || c == '\177') {
896 if (WINputc (w, '^') == NOTOK)
897 return NOTOK;
898 c ^= 0100;
899 }
900 break;
901
902 case '\t':
903 for (i = 8 - (w -> w_bufpos & 0x07); i > 0; i--)
904 if (WINputc (w, ' ') == NOTOK)
905 return NOTOK;
906 return OK;
907
908 case '\b':
909 if (w -> w_bufpos > 0)
910 w -> w_bufpos--;
911 return OK;
912
913 case '\n':
914 break;
915 }
916
917 if (c != '\n') {
918 w -> w_buffer[w -> w_bufpos++] = c;
919 return OK;
920 }
921
922 w -> w_buffer[w -> w_bufpos] = NULL;
923 w -> w_bufpos = 0;
924
925 if ((lp = (struct line *) calloc (1, sizeof *lp)) == NULL)
926 adios (NULLCP, "unable to allocate line storage");
927
928 lp -> l_no = (w -> w_tail ? w -> w_tail -> l_no : 0) + 1;
929 lp -> l_buf = getcpy (w -> w_buffer);
930 for (cp = lp -> l_buf + strlen (lp -> l_buf) - 1; cp >= lp -> l_buf; cp--)
931 if (isspace (*cp))
932 *cp = NULL;
933 else
934 break;
935
936 if (w -> w_head == NULL)
937 w -> w_head = lp;
938 if (w -> w_top == NULL)
939 w -> w_top = lp;
940 if (w -> w_bottom == NULL)
941 w -> w_bottom = lp;
942 if (w -> w_tail)
943 w -> w_tail -> l_next = lp;
944 lp -> l_prev = w -> w_tail;
945 w -> w_tail = lp;
946
947 return DONE;
948 }
949
950 /* \f */
951
952 #define PSLOP 2
953
954
955 static char mylineno[5];
956
957 static bool cancel[] = { 1 };
958 static struct choice mychoices[] = { LABEL, "cancel", VT_White };
959
960 static struct question myquestions[] = {
961 STRING, "Line", SZ (mylineno), (struct choice *) 0,
962
963 TOGGLE, "", SZ (mychoices), mychoices
964 };
965
966 static struct menu mymenu = { "Goto", SZ (myquestions), myquestions };
967
968 static int *myanswers[] = { (int *) mylineno, (int *) cancel };
969
970
971 static WINless (w)
972 register WINDOW *w;
973 {
974 int clear,
975 pos,
976 forw,
977 refresh;
978 struct vtseq vts;
979 register struct vtseq *vt = &vts;
980
981 if (w -> w_fd == NOTOK) {
982 if (w -> w_head)
983 DisplayStatus (dfd, w -> w_top -> l_buf);
984 else
985 RemoveStatus (dfd);
986
987 return;
988 }
989
990 if (ChangeWindowDepth (dfd, w -> w_wd, 0) == NOTOK)
991 adios ("failed", "ChangeWindowDepth");
992
993 Redisplay (w, 0);
994
995 if (w -> w_bottom == w -> w_tail)
996 return;
997
998 if (w -> w_eb == NULL)
999 adios (NULLCP, "internal error--no elevator bar");
1000
1001 for (clear = refresh = 0, forw = 1;;) {
1002 if (clear) {
1003 RemoveStatus (w -> w_fd);
1004 clear = 0;
1005 }
1006 if (refresh) {
1007 Redisplay (w, 0);
1008 refresh = 0;
1009 }
1010
1011 switch (getvtseq (w -> w_fd, vt)) {
1012 case VT_HARDKEY:
1013 case VT_ASCII:
1014 DisplayStatus (w -> w_fd, "use the mouse");
1015 clear++;
1016 break;
1017
1018 case VT_MOUSE:
1019 switch (vt -> u.mouse.buttons
1020 & (VT_MOUSE_LEFT | VT_MOUSE_MIDDLE | VT_MOUSE_RIGHT)) {
1021 case VT_MOUSE_LEFT:
1022 if ((pos = vt -> u.mouse.x) < EWIDTH) {
1023 pos = w -> w_ebloc = DoElevatorBar (w -> w_eb, pos,
1024 vt -> u.mouse.y);
1025 refresh = WINgoto (w, ((pos * (w -> w_tail -> l_no
1026 - w -> w_head -> l_no))
1027 / EB_MAX) + w -> w_head -> l_no);
1028 }
1029 break;
1030
1031 #define WPOP "Paging\0Next\0Prev\0Left\0Right\0First\0Last\0Goto ...\0Exit\0"
1032 case VT_MOUSE_MIDDLE:
1033 SetPosition (w -> w_fd, vt -> u.mouse.x,
1034 vt -> u.mouse.y);
1035 switch (DisplayPopUp (w -> w_fd, WPOP)) {
1036 case 1: /* Next */
1037 do_next_page: ;
1038 if (w -> w_bottom == w -> w_tail)
1039 forw = 0;
1040 refresh = WINgoto (w, w -> w_bottom -> l_no + 1 - PSLOP);
1041 break;
1042
1043 case 2: /* Prev */
1044 do_prev_page: ;
1045 if (w -> w_top == w -> w_head)
1046 forw = 1;
1047 refresh = WINgoto (w, w -> w_top -> l_no
1048 - w -> w_height + PSLOP);
1049 break;
1050
1051 case 3: /* Left */
1052 case 4: /* Right */
1053 DisplayStatus (w -> w_fd, "not yet");
1054 clear++;
1055 break;
1056
1057 case 5: /* First */
1058 forw = 1;
1059 refresh = WINgoto (w, w -> w_head -> l_no);
1060 break;
1061
1062 case 6: /* Last */
1063 forw = 0;
1064 refresh = WINgoto (w, w -> w_tail -> l_no
1065 - w -> w_height + 1);
1066 break;
1067
1068 case 7: /* Goto ... */
1069 (void) sprintf (mylineno, "%d",
1070 w -> w_top -> l_no);
1071 cancel[0] = 0;
1072 if (PresentMenu (&mymenu, myanswers)
1073 || cancel[0])
1074 break;
1075 if (sscanf (mylineno, "%d", &pos) != 1) {
1076 DisplayStatus (w -> w_fd, "bad format");
1077 clear++;
1078 break;
1079 }
1080 if (pos < w -> w_head -> l_no
1081 || pos > w -> w_tail -> l_no) {
1082 DisplayStatus (w -> w_fd, "no such line");
1083 clear++;
1084 break;
1085 }
1086 refresh = WINgoto (w, pos);
1087 break;
1088
1089 case 8: /* Exit */
1090 return;
1091
1092 default: /* failed or none taken */
1093 break;
1094 }
1095 break;
1096 #undef WPOP
1097
1098 case VT_MOUSE_RIGHT:
1099 if (forw) {
1100 if (w -> w_bottom == w -> w_tail)
1101 return;
1102 else
1103 goto do_next_page;
1104 }
1105 else
1106 goto do_prev_page;
1107 }
1108 break;
1109
1110 case VT_EOF:
1111 adios (NULLCP, "end-of-file on window");/* NOTREACHED */
1112
1113 default:
1114 DisplayStatus (w -> w_fd, "unknown VT sequence");
1115 clear++;
1116 break;
1117 }
1118 }
1119 }
1120
1121 /* \f */
1122
1123 static int WINgoto (w, n)
1124 register WINDOW *w;
1125 register int n;
1126 {
1127 register int i,
1128 j;
1129 register struct line *lp;
1130
1131 if (n > (i = w -> w_tail -> l_no - w -> w_height + 1))
1132 n = i;
1133 if (n < w -> w_head -> l_no)
1134 n = w -> w_head -> l_no;
1135
1136 if ((i = n - (lp = w -> w_head) -> l_no)
1137 > (j = abs (n - w -> w_top -> l_no)))
1138 i = j, lp = w -> w_top;
1139
1140 if (i > (j = abs (w -> w_tail -> l_no - n)))
1141 i = j, lp = w -> w_tail;
1142
1143 if (n >= lp -> l_no) {
1144 for (; lp; lp = lp -> l_next)
1145 if (lp -> l_no == n)
1146 break;
1147 }
1148 else {
1149 for (; lp; lp = lp -> l_prev)
1150 if (lp -> l_no == n)
1151 break;
1152 if (!lp)
1153 lp = w -> w_head;
1154 }
1155
1156 if (w -> w_top == lp)
1157 return 0;
1158
1159 w -> w_top = lp;
1160
1161 return 1;
1162 }
1163
1164 /* \f */
1165
1166 static int ADJser (id, ww, wh)
1167 int id;
1168 short ww,
1169 wh;
1170 {
1171 register WINDOW *w;
1172
1173 if (id < 0 || id >= numwins)
1174 adios (NULLCP, "ADJser on bogus window (%d)", id);
1175 w = windows[id];
1176 if (w -> w_fd == NOTOK)
1177 adios (NULLCP, "ADJser on closed window (%d)", id);
1178
1179 w -> w_ws.width = w -> w_ws.tw = ww;
1180 w -> w_ws.height = w -> w_ws.th = wh;
1181
1182 if (w -> w_eb) {
1183 DeleteElevatorBar (w -> w_eb);
1184 w -> w_eb = CreateElevatorBar (w -> w_fd, 0, 0, EWIDTH,
1185 w -> w_ws.height, VT_Gray50, 1, EB_VERTICAL,
1186 EB_ARROWS, w -> w_ebloc = 0, w -> w_ebsize = EB_MAX,
1187 VT_White);
1188 if (w -> w_eb == NULL)
1189 adios (NULLCP, "CreateElevatorBar failed");
1190 }
1191
1192 Redisplay (w, 1);
1193 }
1194
1195
1196 /* ARGSUSED */
1197
1198 static int REFser (id, wx, wy, ww, wh)
1199 int id;
1200 short wx,
1201 wy,
1202 ww,
1203 wh;
1204 {
1205 short cx,
1206 cy,
1207 cw,
1208 ch;
1209 register WINDOW *w;
1210
1211 if (id < 0 || id >= numwins)
1212 adios (NULLCP, "REFser on bogus window (%d)", id);
1213 w = windows[id];
1214 if (w -> w_fd == NOTOK)
1215 adios (NULLCP, "REFser on closed window (%d)", id);
1216
1217
1218 if (GetWindowState (w -> w_fd, &w -> w_ws) == NOTOK)
1219 adios ("failed", "GetWindowState");
1220
1221 GetPermanentClipping (w -> w_fd, &cx, &cy, &cw, &ch);
1222 SetPermanentClipping (w -> w_fd, wx, wy, ww, wh);
1223 Redisplay (w, 1);
1224 SetPermanentClipping (w -> w_fd, cx, cy, cw, ch);
1225 }
1226
1227 /* \f */
1228
1229 static Redisplay (w, doeb)
1230 register WINDOW *w;
1231 int doeb;
1232 {
1233 register int y;
1234 short sx;
1235 register struct line *lp;
1236
1237 if (w -> w_fd == NOTOK)
1238 return;
1239
1240 sx = w -> w_eb ? (EWIDTH + ESLOP) : 0;
1241 w -> w_height = w -> w_ws.height / w -> w_cheight;
1242 if (w -> w_height < 1)
1243 w -> w_height = 1;
1244
1245 w -> w_width = (w -> w_ws.width - (w -> w_eb ? (EWIDTH + ESLOP) : 0))
1246 / w -> w_cwidth;
1247 if (w -> w_width < 1)
1248 w -> w_width = 1;
1249
1250 SetPosition (w -> w_fd, sx, 0);
1251 SetColor (w -> w_fd, VT_White);
1252 PaintRectangleInterior (w -> w_fd, w -> w_ws.width, w -> w_ws.height);
1253
1254 if (w -> w_head) {
1255 SetColor (w -> w_fd, VT_Black);
1256 for (lp = w -> w_top, y = 0;
1257 lp && y < w -> w_height;
1258 w -> w_bottom = lp, lp = lp -> l_next, y++) {
1259 SetPosition (w -> w_fd, sx, y * w -> w_cheight + w -> w_cbase);
1260 PaintString (w -> w_fd, VT_STREND, lp -> l_buf);
1261 }
1262 }
1263
1264 if (w -> w_eb) {
1265 if ((y = EB_LOC (w)) != w -> w_ebloc)
1266 MoveElevator (w -> w_eb, w -> w_ebloc = y);
1267 if ((y = EB_SIZE (w)) != w -> w_ebsize)
1268 SizeElevator (w -> w_eb, w -> w_ebsize = y);
1269 if (doeb)
1270 RefreshElevatorBar (w -> w_eb);
1271 }
1272
1273 Flush (w -> w_fd);
1274 }
1275
1276 /* \f */
1277
1278 static int EB_SIZE (w)
1279 register WINDOW *w;
1280 {
1281 register int i;
1282
1283 if (w -> w_head == NULL)
1284 return 0;
1285
1286 if ((i = w -> w_tail -> l_no - w -> w_head -> l_no) <= 0)
1287 return EB_MAX;
1288
1289 return (((w -> w_bottom -> l_no - w -> w_top -> l_no) * EB_MAX) / i);
1290 }
1291
1292
1293 static int EB_LOC (w)
1294 register WINDOW *w;
1295 {
1296 register int i;
1297
1298 if (w -> w_head == NULL)
1299 return 0;
1300
1301 if ((i = w -> w_tail -> l_no - w -> w_head -> l_no) <= 0)
1302 return EB_MAX;
1303
1304 return (((w -> w_top -> l_no - w -> w_head -> l_no) * EB_MAX) / i);
1305 }
1306
1307 /* \f SIGNALS */
1308
1309 static SIGinit () {
1310 foreground ();
1311 if (ioctl (fileno (stdin), TIOCGETP, (char *) &sg) == NOTOK)
1312 adios ("failed", "ioctl TIOCGETP");
1313 if (ioctl (fileno (stdin), TIOCGETC, (char *) &tc) == NOTOK)
1314 adios ("failed", "ioctl TIOCGETC");
1315 if (ioctl (fileno (stdin), TIOCGLTC, (char *) &ltc) == NOTOK)
1316 adios ("failed", "ioctl TIOCGLTC");
1317 sideground ();
1318
1319 (void) signal (SIGHUP, SIGser);
1320 (void) signal (SIGINT, SIGser);
1321 (void) signal (SIGQUIT, SIGser);
1322 }
1323
1324 /* \f */
1325
1326 static foreground () {
1327 #ifdef TIOCGPGRP
1328 int pgrp,
1329 tpgrp;
1330 TYPESIG (*tstat) ();
1331
1332 if ((pgrp = getpgrp (0)) == NOTOK)
1333 adios ("process group", "unable to determine");
1334 for (;;) {
1335 if (ioctl (fileno (stdin), TIOCGPGRP, (char *) &tpgrp) == NOTOK)
1336 adios ("tty's process group", "unable to determine");
1337 if (pgrp == tpgrp)
1338 break;
1339
1340 tstat = signal (SIGTTIN, SIG_DFL);
1341 (void) kill (0, SIGTTIN);
1342 (void) signal (SIGTTIN, tstat);
1343 }
1344
1345 (void) signal (SIGTTIN, SIG_IGN);
1346 (void) signal (SIGTTOU, SIG_IGN);
1347 (void) signal (SIGTSTP, SIG_IGN);
1348 #endif TIOCGPGRP
1349 }
1350
1351
1352 static sideground () {
1353 #ifdef TIOCGPGRP
1354 (void) signal (SIGTTIN, SIG_DFL);
1355 (void) signal (SIGTTOU, SIG_DFL);
1356 (void) signal (SIGTSTP, SIG_DFL);
1357 #endif TIOCGPGRP
1358 }
1359
1360 /* \f */
1361
1362 /* ARGSUSED */
1363
1364 static int ALRMser (sig)
1365 int sig;
1366 {
1367 longjmp (PEERctx, DONE);
1368 }
1369
1370
1371 #ifdef BSD42
1372 /* ARGSUSED */
1373 #endif BSD42
1374
1375 static int PIPEser (sig)
1376 int sig;
1377 {
1378 #ifndef BSD42
1379 (void) signal (sig, SIG_IGN);
1380 #endif BSD42
1381
1382 adios (NULLCP, "lost peer");
1383 }
1384
1385
1386 #ifdef BSD42
1387 /* ARGSUSED */
1388 #endif BSD42
1389
1390 static int SIGser (sig)
1391 int sig;
1392 {
1393 #ifndef BSD42
1394 (void) signal (sig, SIG_IGN);
1395 #endif BSD42
1396
1397 done (1);
1398 }
1399
1400 /* \f MISCELLANY */
1401
1402 void done (status)
1403 int status;
1404 {
1405 if (dfd != NOTOK)
1406 RemoveStatus (dfd);
1407
1408 (void) pFIN ();
1409
1410 exit (status);
1411 }
1412
1413 /* \f */
1414
1415 /* VARARGS2 */
1416
1417 static void adorn (what, fmt, a, b, c, d, e, f)
1418 char *what,
1419 *fmt,
1420 *a,
1421 *b,
1422 *c,
1423 *d,
1424 *e,
1425 *f;
1426 {
1427 char *cp = invo_name;
1428
1429 invo_name = NULL;
1430 advise (what, fmt, a, b, c, d, e, f);
1431 invo_name = cp;
1432 }
1433
1434 /* \f */
1435
1436 /* VARARGS3 */
1437
1438 void advertise (what, tail, fmt, a, b, c, d, e, f)
1439 char *what,
1440 *tail,
1441 *fmt,
1442 *a,
1443 *b,
1444 *c,
1445 *d,
1446 *e,
1447 *f;
1448 {
1449 int eindex = errno;
1450 char buffer[BUFSIZ],
1451 err[BUFSIZ];
1452 struct iovec iob[20];
1453 register struct iovec *iov = iob;
1454
1455 (void) fflush (stdout);
1456
1457 (void) fflush (stderr);
1458
1459 if (invo_name) {
1460 iov -> iov_len = strlen (iov -> iov_base = invo_name);
1461 iov++;
1462 iov -> iov_len = strlen (iov -> iov_base = ": ");
1463 iov++;
1464 }
1465
1466 (void) sprintf (buffer, fmt, a, b, c, d, e, f);
1467 iov -> iov_len = strlen (iov -> iov_base = buffer);
1468 iov++;
1469 if (what) {
1470 if (*what) {
1471 iov -> iov_len = strlen (iov -> iov_base = " ");
1472 iov++;
1473 iov -> iov_len = strlen (iov -> iov_base = what);
1474 iov++;
1475 iov -> iov_len = strlen (iov -> iov_base = ": ");
1476 iov++;
1477 }
1478 if (eindex > 0 && eindex < sys_nerr)
1479 iov -> iov_len = strlen (iov -> iov_base = sys_errlist[eindex]);
1480 else {
1481 (void) sprintf (err, "Error %d", eindex);
1482 iov -> iov_len = strlen (iov -> iov_base = err);
1483 }
1484 iov++;
1485 }
1486 if (tail && *tail) {
1487 iov -> iov_len = strlen (iov -> iov_base = ", ");
1488 iov++;
1489 iov -> iov_len = strlen (iov -> iov_base = tail);
1490 iov++;
1491 }
1492 iov -> iov_len = strlen (iov -> iov_base = "\n");
1493 iov++;
1494
1495 if (dfd != NOTOK)
1496 (void) DisplayVector (iob, iov - iob);
1497 else
1498 (void) writev (fileno (stderr), iob, iov - iob);
1499 }
1500
1501 /* \f */
1502
1503 static DisplayVector (iov, n)
1504 register struct iovec *iov;
1505 register int n;
1506 {
1507 register int i;
1508 register char *cp;
1509 char buffer[BUFSIZ];
1510
1511 for (i = 0, cp = NULL; i < n; i++, iov++) {
1512 (void) sprintf (buffer, "%*.*s", iov -> iov_len, iov -> iov_len,
1513 iov -> iov_base);
1514 cp = add (buffer, cp);
1515 }
1516
1517 DisplayStatus (dfd, cp);
1518
1519 free (cp);
1520
1521 sleep (PAUSE);
1522
1523 RemoveStatus (dfd);
1524 }
1525 @
1526
1527
1528 1.4
1529 log
1530 @LOCALE
1531 @
1532 text
1533 @d3 1
1534 a3 1
1535 static char ident[] = "@@(#)$Id: wmh.c,v 1.3 1990/04/05 15:03:31 sources Exp jromine $";
1536 d147 1
1537 d150 1
1538 @
1539
1540
1541 1.3
1542 log
1543 @add ID
1544 @
1545 text
1546 @d3 1
1547 a3 1
1548 static char ident[] = "@@(#)$Id:$";
1549 d28 3
1550 d169 3
1551 @
1552
1553
1554 1.2
1555 log
1556 @TYPESIG fix
1557 @
1558 text
1559 @d2 3
1560 @
1561
1562
1563 1.1
1564 log
1565 @Initial revision
1566 @
1567 text
1568 @d409 1
1569 a409 1
1570 int (*hstat) (), (*istat) (), (*qstat) (), (*tstat) ();
1571 d1277 1
1572 a1277 1
1573 int (*tstat) ();
1574 @