/* * If s is a corner of r, remove s from r, yielding * two rectangles r and rr. R holds the part with * smaller coordinates. */ static int rectcornersubr(Rectangle *r, Rectangle s, Rectangle *rr) { # define UPRIGHT(r) Pt((r).max.x, (r).min.y) # define LOWLEFT(r) Pt((r).min.x, (r).max.y) *rr = *r; if(s.min.x == r->min.x){ if(s.min.y == r->min.y){ // upper left *rr = Rpt(UPRIGHT(s), r->max); *r = Rpt(LOWLEFT(s), LOWLEFT(*rr)); return 1; } if(s.max.y == r->max.y){ // lower left *rr = Rpt(Pt(s.max.x, r->min.y), r->max); *r = Rpt(r->min, UPRIGHT(s)); return 1; } } if(s.max.x == r->max.x){ if(s.max.y == r->max.y){ // lower right *rr = Rpt(Pt(s.min.x, r->min.y), UPRIGHT(s)); *r = Rpt(r->min, LOWLEFT(s)); return 1; } if(s.min.y == r->min.y){ // upper right *rr = Rpt(LOWLEFT(s), r->max); *r = Rpt(r->min, LOWLEFT(*rr)); return 1; } } return 0; }
char *pschar(char *s, char *hex, int *wid, int *ht) { Point chpt, spt; Image *b; uchar rowdata[100]; char *hp = hex; int y, i; chpt = stringsize(font, s); /* bounding box of char */ *wid = ((chpt.x+7) / 8) * 8; *ht = chpt.y; /* postscript is backwards to video, so draw white (ones) on black (zeros) */ b = allocimage(display, Rpt(ZP, chpt), GREY1, 0, DBlack); /* place to put it */ spt = string(b, Pt(0,0), display->white, ZP, font, s); /* put it there */ /* Bprint(&bout, "chpt %P, spt %P, wid,ht %d,%d\n", chpt, spt, *wid, *ht); /* Bflush(&bout); */ for (y = 0; y < chpt.y; y++) { /* read bits a row at a time */ memset(rowdata, 0, sizeof rowdata); unloadimage(b, Rect(0, y, chpt.x, y+1), rowdata, sizeof rowdata); for (i = 0; i < spt.x; i += 8) { /* 8 == byte */ sprint(hp, "%2.2x", rowdata[i/8]); hp += 2; } } *hp = 0; freeimage(b); return hex; }
static void scroll(void) { int o; Point p; Rectangle r; o = 8*h; r = Rpt(window.min, Pt(window.max.x, window.max.y-o)); p = Pt(window.min.x, window.min.y+o); memimagedraw(gscreen, r, gscreen, p, nil, p, S); r = Rpt(Pt(window.min.x, window.max.y-o), window.max); memimagedraw(gscreen, r, back, ZP, nil, ZP, S); flushmemscreen(gscreen->r); curpos.y -= o; }
static void vgascroll(VGAscr* scr) { int h, o; Point p; Rectangle r; h = scr->memdefont->height; o = 8*h; r = Rpt(window.min, Pt(window.max.x, window.max.y-o)); p = Pt(window.min.x, window.min.y+o); memimagedraw(scr->gscreen, r, scr->gscreen, p, nil, p, S); r = Rpt(Pt(window.min.x, window.max.y-o), window.max); memimagedraw(scr->gscreen, r, back, ZP, nil, ZP, S); curpos.y -= o; }
static void clrbox(int i, int j) { Point loc; loc = Pt(cen.x + j*PX, cen.y + i*PX); draw(screen, Rpt(loc, addpt(loc, Pt(BX, BX))), display->white, nil, ZP); }
static void setbox(int i, int j) { Point loc; loc = Pt(cen.x + j*PX, cen.y + i*PX); draw(screen, Rpt(loc, addpt(loc, Pt(BX, BX))), box, nil, ZP); }
void readmouse(Vnc *v) { int cursorfd, len, n; char buf[10*EventSize], *start, *end; uchar curs[2*4+2*2*16]; Cursor *cs; Mouse m; cs = &dotcursor; snprint(buf, sizeof buf, "%s/cursor", display->devdir); if((cursorfd = open(buf, OWRITE)) < 0) sysfatal("open %s: %r", buf); BPLONG(curs+0*4, cs->offset.x); BPLONG(curs+1*4, cs->offset.y); memmove(curs+2*4, cs->clr, 2*2*16); write(cursorfd, curs, sizeof curs); resize(v, 1); requestupdate(vnc, 0); start = end = buf; len = 0; for(;;) { if((n = read(mousefd, end, sizeof(buf) - (end - buf))) < 0) sysfatal("read mouse failed"); len += n; end += n; while(len >= EventSize) { if(*start == 'm') { m.xy.x = atoi(start+1); m.xy.y = atoi(start+1+12); m.buttons = atoi(start+1+2*12) & 0x1F; m.xy = subpt(m.xy, screen->r.min); if(ptinrect(m.xy, Rpt(ZP, v->dim))) { mouseevent(v, m); /* send wheel button *release* */ if ((m.buttons & 0x7) != m.buttons) { m.buttons &= 0x7; mouseevent(v, m); } } } else eresized(); start += EventSize; len -= EventSize; } if(start - buf > sizeof(buf) - EventSize) { memmove(buf, start, len); start = buf; end = start+len; } } }
void score(int p) { char buf[128]; points += p; snprint(buf, sizeof(buf), "%.6ld", points); draw(screen, Rpt(pscore, addpt(pscore, scoresz)), display->white, nil, ZP); string(screen, pscore, display->black, ZP, font, buf); }
Rectangle tilerect(Click c) { Point p; Rectangle r; p = Pt(c.x*(Facex/2)-(c.d*TileDxy), c.y*(Facey/2)-(c.d*TileDxy)); r = Rpt(p, addpt(p, Pt(Facex, Facey))); return rectaddpt(r, Pt(Depth*TileDxy, Depth*TileDxy)); }
Line * newline(Point p,Line *n) { Line *l; l = (Line *) malloc(sizeof(Line)); l->type = LINE; l->r = Rpt(p,p); l->sel = 12; l->mod = LINEHIT; l->next = n; return l; }
Line * newdots(Point p,Line *n) { Box *b; b = (Box *) malloc(sizeof(Box)); b->type = DOTS; b->r = Rpt(p,p); b->sel = 12; b->mod = BOXHIT; b->next = n; return (Line *) b; }
Line * newmacro(Point p,Line *n) { Box *b; b = (Macro *) malloc(sizeof(Macro)); b->type = MACRO; b->r = Rpt(p,p); b->sel = 12; b->mod = BOXHIT; b->next = n; return (Line *) b; }
Line * newinst(Point p,char *s,Line *n) { Inst *i; i = (Inst *) malloc(sizeof(Inst)); i->type = INST; i->r = Rpt(p,p); i->sel = 15; i->mod = BOXHIT; i->next = n; i->name = s; return (Line *) i; }
void mousethread(void *v) { Point p; Mouse m; int i, n, prev; char buf[100]; ulong rgb; prev = -1; while(readmouse(mousectl) >= 0){ m = mousectl->m; switch(m.buttons){ case 1: while(m.buttons){ if(screen->depth > 8) n = 256; else n = 1<<screen->depth; for(i=0; i!=n; i++) if(i!=prev && ptinrect(m.xy, crect[i])){ if(ramp) rgb = grey(i); else rgb = cmap2rgb(i); sprint(buf, fmt, i, (rgb>>16)&0xFF, (rgb>>8)&0xFF, rgb&0xFF, (rgb<<8) | 0xFF); p = addpt(screen->r.min, Pt(2,2)); draw(screen, Rpt(p, addpt(p, stringsize(font, buf))), display->white, nil, p); string(screen, p, display->black, ZP, font, buf); prev=i; break; } readmouse(mousectl); m = mousectl->m; } break; case 4: switch(menuhit(3, mousectl, &menu, nil)){ case 0: threadexitsall(0); } } } }
Line * newstring(Point p,int code,Line *n) { String *t; t = (String *) malloc(sizeof(String)); t->type = STRING; t->r = Rpt(p,p); t->len = 8; t->s = (char *) malloc(t->len); *(t->s) = 0; t->sel = 3; t->mod = STRHIT; t->next = n; t->code = code; return (Line *) t; }
void curson(int bl) { Image *col; if(!cursoron){ cursoff(); return; } draw(cursback, cursback->r, screen, nil, pt(x, y)); if(bl) col = red; else col = bordercol; border(screen, Rpt(pt(x, y), addpt(pt(x, y), Pt(CW,NS))), 2, col, ZP); }
void drawlevel(void) { Point p; int x, y, rx, ry, d; char *s = nil; if(finished) draw(screen, screen->r, finished==Won?won:lost, nil, ZP); else draw(screen, screen->r, bg, nil, ZP); d = (Dx(screen->r) > Dy(screen->r)) ? Dy(screen->r) -20: Dx(screen->r) -20; rx = (int)ceil((float)(d-2*Border)/(float)SzX)/2; ry = (int)ceil((float)(d-2*Border)/(float)SzY)/2; for(x = 0; x < SzX; x++) { for(y = 0; y < SzY; y++) { p = board2pix(x, y); switch(grid[x][y]){ case 999: fillellipse(screen, addpt(screen->r.min, p), rx, ry, cc, ZP); break; case 1000: p = addpt(screen->r.min, p); fillellipse(screen, p, rx, ry, ec, ZP); p = subpt(p, Pt(24, 24)); draw(screen, Rpt(p, addpt(p, Pt(48, 48))), gl, glm, ZP); break; default: fillellipse(screen, addpt(screen->r.min, p), rx, ry, ec, ZP); USED(s); /* uncomment the following to see game state and field scores */ /*s = smprint("%d", grid[x][y]); string(screen, addpt(screen->r.min, p), display->black, ZP, font, s); free(s); */ break; } } } flushimage(display, 1); }
main() { register Point Min; register Point Max; register Rectangle r; register Point p, q, s; register Point inc; #ifdef DMD630 local(); #endif request(KBD); s.x = s.y = SIZE; P->state |= RESHAPED; while (kbdchar() != 'q') { if (P->state & MOVED) { q = sub (Drect.origin, q); p = add (q, p); Max = add (q, Max); Min = add (q, Min); P->state &= ~(MOVED|RESHAPED); q = Drect.origin; } else if (P->state & RESHAPED) { rectf(&display, Drect, F_XOR); Min = p = Drect.origin; Max = sub (Drect.corner, s); inc.x = 1; inc.y = 1; P->state &= ~RESHAPED; q = Drect.origin; } rectf(&display, Rpt(p, add (p, s)), F_XOR); p.x += inc.x; if ((p.x >= Max.x) || (p.x <= Min.x)) inc.x = -inc.x; p.y += inc.y; if ((p.y >= Max.y) || (p.y <= Min.y)) inc.y = -inc.y; wait(CPU); } }
void resize() { Point p, q; Rectangle r; r = screen->r; draw(screen, r, light, nil, ZP); p = string(screen, addpt(r.min, Pt(4,4)), text, ZP, display->defaultfont, title); p.x = r.min.x+4; p.y += display->defaultfont->height+4; q = subpt(r.max, Pt(4,4)); rbar = Rpt(p, q); border(screen, rbar, -2, dark, ZP); last = 0; lastp = -1; flushimage(display, 1); drawbar(); }
/* * Translate the image in the window by delta. */ static void translate(Point delta) { Point u; Rectangle r, or; if(im == nil) return; u = pclip(addpt(ul, delta), ulrange); delta = subpt(u, ul); if(delta.x == 0 && delta.y == 0) return; /* * The upper left corner of the image is currently at ul. * We want to move it to u. */ or = rectaddpt(Rpt(ZP, Pt(Dx(im->r), Dy(im->r))), ul); r = rectaddpt(or, delta); drawop(screen, r, screen, nil, ul, S); ul = u; /* fill in gray where image used to be but isn't. */ drawdiff(screen, insetrect(or, -2), insetrect(r, -2), gray, nil, ZP, S); /* fill in black border */ drawdiff(screen, insetrect(r, -2), r, display->black, nil, ZP, S); /* fill in image where it used to be off the screen. */ if(rectclip(&or, screen->r)) drawdiff(screen, r, rectaddpt(or, delta), im, nil, im->r.min, S); else drawop(screen, r, im, nil, im->r.min, S); flushimage(display, 1); }
int rowload(Row *row, char *file, int initing) { int i, j, line, percent, y, nr, nfontr, n, ns, ndumped, dumpid, x, fd; Biobuf *b, *bout; char *buf, *l, *t, *fontname; Rune *r, rune, *fontr; Column *c, *c1, *c2; uint q0, q1; Rectangle r1, r2; Window *w; buf = fbufalloc(); if(file == nil){ if(home == nil){ warning(nil, "can't find file for load: $home not defined\n"); goto Rescue1; } sprint(buf, "%s/acme.dump", home); file = buf; } b = Bopen(file, OREAD); if(b == nil){ warning(nil, "can't open load file %s: %r\n", file); goto Rescue1; } /* current directory */ line = 0; l = rdline(b, &line); if(l == nil) goto Rescue2; l[Blinelen(b)-1] = 0; if(chdir(l) < 0){ warning(nil, "can't chdir %s\n", l); goto Rescue2; } /* global fonts */ for(i=0; i<2; i++){ l = rdline(b, &line); if(l == nil) goto Rescue2; l[Blinelen(b)-1] = 0; if(*l && strcmp(l, fontnames[i])!=0) rfget(i, TRUE, i==0 && initing, l); } if(initing && row->ncol==0) rowinit(row, screen->clipr); l = rdline(b, &line); if(l == nil) goto Rescue2; j = Blinelen(b)/12; if(j<=0 || j>10) goto Rescue2; for(i=0; i<j; i++){ percent = atoi(l+i*12); if(percent<0 || percent>=100) goto Rescue2; x = row->r.min.x+percent*Dx(row->r)/100; if(i < row->ncol){ if(i == 0) continue; c1 = row->col[i-1]; c2 = row->col[i]; r1 = c1->r; r2 = c2->r; r1.max.x = x; r2.min.x = x+Border; if(Dx(r1) < 50 || Dx(r2) < 50) continue; draw(screen, Rpt(r1.min, r2.max), display->white, nil, ZP); colresize(c1, r1); colresize(c2, r2); r2.min.x = x; r2.max.x = x+Border; draw(screen, r2, display->black, nil, ZP); } if(i >= row->ncol) rowadd(row, nil, x); } for(;;){ l = rdline(b, &line); if(l == nil) break; dumpid = 0; switch(l[0]){ case 'e': if(Blinelen(b) < 1+5*12+1) goto Rescue2; l = rdline(b, &line); /* ctl line; ignored */ if(l == nil) goto Rescue2; l = rdline(b, &line); /* directory */ if(l == nil) goto Rescue2; l[Blinelen(b)-1] = 0; if(*l == '\0'){ if(home == nil) r = bytetorune("./", &nr); else{ t = emalloc(strlen(home)+1+1); sprint(t, "%s/", home); r = bytetorune(t, &nr); free(t); } }else r = bytetorune(l, &nr); l = rdline(b, &line); /* command */ if(l == nil) goto Rescue2; t = emalloc(Blinelen(b)+1); memmove(t, l, Blinelen(b)); run(nil, t, r, nr, TRUE, nil, nil, FALSE); /* r is freed in run() */ continue; case 'f': if(Blinelen(b) < 1+5*12+1) goto Rescue2; fontname = l+1+5*12; ndumped = -1; break; case 'F': if(Blinelen(b) < 1+6*12+1) goto Rescue2; fontname = l+1+6*12; ndumped = atoi(l+1+5*12+1); break; case 'x': if(Blinelen(b) < 1+5*12+1) goto Rescue2; fontname = l+1+5*12; ndumped = -1; dumpid = atoi(l+1+1*12); break; default: goto Rescue2; } l[Blinelen(b)-1] = 0; fontr = nil; nfontr = 0; if(*fontname) fontr = bytetorune(fontname, &nfontr); i = atoi(l+1+0*12); j = atoi(l+1+1*12); q0 = atoi(l+1+2*12); q1 = atoi(l+1+3*12); percent = atoi(l+1+4*12); if(i<0 || i>10) goto Rescue2; if(i > row->ncol) i = row->ncol; c = row->col[i]; y = c->r.min.y+(percent*Dy(c->r))/100; if(y<c->r.min.y || y>=c->r.max.y) y = -1; if(dumpid == 0) w = coladd(c, nil, nil, y); else w = coladd(c, nil, lookid(dumpid, TRUE), y); if(w == nil) continue; w->dumpid = j; l = rdline(b, &line); if(l == nil) goto Rescue2; l[Blinelen(b)-1] = 0; r = bytetorune(l+5*12, &nr); ns = -1; for(n=0; n<nr; n++){ if(r[n] == '/') ns = n; if(r[n] == ' ') break; } if(dumpid == 0) winsetname(w, r, n); for(; n<nr; n++) if(r[n] == '|') break; wincleartag(w); textinsert(&w->tag, w->tag.file->nc, r+n+1, nr-(n+1), TRUE); if(ndumped >= 0){ /* simplest thing is to put it in a file and load that */ sprint(buf, "/tmp/d%d.%.4sacme", getpid(), getuser()); fd = create(buf, OWRITE|ORCLOSE, 0600); if(fd < 0){ free(r); warning(nil, "can't create temp file: %r\n"); goto Rescue2; } bout = emalloc(sizeof(Biobuf)); Binit(bout, fd, OWRITE); for(n=0; n<ndumped; n++){ rune = Bgetrune(b); if(rune == '\n') line++; if(rune == (Rune)Beof){ free(r); Bterm(bout); free(bout); close(fd); goto Rescue2; } Bputrune(bout, rune); } Bterm(bout); free(bout); textload(&w->body, 0, buf, 1); close(fd); w->body.file->mod = TRUE; for(n=0; n<w->body.file->ntext; n++) w->body.file->text[n]->w->dirty = TRUE; winsettag(w); }else if(dumpid==0 && r[ns+1]!='+' && r[ns+1]!='-') get(&w->body, nil, nil, FALSE, XXX, nil, 0); if(fontr){ fontx(&w->body, nil, nil, 0, 0, fontr, nfontr); free(fontr); } free(r); if(q0>w->body.file->nc || q1>w->body.file->nc || q0>q1) q0 = q1 = 0; textshow(&w->body, q0, q1, 1); w->maxlines = min(w->body.nlines, max(w->maxlines, w->body.maxlines)); } Bterm(b); fbuffree(buf); return TRUE; Rescue2: warning(nil, "bad load file %s:%d\n", file, line); Bterm(b); Rescue1: fbuffree(buf); return FALSE; }
void cursoff(void) { draw(screen, Rpt(pt(x, y), addpt(pt(x, y), Pt(CW,NS))), cursback, nil, cursback->r.min); }
void emulate(void) { char buf[BUFS+1]; int n; int c; int standout = 0; int insmode = 0; for (;;) { if (x > xmax || y > ymax) { x = 0; newline(); } buf[0] = get_next_char(); buf[1] = '\0'; switch(buf[0]) { case '\000': /* nulls, just ignore 'em */ break; case '\007': /* bell */ ringbell(); break; case '\t': /* tab modulo 8 */ x = (x|7)+1; break; case '\033': switch(get_next_char()) { case 'j': get_next_char(); break; case '&': /* position cursor &c */ switch(get_next_char()) { case 'a': for (;;) { n = number(buf, nil); switch(buf[0]) { case 'r': case 'y': y = n; continue; case 'c': x = n; continue; case 'R': case 'Y': y = n; break; case 'C': x = n; break; } break; } break; case 'd': /* underline stuff */ if ((n=get_next_char())>='A' && n <= 'O') standout++; else if (n == '@') standout = 0; break; default: get_next_char(); break; } break; case 'i': /* back tab */ if (x>0) x = (x-1) & ~07; break; case 'H': /* home cursor */ case 'h': x = 0; y = 0; break; case 'L': /* insert blank line */ scroll(y, ymax, y+1, y); break; case 'M': /* delete line */ scroll(y+1, ymax+1, y, ymax); break; case 'J': /* clear to end of display */ xtipple(Rpt(pt(0, y+1), pt(xmax+1, ymax+1))); /* flow */ case 'K': /* clear to EOL */ xtipple(Rpt(pt(x, y), pt(xmax+1, y+1))); break; case 'P': /* delete char */ bitblt(&screen, pt(x, y), &screen, Rpt(pt(x+1, y), pt(xmax+1, y+1)), S); xtipple(Rpt(pt(xmax, y), pt(xmax+1, y+1))); break; case 'Q': /* enter insert mode */ insmode++; break; case 'R': /* leave insert mode */ insmode = 0; break; case 'S': /* roll up */ scroll(1, ymax+1, 0, ymax); break; case 'T': scroll(0, ymax, 1, 0); break; case 'A': /* upline */ case 't': if (y>0) y--; if (olines > 0) olines--; break; case 'B': case 'w': y++; /* downline */ break; case 'C': /* right */ case 'v': x++; break; case 'D': /* left */ case 'u': x--; } break; case '\b': /* backspace */ if(x > 0) --x; break; case '\n': /* linefeed */ newline(); standout = 0; if( ttystate[cs->raw].nlcr ) x = 0; break; case '\r': /* carriage return */ x = 0; standout = 0; if( ttystate[cs->raw].crnl ) newline(); break; default: /* ordinary char */ n = 1; c = 0; while (!cs->raw && host_avail() && x+n<=xmax && n<BUFS && (c = get_next_char())>=' ' && c<'\177') { buf[n++] = c; c = 0; } buf[n] = 0; if (insmode) { bitblt(&screen, pt(x+n, y), &screen, Rpt(pt(x, y), pt(xmax-n+1, y+1)), S); } xtipple(Rpt(pt(x,y), pt(x+n, y+1))); string(&screen, pt(x, y), font, buf, DxorS); if (standout) rectf(&screen, Rpt(pt(x,y),pt(x+n,y+1)), DxorS); x += n; peekc = c; break; } } }
int eenter(char *ask, char *buf, int len, Mouse *m) { int done, down, tick, n, h, w, l, i; Image *b, *save, *backcol, *bordcol; Point p, o, t; Rectangle r, sc; Event ev; Rune k; o = screen->r.min; backcol = allocimagemix(display, DPurpleblue, DWhite); bordcol = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DPurpleblue); if(backcol == nil || bordcol == nil) return -1; while(ecankbd()) ekbd(); if(m) o = m->xy; if(buf && len > 0) n = strlen(buf); else { buf = nil; len = 0; n = 0; } k = -1; tick = n; save = nil; done = down = 0; p = stringsize(font, " "); h = p.y; w = p.x; b = screen; sc = b->clipr; replclipr(b, 0, b->r); while(!done){ p = stringsize(font, buf ? buf : ""); if(ask && ask[0]){ if(buf) p.x += w; p.x += stringwidth(font, ask); } r = rectaddpt(insetrect(Rpt(ZP, p), -4), o); p.x = 0; r = rectsubpt(r, p); p = ZP; if(r.min.x < screen->r.min.x) p.x = screen->r.min.x - r.min.x; if(r.min.y < screen->r.min.y) p.y = screen->r.min.y - r.min.y; r = rectaddpt(r, p); p = ZP; if(r.max.x > screen->r.max.x) p.x = r.max.x - screen->r.max.x; if(r.max.y > screen->r.max.y) p.y = r.max.y - screen->r.max.y; r = rectsubpt(r, p); r = insetrect(r, -2); if(save == nil){ save = allocimage(display, r, b->chan, 0, DNofill); if(save == nil){ n = -1; break; } draw(save, r, b, nil, r.min); } draw(b, r, backcol, nil, ZP); border(b, r, 2, bordcol, ZP); p = addpt(r.min, Pt(6, 6)); if(ask && ask[0]){ p = string(b, p, bordcol, ZP, font, ask); if(buf) p.x += w; } if(buf){ t = p; p = stringn(b, p, display->black, ZP, font, buf, utfnlen(buf, tick)); draw(b, Rect(p.x-1, p.y, p.x+2, p.y+3), display->black, nil, ZP); draw(b, Rect(p.x, p.y, p.x+1, p.y+h), display->black, nil, ZP); draw(b, Rect(p.x-1, p.y+h-3, p.x+2, p.y+h), display->black, nil, ZP); p = string(b, p, display->black, ZP, font, buf+tick); } flushimage(display, 1); nodraw: i = Ekeyboard; if(m != nil) i |= Emouse; replclipr(b, 0, sc); i = eread(i, &ev); /* screen might have been resized */ if(b != screen || !eqrect(screen->clipr, sc)){ freeimage(save); save = nil; } b = screen; sc = b->clipr; replclipr(b, 0, b->r); switch(i){ default: done = 1; n = -1; break; case Ekeyboard: k = ev.kbdc; if(buf == nil || k == Keof || k == '\n'){ done = 1; break; } if(k == Knack || k == Kesc){ done = !n; buf[n = tick = 0] = 0; break; } if(k == Ksoh || k == Khome){ tick = 0; continue; } if(k == Kenq || k == Kend){ tick = n; continue; } if(k == Kright){ if(tick < n) tick += chartorune(&k, buf+tick); continue; } if(k == Kleft){ for(i = 0; i < n; i += l){ l = chartorune(&k, buf+tick); if(i+l >= tick){ tick = i; break; } } continue; } if(k == Ketb){ while(tick > 0){ tick--; if(tick == 0 || strchr(" !\"#$%&'()*+,-./:;<=>?@`[\\]^{|}~", buf[tick-1])) break; } buf[n = tick] = 0; break; } if(k == Kbs){ if(tick <= 0) continue; for(i = 0; i < n; i += l){ l = chartorune(&k, buf+i); if(i+l >= tick){ memmove(buf+i, buf+i+l, n - (i+l)); buf[n -= l] = 0; tick -= l; break; } } break; } if(k < 0x20 || k == Kdel || (k & 0xFF00) == KF || (k & 0xFF00) == Spec) continue; if((len-n) <= (l = runelen(k))) continue; memmove(buf+tick+l, buf+tick, n - tick); runetochar(buf+tick, &k); buf[n += l] = 0; tick += l; break; case Emouse: *m = ev.mouse; if(!ptinrect(m->xy, r)){ down = 0; goto nodraw; } if(m->buttons & 7){ down = 1; if(buf && m->xy.x >= (t.x - w)){ down = 0; for(i = 0; i < n; i += l){ l = chartorune(&k, buf+i); t.x += stringnwidth(font, buf+i, 1); if(t.x > m->xy.x) break; } tick = i; } continue; } done = down; break; } if(save){ draw(b, save->r, save, nil, save->r.min); freeimage(save); save = nil; } } replclipr(b, 0, sc); freeimage(backcol); freeimage(bordcol); flushimage(display, 1); return n; }
static void groupmouse(Control *c, Mouse *m) { Group *g; int i, lastkid; g = (Group*)c; if (g->type == Ctlstack){ i = g->selected; if (i >= 0 && g->kids[i]->mouse && ( ( ((m->buttons == 0) || (g->lastbut == 0)) && ptinrect(m->xy, g->kids[i]->rect) ) || ( ((m->buttons != 0) || (g->lastbut != 0)) && (g->lastkid == i) ) ) ) { if (debugm) fprint(2, "groupmouse %s mouse kid %s i=%d lastkid=%d buttons=%d lastbut=%d inrect=%d\n", g->name, g->kids[i]->name, i, g->lastkid, m->buttons, g->lastbut, ptinrect(m->xy, g->kids[i]->rect) ? 1 : 0); (g->kids[i]->mouse)(g->kids[i], m); g->lastkid = i; g->lastbut = m->buttons; } else { if (debugm) fprint(2, "groupmouse %s skip kid %s i=%d lastkid=%d buttons=%d lastbut=%d inrect=%d\n", g->name, g->kids[i]->name, i, g->lastkid, m->buttons, g->lastbut, ptinrect(m->xy, g->kids[i]->rect) ? 1 : 0); } return; } lastkid = -1; for(i=0; i<g->nkids; i++) { if(g->kids[i]->mouse && ( ( ((m->buttons == 0) || (g->lastbut == 0)) && ptinrect(m->xy, g->kids[i]->rect) ) || ( ((m->buttons != 0) || (g->lastbut != 0)) && (g->lastkid == i) ) ) ) { if (debugm) fprint(2, "groupmouse %s mouse kid %s i=%d lastkid=%d buttons=%d lastbut=%d inrect=%d\n", g->name, g->kids[i]->name, i, g->lastkid, m->buttons, g->lastbut, ptinrect(m->xy, g->kids[i]->rect) ? 1 : 0); (g->kids[i]->mouse)(g->kids[i], m); lastkid = i; } else { if (debugm) fprint(2, "groupmouse %s skip kid %s i=%d lastkid=%d buttons=%d lastbut=%d inrect=%d\n", g->name, g->kids[i]->name, i, g->lastkid, m->buttons, g->lastbut, ptinrect(m->xy, g->kids[i]->rect) ? 1 : 0); } } g->lastkid = lastkid; g->lastbut = m->buttons; #ifdef notdef if(m->buttons == 0){ /* buttons now up */ g->lastbut = 0; return; } if(g->lastbut == 0 && m->buttons != 0){ /* button went down, start tracking border */ switch(g->stacking){ default: return; case Vertical: p = Pt(m->xy.x, middle_of_border.y); p0 = Pt(g->r.min.x, m->xy.y); p1 = Pt(g->r.max.x, m->xy.y); break; case Horizontal: p = Pt(middle_of_border.x, m->xy.y); p0 = Pt(m->xy.x, g->r.min.y); p1 = Pt(m->xy.x, g->r.max.y); break; } // setcursor(); oi = nil; } else if (g->lastbut != 0 && s->m.buttons != 0){ /* button is down, keep tracking border */ if(!eqpt(s->m.xy, p)){ p = onscreen(s->m.xy); r = canonrect(Rpt(p0, p)); if(Dx(r)>5 && Dy(r)>5){ i = allocwindow(wscreen, r, Refnone, 0xEEEEEEFF); /* grey */ freeimage(oi); if(i == nil) goto Rescue; oi = i; border(i, r, Selborder, red, ZP); flushimage(display, 1); } } } else if (g->lastbut != 0 && s->m.buttons == 0){ /* button went up, resize kiddies */ } g->lastbut = s->m.buttons; #endif }
void emulate(void) { char buf[BUFS+1]; int i; int n; int c; int operand[10]; int noperand; int savex, savey, saveattr, saveisgraphics; int isgraphics; int g0set, g1set; int dch; isgraphics = 0; g0set = 'B'; /* US ASCII */ g1set = 'B'; /* US ASCII */ savex = savey = 0; yscrmin = 0; yscrmax = ymax; saveattr = 0; saveisgraphics = 0; /* set initial tab stops to DEC-standard 8-column spacing */ for(c=0; (c+=8)<nelem(tabcol);) tabcol[c] = 1; for (;;) { if (y > ymax) { x = 0; newline(); } buf[0] = get_next_char(); buf[1] = '\0'; switch(buf[0]) { case '\000': case '\001': case '\002': case '\003': case '\004': case '\005': case '\006': goto Default; case '\007': /* bell */ ringbell(); break; case '\010': /* backspace */ if (x > 0) --x; break; case '\011': /* tab to next tab stop; if none, to right margin */ for(c=x+1; c<nelem(tabcol) && !tabcol[c]; c++) ; if(c < nelem(tabcol)) x = c; else x = xmax; break; case '\012': /* linefeed */ case '\013': case '\014': newline(); if (ttystate[cs->raw].nlcr) x = 0; break; case '\015': /* carriage return */ x = 0; if (ttystate[cs->raw].crnl) newline(); break; case '\016': /* SO: invoke G1 char set */ isgraphics = (isdigit(g1set)); break; case '\017': /* SI: invoke G0 char set */ isgraphics = (isdigit(g0set)); break; case '\020': /* DLE */ case '\021': /* DC1 */ case '\022': /* XON */ case '\023': /* DC3 */ case '\024': /* XOFF */ case '\025': /* NAK */ case '\026': /* SYN */ case '\027': /* ETB */ case '\030': /* CAN: cancel escape sequence, display checkerboard (not implemented) */ case '\031': /* EM */ case '\032': /* SUB: same as CAN */ goto Default; ; /* ESC, \033, is handled below */ case '\034': /* FS */ case '\035': /* GS */ case '\036': /* RS */ case '\037': /* US */ break; case '\177': /* delete: ignored */ break; case '\033': switch(dch = get_next_char()){ /* * 1 - graphic processor option on (no-op; not installed) */ case '1': break; /* * 2 - graphic processor option off (no-op; not installed) */ case '2': break; /* * 7 - save cursor position. */ case '7': //print("save\n"); savex = x; savey = y; saveattr = attr; saveisgraphics = isgraphics; break; /* * 8 - restore cursor position. */ case '8': //print("restore\n"); x = savex; y = savey; attr = saveattr; isgraphics = saveisgraphics; break; /* * c - Reset terminal. */ case 'c': print("resetterminal\n"); cursoron = 1; ttystate[cs->raw].nlcr = 0; break; /* * D - active position down a line, scroll if at bottom margin. * (Original VT100 had a bug: tracked new-line/line-feed mode.) */ case 'D': if(++y > yscrmax) { y = yscrmax; scroll(yscrmin+1, yscrmax+1, yscrmin, yscrmax); } break; /* * E - active position to start of next line, scroll if at bottom margin. */ case 'E': x = 0; if(++y > yscrmax) { y = yscrmax; scroll(yscrmin+1, yscrmax+1, yscrmin, yscrmax); } break; /* * H - set tab stop at current column. * (This is cursor home in VT52 mode (not implemented).) */ case 'H': if(x < nelem(tabcol)) tabcol[x] = 1; break; /* * M - active position up a line, scroll if at top margin.. */ case 'M': if(--y < yscrmin) { y = yscrmin; scroll(yscrmin, yscrmax, yscrmin+1, yscrmin); } break; /* * Z - identification. the terminal * emulator will return the response * code for a generic VT100. */ case 'Z': Ident: sendnchars2(7, "\033[?1;2c"); /* VT100 with AVO option */ // sendnchars2(5, "\033[?6c"); /* VT102 (insert/delete-char, etc.) */ break; /* * < - enter ANSI mode */ case '<': break; /* * > - set numeric keypad mode on (not implemented) */ case '>': break; /* * = - set numeric keypad mode off (not implemented) */ case '=': break; /* * # - Takes a one-digit argument */ case '#': switch(get_next_char()){ case '3': /* Top half of double-height line */ case '4': /* Bottom half of double-height line */ case '5': /* Single-width single-height line */ case '6': /* Double-width line */ case '7': /* Screen print */ case '8': /* Fill screen with E's */ break; } break; /* * ( - switch G0 character set */ case '(': g0set = get_next_char(); break; /* * - switch G1 character set */ case ')': g1set = get_next_char(); break; /* * Received left bracket. */ case '[': /* * A semi-colon or ? delimits arguments. */ memset(operand, 0, sizeof(operand)); operand[0] = number(buf, &i); noperand = 1; while(buf[0] == ';' || buf[0] == '?'){ if(noperand < nelem(operand)){ noperand++; operand[noperand-1] = number(buf, nil); } else number(buf, nil); } /* * do escape2 stuff */ switch(dch = buf[0]){ /* * c - same as ESC Z: what are you? */ case 'c': goto Ident; /* * g - various tabstop manipulation */ case 'g': switch(operand[0]){ case 0: /* clear tab at current column */ if(x < nelem(tabcol)) tabcol[x] = 0; break; case 3: /* clear all tabs */ memset(tabcol, 0, sizeof tabcol); break; } break; /* * l - clear various options. */ case 'l': if(noperand == 1){ switch(operand[0]){ case 20: /* set line feed mode */ ttystate[cs->raw].nlcr = 1; break; case 30: /* screen invisible (? not supported through VT220) */ break; } }else while(--noperand > 0){ switch(operand[noperand]){ case 1: /* set cursor keys to send ANSI functions: ESC [ A..D */ break; case 2: /* set VT52 mode (not implemented) */ break; case 3: /* set 80 columns */ setdim(-1, 80); break; case 4: /* set jump scrolling */ break; case 5: /* set normal video on screen */ break; case 6: /* set origin to absolute */ originrelative = 0; x = y = 0; break; case 7: /* reset auto-wrap mode */ wraparound = 0; break; case 8: /* reset auto-repeat mode */ break; case 9: /* reset interlacing mode */ break; case 25: /* text cursor off (VT220) */ cursoron = 0; break; } } break; /* * s - some dec private stuff. actually [ ? num s, but we can't detect it. */ case 's': break; /* * h - set various options. */ case 'h': if(noperand == 1){ switch(operand[0]){ default: break; case 20: /* set newline mode */ ttystate[cs->raw].nlcr = 0; break; case 30: /* screen visible (? not supported through VT220) */ break; } }else while(--noperand > 0){ switch(operand[noperand]){ default: break; case 1: /* set cursor keys to send application function: ESC O A..D */ break; case 2: /* set ANSI */ break; case 3: /* set 132 columns */ setdim(-1, 132); break; case 4: /* set smooth scrolling */ break; case 5: /* set screen to reverse video (not implemented) */ break; case 6: /* set origin to relative */ originrelative = 1; x = 0; y = yscrmin; break; case 7: /* set auto-wrap mode */ wraparound = 1; break; case 8: /* set auto-repeat mode */ break; case 9: /* set interlacing mode */ break; case 25: /* text cursor on (VT220) */ cursoron = 1; break; } } break; /* * m - change character attrs. */ case 'm': setattr(noperand, operand); break; /* * n - request various reports */ case 'n': switch(operand[0]){ case 5: /* status */ sendnchars2(4, "\033[0n"); /* terminal ok */ break; case 6: /* cursor position */ sendnchars2(sprint(buf, "\033[%d;%dR", originrelative ? y+1 - yscrmin : y+1, x+1), buf); break; } break; /* * q - turn on list of LEDs; turn off others. */ case 'q': break; /* * r - change scrolling region. operand[0] is * min scrolling region and operand[1] is max * scrolling region. */ case 'r': yscrmin = 0; yscrmax = ymax; switch(noperand){ case 2: yscrmax = operand[1]-1; if(yscrmax > ymax) yscrmax = ymax; case 1: yscrmin = operand[0]-1; if(yscrmin < 0) yscrmin = 0; } x = 0; y = yscrmin; break; /* * x - report terminal parameters */ case 'x': sendnchars2(20, "\033[3;1;1;120;120;1;0x"); break; /* * y - invoke confidence test */ case 'y': break; /* * A - cursor up. */ case 'e': case 'A': fixops(operand); y -= operand[0]; if(y < yscrmin) y = yscrmin; olines -= operand[0]; if(olines < 0) olines = 0; break; /* * B - cursor down */ case 'B': fixops(operand); y += operand[0]; if(y > yscrmax) y=yscrmax; break; /* * C - cursor right */ case 'a': case 'C': fixops(operand); x += operand[0]; /* * VT-100-UG says not to go past the * right margin. */ if(x > xmax) x = xmax; break; /* * D - cursor left */ case 'D': fixops(operand); x -= operand[0]; if(x < 0) x = 0; break; /* * G - cursor to column */ case '\'': case 'G': fixops(operand); x = operand[0] - 1; if(x > xmax) x = xmax; break; /* * H and f - cursor motion. operand[0] is row and * operand[1] is column, origin 1. */ case 'H': case 'f': fixops(operand+1); x = operand[1] - 1; if(x > xmax) x = xmax; /* fallthrough */ /* * d - cursor to line n (xterm) */ case 'd': fixops(operand); y = operand[0] - 1; if(originrelative){ y += yscrmin; if(y > yscrmax) y = yscrmax; }else{ if(y > ymax) y = ymax; } break; /* * J - clear some or all of the display. */ case 'J': switch (operand[0]) { /* * operand 2: whole screen. */ case 2: clear(Rpt(pt(0, 0), pt(xmax+1, ymax+1))); break; /* * operand 1: start of screen to active position, inclusive. */ case 1: clear(Rpt(pt(0, 0), pt(xmax+1, y))); clear(Rpt(pt(0, y), pt(x+1, y+1))); break; /* * Default: active position to end of screen, inclusive. */ default: clear(Rpt(pt(x, y), pt(xmax+1, y+1))); clear(Rpt(pt(0, y+1), pt(xmax+1, ymax+1))); break; } break; /* * K - clear some or all of the line. */ case 'K': switch (operand[0]) { /* * operand 2: whole line. */ case 2: clear(Rpt(pt(0, y), pt(xmax+1, y+1))); break; /* * operand 1: start of line to active position, inclusive. */ case 1: clear(Rpt(pt(0, y), pt(x+1, y+1))); break; /* * Default: active position to end of line, inclusive. */ default: clear(Rpt(pt(x, y), pt(xmax+1, y+1))); break; } break; /* * P - delete character(s) from right of cursor (xterm) */ case 'P': fixops(operand); i = x + operand[0]; draw(screen, Rpt(pt(x, y), pt(xmax+1, y+1)), screen, nil, pt(i, y)); clear(Rpt(pt(xmax-operand[0], y), pt(xmax+1, y+1))); break; /* * @ - insert blank(s) to right of cursor (xterm) */ case '@': fixops(operand); i = x + operand[0]; draw(screen, Rpt(pt(i, y), pt(xmax+1, y+1)), screen, nil, pt(x, y)); clear(Rpt(pt(x, y), pt(i, y+1))); break; /* * X - erase character(s) at cursor and to the right (xterm) */ case 'X': fixops(operand); i = x + operand[0]; clear(Rpt(pt(x, y), pt(i, y+1))); break; /* * L - insert a line at cursor position (VT102 and later) */ case 'L': fixops(operand); for(i = 0; i < operand[0]; ++i) scroll(y, yscrmax, y+1, y); break; /* * M - delete a line at cursor position (VT102 and later) */ case 'M': fixops(operand); for(i = 0; i < operand[0]; ++i) scroll(y+1, yscrmax+1, y, yscrmax); break; /* * S,T - scroll up/down (xterm) */ case 'T': fixops(operand); for(i = 0; i < operand[0]; ++i) scroll(yscrmin, yscrmax, yscrmin+1, yscrmin); break; case 'S': fixops(operand); for(i = 0; i < operand[0]; ++i) scroll(yscrmin+1, yscrmax+1, yscrmin, yscrmin); break; case '=': /* ? not supported through VT220 */ number(buf, nil); switch(buf[0]) { case 'h': case 'l': break; } break; /* * Anything else we ignore for now... */ default: print("unknown escape2 '%c' (0x%x)\n", dch, dch); break; } break; /* * Collapse multiple '\033' to one. */ case '\033': peekc = '\033'; break; /* set title */ case ']': /* it's actually <esc> ] num ; title <bel> */ { int ch, fd; number(buf, nil); i = 0; while((ch = get_next_char()) != '\a') if(i < sizeof buf) buf[i++] = ch; fd = open("/dev/label", OWRITE); write(fd, buf, i); close(fd); } break; /* * Ignore other commands. */ default: print("unknown command '%c' (0x%x)\n", dch, dch); break; } break; default: /* ordinary char */ Default: if(isgraphics && gmap[(uint8_t) buf[0]]) buf[0] = gmap[(uint8_t) buf[0]]; /* line wrap */ if (x > xmax){ if(wraparound){ x = 0; newline(); }else{ continue; } } n = 1; c = 0; while (!cs->raw && host_avail() && x+n<=xmax && n<BUFS && (c = get_next_char())>=' ' && c<'\177') { buf[n++] = c; c = 0; } buf[n] = 0; // clear(Rpt(pt(x,y), pt(x+n, y+1))); drawstring(pt(x, y), buf, attr); x += n; peekc = c; break; } } }