13e12c5d1SDavid du Colombier #include <u.h> 23e12c5d1SDavid du Colombier #include <libc.h> 37dd7cddfSDavid du Colombier #include <draw.h> 47dd7cddfSDavid du Colombier #include <cursor.h> 57dd7cddfSDavid du Colombier #include <event.h> 63e12c5d1SDavid du Colombier #include <bio.h> 73e12c5d1SDavid du Colombier 83e12c5d1SDavid du Colombier typedef struct Thing Thing; 93e12c5d1SDavid du Colombier 103e12c5d1SDavid du Colombier struct Thing 113e12c5d1SDavid du Colombier { 127dd7cddfSDavid du Colombier Image *b; 133e12c5d1SDavid du Colombier Subfont *s; 143e12c5d1SDavid du Colombier char *name; /* file name */ 153e12c5d1SDavid du Colombier int face; /* is 48x48 face file or cursor file*/ 163e12c5d1SDavid du Colombier Rectangle r; /* drawing region */ 173e12c5d1SDavid du Colombier Rectangle tr; /* text region */ 183e12c5d1SDavid du Colombier Rectangle er; /* entire region */ 193e12c5d1SDavid du Colombier long c; /* character number in subfont */ 203e12c5d1SDavid du Colombier int mod; /* modified */ 213e12c5d1SDavid du Colombier int mag; /* magnification */ 223e12c5d1SDavid du Colombier Rune off; /* offset for subfont indices */ 233e12c5d1SDavid du Colombier Thing *parent; /* thing of which i'm an edit */ 243e12c5d1SDavid du Colombier Thing *next; 253e12c5d1SDavid du Colombier }; 263e12c5d1SDavid du Colombier 273e12c5d1SDavid du Colombier enum 283e12c5d1SDavid du Colombier { 293e12c5d1SDavid du Colombier Border = 1, 303e12c5d1SDavid du Colombier Up = 1, 313e12c5d1SDavid du Colombier Down = 0, 323e12c5d1SDavid du Colombier Mag = 4, 333e12c5d1SDavid du Colombier Maxmag = 10, 343e12c5d1SDavid du Colombier }; 353e12c5d1SDavid du Colombier 363e12c5d1SDavid du Colombier enum 373e12c5d1SDavid du Colombier { 387dd7cddfSDavid du Colombier NORMAL =0, 397dd7cddfSDavid du Colombier FACE =1, 407dd7cddfSDavid du Colombier CURSOR =2 417dd7cddfSDavid du Colombier }; 427dd7cddfSDavid du Colombier 437dd7cddfSDavid du Colombier enum 447dd7cddfSDavid du Colombier { 453e12c5d1SDavid du Colombier Mopen, 463e12c5d1SDavid du Colombier Mread, 473e12c5d1SDavid du Colombier Mwrite, 483e12c5d1SDavid du Colombier Mcopy, 493e12c5d1SDavid du Colombier Mchar, 507dd7cddfSDavid du Colombier Mpixels, 513e12c5d1SDavid du Colombier Mclose, 523e12c5d1SDavid du Colombier Mexit, 533e12c5d1SDavid du Colombier }; 543e12c5d1SDavid du Colombier 557dd7cddfSDavid du Colombier enum 567dd7cddfSDavid du Colombier { 577dd7cddfSDavid du Colombier Blue = 54, 587dd7cddfSDavid du Colombier }; 593e12c5d1SDavid du Colombier 603e12c5d1SDavid du Colombier char *menu3str[] = { 613e12c5d1SDavid du Colombier [Mopen] "open", 623e12c5d1SDavid du Colombier [Mread] "read", 633e12c5d1SDavid du Colombier [Mwrite] "write", 643e12c5d1SDavid du Colombier [Mcopy] "copy", 653e12c5d1SDavid du Colombier [Mchar] "char", 667dd7cddfSDavid du Colombier [Mpixels] "pixels", 673e12c5d1SDavid du Colombier [Mclose] "close", 683e12c5d1SDavid du Colombier [Mexit] "exit", 693e12c5d1SDavid du Colombier 0, 703e12c5d1SDavid du Colombier }; 713e12c5d1SDavid du Colombier 723e12c5d1SDavid du Colombier Menu menu3 = { 733e12c5d1SDavid du Colombier menu3str 743e12c5d1SDavid du Colombier }; 753e12c5d1SDavid du Colombier 763e12c5d1SDavid du Colombier Cursor sweep0 = { 773e12c5d1SDavid du Colombier {-7, -7}, 783e12c5d1SDavid du Colombier {0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 793e12c5d1SDavid du Colombier 0x03, 0xC0, 0x03, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 803e12c5d1SDavid du Colombier 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xC0, 0x03, 0xC0, 813e12c5d1SDavid du Colombier 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0}, 823e12c5d1SDavid du Colombier {0x00, 0x00, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 833e12c5d1SDavid du Colombier 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x7F, 0xFE, 843e12c5d1SDavid du Colombier 0x7F, 0xFE, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 853e12c5d1SDavid du Colombier 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x00, 0x00} 863e12c5d1SDavid du Colombier }; 873e12c5d1SDavid du Colombier 883e12c5d1SDavid du Colombier Cursor box = { 893e12c5d1SDavid du Colombier {-7, -7}, 903e12c5d1SDavid du Colombier {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 913e12c5d1SDavid du Colombier 0xFF, 0xFF, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 923e12c5d1SDavid du Colombier 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xFF, 0xFF, 933e12c5d1SDavid du Colombier 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, 943e12c5d1SDavid du Colombier {0x00, 0x00, 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE, 953e12c5d1SDavid du Colombier 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 963e12c5d1SDavid du Colombier 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 973e12c5d1SDavid du Colombier 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE, 0x00, 0x00} 983e12c5d1SDavid du Colombier }; 993e12c5d1SDavid du Colombier 1003e12c5d1SDavid du Colombier Cursor sight = { 1013e12c5d1SDavid du Colombier {-7, -7}, 1023e12c5d1SDavid du Colombier {0x1F, 0xF8, 0x3F, 0xFC, 0x7F, 0xFE, 0xFB, 0xDF, 1033e12c5d1SDavid du Colombier 0xF3, 0xCF, 0xE3, 0xC7, 0xFF, 0xFF, 0xFF, 0xFF, 1043e12c5d1SDavid du Colombier 0xFF, 0xFF, 0xFF, 0xFF, 0xE3, 0xC7, 0xF3, 0xCF, 1053e12c5d1SDavid du Colombier 0x7B, 0xDF, 0x7F, 0xFE, 0x3F, 0xFC, 0x1F, 0xF8,}, 1063e12c5d1SDavid du Colombier {0x00, 0x00, 0x0F, 0xF0, 0x31, 0x8C, 0x21, 0x84, 1073e12c5d1SDavid du Colombier 0x41, 0x82, 0x41, 0x82, 0x41, 0x82, 0x7F, 0xFE, 1083e12c5d1SDavid du Colombier 0x7F, 0xFE, 0x41, 0x82, 0x41, 0x82, 0x41, 0x82, 1093e12c5d1SDavid du Colombier 0x21, 0x84, 0x31, 0x8C, 0x0F, 0xF0, 0x00, 0x00,} 1103e12c5d1SDavid du Colombier }; 1113e12c5d1SDavid du Colombier 1127dd7cddfSDavid du Colombier Cursor pixel = { 1137dd7cddfSDavid du Colombier {-7, -7}, 1147dd7cddfSDavid du Colombier {0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, 0xf8, 0x1f, 1157dd7cddfSDavid du Colombier 0xf0, 0x0f, 0xe0, 0x07, 0xe0, 0x07, 0xfe, 0x7f, 1167dd7cddfSDavid du Colombier 0xfe, 0x7f, 0xe0, 0x07, 0xe0, 0x07, 0xf0, 0x0f, 1177dd7cddfSDavid du Colombier 0x78, 0x1f, 0x7f, 0xfe, 0x3f, 0xfc, 0x1f, 0xf8, }, 1187dd7cddfSDavid du Colombier {0x00, 0x00, 0x0f, 0xf0, 0x31, 0x8c, 0x21, 0x84, 1197dd7cddfSDavid du Colombier 0x41, 0x82, 0x41, 0x82, 0x41, 0x82, 0x40, 0x02, 1207dd7cddfSDavid du Colombier 0x40, 0x02, 0x41, 0x82, 0x41, 0x82, 0x41, 0x82, 1217dd7cddfSDavid du Colombier 0x21, 0x84, 0x31, 0x8c, 0x0f, 0xf0, 0x00, 0x00, } 1227dd7cddfSDavid du Colombier }; 1237dd7cddfSDavid du Colombier 1243e12c5d1SDavid du Colombier Cursor busy = { 1253e12c5d1SDavid du Colombier {-7, -7}, 1263e12c5d1SDavid du Colombier {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1273e12c5d1SDavid du Colombier 0x00, 0x00, 0x00, 0x0c, 0x00, 0x8e, 0x1d, 0xc7, 1283e12c5d1SDavid du Colombier 0xff, 0xe3, 0xff, 0xf3, 0xff, 0xff, 0x7f, 0xfe, 1293e12c5d1SDavid du Colombier 0x3f, 0xf8, 0x17, 0xf0, 0x03, 0xe0, 0x00, 0x00,}, 1303e12c5d1SDavid du Colombier {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1313e12c5d1SDavid du Colombier 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x82, 1323e12c5d1SDavid du Colombier 0x04, 0x41, 0xff, 0xe1, 0x5f, 0xf1, 0x3f, 0xfe, 1333e12c5d1SDavid du Colombier 0x17, 0xf0, 0x03, 0xe0, 0x00, 0x00, 0x00, 0x00,} 1343e12c5d1SDavid du Colombier }; 1353e12c5d1SDavid du Colombier 1363e12c5d1SDavid du Colombier Cursor skull = { 1373e12c5d1SDavid du Colombier {-7,-7}, 1383e12c5d1SDavid du Colombier {0x00, 0x00, 0x00, 0x00, 0xc0, 0x03, 0xe7, 0xe7, 1393e12c5d1SDavid du Colombier 0xff, 0xff, 0xff, 0xff, 0x3f, 0xfc, 0x1f, 0xf8, 1403e12c5d1SDavid du Colombier 0x0f, 0xf0, 0x3f, 0xfc, 0xff, 0xff, 0xff, 0xff, 1413e12c5d1SDavid du Colombier 0xef, 0xf7, 0xc7, 0xe3, 0x00, 0x00, 0x00, 0x00,}, 1423e12c5d1SDavid du Colombier {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x03, 1433e12c5d1SDavid du Colombier 0xE7, 0xE7, 0x3F, 0xFC, 0x0F, 0xF0, 0x0D, 0xB0, 1443e12c5d1SDavid du Colombier 0x07, 0xE0, 0x06, 0x60, 0x37, 0xEC, 0xE4, 0x27, 1453e12c5d1SDavid du Colombier 0xC3, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,} 1463e12c5d1SDavid du Colombier }; 1473e12c5d1SDavid du Colombier 1483e12c5d1SDavid du Colombier Rectangle cntlr; /* control region */ 1493e12c5d1SDavid du Colombier Rectangle editr; /* editing region */ 1503e12c5d1SDavid du Colombier Rectangle textr; /* text region */ 1513e12c5d1SDavid du Colombier Thing *thing; 1523e12c5d1SDavid du Colombier Mouse mouse; 1533e12c5d1SDavid du Colombier char hex[] = "0123456789abcdefABCDEF"; 1543e12c5d1SDavid du Colombier jmp_buf err; 1553e12c5d1SDavid du Colombier char *file; 1563e12c5d1SDavid du Colombier int mag; 1577dd7cddfSDavid du Colombier int but1val = 0; 1587dd7cddfSDavid du Colombier int but2val = 255; 1597dd7cddfSDavid du Colombier int invert = 0; 1607dd7cddfSDavid du Colombier Image *values[256]; 1617dd7cddfSDavid du Colombier Image *greyvalues[256]; 1623e12c5d1SDavid du Colombier uchar data[8192]; 1633e12c5d1SDavid du Colombier 1643e12c5d1SDavid du Colombier Thing* tget(char*); 1653e12c5d1SDavid du Colombier void mesg(char*, ...); 1667dd7cddfSDavid du Colombier void drawthing(Thing*, int); 1673e12c5d1SDavid du Colombier void select(void); 1683e12c5d1SDavid du Colombier void menu(void); 1697dd7cddfSDavid du Colombier void error(Display*, char*); 1703e12c5d1SDavid du Colombier void buttons(int); 1713e12c5d1SDavid du Colombier void drawall(void); 1723e12c5d1SDavid du Colombier void tclose1(Thing*); 1733e12c5d1SDavid du Colombier 1743e12c5d1SDavid du Colombier void 1753e12c5d1SDavid du Colombier main(int argc, char *argv[]) 1763e12c5d1SDavid du Colombier { 1777dd7cddfSDavid du Colombier int i; 1783e12c5d1SDavid du Colombier Event e; 1793e12c5d1SDavid du Colombier Thing *t; 1803e12c5d1SDavid du Colombier 1813e12c5d1SDavid du Colombier mag = Mag; 1827dd7cddfSDavid du Colombier if(initdraw(error, 0, "tweak") < 0){ 1837dd7cddfSDavid du Colombier fprint(2, "tweak: initdraw failed: %r\n"); 1847dd7cddfSDavid du Colombier exits("initdraw"); 1857dd7cddfSDavid du Colombier } 1867dd7cddfSDavid du Colombier for(i=0; i<256; i++){ 1877dd7cddfSDavid du Colombier values[i] = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, cmap2rgba(i)); 1887dd7cddfSDavid du Colombier greyvalues[i] = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, (i<<24)|(i<<16)|(i<<8)|0xFF); 1897dd7cddfSDavid du Colombier if(values[i] == 0 || greyvalues[i] == 0) 1907dd7cddfSDavid du Colombier drawerror(display, "can't allocate image"); 1917dd7cddfSDavid du Colombier } 1923e12c5d1SDavid du Colombier einit(Emouse|Ekeyboard); 1937dd7cddfSDavid du Colombier eresized(0); 1943e12c5d1SDavid du Colombier i = 1; 1953e12c5d1SDavid du Colombier setjmp(err); 1963e12c5d1SDavid du Colombier for(; i<argc; i++){ 1973e12c5d1SDavid du Colombier file = argv[i]; 1983e12c5d1SDavid du Colombier t = tget(argv[i]); 1993e12c5d1SDavid du Colombier if(t) 2007dd7cddfSDavid du Colombier drawthing(t, 1); 2017dd7cddfSDavid du Colombier flushimage(display, 1); 2023e12c5d1SDavid du Colombier } 2033e12c5d1SDavid du Colombier file = 0; 2043e12c5d1SDavid du Colombier setjmp(err); 2053e12c5d1SDavid du Colombier for(;;) 2063e12c5d1SDavid du Colombier switch(event(&e)){ 2073e12c5d1SDavid du Colombier case Ekeyboard: 2083e12c5d1SDavid du Colombier break; 2093e12c5d1SDavid du Colombier case Emouse: 2103e12c5d1SDavid du Colombier mouse = e.mouse; 2113e12c5d1SDavid du Colombier if(mouse.buttons & 3){ 2123e12c5d1SDavid du Colombier select(); 2133e12c5d1SDavid du Colombier break; 2143e12c5d1SDavid du Colombier } 2153e12c5d1SDavid du Colombier if(mouse.buttons & 4) 2163e12c5d1SDavid du Colombier menu(); 2173e12c5d1SDavid du Colombier } 2183e12c5d1SDavid du Colombier } 2193e12c5d1SDavid du Colombier 2203e12c5d1SDavid du Colombier void 2217dd7cddfSDavid du Colombier error(Display*, char *s) 2223e12c5d1SDavid du Colombier { 2233e12c5d1SDavid du Colombier if(file) 2243e12c5d1SDavid du Colombier mesg("can't read %s: %s: %r", file, s); 2253e12c5d1SDavid du Colombier else 2263e12c5d1SDavid du Colombier mesg("/dev/bitblt error: %s", s); 2273e12c5d1SDavid du Colombier if(err[0]) 2283e12c5d1SDavid du Colombier longjmp(err, 1); 2293e12c5d1SDavid du Colombier exits(s); 2303e12c5d1SDavid du Colombier } 2313e12c5d1SDavid du Colombier 2323e12c5d1SDavid du Colombier void 2333e12c5d1SDavid du Colombier redraw(Thing *t) 2343e12c5d1SDavid du Colombier { 2353e12c5d1SDavid du Colombier Thing *nt; 2363e12c5d1SDavid du Colombier Point p; 2373e12c5d1SDavid du Colombier 2383e12c5d1SDavid du Colombier if(thing==0 || thing==t) 2397dd7cddfSDavid du Colombier draw(screen, editr, display->white, nil, ZP); 2403e12c5d1SDavid du Colombier if(thing == 0) 2413e12c5d1SDavid du Colombier return; 2423e12c5d1SDavid du Colombier if(thing != t){ 2433e12c5d1SDavid du Colombier for(nt=thing; nt->next!=t; nt=nt->next) 2443e12c5d1SDavid du Colombier ; 2457dd7cddfSDavid du Colombier draw(screen, Rect(screen->r.min.x, nt->er.max.y, editr.max.x, editr.max.y), 2467dd7cddfSDavid du Colombier display->white, nil, ZP); 2473e12c5d1SDavid du Colombier } 2483e12c5d1SDavid du Colombier for(nt=t; nt; nt=nt->next){ 2497dd7cddfSDavid du Colombier drawthing(nt, 0); 2503e12c5d1SDavid du Colombier if(nt->next == 0){ 2513e12c5d1SDavid du Colombier p = Pt(editr.min.x, nt->er.max.y); 2527dd7cddfSDavid du Colombier draw(screen, Rpt(p, editr.max), display->white, nil, ZP); 2533e12c5d1SDavid du Colombier } 2543e12c5d1SDavid du Colombier } 2553e12c5d1SDavid du Colombier mesg(""); 2563e12c5d1SDavid du Colombier } 2573e12c5d1SDavid du Colombier 2583e12c5d1SDavid du Colombier void 2597dd7cddfSDavid du Colombier eresized(int new) 2603e12c5d1SDavid du Colombier { 2617dd7cddfSDavid du Colombier if(new && getwindow(display, Refnone) < 0) 2627dd7cddfSDavid du Colombier error(display, "can't reattach to window"); 2637dd7cddfSDavid du Colombier cntlr = insetrect(screen->clipr, 1); 2643e12c5d1SDavid du Colombier editr = cntlr; 2653e12c5d1SDavid du Colombier textr = editr; 2663e12c5d1SDavid du Colombier textr.min.y = textr.max.y - font->height; 2673e12c5d1SDavid du Colombier cntlr.max.y = cntlr.min.y + font->height; 2683e12c5d1SDavid du Colombier editr.min.y = cntlr.max.y+1; 2693e12c5d1SDavid du Colombier editr.max.y = textr.min.y-1; 2707dd7cddfSDavid du Colombier draw(screen, screen->clipr, display->white, nil, ZP); 2717dd7cddfSDavid du Colombier draw(screen, Rect(editr.min.x, editr.max.y, editr.max.x+1, editr.max.y+1), display->black, nil, ZP); 2727dd7cddfSDavid du Colombier replclipr(screen, 0, editr); 2733e12c5d1SDavid du Colombier drawall(); 2743e12c5d1SDavid du Colombier } 2753e12c5d1SDavid du Colombier 2763e12c5d1SDavid du Colombier void 2773e12c5d1SDavid du Colombier mesgstr(Point p, int line, char *s) 2783e12c5d1SDavid du Colombier { 2793e12c5d1SDavid du Colombier Rectangle c, r; 2803e12c5d1SDavid du Colombier 2813e12c5d1SDavid du Colombier r.min = p; 2823e12c5d1SDavid du Colombier r.min.y += line*font->height; 2833e12c5d1SDavid du Colombier r.max.y = r.min.y+font->height; 2843e12c5d1SDavid du Colombier r.max.x = editr.max.x; 2857dd7cddfSDavid du Colombier c = screen->clipr; 2867dd7cddfSDavid du Colombier replclipr(screen, 0, r); 2877dd7cddfSDavid du Colombier draw(screen, r, values[0xDD], nil, ZP); 2883e12c5d1SDavid du Colombier r.min.x++; 2897dd7cddfSDavid du Colombier string(screen, r.min, display->black, ZP, font, s); 2907dd7cddfSDavid du Colombier replclipr(screen, 0, c); 2917dd7cddfSDavid du Colombier flushimage(display, 1); 2923e12c5d1SDavid du Colombier } 2933e12c5d1SDavid du Colombier 2943e12c5d1SDavid du Colombier void 2953e12c5d1SDavid du Colombier mesg(char *fmt, ...) 2963e12c5d1SDavid du Colombier { 2973e12c5d1SDavid du Colombier char buf[1024]; 2987dd7cddfSDavid du Colombier va_list arg; 2993e12c5d1SDavid du Colombier 3007dd7cddfSDavid du Colombier va_start(arg, fmt); 3019a747e4fSDavid du Colombier vseprint(buf, buf+sizeof(buf), fmt, arg); 3027dd7cddfSDavid du Colombier va_end(arg); 3033e12c5d1SDavid du Colombier mesgstr(textr.min, 0, buf); 3043e12c5d1SDavid du Colombier } 3053e12c5d1SDavid du Colombier 3063e12c5d1SDavid du Colombier void 3073e12c5d1SDavid du Colombier tmesg(Thing *t, int line, char *fmt, ...) 3083e12c5d1SDavid du Colombier { 3093e12c5d1SDavid du Colombier char buf[1024]; 3107dd7cddfSDavid du Colombier va_list arg; 3113e12c5d1SDavid du Colombier 3127dd7cddfSDavid du Colombier va_start(arg, fmt); 3139a747e4fSDavid du Colombier vseprint(buf, buf+sizeof(buf), fmt, arg); 3147dd7cddfSDavid du Colombier va_end(arg); 3153e12c5d1SDavid du Colombier mesgstr(t->tr.min, line, buf); 3163e12c5d1SDavid du Colombier } 3173e12c5d1SDavid du Colombier 3183e12c5d1SDavid du Colombier 3193e12c5d1SDavid du Colombier void 3203e12c5d1SDavid du Colombier scntl(char *l) 3213e12c5d1SDavid du Colombier { 3227dd7cddfSDavid du Colombier sprint(l, "mag: %d but1: %d but2: %d invert-on-copy: %c", mag, but1val, but2val, "ny"[invert]); 3233e12c5d1SDavid du Colombier } 3243e12c5d1SDavid du Colombier 3253e12c5d1SDavid du Colombier void 3263e12c5d1SDavid du Colombier cntl(void) 3273e12c5d1SDavid du Colombier { 3283e12c5d1SDavid du Colombier char buf[256]; 3293e12c5d1SDavid du Colombier 3303e12c5d1SDavid du Colombier scntl(buf); 3313e12c5d1SDavid du Colombier mesgstr(cntlr.min, 0, buf); 3323e12c5d1SDavid du Colombier } 3333e12c5d1SDavid du Colombier 3343e12c5d1SDavid du Colombier void 3353e12c5d1SDavid du Colombier stext(Thing *t, char *l0, char *l1) 3363e12c5d1SDavid du Colombier { 3373e12c5d1SDavid du Colombier Fontchar *fc; 3383e12c5d1SDavid du Colombier char buf[256]; 3393e12c5d1SDavid du Colombier 3403e12c5d1SDavid du Colombier l1[0] = 0; 3417dd7cddfSDavid du Colombier sprint(buf, "depth:%d r:%d %d %d %d ", 3427dd7cddfSDavid du Colombier t->b->depth, t->b->r.min.x, t->b->r.min.y, 3433e12c5d1SDavid du Colombier t->b->r.max.x, t->b->r.max.y); 3443e12c5d1SDavid du Colombier if(t->parent) 3453e12c5d1SDavid du Colombier sprint(buf+strlen(buf), "mag: %d ", t->mag); 3463e12c5d1SDavid du Colombier sprint(l0, "%s file: %s", buf, t->name); 3473e12c5d1SDavid du Colombier if(t->c >= 0){ 3483e12c5d1SDavid du Colombier fc = &t->parent->s->info[t->c]; 3493e12c5d1SDavid du Colombier sprint(l1, "c(hex): %x c(char): %C x: %d " 3503e12c5d1SDavid du Colombier "top: %d bottom: %d left: %d width: %d iwidth: %d", 3517dd7cddfSDavid du Colombier (int)(t->c+t->parent->off), (int)(t->c+t->parent->off), 3523e12c5d1SDavid du Colombier fc->x, fc->top, fc->bottom, fc->left, 3533e12c5d1SDavid du Colombier fc->width, Dx(t->b->r)); 3543e12c5d1SDavid du Colombier }else if(t->s) 3553e12c5d1SDavid du Colombier sprint(l1, "offset(hex): %ux n:%d height:%d ascent:%d", 3563e12c5d1SDavid du Colombier t->off, t->s->n, t->s->height, t->s->ascent); 3573e12c5d1SDavid du Colombier } 3583e12c5d1SDavid du Colombier 3593e12c5d1SDavid du Colombier void 3603e12c5d1SDavid du Colombier text(Thing *t) 3613e12c5d1SDavid du Colombier { 3623e12c5d1SDavid du Colombier char l0[256], l1[256]; 3633e12c5d1SDavid du Colombier 3643e12c5d1SDavid du Colombier stext(t, l0, l1); 3653e12c5d1SDavid du Colombier tmesg(t, 0, l0); 3663e12c5d1SDavid du Colombier if(l1[0]) 3673e12c5d1SDavid du Colombier tmesg(t, 1, l1); 3683e12c5d1SDavid du Colombier } 3693e12c5d1SDavid du Colombier 3703e12c5d1SDavid du Colombier void 3713e12c5d1SDavid du Colombier drawall(void) 3723e12c5d1SDavid du Colombier { 3733e12c5d1SDavid du Colombier Thing *t; 3743e12c5d1SDavid du Colombier 3753e12c5d1SDavid du Colombier cntl(); 3763e12c5d1SDavid du Colombier for(t=thing; t; t=t->next) 3777dd7cddfSDavid du Colombier drawthing(t, 0); 3783e12c5d1SDavid du Colombier } 3793e12c5d1SDavid du Colombier 3803e12c5d1SDavid du Colombier int 3817dd7cddfSDavid du Colombier value(Image *b, int x) 3823e12c5d1SDavid du Colombier { 3833e12c5d1SDavid du Colombier int v, l, w; 3843e12c5d1SDavid du Colombier uchar mask; 3853e12c5d1SDavid du Colombier 3867dd7cddfSDavid du Colombier w = b->depth; 3877dd7cddfSDavid du Colombier if(w > 8){ 3883e12c5d1SDavid du Colombier mesg("ldepth too large"); 3893e12c5d1SDavid du Colombier return 0; 3903e12c5d1SDavid du Colombier } 3917dd7cddfSDavid du Colombier l = log2[w]; 3927dd7cddfSDavid du Colombier mask = (1<<w)-1; /* ones at right end of word */ 3933e12c5d1SDavid du Colombier x -= b->r.min.x&~(7>>l); /* adjust x relative to first pixel */ 3943e12c5d1SDavid du Colombier v = data[x>>(3-l)]; 3953e12c5d1SDavid du Colombier v >>= ((7>>l)<<l) - ((x&(7>>l))<<l); /* pixel at right end of word */ 3963e12c5d1SDavid du Colombier v &= mask; /* pixel at right end of word */ 3973e12c5d1SDavid du Colombier return v; 3983e12c5d1SDavid du Colombier } 3993e12c5d1SDavid du Colombier 4003e12c5d1SDavid du Colombier int 4017dd7cddfSDavid du Colombier bvalue(int v, int d) 4023e12c5d1SDavid du Colombier { 4037dd7cddfSDavid du Colombier v &= (1<<d)-1; 4047dd7cddfSDavid du Colombier if(d > screen->depth) 4057dd7cddfSDavid du Colombier v >>= d - screen->depth; 406219b2ee8SDavid du Colombier else 4077dd7cddfSDavid du Colombier while(d < screen->depth && d < 8){ 4087dd7cddfSDavid du Colombier v |= v << d; 4097dd7cddfSDavid du Colombier d <<= 1; 4103e12c5d1SDavid du Colombier } 4117dd7cddfSDavid du Colombier if(v<0 || v>255){ 4127dd7cddfSDavid du Colombier mesg("internal error: bad color"); 4137dd7cddfSDavid du Colombier return Blue; 4147dd7cddfSDavid du Colombier } 4157dd7cddfSDavid du Colombier return v; 4163e12c5d1SDavid du Colombier } 4173e12c5d1SDavid du Colombier 4183e12c5d1SDavid du Colombier void 4197dd7cddfSDavid du Colombier drawthing(Thing *nt, int link) 4203e12c5d1SDavid du Colombier { 4213e12c5d1SDavid du Colombier int nl, nf, i, x, y, sx, sy, fdx, dx, dy, v; 4223e12c5d1SDavid du Colombier Thing *t; 4233e12c5d1SDavid du Colombier Subfont *s; 4247dd7cddfSDavid du Colombier Image *b, *col; 4253e12c5d1SDavid du Colombier Point p, p1, p2; 4263e12c5d1SDavid du Colombier 4273e12c5d1SDavid du Colombier if(link){ 4283e12c5d1SDavid du Colombier nt->next = 0; 4293e12c5d1SDavid du Colombier if(thing == 0){ 4303e12c5d1SDavid du Colombier thing = nt; 4313e12c5d1SDavid du Colombier y = editr.min.y; 4323e12c5d1SDavid du Colombier }else{ 4333e12c5d1SDavid du Colombier for(t=thing; t->next; t=t->next) 4343e12c5d1SDavid du Colombier ; 4353e12c5d1SDavid du Colombier t->next = nt; 4363e12c5d1SDavid du Colombier y = t->er.max.y; 4373e12c5d1SDavid du Colombier } 4383e12c5d1SDavid du Colombier }else{ 4393e12c5d1SDavid du Colombier if(thing == nt) 4403e12c5d1SDavid du Colombier y = editr.min.y; 4413e12c5d1SDavid du Colombier else{ 4423e12c5d1SDavid du Colombier for(t=thing; t->next!=nt; t=t->next) 4433e12c5d1SDavid du Colombier ; 4443e12c5d1SDavid du Colombier y = t->er.max.y; 4453e12c5d1SDavid du Colombier } 4463e12c5d1SDavid du Colombier } 4473e12c5d1SDavid du Colombier s = nt->s; 4483e12c5d1SDavid du Colombier b = nt->b; 4493e12c5d1SDavid du Colombier nl = font->height; 4503e12c5d1SDavid du Colombier if(s || nt->c>=0) 4513e12c5d1SDavid du Colombier nl += font->height; 4523e12c5d1SDavid du Colombier fdx = Dx(editr) - 2*Border; 4533e12c5d1SDavid du Colombier dx = Dx(b->r); 4543e12c5d1SDavid du Colombier dy = Dy(b->r); 4553e12c5d1SDavid du Colombier if(nt->mag > 1){ 4563e12c5d1SDavid du Colombier dx *= nt->mag; 4573e12c5d1SDavid du Colombier dy *= nt->mag; 4583e12c5d1SDavid du Colombier fdx -= fdx%nt->mag; 4593e12c5d1SDavid du Colombier } 4603e12c5d1SDavid du Colombier nf = 1 + dx/fdx; 4613e12c5d1SDavid du Colombier nt->er.min.y = y; 4623e12c5d1SDavid du Colombier nt->er.min.x = editr.min.x; 4633e12c5d1SDavid du Colombier nt->er.max.x = nt->er.min.x + Border + dx + Border; 4643e12c5d1SDavid du Colombier if(nt->er.max.x > editr.max.x) 4653e12c5d1SDavid du Colombier nt->er.max.x = editr.max.x; 4663e12c5d1SDavid du Colombier nt->er.max.y = nt->er.min.y + Border + nf*(dy+Border); 4677dd7cddfSDavid du Colombier nt->r = insetrect(nt->er, Border); 4683e12c5d1SDavid du Colombier nt->er.max.x = editr.max.x; 4697dd7cddfSDavid du Colombier draw(screen, nt->er, display->white, nil, ZP); 4703e12c5d1SDavid du Colombier for(i=0; i<nf; i++){ 4713e12c5d1SDavid du Colombier p1 = Pt(nt->r.min.x-1, nt->r.min.y+i*(Border+dy)); 4723e12c5d1SDavid du Colombier /* draw portion of bitmap */ 4733e12c5d1SDavid du Colombier p = Pt(p1.x+1, p1.y); 4743e12c5d1SDavid du Colombier if(nt->mag == 1) 4757dd7cddfSDavid du Colombier draw(screen, Rect(p.x, p.y, p.x+fdx+Dx(b->r), p.y+Dy(b->r)), 4767dd7cddfSDavid du Colombier b, nil, Pt(b->r.min.x+i*fdx, b->r.min.y)); 4773e12c5d1SDavid du Colombier else{ 4783e12c5d1SDavid du Colombier for(y=b->r.min.y; y<b->r.max.y; y++){ 4793e12c5d1SDavid du Colombier sy = p.y+(y-b->r.min.y)*nt->mag; 4807dd7cddfSDavid du Colombier unloadimage(b, Rect(b->r.min.x, y, b->r.max.x, y+1), data, sizeof data); 4813e12c5d1SDavid du Colombier for(x=b->r.min.x+i*(fdx/nt->mag); x<b->r.max.x; x++){ 4823e12c5d1SDavid du Colombier sx = p.x+(x-i*(fdx/nt->mag)-b->r.min.x)*nt->mag; 4833e12c5d1SDavid du Colombier if(sx >= nt->r.max.x) 4843e12c5d1SDavid du Colombier break; 4857dd7cddfSDavid du Colombier v = bvalue(value(b, x), b->depth); 4867dd7cddfSDavid du Colombier if(v == 255) 4877dd7cddfSDavid du Colombier continue; 4887dd7cddfSDavid du Colombier if(b->chan == GREY8) 4897dd7cddfSDavid du Colombier draw(screen, Rect(sx, sy, sx+nt->mag, sy+nt->mag), 4907dd7cddfSDavid du Colombier greyvalues[v], nil, ZP); 4917dd7cddfSDavid du Colombier else 4927dd7cddfSDavid du Colombier draw(screen, Rect(sx, sy, sx+nt->mag, sy+nt->mag), 4937dd7cddfSDavid du Colombier values[v], nil, ZP); 4943e12c5d1SDavid du Colombier } 4953e12c5d1SDavid du Colombier 4963e12c5d1SDavid du Colombier } 4973e12c5d1SDavid du Colombier } 4983e12c5d1SDavid du Colombier /* line down left */ 4997dd7cddfSDavid du Colombier if(i == 0) 5007dd7cddfSDavid du Colombier col = display->black; 5013e12c5d1SDavid du Colombier else 5027dd7cddfSDavid du Colombier col = display->white; 5037dd7cddfSDavid du Colombier draw(screen, Rect(p1.x, p1.y, p1.x+1, p1.y+dy+Border), col, nil, ZP); 5047dd7cddfSDavid du Colombier /* line across top */ 5057dd7cddfSDavid du Colombier draw(screen, Rect(p1.x, p1.y-1, nt->r.max.x+Border, p1.y), display->black, nil, ZP); 5067dd7cddfSDavid du Colombier p2 = p1; 5077dd7cddfSDavid du Colombier if(i == nf-1){ 5087dd7cddfSDavid du Colombier p2.x += 1 + dx%fdx; 5097dd7cddfSDavid du Colombier col = display->black; 5107dd7cddfSDavid du Colombier }else{ 5113e12c5d1SDavid du Colombier p2.x = nt->r.max.x; 5127dd7cddfSDavid du Colombier col = display->white; 5137dd7cddfSDavid du Colombier } 5143e12c5d1SDavid du Colombier /* line down right */ 5157dd7cddfSDavid du Colombier draw(screen, Rect(p2.x, p2.y, p2.x+1, p2.y+dy+Border), col, nil, ZP); 5163e12c5d1SDavid du Colombier /* line across bottom */ 5173e12c5d1SDavid du Colombier if(i == nf-1){ 5183e12c5d1SDavid du Colombier p1.y += Border+dy; 5197dd7cddfSDavid du Colombier draw(screen, Rect(p1.x, p1.y-1, p2.x,p1.y), display->black, nil, ZP); 5203e12c5d1SDavid du Colombier } 5213e12c5d1SDavid du Colombier } 5223e12c5d1SDavid du Colombier nt->tr.min.x = editr.min.x; 5233e12c5d1SDavid du Colombier nt->tr.max.x = editr.max.x; 5243e12c5d1SDavid du Colombier nt->tr.min.y = nt->er.max.y + Border; 5253e12c5d1SDavid du Colombier nt->tr.max.y = nt->tr.min.y + nl; 5263e12c5d1SDavid du Colombier nt->er.max.y = nt->tr.max.y + Border; 5273e12c5d1SDavid du Colombier text(nt); 5283e12c5d1SDavid du Colombier } 5293e12c5d1SDavid du Colombier 5303e12c5d1SDavid du Colombier int 5313e12c5d1SDavid du Colombier tohex(int c) 5323e12c5d1SDavid du Colombier { 5333e12c5d1SDavid du Colombier if('0'<=c && c<='9') 5343e12c5d1SDavid du Colombier return c - '0'; 5353e12c5d1SDavid du Colombier if('a'<=c && c<='f') 5363e12c5d1SDavid du Colombier return 10 + (c - 'a'); 5373e12c5d1SDavid du Colombier if('A'<=c && c<='F') 5383e12c5d1SDavid du Colombier return 10 + (c - 'A'); 539*43f733d7SDavid du Colombier return 0; 5403e12c5d1SDavid du Colombier } 5413e12c5d1SDavid du Colombier 5423e12c5d1SDavid du Colombier Thing* 5433e12c5d1SDavid du Colombier tget(char *file) 5443e12c5d1SDavid du Colombier { 5457dd7cddfSDavid du Colombier int i, j, fd, face, x, y, c, chan; 5467dd7cddfSDavid du Colombier Image *b; 5473e12c5d1SDavid du Colombier Subfont *s; 5483e12c5d1SDavid du Colombier Thing *t; 5499a747e4fSDavid du Colombier Dir *d; 5503e12c5d1SDavid du Colombier jmp_buf oerr; 5513e12c5d1SDavid du Colombier uchar buf[256]; 5523e12c5d1SDavid du Colombier char *data; 5533e12c5d1SDavid du Colombier 5549a747e4fSDavid du Colombier buf[0] = '\0'; 5559a747e4fSDavid du Colombier errstr((char*)buf, sizeof buf); /* flush pending error message */ 5563e12c5d1SDavid du Colombier memmove(oerr, err, sizeof err); 5579a747e4fSDavid du Colombier d = nil; 5583e12c5d1SDavid du Colombier if(setjmp(err)){ 5593e12c5d1SDavid du Colombier Err: 5609a747e4fSDavid du Colombier free(d); 5613e12c5d1SDavid du Colombier memmove(err, oerr, sizeof err); 5623e12c5d1SDavid du Colombier return 0; 5633e12c5d1SDavid du Colombier } 5643e12c5d1SDavid du Colombier fd = open(file, OREAD); 5653e12c5d1SDavid du Colombier if(fd < 0){ 5663e12c5d1SDavid du Colombier mesg("can't open %s: %r", file); 5673e12c5d1SDavid du Colombier goto Err; 5683e12c5d1SDavid du Colombier } 5699a747e4fSDavid du Colombier d = dirfstat(fd); 5709a747e4fSDavid du Colombier if(d == nil){ 5713e12c5d1SDavid du Colombier mesg("can't stat bitmap file %s: %r", file); 5723e12c5d1SDavid du Colombier close(fd); 5733e12c5d1SDavid du Colombier goto Err; 5743e12c5d1SDavid du Colombier } 5757dd7cddfSDavid du Colombier if(read(fd, buf, 11) != 11){ 5763e12c5d1SDavid du Colombier mesg("can't read %s: %r", file); 5773e12c5d1SDavid du Colombier close(fd); 5783e12c5d1SDavid du Colombier goto Err; 5793e12c5d1SDavid du Colombier } 5803e12c5d1SDavid du Colombier seek(fd, 0, 0); 5817dd7cddfSDavid du Colombier data = (char*)buf; 5827dd7cddfSDavid du Colombier if(*data == '{') 5837dd7cddfSDavid du Colombier data++; 5847dd7cddfSDavid du Colombier if(memcmp(data, "0x", 2)==0 && data[4]==','){ 5857dd7cddfSDavid du Colombier /* 5867dd7cddfSDavid du Colombier * cursor file 5877dd7cddfSDavid du Colombier */ 5887dd7cddfSDavid du Colombier face = CURSOR; 5897dd7cddfSDavid du Colombier s = 0; 5909a747e4fSDavid du Colombier data = malloc(d->length+1); 5917dd7cddfSDavid du Colombier if(data == 0){ 5927dd7cddfSDavid du Colombier mesg("can't malloc buffer: %r"); 5937dd7cddfSDavid du Colombier close(fd); 5947dd7cddfSDavid du Colombier goto Err; 5957dd7cddfSDavid du Colombier } 5969a747e4fSDavid du Colombier data[d->length] = 0; 5979a747e4fSDavid du Colombier if(read(fd, data, d->length) != d->length){ 5987dd7cddfSDavid du Colombier mesg("can't read cursor file %s: %r", file); 5997dd7cddfSDavid du Colombier close(fd); 6007dd7cddfSDavid du Colombier goto Err; 6017dd7cddfSDavid du Colombier } 6027dd7cddfSDavid du Colombier b = allocimage(display, Rect(0, 0, 16, 32), GREY1, 0, DNofill); 6037dd7cddfSDavid du Colombier if(b == 0){ 6047dd7cddfSDavid du Colombier mesg("image alloc failed file %s: %r", file); 6057dd7cddfSDavid du Colombier free(data); 6067dd7cddfSDavid du Colombier close(fd); 6077dd7cddfSDavid du Colombier goto Err; 6087dd7cddfSDavid du Colombier } 6097dd7cddfSDavid du Colombier i = 0; 6107dd7cddfSDavid du Colombier for(x=0;x<64; ){ 6117dd7cddfSDavid du Colombier if((c=data[i]) == '\0') 6127dd7cddfSDavid du Colombier goto ill; 6137dd7cddfSDavid du Colombier if(c=='0' && data[i+1] == 'x'){ 6147dd7cddfSDavid du Colombier i += 2; 6157dd7cddfSDavid du Colombier continue; 6167dd7cddfSDavid du Colombier } 6177dd7cddfSDavid du Colombier if(strchr(hex, c)){ 6187dd7cddfSDavid du Colombier buf[x++] = (tohex(c)<<4) | tohex(data[i+1]); 6197dd7cddfSDavid du Colombier i += 2; 6207dd7cddfSDavid du Colombier continue; 6217dd7cddfSDavid du Colombier } 6227dd7cddfSDavid du Colombier i++; 6237dd7cddfSDavid du Colombier } 6247dd7cddfSDavid du Colombier loadimage(b, Rect(0, 0, 16, 32), buf, sizeof buf); 6257dd7cddfSDavid du Colombier free(data); 6267dd7cddfSDavid du Colombier }else if(memcmp(buf, "0x", 2)==0){ 6273e12c5d1SDavid du Colombier /* 6283e12c5d1SDavid du Colombier * face file 6293e12c5d1SDavid du Colombier */ 6307dd7cddfSDavid du Colombier face = FACE; 6313e12c5d1SDavid du Colombier s = 0; 6329a747e4fSDavid du Colombier data = malloc(d->length+1); 6333e12c5d1SDavid du Colombier if(data == 0){ 6343e12c5d1SDavid du Colombier mesg("can't malloc buffer: %r"); 6353e12c5d1SDavid du Colombier close(fd); 6363e12c5d1SDavid du Colombier goto Err; 6373e12c5d1SDavid du Colombier } 6389a747e4fSDavid du Colombier data[d->length] = 0; 6399a747e4fSDavid du Colombier if(read(fd, data, d->length) != d->length){ 6403e12c5d1SDavid du Colombier mesg("can't read bitmap file %s: %r", file); 6413e12c5d1SDavid du Colombier close(fd); 6423e12c5d1SDavid du Colombier goto Err; 6433e12c5d1SDavid du Colombier } 6449a747e4fSDavid du Colombier for(y=0,i=0; i<d->length; i++) 6453e12c5d1SDavid du Colombier if(data[i] == '\n') 6463e12c5d1SDavid du Colombier y++; 6473e12c5d1SDavid du Colombier if(y == 0){ 6483e12c5d1SDavid du Colombier ill: 6493e12c5d1SDavid du Colombier mesg("ill-formed face file %s", file); 6503e12c5d1SDavid du Colombier close(fd); 6513e12c5d1SDavid du Colombier free(data); 6523e12c5d1SDavid du Colombier goto Err; 6533e12c5d1SDavid du Colombier } 6543e12c5d1SDavid du Colombier for(x=0,i=0; (c=data[i])!='\n'; ){ 6553e12c5d1SDavid du Colombier if(c==',' || c==' ' || c=='\t'){ 6563e12c5d1SDavid du Colombier i++; 6573e12c5d1SDavid du Colombier continue; 6583e12c5d1SDavid du Colombier } 6593e12c5d1SDavid du Colombier if(c=='0' && data[i+1] == 'x'){ 6603e12c5d1SDavid du Colombier i += 2; 6613e12c5d1SDavid du Colombier continue; 6623e12c5d1SDavid du Colombier } 6633e12c5d1SDavid du Colombier if(strchr(hex, c)){ 6643e12c5d1SDavid du Colombier x += 4; 6653e12c5d1SDavid du Colombier i++; 6663e12c5d1SDavid du Colombier continue; 6673e12c5d1SDavid du Colombier } 6683e12c5d1SDavid du Colombier goto ill; 6693e12c5d1SDavid du Colombier } 6703e12c5d1SDavid du Colombier if(x % y) 6713e12c5d1SDavid du Colombier goto ill; 6723e12c5d1SDavid du Colombier switch(x / y){ 6733e12c5d1SDavid du Colombier default: 6743e12c5d1SDavid du Colombier goto ill; 6753e12c5d1SDavid du Colombier case 1: 6767dd7cddfSDavid du Colombier chan = GREY1; 6773e12c5d1SDavid du Colombier break; 6783e12c5d1SDavid du Colombier case 2: 6797dd7cddfSDavid du Colombier chan = GREY2; 6803e12c5d1SDavid du Colombier break; 6813e12c5d1SDavid du Colombier case 4: 6827dd7cddfSDavid du Colombier chan = GREY4; 6833e12c5d1SDavid du Colombier break; 6843e12c5d1SDavid du Colombier case 8: 6857dd7cddfSDavid du Colombier chan = CMAP8; 6863e12c5d1SDavid du Colombier break; 6873e12c5d1SDavid du Colombier } 6887dd7cddfSDavid du Colombier b = allocimage(display, Rect(0, 0, y, y), chan, 0, -1); 6893e12c5d1SDavid du Colombier if(b == 0){ 6907dd7cddfSDavid du Colombier mesg("image alloc failed file %s: %r", file); 6913e12c5d1SDavid du Colombier free(data); 6923e12c5d1SDavid du Colombier close(fd); 6933e12c5d1SDavid du Colombier goto Err; 6943e12c5d1SDavid du Colombier } 6953e12c5d1SDavid du Colombier i = 0; 6963e12c5d1SDavid du Colombier for(j=0; j<y; j++){ 6973e12c5d1SDavid du Colombier for(x=0; (c=data[i])!='\n'; ){ 6983e12c5d1SDavid du Colombier if(c=='0' && data[i+1] == 'x'){ 6993e12c5d1SDavid du Colombier i += 2; 7003e12c5d1SDavid du Colombier continue; 7013e12c5d1SDavid du Colombier } 7023e12c5d1SDavid du Colombier if(strchr(hex, c)){ 7037dd7cddfSDavid du Colombier buf[x++] = ~((tohex(c)<<4) | tohex(data[i+1])); 7043e12c5d1SDavid du Colombier i += 2; 7053e12c5d1SDavid du Colombier continue; 7063e12c5d1SDavid du Colombier } 7077dd7cddfSDavid du Colombier i++; 7083e12c5d1SDavid du Colombier } 7093e12c5d1SDavid du Colombier i++; 7107dd7cddfSDavid du Colombier loadimage(b, Rect(0, j, y, j+1), buf, sizeof buf); 7113e12c5d1SDavid du Colombier } 7123e12c5d1SDavid du Colombier free(data); 7133e12c5d1SDavid du Colombier }else{ 7147dd7cddfSDavid du Colombier face = NORMAL; 7153e12c5d1SDavid du Colombier s = 0; 7167dd7cddfSDavid du Colombier b = readimage(display, fd, 0); 7173e12c5d1SDavid du Colombier if(b == 0){ 7183e12c5d1SDavid du Colombier mesg("can't read bitmap file %s: %r", file); 7193e12c5d1SDavid du Colombier close(fd); 7203e12c5d1SDavid du Colombier goto Err; 7213e12c5d1SDavid du Colombier } 7229a747e4fSDavid du Colombier if(seek(fd, 0, 1) < d->length) 7237dd7cddfSDavid du Colombier s = readsubfonti(display, file, fd, b, 0); 7243e12c5d1SDavid du Colombier } 7253e12c5d1SDavid du Colombier close(fd); 7263e12c5d1SDavid du Colombier t = malloc(sizeof(Thing)); 7273e12c5d1SDavid du Colombier if(t == 0){ 7283e12c5d1SDavid du Colombier nomem: 7293e12c5d1SDavid du Colombier mesg("malloc failed: %r"); 7303e12c5d1SDavid du Colombier if(s) 7317dd7cddfSDavid du Colombier freesubfont(s); 7327dd7cddfSDavid du Colombier else 7337dd7cddfSDavid du Colombier freeimage(b); 7343e12c5d1SDavid du Colombier goto Err; 7353e12c5d1SDavid du Colombier } 7363e12c5d1SDavid du Colombier t->name = strdup(file); 7373e12c5d1SDavid du Colombier if(t->name == 0){ 7383e12c5d1SDavid du Colombier free(t); 7393e12c5d1SDavid du Colombier goto nomem; 7403e12c5d1SDavid du Colombier } 7413e12c5d1SDavid du Colombier t->b = b; 7423e12c5d1SDavid du Colombier t->s = s; 7433e12c5d1SDavid du Colombier t->face = face; 7443e12c5d1SDavid du Colombier t->mod = 0; 7453e12c5d1SDavid du Colombier t->parent = 0; 7463e12c5d1SDavid du Colombier t->c = -1; 7473e12c5d1SDavid du Colombier t->mag = 1; 7483e12c5d1SDavid du Colombier t->off = 0; 7493e12c5d1SDavid du Colombier memmove(err, oerr, sizeof err); 7503e12c5d1SDavid du Colombier return t; 7513e12c5d1SDavid du Colombier } 7523e12c5d1SDavid du Colombier 7533e12c5d1SDavid du Colombier int 7543e12c5d1SDavid du Colombier atline(int x, Point p, char *line, char *buf) 7553e12c5d1SDavid du Colombier { 7563e12c5d1SDavid du Colombier char *s, *c, *word, *hit; 7573e12c5d1SDavid du Colombier int w, wasblank; 7583e12c5d1SDavid du Colombier Rune r; 7593e12c5d1SDavid du Colombier 7603e12c5d1SDavid du Colombier wasblank = 1; 7613e12c5d1SDavid du Colombier hit = 0; 7623e12c5d1SDavid du Colombier word = 0; 7633e12c5d1SDavid du Colombier for(s=line; *s; s+=w){ 7643e12c5d1SDavid du Colombier w = chartorune(&r, s); 7657dd7cddfSDavid du Colombier x += runestringnwidth(font, &r, 1); 7663e12c5d1SDavid du Colombier if(wasblank && r!=' ') 7673e12c5d1SDavid du Colombier word = s; 7683e12c5d1SDavid du Colombier wasblank = 0; 7693e12c5d1SDavid du Colombier if(r == ' '){ 7703e12c5d1SDavid du Colombier if(x >= p.x) 7713e12c5d1SDavid du Colombier break; 7723e12c5d1SDavid du Colombier wasblank = 1; 7733e12c5d1SDavid du Colombier } 7743e12c5d1SDavid du Colombier if(r == ':') 7753e12c5d1SDavid du Colombier hit = word; 7763e12c5d1SDavid du Colombier } 7773e12c5d1SDavid du Colombier if(x < p.x) 7783e12c5d1SDavid du Colombier return 0; 7793e12c5d1SDavid du Colombier c = utfrune(hit, ':'); 7803e12c5d1SDavid du Colombier strncpy(buf, hit, c-hit); 7813e12c5d1SDavid du Colombier buf[c-hit] = 0; 7823e12c5d1SDavid du Colombier return 1; 7833e12c5d1SDavid du Colombier } 7843e12c5d1SDavid du Colombier 7853e12c5d1SDavid du Colombier int 7863e12c5d1SDavid du Colombier attext(Thing *t, Point p, char *buf) 7873e12c5d1SDavid du Colombier { 7883e12c5d1SDavid du Colombier char l0[256], l1[256]; 7893e12c5d1SDavid du Colombier 7903e12c5d1SDavid du Colombier if(!ptinrect(p, t->tr)) 7913e12c5d1SDavid du Colombier return 0; 7923e12c5d1SDavid du Colombier stext(t, l0, l1); 7933e12c5d1SDavid du Colombier if(p.y < t->tr.min.y+font->height) 7943e12c5d1SDavid du Colombier return atline(t->r.min.x, p, l0, buf); 7953e12c5d1SDavid du Colombier else 7963e12c5d1SDavid du Colombier return atline(t->r.min.x, p, l1, buf); 7973e12c5d1SDavid du Colombier } 7983e12c5d1SDavid du Colombier 7993e12c5d1SDavid du Colombier int 8003e12c5d1SDavid du Colombier type(char *buf, char *tag) 8013e12c5d1SDavid du Colombier { 8023e12c5d1SDavid du Colombier Rune r; 8033e12c5d1SDavid du Colombier char *p; 8043e12c5d1SDavid du Colombier 8057dd7cddfSDavid du Colombier esetcursor(&busy); 8063e12c5d1SDavid du Colombier p = buf; 8073e12c5d1SDavid du Colombier for(;;){ 8083e12c5d1SDavid du Colombier *p = 0; 8093e12c5d1SDavid du Colombier mesg("%s: %s", tag, buf); 8103e12c5d1SDavid du Colombier r = ekbd(); 8113e12c5d1SDavid du Colombier switch(r){ 8123e12c5d1SDavid du Colombier case '\n': 8133e12c5d1SDavid du Colombier mesg(""); 8147dd7cddfSDavid du Colombier esetcursor(0); 8153e12c5d1SDavid du Colombier return p-buf; 8163e12c5d1SDavid du Colombier case 0x15: /* control-U */ 8173e12c5d1SDavid du Colombier p = buf; 8183e12c5d1SDavid du Colombier break; 8193e12c5d1SDavid du Colombier case '\b': 8203e12c5d1SDavid du Colombier if(p > buf) 8213e12c5d1SDavid du Colombier --p; 8223e12c5d1SDavid du Colombier break; 8233e12c5d1SDavid du Colombier default: 8243e12c5d1SDavid du Colombier p += runetochar(p, &r); 8253e12c5d1SDavid du Colombier } 8263e12c5d1SDavid du Colombier } 8273e12c5d1SDavid du Colombier return 0; /* shut up compiler */ 8283e12c5d1SDavid du Colombier } 8293e12c5d1SDavid du Colombier 8303e12c5d1SDavid du Colombier void 8313e12c5d1SDavid du Colombier textedit(Thing *t, char *tag) 8323e12c5d1SDavid du Colombier { 8333e12c5d1SDavid du Colombier char buf[256]; 8343e12c5d1SDavid du Colombier char *s; 8357dd7cddfSDavid du Colombier Image *b; 8363e12c5d1SDavid du Colombier Subfont *f; 8373e12c5d1SDavid du Colombier Fontchar *fc, *nfc; 8383e12c5d1SDavid du Colombier Rectangle r; 8397dd7cddfSDavid du Colombier ulong chan; 8407dd7cddfSDavid du Colombier int i, ld, d, w, c, doredraw, fdx, x; 8413e12c5d1SDavid du Colombier Thing *nt; 8423e12c5d1SDavid du Colombier 8433e12c5d1SDavid du Colombier buttons(Up); 8443e12c5d1SDavid du Colombier if(type(buf, tag) == 0) 8453e12c5d1SDavid du Colombier return; 8463e12c5d1SDavid du Colombier if(strcmp(tag, "file") == 0){ 8473e12c5d1SDavid du Colombier for(s=buf; *s; s++) 8483e12c5d1SDavid du Colombier if(*s <= ' '){ 8493e12c5d1SDavid du Colombier mesg("illegal file name"); 8503e12c5d1SDavid du Colombier return; 8513e12c5d1SDavid du Colombier } 8523e12c5d1SDavid du Colombier if(strcmp(t->name, buf) != 0){ 8533e12c5d1SDavid du Colombier if(t->parent) 8543e12c5d1SDavid du Colombier t->parent->mod = 1; 8553e12c5d1SDavid du Colombier else 8563e12c5d1SDavid du Colombier t->mod = 1; 8573e12c5d1SDavid du Colombier } 8583e12c5d1SDavid du Colombier for(nt=thing; nt; nt=nt->next) 8593e12c5d1SDavid du Colombier if(t==nt || t->parent==nt || nt->parent==t){ 8603e12c5d1SDavid du Colombier free(nt->name); 8613e12c5d1SDavid du Colombier nt->name = strdup(buf); 8623e12c5d1SDavid du Colombier if(nt->name == 0){ 8633e12c5d1SDavid du Colombier mesg("malloc failed: %r"); 8643e12c5d1SDavid du Colombier return; 8653e12c5d1SDavid du Colombier } 8663e12c5d1SDavid du Colombier text(nt); 8673e12c5d1SDavid du Colombier } 8683e12c5d1SDavid du Colombier return; 8693e12c5d1SDavid du Colombier } 8707dd7cddfSDavid du Colombier if(strcmp(tag, "depth") == 0){ 8717dd7cddfSDavid du Colombier if(buf[0]<'0' || '9'<buf[0] || (d=atoi(buf))<0 || d>8 || log2[d]<0){ 8723e12c5d1SDavid du Colombier mesg("illegal ldepth"); 8733e12c5d1SDavid du Colombier return; 8743e12c5d1SDavid du Colombier } 8757dd7cddfSDavid du Colombier if(d == t->b->depth) 8763e12c5d1SDavid du Colombier return; 8773e12c5d1SDavid du Colombier if(t->parent) 8783e12c5d1SDavid du Colombier t->parent->mod = 1; 8793e12c5d1SDavid du Colombier else 8803e12c5d1SDavid du Colombier t->mod = 1; 8817dd7cddfSDavid du Colombier if(d == 8) 8827dd7cddfSDavid du Colombier chan = CMAP8; 8837dd7cddfSDavid du Colombier else 8847dd7cddfSDavid du Colombier chan = CHAN1(CGrey, d); 8853e12c5d1SDavid du Colombier for(nt=thing; nt; nt=nt->next){ 8863e12c5d1SDavid du Colombier if(nt!=t && nt!=t->parent && nt->parent!=t) 8873e12c5d1SDavid du Colombier continue; 8887dd7cddfSDavid du Colombier b = allocimage(display, nt->b->r, chan, 0, 0); 8893e12c5d1SDavid du Colombier if(b == 0){ 8903e12c5d1SDavid du Colombier nobmem: 8917dd7cddfSDavid du Colombier mesg("image alloc failed: %r"); 8923e12c5d1SDavid du Colombier return; 8933e12c5d1SDavid du Colombier } 8947dd7cddfSDavid du Colombier draw(b, b->r, nt->b, nil, nt->b->r.min); 8957dd7cddfSDavid du Colombier freeimage(nt->b); 8963e12c5d1SDavid du Colombier nt->b = b; 8973e12c5d1SDavid du Colombier if(nt->s){ 8987dd7cddfSDavid du Colombier b = allocimage(display, nt->b->r, chan, 0, -1); 8993e12c5d1SDavid du Colombier if(b == 0) 9003e12c5d1SDavid du Colombier goto nobmem; 9017dd7cddfSDavid du Colombier draw(b, b->r, nt->b, nil, nt->b->r.min); 9027dd7cddfSDavid du Colombier f = allocsubfont(t->name, nt->s->n, nt->s->height, nt->s->ascent, nt->s->info, b); 9033e12c5d1SDavid du Colombier if(f == 0){ 9043e12c5d1SDavid du Colombier nofmem: 9057dd7cddfSDavid du Colombier freeimage(b); 9063e12c5d1SDavid du Colombier mesg("can't make subfont: %r"); 9073e12c5d1SDavid du Colombier return; 9083e12c5d1SDavid du Colombier } 9097dd7cddfSDavid du Colombier nt->s->info = 0; /* prevent it being freed */ 9107dd7cddfSDavid du Colombier nt->s->bits = 0; 9117dd7cddfSDavid du Colombier freesubfont(nt->s); 9123e12c5d1SDavid du Colombier nt->s = f; 9133e12c5d1SDavid du Colombier } 9147dd7cddfSDavid du Colombier drawthing(nt, 0); 9153e12c5d1SDavid du Colombier } 9163e12c5d1SDavid du Colombier return; 9173e12c5d1SDavid du Colombier } 9183e12c5d1SDavid du Colombier if(strcmp(tag, "mag") == 0){ 9193e12c5d1SDavid du Colombier if(buf[0]<'0' || '9'<buf[0] || (ld=atoi(buf))<=0 || ld>Maxmag){ 9203e12c5d1SDavid du Colombier mesg("illegal magnification"); 9213e12c5d1SDavid du Colombier return; 9223e12c5d1SDavid du Colombier } 9233e12c5d1SDavid du Colombier if(t->mag == ld) 9243e12c5d1SDavid du Colombier return; 9253e12c5d1SDavid du Colombier t->mag = ld; 9263e12c5d1SDavid du Colombier redraw(t); 9273e12c5d1SDavid du Colombier return; 9283e12c5d1SDavid du Colombier } 9297dd7cddfSDavid du Colombier if(strcmp(tag, "r") == 0){ 9307dd7cddfSDavid du Colombier if(t->s){ 9317dd7cddfSDavid du Colombier mesg("can't change rectangle of subfont\n"); 9327dd7cddfSDavid du Colombier return; 9337dd7cddfSDavid du Colombier } 9347dd7cddfSDavid du Colombier s = buf; 9357dd7cddfSDavid du Colombier r.min.x = strtoul(s, &s, 0); 9367dd7cddfSDavid du Colombier r.min.y = strtoul(s, &s, 0); 9377dd7cddfSDavid du Colombier r.max.x = strtoul(s, &s, 0); 9387dd7cddfSDavid du Colombier r.max.y = strtoul(s, &s, 0); 9397dd7cddfSDavid du Colombier if(Dx(r)<=0 || Dy(r)<=0){ 9407dd7cddfSDavid du Colombier mesg("illegal rectangle"); 9417dd7cddfSDavid du Colombier return; 9427dd7cddfSDavid du Colombier } 9437dd7cddfSDavid du Colombier if(t->parent) 9447dd7cddfSDavid du Colombier t = t->parent; 9457dd7cddfSDavid du Colombier for(nt=thing; nt; nt=nt->next){ 9467dd7cddfSDavid du Colombier if(nt->parent==t && !rectinrect(nt->b->r, r)) 9477dd7cddfSDavid du Colombier tclose1(nt); 9487dd7cddfSDavid du Colombier } 9497dd7cddfSDavid du Colombier b = allocimage(display, r, t->b->chan, 0, 0); 9507dd7cddfSDavid du Colombier if(b == 0) 9517dd7cddfSDavid du Colombier goto nobmem; 9527dd7cddfSDavid du Colombier draw(b, r, t->b, nil, r.min); 9537dd7cddfSDavid du Colombier freeimage(t->b); 9547dd7cddfSDavid du Colombier t->b = b; 9557dd7cddfSDavid du Colombier b = allocimage(display, r, t->b->chan, 0, 0); 9567dd7cddfSDavid du Colombier if(b == 0) 9577dd7cddfSDavid du Colombier goto nobmem; 9587dd7cddfSDavid du Colombier redraw(t); 9597dd7cddfSDavid du Colombier t->mod = 1; 9607dd7cddfSDavid du Colombier return; 9617dd7cddfSDavid du Colombier } 9623e12c5d1SDavid du Colombier if(strcmp(tag, "ascent") == 0){ 9633e12c5d1SDavid du Colombier if(buf[0]<'0' || '9'<buf[0] || (ld=atoi(buf))<0 || ld>t->s->height){ 9643e12c5d1SDavid du Colombier mesg("illegal ascent"); 9653e12c5d1SDavid du Colombier return; 9663e12c5d1SDavid du Colombier } 9673e12c5d1SDavid du Colombier if(t->s->ascent == ld) 9683e12c5d1SDavid du Colombier return; 9693e12c5d1SDavid du Colombier t->s->ascent = ld; 9703e12c5d1SDavid du Colombier text(t); 9713e12c5d1SDavid du Colombier t->mod = 1; 9723e12c5d1SDavid du Colombier return; 9733e12c5d1SDavid du Colombier } 9743e12c5d1SDavid du Colombier if(strcmp(tag, "height") == 0){ 9753e12c5d1SDavid du Colombier if(buf[0]<'0' || '9'<buf[0] || (ld=atoi(buf))<0){ 9763e12c5d1SDavid du Colombier mesg("illegal height"); 9773e12c5d1SDavid du Colombier return; 9783e12c5d1SDavid du Colombier } 9793e12c5d1SDavid du Colombier if(t->s->height == ld) 9803e12c5d1SDavid du Colombier return; 9813e12c5d1SDavid du Colombier t->s->height = ld; 9823e12c5d1SDavid du Colombier text(t); 9833e12c5d1SDavid du Colombier t->mod = 1; 9843e12c5d1SDavid du Colombier return; 9853e12c5d1SDavid du Colombier } 9863e12c5d1SDavid du Colombier if(strcmp(tag, "left")==0 || strcmp(tag, "width") == 0){ 9873e12c5d1SDavid du Colombier if(buf[0]<'0' || '9'<buf[0] || (ld=atoi(buf))<0){ 9883e12c5d1SDavid du Colombier mesg("illegal value"); 9893e12c5d1SDavid du Colombier return; 9903e12c5d1SDavid du Colombier } 9913e12c5d1SDavid du Colombier fc = &t->parent->s->info[t->c]; 9923e12c5d1SDavid du Colombier if(strcmp(tag, "left")==0){ 9933e12c5d1SDavid du Colombier if(fc->left == ld) 9943e12c5d1SDavid du Colombier return; 9953e12c5d1SDavid du Colombier fc->left = ld; 9963e12c5d1SDavid du Colombier }else{ 9973e12c5d1SDavid du Colombier if(fc->width == ld) 9983e12c5d1SDavid du Colombier return; 9993e12c5d1SDavid du Colombier fc->width = ld; 10003e12c5d1SDavid du Colombier } 10013e12c5d1SDavid du Colombier text(t); 10023e12c5d1SDavid du Colombier t->parent->mod = 1; 10033e12c5d1SDavid du Colombier return; 10043e12c5d1SDavid du Colombier } 10053e12c5d1SDavid du Colombier if(strcmp(tag, "offset(hex)") == 0){ 10063e12c5d1SDavid du Colombier if(!strchr(hex, buf[0])){ 10073e12c5d1SDavid du Colombier illoff: 10083e12c5d1SDavid du Colombier mesg("illegal offset"); 10093e12c5d1SDavid du Colombier return; 10103e12c5d1SDavid du Colombier } 10113e12c5d1SDavid du Colombier s = 0; 10123e12c5d1SDavid du Colombier ld = strtoul(buf, &s, 16); 10133e12c5d1SDavid du Colombier if(*s) 10143e12c5d1SDavid du Colombier goto illoff; 10153e12c5d1SDavid du Colombier t->off = ld; 10163e12c5d1SDavid du Colombier text(t); 10173e12c5d1SDavid du Colombier for(nt=thing; nt; nt=nt->next) 10183e12c5d1SDavid du Colombier if(nt->parent == t) 10193e12c5d1SDavid du Colombier text(nt); 10203e12c5d1SDavid du Colombier return; 10213e12c5d1SDavid du Colombier } 10223e12c5d1SDavid du Colombier if(strcmp(tag, "n") == 0){ 10233e12c5d1SDavid du Colombier if(buf[0]<'0' || '9'<buf[0] || (w=atoi(buf))<=0){ 10243e12c5d1SDavid du Colombier mesg("illegal n"); 10253e12c5d1SDavid du Colombier return; 10263e12c5d1SDavid du Colombier } 10273e12c5d1SDavid du Colombier f = t->s; 10283e12c5d1SDavid du Colombier if(w == f->n) 10293e12c5d1SDavid du Colombier return; 10303e12c5d1SDavid du Colombier doredraw = 0; 10313e12c5d1SDavid du Colombier again: 10323e12c5d1SDavid du Colombier for(nt=thing; nt; nt=nt->next) 10333e12c5d1SDavid du Colombier if(nt->parent == t){ 10343e12c5d1SDavid du Colombier doredraw = 1; 10353e12c5d1SDavid du Colombier tclose1(nt); 10363e12c5d1SDavid du Colombier goto again; 10373e12c5d1SDavid du Colombier } 10383e12c5d1SDavid du Colombier r = t->b->r; 10393e12c5d1SDavid du Colombier if(w < f->n) 10403e12c5d1SDavid du Colombier r.max.x = f->info[w].x; 10417dd7cddfSDavid du Colombier b = allocimage(display, r, t->b->chan, 0, 0); 10423e12c5d1SDavid du Colombier if(b == 0) 10433e12c5d1SDavid du Colombier goto nobmem; 10447dd7cddfSDavid du Colombier draw(b, b->r, t->b, nil, r.min); 10453e12c5d1SDavid du Colombier fdx = Dx(editr) - 2*Border; 10463e12c5d1SDavid du Colombier if(Dx(t->b->r)/fdx != Dx(b->r)/fdx) 10473e12c5d1SDavid du Colombier doredraw = 1; 10487dd7cddfSDavid du Colombier freeimage(t->b); 10493e12c5d1SDavid du Colombier t->b = b; 10507dd7cddfSDavid du Colombier b = allocimage(display, r, t->b->chan, 0, 0); 10513e12c5d1SDavid du Colombier if(b == 0) 10523e12c5d1SDavid du Colombier goto nobmem; 10537dd7cddfSDavid du Colombier draw(b, b->r, t->b, nil, r.min); 10543e12c5d1SDavid du Colombier nfc = malloc((w+1)*sizeof(Fontchar)); 10553e12c5d1SDavid du Colombier if(nfc == 0){ 10563e12c5d1SDavid du Colombier mesg("malloc failed"); 10577dd7cddfSDavid du Colombier freeimage(b); 10583e12c5d1SDavid du Colombier return; 10593e12c5d1SDavid du Colombier } 10603e12c5d1SDavid du Colombier fc = f->info; 10613e12c5d1SDavid du Colombier for(i=0; i<=w && i<=f->n; i++) 10623e12c5d1SDavid du Colombier nfc[i] = fc[i]; 10633e12c5d1SDavid du Colombier if(w+1 < i) 10643e12c5d1SDavid du Colombier memset(nfc+i, 0, ((w+1)-i)*sizeof(Fontchar)); 10653e12c5d1SDavid du Colombier x = fc[f->n].x; 10663e12c5d1SDavid du Colombier for(; i<=w; i++) 10673e12c5d1SDavid du Colombier nfc[i].x = x; 10687dd7cddfSDavid du Colombier f = allocsubfont(t->name, w, f->height, f->ascent, nfc, b); 10693e12c5d1SDavid du Colombier if(f == 0) 10703e12c5d1SDavid du Colombier goto nofmem; 10717dd7cddfSDavid du Colombier t->s->bits = nil; /* don't free it */ 10727dd7cddfSDavid du Colombier freesubfont(t->s); 10733e12c5d1SDavid du Colombier f->info = nfc; 10743e12c5d1SDavid du Colombier t->s = f; 10753e12c5d1SDavid du Colombier if(doredraw) 10763e12c5d1SDavid du Colombier redraw(thing); 10773e12c5d1SDavid du Colombier else 10787dd7cddfSDavid du Colombier drawthing(t, 0); 10793e12c5d1SDavid du Colombier t->mod = 1; 10803e12c5d1SDavid du Colombier return; 10813e12c5d1SDavid du Colombier } 10823e12c5d1SDavid du Colombier if(strcmp(tag, "iwidth") == 0){ 10833e12c5d1SDavid du Colombier if(buf[0]<'0' || '9'<buf[0] || (w=atoi(buf))<0){ 10843e12c5d1SDavid du Colombier mesg("illegal iwidth"); 10853e12c5d1SDavid du Colombier return; 10863e12c5d1SDavid du Colombier } 10873e12c5d1SDavid du Colombier w -= Dx(t->b->r); 10883e12c5d1SDavid du Colombier if(w == 0) 10893e12c5d1SDavid du Colombier return; 10903e12c5d1SDavid du Colombier r = t->parent->b->r; 10913e12c5d1SDavid du Colombier r.max.x += w; 10923e12c5d1SDavid du Colombier c = t->c; 10933e12c5d1SDavid du Colombier t = t->parent; 10943e12c5d1SDavid du Colombier f = t->s; 10957dd7cddfSDavid du Colombier b = allocimage(display, r, t->b->chan, 0, 0); 10963e12c5d1SDavid du Colombier if(b == 0) 10973e12c5d1SDavid du Colombier goto nobmem; 10983e12c5d1SDavid du Colombier fc = &f->info[c]; 10997dd7cddfSDavid du Colombier draw(b, Rect(b->r.min.x, b->r.min.y, 11007dd7cddfSDavid du Colombier b->r.min.x+(fc[1].x-t->b->r.min.x), b->r.min.y+Dy(t->b->r)), 11017dd7cddfSDavid du Colombier t->b, nil, t->b->r.min); 11027dd7cddfSDavid du Colombier draw(b, Rect(fc[1].x+w, b->r.min.y, w+t->b->r.max.x, b->r.min.y+Dy(t->b->r)), 11037dd7cddfSDavid du Colombier t->b, nil, Pt(fc[1].x, t->b->r.min.y)); 11043e12c5d1SDavid du Colombier fdx = Dx(editr) - 2*Border; 11053e12c5d1SDavid du Colombier doredraw = 0; 11063e12c5d1SDavid du Colombier if(Dx(t->b->r)/fdx != Dx(b->r)/fdx) 11073e12c5d1SDavid du Colombier doredraw = 1; 11087dd7cddfSDavid du Colombier freeimage(t->b); 11093e12c5d1SDavid du Colombier t->b = b; 11107dd7cddfSDavid du Colombier b = allocimage(display, r, t->b->chan, 0, 0); 11113e12c5d1SDavid du Colombier if(b == 0) 11123e12c5d1SDavid du Colombier goto nobmem; 11137dd7cddfSDavid du Colombier draw(b, b->r, t->b, nil, t->b->r.min); 11143e12c5d1SDavid du Colombier fc = &f->info[c+1]; 11153e12c5d1SDavid du Colombier for(i=c+1; i<=f->n; i++, fc++) 11163e12c5d1SDavid du Colombier fc->x += w; 11177dd7cddfSDavid du Colombier f = allocsubfont(t->name, f->n, f->height, f->ascent, 11187dd7cddfSDavid du Colombier f->info, b); 11193e12c5d1SDavid du Colombier if(f == 0) 11203e12c5d1SDavid du Colombier goto nofmem; 11213e12c5d1SDavid du Colombier /* t->s and f share info; free carefully */ 11223e12c5d1SDavid du Colombier fc = f->info; 11237dd7cddfSDavid du Colombier t->s->bits = nil; 11243e12c5d1SDavid du Colombier t->s->info = 0; 11257dd7cddfSDavid du Colombier freesubfont(t->s); 11263e12c5d1SDavid du Colombier f->info = fc; 11273e12c5d1SDavid du Colombier t->s = f; 11283e12c5d1SDavid du Colombier if(doredraw) 11293e12c5d1SDavid du Colombier redraw(t); 11303e12c5d1SDavid du Colombier else 11317dd7cddfSDavid du Colombier drawthing(t, 0); 11323e12c5d1SDavid du Colombier /* redraw all affected chars */ 11333e12c5d1SDavid du Colombier for(nt=thing; nt; nt=nt->next){ 11343e12c5d1SDavid du Colombier if(nt->parent!=t || nt->c<c) 11353e12c5d1SDavid du Colombier continue; 11363e12c5d1SDavid du Colombier fc = &f->info[nt->c]; 11373e12c5d1SDavid du Colombier r.min.x = fc[0].x; 11383e12c5d1SDavid du Colombier r.min.y = nt->b->r.min.y; 11393e12c5d1SDavid du Colombier r.max.x = fc[1].x; 11403e12c5d1SDavid du Colombier r.max.y = nt->b->r.max.y; 11417dd7cddfSDavid du Colombier b = allocimage(display, r, nt->b->chan, 0, 0); 11423e12c5d1SDavid du Colombier if(b == 0) 11433e12c5d1SDavid du Colombier goto nobmem; 11447dd7cddfSDavid du Colombier draw(b, r, t->b, nil, r.min); 11453e12c5d1SDavid du Colombier doredraw = 0; 11463e12c5d1SDavid du Colombier if(Dx(nt->b->r)/fdx != Dx(b->r)/fdx) 11473e12c5d1SDavid du Colombier doredraw = 1; 11487dd7cddfSDavid du Colombier freeimage(nt->b); 11493e12c5d1SDavid du Colombier nt->b = b; 11503e12c5d1SDavid du Colombier if(c != nt->c) 11513e12c5d1SDavid du Colombier text(nt); 11523e12c5d1SDavid du Colombier else{ 11533e12c5d1SDavid du Colombier if(doredraw) 11543e12c5d1SDavid du Colombier redraw(nt); 11553e12c5d1SDavid du Colombier else 11567dd7cddfSDavid du Colombier drawthing(nt, 0); 11573e12c5d1SDavid du Colombier } 11583e12c5d1SDavid du Colombier } 11593e12c5d1SDavid du Colombier t->mod = 1; 11603e12c5d1SDavid du Colombier return; 11613e12c5d1SDavid du Colombier } 11623e12c5d1SDavid du Colombier mesg("cannot edit %s in file %s", tag, t->name); 11633e12c5d1SDavid du Colombier } 11643e12c5d1SDavid du Colombier 11653e12c5d1SDavid du Colombier void 11663e12c5d1SDavid du Colombier cntledit(char *tag) 11673e12c5d1SDavid du Colombier { 11683e12c5d1SDavid du Colombier char buf[256]; 116922a127bbSDavid du Colombier long l; 11703e12c5d1SDavid du Colombier 11713e12c5d1SDavid du Colombier buttons(Up); 11723e12c5d1SDavid du Colombier if(type(buf, tag) == 0) 11733e12c5d1SDavid du Colombier return; 11743e12c5d1SDavid du Colombier if(strcmp(tag, "mag") == 0){ 11753e12c5d1SDavid du Colombier if(buf[0]<'0' || '9'<buf[0] || (l=atoi(buf))<=0 || l>Maxmag){ 11763e12c5d1SDavid du Colombier mesg("illegal magnification"); 11773e12c5d1SDavid du Colombier return; 11783e12c5d1SDavid du Colombier } 11793e12c5d1SDavid du Colombier mag = l; 11803e12c5d1SDavid du Colombier cntl(); 11813e12c5d1SDavid du Colombier return; 11823e12c5d1SDavid du Colombier } 11833e12c5d1SDavid du Colombier if(strcmp(tag, "but1")==0 11847dd7cddfSDavid du Colombier || strcmp(tag, "but2")==0){ 11857dd7cddfSDavid du Colombier if(buf[0]<'0' || '9'<buf[0] || (l=atoi(buf))<0 || l>255){ 11867dd7cddfSDavid du Colombier mesg("illegal value"); 11873e12c5d1SDavid du Colombier return; 11883e12c5d1SDavid du Colombier } 11893e12c5d1SDavid du Colombier if(strcmp(tag, "but1") == 0) 11907dd7cddfSDavid du Colombier but1val = l; 11913e12c5d1SDavid du Colombier else if(strcmp(tag, "but2") == 0) 11927dd7cddfSDavid du Colombier but2val = l; 11937dd7cddfSDavid du Colombier cntl(); 11947dd7cddfSDavid du Colombier return; 11957dd7cddfSDavid du Colombier } 11967dd7cddfSDavid du Colombier if(strcmp(tag, "invert-on-copy")==0){ 11977dd7cddfSDavid du Colombier if(buf[0]=='y' || buf[0]=='1') 11987dd7cddfSDavid du Colombier invert = 1; 11997dd7cddfSDavid du Colombier else if(buf[0]=='n' || buf[0]=='0') 12007dd7cddfSDavid du Colombier invert = 0; 12017dd7cddfSDavid du Colombier else{ 12027dd7cddfSDavid du Colombier mesg("illegal value"); 12037dd7cddfSDavid du Colombier return; 12047dd7cddfSDavid du Colombier } 12053e12c5d1SDavid du Colombier cntl(); 12063e12c5d1SDavid du Colombier return; 12073e12c5d1SDavid du Colombier } 12083e12c5d1SDavid du Colombier mesg("cannot edit %s", tag); 12093e12c5d1SDavid du Colombier } 12103e12c5d1SDavid du Colombier 12113e12c5d1SDavid du Colombier void 12123e12c5d1SDavid du Colombier buttons(int ud) 12133e12c5d1SDavid du Colombier { 12143e12c5d1SDavid du Colombier while((mouse.buttons==0) != ud) 12153e12c5d1SDavid du Colombier mouse = emouse(); 12163e12c5d1SDavid du Colombier } 12173e12c5d1SDavid du Colombier 12187dd7cddfSDavid du Colombier Point 12197dd7cddfSDavid du Colombier screenpt(Thing *t, Point realp) 12203e12c5d1SDavid du Colombier { 12217dd7cddfSDavid du Colombier int fdx, n; 12223e12c5d1SDavid du Colombier Point p; 12233e12c5d1SDavid du Colombier 12247dd7cddfSDavid du Colombier fdx = Dx(editr)-2*Border; 12257dd7cddfSDavid du Colombier if(t->mag > 1) 12267dd7cddfSDavid du Colombier fdx -= fdx%t->mag; 12277dd7cddfSDavid du Colombier p = mulpt(subpt(realp, t->b->r.min), t->mag); 12287dd7cddfSDavid du Colombier if(fdx < Dx(t->b->r)*t->mag){ 12297dd7cddfSDavid du Colombier n = p.x/fdx; 12307dd7cddfSDavid du Colombier p.y += n * (Dy(t->b->r)*t->mag+Border); 12317dd7cddfSDavid du Colombier p.x -= n * fdx; 12327dd7cddfSDavid du Colombier } 12337dd7cddfSDavid du Colombier p = addpt(p, t->r.min); 12347dd7cddfSDavid du Colombier return p; 12357dd7cddfSDavid du Colombier } 12367dd7cddfSDavid du Colombier 12377dd7cddfSDavid du Colombier Point 12387dd7cddfSDavid du Colombier realpt(Thing *t, Point screenp) 12397dd7cddfSDavid du Colombier { 12407dd7cddfSDavid du Colombier int fdx, n, dy; 12417dd7cddfSDavid du Colombier Point p; 12427dd7cddfSDavid du Colombier 12437dd7cddfSDavid du Colombier fdx = (Dx(editr)-2*Border); 12447dd7cddfSDavid du Colombier if(t->mag > 1) 12457dd7cddfSDavid du Colombier fdx -= fdx%t->mag; 12467dd7cddfSDavid du Colombier p.y = screenp.y-t->r.min.y; 12477dd7cddfSDavid du Colombier p.x = 0; 12487dd7cddfSDavid du Colombier if(fdx < Dx(t->b->r)*t->mag){ 12497dd7cddfSDavid du Colombier dy = Dy(t->b->r)*t->mag+Border; 12507dd7cddfSDavid du Colombier n = (p.y/dy); 12517dd7cddfSDavid du Colombier p.x = n * fdx; 12527dd7cddfSDavid du Colombier p.y -= n * dy; 12537dd7cddfSDavid du Colombier } 12547dd7cddfSDavid du Colombier p.x += screenp.x-t->r.min.x; 12557dd7cddfSDavid du Colombier p = addpt(divpt(p, t->mag), t->b->r.min); 12567dd7cddfSDavid du Colombier return p; 12577dd7cddfSDavid du Colombier } 12587dd7cddfSDavid du Colombier 12597dd7cddfSDavid du Colombier int 12607dd7cddfSDavid du Colombier sweep(int but, Rectangle *r) 12617dd7cddfSDavid du Colombier { 12627dd7cddfSDavid du Colombier Thing *t; 12637dd7cddfSDavid du Colombier Point p, q, lastq; 12647dd7cddfSDavid du Colombier 12657dd7cddfSDavid du Colombier esetcursor(&sweep0); 12663e12c5d1SDavid du Colombier buttons(Down); 12677dd7cddfSDavid du Colombier if(mouse.buttons != (1<<(but-1))){ 12683e12c5d1SDavid du Colombier buttons(Up); 12697dd7cddfSDavid du Colombier esetcursor(0); 12703e12c5d1SDavid du Colombier return 0; 12713e12c5d1SDavid du Colombier } 12723e12c5d1SDavid du Colombier p = mouse.xy; 12737dd7cddfSDavid du Colombier for(t=thing; t; t=t->next) 12747dd7cddfSDavid du Colombier if(ptinrect(p, t->r)) 12757dd7cddfSDavid du Colombier break; 12767dd7cddfSDavid du Colombier if(t) 12777dd7cddfSDavid du Colombier p = screenpt(t, realpt(t, p)); 12783e12c5d1SDavid du Colombier r->min = p; 12793e12c5d1SDavid du Colombier r->max = p; 12807dd7cddfSDavid du Colombier esetcursor(&box); 12817dd7cddfSDavid du Colombier lastq = ZP; 12827dd7cddfSDavid du Colombier while(mouse.buttons == (1<<(but-1))){ 12837dd7cddfSDavid du Colombier edrawgetrect(insetrect(*r, -Borderwidth), 1); 12843e12c5d1SDavid du Colombier mouse = emouse(); 12857dd7cddfSDavid du Colombier edrawgetrect(insetrect(*r, -Borderwidth), 0); 12867dd7cddfSDavid du Colombier q = mouse.xy; 12877dd7cddfSDavid du Colombier if(t) 12887dd7cddfSDavid du Colombier q = screenpt(t, realpt(t, q)); 12897dd7cddfSDavid du Colombier if(eqpt(q, lastq)) 12907dd7cddfSDavid du Colombier continue; 12917dd7cddfSDavid du Colombier *r = canonrect(Rpt(p, q)); 12927dd7cddfSDavid du Colombier lastq = q; 12933e12c5d1SDavid du Colombier } 12947dd7cddfSDavid du Colombier esetcursor(0); 12953e12c5d1SDavid du Colombier if(mouse.buttons){ 12963e12c5d1SDavid du Colombier buttons(Up); 12973e12c5d1SDavid du Colombier return 0; 12983e12c5d1SDavid du Colombier } 12993e12c5d1SDavid du Colombier return 1; 13003e12c5d1SDavid du Colombier } 13013e12c5d1SDavid du Colombier 13023e12c5d1SDavid du Colombier void 13033e12c5d1SDavid du Colombier openedit(Thing *t, Point pt, int c) 13043e12c5d1SDavid du Colombier { 13053e12c5d1SDavid du Colombier int x, y; 13063e12c5d1SDavid du Colombier Point p; 13073e12c5d1SDavid du Colombier Rectangle r; 13083e12c5d1SDavid du Colombier Rectangle br; 13093e12c5d1SDavid du Colombier Fontchar *fc; 13103e12c5d1SDavid du Colombier Thing *nt; 13113e12c5d1SDavid du Colombier 13127dd7cddfSDavid du Colombier if(t->b->depth > 8){ 13137dd7cddfSDavid du Colombier mesg("image has depth %d; can't handle >8", t->b->depth); 13147dd7cddfSDavid du Colombier return; 13157dd7cddfSDavid du Colombier } 13163e12c5d1SDavid du Colombier br = t->b->r; 13173e12c5d1SDavid du Colombier if(t->s == 0){ 13183e12c5d1SDavid du Colombier c = -1; 13193e12c5d1SDavid du Colombier /* if big enough to bother, sweep box */ 13203e12c5d1SDavid du Colombier if(Dx(br)<=16 && Dy(br)<=16) 13213e12c5d1SDavid du Colombier r = br; 13223e12c5d1SDavid du Colombier else{ 13233e12c5d1SDavid du Colombier if(!sweep(1, &r)) 13243e12c5d1SDavid du Colombier return; 13257dd7cddfSDavid du Colombier r = rectaddpt(r, subpt(br.min, t->r.min)); 13263e12c5d1SDavid du Colombier if(!rectclip(&r, br)) 13273e12c5d1SDavid du Colombier return; 13283e12c5d1SDavid du Colombier if(Dx(br) <= 8){ 13293e12c5d1SDavid du Colombier r.min.x = br.min.x; 13303e12c5d1SDavid du Colombier r.max.x = br.max.x; 13313e12c5d1SDavid du Colombier }else if(Dx(r) < 4){ 13323e12c5d1SDavid du Colombier toosmall: 13333e12c5d1SDavid du Colombier mesg("rectangle too small"); 13343e12c5d1SDavid du Colombier return; 13353e12c5d1SDavid du Colombier } 13363e12c5d1SDavid du Colombier if(Dy(br) <= 8){ 13373e12c5d1SDavid du Colombier r.min.y = br.min.y; 13383e12c5d1SDavid du Colombier r.max.y = br.max.y; 13393e12c5d1SDavid du Colombier }else if(Dy(r) < 4) 13403e12c5d1SDavid du Colombier goto toosmall; 13413e12c5d1SDavid du Colombier } 13423e12c5d1SDavid du Colombier }else if(c >= 0){ 13433e12c5d1SDavid du Colombier fc = &t->s->info[c]; 13443e12c5d1SDavid du Colombier r.min.x = fc[0].x; 13453e12c5d1SDavid du Colombier r.min.y = br.min.y; 13463e12c5d1SDavid du Colombier r.max.x = fc[1].x; 13473e12c5d1SDavid du Colombier r.max.y = br.min.y + Dy(br); 13483e12c5d1SDavid du Colombier }else{ 13493e12c5d1SDavid du Colombier /* just point at character */ 13503e12c5d1SDavid du Colombier fc = t->s->info; 13517dd7cddfSDavid du Colombier p = addpt(pt, subpt(br.min, t->r.min)); 13523e12c5d1SDavid du Colombier x = br.min.x; 13533e12c5d1SDavid du Colombier y = br.min.y; 13543e12c5d1SDavid du Colombier for(c=0; c<t->s->n; c++,fc++){ 13553e12c5d1SDavid du Colombier again: 13563e12c5d1SDavid du Colombier r.min.x = x; 13573e12c5d1SDavid du Colombier r.min.y = y; 13583e12c5d1SDavid du Colombier r.max.x = x + fc[1].x - fc[0].x; 13593e12c5d1SDavid du Colombier r.max.y = y + Dy(br); 13603e12c5d1SDavid du Colombier if(ptinrect(p, r)) 13613e12c5d1SDavid du Colombier goto found; 13623e12c5d1SDavid du Colombier if(r.max.x >= br.min.x+Dx(t->r)){ 13633e12c5d1SDavid du Colombier x -= Dx(t->r); 13643e12c5d1SDavid du Colombier y += t->s->height; 13653e12c5d1SDavid du Colombier if(fc[1].x > fc[0].x) 13663e12c5d1SDavid du Colombier goto again; 13673e12c5d1SDavid du Colombier } 13683e12c5d1SDavid du Colombier x += fc[1].x - fc[0].x; 13693e12c5d1SDavid du Colombier } 13703e12c5d1SDavid du Colombier return; 13713e12c5d1SDavid du Colombier found: 13723e12c5d1SDavid du Colombier r = br; 13733e12c5d1SDavid du Colombier r.min.x = fc[0].x; 13743e12c5d1SDavid du Colombier r.max.x = fc[1].x; 13753e12c5d1SDavid du Colombier } 13763e12c5d1SDavid du Colombier nt = malloc(sizeof(Thing)); 13773e12c5d1SDavid du Colombier if(nt == 0){ 13783e12c5d1SDavid du Colombier nomem: 13793e12c5d1SDavid du Colombier mesg("can't allocate: %r"); 13803e12c5d1SDavid du Colombier return; 13813e12c5d1SDavid du Colombier } 13823e12c5d1SDavid du Colombier memset(nt, 0, sizeof(Thing)); 13833e12c5d1SDavid du Colombier nt->c = c; 13847dd7cddfSDavid du Colombier nt->b = allocimage(display, r, t->b->chan, 0, DNofill); 13853e12c5d1SDavid du Colombier if(nt->b == 0){ 13863e12c5d1SDavid du Colombier free(nt); 13873e12c5d1SDavid du Colombier goto nomem; 13883e12c5d1SDavid du Colombier } 13897dd7cddfSDavid du Colombier draw(nt->b, r, t->b, nil, r.min); 13903e12c5d1SDavid du Colombier nt->name = strdup(t->name); 13913e12c5d1SDavid du Colombier if(nt->name == 0){ 13927dd7cddfSDavid du Colombier freeimage(nt->b); 13933e12c5d1SDavid du Colombier free(nt); 13943e12c5d1SDavid du Colombier goto nomem; 13953e12c5d1SDavid du Colombier } 13963e12c5d1SDavid du Colombier nt->parent = t; 13973e12c5d1SDavid du Colombier nt->mag = mag; 13987dd7cddfSDavid du Colombier drawthing(nt, 1); 13993e12c5d1SDavid du Colombier } 14003e12c5d1SDavid du Colombier 14013e12c5d1SDavid du Colombier void 14023e12c5d1SDavid du Colombier ckinfo(Thing *t, Rectangle mod) 14033e12c5d1SDavid du Colombier { 14043e12c5d1SDavid du Colombier int i, j, k, top, bot, n, zero; 14053e12c5d1SDavid du Colombier Fontchar *fc; 14063e12c5d1SDavid du Colombier Rectangle r; 14077dd7cddfSDavid du Colombier Image *b; 14083e12c5d1SDavid du Colombier Thing *nt; 14093e12c5d1SDavid du Colombier 14103e12c5d1SDavid du Colombier if(t->parent) 14113e12c5d1SDavid du Colombier t = t->parent; 14123e12c5d1SDavid du Colombier if(t->s==0 || Dy(t->b->r)==0) 14133e12c5d1SDavid du Colombier return; 14143e12c5d1SDavid du Colombier b = 0; 14153e12c5d1SDavid du Colombier /* check bounding boxes */ 14163e12c5d1SDavid du Colombier fc = &t->s->info[0]; 14173e12c5d1SDavid du Colombier r.min.y = t->b->r.min.y; 14183e12c5d1SDavid du Colombier r.max.y = t->b->r.max.y; 14193e12c5d1SDavid du Colombier for(i=0; i<t->s->n; i++, fc++){ 14203e12c5d1SDavid du Colombier r.min.x = fc[0].x; 14213e12c5d1SDavid du Colombier r.max.x = fc[1].x; 14223e12c5d1SDavid du Colombier if(!rectXrect(mod, r)) 14233e12c5d1SDavid du Colombier continue; 14243e12c5d1SDavid du Colombier if(b==0 || Dx(b->r)<Dx(r)){ 14253e12c5d1SDavid du Colombier if(b) 14267dd7cddfSDavid du Colombier freeimage(b); 14277dd7cddfSDavid du Colombier b = allocimage(display, rectsubpt(r, r.min), t->b->chan, 0, 0); 14283e12c5d1SDavid du Colombier if(b == 0){ 14297dd7cddfSDavid du Colombier mesg("can't alloc image"); 14303e12c5d1SDavid du Colombier break; 14313e12c5d1SDavid du Colombier } 14323e12c5d1SDavid du Colombier } 14337dd7cddfSDavid du Colombier draw(b, b->r, display->white, nil, ZP); 14347dd7cddfSDavid du Colombier draw(b, b->r, t->b, nil, r.min); 14353e12c5d1SDavid du Colombier top = 100000; 14363e12c5d1SDavid du Colombier bot = 0; 14377dd7cddfSDavid du Colombier n = 2+((Dx(r)/8)*t->b->depth); 14383e12c5d1SDavid du Colombier for(j=0; j<b->r.max.y; j++){ 14393e12c5d1SDavid du Colombier memset(data, 0, n); 14407dd7cddfSDavid du Colombier unloadimage(b, Rect(b->r.min.x, j, b->r.max.x, j+1), data, sizeof data); 14413e12c5d1SDavid du Colombier zero = 1; 14423e12c5d1SDavid du Colombier for(k=0; k<n; k++) 14433e12c5d1SDavid du Colombier if(data[k]){ 14443e12c5d1SDavid du Colombier zero = 0; 14453e12c5d1SDavid du Colombier break; 14463e12c5d1SDavid du Colombier } 14473e12c5d1SDavid du Colombier if(!zero){ 14483e12c5d1SDavid du Colombier if(top > j) 14493e12c5d1SDavid du Colombier top = j; 14503e12c5d1SDavid du Colombier bot = j+1; 14513e12c5d1SDavid du Colombier } 14523e12c5d1SDavid du Colombier } 14533e12c5d1SDavid du Colombier if(top > j) 14543e12c5d1SDavid du Colombier top = 0; 14553e12c5d1SDavid du Colombier if(top!=fc->top || bot!=fc->bottom){ 14563e12c5d1SDavid du Colombier fc->top = top; 14573e12c5d1SDavid du Colombier fc->bottom = bot; 14583e12c5d1SDavid du Colombier for(nt=thing; nt; nt=nt->next) 14593e12c5d1SDavid du Colombier if(nt->parent==t && nt->c==i) 14603e12c5d1SDavid du Colombier text(nt); 14613e12c5d1SDavid du Colombier } 14623e12c5d1SDavid du Colombier } 14633e12c5d1SDavid du Colombier if(b) 14647dd7cddfSDavid du Colombier freeimage(b); 14653e12c5d1SDavid du Colombier } 14663e12c5d1SDavid du Colombier 14673e12c5d1SDavid du Colombier void 14683e12c5d1SDavid du Colombier twidpix(Thing *t, Point p, int set) 14693e12c5d1SDavid du Colombier { 14707dd7cddfSDavid du Colombier Image *b, *v; 14717dd7cddfSDavid du Colombier int c; 14723e12c5d1SDavid du Colombier 14733e12c5d1SDavid du Colombier b = t->b; 14743e12c5d1SDavid du Colombier if(!ptinrect(p, b->r)) 14753e12c5d1SDavid du Colombier return; 14767dd7cddfSDavid du Colombier if(set) 14777dd7cddfSDavid du Colombier c = but1val; 14787dd7cddfSDavid du Colombier else 14797dd7cddfSDavid du Colombier c = but2val; 14807dd7cddfSDavid du Colombier if(b->chan == GREY8) 14817dd7cddfSDavid du Colombier v = greyvalues[c]; 14827dd7cddfSDavid du Colombier else 14837dd7cddfSDavid du Colombier v = values[c]; 14847dd7cddfSDavid du Colombier draw(b, Rect(p.x, p.y, p.x+1, p.y+1), v, nil, ZP); 14853e12c5d1SDavid du Colombier p = screenpt(t, p); 14867dd7cddfSDavid du Colombier draw(screen, Rect(p.x, p.y, p.x+t->mag, p.y+t->mag), v, nil, ZP); 14873e12c5d1SDavid du Colombier } 14883e12c5d1SDavid du Colombier 14893e12c5d1SDavid du Colombier void 14903e12c5d1SDavid du Colombier twiddle(Thing *t) 14913e12c5d1SDavid du Colombier { 14923e12c5d1SDavid du Colombier int set; 14933e12c5d1SDavid du Colombier Point p, lastp; 14947dd7cddfSDavid du Colombier Image *b; 14953e12c5d1SDavid du Colombier Thing *nt; 14963e12c5d1SDavid du Colombier Rectangle mod; 14973e12c5d1SDavid du Colombier 14983e12c5d1SDavid du Colombier if(mouse.buttons!=1 && mouse.buttons!=2){ 14993e12c5d1SDavid du Colombier buttons(Up); 15003e12c5d1SDavid du Colombier return; 15013e12c5d1SDavid du Colombier } 15023e12c5d1SDavid du Colombier set = mouse.buttons==1; 15033e12c5d1SDavid du Colombier b = t->b; 15047dd7cddfSDavid du Colombier lastp = addpt(b->r.min, Pt(-1, -1)); 15057dd7cddfSDavid du Colombier mod = Rpt(addpt(b->r.max, Pt(1, 1)), lastp); 15063e12c5d1SDavid du Colombier while(mouse.buttons){ 15073e12c5d1SDavid du Colombier p = realpt(t, mouse.xy); 15083e12c5d1SDavid du Colombier if(!eqpt(p, lastp)){ 15093e12c5d1SDavid du Colombier lastp = p; 15103e12c5d1SDavid du Colombier if(ptinrect(p, b->r)){ 15113e12c5d1SDavid du Colombier for(nt=thing; nt; nt=nt->next) 15123e12c5d1SDavid du Colombier if(nt->parent==t->parent || nt==t->parent) 15133e12c5d1SDavid du Colombier twidpix(nt, p, set); 15143e12c5d1SDavid du Colombier if(t->parent) 15153e12c5d1SDavid du Colombier t->parent->mod = 1; 15163e12c5d1SDavid du Colombier else 15173e12c5d1SDavid du Colombier t->mod = 1; 15183e12c5d1SDavid du Colombier if(p.x < mod.min.x) 15193e12c5d1SDavid du Colombier mod.min.x = p.x; 15203e12c5d1SDavid du Colombier if(p.y < mod.min.y) 15213e12c5d1SDavid du Colombier mod.min.y = p.y; 15223e12c5d1SDavid du Colombier if(p.x >= mod.max.x) 15233e12c5d1SDavid du Colombier mod.max.x = p.x+1; 15243e12c5d1SDavid du Colombier if(p.y >= mod.max.y) 15253e12c5d1SDavid du Colombier mod.max.y = p.y+1; 15263e12c5d1SDavid du Colombier } 15273e12c5d1SDavid du Colombier } 15283e12c5d1SDavid du Colombier mouse = emouse(); 15293e12c5d1SDavid du Colombier } 15303e12c5d1SDavid du Colombier ckinfo(t, mod); 15313e12c5d1SDavid du Colombier } 15323e12c5d1SDavid du Colombier 15333e12c5d1SDavid du Colombier void 15343e12c5d1SDavid du Colombier select(void) 15353e12c5d1SDavid du Colombier { 15363e12c5d1SDavid du Colombier Thing *t; 15373e12c5d1SDavid du Colombier char line[128], buf[128]; 15383e12c5d1SDavid du Colombier Point p; 15393e12c5d1SDavid du Colombier 15403e12c5d1SDavid du Colombier if(ptinrect(mouse.xy, cntlr)){ 15413e12c5d1SDavid du Colombier scntl(line); 15423e12c5d1SDavid du Colombier if(atline(cntlr.min.x, mouse.xy, line, buf)){ 15433e12c5d1SDavid du Colombier if(mouse.buttons == 1) 15443e12c5d1SDavid du Colombier cntledit(buf); 15453e12c5d1SDavid du Colombier else 15463e12c5d1SDavid du Colombier buttons(Up); 15473e12c5d1SDavid du Colombier return; 15483e12c5d1SDavid du Colombier } 15493e12c5d1SDavid du Colombier return; 15503e12c5d1SDavid du Colombier } 15513e12c5d1SDavid du Colombier for(t=thing; t; t=t->next){ 15523e12c5d1SDavid du Colombier if(attext(t, mouse.xy, buf)){ 15533e12c5d1SDavid du Colombier if(mouse.buttons == 1) 15543e12c5d1SDavid du Colombier textedit(t, buf); 15553e12c5d1SDavid du Colombier else 15563e12c5d1SDavid du Colombier buttons(Up); 15573e12c5d1SDavid du Colombier return; 15583e12c5d1SDavid du Colombier } 15593e12c5d1SDavid du Colombier if(ptinrect(mouse.xy, t->r)){ 15603e12c5d1SDavid du Colombier if(t->parent == 0){ 15613e12c5d1SDavid du Colombier if(mouse.buttons == 1){ 15623e12c5d1SDavid du Colombier p = mouse.xy; 15633e12c5d1SDavid du Colombier buttons(Up); 15643e12c5d1SDavid du Colombier openedit(t, p, -1); 15653e12c5d1SDavid du Colombier }else 15663e12c5d1SDavid du Colombier buttons(Up); 15673e12c5d1SDavid du Colombier return; 15683e12c5d1SDavid du Colombier } 15693e12c5d1SDavid du Colombier twiddle(t); 15703e12c5d1SDavid du Colombier return; 15713e12c5d1SDavid du Colombier } 15723e12c5d1SDavid du Colombier } 15733e12c5d1SDavid du Colombier } 15743e12c5d1SDavid du Colombier 15753e12c5d1SDavid du Colombier void 15763e12c5d1SDavid du Colombier twrite(Thing *t) 15773e12c5d1SDavid du Colombier { 15783e12c5d1SDavid du Colombier int i, j, x, y, fd, ws, ld; 15793e12c5d1SDavid du Colombier Biobuf buf; 15803e12c5d1SDavid du Colombier Rectangle r; 15813e12c5d1SDavid du Colombier 15823e12c5d1SDavid du Colombier if(t->parent) 15833e12c5d1SDavid du Colombier t = t->parent; 15847dd7cddfSDavid du Colombier esetcursor(&busy); 15853e12c5d1SDavid du Colombier fd = create(t->name, OWRITE, 0666); 15863e12c5d1SDavid du Colombier if(fd < 0){ 15873e12c5d1SDavid du Colombier mesg("can't write %s: %r", t->name); 15883e12c5d1SDavid du Colombier return; 15893e12c5d1SDavid du Colombier } 15909a747e4fSDavid du Colombier if(t->face && t->b->depth <= 4){ 15913e12c5d1SDavid du Colombier r = t->b->r; 15927dd7cddfSDavid du Colombier ld = log2[t->b->depth]; 15933e12c5d1SDavid du Colombier /* This heuristic reflects peculiarly different formats */ 15943e12c5d1SDavid du Colombier ws = 4; 15957dd7cddfSDavid du Colombier if(t->face == 2) /* cursor file */ 15963e12c5d1SDavid du Colombier ws = 1; 15973e12c5d1SDavid du Colombier else if(Dx(r)<32 || ld==0) 15983e12c5d1SDavid du Colombier ws = 2; 15993e12c5d1SDavid du Colombier Binit(&buf, fd, OWRITE); 16007dd7cddfSDavid du Colombier if(t->face == CURSOR) 16017dd7cddfSDavid du Colombier Bprint(&buf, "{"); 16023e12c5d1SDavid du Colombier for(y=r.min.y; y<r.max.y; y++){ 16037dd7cddfSDavid du Colombier unloadimage(t->b, Rect(r.min.x, y, r.max.x, y+1), data, sizeof data); 16043e12c5d1SDavid du Colombier j = 0; 16053e12c5d1SDavid du Colombier for(x=r.min.x; x<r.max.x; j+=ws,x+=ws*8>>ld){ 16063e12c5d1SDavid du Colombier Bprint(&buf, "0x"); 16073e12c5d1SDavid du Colombier for(i=0; i<ws; i++) 16083e12c5d1SDavid du Colombier Bprint(&buf, "%.2x", data[i+j]); 16093e12c5d1SDavid du Colombier Bprint(&buf, ", "); 16103e12c5d1SDavid du Colombier } 16117dd7cddfSDavid du Colombier if(t->face == CURSOR){ 16127dd7cddfSDavid du Colombier switch(y){ 16137dd7cddfSDavid du Colombier case 3: case 7: case 11: case 19: case 23: case 27: 16147dd7cddfSDavid du Colombier Bprint(&buf, "\n "); 16157dd7cddfSDavid du Colombier break; 16167dd7cddfSDavid du Colombier case 15: 16177dd7cddfSDavid du Colombier Bprint(&buf, "},\n{"); 16187dd7cddfSDavid du Colombier break; 16197dd7cddfSDavid du Colombier case 31: 16207dd7cddfSDavid du Colombier Bprint(&buf, "}\n"); 16217dd7cddfSDavid du Colombier break; 16227dd7cddfSDavid du Colombier } 16237dd7cddfSDavid du Colombier }else 16243e12c5d1SDavid du Colombier Bprint(&buf, "\n"); 16253e12c5d1SDavid du Colombier } 1626219b2ee8SDavid du Colombier Bterm(&buf); 16277dd7cddfSDavid du Colombier }else 16287dd7cddfSDavid du Colombier if(writeimage(fd, t->b, 0)<0 || (t->s && writesubfont(fd, t->s)<0)){ 16297dd7cddfSDavid du Colombier close(fd); 16307dd7cddfSDavid du Colombier mesg("can't write %s: %r", t->name); 16313e12c5d1SDavid du Colombier } 16323e12c5d1SDavid du Colombier t->mod = 0; 16333e12c5d1SDavid du Colombier close(fd); 16343e12c5d1SDavid du Colombier mesg("wrote %s", t->name); 16353e12c5d1SDavid du Colombier } 16363e12c5d1SDavid du Colombier 16373e12c5d1SDavid du Colombier void 16387dd7cddfSDavid du Colombier tpixels(void) 16397dd7cddfSDavid du Colombier { 16407dd7cddfSDavid du Colombier Thing *t; 16417dd7cddfSDavid du Colombier Point p, lastp; 16427dd7cddfSDavid du Colombier 16437dd7cddfSDavid du Colombier esetcursor(&pixel); 16447dd7cddfSDavid du Colombier for(;;){ 16457dd7cddfSDavid du Colombier buttons(Down); 16467dd7cddfSDavid du Colombier if(mouse.buttons != 4) 16477dd7cddfSDavid du Colombier break; 16487dd7cddfSDavid du Colombier for(t=thing; t; t=t->next){ 16497dd7cddfSDavid du Colombier lastp = Pt(-1, -1); 16507dd7cddfSDavid du Colombier if(ptinrect(mouse.xy, t->r)){ 16517dd7cddfSDavid du Colombier while(ptinrect(mouse.xy, t->r) && mouse.buttons==4){ 16527dd7cddfSDavid du Colombier p = realpt(t, mouse.xy); 16537dd7cddfSDavid du Colombier if(!eqpt(p, lastp)){ 16547dd7cddfSDavid du Colombier if(p.y != lastp.y) 16557dd7cddfSDavid du Colombier unloadimage(t->b, Rect(t->b->r.min.x, p.y, t->b->r.max.x, p.y+1), data, sizeof data); 16567dd7cddfSDavid du Colombier mesg("[%d,%d] = %d=0x%ux", p.x, p.y, value(t->b, p.x), value(t->b, p.x)); 16577dd7cddfSDavid du Colombier lastp = p; 16587dd7cddfSDavid du Colombier } 16597dd7cddfSDavid du Colombier mouse = emouse(); 16607dd7cddfSDavid du Colombier } 16617dd7cddfSDavid du Colombier goto Continue; 16627dd7cddfSDavid du Colombier } 16637dd7cddfSDavid du Colombier } 16647dd7cddfSDavid du Colombier mouse = emouse(); 16657dd7cddfSDavid du Colombier Continue:; 16667dd7cddfSDavid du Colombier } 16677dd7cddfSDavid du Colombier buttons(Up); 16687dd7cddfSDavid du Colombier esetcursor(0); 16697dd7cddfSDavid du Colombier } 16707dd7cddfSDavid du Colombier 16717dd7cddfSDavid du Colombier void 16723e12c5d1SDavid du Colombier tclose1(Thing *t) 16733e12c5d1SDavid du Colombier { 16743e12c5d1SDavid du Colombier Thing *nt; 16753e12c5d1SDavid du Colombier 16763e12c5d1SDavid du Colombier if(t == thing) 16773e12c5d1SDavid du Colombier thing = t->next; 16783e12c5d1SDavid du Colombier else{ 16793e12c5d1SDavid du Colombier for(nt=thing; nt->next!=t; nt=nt->next) 16803e12c5d1SDavid du Colombier ; 16813e12c5d1SDavid du Colombier nt->next = t->next; 16823e12c5d1SDavid du Colombier } 16833e12c5d1SDavid du Colombier do 16843e12c5d1SDavid du Colombier for(nt=thing; nt; nt=nt->next) 16853e12c5d1SDavid du Colombier if(nt->parent == t){ 16863e12c5d1SDavid du Colombier tclose1(nt); 16873e12c5d1SDavid du Colombier break; 16883e12c5d1SDavid du Colombier } 16893e12c5d1SDavid du Colombier while(nt); 16903e12c5d1SDavid du Colombier if(t->s) 16917dd7cddfSDavid du Colombier freesubfont(t->s); 16927dd7cddfSDavid du Colombier else 16937dd7cddfSDavid du Colombier freeimage(t->b); 16943e12c5d1SDavid du Colombier free(t->name); 16953e12c5d1SDavid du Colombier free(t); 16963e12c5d1SDavid du Colombier } 16973e12c5d1SDavid du Colombier 16983e12c5d1SDavid du Colombier void 16993e12c5d1SDavid du Colombier tclose(Thing *t) 17003e12c5d1SDavid du Colombier { 17013e12c5d1SDavid du Colombier Thing *ct; 17023e12c5d1SDavid du Colombier 17033e12c5d1SDavid du Colombier if(t->mod){ 17043e12c5d1SDavid du Colombier mesg("%s modified", t->name); 17053e12c5d1SDavid du Colombier t->mod = 0; 17063e12c5d1SDavid du Colombier return; 17073e12c5d1SDavid du Colombier } 17083e12c5d1SDavid du Colombier /* fiddle to save redrawing unmoved things */ 17093e12c5d1SDavid du Colombier if(t == thing) 17103e12c5d1SDavid du Colombier ct = 0; 17113e12c5d1SDavid du Colombier else 17123e12c5d1SDavid du Colombier for(ct=thing; ct; ct=ct->next) 17133e12c5d1SDavid du Colombier if(ct->next==t || ct->next->parent==t) 17143e12c5d1SDavid du Colombier break; 17153e12c5d1SDavid du Colombier tclose1(t); 17163e12c5d1SDavid du Colombier if(ct) 17173e12c5d1SDavid du Colombier ct = ct->next; 17183e12c5d1SDavid du Colombier else 17193e12c5d1SDavid du Colombier ct = thing; 17203e12c5d1SDavid du Colombier redraw(ct); 17213e12c5d1SDavid du Colombier } 17223e12c5d1SDavid du Colombier 17233e12c5d1SDavid du Colombier void 17243e12c5d1SDavid du Colombier tread(Thing *t) 17253e12c5d1SDavid du Colombier { 17263e12c5d1SDavid du Colombier Thing *nt, *new; 17273e12c5d1SDavid du Colombier Fontchar *i; 17283e12c5d1SDavid du Colombier Rectangle r; 17293e12c5d1SDavid du Colombier int nclosed; 17303e12c5d1SDavid du Colombier 17313e12c5d1SDavid du Colombier if(t->parent) 17323e12c5d1SDavid du Colombier t = t->parent; 17333e12c5d1SDavid du Colombier new = tget(t->name); 17343e12c5d1SDavid du Colombier if(new == 0) 17353e12c5d1SDavid du Colombier return; 17363e12c5d1SDavid du Colombier nclosed = 0; 17373e12c5d1SDavid du Colombier again: 17383e12c5d1SDavid du Colombier for(nt=thing; nt; nt=nt->next) 17393e12c5d1SDavid du Colombier if(nt->parent == t){ 17403e12c5d1SDavid du Colombier if(!rectinrect(nt->b->r, new->b->r) 17417dd7cddfSDavid du Colombier || new->b->depth!=nt->b->depth){ 17423e12c5d1SDavid du Colombier closeit: 17433e12c5d1SDavid du Colombier nclosed++; 17443e12c5d1SDavid du Colombier nt->parent = 0; 17453e12c5d1SDavid du Colombier tclose1(nt); 17463e12c5d1SDavid du Colombier goto again; 17473e12c5d1SDavid du Colombier } 17483e12c5d1SDavid du Colombier if((t->s==0) != (new->s==0)) 17493e12c5d1SDavid du Colombier goto closeit; 17503e12c5d1SDavid du Colombier if((t->face==0) != (new->face==0)) 17513e12c5d1SDavid du Colombier goto closeit; 17523e12c5d1SDavid du Colombier if(t->s){ /* check same char */ 17533e12c5d1SDavid du Colombier if(nt->c >= new->s->n) 17543e12c5d1SDavid du Colombier goto closeit; 17553e12c5d1SDavid du Colombier i = &new->s->info[nt->c]; 17563e12c5d1SDavid du Colombier r.min.x = i[0].x; 17573e12c5d1SDavid du Colombier r.max.x = i[1].x; 17583e12c5d1SDavid du Colombier r.min.y = new->b->r.min.y; 17593e12c5d1SDavid du Colombier r.max.y = new->b->r.max.y; 17603e12c5d1SDavid du Colombier if(!eqrect(r, nt->b->r)) 17613e12c5d1SDavid du Colombier goto closeit; 17623e12c5d1SDavid du Colombier } 17633e12c5d1SDavid du Colombier nt->parent = new; 17647dd7cddfSDavid du Colombier draw(nt->b, nt->b->r, new->b, nil, nt->b->r.min); 17653e12c5d1SDavid du Colombier } 17663e12c5d1SDavid du Colombier new->next = t->next; 17673e12c5d1SDavid du Colombier if(t == thing) 17683e12c5d1SDavid du Colombier thing = new; 17693e12c5d1SDavid du Colombier else{ 17703e12c5d1SDavid du Colombier for(nt=thing; nt->next!=t; nt=nt->next) 17713e12c5d1SDavid du Colombier ; 17723e12c5d1SDavid du Colombier nt->next = new; 17733e12c5d1SDavid du Colombier } 17743e12c5d1SDavid du Colombier if(t->s) 17757dd7cddfSDavid du Colombier freesubfont(t->s); 17767dd7cddfSDavid du Colombier else 17777dd7cddfSDavid du Colombier freeimage(t->b); 17783e12c5d1SDavid du Colombier free(t->name); 17793e12c5d1SDavid du Colombier free(t); 17803e12c5d1SDavid du Colombier for(nt=thing; nt; nt=nt->next) 17813e12c5d1SDavid du Colombier if(nt==new || nt->parent==new) 17823e12c5d1SDavid du Colombier if(nclosed == 0) 17837dd7cddfSDavid du Colombier drawthing(nt, 0); /* can draw in place */ 17843e12c5d1SDavid du Colombier else{ 17853e12c5d1SDavid du Colombier redraw(nt); /* must redraw all below */ 17863e12c5d1SDavid du Colombier break; 17873e12c5d1SDavid du Colombier } 17883e12c5d1SDavid du Colombier } 17893e12c5d1SDavid du Colombier 17903e12c5d1SDavid du Colombier void 17913e12c5d1SDavid du Colombier tchar(Thing *t) 17923e12c5d1SDavid du Colombier { 1793219b2ee8SDavid du Colombier char buf[256], *p; 17943e12c5d1SDavid du Colombier Rune r; 1795219b2ee8SDavid du Colombier ulong c, d; 17963e12c5d1SDavid du Colombier 17973e12c5d1SDavid du Colombier if(t->s == 0){ 17987dd7cddfSDavid du Colombier t = t->parent; 17997dd7cddfSDavid du Colombier if(t==0 || t->s==0){ 18003e12c5d1SDavid du Colombier mesg("not a subfont"); 18013e12c5d1SDavid du Colombier return; 18023e12c5d1SDavid du Colombier } 18037dd7cddfSDavid du Colombier } 1804219b2ee8SDavid du Colombier if(type(buf, "char (hex or character or hex-hex)") == 0) 18053e12c5d1SDavid du Colombier return; 18063e12c5d1SDavid du Colombier if(utflen(buf) == 1){ 18073e12c5d1SDavid du Colombier chartorune(&r, buf); 18083e12c5d1SDavid du Colombier c = r; 1809219b2ee8SDavid du Colombier d = r; 18103e12c5d1SDavid du Colombier }else{ 18113e12c5d1SDavid du Colombier if(!strchr(hex, buf[0])){ 18123e12c5d1SDavid du Colombier mesg("illegal hex character"); 18133e12c5d1SDavid du Colombier return; 18143e12c5d1SDavid du Colombier } 18153e12c5d1SDavid du Colombier c = strtoul(buf, 0, 16); 1816219b2ee8SDavid du Colombier d = c; 1817219b2ee8SDavid du Colombier p = utfrune(buf, '-'); 1818219b2ee8SDavid du Colombier if(p){ 1819219b2ee8SDavid du Colombier d = strtoul(p+1, 0, 16); 1820219b2ee8SDavid du Colombier if(d < c){ 1821219b2ee8SDavid du Colombier mesg("invalid range"); 1822219b2ee8SDavid du Colombier return; 1823219b2ee8SDavid du Colombier } 1824219b2ee8SDavid du Colombier } 18253e12c5d1SDavid du Colombier } 18263e12c5d1SDavid du Colombier c -= t->off; 1827219b2ee8SDavid du Colombier d -= t->off; 1828219b2ee8SDavid du Colombier while(c <= d){ 18293e12c5d1SDavid du Colombier if(c<0 || c>=t->s->n){ 18303e12c5d1SDavid du Colombier mesg("0x%lux not in font %s", c+t->off, t->name); 18313e12c5d1SDavid du Colombier return; 18323e12c5d1SDavid du Colombier } 18333e12c5d1SDavid du Colombier openedit(t, Pt(0, 0), c); 1834219b2ee8SDavid du Colombier c++; 1835219b2ee8SDavid du Colombier } 18363e12c5d1SDavid du Colombier } 18373e12c5d1SDavid du Colombier 18383e12c5d1SDavid du Colombier void 18393e12c5d1SDavid du Colombier apply(void (*f)(Thing*)) 18403e12c5d1SDavid du Colombier { 18413e12c5d1SDavid du Colombier Thing *t; 18423e12c5d1SDavid du Colombier 18437dd7cddfSDavid du Colombier esetcursor(&sight); 18443e12c5d1SDavid du Colombier buttons(Down); 18453e12c5d1SDavid du Colombier if(mouse.buttons == 4) 18463e12c5d1SDavid du Colombier for(t=thing; t; t=t->next) 18473e12c5d1SDavid du Colombier if(ptinrect(mouse.xy, t->er)){ 18483e12c5d1SDavid du Colombier buttons(Up); 18493e12c5d1SDavid du Colombier f(t); 18503e12c5d1SDavid du Colombier break; 18513e12c5d1SDavid du Colombier } 18523e12c5d1SDavid du Colombier buttons(Up); 18537dd7cddfSDavid du Colombier esetcursor(0); 18547dd7cddfSDavid du Colombier } 18557dd7cddfSDavid du Colombier 18567dd7cddfSDavid du Colombier int 18577dd7cddfSDavid du Colombier complement(Image *t) 18587dd7cddfSDavid du Colombier { 18597dd7cddfSDavid du Colombier int i, n; 18607dd7cddfSDavid du Colombier uchar *buf; 18617dd7cddfSDavid du Colombier 18627dd7cddfSDavid du Colombier n = Dy(t->r)*bytesperline(t->r, t->depth); 18637dd7cddfSDavid du Colombier buf = malloc(n); 18647dd7cddfSDavid du Colombier if(buf == 0) 18657dd7cddfSDavid du Colombier return 0; 18667dd7cddfSDavid du Colombier unloadimage(t, t->r, buf, n); 18677dd7cddfSDavid du Colombier for(i=0; i<n; i++) 18687dd7cddfSDavid du Colombier buf[i] = ~buf[i]; 18697dd7cddfSDavid du Colombier loadimage(t, t->r, buf, n); 18707dd7cddfSDavid du Colombier free(buf); 18717dd7cddfSDavid du Colombier return 1; 18723e12c5d1SDavid du Colombier } 18733e12c5d1SDavid du Colombier 18743e12c5d1SDavid du Colombier void 18753e12c5d1SDavid du Colombier copy(void) 18763e12c5d1SDavid du Colombier { 18773e12c5d1SDavid du Colombier Thing *st, *dt, *nt; 18783e12c5d1SDavid du Colombier Rectangle sr, dr, fr; 18797dd7cddfSDavid du Colombier Image *tmp; 18803e12c5d1SDavid du Colombier Point p1, p2; 18813e12c5d1SDavid du Colombier int but, up; 18823e12c5d1SDavid du Colombier 18837dd7cddfSDavid du Colombier if(!sweep(3, &sr)) 18843e12c5d1SDavid du Colombier return; 18853e12c5d1SDavid du Colombier for(st=thing; st; st=st->next) 18863e12c5d1SDavid du Colombier if(rectXrect(sr, st->r)) 18873e12c5d1SDavid du Colombier break; 18883e12c5d1SDavid du Colombier if(st == 0) 18893e12c5d1SDavid du Colombier return; 18903e12c5d1SDavid du Colombier /* click gives full rectangle */ 18913e12c5d1SDavid du Colombier if(Dx(sr)<4 && Dy(sr)<4) 18923e12c5d1SDavid du Colombier sr = st->r; 18933e12c5d1SDavid du Colombier rectclip(&sr, st->r); 18943e12c5d1SDavid du Colombier p1 = realpt(st, sr.min); 18953e12c5d1SDavid du Colombier p2 = realpt(st, Pt(sr.min.x, sr.max.y)); 189680ee5cbfSDavid du Colombier up = 0; 18973e12c5d1SDavid du Colombier if(p1.x != p2.x){ /* swept across a fold */ 18983e12c5d1SDavid du Colombier onafold: 18993e12c5d1SDavid du Colombier mesg("sweep spans a fold"); 190080ee5cbfSDavid du Colombier goto Return; 19013e12c5d1SDavid du Colombier } 19023e12c5d1SDavid du Colombier p2 = realpt(st, sr.max); 19033e12c5d1SDavid du Colombier sr.min = p1; 19043e12c5d1SDavid du Colombier sr.max = p2; 19053e12c5d1SDavid du Colombier fr.min = screenpt(st, sr.min); 19063e12c5d1SDavid du Colombier fr.max = screenpt(st, sr.max); 19077dd7cddfSDavid du Colombier p1 = subpt(p2, p1); /* diagonal */ 19087dd7cddfSDavid du Colombier if(p1.x==0 || p1.y==0) 19093e12c5d1SDavid du Colombier return; 19107dd7cddfSDavid du Colombier border(screen, fr, -1, values[Blue], ZP); 19117dd7cddfSDavid du Colombier esetcursor(&box); 19123e12c5d1SDavid du Colombier for(; mouse.buttons==0; mouse=emouse()){ 19133e12c5d1SDavid du Colombier for(dt=thing; dt; dt=dt->next) 19143e12c5d1SDavid du Colombier if(ptinrect(mouse.xy, dt->er)) 19153e12c5d1SDavid du Colombier break; 19163e12c5d1SDavid du Colombier if(up) 19177dd7cddfSDavid du Colombier edrawgetrect(insetrect(dr, -Borderwidth), 0); 19183e12c5d1SDavid du Colombier up = 0; 19193e12c5d1SDavid du Colombier if(dt == 0) 19203e12c5d1SDavid du Colombier continue; 19213e12c5d1SDavid du Colombier dr.max = screenpt(dt, realpt(dt, mouse.xy)); 19227dd7cddfSDavid du Colombier dr.min = subpt(dr.max, mulpt(p1, dt->mag)); 19233e12c5d1SDavid du Colombier if(!rectXrect(dr, dt->r)) 19243e12c5d1SDavid du Colombier continue; 19257dd7cddfSDavid du Colombier edrawgetrect(insetrect(dr, -Borderwidth), 1); 19263e12c5d1SDavid du Colombier up = 1; 19273e12c5d1SDavid du Colombier } 19283e12c5d1SDavid du Colombier /* if up==1, we had a hit */ 19297dd7cddfSDavid du Colombier esetcursor(0); 19303e12c5d1SDavid du Colombier if(up) 19317dd7cddfSDavid du Colombier edrawgetrect(insetrect(dr, -Borderwidth), 0); 19323e12c5d1SDavid du Colombier but = mouse.buttons; 19333e12c5d1SDavid du Colombier buttons(Up); 19343e12c5d1SDavid du Colombier if(!up || but!=4) 19357dd7cddfSDavid du Colombier goto Return; 19363e12c5d1SDavid du Colombier dt = 0; 19373e12c5d1SDavid du Colombier for(nt=thing; nt; nt=nt->next) 19383e12c5d1SDavid du Colombier if(rectXrect(dr, nt->r)){ 19393e12c5d1SDavid du Colombier if(dt){ 19403e12c5d1SDavid du Colombier mesg("ambiguous sweep"); 19413e12c5d1SDavid du Colombier return; 19423e12c5d1SDavid du Colombier } 19433e12c5d1SDavid du Colombier dt = nt; 19443e12c5d1SDavid du Colombier } 19453e12c5d1SDavid du Colombier if(dt == 0) 19467dd7cddfSDavid du Colombier goto Return; 19473e12c5d1SDavid du Colombier p1 = realpt(dt, dr.min); 19483e12c5d1SDavid du Colombier p2 = realpt(dt, Pt(dr.min.x, dr.max.y)); 19493e12c5d1SDavid du Colombier if(p1.x != p2.x) 19503e12c5d1SDavid du Colombier goto onafold; 19513e12c5d1SDavid du Colombier p2 = realpt(dt, dr.max); 19523e12c5d1SDavid du Colombier dr.min = p1; 19533e12c5d1SDavid du Colombier dr.max = p2; 19547dd7cddfSDavid du Colombier 19557dd7cddfSDavid du Colombier if(invert){ 19567dd7cddfSDavid du Colombier tmp = allocimage(display, dr, dt->b->chan, 0, 255); 19577dd7cddfSDavid du Colombier if(tmp == 0){ 19587dd7cddfSDavid du Colombier nomem: 19597dd7cddfSDavid du Colombier mesg("can't allocate temporary"); 19607dd7cddfSDavid du Colombier goto Return; 19617dd7cddfSDavid du Colombier } 19627dd7cddfSDavid du Colombier draw(tmp, dr, st->b, nil, sr.min); 19637dd7cddfSDavid du Colombier if(!complement(tmp)) 19647dd7cddfSDavid du Colombier goto nomem; 19657dd7cddfSDavid du Colombier draw(dt->b, dr, tmp, nil, dr.min); 19667dd7cddfSDavid du Colombier freeimage(tmp); 19677dd7cddfSDavid du Colombier }else 19687dd7cddfSDavid du Colombier draw(dt->b, dr, st->b, nil, sr.min); 19693e12c5d1SDavid du Colombier if(dt->parent){ 19707dd7cddfSDavid du Colombier draw(dt->parent->b, dr, dt->b, nil, dr.min); 19713e12c5d1SDavid du Colombier dt = dt->parent; 19723e12c5d1SDavid du Colombier } 19737dd7cddfSDavid du Colombier drawthing(dt, 0); 19743e12c5d1SDavid du Colombier for(nt=thing; nt; nt=nt->next) 19753e12c5d1SDavid du Colombier if(nt->parent==dt && rectXrect(dr, nt->b->r)){ 19767dd7cddfSDavid du Colombier draw(nt->b, dr, dt->b, nil, dr.min); 19777dd7cddfSDavid du Colombier drawthing(nt, 0); 19783e12c5d1SDavid du Colombier } 19793e12c5d1SDavid du Colombier ckinfo(dt, dr); 19803e12c5d1SDavid du Colombier dt->mod = 1; 19817dd7cddfSDavid du Colombier 19827dd7cddfSDavid du Colombier Return: 19837dd7cddfSDavid du Colombier /* clear blue box */ 19847dd7cddfSDavid du Colombier drawthing(st, 0); 19853e12c5d1SDavid du Colombier } 19863e12c5d1SDavid du Colombier 19873e12c5d1SDavid du Colombier void 19883e12c5d1SDavid du Colombier menu(void) 19893e12c5d1SDavid du Colombier { 19903e12c5d1SDavid du Colombier Thing *t; 19913e12c5d1SDavid du Colombier char *mod; 19923e12c5d1SDavid du Colombier int sel; 19933e12c5d1SDavid du Colombier char buf[256]; 19943e12c5d1SDavid du Colombier 19957dd7cddfSDavid du Colombier sel = emenuhit(3, &mouse, &menu3); 19963e12c5d1SDavid du Colombier switch(sel){ 19973e12c5d1SDavid du Colombier case Mopen: 19983e12c5d1SDavid du Colombier if(type(buf, "file")){ 19993e12c5d1SDavid du Colombier t = tget(buf); 20003e12c5d1SDavid du Colombier if(t) 20017dd7cddfSDavid du Colombier drawthing(t, 1); 20023e12c5d1SDavid du Colombier } 20033e12c5d1SDavid du Colombier break; 20043e12c5d1SDavid du Colombier case Mwrite: 20053e12c5d1SDavid du Colombier apply(twrite); 20063e12c5d1SDavid du Colombier break; 20073e12c5d1SDavid du Colombier case Mread: 20083e12c5d1SDavid du Colombier apply(tread); 20093e12c5d1SDavid du Colombier break; 20103e12c5d1SDavid du Colombier case Mchar: 20113e12c5d1SDavid du Colombier apply(tchar); 20123e12c5d1SDavid du Colombier break; 20133e12c5d1SDavid du Colombier case Mcopy: 20143e12c5d1SDavid du Colombier copy(); 20153e12c5d1SDavid du Colombier break; 20167dd7cddfSDavid du Colombier case Mpixels: 20177dd7cddfSDavid du Colombier tpixels(); 20187dd7cddfSDavid du Colombier break; 20193e12c5d1SDavid du Colombier case Mclose: 20203e12c5d1SDavid du Colombier apply(tclose); 20213e12c5d1SDavid du Colombier break; 20223e12c5d1SDavid du Colombier case Mexit: 20233e12c5d1SDavid du Colombier mod = 0; 20243e12c5d1SDavid du Colombier for(t=thing; t; t=t->next) 20253e12c5d1SDavid du Colombier if(t->mod){ 20263e12c5d1SDavid du Colombier mod = t->name; 20273e12c5d1SDavid du Colombier t->mod = 0; 20283e12c5d1SDavid du Colombier } 20293e12c5d1SDavid du Colombier if(mod){ 20303e12c5d1SDavid du Colombier mesg("%s modified", mod); 20313e12c5d1SDavid du Colombier break; 20323e12c5d1SDavid du Colombier } 20337dd7cddfSDavid du Colombier esetcursor(&skull); 20343e12c5d1SDavid du Colombier buttons(Down); 20353e12c5d1SDavid du Colombier if(mouse.buttons == 4){ 20363e12c5d1SDavid du Colombier buttons(Up); 20373e12c5d1SDavid du Colombier exits(0); 20383e12c5d1SDavid du Colombier } 20393e12c5d1SDavid du Colombier buttons(Up); 20407dd7cddfSDavid du Colombier esetcursor(0); 20413e12c5d1SDavid du Colombier break; 20423e12c5d1SDavid du Colombier } 20433e12c5d1SDavid du Colombier } 2044