📄 wctl.c
字号:
#include <u.h>#include <libc.h>#include <draw.h>#include <thread.h>#include <cursor.h>#include <mouse.h>#include <keyboard.h>#include <frame.h>#include <fcall.h>#include <plumb.h>#include "dat.h"#include "fns.h"#include <ctype.h>char Ebadwr[] = "bad rectangle in wctl request";char Ewalloc[] = "window allocation failed in wctl request";/* >= Top are disallowed if mouse button is pressed */enum{ New, Resize, Move, Scroll, Noscroll, Set, Top, Bottom, Current, Hide, Unhide, Delete,};static char *cmds[] = { [New] = "new", [Resize] = "resize", [Move] = "move", [Scroll] = "scroll", [Noscroll] = "noscroll", [Set] = "set", [Top] = "top", [Bottom] = "bottom", [Current] = "current", [Hide] = "hide", [Unhide] = "unhide", [Delete] = "delete", nil};enum{ Cd, Deltax, Deltay, Hidden, Id, Maxx, Maxy, Minx, Miny, PID, R, Scrolling, Noscrolling,};static char *params[] = { [Cd] = "-cd", [Deltax] = "-dx", [Deltay] = "-dy", [Hidden] = "-hide", [Id] = "-id", [Maxx] = "-maxx", [Maxy] = "-maxy", [Minx] = "-minx", [Miny] = "-miny", [PID] = "-pid", [R] = "-r", [Scrolling] = "-scroll", [Noscrolling] = "-noscroll", nil};/* * Check that newly created window will be of manageable size */intgoodrect(Rectangle r){ if(!eqrect(canonrect(r), r)) return 0; if(Dx(r)<100 || Dy(r)<3*font->height) return 0; /* must have some screen and border visible so we can move it out of the way */ if(Dx(r) >= Dx(screen->r) && Dy(r) >= Dy(screen->r)) return 0; /* reasonable sizes only please */ if(Dx(r) > BIG*Dx(screen->r)) return 0; if(Dy(r) > BIG*Dx(screen->r)) return 0; return 1;}staticintword(char **sp, char *tab[]){ char *s, *t; int i; s = *sp; while(isspace(*s)) s++; t = s; while(*s!='\0' && !isspace(*s)) s++; for(i=0; tab[i]!=nil; i++) if(strncmp(tab[i], t, strlen(tab[i])) == 0){ *sp = s; return i; } return -1;}intset(int sign, int neg, int abs, int pos){ if(sign < 0) return neg; if(sign > 0) return pos; return abs;}Rectanglenewrect(void){ static int i = 0; int minx, miny, dx, dy; dx = min(600, Dx(screen->r) - 2*Borderwidth); dy = min(400, Dy(screen->r) - 2*Borderwidth); minx = 32 + 16*i; miny = 32 + 16*i; i++; i %= 10; return Rect(minx, miny, minx+dx, miny+dy);}voidshift(int *minp, int *maxp, int min, int max){ if(*minp < min){ *maxp += min-*minp; *minp = min; } if(*maxp > max){ *minp += max-*maxp; *maxp = max; }}Rectanglerectonscreen(Rectangle r){ shift(&r.min.x, &r.max.x, screen->r.min.x, screen->r.max.x); shift(&r.min.y, &r.max.y, screen->r.min.y, screen->r.max.y); return r;}/* permit square brackets, in the manner of %R */intriostrtol(char *s, char **t){ int n; while(*s!='\0' && (*s==' ' || *s=='\t' || *s=='[')) s++; if(*s == '[') s++; n = strtol(s, t, 10); if(*t != s) while((*t)[0] == ']') (*t)++; return n;}intparsewctl(char **argp, Rectangle r, Rectangle *rp, int *pidp, int *idp, int *hiddenp, int *scrollingp, char **cdp, char *s, char *err){ int cmd, param, xy, sign; char *t; *pidp = 0; *hiddenp = 0; *scrollingp = scrolling; *cdp = nil; cmd = word(&s, cmds); if(cmd < 0){ strcpy(err, "unrecognized wctl command"); return -1; } if(cmd == New) r = newrect(); strcpy(err, "missing or bad wctl parameter"); while((param = word(&s, params)) >= 0){ switch(param){ /* special cases */ case Hidden: *hiddenp = 1; continue; case Scrolling: *scrollingp = 1; continue; case Noscrolling: *scrollingp = 0; continue; case R: r.min.x = riostrtol(s, &t); if(t == s) return -1; s = t; r.min.y = riostrtol(s, &t); if(t == s) return -1; s = t; r.max.x = riostrtol(s, &t); if(t == s) return -1; s = t; r.max.y = riostrtol(s, &t); if(t == s) return -1; s = t; continue; } while(isspace(*s)) s++; if(param == Cd){ *cdp = s; while(*s && !isspace(*s)) s++; if(*s != '\0') *s++ = '\0'; continue; } sign = 0; if(*s == '-'){ sign = -1; s++; }else if(*s == '+'){ sign = +1; s++; } if(!isdigit(*s)) return -1; xy = riostrtol(s, &s); switch(param){ case -1: strcpy(err, "unrecognized wctl parameter"); return -1; case Minx: r.min.x = set(sign, r.min.x-xy, xy, r.min.x+xy); break; case Miny: r.min.y = set(sign, r.min.y-xy, xy, r.min.y+xy); break; case Maxx: r.max.x = set(sign, r.max.x-xy, xy, r.max.x+xy); break; case Maxy: r.max.y = set(sign, r.max.y-xy, xy, r.max.y+xy); break; case Deltax: r.max.x = set(sign, r.max.x-xy, r.min.x+xy, r.max.x+xy); break; case Deltay: r.max.y = set(sign, r.max.y-xy, r.min.y+xy, r.max.y+xy); break; case Id: if(idp != nil) *idp = xy; break; case PID: if(pidp != nil) *pidp = xy; break; } } *rp = rectonscreen(rectaddpt(r, screen->r.min)); while(isspace(*s)) s++; if(cmd!=New && *s!='\0'){ strcpy(err, "extraneous text in wctl message"); return -1; } if(argp) *argp = s; return cmd;}intwctlnew(Rectangle rect, char *arg, int pid, int hideit, int scrollit, char *dir, char *err){ char **argv; Image *i; if(!goodrect(rect)){ strcpy(err, Ebadwr); return -1; } argv = emalloc(4*sizeof(char*)); argv[0] = "rc"; argv[1] = "-c"; while(isspace(*arg)) arg++; if(*arg == '\0'){ argv[1] = "-i"; argv[2] = nil; }else{ argv[2] = arg; argv[3] = nil; } if(hideit) i = allocimage(display, rect, screen->chan, 0, DWhite); else i = allocwindow(wscreen, rect, Refbackup, DWhite); if(i == nil){ strcpy(err, Ewalloc); return -1; } border(i, rect, Selborder, red, ZP); new(i, hideit, scrollit, pid, dir, "/bin/rc", argv); free(argv); /* when new() returns, argv and args have been copied */ return 1;}intwritewctl(Xfid *x, char *err){ int cnt, cmd, j, id, hideit, scrollit, pid; Image *i; char *arg, *dir; Rectangle rect; Window *w; w = x->f->w; cnt = x->count; x->data[cnt] = '\0'; id = 0; rect = rectsubpt(w->screenr, screen->r.min); cmd = parsewctl(&arg, rect, &rect, &pid, &id, &hideit, &scrollit, &dir, x->data, err); if(cmd < 0) return -1; if(mouse->buttons!=0 && cmd>=Top){ strcpy(err, "action disallowed when mouse active"); return -1; } if(id != 0){ for(j=0; j<nwindow; j++) if(window[j]->id == id) break; if(j == nwindow){ strcpy(err, "no such window id"); return -1; } w = window[j]; if(w->deleted || w->i==nil){ strcpy(err, "window deleted"); return -1; } } switch(cmd){ case New: return wctlnew(rect, arg, pid, hideit, scrollit, dir, err); case Set: if(pid > 0) wsetpid(w, pid, 0); return 1; case Move: rect = Rect(rect.min.x, rect.min.y, rect.min.x+Dx(w->screenr), rect.min.y+Dy(w->screenr)); rect = rectonscreen(rect); /* fall through */ case Resize: if(!goodrect(rect)){ strcpy(err, Ebadwr); return -1; } if(eqrect(rect, w->screenr)) return 1; i = allocwindow(wscreen, rect, Refbackup, DWhite); if(i == nil){ strcpy(err, Ewalloc); return -1; } border(i, rect, Selborder, red, ZP); wsendctlmesg(w, Reshaped, i->r, i); return 1; case Scroll: w->scrolling = 1; wshow(w, w->nr); wsendctlmesg(w, Wakeup, ZR, nil); return 1; case Noscroll: w->scrolling = 0; wsendctlmesg(w, Wakeup, ZR, nil); return 1; case Top: wtopme(w); return 1; case Bottom: wbottomme(w); return 1; case Current: wcurrent(w); return 1; case Hide: switch(whide(w)){ case -1: strcpy(err, "window already hidden"); return -1; case 0: strcpy(err, "hide failed"); return -1; default: break; } return 1; case Unhide: for(j=0; j<nhidden; j++) if(hidden[j] == w) break; if(j == nhidden){ strcpy(err, "window not hidden"); return -1; } if(wunhide(j) == 0){ strcpy(err, "hide failed"); return -1; } return 1; case Delete: wsendctlmesg(w, Deleted, ZR, nil); return 1; } strcpy(err, "invalid wctl message"); return -1;}voidwctlthread(void *v){ char *buf, *arg, *dir; int cmd, id, pid, hideit, scrollit; Rectangle rect; char err[ERRMAX]; Channel *c; c = v; threadsetname("WCTLTHREAD"); for(;;){ buf = recvp(c); cmd = parsewctl(&arg, ZR, &rect, &pid, &id, &hideit, &scrollit, &dir, buf, err); switch(cmd){ case New: wctlnew(rect, arg, pid, hideit, scrollit, dir, err); } free(buf); }}voidwctlproc(void *v){ char *buf; int n, eofs; Channel *c; threadsetname("WCTLPROC"); c = v; eofs = 0; for(;;){ buf = emalloc(messagesize); n = read(wctlfd, buf, messagesize-1); /* room for \0 */ if(n < 0) break; if(n == 0){ if(++eofs > 20) break; continue; } eofs = 0; buf[n] = '\0'; sendp(c, buf); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -