13e12c5d1SDavid du Colombier #include <u.h> 23e12c5d1SDavid du Colombier #include <libc.h> 33e12c5d1SDavid du Colombier #include <libg.h> 43e12c5d1SDavid du Colombier #include <bio.h> 53e12c5d1SDavid du Colombier 63e12c5d1SDavid du Colombier /* 73e12c5d1SDavid du Colombier * This program keeps the system's and the application's bitmap and 83e12c5d1SDavid du Colombier * subfont structures consistent, but that is really not necessary; 93e12c5d1SDavid du Colombier * in fact it isn't even necessary to hold the subfonts in the system 103e12c5d1SDavid du Colombier * at all. Doing it this way makes it easy to do I/O on subfonts. 113e12c5d1SDavid du Colombier * Even so, edits to individual character's Fontchars are not passed 123e12c5d1SDavid du Colombier * to the system. 133e12c5d1SDavid du Colombier */ 143e12c5d1SDavid du Colombier 153e12c5d1SDavid du Colombier typedef struct Thing Thing; 163e12c5d1SDavid du Colombier 173e12c5d1SDavid du Colombier struct Thing 183e12c5d1SDavid du Colombier { 193e12c5d1SDavid du Colombier Bitmap *b; 203e12c5d1SDavid du Colombier Subfont *s; 213e12c5d1SDavid du Colombier char *name; /* file name */ 223e12c5d1SDavid du Colombier int face; /* is 48x48 face file or cursor file*/ 233e12c5d1SDavid du Colombier Rectangle r; /* drawing region */ 243e12c5d1SDavid du Colombier Rectangle tr; /* text region */ 253e12c5d1SDavid du Colombier Rectangle er; /* entire region */ 263e12c5d1SDavid du Colombier long c; /* character number in subfont */ 273e12c5d1SDavid du Colombier int mod; /* modified */ 283e12c5d1SDavid du Colombier int mag; /* magnification */ 293e12c5d1SDavid du Colombier Rune off; /* offset for subfont indices */ 303e12c5d1SDavid du Colombier Thing *parent; /* thing of which i'm an edit */ 313e12c5d1SDavid du Colombier Thing *next; 323e12c5d1SDavid du Colombier }; 333e12c5d1SDavid du Colombier 343e12c5d1SDavid du Colombier enum 353e12c5d1SDavid du Colombier { 363e12c5d1SDavid du Colombier Border = 1, 373e12c5d1SDavid du Colombier Up = 1, 383e12c5d1SDavid du Colombier Down = 0, 393e12c5d1SDavid du Colombier Mag = 4, 403e12c5d1SDavid du Colombier Maxmag = 10, 413e12c5d1SDavid du Colombier }; 423e12c5d1SDavid du Colombier 433e12c5d1SDavid du Colombier enum 443e12c5d1SDavid du Colombier { 453e12c5d1SDavid du Colombier Mopen, 463e12c5d1SDavid du Colombier Mread, 473e12c5d1SDavid du Colombier Mwrite, 483e12c5d1SDavid du Colombier Mcopy, 493e12c5d1SDavid du Colombier Mchar, 503e12c5d1SDavid du Colombier Mclose, 513e12c5d1SDavid du Colombier Mexit, 523e12c5d1SDavid du Colombier }; 533e12c5d1SDavid du Colombier 543e12c5d1SDavid du Colombier 553e12c5d1SDavid du Colombier char *menu3str[] = { 563e12c5d1SDavid du Colombier [Mopen] "open", 573e12c5d1SDavid du Colombier [Mread] "read", 583e12c5d1SDavid du Colombier [Mwrite] "write", 593e12c5d1SDavid du Colombier [Mcopy] "copy", 603e12c5d1SDavid du Colombier [Mchar] "char", 613e12c5d1SDavid du Colombier [Mclose] "close", 623e12c5d1SDavid du Colombier [Mexit] "exit", 633e12c5d1SDavid du Colombier 0, 643e12c5d1SDavid du Colombier }; 653e12c5d1SDavid du Colombier 663e12c5d1SDavid du Colombier Menu menu3 = { 673e12c5d1SDavid du Colombier menu3str 683e12c5d1SDavid du Colombier }; 693e12c5d1SDavid du Colombier 703e12c5d1SDavid du Colombier Cursor sweep0 = { 713e12c5d1SDavid du Colombier {-7, -7}, 723e12c5d1SDavid du Colombier {0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 733e12c5d1SDavid du Colombier 0x03, 0xC0, 0x03, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 743e12c5d1SDavid du Colombier 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xC0, 0x03, 0xC0, 753e12c5d1SDavid du Colombier 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0}, 763e12c5d1SDavid du Colombier {0x00, 0x00, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 773e12c5d1SDavid du Colombier 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x7F, 0xFE, 783e12c5d1SDavid du Colombier 0x7F, 0xFE, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 793e12c5d1SDavid du Colombier 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x00, 0x00} 803e12c5d1SDavid du Colombier }; 813e12c5d1SDavid du Colombier 823e12c5d1SDavid du Colombier Cursor box = { 833e12c5d1SDavid du Colombier {-7, -7}, 843e12c5d1SDavid du Colombier {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 853e12c5d1SDavid du Colombier 0xFF, 0xFF, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 863e12c5d1SDavid du Colombier 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xFF, 0xFF, 873e12c5d1SDavid du Colombier 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, 883e12c5d1SDavid du Colombier {0x00, 0x00, 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE, 893e12c5d1SDavid du Colombier 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 903e12c5d1SDavid du Colombier 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 913e12c5d1SDavid du Colombier 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE, 0x00, 0x00} 923e12c5d1SDavid du Colombier }; 933e12c5d1SDavid du Colombier 943e12c5d1SDavid du Colombier Cursor sight = { 953e12c5d1SDavid du Colombier {-7, -7}, 963e12c5d1SDavid du Colombier {0x1F, 0xF8, 0x3F, 0xFC, 0x7F, 0xFE, 0xFB, 0xDF, 973e12c5d1SDavid du Colombier 0xF3, 0xCF, 0xE3, 0xC7, 0xFF, 0xFF, 0xFF, 0xFF, 983e12c5d1SDavid du Colombier 0xFF, 0xFF, 0xFF, 0xFF, 0xE3, 0xC7, 0xF3, 0xCF, 993e12c5d1SDavid du Colombier 0x7B, 0xDF, 0x7F, 0xFE, 0x3F, 0xFC, 0x1F, 0xF8,}, 1003e12c5d1SDavid du Colombier {0x00, 0x00, 0x0F, 0xF0, 0x31, 0x8C, 0x21, 0x84, 1013e12c5d1SDavid du Colombier 0x41, 0x82, 0x41, 0x82, 0x41, 0x82, 0x7F, 0xFE, 1023e12c5d1SDavid du Colombier 0x7F, 0xFE, 0x41, 0x82, 0x41, 0x82, 0x41, 0x82, 1033e12c5d1SDavid du Colombier 0x21, 0x84, 0x31, 0x8C, 0x0F, 0xF0, 0x00, 0x00,} 1043e12c5d1SDavid du Colombier }; 1053e12c5d1SDavid du Colombier 1063e12c5d1SDavid du Colombier Cursor busy = { 1073e12c5d1SDavid du Colombier {-7, -7}, 1083e12c5d1SDavid du Colombier {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1093e12c5d1SDavid du Colombier 0x00, 0x00, 0x00, 0x0c, 0x00, 0x8e, 0x1d, 0xc7, 1103e12c5d1SDavid du Colombier 0xff, 0xe3, 0xff, 0xf3, 0xff, 0xff, 0x7f, 0xfe, 1113e12c5d1SDavid du Colombier 0x3f, 0xf8, 0x17, 0xf0, 0x03, 0xe0, 0x00, 0x00,}, 1123e12c5d1SDavid du Colombier {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 1133e12c5d1SDavid du Colombier 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x82, 1143e12c5d1SDavid du Colombier 0x04, 0x41, 0xff, 0xe1, 0x5f, 0xf1, 0x3f, 0xfe, 1153e12c5d1SDavid du Colombier 0x17, 0xf0, 0x03, 0xe0, 0x00, 0x00, 0x00, 0x00,} 1163e12c5d1SDavid du Colombier }; 1173e12c5d1SDavid du Colombier 1183e12c5d1SDavid du Colombier Cursor skull = { 1193e12c5d1SDavid du Colombier {-7,-7}, 1203e12c5d1SDavid du Colombier {0x00, 0x00, 0x00, 0x00, 0xc0, 0x03, 0xe7, 0xe7, 1213e12c5d1SDavid du Colombier 0xff, 0xff, 0xff, 0xff, 0x3f, 0xfc, 0x1f, 0xf8, 1223e12c5d1SDavid du Colombier 0x0f, 0xf0, 0x3f, 0xfc, 0xff, 0xff, 0xff, 0xff, 1233e12c5d1SDavid du Colombier 0xef, 0xf7, 0xc7, 0xe3, 0x00, 0x00, 0x00, 0x00,}, 1243e12c5d1SDavid du Colombier {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x03, 1253e12c5d1SDavid du Colombier 0xE7, 0xE7, 0x3F, 0xFC, 0x0F, 0xF0, 0x0D, 0xB0, 1263e12c5d1SDavid du Colombier 0x07, 0xE0, 0x06, 0x60, 0x37, 0xEC, 0xE4, 0x27, 1273e12c5d1SDavid du Colombier 0xC3, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,} 1283e12c5d1SDavid du Colombier }; 1293e12c5d1SDavid du Colombier 1303e12c5d1SDavid du Colombier char *fns[] = { 1313e12c5d1SDavid du Colombier "0", "Zero", 0, 1323e12c5d1SDavid du Colombier "~(S|D)", "~(D|S)", "DnorS", 0, 1333e12c5d1SDavid du Colombier "~S&D", "D&~S", "DandnotS", 0, 1343e12c5d1SDavid du Colombier "~S", "notS", 0, 1353e12c5d1SDavid du Colombier "S&~D", "~D&S", "notDandS", 0, 1363e12c5d1SDavid du Colombier "~D", "notD", 0, 1373e12c5d1SDavid du Colombier "S^D", "D^S", "DxorS", 0, 1383e12c5d1SDavid du Colombier "~(S&D)", "~(D&S)", "DnandS", 0, 1393e12c5d1SDavid du Colombier "S&D", "D&S", "DandS", 0, 1403e12c5d1SDavid du Colombier "~(S^D)", "~(D^S)", "DxnorS", 0, 1413e12c5d1SDavid du Colombier "D", 0, 1423e12c5d1SDavid du Colombier "~S|D", "D|~S", "DornotS", 0, 1433e12c5d1SDavid du Colombier "S", 0, 1443e12c5d1SDavid du Colombier "S|~D", "~D|S", "notDorS", 0, 1453e12c5d1SDavid du Colombier "S|D", "D|S", "DorS", 0, 1463e12c5d1SDavid du Colombier "F", 0, 1473e12c5d1SDavid du Colombier 0 1483e12c5d1SDavid du Colombier }; 1493e12c5d1SDavid du Colombier 1503e12c5d1SDavid du Colombier Rectangle cntlr; /* control region */ 1513e12c5d1SDavid du Colombier Rectangle editr; /* editing region */ 1523e12c5d1SDavid du Colombier Rectangle textr; /* text region */ 1533e12c5d1SDavid du Colombier Thing *thing; 1543e12c5d1SDavid du Colombier Mouse mouse; 1553e12c5d1SDavid du Colombier char hex[] = "0123456789abcdefABCDEF"; 1563e12c5d1SDavid du Colombier jmp_buf err; 1573e12c5d1SDavid du Colombier char *file; 1583e12c5d1SDavid du Colombier int mag; 1593e12c5d1SDavid du Colombier uint copyfn = S; 1603e12c5d1SDavid du Colombier uint but1fn = S; 1613e12c5d1SDavid du Colombier uint but2fn = 0; 1623e12c5d1SDavid du Colombier Bitmap *values; 1633e12c5d1SDavid du Colombier ulong val = ~0; 1643e12c5d1SDavid du Colombier uchar data[8192]; 1653e12c5d1SDavid du Colombier 1663e12c5d1SDavid du Colombier Thing* tget(char*); 1673e12c5d1SDavid du Colombier void mesg(char*, ...); 1683e12c5d1SDavid du Colombier void draw(Thing*, int); 1693e12c5d1SDavid du Colombier void select(void); 1703e12c5d1SDavid du Colombier void menu(void); 1713e12c5d1SDavid du Colombier void error(char*); 1723e12c5d1SDavid du Colombier void buttons(int); 1733e12c5d1SDavid du Colombier char *fntostr(uint); 1743e12c5d1SDavid du Colombier int strtofn(char*); 1753e12c5d1SDavid du Colombier void drawall(void); 1763e12c5d1SDavid du Colombier void tclose1(Thing*); 1773e12c5d1SDavid du Colombier 1783e12c5d1SDavid du Colombier void 1793e12c5d1SDavid du Colombier main(int argc, char *argv[]) 1803e12c5d1SDavid du Colombier { 1813e12c5d1SDavid du Colombier int i, j; 1823e12c5d1SDavid du Colombier Event e; 1833e12c5d1SDavid du Colombier Thing *t; 1843e12c5d1SDavid du Colombier 1853e12c5d1SDavid du Colombier mag = Mag; 1863e12c5d1SDavid du Colombier binit(error, 0, "tweak"); 1873e12c5d1SDavid du Colombier values = balloc(Rect(0, 0, 256*Maxmag, Maxmag), screen.ldepth); 1883e12c5d1SDavid du Colombier if(values == 0) 1893e12c5d1SDavid du Colombier berror("can't balloc"); 1903e12c5d1SDavid du Colombier for(i=0; i<256; i++) 1913e12c5d1SDavid du Colombier for(j=0; j<Maxmag; j++) 1923e12c5d1SDavid du Colombier segment(values, Pt(i*Maxmag, j), Pt((i+1)*Maxmag, j), i, S); 1933e12c5d1SDavid du Colombier einit(Emouse|Ekeyboard); 1943e12c5d1SDavid du Colombier ereshaped(screen.r); 1953e12c5d1SDavid du Colombier i = 1; 1963e12c5d1SDavid du Colombier setjmp(err); 1973e12c5d1SDavid du Colombier for(; i<argc; i++){ 1983e12c5d1SDavid du Colombier file = argv[i]; 1993e12c5d1SDavid du Colombier t = tget(argv[i]); 2003e12c5d1SDavid du Colombier if(t) 2013e12c5d1SDavid du Colombier draw(t, 1); 2023e12c5d1SDavid du Colombier bflush(); 2033e12c5d1SDavid du Colombier } 2043e12c5d1SDavid du Colombier file = 0; 2053e12c5d1SDavid du Colombier setjmp(err); 2063e12c5d1SDavid du Colombier for(;;) 2073e12c5d1SDavid du Colombier switch(event(&e)){ 2083e12c5d1SDavid du Colombier case Ekeyboard: 2093e12c5d1SDavid du Colombier break; 2103e12c5d1SDavid du Colombier case Emouse: 2113e12c5d1SDavid du Colombier mouse = e.mouse; 2123e12c5d1SDavid du Colombier if(mouse.buttons & 3){ 2133e12c5d1SDavid du Colombier select(); 2143e12c5d1SDavid du Colombier break; 2153e12c5d1SDavid du Colombier } 2163e12c5d1SDavid du Colombier if(mouse.buttons & 4) 2173e12c5d1SDavid du Colombier menu(); 2183e12c5d1SDavid du Colombier } 2193e12c5d1SDavid du Colombier } 2203e12c5d1SDavid du Colombier 2213e12c5d1SDavid du Colombier void 2223e12c5d1SDavid du Colombier error(char *s) 2233e12c5d1SDavid du Colombier { 2243e12c5d1SDavid du Colombier if(file) 2253e12c5d1SDavid du Colombier mesg("can't read %s: %s: %r", file, s); 2263e12c5d1SDavid du Colombier else 2273e12c5d1SDavid du Colombier mesg("/dev/bitblt error: %s", s); 2283e12c5d1SDavid du Colombier if(err[0]) 2293e12c5d1SDavid du Colombier longjmp(err, 1); 2303e12c5d1SDavid du Colombier exits(s); 2313e12c5d1SDavid du Colombier } 2323e12c5d1SDavid du Colombier 2333e12c5d1SDavid du Colombier void 2343e12c5d1SDavid du Colombier redraw(Thing *t) 2353e12c5d1SDavid du Colombier { 2363e12c5d1SDavid du Colombier Thing *nt; 2373e12c5d1SDavid du Colombier Point p; 2383e12c5d1SDavid du Colombier 2393e12c5d1SDavid du Colombier if(thing==0 || thing==t) 2403e12c5d1SDavid du Colombier bitblt(&screen, editr.min, &screen, editr, 0); 2413e12c5d1SDavid du Colombier if(thing == 0) 2423e12c5d1SDavid du Colombier return; 2433e12c5d1SDavid du Colombier if(thing != t){ 2443e12c5d1SDavid du Colombier for(nt=thing; nt->next!=t; nt=nt->next) 2453e12c5d1SDavid du Colombier ; 2463e12c5d1SDavid du Colombier bitblt(&screen, Pt(screen.r.min.x, nt->er.max.y), &screen, 2473e12c5d1SDavid du Colombier Rect(screen.r.min.x, nt->er.max.y, editr.max.x, editr.max.y), 0); 2483e12c5d1SDavid du Colombier } 2493e12c5d1SDavid du Colombier for(nt=t; nt; nt=nt->next){ 2503e12c5d1SDavid du Colombier draw(nt, 0); 2513e12c5d1SDavid du Colombier if(nt->next == 0){ 2523e12c5d1SDavid du Colombier p = Pt(editr.min.x, nt->er.max.y); 2533e12c5d1SDavid du Colombier bitblt(&screen, p, &screen, Rpt(p, editr.max), 0); 2543e12c5d1SDavid du Colombier } 2553e12c5d1SDavid du Colombier } 2563e12c5d1SDavid du Colombier mesg(""); 2573e12c5d1SDavid du Colombier } 2583e12c5d1SDavid du Colombier 2593e12c5d1SDavid du Colombier void 2603e12c5d1SDavid du Colombier ereshaped(Rectangle r) 2613e12c5d1SDavid du Colombier { 2623e12c5d1SDavid du Colombier USED(r); 2633e12c5d1SDavid du Colombier 2643e12c5d1SDavid du Colombier screen.r = bscreenrect(&screen.clipr); 2653e12c5d1SDavid du Colombier cntlr = inset(screen.clipr, 1); 2663e12c5d1SDavid du Colombier editr = cntlr; 2673e12c5d1SDavid du Colombier textr = editr; 2683e12c5d1SDavid du Colombier textr.min.y = textr.max.y - font->height; 2693e12c5d1SDavid du Colombier cntlr.max.y = cntlr.min.y + font->height; 2703e12c5d1SDavid du Colombier editr.min.y = cntlr.max.y+1; 2713e12c5d1SDavid du Colombier editr.max.y = textr.min.y-1; 2723e12c5d1SDavid du Colombier bitblt(&screen, screen.clipr.min, &screen, screen.clipr, 0); 2733e12c5d1SDavid du Colombier segment(&screen, Pt(editr.min.x, editr.max.y), 2743e12c5d1SDavid du Colombier Pt(editr.max.x+1, editr.max.y), ~0, F); 2753e12c5d1SDavid du Colombier clipr(&screen, editr); 2763e12c5d1SDavid du Colombier drawall(); 2773e12c5d1SDavid du Colombier } 2783e12c5d1SDavid du Colombier 2793e12c5d1SDavid du Colombier void 2803e12c5d1SDavid du Colombier mesgstr(Point p, int line, char *s) 2813e12c5d1SDavid du Colombier { 2823e12c5d1SDavid du Colombier Rectangle c, r; 2833e12c5d1SDavid du Colombier 2843e12c5d1SDavid du Colombier r.min = p; 2853e12c5d1SDavid du Colombier r.min.y += line*font->height; 2863e12c5d1SDavid du Colombier r.max.y = r.min.y+font->height; 2873e12c5d1SDavid du Colombier r.max.x = editr.max.x; 2883e12c5d1SDavid du Colombier c = screen.clipr; 2893e12c5d1SDavid du Colombier clipr(&screen, r); 2903e12c5d1SDavid du Colombier bitblt(&screen, r.min, &screen, r, 0); 2913e12c5d1SDavid du Colombier r.min.x++; 2923e12c5d1SDavid du Colombier p = string(&screen, r.min, font, s, S); 2933e12c5d1SDavid du Colombier r.max.x = p.x + 1; 2943e12c5d1SDavid du Colombier r.min.x--; 2953e12c5d1SDavid du Colombier bitblt(&screen, r.min, &screen, r, ~D); 2963e12c5d1SDavid du Colombier clipr(&screen, c); 2973e12c5d1SDavid du Colombier bflush(); 2983e12c5d1SDavid du Colombier } 2993e12c5d1SDavid du Colombier 3003e12c5d1SDavid du Colombier void 3013e12c5d1SDavid du Colombier mesg(char *fmt, ...) 3023e12c5d1SDavid du Colombier { 3033e12c5d1SDavid du Colombier char buf[1024]; 3043e12c5d1SDavid du Colombier 3053e12c5d1SDavid du Colombier doprint(buf, buf+sizeof(buf), fmt, (&fmt+1)); 3063e12c5d1SDavid du Colombier mesgstr(textr.min, 0, buf); 3073e12c5d1SDavid du Colombier } 3083e12c5d1SDavid du Colombier 3093e12c5d1SDavid du Colombier void 3103e12c5d1SDavid du Colombier tmesg(Thing *t, int line, char *fmt, ...) 3113e12c5d1SDavid du Colombier { 3123e12c5d1SDavid du Colombier char buf[1024]; 3133e12c5d1SDavid du Colombier 3143e12c5d1SDavid du Colombier doprint(buf, buf+sizeof(buf), fmt, (&fmt+1)); 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 { 3223e12c5d1SDavid du Colombier char vals[16]; 3233e12c5d1SDavid du Colombier 3243e12c5d1SDavid du Colombier if(val & 0x80000000) 3253e12c5d1SDavid du Colombier sprint(vals, "~%lux", ~val); 3263e12c5d1SDavid du Colombier else 3273e12c5d1SDavid du Colombier sprint(vals, "%lux", val); 3283e12c5d1SDavid du Colombier sprint(l, "mag: %d val(hex): %s but1: %s but2: %s copy: %s", 3293e12c5d1SDavid du Colombier mag, vals, fntostr(but1fn), fntostr(but2fn), fntostr(copyfn)); 3303e12c5d1SDavid du Colombier } 3313e12c5d1SDavid du Colombier 3323e12c5d1SDavid du Colombier void 3333e12c5d1SDavid du Colombier cntl(void) 3343e12c5d1SDavid du Colombier { 3353e12c5d1SDavid du Colombier char buf[256]; 3363e12c5d1SDavid du Colombier 3373e12c5d1SDavid du Colombier scntl(buf); 3383e12c5d1SDavid du Colombier mesgstr(cntlr.min, 0, buf); 3393e12c5d1SDavid du Colombier } 3403e12c5d1SDavid du Colombier 3413e12c5d1SDavid du Colombier void 3423e12c5d1SDavid du Colombier stext(Thing *t, char *l0, char *l1) 3433e12c5d1SDavid du Colombier { 3443e12c5d1SDavid du Colombier Fontchar *fc; 3453e12c5d1SDavid du Colombier char buf[256]; 3463e12c5d1SDavid du Colombier 3473e12c5d1SDavid du Colombier l1[0] = 0; 3483e12c5d1SDavid du Colombier sprint(buf, "ldepth:%d r:%d %d %d %d ", 3493e12c5d1SDavid du Colombier t->b->ldepth, t->b->r.min.x, t->b->r.min.y, 3503e12c5d1SDavid du Colombier t->b->r.max.x, t->b->r.max.y); 3513e12c5d1SDavid du Colombier if(t->parent) 3523e12c5d1SDavid du Colombier sprint(buf+strlen(buf), "mag: %d ", t->mag); 3533e12c5d1SDavid du Colombier sprint(l0, "%s file: %s", buf, t->name); 3543e12c5d1SDavid du Colombier if(t->c >= 0){ 3553e12c5d1SDavid du Colombier fc = &t->parent->s->info[t->c]; 3563e12c5d1SDavid du Colombier sprint(l1, "c(hex): %x c(char): %C x: %d " 3573e12c5d1SDavid du Colombier "top: %d bottom: %d left: %d width: %d iwidth: %d", 3583e12c5d1SDavid du Colombier t->c+t->parent->off, t->c+t->parent->off, 3593e12c5d1SDavid du Colombier fc->x, fc->top, fc->bottom, fc->left, 3603e12c5d1SDavid du Colombier fc->width, Dx(t->b->r)); 3613e12c5d1SDavid du Colombier }else if(t->s) 3623e12c5d1SDavid du Colombier sprint(l1, "offset(hex): %ux n:%d height:%d ascent:%d", 3633e12c5d1SDavid du Colombier t->off, t->s->n, t->s->height, t->s->ascent); 3643e12c5d1SDavid du Colombier } 3653e12c5d1SDavid du Colombier 3663e12c5d1SDavid du Colombier void 3673e12c5d1SDavid du Colombier text(Thing *t) 3683e12c5d1SDavid du Colombier { 3693e12c5d1SDavid du Colombier char l0[256], l1[256]; 3703e12c5d1SDavid du Colombier 3713e12c5d1SDavid du Colombier stext(t, l0, l1); 3723e12c5d1SDavid du Colombier tmesg(t, 0, l0); 3733e12c5d1SDavid du Colombier if(l1[0]) 3743e12c5d1SDavid du Colombier tmesg(t, 1, l1); 3753e12c5d1SDavid du Colombier } 3763e12c5d1SDavid du Colombier 3773e12c5d1SDavid du Colombier void 3783e12c5d1SDavid du Colombier drawall(void) 3793e12c5d1SDavid du Colombier { 3803e12c5d1SDavid du Colombier Thing *t; 3813e12c5d1SDavid du Colombier 3823e12c5d1SDavid du Colombier cntl(); 3833e12c5d1SDavid du Colombier for(t=thing; t; t=t->next) 3843e12c5d1SDavid du Colombier draw(t, 0); 3853e12c5d1SDavid du Colombier } 3863e12c5d1SDavid du Colombier 3873e12c5d1SDavid du Colombier int 3883e12c5d1SDavid du Colombier value(Bitmap *b, int x) 3893e12c5d1SDavid du Colombier { 3903e12c5d1SDavid du Colombier int v, l, w; 3913e12c5d1SDavid du Colombier uchar mask; 3923e12c5d1SDavid du Colombier 3933e12c5d1SDavid du Colombier l = b->ldepth; 3943e12c5d1SDavid du Colombier if(l > 3){ 3953e12c5d1SDavid du Colombier mesg("ldepth too large"); 3963e12c5d1SDavid du Colombier return 0; 3973e12c5d1SDavid du Colombier } 3983e12c5d1SDavid du Colombier w = 1<<l; 3993e12c5d1SDavid du Colombier mask = (2<<w)-1; /* ones at right end of word */ 4003e12c5d1SDavid du Colombier x -= b->r.min.x&~(7>>l); /* adjust x relative to first pixel */ 4013e12c5d1SDavid du Colombier v = data[x>>(3-l)]; 4023e12c5d1SDavid du Colombier v >>= ((7>>l)<<l) - ((x&(7>>l))<<l); /* pixel at right end of word */ 4033e12c5d1SDavid du Colombier v &= mask; /* pixel at right end of word */ 4043e12c5d1SDavid du Colombier return v; 4053e12c5d1SDavid du Colombier } 4063e12c5d1SDavid du Colombier 4073e12c5d1SDavid du Colombier int 4083e12c5d1SDavid du Colombier bvalue(int v, int l) 4093e12c5d1SDavid du Colombier { 410*219b2ee8SDavid du Colombier v &= (1<<(1<<l))-1; 4113e12c5d1SDavid du Colombier if(l > screen.ldepth) 412*219b2ee8SDavid du Colombier v >>= (1<<l) - (1<<screen.ldepth); 413*219b2ee8SDavid du Colombier else 414*219b2ee8SDavid du Colombier while(l < screen.ldepth){ 415*219b2ee8SDavid du Colombier v |= v << (1<<l); 416*219b2ee8SDavid du Colombier l++; 4173e12c5d1SDavid du Colombier } 4183e12c5d1SDavid du Colombier return v*Maxmag; 4193e12c5d1SDavid du Colombier } 4203e12c5d1SDavid du Colombier 4213e12c5d1SDavid du Colombier void 4223e12c5d1SDavid du Colombier draw(Thing *nt, int link) 4233e12c5d1SDavid du Colombier { 4243e12c5d1SDavid du Colombier int nl, nf, i, x, y, sx, sy, fdx, dx, dy, v; 4253e12c5d1SDavid du Colombier Thing *t; 4263e12c5d1SDavid du Colombier Subfont *s; 4273e12c5d1SDavid du Colombier Bitmap *b; 4283e12c5d1SDavid du Colombier Point p, p1, p2; 4293e12c5d1SDavid du Colombier 4303e12c5d1SDavid du Colombier if(link){ 4313e12c5d1SDavid du Colombier nt->next = 0; 4323e12c5d1SDavid du Colombier if(thing == 0){ 4333e12c5d1SDavid du Colombier thing = nt; 4343e12c5d1SDavid du Colombier y = editr.min.y; 4353e12c5d1SDavid du Colombier }else{ 4363e12c5d1SDavid du Colombier for(t=thing; t->next; t=t->next) 4373e12c5d1SDavid du Colombier ; 4383e12c5d1SDavid du Colombier t->next = nt; 4393e12c5d1SDavid du Colombier y = t->er.max.y; 4403e12c5d1SDavid du Colombier } 4413e12c5d1SDavid du Colombier }else{ 4423e12c5d1SDavid du Colombier if(thing == nt) 4433e12c5d1SDavid du Colombier y = editr.min.y; 4443e12c5d1SDavid du Colombier else{ 4453e12c5d1SDavid du Colombier for(t=thing; t->next!=nt; t=t->next) 4463e12c5d1SDavid du Colombier ; 4473e12c5d1SDavid du Colombier y = t->er.max.y; 4483e12c5d1SDavid du Colombier } 4493e12c5d1SDavid du Colombier } 4503e12c5d1SDavid du Colombier s = nt->s; 4513e12c5d1SDavid du Colombier b = nt->b; 4523e12c5d1SDavid du Colombier nl = font->height; 4533e12c5d1SDavid du Colombier if(s || nt->c>=0) 4543e12c5d1SDavid du Colombier nl += font->height; 4553e12c5d1SDavid du Colombier fdx = Dx(editr) - 2*Border; 4563e12c5d1SDavid du Colombier dx = Dx(b->r); 4573e12c5d1SDavid du Colombier dy = Dy(b->r); 4583e12c5d1SDavid du Colombier if(nt->mag > 1){ 4593e12c5d1SDavid du Colombier dx *= nt->mag; 4603e12c5d1SDavid du Colombier dy *= nt->mag; 4613e12c5d1SDavid du Colombier fdx -= fdx%nt->mag; 4623e12c5d1SDavid du Colombier } 4633e12c5d1SDavid du Colombier nf = 1 + dx/fdx; 4643e12c5d1SDavid du Colombier nt->er.min.y = y; 4653e12c5d1SDavid du Colombier nt->er.min.x = editr.min.x; 4663e12c5d1SDavid du Colombier nt->er.max.x = nt->er.min.x + Border + dx + Border; 4673e12c5d1SDavid du Colombier if(nt->er.max.x > editr.max.x) 4683e12c5d1SDavid du Colombier nt->er.max.x = editr.max.x; 4693e12c5d1SDavid du Colombier nt->er.max.y = nt->er.min.y + Border + nf*(dy+Border); 4703e12c5d1SDavid du Colombier nt->r = inset(nt->er, Border); 4713e12c5d1SDavid du Colombier nt->er.max.x = editr.max.x; 4723e12c5d1SDavid du Colombier bitblt(&screen, nt->er.min, &screen, nt->er, 0); 4733e12c5d1SDavid du Colombier for(i=0; i<nf; i++){ 4743e12c5d1SDavid du Colombier p1 = Pt(nt->r.min.x-1, nt->r.min.y+i*(Border+dy)); 4753e12c5d1SDavid du Colombier /* draw portion of bitmap */ 4763e12c5d1SDavid du Colombier p = Pt(p1.x+1, p1.y); 4773e12c5d1SDavid du Colombier if(nt->mag == 1) 4783e12c5d1SDavid du Colombier bitblt(&screen, p, b, 4793e12c5d1SDavid du Colombier Rect(b->r.min.x+i*fdx, b->r.min.y, 4803e12c5d1SDavid du Colombier b->r.max.x+(i+1)*fdx, b->r.max.y), S); 4813e12c5d1SDavid du Colombier else{ 4823e12c5d1SDavid du Colombier for(y=b->r.min.y; y<b->r.max.y; y++){ 4833e12c5d1SDavid du Colombier sy = p.y+(y-b->r.min.y)*nt->mag; 4843e12c5d1SDavid du Colombier rdbitmap(b, y, y+1, data); 4853e12c5d1SDavid du Colombier for(x=b->r.min.x+i*(fdx/nt->mag); x<b->r.max.x; x++){ 4863e12c5d1SDavid du Colombier sx = p.x+(x-i*(fdx/nt->mag)-b->r.min.x)*nt->mag; 4873e12c5d1SDavid du Colombier if(sx >= nt->r.max.x) 4883e12c5d1SDavid du Colombier break; 4893e12c5d1SDavid du Colombier v = bvalue(value(b, x), b->ldepth); 4903e12c5d1SDavid du Colombier if(v) 4913e12c5d1SDavid du Colombier bitblt(&screen, Pt(sx, sy), 4923e12c5d1SDavid du Colombier values, 4933e12c5d1SDavid du Colombier Rect(v, 0, v+nt->mag, nt->mag), S); 4943e12c5d1SDavid du Colombier } 4953e12c5d1SDavid du Colombier 4963e12c5d1SDavid du Colombier } 4973e12c5d1SDavid du Colombier } 4983e12c5d1SDavid du Colombier /* line down left */ 4993e12c5d1SDavid du Colombier segment(&screen, p1, Pt(p1.x, p1.y+dy+Border+1), i==0? ~0 : 0, S); 5003e12c5d1SDavid du Colombier /* line across top */ 5013e12c5d1SDavid du Colombier segment(&screen, Pt(p1.x, p1.y-1), Pt(nt->r.max.x+Border, p1.y-1), ~0, F); 5023e12c5d1SDavid du Colombier p2 = p1; 5033e12c5d1SDavid du Colombier if(i == nf-1) 5043e12c5d1SDavid du Colombier p2.x += 1 + dx%fdx; 5053e12c5d1SDavid du Colombier else 5063e12c5d1SDavid du Colombier p2.x = nt->r.max.x; 5073e12c5d1SDavid du Colombier /* line down right */ 5083e12c5d1SDavid du Colombier segment(&screen, p2, Pt(p2.x, p2.y+dy+1), i==nf-1? ~0 : 0, S); 5093e12c5d1SDavid du Colombier /* line across bottom */ 5103e12c5d1SDavid du Colombier if(i == nf-1){ 5113e12c5d1SDavid du Colombier p1.y += Border+dy; 5123e12c5d1SDavid du Colombier segment(&screen, Pt(p1.x, p1.y-1), Pt(p2.x, p1.y-1), ~0, F); 5133e12c5d1SDavid du Colombier } 5143e12c5d1SDavid du Colombier } 5153e12c5d1SDavid du Colombier nt->tr.min.x = editr.min.x; 5163e12c5d1SDavid du Colombier nt->tr.max.x = editr.max.x; 5173e12c5d1SDavid du Colombier nt->tr.min.y = nt->er.max.y + Border; 5183e12c5d1SDavid du Colombier nt->tr.max.y = nt->tr.min.y + nl; 5193e12c5d1SDavid du Colombier nt->er.max.y = nt->tr.max.y + Border; 5203e12c5d1SDavid du Colombier text(nt); 5213e12c5d1SDavid du Colombier } 5223e12c5d1SDavid du Colombier 5233e12c5d1SDavid du Colombier int 5243e12c5d1SDavid du Colombier tohex(int c) 5253e12c5d1SDavid du Colombier { 5263e12c5d1SDavid du Colombier if('0'<=c && c<='9') 5273e12c5d1SDavid du Colombier return c - '0'; 5283e12c5d1SDavid du Colombier if('a'<=c && c<='f') 5293e12c5d1SDavid du Colombier return 10 + (c - 'a'); 5303e12c5d1SDavid du Colombier if('A'<=c && c<='F') 5313e12c5d1SDavid du Colombier return 10 + (c - 'A'); 5323e12c5d1SDavid du Colombier } 5333e12c5d1SDavid du Colombier 5343e12c5d1SDavid du Colombier Thing* 5353e12c5d1SDavid du Colombier tget(char *file) 5363e12c5d1SDavid du Colombier { 5373e12c5d1SDavid du Colombier int i, j, fd, face, x, y, c, ld; 5383e12c5d1SDavid du Colombier Bitmap *b, *tb; 5393e12c5d1SDavid du Colombier Subfont *s; 5403e12c5d1SDavid du Colombier Thing *t; 5413e12c5d1SDavid du Colombier Dir d; 5423e12c5d1SDavid du Colombier jmp_buf oerr; 5433e12c5d1SDavid du Colombier uchar buf[256]; 5443e12c5d1SDavid du Colombier char *data; 5453e12c5d1SDavid du Colombier 5463e12c5d1SDavid du Colombier errstr((char*)buf); /* flush pending error message */ 5473e12c5d1SDavid du Colombier memmove(oerr, err, sizeof err); 5483e12c5d1SDavid du Colombier if(setjmp(err)){ 5493e12c5d1SDavid du Colombier Err: 5503e12c5d1SDavid du Colombier memmove(err, oerr, sizeof err); 5513e12c5d1SDavid du Colombier return 0; 5523e12c5d1SDavid du Colombier } 5533e12c5d1SDavid du Colombier fd = open(file, OREAD); 5543e12c5d1SDavid du Colombier if(fd < 0){ 5553e12c5d1SDavid du Colombier mesg("can't open %s: %r", file); 5563e12c5d1SDavid du Colombier goto Err; 5573e12c5d1SDavid du Colombier } 5583e12c5d1SDavid du Colombier if(dirfstat(fd, &d) < 0){ 5593e12c5d1SDavid du Colombier mesg("can't stat bitmap file %s: %r", file); 5603e12c5d1SDavid du Colombier close(fd); 5613e12c5d1SDavid du Colombier goto Err; 5623e12c5d1SDavid du Colombier } 5633e12c5d1SDavid du Colombier if(read(fd, buf, 2) != 2){ 5643e12c5d1SDavid du Colombier mesg("can't read %s: %r", file); 5653e12c5d1SDavid du Colombier close(fd); 5663e12c5d1SDavid du Colombier goto Err; 5673e12c5d1SDavid du Colombier } 5683e12c5d1SDavid du Colombier seek(fd, 0, 0); 5693e12c5d1SDavid du Colombier if(buf[0]=='0' && buf[1]=='x'){ 5703e12c5d1SDavid du Colombier /* 5713e12c5d1SDavid du Colombier * face file 5723e12c5d1SDavid du Colombier */ 5733e12c5d1SDavid du Colombier face = 1; 5743e12c5d1SDavid du Colombier s = 0; 5753e12c5d1SDavid du Colombier data = malloc(d.length+1); 5763e12c5d1SDavid du Colombier if(data == 0){ 5773e12c5d1SDavid du Colombier mesg("can't malloc buffer: %r"); 5783e12c5d1SDavid du Colombier close(fd); 5793e12c5d1SDavid du Colombier goto Err; 5803e12c5d1SDavid du Colombier } 5813e12c5d1SDavid du Colombier data[d.length] = 0; 5823e12c5d1SDavid du Colombier if(read(fd, data, d.length) != d.length){ 5833e12c5d1SDavid du Colombier mesg("can't read bitmap file %s: %r", file); 5843e12c5d1SDavid du Colombier close(fd); 5853e12c5d1SDavid du Colombier goto Err; 5863e12c5d1SDavid du Colombier } 5873e12c5d1SDavid du Colombier for(y=0,i=0; i<d.length; i++) 5883e12c5d1SDavid du Colombier if(data[i] == '\n') 5893e12c5d1SDavid du Colombier y++; 5903e12c5d1SDavid du Colombier if(y == 0){ 5913e12c5d1SDavid du Colombier ill: 5923e12c5d1SDavid du Colombier mesg("ill-formed face file %s", file); 5933e12c5d1SDavid du Colombier close(fd); 5943e12c5d1SDavid du Colombier free(data); 5953e12c5d1SDavid du Colombier goto Err; 5963e12c5d1SDavid du Colombier } 5973e12c5d1SDavid du Colombier for(x=0,i=0; (c=data[i])!='\n'; ){ 5983e12c5d1SDavid du Colombier if(c==',' || c==' ' || c=='\t'){ 5993e12c5d1SDavid du Colombier i++; 6003e12c5d1SDavid du Colombier continue; 6013e12c5d1SDavid du Colombier } 6023e12c5d1SDavid du Colombier if(c=='0' && data[i+1] == 'x'){ 6033e12c5d1SDavid du Colombier i += 2; 6043e12c5d1SDavid du Colombier continue; 6053e12c5d1SDavid du Colombier } 6063e12c5d1SDavid du Colombier if(strchr(hex, c)){ 6073e12c5d1SDavid du Colombier x += 4; 6083e12c5d1SDavid du Colombier i++; 6093e12c5d1SDavid du Colombier continue; 6103e12c5d1SDavid du Colombier } 6113e12c5d1SDavid du Colombier goto ill; 6123e12c5d1SDavid du Colombier } 6133e12c5d1SDavid du Colombier if(x % y) 6143e12c5d1SDavid du Colombier goto ill; 6153e12c5d1SDavid du Colombier switch(x / y){ 6163e12c5d1SDavid du Colombier default: 6173e12c5d1SDavid du Colombier goto ill; 6183e12c5d1SDavid du Colombier case 1: 6193e12c5d1SDavid du Colombier ld = 0; 6203e12c5d1SDavid du Colombier break; 6213e12c5d1SDavid du Colombier case 2: 6223e12c5d1SDavid du Colombier ld = 1; 6233e12c5d1SDavid du Colombier break; 6243e12c5d1SDavid du Colombier case 4: 6253e12c5d1SDavid du Colombier ld = 2; 6263e12c5d1SDavid du Colombier break; 6273e12c5d1SDavid du Colombier case 8: 6283e12c5d1SDavid du Colombier ld = 3; 6293e12c5d1SDavid du Colombier break; 6303e12c5d1SDavid du Colombier } 6313e12c5d1SDavid du Colombier b = balloc(Rect(0, 0, y, y), ld); 6323e12c5d1SDavid du Colombier if(b == 0){ 6333e12c5d1SDavid du Colombier mesg("balloc failed file %s: %r", file); 6343e12c5d1SDavid du Colombier free(data); 6353e12c5d1SDavid du Colombier close(fd); 6363e12c5d1SDavid du Colombier goto Err; 6373e12c5d1SDavid du Colombier } 6383e12c5d1SDavid du Colombier i = 0; 6393e12c5d1SDavid du Colombier for(j=0; j<y; j++){ 6403e12c5d1SDavid du Colombier for(x=0; (c=data[i])!='\n'; ){ 6413e12c5d1SDavid du Colombier if(strchr(" \t,{}", c)){ 6423e12c5d1SDavid du Colombier i++; 6433e12c5d1SDavid du Colombier continue; 6443e12c5d1SDavid du Colombier } 6453e12c5d1SDavid du Colombier if(c=='0' && data[i+1] == 'x'){ 6463e12c5d1SDavid du Colombier i += 2; 6473e12c5d1SDavid du Colombier continue; 6483e12c5d1SDavid du Colombier } 6493e12c5d1SDavid du Colombier if(strchr(hex, c)){ 6503e12c5d1SDavid du Colombier buf[x++] = (tohex(c)<<4) | tohex(data[i+1]); 6513e12c5d1SDavid du Colombier i += 2; 6523e12c5d1SDavid du Colombier continue; 6533e12c5d1SDavid du Colombier } 6543e12c5d1SDavid du Colombier } 6553e12c5d1SDavid du Colombier i++; 6563e12c5d1SDavid du Colombier wrbitmap(b, j, j+1, buf); 6573e12c5d1SDavid du Colombier } 6583e12c5d1SDavid du Colombier free(data); 6593e12c5d1SDavid du Colombier }else{ 6603e12c5d1SDavid du Colombier /* 6613e12c5d1SDavid du Colombier * plain bitmap file 6623e12c5d1SDavid du Colombier */ 6633e12c5d1SDavid du Colombier face = 0; 6643e12c5d1SDavid du Colombier s = 0; 6653e12c5d1SDavid du Colombier b = rdbitmapfile(fd); 6663e12c5d1SDavid du Colombier if(b == 0){ 6673e12c5d1SDavid du Colombier mesg("can't read bitmap file %s: %r", file); 6683e12c5d1SDavid du Colombier close(fd); 6693e12c5d1SDavid du Colombier goto Err; 6703e12c5d1SDavid du Colombier } 6713e12c5d1SDavid du Colombier if(seek(fd, 0, 1) < d.length){ 6723e12c5d1SDavid du Colombier /* rdsubfontfile drops bitmap; must make a copy */ 6733e12c5d1SDavid du Colombier tb = balloc(b->r, b->ldepth); 6743e12c5d1SDavid du Colombier if(tb == 0){ 6753e12c5d1SDavid du Colombier mesg("can't balloc bitmap for file %s: %r", file); 6763e12c5d1SDavid du Colombier close(fd); 6773e12c5d1SDavid du Colombier goto Err; 6783e12c5d1SDavid du Colombier } 6793e12c5d1SDavid du Colombier bitblt(tb, tb->r.min, b, b->r, S); 6803e12c5d1SDavid du Colombier s = rdsubfontfile(fd, tb); 6813e12c5d1SDavid du Colombier } 6823e12c5d1SDavid du Colombier } 6833e12c5d1SDavid du Colombier close(fd); 6843e12c5d1SDavid du Colombier t = malloc(sizeof(Thing)); 6853e12c5d1SDavid du Colombier if(t == 0){ 6863e12c5d1SDavid du Colombier nomem: 6873e12c5d1SDavid du Colombier mesg("malloc failed: %r"); 6883e12c5d1SDavid du Colombier if(s) 6893e12c5d1SDavid du Colombier subffree(s); 6903e12c5d1SDavid du Colombier bfree(b); 6913e12c5d1SDavid du Colombier goto Err; 6923e12c5d1SDavid du Colombier } 6933e12c5d1SDavid du Colombier t->name = strdup(file); 6943e12c5d1SDavid du Colombier if(t->name == 0){ 6953e12c5d1SDavid du Colombier free(t); 6963e12c5d1SDavid du Colombier goto nomem; 6973e12c5d1SDavid du Colombier } 6983e12c5d1SDavid du Colombier t->b = b; 6993e12c5d1SDavid du Colombier t->s = s; 7003e12c5d1SDavid du Colombier t->face = face; 7013e12c5d1SDavid du Colombier t->mod = 0; 7023e12c5d1SDavid du Colombier t->parent = 0; 7033e12c5d1SDavid du Colombier t->c = -1; 7043e12c5d1SDavid du Colombier t->mag = 1; 7053e12c5d1SDavid du Colombier t->off = 0; 7063e12c5d1SDavid du Colombier memmove(err, oerr, sizeof err); 7073e12c5d1SDavid du Colombier return t; 7083e12c5d1SDavid du Colombier } 7093e12c5d1SDavid du Colombier 7103e12c5d1SDavid du Colombier int 7113e12c5d1SDavid du Colombier atline(int x, Point p, char *line, char *buf) 7123e12c5d1SDavid du Colombier { 7133e12c5d1SDavid du Colombier char *s, *c, *word, *hit; 7143e12c5d1SDavid du Colombier int w, wasblank; 7153e12c5d1SDavid du Colombier Rune r; 7163e12c5d1SDavid du Colombier 7173e12c5d1SDavid du Colombier wasblank = 1; 7183e12c5d1SDavid du Colombier hit = 0; 7193e12c5d1SDavid du Colombier word = 0; 7203e12c5d1SDavid du Colombier for(s=line; *s; s+=w){ 7213e12c5d1SDavid du Colombier w = chartorune(&r, s); 7223e12c5d1SDavid du Colombier x += charwidth(font, r); 7233e12c5d1SDavid du Colombier if(wasblank && r!=' ') 7243e12c5d1SDavid du Colombier word = s; 7253e12c5d1SDavid du Colombier wasblank = 0; 7263e12c5d1SDavid du Colombier if(r == ' '){ 7273e12c5d1SDavid du Colombier if(x >= p.x) 7283e12c5d1SDavid du Colombier break; 7293e12c5d1SDavid du Colombier wasblank = 1; 7303e12c5d1SDavid du Colombier } 7313e12c5d1SDavid du Colombier if(r == ':') 7323e12c5d1SDavid du Colombier hit = word; 7333e12c5d1SDavid du Colombier } 7343e12c5d1SDavid du Colombier if(x < p.x) 7353e12c5d1SDavid du Colombier return 0; 7363e12c5d1SDavid du Colombier c = utfrune(hit, ':'); 7373e12c5d1SDavid du Colombier strncpy(buf, hit, c-hit); 7383e12c5d1SDavid du Colombier buf[c-hit] = 0; 7393e12c5d1SDavid du Colombier return 1; 7403e12c5d1SDavid du Colombier } 7413e12c5d1SDavid du Colombier 7423e12c5d1SDavid du Colombier int 7433e12c5d1SDavid du Colombier attext(Thing *t, Point p, char *buf) 7443e12c5d1SDavid du Colombier { 7453e12c5d1SDavid du Colombier char l0[256], l1[256]; 7463e12c5d1SDavid du Colombier 7473e12c5d1SDavid du Colombier if(!ptinrect(p, t->tr)) 7483e12c5d1SDavid du Colombier return 0; 7493e12c5d1SDavid du Colombier stext(t, l0, l1); 7503e12c5d1SDavid du Colombier if(p.y < t->tr.min.y+font->height) 7513e12c5d1SDavid du Colombier return atline(t->r.min.x, p, l0, buf); 7523e12c5d1SDavid du Colombier else 7533e12c5d1SDavid du Colombier return atline(t->r.min.x, p, l1, buf); 7543e12c5d1SDavid du Colombier } 7553e12c5d1SDavid du Colombier 7563e12c5d1SDavid du Colombier int 7573e12c5d1SDavid du Colombier type(char *buf, char *tag) 7583e12c5d1SDavid du Colombier { 7593e12c5d1SDavid du Colombier Rune r; 7603e12c5d1SDavid du Colombier char *p; 7613e12c5d1SDavid du Colombier 7623e12c5d1SDavid du Colombier cursorswitch(&busy); 7633e12c5d1SDavid du Colombier p = buf; 7643e12c5d1SDavid du Colombier for(;;){ 7653e12c5d1SDavid du Colombier *p = 0; 7663e12c5d1SDavid du Colombier mesg("%s: %s", tag, buf); 7673e12c5d1SDavid du Colombier r = ekbd(); 7683e12c5d1SDavid du Colombier switch(r){ 7693e12c5d1SDavid du Colombier case '\n': 7703e12c5d1SDavid du Colombier mesg(""); 7713e12c5d1SDavid du Colombier cursorswitch(0); 7723e12c5d1SDavid du Colombier return p-buf; 7733e12c5d1SDavid du Colombier case 0x15: /* control-U */ 7743e12c5d1SDavid du Colombier p = buf; 7753e12c5d1SDavid du Colombier break; 7763e12c5d1SDavid du Colombier case '\b': 7773e12c5d1SDavid du Colombier if(p > buf) 7783e12c5d1SDavid du Colombier --p; 7793e12c5d1SDavid du Colombier break; 7803e12c5d1SDavid du Colombier default: 7813e12c5d1SDavid du Colombier p += runetochar(p, &r); 7823e12c5d1SDavid du Colombier } 7833e12c5d1SDavid du Colombier } 7843e12c5d1SDavid du Colombier return 0; /* shut up compiler */ 7853e12c5d1SDavid du Colombier } 7863e12c5d1SDavid du Colombier 7873e12c5d1SDavid du Colombier void 7883e12c5d1SDavid du Colombier textedit(Thing *t, char *tag) 7893e12c5d1SDavid du Colombier { 7903e12c5d1SDavid du Colombier char buf[256]; 7913e12c5d1SDavid du Colombier char *s; 7923e12c5d1SDavid du Colombier Bitmap *b; 7933e12c5d1SDavid du Colombier Subfont *f; 7943e12c5d1SDavid du Colombier Fontchar *fc, *nfc; 7953e12c5d1SDavid du Colombier Rectangle r; 7963e12c5d1SDavid du Colombier int i, ld, w, c, doredraw, fdx, x; 7973e12c5d1SDavid du Colombier Thing *nt; 7983e12c5d1SDavid du Colombier 7993e12c5d1SDavid du Colombier buttons(Up); 8003e12c5d1SDavid du Colombier if(type(buf, tag) == 0) 8013e12c5d1SDavid du Colombier return; 8023e12c5d1SDavid du Colombier if(strcmp(tag, "file") == 0){ 8033e12c5d1SDavid du Colombier for(s=buf; *s; s++) 8043e12c5d1SDavid du Colombier if(*s <= ' '){ 8053e12c5d1SDavid du Colombier mesg("illegal file name"); 8063e12c5d1SDavid du Colombier return; 8073e12c5d1SDavid du Colombier } 8083e12c5d1SDavid du Colombier if(strcmp(t->name, buf) != 0){ 8093e12c5d1SDavid du Colombier if(t->parent) 8103e12c5d1SDavid du Colombier t->parent->mod = 1; 8113e12c5d1SDavid du Colombier else 8123e12c5d1SDavid du Colombier t->mod = 1; 8133e12c5d1SDavid du Colombier } 8143e12c5d1SDavid du Colombier for(nt=thing; nt; nt=nt->next) 8153e12c5d1SDavid du Colombier if(t==nt || t->parent==nt || nt->parent==t){ 8163e12c5d1SDavid du Colombier free(nt->name); 8173e12c5d1SDavid du Colombier nt->name = strdup(buf); 8183e12c5d1SDavid du Colombier if(nt->name == 0){ 8193e12c5d1SDavid du Colombier nomem: 8203e12c5d1SDavid du Colombier mesg("malloc failed: %r"); 8213e12c5d1SDavid du Colombier return; 8223e12c5d1SDavid du Colombier } 8233e12c5d1SDavid du Colombier text(nt); 8243e12c5d1SDavid du Colombier } 8253e12c5d1SDavid du Colombier return; 8263e12c5d1SDavid du Colombier } 8273e12c5d1SDavid du Colombier if(strcmp(tag, "ldepth") == 0){ 8283e12c5d1SDavid du Colombier if(buf[0]<'0' || '9'<buf[0] || (ld=atoi(buf))<0 || ld>3){ 8293e12c5d1SDavid du Colombier mesg("illegal ldepth"); 8303e12c5d1SDavid du Colombier return; 8313e12c5d1SDavid du Colombier } 8323e12c5d1SDavid du Colombier if(ld == t->b->ldepth) 8333e12c5d1SDavid du Colombier return; 8343e12c5d1SDavid du Colombier if(t->parent) 8353e12c5d1SDavid du Colombier t->parent->mod = 1; 8363e12c5d1SDavid du Colombier else 8373e12c5d1SDavid du Colombier t->mod = 1; 8383e12c5d1SDavid du Colombier for(nt=thing; nt; nt=nt->next){ 8393e12c5d1SDavid du Colombier if(nt!=t && nt!=t->parent && nt->parent!=t) 8403e12c5d1SDavid du Colombier continue; 8413e12c5d1SDavid du Colombier b = balloc(nt->b->r, ld); 8423e12c5d1SDavid du Colombier if(b == 0){ 8433e12c5d1SDavid du Colombier nobmem: 8443e12c5d1SDavid du Colombier mesg("balloc failed: %r"); 8453e12c5d1SDavid du Colombier return; 8463e12c5d1SDavid du Colombier } 8473e12c5d1SDavid du Colombier bitblt(b, b->r.min, nt->b, nt->b->r, S); 8483e12c5d1SDavid du Colombier bfree(nt->b); 8493e12c5d1SDavid du Colombier nt->b = b; 8503e12c5d1SDavid du Colombier if(nt->s){ 8513e12c5d1SDavid du Colombier b = balloc(nt->b->r, ld); 8523e12c5d1SDavid du Colombier if(b == 0) 8533e12c5d1SDavid du Colombier goto nobmem; 8543e12c5d1SDavid du Colombier bitblt(b, b->r.min, nt->b, nt->b->r, S); 8553e12c5d1SDavid du Colombier f = subfalloc(nt->s->n, nt->s->height, nt->s->ascent, 8563e12c5d1SDavid du Colombier nt->s->info, b, ~0, ~0); 8573e12c5d1SDavid du Colombier if(f == 0){ 8583e12c5d1SDavid du Colombier nofmem: 8593e12c5d1SDavid du Colombier mesg("can't make subfont: %r"); 8603e12c5d1SDavid du Colombier return; 8613e12c5d1SDavid du Colombier } 8623e12c5d1SDavid du Colombier subffree(nt->s); 8633e12c5d1SDavid du Colombier nt->s = f; 8643e12c5d1SDavid du Colombier } 8653e12c5d1SDavid du Colombier draw(nt, 0); 8663e12c5d1SDavid du Colombier } 8673e12c5d1SDavid du Colombier return; 8683e12c5d1SDavid du Colombier } 8693e12c5d1SDavid du Colombier if(strcmp(tag, "mag") == 0){ 8703e12c5d1SDavid du Colombier if(buf[0]<'0' || '9'<buf[0] || (ld=atoi(buf))<=0 || ld>Maxmag){ 8713e12c5d1SDavid du Colombier mesg("illegal magnification"); 8723e12c5d1SDavid du Colombier return; 8733e12c5d1SDavid du Colombier } 8743e12c5d1SDavid du Colombier if(t->mag == ld) 8753e12c5d1SDavid du Colombier return; 8763e12c5d1SDavid du Colombier t->mag = ld; 8773e12c5d1SDavid du Colombier redraw(t); 8783e12c5d1SDavid du Colombier return; 8793e12c5d1SDavid du Colombier } 8803e12c5d1SDavid du Colombier if(strcmp(tag, "ascent") == 0){ 8813e12c5d1SDavid du Colombier if(buf[0]<'0' || '9'<buf[0] || (ld=atoi(buf))<0 || ld>t->s->height){ 8823e12c5d1SDavid du Colombier mesg("illegal ascent"); 8833e12c5d1SDavid du Colombier return; 8843e12c5d1SDavid du Colombier } 8853e12c5d1SDavid du Colombier if(t->s->ascent == ld) 8863e12c5d1SDavid du Colombier return; 8873e12c5d1SDavid du Colombier t->s->ascent = ld; 8883e12c5d1SDavid du Colombier text(t); 8893e12c5d1SDavid du Colombier t->mod = 1; 8903e12c5d1SDavid du Colombier return; 8913e12c5d1SDavid du Colombier } 8923e12c5d1SDavid du Colombier if(strcmp(tag, "height") == 0){ 8933e12c5d1SDavid du Colombier if(buf[0]<'0' || '9'<buf[0] || (ld=atoi(buf))<0){ 8943e12c5d1SDavid du Colombier mesg("illegal height"); 8953e12c5d1SDavid du Colombier return; 8963e12c5d1SDavid du Colombier } 8973e12c5d1SDavid du Colombier if(t->s->height == ld) 8983e12c5d1SDavid du Colombier return; 8993e12c5d1SDavid du Colombier t->s->height = ld; 9003e12c5d1SDavid du Colombier text(t); 9013e12c5d1SDavid du Colombier t->mod = 1; 9023e12c5d1SDavid du Colombier return; 9033e12c5d1SDavid du Colombier } 9043e12c5d1SDavid du Colombier if(strcmp(tag, "left")==0 || strcmp(tag, "width") == 0){ 9053e12c5d1SDavid du Colombier if(buf[0]<'0' || '9'<buf[0] || (ld=atoi(buf))<0){ 9063e12c5d1SDavid du Colombier mesg("illegal value"); 9073e12c5d1SDavid du Colombier return; 9083e12c5d1SDavid du Colombier } 9093e12c5d1SDavid du Colombier fc = &t->parent->s->info[t->c]; 9103e12c5d1SDavid du Colombier if(strcmp(tag, "left")==0){ 9113e12c5d1SDavid du Colombier if(fc->left == ld) 9123e12c5d1SDavid du Colombier return; 9133e12c5d1SDavid du Colombier fc->left = ld; 9143e12c5d1SDavid du Colombier }else{ 9153e12c5d1SDavid du Colombier if(fc->width == ld) 9163e12c5d1SDavid du Colombier return; 9173e12c5d1SDavid du Colombier fc->width = ld; 9183e12c5d1SDavid du Colombier } 9193e12c5d1SDavid du Colombier text(t); 9203e12c5d1SDavid du Colombier t->parent->mod = 1; 9213e12c5d1SDavid du Colombier return; 9223e12c5d1SDavid du Colombier } 9233e12c5d1SDavid du Colombier if(strcmp(tag, "offset(hex)") == 0){ 9243e12c5d1SDavid du Colombier if(!strchr(hex, buf[0])){ 9253e12c5d1SDavid du Colombier illoff: 9263e12c5d1SDavid du Colombier mesg("illegal offset"); 9273e12c5d1SDavid du Colombier return; 9283e12c5d1SDavid du Colombier } 9293e12c5d1SDavid du Colombier s = 0; 9303e12c5d1SDavid du Colombier ld = strtoul(buf, &s, 16); 9313e12c5d1SDavid du Colombier if(*s) 9323e12c5d1SDavid du Colombier goto illoff; 9333e12c5d1SDavid du Colombier t->off = ld; 9343e12c5d1SDavid du Colombier text(t); 9353e12c5d1SDavid du Colombier for(nt=thing; nt; nt=nt->next) 9363e12c5d1SDavid du Colombier if(nt->parent == t) 9373e12c5d1SDavid du Colombier text(nt); 9383e12c5d1SDavid du Colombier return; 9393e12c5d1SDavid du Colombier } 9403e12c5d1SDavid du Colombier if(strcmp(tag, "n") == 0){ 9413e12c5d1SDavid du Colombier if(buf[0]<'0' || '9'<buf[0] || (w=atoi(buf))<=0){ 9423e12c5d1SDavid du Colombier mesg("illegal n"); 9433e12c5d1SDavid du Colombier return; 9443e12c5d1SDavid du Colombier } 9453e12c5d1SDavid du Colombier f = t->s; 9463e12c5d1SDavid du Colombier if(w == f->n) 9473e12c5d1SDavid du Colombier return; 9483e12c5d1SDavid du Colombier doredraw = 0; 9493e12c5d1SDavid du Colombier again: 9503e12c5d1SDavid du Colombier for(nt=thing; nt; nt=nt->next) 9513e12c5d1SDavid du Colombier if(nt->parent == t){ 9523e12c5d1SDavid du Colombier doredraw = 1; 9533e12c5d1SDavid du Colombier tclose1(nt); 9543e12c5d1SDavid du Colombier goto again; 9553e12c5d1SDavid du Colombier } 9563e12c5d1SDavid du Colombier r = t->b->r; 9573e12c5d1SDavid du Colombier if(w < f->n) 9583e12c5d1SDavid du Colombier r.max.x = f->info[w].x; 9593e12c5d1SDavid du Colombier b = balloc(r, t->b->ldepth); 9603e12c5d1SDavid du Colombier if(b == 0) 9613e12c5d1SDavid du Colombier goto nobmem; 9623e12c5d1SDavid du Colombier bitblt(b, b->r.min, t->b, r, S); 9633e12c5d1SDavid du Colombier fdx = Dx(editr) - 2*Border; 9643e12c5d1SDavid du Colombier if(Dx(t->b->r)/fdx != Dx(b->r)/fdx) 9653e12c5d1SDavid du Colombier doredraw = 1; 9663e12c5d1SDavid du Colombier bfree(t->b); 9673e12c5d1SDavid du Colombier t->b = b; 9683e12c5d1SDavid du Colombier b = balloc(r, t->b->ldepth); 9693e12c5d1SDavid du Colombier if(b == 0) 9703e12c5d1SDavid du Colombier goto nobmem; 9713e12c5d1SDavid du Colombier bitblt(b, b->r.min, t->b, r, S); 9723e12c5d1SDavid du Colombier nfc = malloc((w+1)*sizeof(Fontchar)); 9733e12c5d1SDavid du Colombier if(nfc == 0){ 9743e12c5d1SDavid du Colombier mesg("malloc failed"); 9753e12c5d1SDavid du Colombier bfree(b); 9763e12c5d1SDavid du Colombier return; 9773e12c5d1SDavid du Colombier } 9783e12c5d1SDavid du Colombier fc = f->info; 9793e12c5d1SDavid du Colombier for(i=0; i<=w && i<=f->n; i++) 9803e12c5d1SDavid du Colombier nfc[i] = fc[i]; 9813e12c5d1SDavid du Colombier if(w+1 < i) 9823e12c5d1SDavid du Colombier memset(nfc+i, 0, ((w+1)-i)*sizeof(Fontchar)); 9833e12c5d1SDavid du Colombier x = fc[f->n].x; 9843e12c5d1SDavid du Colombier for(; i<=w; i++) 9853e12c5d1SDavid du Colombier nfc[i].x = x; 9863e12c5d1SDavid du Colombier f = subfalloc(w, f->height, f->ascent, nfc, b, ~0, ~0); 9873e12c5d1SDavid du Colombier if(f == 0) 9883e12c5d1SDavid du Colombier goto nofmem; 9893e12c5d1SDavid du Colombier subffree(t->s); 9903e12c5d1SDavid du Colombier f->info = nfc; 9913e12c5d1SDavid du Colombier t->s = f; 9923e12c5d1SDavid du Colombier if(doredraw) 9933e12c5d1SDavid du Colombier redraw(thing); 9943e12c5d1SDavid du Colombier else 9953e12c5d1SDavid du Colombier draw(t, 0); 9963e12c5d1SDavid du Colombier t->mod = 1; 9973e12c5d1SDavid du Colombier return; 9983e12c5d1SDavid du Colombier } 9993e12c5d1SDavid du Colombier if(strcmp(tag, "iwidth") == 0){ 10003e12c5d1SDavid du Colombier if(buf[0]<'0' || '9'<buf[0] || (w=atoi(buf))<0){ 10013e12c5d1SDavid du Colombier mesg("illegal iwidth"); 10023e12c5d1SDavid du Colombier return; 10033e12c5d1SDavid du Colombier } 10043e12c5d1SDavid du Colombier w -= Dx(t->b->r); 10053e12c5d1SDavid du Colombier if(w == 0) 10063e12c5d1SDavid du Colombier return; 10073e12c5d1SDavid du Colombier r = t->parent->b->r; 10083e12c5d1SDavid du Colombier r.max.x += w; 10093e12c5d1SDavid du Colombier c = t->c; 10103e12c5d1SDavid du Colombier t = t->parent; 10113e12c5d1SDavid du Colombier f = t->s; 10123e12c5d1SDavid du Colombier b = balloc(r, t->b->ldepth); 10133e12c5d1SDavid du Colombier if(b == 0) 10143e12c5d1SDavid du Colombier goto nobmem; 10153e12c5d1SDavid du Colombier fc = &f->info[c]; 10163e12c5d1SDavid du Colombier bitblt(b, b->r.min, t->b, 10173e12c5d1SDavid du Colombier Rect(t->b->r.min.x, t->b->r.min.y, 10183e12c5d1SDavid du Colombier fc[1].x, t->b->r.max.y), S); 10193e12c5d1SDavid du Colombier bitblt(b, Pt(fc[1].x+w, b->r.min.y), t->b, 10203e12c5d1SDavid du Colombier Rect(fc[1].x, t->b->r.min.y, 10213e12c5d1SDavid du Colombier t->b->r.max.x, t->b->r.max.y), S); 10223e12c5d1SDavid du Colombier fdx = Dx(editr) - 2*Border; 10233e12c5d1SDavid du Colombier doredraw = 0; 10243e12c5d1SDavid du Colombier if(Dx(t->b->r)/fdx != Dx(b->r)/fdx) 10253e12c5d1SDavid du Colombier doredraw = 1; 10263e12c5d1SDavid du Colombier bfree(t->b); 10273e12c5d1SDavid du Colombier t->b = b; 10283e12c5d1SDavid du Colombier b = balloc(r, t->b->ldepth); 10293e12c5d1SDavid du Colombier if(b == 0) 10303e12c5d1SDavid du Colombier goto nobmem; 10313e12c5d1SDavid du Colombier bitblt(b, b->r.min, t->b, t->b->r, S); 10323e12c5d1SDavid du Colombier fc = &f->info[c+1]; 10333e12c5d1SDavid du Colombier for(i=c+1; i<=f->n; i++, fc++) 10343e12c5d1SDavid du Colombier fc->x += w; 10353e12c5d1SDavid du Colombier f = subfalloc(f->n, f->height, f->ascent, 10363e12c5d1SDavid du Colombier f->info, b, ~0, ~0); 10373e12c5d1SDavid du Colombier if(f == 0) 10383e12c5d1SDavid du Colombier goto nofmem; 10393e12c5d1SDavid du Colombier /* t->s and f share info; free carefully */ 10403e12c5d1SDavid du Colombier fc = f->info; 10413e12c5d1SDavid du Colombier t->s->info = 0; 10423e12c5d1SDavid du Colombier subffree(t->s); 10433e12c5d1SDavid du Colombier f->info = fc; 10443e12c5d1SDavid du Colombier t->s = f; 10453e12c5d1SDavid du Colombier if(doredraw) 10463e12c5d1SDavid du Colombier redraw(t); 10473e12c5d1SDavid du Colombier else 10483e12c5d1SDavid du Colombier draw(t, 0); 10493e12c5d1SDavid du Colombier /* redraw all affected chars */ 10503e12c5d1SDavid du Colombier for(nt=thing; nt; nt=nt->next){ 10513e12c5d1SDavid du Colombier if(nt->parent!=t || nt->c<c) 10523e12c5d1SDavid du Colombier continue; 10533e12c5d1SDavid du Colombier fc = &f->info[nt->c]; 10543e12c5d1SDavid du Colombier r.min.x = fc[0].x; 10553e12c5d1SDavid du Colombier r.min.y = nt->b->r.min.y; 10563e12c5d1SDavid du Colombier r.max.x = fc[1].x; 10573e12c5d1SDavid du Colombier r.max.y = nt->b->r.max.y; 10583e12c5d1SDavid du Colombier b = balloc(r, nt->b->ldepth); 10593e12c5d1SDavid du Colombier if(b == 0) 10603e12c5d1SDavid du Colombier goto nobmem; 10613e12c5d1SDavid du Colombier bitblt(b, r.min, t->b, r, S); 10623e12c5d1SDavid du Colombier doredraw = 0; 10633e12c5d1SDavid du Colombier if(Dx(nt->b->r)/fdx != Dx(b->r)/fdx) 10643e12c5d1SDavid du Colombier doredraw = 1; 10653e12c5d1SDavid du Colombier bfree(nt->b); 10663e12c5d1SDavid du Colombier nt->b = b; 10673e12c5d1SDavid du Colombier if(c != nt->c) 10683e12c5d1SDavid du Colombier text(nt); 10693e12c5d1SDavid du Colombier else{ 10703e12c5d1SDavid du Colombier if(doredraw) 10713e12c5d1SDavid du Colombier redraw(nt); 10723e12c5d1SDavid du Colombier else 10733e12c5d1SDavid du Colombier draw(nt, 0); 10743e12c5d1SDavid du Colombier } 10753e12c5d1SDavid du Colombier } 10763e12c5d1SDavid du Colombier t->mod = 1; 10773e12c5d1SDavid du Colombier return; 10783e12c5d1SDavid du Colombier } 10793e12c5d1SDavid du Colombier mesg("cannot edit %s in file %s", tag, t->name); 10803e12c5d1SDavid du Colombier } 10813e12c5d1SDavid du Colombier 10823e12c5d1SDavid du Colombier void 10833e12c5d1SDavid du Colombier cntledit(char *tag) 10843e12c5d1SDavid du Colombier { 10853e12c5d1SDavid du Colombier char buf[256]; 10863e12c5d1SDavid du Colombier char *p, *q; 10873e12c5d1SDavid du Colombier ulong l; 10883e12c5d1SDavid du Colombier int i, inv; 10893e12c5d1SDavid du Colombier 10903e12c5d1SDavid du Colombier buttons(Up); 10913e12c5d1SDavid du Colombier if(type(buf, tag) == 0) 10923e12c5d1SDavid du Colombier return; 10933e12c5d1SDavid du Colombier if(strcmp(tag, "mag") == 0){ 10943e12c5d1SDavid du Colombier if(buf[0]<'0' || '9'<buf[0] || (l=atoi(buf))<=0 || l>Maxmag){ 10953e12c5d1SDavid du Colombier mesg("illegal magnification"); 10963e12c5d1SDavid du Colombier return; 10973e12c5d1SDavid du Colombier } 10983e12c5d1SDavid du Colombier mag = l; 10993e12c5d1SDavid du Colombier cntl(); 11003e12c5d1SDavid du Colombier return; 11013e12c5d1SDavid du Colombier } 11023e12c5d1SDavid du Colombier if(strcmp(tag, "val(hex)") == 0){ 11033e12c5d1SDavid du Colombier inv = 0; 11043e12c5d1SDavid du Colombier p = buf; 11053e12c5d1SDavid du Colombier if(*p == '~'){ 11063e12c5d1SDavid du Colombier p++; 11073e12c5d1SDavid du Colombier inv = 1; 11083e12c5d1SDavid du Colombier } 11093e12c5d1SDavid du Colombier l = strtoul(p, &q, 16); 11103e12c5d1SDavid du Colombier if(l==0 && q==p){ 11113e12c5d1SDavid du Colombier mesg("illegal magnification"); 11123e12c5d1SDavid du Colombier return; 11133e12c5d1SDavid du Colombier } 11143e12c5d1SDavid du Colombier if(inv) 11153e12c5d1SDavid du Colombier l = ~l; 11163e12c5d1SDavid du Colombier val = l; 11173e12c5d1SDavid du Colombier cntl(); 11183e12c5d1SDavid du Colombier return; 11193e12c5d1SDavid du Colombier } 11203e12c5d1SDavid du Colombier if(strcmp(tag, "but1")==0 11213e12c5d1SDavid du Colombier || strcmp(tag, "but2")==0 11223e12c5d1SDavid du Colombier || strcmp(tag, "copy")==0){ 11233e12c5d1SDavid du Colombier i = strtofn(buf); 11243e12c5d1SDavid du Colombier if(i < 0){ 11253e12c5d1SDavid du Colombier mesg("unknown function"); 11263e12c5d1SDavid du Colombier return; 11273e12c5d1SDavid du Colombier } 11283e12c5d1SDavid du Colombier if(strcmp(tag, "but1") == 0) 11293e12c5d1SDavid du Colombier but1fn = i; 11303e12c5d1SDavid du Colombier else if(strcmp(tag, "but2") == 0) 11313e12c5d1SDavid du Colombier but2fn = i; 11323e12c5d1SDavid du Colombier else 11333e12c5d1SDavid du Colombier copyfn = i; 11343e12c5d1SDavid du Colombier cntl(); 11353e12c5d1SDavid du Colombier return; 11363e12c5d1SDavid du Colombier } 11373e12c5d1SDavid du Colombier mesg("cannot edit %s", tag); 11383e12c5d1SDavid du Colombier } 11393e12c5d1SDavid du Colombier 11403e12c5d1SDavid du Colombier void 11413e12c5d1SDavid du Colombier buttons(int ud) 11423e12c5d1SDavid du Colombier { 11433e12c5d1SDavid du Colombier while((mouse.buttons==0) != ud) 11443e12c5d1SDavid du Colombier mouse = emouse(); 11453e12c5d1SDavid du Colombier } 11463e12c5d1SDavid du Colombier 11473e12c5d1SDavid du Colombier int 11483e12c5d1SDavid du Colombier sweep(int butmask, Rectangle *r) 11493e12c5d1SDavid du Colombier { 11503e12c5d1SDavid du Colombier Point p; 11513e12c5d1SDavid du Colombier 11523e12c5d1SDavid du Colombier cursorswitch(&sweep0); 11533e12c5d1SDavid du Colombier buttons(Down); 11543e12c5d1SDavid du Colombier if(mouse.buttons != butmask){ 11553e12c5d1SDavid du Colombier buttons(Up); 11563e12c5d1SDavid du Colombier cursorswitch(0); 11573e12c5d1SDavid du Colombier return 0; 11583e12c5d1SDavid du Colombier } 11593e12c5d1SDavid du Colombier p = mouse.xy; 11603e12c5d1SDavid du Colombier cursorswitch(&box); 11613e12c5d1SDavid du Colombier r->min = p; 11623e12c5d1SDavid du Colombier r->max = p; 11633e12c5d1SDavid du Colombier while(mouse.buttons == butmask){ 11643e12c5d1SDavid du Colombier border(&screen, *r, -2, ~D); 11653e12c5d1SDavid du Colombier bflush(); 11663e12c5d1SDavid du Colombier mouse = emouse(); 11673e12c5d1SDavid du Colombier border(&screen, *r, -2, ~D); 11683e12c5d1SDavid du Colombier *r = rcanon(Rpt(p, mouse.xy)); 11693e12c5d1SDavid du Colombier } 11703e12c5d1SDavid du Colombier cursorswitch(0); 11713e12c5d1SDavid du Colombier if(mouse.buttons){ 11723e12c5d1SDavid du Colombier buttons(Up); 11733e12c5d1SDavid du Colombier return 0; 11743e12c5d1SDavid du Colombier } 11753e12c5d1SDavid du Colombier return 1; 11763e12c5d1SDavid du Colombier } 11773e12c5d1SDavid du Colombier 11783e12c5d1SDavid du Colombier void 11793e12c5d1SDavid du Colombier openedit(Thing *t, Point pt, int c) 11803e12c5d1SDavid du Colombier { 11813e12c5d1SDavid du Colombier int x, y; 11823e12c5d1SDavid du Colombier Point p; 11833e12c5d1SDavid du Colombier Rectangle r; 11843e12c5d1SDavid du Colombier Rectangle br; 11853e12c5d1SDavid du Colombier Fontchar *fc; 11863e12c5d1SDavid du Colombier Thing *nt; 11873e12c5d1SDavid du Colombier 11883e12c5d1SDavid du Colombier br = t->b->r; 11893e12c5d1SDavid du Colombier if(t->s == 0){ 11903e12c5d1SDavid du Colombier c = -1; 11913e12c5d1SDavid du Colombier /* if big enough to bother, sweep box */ 11923e12c5d1SDavid du Colombier if(Dx(br)<=16 && Dy(br)<=16) 11933e12c5d1SDavid du Colombier r = br; 11943e12c5d1SDavid du Colombier else{ 11953e12c5d1SDavid du Colombier if(!sweep(1, &r)) 11963e12c5d1SDavid du Colombier return; 11973e12c5d1SDavid du Colombier r = raddp(r, sub(br.min, t->r.min)); 11983e12c5d1SDavid du Colombier if(!rectclip(&r, br)) 11993e12c5d1SDavid du Colombier return; 12003e12c5d1SDavid du Colombier if(Dx(br) <= 8){ 12013e12c5d1SDavid du Colombier r.min.x = br.min.x; 12023e12c5d1SDavid du Colombier r.max.x = br.max.x; 12033e12c5d1SDavid du Colombier }else if(Dx(r) < 4){ 12043e12c5d1SDavid du Colombier toosmall: 12053e12c5d1SDavid du Colombier mesg("rectangle too small"); 12063e12c5d1SDavid du Colombier return; 12073e12c5d1SDavid du Colombier } 12083e12c5d1SDavid du Colombier if(Dy(br) <= 8){ 12093e12c5d1SDavid du Colombier r.min.y = br.min.y; 12103e12c5d1SDavid du Colombier r.max.y = br.max.y; 12113e12c5d1SDavid du Colombier }else if(Dy(r) < 4) 12123e12c5d1SDavid du Colombier goto toosmall; 12133e12c5d1SDavid du Colombier } 12143e12c5d1SDavid du Colombier }else if(c >= 0){ 12153e12c5d1SDavid du Colombier fc = &t->s->info[c]; 12163e12c5d1SDavid du Colombier r.min.x = fc[0].x; 12173e12c5d1SDavid du Colombier r.min.y = br.min.y; 12183e12c5d1SDavid du Colombier r.max.x = fc[1].x; 12193e12c5d1SDavid du Colombier r.max.y = br.min.y + Dy(br); 12203e12c5d1SDavid du Colombier }else{ 12213e12c5d1SDavid du Colombier /* just point at character */ 12223e12c5d1SDavid du Colombier fc = t->s->info; 12233e12c5d1SDavid du Colombier p = add(pt, sub(br.min, t->r.min)); 12243e12c5d1SDavid du Colombier x = br.min.x; 12253e12c5d1SDavid du Colombier y = br.min.y; 12263e12c5d1SDavid du Colombier for(c=0; c<t->s->n; c++,fc++){ 12273e12c5d1SDavid du Colombier again: 12283e12c5d1SDavid du Colombier r.min.x = x; 12293e12c5d1SDavid du Colombier r.min.y = y; 12303e12c5d1SDavid du Colombier r.max.x = x + fc[1].x - fc[0].x; 12313e12c5d1SDavid du Colombier r.max.y = y + Dy(br); 12323e12c5d1SDavid du Colombier if(ptinrect(p, r)) 12333e12c5d1SDavid du Colombier goto found; 12343e12c5d1SDavid du Colombier if(r.max.x >= br.min.x+Dx(t->r)){ 12353e12c5d1SDavid du Colombier x -= Dx(t->r); 12363e12c5d1SDavid du Colombier y += t->s->height; 12373e12c5d1SDavid du Colombier if(fc[1].x > fc[0].x) 12383e12c5d1SDavid du Colombier goto again; 12393e12c5d1SDavid du Colombier } 12403e12c5d1SDavid du Colombier x += fc[1].x - fc[0].x; 12413e12c5d1SDavid du Colombier } 12423e12c5d1SDavid du Colombier return; 12433e12c5d1SDavid du Colombier found: 12443e12c5d1SDavid du Colombier r = br; 12453e12c5d1SDavid du Colombier r.min.x = fc[0].x; 12463e12c5d1SDavid du Colombier r.max.x = fc[1].x; 12473e12c5d1SDavid du Colombier } 12483e12c5d1SDavid du Colombier nt = malloc(sizeof(Thing)); 12493e12c5d1SDavid du Colombier if(nt == 0){ 12503e12c5d1SDavid du Colombier nomem: 12513e12c5d1SDavid du Colombier mesg("can't allocate: %r"); 12523e12c5d1SDavid du Colombier return; 12533e12c5d1SDavid du Colombier } 12543e12c5d1SDavid du Colombier memset(nt, 0, sizeof(Thing)); 12553e12c5d1SDavid du Colombier nt->c = c; 12563e12c5d1SDavid du Colombier nt->b = balloc(r, t->b->ldepth); 12573e12c5d1SDavid du Colombier if(nt->b == 0){ 12583e12c5d1SDavid du Colombier free(nt); 12593e12c5d1SDavid du Colombier goto nomem; 12603e12c5d1SDavid du Colombier } 12613e12c5d1SDavid du Colombier bitblt(nt->b, r.min, t->b, r, S); 12623e12c5d1SDavid du Colombier nt->name = strdup(t->name); 12633e12c5d1SDavid du Colombier if(nt->name == 0){ 12643e12c5d1SDavid du Colombier bfree(nt->b); 12653e12c5d1SDavid du Colombier free(nt); 12663e12c5d1SDavid du Colombier goto nomem; 12673e12c5d1SDavid du Colombier } 12683e12c5d1SDavid du Colombier nt->parent = t; 12693e12c5d1SDavid du Colombier nt->mag = mag; 12703e12c5d1SDavid du Colombier draw(nt, 1); 12713e12c5d1SDavid du Colombier } 12723e12c5d1SDavid du Colombier 12733e12c5d1SDavid du Colombier void 12743e12c5d1SDavid du Colombier ckinfo(Thing *t, Rectangle mod) 12753e12c5d1SDavid du Colombier { 12763e12c5d1SDavid du Colombier int i, j, k, top, bot, n, zero; 12773e12c5d1SDavid du Colombier Fontchar *fc; 12783e12c5d1SDavid du Colombier Rectangle r; 12793e12c5d1SDavid du Colombier Bitmap *b; 12803e12c5d1SDavid du Colombier Thing *nt; 12813e12c5d1SDavid du Colombier 12823e12c5d1SDavid du Colombier if(t->parent) 12833e12c5d1SDavid du Colombier t = t->parent; 12843e12c5d1SDavid du Colombier if(t->s==0 || Dy(t->b->r)==0) 12853e12c5d1SDavid du Colombier return; 12863e12c5d1SDavid du Colombier b = 0; 12873e12c5d1SDavid du Colombier /* check bounding boxes */ 12883e12c5d1SDavid du Colombier fc = &t->s->info[0]; 12893e12c5d1SDavid du Colombier r.min.y = t->b->r.min.y; 12903e12c5d1SDavid du Colombier r.max.y = t->b->r.max.y; 12913e12c5d1SDavid du Colombier for(i=0; i<t->s->n; i++, fc++){ 12923e12c5d1SDavid du Colombier r.min.x = fc[0].x; 12933e12c5d1SDavid du Colombier r.max.x = fc[1].x; 12943e12c5d1SDavid du Colombier if(!rectXrect(mod, r)) 12953e12c5d1SDavid du Colombier continue; 12963e12c5d1SDavid du Colombier if(b==0 || Dx(b->r)<Dx(r)){ 12973e12c5d1SDavid du Colombier if(b) 12983e12c5d1SDavid du Colombier bfree(b); 12993e12c5d1SDavid du Colombier b = balloc(rsubp(r, r.min), t->b->ldepth); 13003e12c5d1SDavid du Colombier if(b == 0){ 13013e12c5d1SDavid du Colombier mesg("can't balloc"); 13023e12c5d1SDavid du Colombier break; 13033e12c5d1SDavid du Colombier } 13043e12c5d1SDavid du Colombier } 13053e12c5d1SDavid du Colombier bitblt(b, b->r.min, b, b->r, 0); 13063e12c5d1SDavid du Colombier bitblt(b, b->r.min, t->b, r, S); 13073e12c5d1SDavid du Colombier top = 100000; 13083e12c5d1SDavid du Colombier bot = 0; 13093e12c5d1SDavid du Colombier n = 2+(Dx(r)/8<<t->b->ldepth); 13103e12c5d1SDavid du Colombier for(j=0; j<b->r.max.y; j++){ 13113e12c5d1SDavid du Colombier memset(data, 0, n); 13123e12c5d1SDavid du Colombier rdbitmap(b, j, j+1, data); 13133e12c5d1SDavid du Colombier zero = 1; 13143e12c5d1SDavid du Colombier for(k=0; k<n; k++) 13153e12c5d1SDavid du Colombier if(data[k]){ 13163e12c5d1SDavid du Colombier zero = 0; 13173e12c5d1SDavid du Colombier break; 13183e12c5d1SDavid du Colombier } 13193e12c5d1SDavid du Colombier if(!zero){ 13203e12c5d1SDavid du Colombier if(top > j) 13213e12c5d1SDavid du Colombier top = j; 13223e12c5d1SDavid du Colombier bot = j+1; 13233e12c5d1SDavid du Colombier } 13243e12c5d1SDavid du Colombier } 13253e12c5d1SDavid du Colombier if(top > j) 13263e12c5d1SDavid du Colombier top = 0; 13273e12c5d1SDavid du Colombier if(top!=fc->top || bot!=fc->bottom){ 13283e12c5d1SDavid du Colombier fc->top = top; 13293e12c5d1SDavid du Colombier fc->bottom = bot; 13303e12c5d1SDavid du Colombier for(nt=thing; nt; nt=nt->next) 13313e12c5d1SDavid du Colombier if(nt->parent==t && nt->c==i) 13323e12c5d1SDavid du Colombier text(nt); 13333e12c5d1SDavid du Colombier } 13343e12c5d1SDavid du Colombier } 13353e12c5d1SDavid du Colombier if(b) 13363e12c5d1SDavid du Colombier bfree(b); 13373e12c5d1SDavid du Colombier } 13383e12c5d1SDavid du Colombier 13393e12c5d1SDavid du Colombier Point 13403e12c5d1SDavid du Colombier screenpt(Thing *t, Point realp) 13413e12c5d1SDavid du Colombier { 13423e12c5d1SDavid du Colombier int fdx, n; 13433e12c5d1SDavid du Colombier Point p; 13443e12c5d1SDavid du Colombier 13453e12c5d1SDavid du Colombier fdx = Dx(editr)-2*Border; 13463e12c5d1SDavid du Colombier if(t->mag > 1) 13473e12c5d1SDavid du Colombier fdx -= fdx%t->mag; 13483e12c5d1SDavid du Colombier p = mul(sub(realp, t->b->r.min), t->mag); 13493e12c5d1SDavid du Colombier if(fdx < Dx(t->b->r)*t->mag){ 13503e12c5d1SDavid du Colombier n = p.x/fdx; 13513e12c5d1SDavid du Colombier p.y += n * (Dy(t->b->r)*t->mag+Border); 13523e12c5d1SDavid du Colombier p.x -= n * fdx; 13533e12c5d1SDavid du Colombier } 13543e12c5d1SDavid du Colombier p = add(p, t->r.min); 13553e12c5d1SDavid du Colombier return p; 13563e12c5d1SDavid du Colombier } 13573e12c5d1SDavid du Colombier 13583e12c5d1SDavid du Colombier Point 13593e12c5d1SDavid du Colombier realpt(Thing *t, Point screenp) 13603e12c5d1SDavid du Colombier { 13613e12c5d1SDavid du Colombier int fdx, n, dy; 13623e12c5d1SDavid du Colombier Point p; 13633e12c5d1SDavid du Colombier 13643e12c5d1SDavid du Colombier fdx = (Dx(editr)-2*Border); 13653e12c5d1SDavid du Colombier if(t->mag > 1) 13663e12c5d1SDavid du Colombier fdx -= fdx%t->mag; 13673e12c5d1SDavid du Colombier p.y = screenp.y-t->r.min.y; 13683e12c5d1SDavid du Colombier p.x = 0; 13693e12c5d1SDavid du Colombier if(fdx < Dx(t->b->r)*t->mag){ 13703e12c5d1SDavid du Colombier dy = Dy(t->b->r)*t->mag+Border; 13713e12c5d1SDavid du Colombier n = (p.y/dy); 13723e12c5d1SDavid du Colombier p.x = n * fdx; 13733e12c5d1SDavid du Colombier p.y -= n * dy; 13743e12c5d1SDavid du Colombier } 13753e12c5d1SDavid du Colombier p.x += screenp.x-t->r.min.x; 13763e12c5d1SDavid du Colombier p = add(div(p, t->mag), t->b->r.min); 13773e12c5d1SDavid du Colombier return p; 13783e12c5d1SDavid du Colombier } 13793e12c5d1SDavid du Colombier 13803e12c5d1SDavid du Colombier void 13813e12c5d1SDavid du Colombier twidpix(Thing *t, Point p, int set) 13823e12c5d1SDavid du Colombier { 13833e12c5d1SDavid du Colombier Bitmap *b; 13843e12c5d1SDavid du Colombier int v, c; 13853e12c5d1SDavid du Colombier 13863e12c5d1SDavid du Colombier c = but1fn; 13873e12c5d1SDavid du Colombier if(!set) 13883e12c5d1SDavid du Colombier c = but2fn; 13893e12c5d1SDavid du Colombier b = t->b; 13903e12c5d1SDavid du Colombier if(!ptinrect(p, b->r)) 13913e12c5d1SDavid du Colombier return; 13923e12c5d1SDavid du Colombier point(b, p, val, c); 13933e12c5d1SDavid du Colombier v = bvalue(val, b->ldepth); 13943e12c5d1SDavid du Colombier p = screenpt(t, p); 13953e12c5d1SDavid du Colombier bitblt(&screen, p, values, Rect(v, 0, v+t->mag, t->mag), c); 13963e12c5d1SDavid du Colombier } 13973e12c5d1SDavid du Colombier 13983e12c5d1SDavid du Colombier void 13993e12c5d1SDavid du Colombier twiddle(Thing *t) 14003e12c5d1SDavid du Colombier { 14013e12c5d1SDavid du Colombier int set; 14023e12c5d1SDavid du Colombier Point p, lastp; 14033e12c5d1SDavid du Colombier Bitmap *b; 14043e12c5d1SDavid du Colombier Thing *nt; 14053e12c5d1SDavid du Colombier Rectangle mod; 14063e12c5d1SDavid du Colombier 14073e12c5d1SDavid du Colombier if(mouse.buttons!=1 && mouse.buttons!=2){ 14083e12c5d1SDavid du Colombier buttons(Up); 14093e12c5d1SDavid du Colombier return; 14103e12c5d1SDavid du Colombier } 14113e12c5d1SDavid du Colombier set = mouse.buttons==1; 14123e12c5d1SDavid du Colombier b = t->b; 14133e12c5d1SDavid du Colombier lastp = add(b->r.min, Pt(-1, -1)); 14143e12c5d1SDavid du Colombier mod = Rpt(add(b->r.max, Pt(1, 1)), lastp); 14153e12c5d1SDavid du Colombier while(mouse.buttons){ 14163e12c5d1SDavid du Colombier p = realpt(t, mouse.xy); 14173e12c5d1SDavid du Colombier if(!eqpt(p, lastp)){ 14183e12c5d1SDavid du Colombier lastp = p; 14193e12c5d1SDavid du Colombier if(ptinrect(p, b->r)){ 14203e12c5d1SDavid du Colombier for(nt=thing; nt; nt=nt->next) 14213e12c5d1SDavid du Colombier if(nt->parent==t->parent || nt==t->parent) 14223e12c5d1SDavid du Colombier twidpix(nt, p, set); 14233e12c5d1SDavid du Colombier if(t->parent) 14243e12c5d1SDavid du Colombier t->parent->mod = 1; 14253e12c5d1SDavid du Colombier else 14263e12c5d1SDavid du Colombier t->mod = 1; 14273e12c5d1SDavid du Colombier if(p.x < mod.min.x) 14283e12c5d1SDavid du Colombier mod.min.x = p.x; 14293e12c5d1SDavid du Colombier if(p.y < mod.min.y) 14303e12c5d1SDavid du Colombier mod.min.y = p.y; 14313e12c5d1SDavid du Colombier if(p.x >= mod.max.x) 14323e12c5d1SDavid du Colombier mod.max.x = p.x+1; 14333e12c5d1SDavid du Colombier if(p.y >= mod.max.y) 14343e12c5d1SDavid du Colombier mod.max.y = p.y+1; 14353e12c5d1SDavid du Colombier } 14363e12c5d1SDavid du Colombier } 14373e12c5d1SDavid du Colombier mouse = emouse(); 14383e12c5d1SDavid du Colombier } 14393e12c5d1SDavid du Colombier ckinfo(t, mod); 14403e12c5d1SDavid du Colombier } 14413e12c5d1SDavid du Colombier 14423e12c5d1SDavid du Colombier void 14433e12c5d1SDavid du Colombier select(void) 14443e12c5d1SDavid du Colombier { 14453e12c5d1SDavid du Colombier Thing *t; 14463e12c5d1SDavid du Colombier char line[128], buf[128]; 14473e12c5d1SDavid du Colombier Point p; 14483e12c5d1SDavid du Colombier 14493e12c5d1SDavid du Colombier if(ptinrect(mouse.xy, cntlr)){ 14503e12c5d1SDavid du Colombier scntl(line); 14513e12c5d1SDavid du Colombier if(atline(cntlr.min.x, mouse.xy, line, buf)){ 14523e12c5d1SDavid du Colombier if(mouse.buttons == 1) 14533e12c5d1SDavid du Colombier cntledit(buf); 14543e12c5d1SDavid du Colombier else 14553e12c5d1SDavid du Colombier buttons(Up); 14563e12c5d1SDavid du Colombier return; 14573e12c5d1SDavid du Colombier } 14583e12c5d1SDavid du Colombier return; 14593e12c5d1SDavid du Colombier } 14603e12c5d1SDavid du Colombier for(t=thing; t; t=t->next){ 14613e12c5d1SDavid du Colombier if(attext(t, mouse.xy, buf)){ 14623e12c5d1SDavid du Colombier if(mouse.buttons == 1) 14633e12c5d1SDavid du Colombier textedit(t, buf); 14643e12c5d1SDavid du Colombier else 14653e12c5d1SDavid du Colombier buttons(Up); 14663e12c5d1SDavid du Colombier return; 14673e12c5d1SDavid du Colombier } 14683e12c5d1SDavid du Colombier if(ptinrect(mouse.xy, t->r)){ 14693e12c5d1SDavid du Colombier if(t->parent == 0){ 14703e12c5d1SDavid du Colombier if(mouse.buttons == 1){ 14713e12c5d1SDavid du Colombier p = mouse.xy; 14723e12c5d1SDavid du Colombier buttons(Up); 14733e12c5d1SDavid du Colombier openedit(t, p, -1); 14743e12c5d1SDavid du Colombier }else 14753e12c5d1SDavid du Colombier buttons(Up); 14763e12c5d1SDavid du Colombier return; 14773e12c5d1SDavid du Colombier } 14783e12c5d1SDavid du Colombier twiddle(t); 14793e12c5d1SDavid du Colombier return; 14803e12c5d1SDavid du Colombier } 14813e12c5d1SDavid du Colombier } 14823e12c5d1SDavid du Colombier } 14833e12c5d1SDavid du Colombier 14843e12c5d1SDavid du Colombier void 14853e12c5d1SDavid du Colombier twrite(Thing *t) 14863e12c5d1SDavid du Colombier { 14873e12c5d1SDavid du Colombier int i, j, x, y, fd, ws, ld; 14883e12c5d1SDavid du Colombier Biobuf buf; 14893e12c5d1SDavid du Colombier Rectangle r; 14903e12c5d1SDavid du Colombier 14913e12c5d1SDavid du Colombier if(t->parent) 14923e12c5d1SDavid du Colombier t = t->parent; 14933e12c5d1SDavid du Colombier cursorswitch(&busy); 14943e12c5d1SDavid du Colombier fd = create(t->name, OWRITE, 0666); 14953e12c5d1SDavid du Colombier if(fd < 0){ 14963e12c5d1SDavid du Colombier mesg("can't write %s: %r", t->name); 14973e12c5d1SDavid du Colombier return; 14983e12c5d1SDavid du Colombier } 14993e12c5d1SDavid du Colombier if(t->face){ 15003e12c5d1SDavid du Colombier r = t->b->r; 15013e12c5d1SDavid du Colombier ld = t->b->ldepth; 15023e12c5d1SDavid du Colombier /* This heuristic reflects peculiarly different formats */ 15033e12c5d1SDavid du Colombier ws = 4; 15043e12c5d1SDavid du Colombier if(Dx(r) == 16) /* probably cursor file */ 15053e12c5d1SDavid du Colombier ws = 1; 15063e12c5d1SDavid du Colombier else if(Dx(r)<32 || ld==0) 15073e12c5d1SDavid du Colombier ws = 2; 15083e12c5d1SDavid du Colombier Binit(&buf, fd, OWRITE); 15093e12c5d1SDavid du Colombier for(y=r.min.y; y<r.max.y; y++){ 15103e12c5d1SDavid du Colombier rdbitmap(t->b, y, y+1, data); 15113e12c5d1SDavid du Colombier j = 0; 15123e12c5d1SDavid du Colombier for(x=r.min.x; x<r.max.x; j+=ws,x+=ws*8>>ld){ 15133e12c5d1SDavid du Colombier Bprint(&buf, "0x"); 15143e12c5d1SDavid du Colombier for(i=0; i<ws; i++) 15153e12c5d1SDavid du Colombier Bprint(&buf, "%.2x", data[i+j]); 15163e12c5d1SDavid du Colombier Bprint(&buf, ", "); 15173e12c5d1SDavid du Colombier } 15183e12c5d1SDavid du Colombier Bprint(&buf, "\n"); 15193e12c5d1SDavid du Colombier } 1520*219b2ee8SDavid du Colombier Bterm(&buf); 15213e12c5d1SDavid du Colombier }else{ 15223e12c5d1SDavid du Colombier wrbitmapfile(fd, t->b); 15233e12c5d1SDavid du Colombier if(t->s) 15243e12c5d1SDavid du Colombier wrsubfontfile(fd, t->s); 15253e12c5d1SDavid du Colombier } 15263e12c5d1SDavid du Colombier t->mod = 0; 15273e12c5d1SDavid du Colombier close(fd); 15283e12c5d1SDavid du Colombier mesg("wrote %s", t->name); 15293e12c5d1SDavid du Colombier } 15303e12c5d1SDavid du Colombier 15313e12c5d1SDavid du Colombier void 15323e12c5d1SDavid du Colombier tclose1(Thing *t) 15333e12c5d1SDavid du Colombier { 15343e12c5d1SDavid du Colombier Thing *nt; 15353e12c5d1SDavid du Colombier 15363e12c5d1SDavid du Colombier if(t == thing) 15373e12c5d1SDavid du Colombier thing = t->next; 15383e12c5d1SDavid du Colombier else{ 15393e12c5d1SDavid du Colombier for(nt=thing; nt->next!=t; nt=nt->next) 15403e12c5d1SDavid du Colombier ; 15413e12c5d1SDavid du Colombier nt->next = t->next; 15423e12c5d1SDavid du Colombier } 15433e12c5d1SDavid du Colombier do 15443e12c5d1SDavid du Colombier for(nt=thing; nt; nt=nt->next) 15453e12c5d1SDavid du Colombier if(nt->parent == t){ 15463e12c5d1SDavid du Colombier tclose1(nt); 15473e12c5d1SDavid du Colombier break; 15483e12c5d1SDavid du Colombier } 15493e12c5d1SDavid du Colombier while(nt); 15503e12c5d1SDavid du Colombier if(t->s) 15513e12c5d1SDavid du Colombier subffree(t->s); 15523e12c5d1SDavid du Colombier bfree(t->b); 15533e12c5d1SDavid du Colombier free(t->name); 15543e12c5d1SDavid du Colombier free(t); 15553e12c5d1SDavid du Colombier } 15563e12c5d1SDavid du Colombier 15573e12c5d1SDavid du Colombier void 15583e12c5d1SDavid du Colombier tclose(Thing *t) 15593e12c5d1SDavid du Colombier { 15603e12c5d1SDavid du Colombier Thing *ct; 15613e12c5d1SDavid du Colombier 15623e12c5d1SDavid du Colombier if(t->mod){ 15633e12c5d1SDavid du Colombier mesg("%s modified", t->name); 15643e12c5d1SDavid du Colombier t->mod = 0; 15653e12c5d1SDavid du Colombier return; 15663e12c5d1SDavid du Colombier } 15673e12c5d1SDavid du Colombier /* fiddle to save redrawing unmoved things */ 15683e12c5d1SDavid du Colombier if(t == thing) 15693e12c5d1SDavid du Colombier ct = 0; 15703e12c5d1SDavid du Colombier else 15713e12c5d1SDavid du Colombier for(ct=thing; ct; ct=ct->next) 15723e12c5d1SDavid du Colombier if(ct->next==t || ct->next->parent==t) 15733e12c5d1SDavid du Colombier break; 15743e12c5d1SDavid du Colombier tclose1(t); 15753e12c5d1SDavid du Colombier if(ct) 15763e12c5d1SDavid du Colombier ct = ct->next; 15773e12c5d1SDavid du Colombier else 15783e12c5d1SDavid du Colombier ct = thing; 15793e12c5d1SDavid du Colombier redraw(ct); 15803e12c5d1SDavid du Colombier } 15813e12c5d1SDavid du Colombier 15823e12c5d1SDavid du Colombier void 15833e12c5d1SDavid du Colombier tread(Thing *t) 15843e12c5d1SDavid du Colombier { 15853e12c5d1SDavid du Colombier Thing *nt, *new; 15863e12c5d1SDavid du Colombier Fontchar *i; 15873e12c5d1SDavid du Colombier Rectangle r; 15883e12c5d1SDavid du Colombier int nclosed; 15893e12c5d1SDavid du Colombier 15903e12c5d1SDavid du Colombier if(t->parent) 15913e12c5d1SDavid du Colombier t = t->parent; 15923e12c5d1SDavid du Colombier new = tget(t->name); 15933e12c5d1SDavid du Colombier if(new == 0) 15943e12c5d1SDavid du Colombier return; 15953e12c5d1SDavid du Colombier nclosed = 0; 15963e12c5d1SDavid du Colombier again: 15973e12c5d1SDavid du Colombier for(nt=thing; nt; nt=nt->next) 15983e12c5d1SDavid du Colombier if(nt->parent == t){ 15993e12c5d1SDavid du Colombier if(!rectinrect(nt->b->r, new->b->r) 16003e12c5d1SDavid du Colombier || new->b->ldepth!=nt->b->ldepth){ 16013e12c5d1SDavid du Colombier closeit: 16023e12c5d1SDavid du Colombier nclosed++; 16033e12c5d1SDavid du Colombier nt->parent = 0; 16043e12c5d1SDavid du Colombier tclose1(nt); 16053e12c5d1SDavid du Colombier goto again; 16063e12c5d1SDavid du Colombier } 16073e12c5d1SDavid du Colombier if((t->s==0) != (new->s==0)) 16083e12c5d1SDavid du Colombier goto closeit; 16093e12c5d1SDavid du Colombier if((t->face==0) != (new->face==0)) 16103e12c5d1SDavid du Colombier goto closeit; 16113e12c5d1SDavid du Colombier if(t->s){ /* check same char */ 16123e12c5d1SDavid du Colombier if(nt->c >= new->s->n) 16133e12c5d1SDavid du Colombier goto closeit; 16143e12c5d1SDavid du Colombier i = &new->s->info[nt->c]; 16153e12c5d1SDavid du Colombier r.min.x = i[0].x; 16163e12c5d1SDavid du Colombier r.max.x = i[1].x; 16173e12c5d1SDavid du Colombier r.min.y = new->b->r.min.y; 16183e12c5d1SDavid du Colombier r.max.y = new->b->r.max.y; 16193e12c5d1SDavid du Colombier if(!eqrect(r, nt->b->r)) 16203e12c5d1SDavid du Colombier goto closeit; 16213e12c5d1SDavid du Colombier } 16223e12c5d1SDavid du Colombier nt->parent = new; 16233e12c5d1SDavid du Colombier bitblt(nt->b, nt->b->r.min, new->b, 16243e12c5d1SDavid du Colombier nt->b->r, S); 16253e12c5d1SDavid du Colombier } 16263e12c5d1SDavid du Colombier new->next = t->next; 16273e12c5d1SDavid du Colombier if(t == thing) 16283e12c5d1SDavid du Colombier thing = new; 16293e12c5d1SDavid du Colombier else{ 16303e12c5d1SDavid du Colombier for(nt=thing; nt->next!=t; nt=nt->next) 16313e12c5d1SDavid du Colombier ; 16323e12c5d1SDavid du Colombier nt->next = new; 16333e12c5d1SDavid du Colombier } 16343e12c5d1SDavid du Colombier if(t->s) 16353e12c5d1SDavid du Colombier subffree(t->s); 16363e12c5d1SDavid du Colombier bfree(t->b); 16373e12c5d1SDavid du Colombier free(t->name); 16383e12c5d1SDavid du Colombier free(t); 16393e12c5d1SDavid du Colombier for(nt=thing; nt; nt=nt->next) 16403e12c5d1SDavid du Colombier if(nt==new || nt->parent==new) 16413e12c5d1SDavid du Colombier if(nclosed == 0) 16423e12c5d1SDavid du Colombier draw(nt, 0); /* can draw in place */ 16433e12c5d1SDavid du Colombier else{ 16443e12c5d1SDavid du Colombier redraw(nt); /* must redraw all below */ 16453e12c5d1SDavid du Colombier break; 16463e12c5d1SDavid du Colombier } 16473e12c5d1SDavid du Colombier } 16483e12c5d1SDavid du Colombier 16493e12c5d1SDavid du Colombier void 16503e12c5d1SDavid du Colombier tchar(Thing *t) 16513e12c5d1SDavid du Colombier { 1652*219b2ee8SDavid du Colombier char buf[256], *p; 16533e12c5d1SDavid du Colombier Rune r; 1654*219b2ee8SDavid du Colombier ulong c, d; 16553e12c5d1SDavid du Colombier 16563e12c5d1SDavid du Colombier if(t->s == 0){ 16573e12c5d1SDavid du Colombier mesg("not a subfont"); 16583e12c5d1SDavid du Colombier return; 16593e12c5d1SDavid du Colombier } 1660*219b2ee8SDavid du Colombier if(type(buf, "char (hex or character or hex-hex)") == 0) 16613e12c5d1SDavid du Colombier return; 16623e12c5d1SDavid du Colombier if(utflen(buf) == 1){ 16633e12c5d1SDavid du Colombier chartorune(&r, buf); 16643e12c5d1SDavid du Colombier c = r; 1665*219b2ee8SDavid du Colombier d = r; 16663e12c5d1SDavid du Colombier }else{ 16673e12c5d1SDavid du Colombier if(!strchr(hex, buf[0])){ 16683e12c5d1SDavid du Colombier mesg("illegal hex character"); 16693e12c5d1SDavid du Colombier return; 16703e12c5d1SDavid du Colombier } 16713e12c5d1SDavid du Colombier c = strtoul(buf, 0, 16); 1672*219b2ee8SDavid du Colombier d = c; 1673*219b2ee8SDavid du Colombier p = utfrune(buf, '-'); 1674*219b2ee8SDavid du Colombier if(p){ 1675*219b2ee8SDavid du Colombier d = strtoul(p+1, 0, 16); 1676*219b2ee8SDavid du Colombier if(d < c){ 1677*219b2ee8SDavid du Colombier mesg("invalid range"); 1678*219b2ee8SDavid du Colombier return; 1679*219b2ee8SDavid du Colombier } 1680*219b2ee8SDavid du Colombier } 16813e12c5d1SDavid du Colombier } 16823e12c5d1SDavid du Colombier c -= t->off; 1683*219b2ee8SDavid du Colombier d -= t->off; 1684*219b2ee8SDavid du Colombier while(c <= d){ 16853e12c5d1SDavid du Colombier if(c<0 || c>=t->s->n){ 16863e12c5d1SDavid du Colombier mesg("0x%lux not in font %s", c+t->off, t->name); 16873e12c5d1SDavid du Colombier return; 16883e12c5d1SDavid du Colombier } 16893e12c5d1SDavid du Colombier openedit(t, Pt(0, 0), c); 1690*219b2ee8SDavid du Colombier c++; 1691*219b2ee8SDavid du Colombier } 16923e12c5d1SDavid du Colombier } 16933e12c5d1SDavid du Colombier 16943e12c5d1SDavid du Colombier void 16953e12c5d1SDavid du Colombier apply(void (*f)(Thing*)) 16963e12c5d1SDavid du Colombier { 16973e12c5d1SDavid du Colombier Thing *t; 16983e12c5d1SDavid du Colombier 16993e12c5d1SDavid du Colombier cursorswitch(&sight); 17003e12c5d1SDavid du Colombier buttons(Down); 17013e12c5d1SDavid du Colombier if(mouse.buttons == 4) 17023e12c5d1SDavid du Colombier for(t=thing; t; t=t->next) 17033e12c5d1SDavid du Colombier if(ptinrect(mouse.xy, t->er)){ 17043e12c5d1SDavid du Colombier buttons(Up); 17053e12c5d1SDavid du Colombier f(t); 17063e12c5d1SDavid du Colombier break; 17073e12c5d1SDavid du Colombier } 17083e12c5d1SDavid du Colombier buttons(Up); 17093e12c5d1SDavid du Colombier cursorswitch(0); 17103e12c5d1SDavid du Colombier } 17113e12c5d1SDavid du Colombier 17123e12c5d1SDavid du Colombier void 17133e12c5d1SDavid du Colombier copy(void) 17143e12c5d1SDavid du Colombier { 17153e12c5d1SDavid du Colombier Thing *st, *dt, *nt; 17163e12c5d1SDavid du Colombier Rectangle sr, dr, fr; 17173e12c5d1SDavid du Colombier Point p1, p2; 17183e12c5d1SDavid du Colombier int but, up; 17193e12c5d1SDavid du Colombier 17203e12c5d1SDavid du Colombier if(!sweep(4, &sr)) 17213e12c5d1SDavid du Colombier return; 17223e12c5d1SDavid du Colombier for(st=thing; st; st=st->next) 17233e12c5d1SDavid du Colombier if(rectXrect(sr, st->r)) 17243e12c5d1SDavid du Colombier break; 17253e12c5d1SDavid du Colombier if(st == 0) 17263e12c5d1SDavid du Colombier return; 17273e12c5d1SDavid du Colombier /* click gives full rectangle */ 17283e12c5d1SDavid du Colombier if(Dx(sr)<4 && Dy(sr)<4) 17293e12c5d1SDavid du Colombier sr = st->r; 17303e12c5d1SDavid du Colombier rectclip(&sr, st->r); 17313e12c5d1SDavid du Colombier p1 = realpt(st, sr.min); 17323e12c5d1SDavid du Colombier p2 = realpt(st, Pt(sr.min.x, sr.max.y)); 17333e12c5d1SDavid du Colombier if(p1.x != p2.x){ /* swept across a fold */ 17343e12c5d1SDavid du Colombier onafold: 17353e12c5d1SDavid du Colombier mesg("sweep spans a fold"); 17363e12c5d1SDavid du Colombier return; 17373e12c5d1SDavid du Colombier } 17383e12c5d1SDavid du Colombier p2 = realpt(st, sr.max); 17393e12c5d1SDavid du Colombier sr.min = p1; 17403e12c5d1SDavid du Colombier sr.max = p2; 17413e12c5d1SDavid du Colombier fr.min = screenpt(st, sr.min); 17423e12c5d1SDavid du Colombier fr.max = screenpt(st, sr.max); 17433e12c5d1SDavid du Colombier border(&screen, fr, -3, ~D); 17443e12c5d1SDavid du Colombier p1 = sub(p2, p1); /* diagonal */ 17453e12c5d1SDavid du Colombier if(p1.x==0 || p1.y==0){ 17463e12c5d1SDavid du Colombier Return: 17473e12c5d1SDavid du Colombier border(&screen, fr, -3, ~D); 17483e12c5d1SDavid du Colombier return; 17493e12c5d1SDavid du Colombier } 17503e12c5d1SDavid du Colombier cursorswitch(&box); 17513e12c5d1SDavid du Colombier up = 0; 17523e12c5d1SDavid du Colombier for(; mouse.buttons==0; mouse=emouse()){ 17533e12c5d1SDavid du Colombier for(dt=thing; dt; dt=dt->next) 17543e12c5d1SDavid du Colombier if(ptinrect(mouse.xy, dt->er)) 17553e12c5d1SDavid du Colombier break; 17563e12c5d1SDavid du Colombier if(up) 17573e12c5d1SDavid du Colombier border(&screen, dr, -2, ~D); 17583e12c5d1SDavid du Colombier up = 0; 17593e12c5d1SDavid du Colombier if(dt == 0) 17603e12c5d1SDavid du Colombier continue; 17613e12c5d1SDavid du Colombier dr.max = screenpt(dt, realpt(dt, mouse.xy)); 17623e12c5d1SDavid du Colombier dr.min = sub(dr.max, mul(p1, dt->mag)); 17633e12c5d1SDavid du Colombier if(!rectXrect(dr, dt->r)) 17643e12c5d1SDavid du Colombier continue; 17653e12c5d1SDavid du Colombier border(&screen, dr, -2, ~D); 17663e12c5d1SDavid du Colombier up = 1; 17673e12c5d1SDavid du Colombier } 17683e12c5d1SDavid du Colombier /* if up==1, we had a hit */ 17693e12c5d1SDavid du Colombier cursorswitch(0); 17703e12c5d1SDavid du Colombier if(up) 17713e12c5d1SDavid du Colombier border(&screen, dr, -2, ~D); 17723e12c5d1SDavid du Colombier but = mouse.buttons; 17733e12c5d1SDavid du Colombier border(&screen, fr, -3, ~D); 17743e12c5d1SDavid du Colombier buttons(Up); 17753e12c5d1SDavid du Colombier if(!up || but!=4) 17763e12c5d1SDavid du Colombier return; 17773e12c5d1SDavid du Colombier dt = 0; 17783e12c5d1SDavid du Colombier for(nt=thing; nt; nt=nt->next) 17793e12c5d1SDavid du Colombier if(rectXrect(dr, nt->r)){ 17803e12c5d1SDavid du Colombier if(dt){ 17813e12c5d1SDavid du Colombier mesg("ambiguous sweep"); 17823e12c5d1SDavid du Colombier return; 17833e12c5d1SDavid du Colombier } 17843e12c5d1SDavid du Colombier dt = nt; 17853e12c5d1SDavid du Colombier } 17863e12c5d1SDavid du Colombier if(dt == 0) 17873e12c5d1SDavid du Colombier return; 17883e12c5d1SDavid du Colombier p1 = realpt(dt, dr.min); 17893e12c5d1SDavid du Colombier p2 = realpt(dt, Pt(dr.min.x, dr.max.y)); 17903e12c5d1SDavid du Colombier if(p1.x != p2.x) 17913e12c5d1SDavid du Colombier goto onafold; 17923e12c5d1SDavid du Colombier p2 = realpt(dt, dr.max); 17933e12c5d1SDavid du Colombier dr.min = p1; 17943e12c5d1SDavid du Colombier dr.max = p2; 17953e12c5d1SDavid du Colombier bitblt(dt->b, dr.min, st->b, sr, copyfn); 17963e12c5d1SDavid du Colombier if(dt->parent){ 17973e12c5d1SDavid du Colombier bitblt(dt->parent->b, dr.min, dt->b, dr, S); 17983e12c5d1SDavid du Colombier dt = dt->parent; 17993e12c5d1SDavid du Colombier } 18003e12c5d1SDavid du Colombier draw(dt, 0); 18013e12c5d1SDavid du Colombier for(nt=thing; nt; nt=nt->next) 18023e12c5d1SDavid du Colombier if(nt->parent==dt && rectXrect(dr, nt->b->r)){ 18033e12c5d1SDavid du Colombier bitblt(nt->b, dr.min, dt->b, dr, S); 18043e12c5d1SDavid du Colombier draw(nt, 0); 18053e12c5d1SDavid du Colombier } 18063e12c5d1SDavid du Colombier ckinfo(dt, dr); 18073e12c5d1SDavid du Colombier dt->mod = 1; 18083e12c5d1SDavid du Colombier } 18093e12c5d1SDavid du Colombier 18103e12c5d1SDavid du Colombier void 18113e12c5d1SDavid du Colombier menu(void) 18123e12c5d1SDavid du Colombier { 18133e12c5d1SDavid du Colombier Thing *t; 18143e12c5d1SDavid du Colombier char *mod; 18153e12c5d1SDavid du Colombier int sel; 18163e12c5d1SDavid du Colombier char buf[256]; 18173e12c5d1SDavid du Colombier 18183e12c5d1SDavid du Colombier sel = menuhit(3, &mouse, &menu3); 18193e12c5d1SDavid du Colombier switch(sel){ 18203e12c5d1SDavid du Colombier case Mopen: 18213e12c5d1SDavid du Colombier if(type(buf, "file")){ 18223e12c5d1SDavid du Colombier t = tget(buf); 18233e12c5d1SDavid du Colombier if(t) 18243e12c5d1SDavid du Colombier draw(t, 1); 18253e12c5d1SDavid du Colombier } 18263e12c5d1SDavid du Colombier break; 18273e12c5d1SDavid du Colombier case Mwrite: 18283e12c5d1SDavid du Colombier apply(twrite); 18293e12c5d1SDavid du Colombier break; 18303e12c5d1SDavid du Colombier case Mread: 18313e12c5d1SDavid du Colombier apply(tread); 18323e12c5d1SDavid du Colombier break; 18333e12c5d1SDavid du Colombier case Mchar: 18343e12c5d1SDavid du Colombier apply(tchar); 18353e12c5d1SDavid du Colombier break; 18363e12c5d1SDavid du Colombier case Mcopy: 18373e12c5d1SDavid du Colombier copy(); 18383e12c5d1SDavid du Colombier break; 18393e12c5d1SDavid du Colombier case Mclose: 18403e12c5d1SDavid du Colombier apply(tclose); 18413e12c5d1SDavid du Colombier break; 18423e12c5d1SDavid du Colombier case Mexit: 18433e12c5d1SDavid du Colombier mod = 0; 18443e12c5d1SDavid du Colombier for(t=thing; t; t=t->next) 18453e12c5d1SDavid du Colombier if(t->mod){ 18463e12c5d1SDavid du Colombier mod = t->name; 18473e12c5d1SDavid du Colombier t->mod = 0; 18483e12c5d1SDavid du Colombier } 18493e12c5d1SDavid du Colombier if(mod){ 18503e12c5d1SDavid du Colombier mesg("%s modified", mod); 18513e12c5d1SDavid du Colombier break; 18523e12c5d1SDavid du Colombier } 18533e12c5d1SDavid du Colombier cursorswitch(&skull); 18543e12c5d1SDavid du Colombier buttons(Down); 18553e12c5d1SDavid du Colombier if(mouse.buttons == 4){ 18563e12c5d1SDavid du Colombier buttons(Up); 18573e12c5d1SDavid du Colombier exits(0); 18583e12c5d1SDavid du Colombier } 18593e12c5d1SDavid du Colombier buttons(Up); 18603e12c5d1SDavid du Colombier cursorswitch(0); 18613e12c5d1SDavid du Colombier break; 18623e12c5d1SDavid du Colombier } 18633e12c5d1SDavid du Colombier } 18643e12c5d1SDavid du Colombier 18653e12c5d1SDavid du Colombier char* 18663e12c5d1SDavid du Colombier fntostr(uint f) 18673e12c5d1SDavid du Colombier { 18683e12c5d1SDavid du Colombier char **s; 18693e12c5d1SDavid du Colombier int i; 18703e12c5d1SDavid du Colombier 18713e12c5d1SDavid du Colombier f &= F; 18723e12c5d1SDavid du Colombier s = fns; 18733e12c5d1SDavid du Colombier for(i=0; i<f; i++) 18743e12c5d1SDavid du Colombier do; while(*s++); 18753e12c5d1SDavid du Colombier return *s; 18763e12c5d1SDavid du Colombier } 18773e12c5d1SDavid du Colombier 18783e12c5d1SDavid du Colombier int 18793e12c5d1SDavid du Colombier strtofn(char *str) 18803e12c5d1SDavid du Colombier { 18813e12c5d1SDavid du Colombier char **s; 18823e12c5d1SDavid du Colombier int i; 18833e12c5d1SDavid du Colombier 18843e12c5d1SDavid du Colombier s = fns; 18853e12c5d1SDavid du Colombier i = 0; 18863e12c5d1SDavid du Colombier while(i <= F){ 18873e12c5d1SDavid du Colombier if(*s == 0) 18883e12c5d1SDavid du Colombier i++; 18893e12c5d1SDavid du Colombier else 18903e12c5d1SDavid du Colombier if(strcmp(str, *s) == 0) 18913e12c5d1SDavid du Colombier return i; 18923e12c5d1SDavid du Colombier s++; 18933e12c5d1SDavid du Colombier } 18943e12c5d1SDavid du Colombier return -1; 18953e12c5d1SDavid du Colombier } 1896