📄 screen.c
字号:
xscreenchan = BGR24; break; case XRGB32: xscreenchan = XBGR32; break; default: panic("don't know how to byteswap channel %s", chantostr(buf, xscreenchan)); break; } } } else if(xvis->class == TrueColor || xvis->class == DirectColor) { } else if(xvis->class == PseudoColor) { if(xtblbit == 0){ xcmap = XCreateColormap(xdisplay, w, xvis, AllocAll); XStoreColors(xdisplay, xcmap, map, 256); for(i = 0; i < 256; i++) { plan9tox11[i] = i; x11toplan9[i] = i; } } else { for(i = 0; i < 128; i++) { c = map7[i]; if(!XAllocColor(xdisplay, xcmap, &c)) { iprint("drawterm: can't alloc colors in default map, don't use -7\n"); exit(0); } plan9tox11[map7to8[i][0]] = c.pixel; plan9tox11[map7to8[i][1]] = c.pixel; x11toplan9[c.pixel] = map7to8[i][0]; } } } else panic("drawterm: unsupported visual class %d\n", xvis->class);}static voidxdestroy(XEvent *e){ XDestroyWindowEvent *xe; if(e->type != DestroyNotify) return; xe = (XDestroyWindowEvent*)e; if(xe->window == xdrawable) exit(0);}static voidxmapping(XEvent *e){ XMappingEvent *xe; if(e->type != MappingNotify) return; xe = (XMappingEvent*)e; USED(xe);}/* * Disable generation of GraphicsExpose/NoExpose events in the GC. */static GCcreategc(Drawable d){ XGCValues gcv; gcv.function = GXcopy; gcv.graphics_exposures = False; return XCreateGC(xdisplay, d, GCFunction|GCGraphicsExposures, &gcv);}static voidxexpose(XEvent *e){ IRectangle r; XExposeEvent *xe; if(e->type != Expose) return; xe = (XExposeEvent*)e; r.min.x = xe->x; r.min.y = xe->y; r.max.x = xe->x + xe->width; r.max.y = xe->y + xe->height; drawflushr(r);}static voidxkeyboard(XEvent *e){ KeySym k; /* * I tried using XtGetActionKeysym, but it didn't seem to * do case conversion properly * (at least, with Xterminal servers and R4 intrinsics) */ if(e->xany.type != KeyPress) return; XLookupString((XKeyEvent*)e, NULL, 0, &k, NULL); if(k == XK_Multi_key || k == NoSymbol) return; if(k&0xFF00){ switch(k){ case XK_BackSpace: case XK_Tab: case XK_Escape: case XK_Delete: case XK_KP_0: case XK_KP_1: case XK_KP_2: case XK_KP_3: case XK_KP_4: case XK_KP_5: case XK_KP_6: case XK_KP_7: case XK_KP_8: case XK_KP_9: case XK_KP_Divide: case XK_KP_Multiply: case XK_KP_Subtract: case XK_KP_Add: case XK_KP_Decimal: k &= 0x7F; break; case XK_Linefeed: k = '\r'; break; case XK_KP_Space: k = ' '; break; case XK_Home: case XK_KP_Home: k = Khome; break; case XK_Left: case XK_KP_Left: k = Kleft; break; case XK_Up: case XK_KP_Up: k = Kup; break; case XK_Down: case XK_KP_Down: k = Kdown; break; case XK_Right: case XK_KP_Right: k = Kright; break; case XK_Page_Down: case XK_KP_Page_Down: k = Kpgdown; break; case XK_End: case XK_KP_End: k = Kend; break; case XK_Page_Up: case XK_KP_Page_Up: k = Kpgup; break; case XK_Insert: case XK_KP_Insert: k = Kins; break; case XK_KP_Enter: case XK_Return: k = '\n'; break; case XK_Alt_L: case XK_Alt_R: k = Kalt; break; case XK_Shift_L: case XK_Shift_R: case XK_Control_L: case XK_Control_R: case XK_Caps_Lock: case XK_Shift_Lock: case XK_Meta_L: case XK_Meta_R: case XK_Super_L: case XK_Super_R: case XK_Hyper_L: case XK_Hyper_R: return; default: /* not ISO-1 or tty control */ if(k>0xff){ k = keysym2ucs(k); /* supplied by X */ if(k == -1) return; } break; } } /* Compensate for servers that call a minus a hyphen */ if(k == XK_hyphen) k = XK_minus; /* Do control mapping ourselves if translator doesn't */ if(e->xkey.state&ControlMask) k &= 0x9f; if(k == NoSymbol) { return; } kbdputc(kbdq, k);}static voidxmouse(XEvent *e){ Mousestate ms; int i, s; XButtonEvent *be; XMotionEvent *me; if(putsnarf != assertsnarf){ assertsnarf = putsnarf; XSetSelectionOwner(xkmcon, XA_PRIMARY, xdrawable, CurrentTime); if(clipboard != None) XSetSelectionOwner(xkmcon, clipboard, xdrawable, CurrentTime); XFlush(xkmcon); } switch(e->type){ case ButtonPress: be = (XButtonEvent *)e; /* * Fake message, just sent to make us announce snarf. * Apparently state and button are 16 and 8 bits on * the wire, since they are truncated by the time they * get to us. */ if(be->send_event && (~be->state&0xFFFF)==0 && (~be->button&0xFF)==0) return; ms.xy.x = be->x; ms.xy.y = be->y; s = be->state; ms.msec = be->time; switch(be->button){ case 1: s |= Button1Mask; break; case 2: s |= Button2Mask; break; case 3: s |= Button3Mask; break; case 4: s |= Button4Mask; break; case 5: s |= Button5Mask; break; } break; case ButtonRelease: be = (XButtonEvent *)e; ms.xy.x = be->x; ms.xy.y = be->y; ms.msec = be->time; s = be->state; switch(be->button){ case 1: s &= ~Button1Mask; break; case 2: s &= ~Button2Mask; break; case 3: s &= ~Button3Mask; break; case 4: s &= ~Button4Mask; break; case 5: s &= ~Button5Mask; break; } break; case MotionNotify: me = (XMotionEvent *)e; s = me->state; ms.xy.x = me->x; ms.xy.y = me->y; ms.msec = me->time; break; default: return; } ms.buttons = 0; if(s & Button1Mask) ms.buttons |= 1; if(s & Button2Mask) ms.buttons |= 2; if(s & Button3Mask) ms.buttons |= 4; if(s & Button4Mask) ms.buttons |= 8; if(s & Button5Mask) ms.buttons |= 16; lock(&mouse.lk); i = mouse.wi; if(mousequeue) { if(i == mouse.ri || mouse.lastb != ms.buttons || mouse.trans) { mouse.wi = (i+1)%Mousequeue; if(mouse.wi == mouse.ri) mouse.ri = (mouse.ri+1)%Mousequeue; mouse.trans = mouse.lastb != ms.buttons; } else { i = (i-1+Mousequeue)%Mousequeue; } } else { mouse.wi = (i+1)%Mousequeue; mouse.ri = i; } mouse.queue[i] = ms; mouse.lastb = ms.buttons; unlock(&mouse.lk); wakeup(&mouse.r);}voidgetcolor(ulong i, ulong *r, ulong *g, ulong *b){ ulong v; v = cmap2rgb(i); *r = (v>>16)&0xFF; *g = (v>>8)&0xFF; *b = v&0xFF;}voidsetcolor(ulong i, ulong r, ulong g, ulong b){ /* no-op */}intatlocalconsole(void){ char *p, *q; char buf[128]; p = getenv("DRAWTERM_ATLOCALCONSOLE"); if(p && atoi(p) == 1) return 1; p = getenv("DISPLAY"); if(p == nil) return 0; /* extract host part */ q = strchr(p, ':'); if(q == nil) return 0; *q = 0; if(strcmp(p, "") == 0) return 1; /* try to match against system name (i.e. for ssh) */ if(gethostname(buf, sizeof buf) == 0){ if(strcmp(p, buf) == 0) return 1; if(strncmp(p, buf, strlen(p)) == 0 && buf[strlen(p)]=='.') return 1; } return 0;}/* * Cut and paste. Just couldn't stand to make this simple... */typedef struct Clip Clip;struct Clip{ char buf[SnarfSize]; QLock lk;};Clip clip;#undef long /* sic */#undef ulongstatic char*_xgetsnarf(Display *xd){ uchar *data, *xdata; Atom clipboard, type, prop; unsigned long len, lastlen, dummy; int fmt, i; Window w; qlock(&clip.lk); /* * Have we snarfed recently and the X server hasn't caught up? */ if(putsnarf != assertsnarf) goto mine; /* * Is there a primary selection (highlighted text in an xterm)? */ clipboard = XA_PRIMARY; w = XGetSelectionOwner(xd, XA_PRIMARY); if(w == xdrawable){ mine: data = (uchar*)strdup(clip.buf); goto out; } /* * If not, is there a clipboard selection? */ if(w == None && clipboard != None){ clipboard = clipboard; w = XGetSelectionOwner(xd, clipboard); if(w == xdrawable) goto mine; } /* * If not, give up. */ if(w == None){ data = nil; goto out; } /* * We should be waiting for SelectionNotify here, but it might never * come, and we have no way to time out. Instead, we will clear * local property #1, request our buddy to fill it in for us, and poll * until he's done or we get tired of waiting. * * We should try to go for utf8string instead of XA_STRING, * but that would add to the polling. */ prop = 1; XChangeProperty(xd, xdrawable, prop, XA_STRING, 8, PropModeReplace, (uchar*)"", 0); XConvertSelection(xd, clipboard, XA_STRING, prop, xdrawable, CurrentTime); XFlush(xd); lastlen = 0; for(i=0; i<10 || (lastlen!=0 && i<30); i++){ usleep(100*1000); XGetWindowProperty(xd, xdrawable, prop, 0, 0, 0, AnyPropertyType, &type, &fmt, &dummy, &len, &data); if(lastlen == len && len > 0) break; lastlen = len; } if(i == 10){ data = nil; goto out; } /* get the property */ data = nil; XGetWindowProperty(xd, xdrawable, prop, 0, SnarfSize/sizeof(unsigned long), 0, AnyPropertyType, &type, &fmt, &len, &dummy, &xdata); if((type != XA_STRING && type != utf8string) || len == 0){ if(xdata) XFree(xdata); data = nil; }else{ if(xdata){ data = (uchar*)strdup((char*)xdata); XFree(xdata); }else data = nil; }out: qunlock(&clip.lk); return (char*)data;}static void_xputsnarf(Display *xd, char *data){ XButtonEvent e; if(strlen(data) >= SnarfSize) return; qlock(&clip.lk); strcpy(clip.buf, data); /* leave note for mouse proc to assert selection ownership */ putsnarf++; /* send mouse a fake event so snarf is announced */ memset(&e, 0, sizeof e); e.type = ButtonPress; e.window = xdrawable; e.state = ~0; e.button = ~0; XSendEvent(xd, xdrawable, True, ButtonPressMask, (XEvent*)&e); XFlush(xd); qunlock(&clip.lk);}static voidxselect(XEvent *e, Display *xd){ char *name; XEvent r; XSelectionRequestEvent *xe; Atom a[4]; if(e->xany.type != SelectionRequest) return; memset(&r, 0, sizeof r); xe = (XSelectionRequestEvent*)e;if(0) iprint("xselect target=%d requestor=%d property=%d selection=%d\n", xe->target, xe->requestor, xe->property, xe->selection); r.xselection.property = xe->property; if(xe->target == targets){ a[0] = XA_STRING; a[1] = utf8string; a[2] = text; a[3] = compoundtext; XChangeProperty(xd, xe->requestor, xe->property, xe->target, 8, PropModeReplace, (uchar*)a, sizeof a); }else if(xe->target == XA_STRING || xe->target == utf8string || xe->target == text || xe->target == compoundtext){ /* if the target is STRING we're supposed to reply with Latin1 XXX */ qlock(&clip.lk); XChangeProperty(xd, xe->requestor, xe->property, xe->target, 8, PropModeReplace, (uchar*)clip.buf, strlen(clip.buf)); qunlock(&clip.lk); }else{ iprint("get %d\n", xe->target); name = XGetAtomName(xd, xe->target); if(name == nil) iprint("XGetAtomName failed\n"); else if(strcmp(name, "TIMESTAMP") != 0) iprint("%s: cannot handle selection request for '%s' (%d)\n", argv0, name, (int)xe->target); r.xselection.property = None; } r.xselection.display = xe->display; /* r.xselection.property filled above */ r.xselection.target = xe->target; r.xselection.type = SelectionNotify; r.xselection.requestor = xe->requestor; r.xselection.time = xe->time; r.xselection.send_event = True; r.xselection.selection = xe->selection; XSendEvent(xd, xe->requestor, False, 0, &r); XFlush(xd);}char*clipread(void){ return _xgetsnarf(xsnarfcon);}intclipwrite(char *buf){ _xputsnarf(xsnarfcon, buf); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -