📄 wmh.c
字号:
/* wmh.c - window front-end to mh */#ifndef lintstatic char ident[] = "@(#)$Id: wmh.c,v 1.2 90/11/25 19:06:20 sharpe Exp $";#endif lint/* TODO: Pass signals to client during execution Figure out a way for the user to say how big the Scan/Display windows should be, and where all the windows should be. */#include <stdio.h>#include "../h/mh.h"#include "../h/vmhsbr.h"#include <ctype.h>#include <errno.h>#include <setjmp.h>#include <signal.h>#ifndef sigmask#define sigmask(s) (1 << ((s) - 1))#endif not sigmask#include <sys/types.h>#include <sys/uio.h>#include <vt.h>#include <bitmap.h>#include <tools.h>#define ALARM ((unsigned int) 10)#define PAUSE ((unsigned int) 2)#define abs(a) ((a) > 0 ? (a) : -(a))#define SZ(a) (sizeof a / sizeof a[0])/* */static struct swit switches[] = {#define PRMPTSW 0 "prompt string", 6,#define PROGSW 1 "vmhproc program", 7,#define NPROGSW 2 "novmhproc", 9,#define HELPSW 3 "help", 4, NULL, NULL};/* */ /* PEERS */static int PEERpid = NOTOK;static jmp_buf PEERctx; /* WINDOWS */static int dfd = NOTOK;static int twd = NOTOK;static char *myprompt = "(%s) ";struct line { int l_no; char *l_buf; struct line *l_prev; struct line *l_next;};typedef struct { int w_fd; int w_flags;#define W_NULL 0x00#define W_CMND 0x01#define W_FAKE 0x02#define W_EBAR 0x04 int w_wd; struct wstate w_ws; char *w_eb; int w_ebloc; int w_ebsize; int w_cbase; int w_height; int w_cheight; int w_width; int w_cwidth; struct line *w_head; struct line *w_top; struct line *w_bottom; struct line *w_tail; char w_buffer[BUFSIZ]; int w_bufpos;} WINDOW;static WINDOW *Scan;static WINDOW *Status;static WINDOW *Display;static WINDOW *Command;#define NWIN 4static int numwins;WINDOW *windows[NWIN + 1];WINDOW *WINnew (); /* SIGNALS */#define ERASE sg.sg_erase#define KILL sg.sg_killstatic struct sgttyb sg;#define EOFC tc.t_eofc#define INTR tc.t_intrcstatic struct tchars tc;#define WERASC ltc.t_werascstatic struct ltchars ltc;int ALRMser (), PIPEser (), SIGser ();int ADJser (), REFser (); /* MISCELLANY */extern int errno;extern int sys_nerr;extern char *sys_errlist[];void adorn ();/* *//* ARGSUSED */main (argc, argv)int argc;char *argv[];{ int vecp = 1, nprog = 0; char *cp, buffer[BUFSIZ], **ap, **argp, *arguments[MAXARGS], *vec[MAXARGS]; invo_name = r1bindex (argv[0], '/'); if ((cp = m_find (invo_name)) != NULL) { ap = brkstring (cp = getcpy (cp), " ", "\n"); ap = copyip (ap, arguments); } else ap = arguments; (void) copyip (argv + 1, ap); argp = arguments;/* */ while (cp = *argp++) if (*cp == '-') switch (smatch (++cp, switches)) { case AMBIGSW: ambigsw (cp, switches); done (1); case UNKWNSW: vec[vecp++] = --cp; continue; case HELPSW: (void) sprintf (buffer, "%s [switches for vmhproc]", invo_name); help (buffer, switches); done (1); case PRMPTSW: if (!(myprompt = *argp++) || *myprompt == '-') adios (NULLCP, "missing argument to %s", argp[-2]); continue; case PROGSW: if (!(vmhproc = *argp++) || *vmhproc == '-') adios (NULLCP, "missing argument to %s", argp[-2]); continue; case NPROGSW: nprog++; continue; } else vec[vecp++] = cp;/* */ (void) SIGinit (); if (WINinit (nprog) == NOTOK) { vec[vecp] = NULL; vec[0] = r1bindex (vmhproc, '/'); execvp (vmhproc, vec); adios (vmhproc, "unable to exec"); } (void) PEERinit (vecp, vec); vmh (); done (0);}/* */static vmh () { char buffer[BUFSIZ], prompt[BUFSIZ]; for (;;) { (void) pLOOP (RC_QRY, NULLCP); (void) sprintf (prompt, myprompt, invo_name); switch (WINgetstr (Command, prompt, buffer)) { case NOTOK: break; case OK: done (0); /* NOTREACHED */ default: if (*buffer) (void) pLOOP (RC_CMD, buffer); break; } }}/* PEERS */static int PEERinit (vecp, vec)int vecp;char *vec[];{ int pfd0[2], pfd1[2]; char buf1[BUFSIZ], buf2[BUFSIZ]; register WINDOW **w; (void) signal (SIGPIPE, PIPEser); if (pipe (pfd0) == NOTOK || pipe (pfd1) == NOTOK) adios ("pipe", "unable to"); switch (PEERpid = vfork ()) { case NOTOK: adios ("vfork", "unable to");/* NOTREACHED */ case OK: for (w = windows; *w; w++) if ((*w) -> w_fd != NOTOK) (void) close ((*w) -> w_fd); (void) close (pfd0[0]); (void) close (pfd1[1]); vec[vecp++] = "-vmhread"; (void) sprintf (buf1, "%d", pfd1[0]); vec[vecp++] = buf1; vec[vecp++] = "-vmhwrite"; (void) sprintf (buf2, "%d", pfd0[1]); vec[vecp++] = buf2; vec[vecp] = NULL; (void) signal (SIGINT, SIG_DFL); (void) signal (SIGQUIT, SIG_DFL); (void) signal (SIGTERM, SIG_DFL); vec[0] = r1bindex (vmhproc, '/'); execvp (vmhproc, vec); perror (vmhproc); _exit (-1); /* NOTREACHED */ default: (void) close (pfd0[1]); (void) close (pfd1[0]); (void) rcinit (pfd0[0], pfd1[1]); return pINI (); }}/* */static int pINI () { register char *bp; char buffer[BUFSIZ]; struct record rcs; register struct record *rc = &rcs; register WINDOW **w; initrc (rc); bp = buffer; (void) sprintf (bp, "%d %d", RC_VRSN, numwins); bp += strlen (bp); for (w = windows; *w; w++) { (void) sprintf (bp, " %d", (*w) -> w_height); bp += strlen (bp); } switch (str2rc (RC_INI, buffer, rc)) { case RC_ACK: return OK; case RC_ERR: if (rc -> rc_len) adios (NULLCP, "%s", rc -> rc_data); else adios (NULLCP, "pINI peer error"); case RC_XXX: adios (NULLCP, "%s", rc -> rc_data); default: adios (NULLCP, "pINI protocol screw-up"); }/* NOTREACHED */}/* */static int pLOOP (code, str)char code, *str;{ int i; struct record rcs; register struct record *rc = &rcs; WINDOW *w; initrc (rc); (void) str2peer (code, str); for (;;) switch (peer2rc (rc)) { case RC_TTY: if (pTTY () == NOTOK) return NOTOK; break; case RC_WIN: if (sscanf (rc -> rc_data, "%d", &i) != 1 || i <= 0 || i > numwins) { (void) fmt2peer (RC_ERR, "no such window \"%s\"", rc -> rc_data); return NOTOK; } if ((w = windows[i - 1]) -> w_flags & W_CMND) { (void) fmt2peer (RC_ERR, "not a display window \"%s\"", rc -> rc_data); return NOTOK; } if (pWIN (w) == NOTOK) return NOTOK; break; case RC_EOF: return OK; case RC_ERR: if (rc -> rc_len) adorn (NULLCP, "%s", rc -> rc_data); else adorn (NULLCP, "pLOOP(%s) peer error", code == RC_QRY ? "QRY" : "CMD"); return NOTOK; case RC_FIN: if (rc -> rc_len) adorn (NULLCP, "%s", rc -> rc_data); (void) rcdone (); i = pidwait (PEERpid, OK); PEERpid = NOTOK; done (i); case RC_XXX: adios (NULLCP, "%s", rc -> rc_data); default: adios (NULLCP, "pLOOP(%s) protocol screw-up", code == RC_QRY ? "QRY" : "CMD"); }}/* */static int pTTY () { TYPESIG (*hstat) (), (*istat) (), (*qstat) (), (*tstat) (); struct record rcs; register struct record *rc = &rcs; initrc (rc); if (ChangeWindowDepth (dfd, twd, 0) == NOTOK) adios ("failed", "ChangeWindowDepth"); hstat = signal (SIGHUP, SIG_IGN); istat = signal (SIGINT, SIG_IGN); qstat = signal (SIGQUIT, SIG_IGN); tstat = signal (SIGTERM, SIG_IGN); (void) rc2rc (RC_ACK, 0, NULLCP, rc); (void) signal (SIGHUP, hstat); (void) signal (SIGINT, istat); (void) signal (SIGQUIT, qstat); (void) signal (SIGTERM, tstat); switch (rc -> rc_type) { case RC_EOF: (void) rc2peer (RC_ACK, 0, NULLCP); return OK; case RC_ERR: if (rc -> rc_len) adorn (NULLCP, "%s", rc -> rc_data); else adorn (NULLCP, "pTTY peer error"); return NOTOK; case RC_XXX: adios (NULLCP, "%s", rc -> rc_data); default: adios (NULLCP, "pTTY protocol screw-up"); }/* NOTREACHED */}/* */static int pWIN (w)register WINDOW *w;{ int i; if ((i = pWINaux (w)) == OK) WINless (w); return i;}/* */static int pWINaux (w)register WINDOW *w;{ register int n; register char *bp; register struct line *lp, *mp; struct record rcs; register struct record *rc = &rcs; initrc (rc); for (lp = w -> w_head; lp; lp = mp) { mp = lp -> l_next; free (lp -> l_buf); free ((char *) lp); } w -> w_head = w -> w_top = w -> w_bottom = w -> w_tail = NULL; w -> w_bufpos = 0; for (;;) switch (rc2rc (RC_ACK, 0, NULLCP, rc)) { case RC_DATA: for (bp = rc -> rc_data, n = rc -> rc_len; n-- > 0; ) (void) WINputc (w, *bp++); break; case RC_EOF: (void) rc2peer (RC_ACK, 0, NULLCP); if (w -> w_bufpos) (void) WINputc (w, '\n'); return OK; case RC_ERR: if (rc -> rc_len) adorn (NULLCP, "%s", rc -> rc_data); else adorn (NULLCP, "pWIN peer error"); return NOTOK; case RC_XXX: adios (NULLCP, "%s", rc -> rc_data); default: adios (NULLCP, "pWIN protocol screw-up"); }/* NOTREACHED */}/* */static int pFIN () { int status; if (PEERpid <= OK) return OK; (void) rc2peer (RC_FIN, 0, NULLCP); (void) rcdone (); switch (setjmp (PEERctx)) { case OK: (void) signal (SIGALRM, ALRMser); (void) alarm (ALARM); status = pidwait (PEERpid, OK); (void) alarm (0); break; default: (void) kill (PEERpid, SIGKILL); status = NOTOK; break; } PEERpid = NOTOK; return status;}/* WINDOWS *//* should dynamically determine all this stuff from gconfig... */#define MyX 20 /* anchored hpos */#define MyY 40 /* .. vpos */#define MyW 800 /* .. width */#define MyH 500 /* .. height */#define MyS 30 /* .. height for Status, about one line */#define MySlop 45 /* slop */#define EWIDTH 25 /* Width of vertical EBAR */#define ESLOP 5 /* .. slop */static int WINinit (nprog) { short wx, wy, wh, sy; struct gconfig gc; if (GetGraphicsConfig (fileno (stderr), &gc) == NOTOK) if (nprog) return NOTOK; else adios (NULLCP, "not a window"); if ((dfd = open ("/dev/ttyw0", 2)) == NOTOK) adios ("/dev/ttyw0", "unable to open"); if ((twd = GetTopWindow (dfd)) == NOTOK) adios ("failed", "GetTopWindow"); (void) BlockRefreshAdjust (1); numwins = 0; wx = gc.w - (MyX + MyW + EWIDTH + ESLOP); Scan = WINnew (wx, wy = MyY, MyW, wh = MyH * 2 / 3, "Scan", W_EBAR); wy += wh + MySlop; Status = WINnew (wx, sy = wy, MyW, wh = MyS, "Status", W_FAKE); wy += wh + MySlop; Display = WINnew (wx, wy, MyW, MyH, "Display", W_EBAR); Command = WINnew (wx, sy, MyW, MyS, invo_name, W_CMND); windows[numwins] = NULL; return OK;}/* */WINDOW *WINnew (wx, wy, ww, wh, name, flags)short wx, wy, ww, wh;char *name;int flags;{ register WINDOW *w; if ((w = (WINDOW *) calloc (1, sizeof *w)) == NULL) adios (NULLCP, "unable to allocate window"); if ((w -> w_flags = flags) & W_FAKE) { w -> w_fd = NOTOK; w -> w_height = 1; goto out; } if (w -> w_flags & W_EBAR) ww += EWIDTH + ESLOP; else wx += EWIDTH + ESLOP; if ((w -> w_fd = OpenWindow (wx, wy, ww, wh, name)) == NOTOK) adios ("failed", "OpenWindow"); if ((w -> w_wd = GetTopWindow (dfd)) == NOTOK) adios ("failed", "GetTopWindow"); if (GetWindowState (w -> w_fd, &w -> w_ws) == NOTOK) adios ("failed", "GetWindowState"); if (SetLineDisc (w -> w_fd, TWSDISC) == NOTOK) adios ("failed", "SetLineDisc"); SetBuf (w -> w_fd, 1024); (void) SetAdjust (w -> w_fd, numwins, ADJser); (void) SetRefresh (w -> w_fd, numwins, REFser); SetAddressing (w -> w_fd, VT_ABSOLUTE); if (w -> w_flags & W_EBAR) { w -> w_eb = CreateElevatorBar (w -> w_fd, 0, 0, EWIDTH, w -> w_ws.height, VT_Gray50, 1, EB_VERTICAL, EB_ARROWS, w -> w_ebloc = 0, w -> w_ebsize = EB_MAX, VT_White); if (w -> w_eb == NULL) adios (NULLCP, "CreateElevatorBar failed"); RefreshElevatorBar (w -> w_eb); } if ((w -> w_cbase = CharacterBaseline (w -> w_ws.font)) <= 0) w -> w_cbase = 14; if ((w -> w_cheight = CharacterHeight (w -> w_ws.font)) <= 0) w -> w_cheight = 20; w -> w_height = w -> w_ws.height / w -> w_cheight; if (w -> w_height < 1) w -> w_height = 1; /* 1 em */ if ((w -> w_cwidth = CharacterWidth (w -> w_ws.font, 'm')) <= 0) w -> w_cwidth = 10; w -> w_width = (w -> w_ws.width - (w -> w_eb ? (EWIDTH + ESLOP) : 0)) / w -> w_cwidth; if (w -> w_width < 1) w -> w_width = 1;out: ; windows[numwins++] = w; return w;}/* */static int WINgetstr (w, prompt, buffer)register WINDOW *w;char *prompt, *buffer;{ register int c; register char *bp, *ip; char image[BUFSIZ]; struct vtseq vts; register struct vtseq *vt = &vts; if (w -> w_eb != NULL) adios (NULLCP, "internal error--elevator bar found"); if (w -> w_head == NULL && (w -> w_head = (struct line *) calloc (1, sizeof *w -> w_head)) == NULL) adios (NULLCP, "unable to allocate line storage"); w -> w_head -> l_buf = image; w -> w_top = w -> w_bottom = w -> w_tail = w -> w_head; if (ChangeWindowDepth (dfd, w -> w_wd, 0) == NOTOK) adios ("failed", "ChangeWindowDepth"); (void) strcpy (image, prompt); bp = ip = image + strlen (image); Redisplay (w, 0); for (;;) switch (getvtseq (w -> w_fd, vt)) { case VT_HARDKEY: DisplayStatus (w -> w_fd, "no hardkeys, please"); break; case VT_ASCII: switch (c = toascii (vt -> u.ascii)) { case '\f': /* refresh? */ break; case '\r': case '\n': (void) strcpy (buffer, ip); return DONE; default: if (c == INTR) { adorn (NULLCP, "Interrupt"); return NOTOK; } if (c == EOFC) { if (bp <= ip) return OK; break; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -