📄 wind.c
字号:
/* * Convert back to physical coordinates */voidwmovemouse(Window *w, Point p){ p.x += w->screenr.min.x-w->i->r.min.x; p.y += w->screenr.min.y-w->i->r.min.y; moveto(mousectl, p);}voidwborder(Window *w, int type){ Image *col; if(w->i == nil) return; if(w->holding){ if(type == Selborder) col = holdcol; else col = paleholdcol; }else{ if(type == Selborder) col = titlecol; else col = lighttitlecol; } border(w->i, w->i->r, Selborder, col, ZP);}Window*wpointto(Point pt){ int i; Window *v, *w; w = nil; for(i=0; i<nwindow; i++){ v = window[i]; if(ptinrect(pt, v->screenr)) if(!v->deleted) if(w==nil || v->topped>w->topped) w = v; } return w;}voidwcurrent(Window *w){ Window *oi; if(wkeyboard!=nil && w==wkeyboard) return; oi = input; input = w; if(oi!=w && oi!=nil) wrepaint(oi); if(w !=nil){ wrepaint(w); wsetcursor(w, 0); } if(w != oi){ if(oi){ oi->wctlready = 1; wsendctlmesg(oi, Wakeup, ZR, nil); } if(w){ w->wctlready = 1; wsendctlmesg(w, Wakeup, ZR, nil); } }}voidwsetcursor(Window *w, int force){ Cursor *p; if(w==nil || /*w!=input || */ w->i==nil || Dx(w->screenr)<=0) p = nil; else if(wpointto(mouse->xy) == w){ p = w->cursorp; if(p==nil && w->holding) p = &whitearrow; }else p = nil; if(!menuing) riosetcursor(p, force && !menuing);}voidriosetcursor(Cursor *p, int force){ if(!force && p==lastcursor) return; setcursor(mousectl, p); lastcursor = p;}Window*wtop(Point pt){ Window *w; w = wpointto(pt); if(w){ if(w->topped == topped) return nil; topwindow(w->i); wcurrent(w); flushimage(display, 1); w->topped = ++topped; } return w;}voidwtopme(Window *w){ if(w!=nil && w->i!=nil && !w->deleted && w->topped!=topped){ topwindow(w->i); flushimage(display, 1); w->topped = ++ topped; }}voidwbottomme(Window *w){ if(w!=nil && w->i!=nil && !w->deleted){ bottomwindow(w->i); flushimage(display, 1); w->topped = - ++topped; }}Window*wlookid(int id){ int i; for(i=0; i<nwindow; i++) if(window[i]->id == id) return window[i]; return nil;}voidwclosewin(Window *w){ Rectangle r; int i; w->deleted = TRUE; if(w == input){ input = nil; wsetcursor(w, 0); } if(w == wkeyboard) wkeyboard = nil; for(i=0; i<nhidden; i++) if(hidden[i] == w){ --nhidden; memmove(hidden+i, hidden+i+1, (nhidden-i)*sizeof(hidden[0])); break; } for(i=0; i<nwindow; i++) if(window[i] == w){ --nwindow; memmove(window+i, window+i+1, (nwindow-i)*sizeof(Window*)); w->deleted = TRUE; r = w->i->r; /* move it off-screen to hide it, in case client is slow in letting it go */ MOVEIT originwindow(w->i, r.min, view->r.max); freeimage(w->i); w->i = nil; return; } error("unknown window in closewin");}voidwsetpid(Window *w, int pid, int dolabel){ char buf[128]; int fd; w->pid = pid; if(dolabel){ sprint(buf, "rc %d", pid); free(w->label); w->label = estrdup(buf); } sprint(buf, "/proc/%d/notepg", pid); fd = open(buf, OWRITE|OCEXEC); if(w->notefd > 0) close(w->notefd); w->notefd = fd;}voidwinshell(void *args){ Window *w; Channel *pidc; void **arg; char *cmd, *dir; char **argv; arg = args; w = arg[0]; pidc = arg[1]; cmd = arg[2]; argv = arg[3]; dir = arg[4]; rfork(RFNAMEG|RFFDG|RFENVG); if(filsysmount(filsys, w->id) < 0){ fprint(2, "mount failed: %r\n"); sendul(pidc, 0); threadexits("mount failed"); } close(0); if(open("/dev/cons", OREAD) < 0){ fprint(2, "can't open /dev/cons: %r\n"); sendul(pidc, 0); threadexits("/dev/cons"); } close(1); if(open("/dev/cons", OWRITE) < 0){ fprint(2, "can't open /dev/cons: %r\n"); sendul(pidc, 0); threadexits("open"); /* BUG? was terminate() */ } if(wclose(w) == 0){ /* remove extra ref hanging from creation */ notify(nil); dup(1, 2); if(dir) chdir(dir); procexec(pidc, cmd, argv); _exits("exec failed"); }}static Rune left1[] = { L'{', L'[', L'(', L'<', L'«', 0 };static Rune right1[] = { L'}', L']', L')', L'>', L'»', 0 };static Rune left2[] = { L'\n', 0 };static Rune left3[] = { L'\'', L'"', L'`', 0 };Rune *left[] = { left1, left2, left3, nil};Rune *right[] = { right1, left2, left3, nil};voidwdoubleclick(Window *w, uint *q0, uint *q1){ int c, i; Rune *r, *l, *p; uint q; for(i=0; left[i]!=nil; i++){ q = *q0; l = left[i]; r = right[i]; /* try matching character to left, looking right */ if(q == 0) c = '\n'; else c = w->r[q-1]; p = strrune(l, c); if(p != nil){ if(wclickmatch(w, c, r[p-l], 1, &q)) *q1 = q-(c!='\n'); return; } /* try matching character to right, looking left */ if(q == w->nr) c = '\n'; else c = w->r[q]; p = strrune(r, c); if(p != nil){ if(wclickmatch(w, c, l[p-r], -1, &q)){ *q1 = *q0+(*q0<w->nr && c=='\n'); *q0 = q; if(c!='\n' || q!=0 || w->r[0]=='\n') (*q0)++; } return; } } /* try filling out word to right */ while(*q1<w->nr && isalnum(w->r[*q1])) (*q1)++; /* try filling out word to left */ while(*q0>0 && isalnum(w->r[*q0-1])) (*q0)--;}intwclickmatch(Window *w, int cl, int cr, int dir, uint *q){ Rune c; int nest; nest = 1; for(;;){ if(dir > 0){ if(*q == w->nr) break; c = w->r[*q]; (*q)++; }else{ if(*q == 0) break; (*q)--; c = w->r[*q]; } if(c == cr){ if(--nest==0) return 1; }else if(c == cl) nest++; } return cl=='\n' && nest==1;}uintwbacknl(Window *w, uint p, uint n){ int i, j; /* look for start of this line if n==0 */ if(n==0 && p>0 && w->r[p-1]!='\n') n = 1; i = n; while(i-->0 && p>0){ --p; /* it's at a newline now; back over it */ if(p == 0) break; /* at 128 chars, call it a line anyway */ for(j=128; --j>0 && p>0; p--) if(w->r[p-1]=='\n') break; } return p;}voidwshow(Window *w, uint q0){ int qe; int nl; uint q; qe = w->org+w->nchars; if(w->org<=q0 && (q0<qe || (q0==qe && qe==w->nr))) wscrdraw(w); else{ nl = 4*w->maxlines/5; q = wbacknl(w, q0, nl); /* avoid going backwards if trying to go forwards - long lines! */ if(!(q0>w->org && q<w->org)) wsetorigin(w, q, TRUE); while(q0 > w->org+w->nchars) wsetorigin(w, w->org+1, FALSE); }}voidwsetorigin(Window *w, uint org, int exact){ int i, a, fixup; Rune *r; uint n; if(org>0 && !exact){ /* org is an estimate of the char posn; find a newline */ /* don't try harder than 256 chars */ for(i=0; i<256 && org<w->nr; i++){ if(w->r[org] == '\n'){ org++; break; } org++; } } a = org-w->org; fixup = 0; if(a>=0 && a<w->nchars){ frdelete(w, 0, a); fixup = 1; /* frdelete can leave end of last line in wrong selection mode; it doesn't know what follows */ }else if(a<0 && -a<w->nchars){ n = w->org - org; r = runemalloc(n); runemove(r, w->r+org, n); frinsert(w, r, r+n, 0); free(r); }else frdelete(w, 0, w->nchars); w->org = org; wfill(w); wscrdraw(w); wsetselect(w, w->q0, w->q1); if(fixup && w->p1 > w->p0) frdrawsel(w, frptofchar(w, w->p1-1), w->p1-1, w->p1, 1);}voidwsetselect(Window *w, uint q0, uint q1){ int p0, p1; /* w->p0 and w->p1 are always right; w->q0 and w->q1 may be off */ w->q0 = q0; w->q1 = q1; /* compute desired p0,p1 from q0,q1 */ p0 = q0-w->org; p1 = q1-w->org; if(p0 < 0) p0 = 0; if(p1 < 0) p1 = 0; if(p0 > w->nchars) p0 = w->nchars; if(p1 > w->nchars) p1 = w->nchars; if(p0==w->p0 && p1==w->p1) return; /* screen disagrees with desired selection */ if(w->p1<=p0 || p1<=w->p0 || p0==p1 || w->p1==w->p0){ /* no overlap or too easy to bother trying */ frdrawsel(w, frptofchar(w, w->p0), w->p0, w->p1, 0); frdrawsel(w, frptofchar(w, p0), p0, p1, 1); goto Return; } /* overlap; avoid unnecessary painting */ if(p0 < w->p0){ /* extend selection backwards */ frdrawsel(w, frptofchar(w, p0), p0, w->p0, 1); }else if(p0 > w->p0){ /* trim first part of selection */ frdrawsel(w, frptofchar(w, w->p0), w->p0, p0, 0); } if(p1 > w->p1){ /* extend selection forwards */ frdrawsel(w, frptofchar(w, w->p1), w->p1, p1, 1); }else if(p1 < w->p1){ /* trim last part of selection */ frdrawsel(w, frptofchar(w, p1), p1, w->p1, 0); } Return: w->p0 = p0; w->p1 = p1;}uintwinsert(Window *w, Rune *r, int n, uint q0){ uint m; if(n == 0) return q0; if(w->nr+n>HiWater && q0>=w->org && q0>=w->qh){ m = min(HiWater-LoWater, min(w->org, w->qh)); w->org -= m; w->qh -= m; if(w->q0 > m) w->q0 -= m; else w->q0 = 0; if(w->q1 > m) w->q1 -= m; else w->q1 = 0; w->nr -= m; runemove(w->r, w->r+m, w->nr); q0 -= m; } if(w->nr+n > w->maxr){ /* * Minimize realloc breakage: * Allocate at least MinWater * Double allocation size each time * But don't go much above HiWater */ m = max(min(2*(w->nr+n), HiWater), w->nr+n)+MinWater; if(m > HiWater) m = max(HiWater+MinWater, w->nr+n); if(m > w->maxr){ w->r = runerealloc(w->r, m); w->maxr = m; } } runemove(w->r+q0+n, w->r+q0, w->nr-q0); runemove(w->r+q0, r, n); w->nr += n; /* if output touches, advance selection, not qh; works best for keyboard and output */ if(q0 <= w->q1) w->q1 += n; if(q0 <= w->q0) w->q0 += n; if(q0 < w->qh) w->qh += n; if(q0 < w->org) w->org += n; else if(q0 <= w->org+w->nchars) frinsert(w, r, r+n, q0-w->org); return q0;}voidwfill(Window *w){ Rune *rp; int i, n, m, nl; if(w->lastlinefull) return; rp = malloc(messagesize); do{ n = w->nr-(w->org+w->nchars); if(n == 0) break; if(n > 2000) /* educated guess at reasonable amount */ n = 2000; runemove(rp, w->r+(w->org+w->nchars), n); /* * it's expensive to frinsert more than we need, so * count newlines. */ nl = w->maxlines-w->nlines; m = 0; for(i=0; i<n; ){ if(rp[i++] == '\n'){ m++; if(m >= nl) break; } } frinsert(w, rp, rp+i, w->nchars); }while(w->lastlinefull == FALSE); free(rp);}char*wcontents(Window *w, int *ip){ return runetobyte(w->r, w->nr, ip);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -