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
main(int argc,char * argv[])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
error(Display *,char * s)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
redraw(Thing * t)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
eresized(int new)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
mesgstr(Point p,int line,char * s)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
mesg(char * fmt,...)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
tmesg(Thing * t,int line,char * fmt,...)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
scntl(char * l)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
cntl(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
stext(Thing * t,char * l0,char * l1)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
text(Thing * t)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
drawall(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
380*bacfa46cSDavid du Colombier /* imported from libdraw/arith.c to permit an extern log2 function */
381*bacfa46cSDavid du Colombier static int log2[] = {
382*bacfa46cSDavid du Colombier -1, 0, 1, -1, 2, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1, 4,
383*bacfa46cSDavid du Colombier -1, -1, -1, -1, -1, -1, -1, 4 /* BUG */, -1, -1, -1, -1, -1, -1, -1, 5
384*bacfa46cSDavid du Colombier };
385*bacfa46cSDavid du Colombier
3863e12c5d1SDavid du Colombier int
value(Image * b,int x)3877dd7cddfSDavid du Colombier value(Image *b, int x)
3883e12c5d1SDavid du Colombier {
3893e12c5d1SDavid du Colombier int v, l, w;
3903e12c5d1SDavid du Colombier uchar mask;
3913e12c5d1SDavid du Colombier
3927dd7cddfSDavid du Colombier w = b->depth;
3937dd7cddfSDavid du Colombier if(w > 8){
3943e12c5d1SDavid du Colombier mesg("ldepth too large");
3953e12c5d1SDavid du Colombier return 0;
3963e12c5d1SDavid du Colombier }
3977dd7cddfSDavid du Colombier l = log2[w];
3987dd7cddfSDavid du Colombier mask = (1<<w)-1; /* ones at right end of word */
3993e12c5d1SDavid du Colombier x -= b->r.min.x&~(7>>l); /* adjust x relative to first pixel */
4003e12c5d1SDavid du Colombier v = data[x>>(3-l)];
4013e12c5d1SDavid du Colombier v >>= ((7>>l)<<l) - ((x&(7>>l))<<l); /* pixel at right end of word */
4023e12c5d1SDavid du Colombier v &= mask; /* pixel at right end of word */
4033e12c5d1SDavid du Colombier return v;
4043e12c5d1SDavid du Colombier }
4053e12c5d1SDavid du Colombier
4063e12c5d1SDavid du Colombier int
bvalue(int v,int d)4077dd7cddfSDavid du Colombier bvalue(int v, int d)
4083e12c5d1SDavid du Colombier {
4097dd7cddfSDavid du Colombier v &= (1<<d)-1;
4107dd7cddfSDavid du Colombier if(d > screen->depth)
4117dd7cddfSDavid du Colombier v >>= d - screen->depth;
412219b2ee8SDavid du Colombier else
4137dd7cddfSDavid du Colombier while(d < screen->depth && d < 8){
4147dd7cddfSDavid du Colombier v |= v << d;
4157dd7cddfSDavid du Colombier d <<= 1;
4163e12c5d1SDavid du Colombier }
4177dd7cddfSDavid du Colombier if(v<0 || v>255){
4187dd7cddfSDavid du Colombier mesg("internal error: bad color");
4197dd7cddfSDavid du Colombier return Blue;
4207dd7cddfSDavid du Colombier }
4217dd7cddfSDavid du Colombier return v;
4223e12c5d1SDavid du Colombier }
4233e12c5d1SDavid du Colombier
4243e12c5d1SDavid du Colombier void
drawthing(Thing * nt,int link)4257dd7cddfSDavid du Colombier drawthing(Thing *nt, int link)
4263e12c5d1SDavid du Colombier {
4273e12c5d1SDavid du Colombier int nl, nf, i, x, y, sx, sy, fdx, dx, dy, v;
4283e12c5d1SDavid du Colombier Thing *t;
4293e12c5d1SDavid du Colombier Subfont *s;
4307dd7cddfSDavid du Colombier Image *b, *col;
4313e12c5d1SDavid du Colombier Point p, p1, p2;
4323e12c5d1SDavid du Colombier
4333e12c5d1SDavid du Colombier if(link){
4343e12c5d1SDavid du Colombier nt->next = 0;
4353e12c5d1SDavid du Colombier if(thing == 0){
4363e12c5d1SDavid du Colombier thing = nt;
4373e12c5d1SDavid du Colombier y = editr.min.y;
4383e12c5d1SDavid du Colombier }else{
4393e12c5d1SDavid du Colombier for(t=thing; t->next; t=t->next)
4403e12c5d1SDavid du Colombier ;
4413e12c5d1SDavid du Colombier t->next = nt;
4423e12c5d1SDavid du Colombier y = t->er.max.y;
4433e12c5d1SDavid du Colombier }
4443e12c5d1SDavid du Colombier }else{
4453e12c5d1SDavid du Colombier if(thing == nt)
4463e12c5d1SDavid du Colombier y = editr.min.y;
4473e12c5d1SDavid du Colombier else{
4483e12c5d1SDavid du Colombier for(t=thing; t->next!=nt; t=t->next)
4493e12c5d1SDavid du Colombier ;
4503e12c5d1SDavid du Colombier y = t->er.max.y;
4513e12c5d1SDavid du Colombier }
4523e12c5d1SDavid du Colombier }
4533e12c5d1SDavid du Colombier s = nt->s;
4543e12c5d1SDavid du Colombier b = nt->b;
4553e12c5d1SDavid du Colombier nl = font->height;
4563e12c5d1SDavid du Colombier if(s || nt->c>=0)
4573e12c5d1SDavid du Colombier nl += font->height;
4583e12c5d1SDavid du Colombier fdx = Dx(editr) - 2*Border;
4593e12c5d1SDavid du Colombier dx = Dx(b->r);
4603e12c5d1SDavid du Colombier dy = Dy(b->r);
4613e12c5d1SDavid du Colombier if(nt->mag > 1){
4623e12c5d1SDavid du Colombier dx *= nt->mag;
4633e12c5d1SDavid du Colombier dy *= nt->mag;
4643e12c5d1SDavid du Colombier fdx -= fdx%nt->mag;
4653e12c5d1SDavid du Colombier }
4663e12c5d1SDavid du Colombier nf = 1 + dx/fdx;
4673e12c5d1SDavid du Colombier nt->er.min.y = y;
4683e12c5d1SDavid du Colombier nt->er.min.x = editr.min.x;
4693e12c5d1SDavid du Colombier nt->er.max.x = nt->er.min.x + Border + dx + Border;
4703e12c5d1SDavid du Colombier if(nt->er.max.x > editr.max.x)
4713e12c5d1SDavid du Colombier nt->er.max.x = editr.max.x;
4723e12c5d1SDavid du Colombier nt->er.max.y = nt->er.min.y + Border + nf*(dy+Border);
4737dd7cddfSDavid du Colombier nt->r = insetrect(nt->er, Border);
4743e12c5d1SDavid du Colombier nt->er.max.x = editr.max.x;
4757dd7cddfSDavid du Colombier draw(screen, nt->er, display->white, nil, ZP);
4763e12c5d1SDavid du Colombier for(i=0; i<nf; i++){
4773e12c5d1SDavid du Colombier p1 = Pt(nt->r.min.x-1, nt->r.min.y+i*(Border+dy));
4783e12c5d1SDavid du Colombier /* draw portion of bitmap */
4793e12c5d1SDavid du Colombier p = Pt(p1.x+1, p1.y);
4803e12c5d1SDavid du Colombier if(nt->mag == 1)
4817dd7cddfSDavid du Colombier draw(screen, Rect(p.x, p.y, p.x+fdx+Dx(b->r), p.y+Dy(b->r)),
4827dd7cddfSDavid du Colombier b, nil, Pt(b->r.min.x+i*fdx, b->r.min.y));
4833e12c5d1SDavid du Colombier else{
4843e12c5d1SDavid du Colombier for(y=b->r.min.y; y<b->r.max.y; y++){
4853e12c5d1SDavid du Colombier sy = p.y+(y-b->r.min.y)*nt->mag;
4867dd7cddfSDavid du Colombier unloadimage(b, Rect(b->r.min.x, y, b->r.max.x, y+1), data, sizeof data);
4873e12c5d1SDavid du Colombier for(x=b->r.min.x+i*(fdx/nt->mag); x<b->r.max.x; x++){
4883e12c5d1SDavid du Colombier sx = p.x+(x-i*(fdx/nt->mag)-b->r.min.x)*nt->mag;
4893e12c5d1SDavid du Colombier if(sx >= nt->r.max.x)
4903e12c5d1SDavid du Colombier break;
4917dd7cddfSDavid du Colombier v = bvalue(value(b, x), b->depth);
4927dd7cddfSDavid du Colombier if(v == 255)
4937dd7cddfSDavid du Colombier continue;
4947dd7cddfSDavid du Colombier if(b->chan == GREY8)
4957dd7cddfSDavid du Colombier draw(screen, Rect(sx, sy, sx+nt->mag, sy+nt->mag),
4967dd7cddfSDavid du Colombier greyvalues[v], nil, ZP);
4977dd7cddfSDavid du Colombier else
4987dd7cddfSDavid du Colombier draw(screen, Rect(sx, sy, sx+nt->mag, sy+nt->mag),
4997dd7cddfSDavid du Colombier values[v], nil, ZP);
5003e12c5d1SDavid du Colombier }
5013e12c5d1SDavid du Colombier
5023e12c5d1SDavid du Colombier }
5033e12c5d1SDavid du Colombier }
5043e12c5d1SDavid du Colombier /* line down left */
5057dd7cddfSDavid du Colombier if(i == 0)
5067dd7cddfSDavid du Colombier col = display->black;
5073e12c5d1SDavid du Colombier else
5087dd7cddfSDavid du Colombier col = display->white;
5097dd7cddfSDavid du Colombier draw(screen, Rect(p1.x, p1.y, p1.x+1, p1.y+dy+Border), col, nil, ZP);
5107dd7cddfSDavid du Colombier /* line across top */
5117dd7cddfSDavid du Colombier draw(screen, Rect(p1.x, p1.y-1, nt->r.max.x+Border, p1.y), display->black, nil, ZP);
5127dd7cddfSDavid du Colombier p2 = p1;
5137dd7cddfSDavid du Colombier if(i == nf-1){
5147dd7cddfSDavid du Colombier p2.x += 1 + dx%fdx;
5157dd7cddfSDavid du Colombier col = display->black;
5167dd7cddfSDavid du Colombier }else{
5173e12c5d1SDavid du Colombier p2.x = nt->r.max.x;
5187dd7cddfSDavid du Colombier col = display->white;
5197dd7cddfSDavid du Colombier }
5203e12c5d1SDavid du Colombier /* line down right */
5217dd7cddfSDavid du Colombier draw(screen, Rect(p2.x, p2.y, p2.x+1, p2.y+dy+Border), col, nil, ZP);
5223e12c5d1SDavid du Colombier /* line across bottom */
5233e12c5d1SDavid du Colombier if(i == nf-1){
5243e12c5d1SDavid du Colombier p1.y += Border+dy;
5257dd7cddfSDavid du Colombier draw(screen, Rect(p1.x, p1.y-1, p2.x,p1.y), display->black, nil, ZP);
5263e12c5d1SDavid du Colombier }
5273e12c5d1SDavid du Colombier }
5283e12c5d1SDavid du Colombier nt->tr.min.x = editr.min.x;
5293e12c5d1SDavid du Colombier nt->tr.max.x = editr.max.x;
5303e12c5d1SDavid du Colombier nt->tr.min.y = nt->er.max.y + Border;
5313e12c5d1SDavid du Colombier nt->tr.max.y = nt->tr.min.y + nl;
5323e12c5d1SDavid du Colombier nt->er.max.y = nt->tr.max.y + Border;
5333e12c5d1SDavid du Colombier text(nt);
5343e12c5d1SDavid du Colombier }
5353e12c5d1SDavid du Colombier
5363e12c5d1SDavid du Colombier int
tohex(int c)5373e12c5d1SDavid du Colombier tohex(int c)
5383e12c5d1SDavid du Colombier {
5393e12c5d1SDavid du Colombier if('0'<=c && c<='9')
5403e12c5d1SDavid du Colombier return c - '0';
5413e12c5d1SDavid du Colombier if('a'<=c && c<='f')
5423e12c5d1SDavid du Colombier return 10 + (c - 'a');
5433e12c5d1SDavid du Colombier if('A'<=c && c<='F')
5443e12c5d1SDavid du Colombier return 10 + (c - 'A');
54543f733d7SDavid du Colombier return 0;
5463e12c5d1SDavid du Colombier }
5473e12c5d1SDavid du Colombier
5483e12c5d1SDavid du Colombier Thing*
tget(char * file)5493e12c5d1SDavid du Colombier tget(char *file)
5503e12c5d1SDavid du Colombier {
5517dd7cddfSDavid du Colombier int i, j, fd, face, x, y, c, chan;
5527dd7cddfSDavid du Colombier Image *b;
5533e12c5d1SDavid du Colombier Subfont *s;
5543e12c5d1SDavid du Colombier Thing *t;
5559a747e4fSDavid du Colombier Dir *d;
5563e12c5d1SDavid du Colombier jmp_buf oerr;
5573e12c5d1SDavid du Colombier uchar buf[256];
5583e12c5d1SDavid du Colombier char *data;
5593e12c5d1SDavid du Colombier
5609a747e4fSDavid du Colombier buf[0] = '\0';
5619a747e4fSDavid du Colombier errstr((char*)buf, sizeof buf); /* flush pending error message */
5623e12c5d1SDavid du Colombier memmove(oerr, err, sizeof err);
5639a747e4fSDavid du Colombier d = nil;
5643e12c5d1SDavid du Colombier if(setjmp(err)){
5653e12c5d1SDavid du Colombier Err:
5669a747e4fSDavid du Colombier free(d);
5673e12c5d1SDavid du Colombier memmove(err, oerr, sizeof err);
5683e12c5d1SDavid du Colombier return 0;
5693e12c5d1SDavid du Colombier }
5703e12c5d1SDavid du Colombier fd = open(file, OREAD);
5713e12c5d1SDavid du Colombier if(fd < 0){
5723e12c5d1SDavid du Colombier mesg("can't open %s: %r", file);
5733e12c5d1SDavid du Colombier goto Err;
5743e12c5d1SDavid du Colombier }
5759a747e4fSDavid du Colombier d = dirfstat(fd);
5769a747e4fSDavid du Colombier if(d == nil){
5773e12c5d1SDavid du Colombier mesg("can't stat bitmap file %s: %r", file);
5783e12c5d1SDavid du Colombier close(fd);
5793e12c5d1SDavid du Colombier goto Err;
5803e12c5d1SDavid du Colombier }
5817dd7cddfSDavid du Colombier if(read(fd, buf, 11) != 11){
5823e12c5d1SDavid du Colombier mesg("can't read %s: %r", file);
5833e12c5d1SDavid du Colombier close(fd);
5843e12c5d1SDavid du Colombier goto Err;
5853e12c5d1SDavid du Colombier }
5863e12c5d1SDavid du Colombier seek(fd, 0, 0);
5877dd7cddfSDavid du Colombier data = (char*)buf;
5887dd7cddfSDavid du Colombier if(*data == '{')
5897dd7cddfSDavid du Colombier data++;
5907dd7cddfSDavid du Colombier if(memcmp(data, "0x", 2)==0 && data[4]==','){
5917dd7cddfSDavid du Colombier /*
5927dd7cddfSDavid du Colombier * cursor file
5937dd7cddfSDavid du Colombier */
5947dd7cddfSDavid du Colombier face = CURSOR;
5957dd7cddfSDavid du Colombier s = 0;
5969a747e4fSDavid du Colombier data = malloc(d->length+1);
5977dd7cddfSDavid du Colombier if(data == 0){
5987dd7cddfSDavid du Colombier mesg("can't malloc buffer: %r");
5997dd7cddfSDavid du Colombier close(fd);
6007dd7cddfSDavid du Colombier goto Err;
6017dd7cddfSDavid du Colombier }
6029a747e4fSDavid du Colombier data[d->length] = 0;
6039a747e4fSDavid du Colombier if(read(fd, data, d->length) != d->length){
6047dd7cddfSDavid du Colombier mesg("can't read cursor file %s: %r", file);
6057dd7cddfSDavid du Colombier close(fd);
6067dd7cddfSDavid du Colombier goto Err;
6077dd7cddfSDavid du Colombier }
6087dd7cddfSDavid du Colombier b = allocimage(display, Rect(0, 0, 16, 32), GREY1, 0, DNofill);
6097dd7cddfSDavid du Colombier if(b == 0){
6107dd7cddfSDavid du Colombier mesg("image alloc failed file %s: %r", file);
6117dd7cddfSDavid du Colombier free(data);
6127dd7cddfSDavid du Colombier close(fd);
6137dd7cddfSDavid du Colombier goto Err;
6147dd7cddfSDavid du Colombier }
6157dd7cddfSDavid du Colombier i = 0;
6167dd7cddfSDavid du Colombier for(x=0;x<64; ){
6177dd7cddfSDavid du Colombier if((c=data[i]) == '\0')
6187dd7cddfSDavid du Colombier goto ill;
6197dd7cddfSDavid du Colombier if(c=='0' && data[i+1] == 'x'){
6207dd7cddfSDavid du Colombier i += 2;
6217dd7cddfSDavid du Colombier continue;
6227dd7cddfSDavid du Colombier }
6237dd7cddfSDavid du Colombier if(strchr(hex, c)){
6247dd7cddfSDavid du Colombier buf[x++] = (tohex(c)<<4) | tohex(data[i+1]);
6257dd7cddfSDavid du Colombier i += 2;
6267dd7cddfSDavid du Colombier continue;
6277dd7cddfSDavid du Colombier }
6287dd7cddfSDavid du Colombier i++;
6297dd7cddfSDavid du Colombier }
6307dd7cddfSDavid du Colombier loadimage(b, Rect(0, 0, 16, 32), buf, sizeof buf);
6317dd7cddfSDavid du Colombier free(data);
6327dd7cddfSDavid du Colombier }else if(memcmp(buf, "0x", 2)==0){
6333e12c5d1SDavid du Colombier /*
6343e12c5d1SDavid du Colombier * face file
6353e12c5d1SDavid du Colombier */
6367dd7cddfSDavid du Colombier face = FACE;
6373e12c5d1SDavid du Colombier s = 0;
6389a747e4fSDavid du Colombier data = malloc(d->length+1);
6393e12c5d1SDavid du Colombier if(data == 0){
6403e12c5d1SDavid du Colombier mesg("can't malloc buffer: %r");
6413e12c5d1SDavid du Colombier close(fd);
6423e12c5d1SDavid du Colombier goto Err;
6433e12c5d1SDavid du Colombier }
6449a747e4fSDavid du Colombier data[d->length] = 0;
6459a747e4fSDavid du Colombier if(read(fd, data, d->length) != d->length){
6463e12c5d1SDavid du Colombier mesg("can't read bitmap file %s: %r", file);
6473e12c5d1SDavid du Colombier close(fd);
6483e12c5d1SDavid du Colombier goto Err;
6493e12c5d1SDavid du Colombier }
6509a747e4fSDavid du Colombier for(y=0,i=0; i<d->length; i++)
6513e12c5d1SDavid du Colombier if(data[i] == '\n')
6523e12c5d1SDavid du Colombier y++;
6533e12c5d1SDavid du Colombier if(y == 0){
6543e12c5d1SDavid du Colombier ill:
6553e12c5d1SDavid du Colombier mesg("ill-formed face file %s", file);
6563e12c5d1SDavid du Colombier close(fd);
6573e12c5d1SDavid du Colombier free(data);
6583e12c5d1SDavid du Colombier goto Err;
6593e12c5d1SDavid du Colombier }
6603e12c5d1SDavid du Colombier for(x=0,i=0; (c=data[i])!='\n'; ){
6613e12c5d1SDavid du Colombier if(c==',' || c==' ' || c=='\t'){
6623e12c5d1SDavid du Colombier i++;
6633e12c5d1SDavid du Colombier continue;
6643e12c5d1SDavid du Colombier }
6653e12c5d1SDavid du Colombier if(c=='0' && data[i+1] == 'x'){
6663e12c5d1SDavid du Colombier i += 2;
6673e12c5d1SDavid du Colombier continue;
6683e12c5d1SDavid du Colombier }
6693e12c5d1SDavid du Colombier if(strchr(hex, c)){
6703e12c5d1SDavid du Colombier x += 4;
6713e12c5d1SDavid du Colombier i++;
6723e12c5d1SDavid du Colombier continue;
6733e12c5d1SDavid du Colombier }
6743e12c5d1SDavid du Colombier goto ill;
6753e12c5d1SDavid du Colombier }
6763e12c5d1SDavid du Colombier if(x % y)
6773e12c5d1SDavid du Colombier goto ill;
6783e12c5d1SDavid du Colombier switch(x / y){
6793e12c5d1SDavid du Colombier default:
6803e12c5d1SDavid du Colombier goto ill;
6813e12c5d1SDavid du Colombier case 1:
6827dd7cddfSDavid du Colombier chan = GREY1;
6833e12c5d1SDavid du Colombier break;
6843e12c5d1SDavid du Colombier case 2:
6857dd7cddfSDavid du Colombier chan = GREY2;
6863e12c5d1SDavid du Colombier break;
6873e12c5d1SDavid du Colombier case 4:
6887dd7cddfSDavid du Colombier chan = GREY4;
6893e12c5d1SDavid du Colombier break;
6903e12c5d1SDavid du Colombier case 8:
6917dd7cddfSDavid du Colombier chan = CMAP8;
6923e12c5d1SDavid du Colombier break;
6933e12c5d1SDavid du Colombier }
6947dd7cddfSDavid du Colombier b = allocimage(display, Rect(0, 0, y, y), chan, 0, -1);
6953e12c5d1SDavid du Colombier if(b == 0){
6967dd7cddfSDavid du Colombier mesg("image alloc failed file %s: %r", file);
6973e12c5d1SDavid du Colombier free(data);
6983e12c5d1SDavid du Colombier close(fd);
6993e12c5d1SDavid du Colombier goto Err;
7003e12c5d1SDavid du Colombier }
7013e12c5d1SDavid du Colombier i = 0;
7023e12c5d1SDavid du Colombier for(j=0; j<y; j++){
7033e12c5d1SDavid du Colombier for(x=0; (c=data[i])!='\n'; ){
7043e12c5d1SDavid du Colombier if(c=='0' && data[i+1] == 'x'){
7053e12c5d1SDavid du Colombier i += 2;
7063e12c5d1SDavid du Colombier continue;
7073e12c5d1SDavid du Colombier }
7083e12c5d1SDavid du Colombier if(strchr(hex, c)){
7097dd7cddfSDavid du Colombier buf[x++] = ~((tohex(c)<<4) | tohex(data[i+1]));
7103e12c5d1SDavid du Colombier i += 2;
7113e12c5d1SDavid du Colombier continue;
7123e12c5d1SDavid du Colombier }
7137dd7cddfSDavid du Colombier i++;
7143e12c5d1SDavid du Colombier }
7153e12c5d1SDavid du Colombier i++;
7167dd7cddfSDavid du Colombier loadimage(b, Rect(0, j, y, j+1), buf, sizeof buf);
7173e12c5d1SDavid du Colombier }
7183e12c5d1SDavid du Colombier free(data);
7193e12c5d1SDavid du Colombier }else{
7207dd7cddfSDavid du Colombier face = NORMAL;
7213e12c5d1SDavid du Colombier s = 0;
7227dd7cddfSDavid du Colombier b = readimage(display, fd, 0);
7233e12c5d1SDavid du Colombier if(b == 0){
7243e12c5d1SDavid du Colombier mesg("can't read bitmap file %s: %r", file);
7253e12c5d1SDavid du Colombier close(fd);
7263e12c5d1SDavid du Colombier goto Err;
7273e12c5d1SDavid du Colombier }
7289a747e4fSDavid du Colombier if(seek(fd, 0, 1) < d->length)
7297dd7cddfSDavid du Colombier s = readsubfonti(display, file, fd, b, 0);
7303e12c5d1SDavid du Colombier }
7313e12c5d1SDavid du Colombier close(fd);
7323e12c5d1SDavid du Colombier t = malloc(sizeof(Thing));
7333e12c5d1SDavid du Colombier if(t == 0){
7343e12c5d1SDavid du Colombier nomem:
7353e12c5d1SDavid du Colombier mesg("malloc failed: %r");
7363e12c5d1SDavid du Colombier if(s)
7377dd7cddfSDavid du Colombier freesubfont(s);
7387dd7cddfSDavid du Colombier else
7397dd7cddfSDavid du Colombier freeimage(b);
7403e12c5d1SDavid du Colombier goto Err;
7413e12c5d1SDavid du Colombier }
7423e12c5d1SDavid du Colombier t->name = strdup(file);
7433e12c5d1SDavid du Colombier if(t->name == 0){
7443e12c5d1SDavid du Colombier free(t);
7453e12c5d1SDavid du Colombier goto nomem;
7463e12c5d1SDavid du Colombier }
7473e12c5d1SDavid du Colombier t->b = b;
7483e12c5d1SDavid du Colombier t->s = s;
7493e12c5d1SDavid du Colombier t->face = face;
7503e12c5d1SDavid du Colombier t->mod = 0;
7513e12c5d1SDavid du Colombier t->parent = 0;
7523e12c5d1SDavid du Colombier t->c = -1;
7533e12c5d1SDavid du Colombier t->mag = 1;
7543e12c5d1SDavid du Colombier t->off = 0;
7553e12c5d1SDavid du Colombier memmove(err, oerr, sizeof err);
7563e12c5d1SDavid du Colombier return t;
7573e12c5d1SDavid du Colombier }
7583e12c5d1SDavid du Colombier
7593e12c5d1SDavid du Colombier int
atline(int x,Point p,char * line,char * buf)7603e12c5d1SDavid du Colombier atline(int x, Point p, char *line, char *buf)
7613e12c5d1SDavid du Colombier {
7623e12c5d1SDavid du Colombier char *s, *c, *word, *hit;
7633e12c5d1SDavid du Colombier int w, wasblank;
7643e12c5d1SDavid du Colombier Rune r;
7653e12c5d1SDavid du Colombier
7663e12c5d1SDavid du Colombier wasblank = 1;
7673e12c5d1SDavid du Colombier hit = 0;
7683e12c5d1SDavid du Colombier word = 0;
7693e12c5d1SDavid du Colombier for(s=line; *s; s+=w){
7703e12c5d1SDavid du Colombier w = chartorune(&r, s);
7717dd7cddfSDavid du Colombier x += runestringnwidth(font, &r, 1);
7723e12c5d1SDavid du Colombier if(wasblank && r!=' ')
7733e12c5d1SDavid du Colombier word = s;
7743e12c5d1SDavid du Colombier wasblank = 0;
7753e12c5d1SDavid du Colombier if(r == ' '){
7763e12c5d1SDavid du Colombier if(x >= p.x)
7773e12c5d1SDavid du Colombier break;
7783e12c5d1SDavid du Colombier wasblank = 1;
7793e12c5d1SDavid du Colombier }
7803e12c5d1SDavid du Colombier if(r == ':')
7813e12c5d1SDavid du Colombier hit = word;
7823e12c5d1SDavid du Colombier }
7833e12c5d1SDavid du Colombier if(x < p.x)
7843e12c5d1SDavid du Colombier return 0;
7853e12c5d1SDavid du Colombier c = utfrune(hit, ':');
7863e12c5d1SDavid du Colombier strncpy(buf, hit, c-hit);
7873e12c5d1SDavid du Colombier buf[c-hit] = 0;
7883e12c5d1SDavid du Colombier return 1;
7893e12c5d1SDavid du Colombier }
7903e12c5d1SDavid du Colombier
7913e12c5d1SDavid du Colombier int
attext(Thing * t,Point p,char * buf)7923e12c5d1SDavid du Colombier attext(Thing *t, Point p, char *buf)
7933e12c5d1SDavid du Colombier {
7943e12c5d1SDavid du Colombier char l0[256], l1[256];
7953e12c5d1SDavid du Colombier
7963e12c5d1SDavid du Colombier if(!ptinrect(p, t->tr))
7973e12c5d1SDavid du Colombier return 0;
7983e12c5d1SDavid du Colombier stext(t, l0, l1);
7993e12c5d1SDavid du Colombier if(p.y < t->tr.min.y+font->height)
8003e12c5d1SDavid du Colombier return atline(t->r.min.x, p, l0, buf);
8013e12c5d1SDavid du Colombier else
8023e12c5d1SDavid du Colombier return atline(t->r.min.x, p, l1, buf);
8033e12c5d1SDavid du Colombier }
8043e12c5d1SDavid du Colombier
8053e12c5d1SDavid du Colombier int
type(char * buf,char * tag)8063e12c5d1SDavid du Colombier type(char *buf, char *tag)
8073e12c5d1SDavid du Colombier {
8083e12c5d1SDavid du Colombier Rune r;
8093e12c5d1SDavid du Colombier char *p;
8103e12c5d1SDavid du Colombier
8117dd7cddfSDavid du Colombier esetcursor(&busy);
8123e12c5d1SDavid du Colombier p = buf;
8133e12c5d1SDavid du Colombier for(;;){
8143e12c5d1SDavid du Colombier *p = 0;
8153e12c5d1SDavid du Colombier mesg("%s: %s", tag, buf);
8163e12c5d1SDavid du Colombier r = ekbd();
8173e12c5d1SDavid du Colombier switch(r){
8183e12c5d1SDavid du Colombier case '\n':
8193e12c5d1SDavid du Colombier mesg("");
8207dd7cddfSDavid du Colombier esetcursor(0);
8213e12c5d1SDavid du Colombier return p-buf;
8223e12c5d1SDavid du Colombier case 0x15: /* control-U */
8233e12c5d1SDavid du Colombier p = buf;
8243e12c5d1SDavid du Colombier break;
8253e12c5d1SDavid du Colombier case '\b':
8263e12c5d1SDavid du Colombier if(p > buf)
8273e12c5d1SDavid du Colombier --p;
8283e12c5d1SDavid du Colombier break;
8293e12c5d1SDavid du Colombier default:
8303e12c5d1SDavid du Colombier p += runetochar(p, &r);
8313e12c5d1SDavid du Colombier }
8323e12c5d1SDavid du Colombier }
8333e12c5d1SDavid du Colombier }
8343e12c5d1SDavid du Colombier
8353e12c5d1SDavid du Colombier void
textedit(Thing * t,char * tag)8363e12c5d1SDavid du Colombier textedit(Thing *t, char *tag)
8373e12c5d1SDavid du Colombier {
8383e12c5d1SDavid du Colombier char buf[256];
8393e12c5d1SDavid du Colombier char *s;
8407dd7cddfSDavid du Colombier Image *b;
8413e12c5d1SDavid du Colombier Subfont *f;
8423e12c5d1SDavid du Colombier Fontchar *fc, *nfc;
8433e12c5d1SDavid du Colombier Rectangle r;
8447dd7cddfSDavid du Colombier ulong chan;
8457dd7cddfSDavid du Colombier int i, ld, d, w, c, doredraw, fdx, x;
8463e12c5d1SDavid du Colombier Thing *nt;
8473e12c5d1SDavid du Colombier
8483e12c5d1SDavid du Colombier buttons(Up);
8493e12c5d1SDavid du Colombier if(type(buf, tag) == 0)
8503e12c5d1SDavid du Colombier return;
8513e12c5d1SDavid du Colombier if(strcmp(tag, "file") == 0){
8523e12c5d1SDavid du Colombier for(s=buf; *s; s++)
8533e12c5d1SDavid du Colombier if(*s <= ' '){
8543e12c5d1SDavid du Colombier mesg("illegal file name");
8553e12c5d1SDavid du Colombier return;
8563e12c5d1SDavid du Colombier }
8573e12c5d1SDavid du Colombier if(strcmp(t->name, buf) != 0){
8583e12c5d1SDavid du Colombier if(t->parent)
8593e12c5d1SDavid du Colombier t->parent->mod = 1;
8603e12c5d1SDavid du Colombier else
8613e12c5d1SDavid du Colombier t->mod = 1;
8623e12c5d1SDavid du Colombier }
8633e12c5d1SDavid du Colombier for(nt=thing; nt; nt=nt->next)
8643e12c5d1SDavid du Colombier if(t==nt || t->parent==nt || nt->parent==t){
8653e12c5d1SDavid du Colombier free(nt->name);
8663e12c5d1SDavid du Colombier nt->name = strdup(buf);
8673e12c5d1SDavid du Colombier if(nt->name == 0){
8683e12c5d1SDavid du Colombier mesg("malloc failed: %r");
8693e12c5d1SDavid du Colombier return;
8703e12c5d1SDavid du Colombier }
8713e12c5d1SDavid du Colombier text(nt);
8723e12c5d1SDavid du Colombier }
8733e12c5d1SDavid du Colombier return;
8743e12c5d1SDavid du Colombier }
8757dd7cddfSDavid du Colombier if(strcmp(tag, "depth") == 0){
8767dd7cddfSDavid du Colombier if(buf[0]<'0' || '9'<buf[0] || (d=atoi(buf))<0 || d>8 || log2[d]<0){
8773e12c5d1SDavid du Colombier mesg("illegal ldepth");
8783e12c5d1SDavid du Colombier return;
8793e12c5d1SDavid du Colombier }
8807dd7cddfSDavid du Colombier if(d == t->b->depth)
8813e12c5d1SDavid du Colombier return;
8823e12c5d1SDavid du Colombier if(t->parent)
8833e12c5d1SDavid du Colombier t->parent->mod = 1;
8843e12c5d1SDavid du Colombier else
8853e12c5d1SDavid du Colombier t->mod = 1;
8867dd7cddfSDavid du Colombier if(d == 8)
8877dd7cddfSDavid du Colombier chan = CMAP8;
8887dd7cddfSDavid du Colombier else
8897dd7cddfSDavid du Colombier chan = CHAN1(CGrey, d);
8903e12c5d1SDavid du Colombier for(nt=thing; nt; nt=nt->next){
8913e12c5d1SDavid du Colombier if(nt!=t && nt!=t->parent && nt->parent!=t)
8923e12c5d1SDavid du Colombier continue;
8937dd7cddfSDavid du Colombier b = allocimage(display, nt->b->r, chan, 0, 0);
8943e12c5d1SDavid du Colombier if(b == 0){
8953e12c5d1SDavid du Colombier nobmem:
8967dd7cddfSDavid du Colombier mesg("image alloc failed: %r");
8973e12c5d1SDavid du Colombier return;
8983e12c5d1SDavid du Colombier }
8997dd7cddfSDavid du Colombier draw(b, b->r, nt->b, nil, nt->b->r.min);
9007dd7cddfSDavid du Colombier freeimage(nt->b);
9013e12c5d1SDavid du Colombier nt->b = b;
9023e12c5d1SDavid du Colombier if(nt->s){
9037dd7cddfSDavid du Colombier b = allocimage(display, nt->b->r, chan, 0, -1);
9043e12c5d1SDavid du Colombier if(b == 0)
9053e12c5d1SDavid du Colombier goto nobmem;
9067dd7cddfSDavid du Colombier draw(b, b->r, nt->b, nil, nt->b->r.min);
9077dd7cddfSDavid du Colombier f = allocsubfont(t->name, nt->s->n, nt->s->height, nt->s->ascent, nt->s->info, b);
9083e12c5d1SDavid du Colombier if(f == 0){
9093e12c5d1SDavid du Colombier nofmem:
9107dd7cddfSDavid du Colombier freeimage(b);
9113e12c5d1SDavid du Colombier mesg("can't make subfont: %r");
9123e12c5d1SDavid du Colombier return;
9133e12c5d1SDavid du Colombier }
9147dd7cddfSDavid du Colombier nt->s->info = 0; /* prevent it being freed */
9157dd7cddfSDavid du Colombier nt->s->bits = 0;
9167dd7cddfSDavid du Colombier freesubfont(nt->s);
9173e12c5d1SDavid du Colombier nt->s = f;
9183e12c5d1SDavid du Colombier }
9197dd7cddfSDavid du Colombier drawthing(nt, 0);
9203e12c5d1SDavid du Colombier }
9213e12c5d1SDavid du Colombier return;
9223e12c5d1SDavid du Colombier }
9233e12c5d1SDavid du Colombier if(strcmp(tag, "mag") == 0){
9243e12c5d1SDavid du Colombier if(buf[0]<'0' || '9'<buf[0] || (ld=atoi(buf))<=0 || ld>Maxmag){
9253e12c5d1SDavid du Colombier mesg("illegal magnification");
9263e12c5d1SDavid du Colombier return;
9273e12c5d1SDavid du Colombier }
9283e12c5d1SDavid du Colombier if(t->mag == ld)
9293e12c5d1SDavid du Colombier return;
9303e12c5d1SDavid du Colombier t->mag = ld;
9313e12c5d1SDavid du Colombier redraw(t);
9323e12c5d1SDavid du Colombier return;
9333e12c5d1SDavid du Colombier }
9347dd7cddfSDavid du Colombier if(strcmp(tag, "r") == 0){
9357dd7cddfSDavid du Colombier if(t->s){
9367dd7cddfSDavid du Colombier mesg("can't change rectangle of subfont\n");
9377dd7cddfSDavid du Colombier return;
9387dd7cddfSDavid du Colombier }
9397dd7cddfSDavid du Colombier s = buf;
9407dd7cddfSDavid du Colombier r.min.x = strtoul(s, &s, 0);
9417dd7cddfSDavid du Colombier r.min.y = strtoul(s, &s, 0);
9427dd7cddfSDavid du Colombier r.max.x = strtoul(s, &s, 0);
9437dd7cddfSDavid du Colombier r.max.y = strtoul(s, &s, 0);
9447dd7cddfSDavid du Colombier if(Dx(r)<=0 || Dy(r)<=0){
9457dd7cddfSDavid du Colombier mesg("illegal rectangle");
9467dd7cddfSDavid du Colombier return;
9477dd7cddfSDavid du Colombier }
9487dd7cddfSDavid du Colombier if(t->parent)
9497dd7cddfSDavid du Colombier t = t->parent;
9507dd7cddfSDavid du Colombier for(nt=thing; nt; nt=nt->next){
9517dd7cddfSDavid du Colombier if(nt->parent==t && !rectinrect(nt->b->r, r))
9527dd7cddfSDavid du Colombier tclose1(nt);
9537dd7cddfSDavid du Colombier }
9547dd7cddfSDavid du Colombier b = allocimage(display, r, t->b->chan, 0, 0);
9557dd7cddfSDavid du Colombier if(b == 0)
9567dd7cddfSDavid du Colombier goto nobmem;
9577dd7cddfSDavid du Colombier draw(b, r, t->b, nil, r.min);
9587dd7cddfSDavid du Colombier freeimage(t->b);
9597dd7cddfSDavid du Colombier t->b = b;
9607dd7cddfSDavid du Colombier b = allocimage(display, r, t->b->chan, 0, 0);
9617dd7cddfSDavid du Colombier if(b == 0)
9627dd7cddfSDavid du Colombier goto nobmem;
9637dd7cddfSDavid du Colombier redraw(t);
9647dd7cddfSDavid du Colombier t->mod = 1;
9657dd7cddfSDavid du Colombier return;
9667dd7cddfSDavid du Colombier }
9673e12c5d1SDavid du Colombier if(strcmp(tag, "ascent") == 0){
9683e12c5d1SDavid du Colombier if(buf[0]<'0' || '9'<buf[0] || (ld=atoi(buf))<0 || ld>t->s->height){
9693e12c5d1SDavid du Colombier mesg("illegal ascent");
9703e12c5d1SDavid du Colombier return;
9713e12c5d1SDavid du Colombier }
9723e12c5d1SDavid du Colombier if(t->s->ascent == ld)
9733e12c5d1SDavid du Colombier return;
9743e12c5d1SDavid du Colombier t->s->ascent = ld;
9753e12c5d1SDavid du Colombier text(t);
9763e12c5d1SDavid du Colombier t->mod = 1;
9773e12c5d1SDavid du Colombier return;
9783e12c5d1SDavid du Colombier }
9793e12c5d1SDavid du Colombier if(strcmp(tag, "height") == 0){
9803e12c5d1SDavid du Colombier if(buf[0]<'0' || '9'<buf[0] || (ld=atoi(buf))<0){
9813e12c5d1SDavid du Colombier mesg("illegal height");
9823e12c5d1SDavid du Colombier return;
9833e12c5d1SDavid du Colombier }
9843e12c5d1SDavid du Colombier if(t->s->height == ld)
9853e12c5d1SDavid du Colombier return;
9863e12c5d1SDavid du Colombier t->s->height = ld;
9873e12c5d1SDavid du Colombier text(t);
9883e12c5d1SDavid du Colombier t->mod = 1;
9893e12c5d1SDavid du Colombier return;
9903e12c5d1SDavid du Colombier }
9913e12c5d1SDavid du Colombier if(strcmp(tag, "left")==0 || strcmp(tag, "width") == 0){
9923e12c5d1SDavid du Colombier if(buf[0]<'0' || '9'<buf[0] || (ld=atoi(buf))<0){
9933e12c5d1SDavid du Colombier mesg("illegal value");
9943e12c5d1SDavid du Colombier return;
9953e12c5d1SDavid du Colombier }
9963e12c5d1SDavid du Colombier fc = &t->parent->s->info[t->c];
9973e12c5d1SDavid du Colombier if(strcmp(tag, "left")==0){
9983e12c5d1SDavid du Colombier if(fc->left == ld)
9993e12c5d1SDavid du Colombier return;
10003e12c5d1SDavid du Colombier fc->left = ld;
10013e12c5d1SDavid du Colombier }else{
10023e12c5d1SDavid du Colombier if(fc->width == ld)
10033e12c5d1SDavid du Colombier return;
10043e12c5d1SDavid du Colombier fc->width = ld;
10053e12c5d1SDavid du Colombier }
10063e12c5d1SDavid du Colombier text(t);
10073e12c5d1SDavid du Colombier t->parent->mod = 1;
10083e12c5d1SDavid du Colombier return;
10093e12c5d1SDavid du Colombier }
10103e12c5d1SDavid du Colombier if(strcmp(tag, "offset(hex)") == 0){
10113e12c5d1SDavid du Colombier if(!strchr(hex, buf[0])){
10123e12c5d1SDavid du Colombier illoff:
10133e12c5d1SDavid du Colombier mesg("illegal offset");
10143e12c5d1SDavid du Colombier return;
10153e12c5d1SDavid du Colombier }
10163e12c5d1SDavid du Colombier s = 0;
10173e12c5d1SDavid du Colombier ld = strtoul(buf, &s, 16);
10183e12c5d1SDavid du Colombier if(*s)
10193e12c5d1SDavid du Colombier goto illoff;
10203e12c5d1SDavid du Colombier t->off = ld;
10213e12c5d1SDavid du Colombier text(t);
10223e12c5d1SDavid du Colombier for(nt=thing; nt; nt=nt->next)
10233e12c5d1SDavid du Colombier if(nt->parent == t)
10243e12c5d1SDavid du Colombier text(nt);
10253e12c5d1SDavid du Colombier return;
10263e12c5d1SDavid du Colombier }
10273e12c5d1SDavid du Colombier if(strcmp(tag, "n") == 0){
10283e12c5d1SDavid du Colombier if(buf[0]<'0' || '9'<buf[0] || (w=atoi(buf))<=0){
10293e12c5d1SDavid du Colombier mesg("illegal n");
10303e12c5d1SDavid du Colombier return;
10313e12c5d1SDavid du Colombier }
10323e12c5d1SDavid du Colombier f = t->s;
10333e12c5d1SDavid du Colombier if(w == f->n)
10343e12c5d1SDavid du Colombier return;
10353e12c5d1SDavid du Colombier doredraw = 0;
10363e12c5d1SDavid du Colombier again:
10373e12c5d1SDavid du Colombier for(nt=thing; nt; nt=nt->next)
10383e12c5d1SDavid du Colombier if(nt->parent == t){
10393e12c5d1SDavid du Colombier doredraw = 1;
10403e12c5d1SDavid du Colombier tclose1(nt);
10413e12c5d1SDavid du Colombier goto again;
10423e12c5d1SDavid du Colombier }
10433e12c5d1SDavid du Colombier r = t->b->r;
10443e12c5d1SDavid du Colombier if(w < f->n)
10453e12c5d1SDavid du Colombier r.max.x = f->info[w].x;
10467dd7cddfSDavid du Colombier b = allocimage(display, r, t->b->chan, 0, 0);
10473e12c5d1SDavid du Colombier if(b == 0)
10483e12c5d1SDavid du Colombier goto nobmem;
10497dd7cddfSDavid du Colombier draw(b, b->r, t->b, nil, r.min);
10503e12c5d1SDavid du Colombier fdx = Dx(editr) - 2*Border;
10513e12c5d1SDavid du Colombier if(Dx(t->b->r)/fdx != Dx(b->r)/fdx)
10523e12c5d1SDavid du Colombier doredraw = 1;
10537dd7cddfSDavid du Colombier freeimage(t->b);
10543e12c5d1SDavid du Colombier t->b = b;
10557dd7cddfSDavid du Colombier b = allocimage(display, r, t->b->chan, 0, 0);
10563e12c5d1SDavid du Colombier if(b == 0)
10573e12c5d1SDavid du Colombier goto nobmem;
10587dd7cddfSDavid du Colombier draw(b, b->r, t->b, nil, r.min);
10593e12c5d1SDavid du Colombier nfc = malloc((w+1)*sizeof(Fontchar));
10603e12c5d1SDavid du Colombier if(nfc == 0){
10613e12c5d1SDavid du Colombier mesg("malloc failed");
10627dd7cddfSDavid du Colombier freeimage(b);
10633e12c5d1SDavid du Colombier return;
10643e12c5d1SDavid du Colombier }
10653e12c5d1SDavid du Colombier fc = f->info;
10663e12c5d1SDavid du Colombier for(i=0; i<=w && i<=f->n; i++)
10673e12c5d1SDavid du Colombier nfc[i] = fc[i];
10683e12c5d1SDavid du Colombier if(w+1 < i)
10693e12c5d1SDavid du Colombier memset(nfc+i, 0, ((w+1)-i)*sizeof(Fontchar));
10703e12c5d1SDavid du Colombier x = fc[f->n].x;
10713e12c5d1SDavid du Colombier for(; i<=w; i++)
10723e12c5d1SDavid du Colombier nfc[i].x = x;
10737dd7cddfSDavid du Colombier f = allocsubfont(t->name, w, f->height, f->ascent, nfc, b);
10743e12c5d1SDavid du Colombier if(f == 0)
10753e12c5d1SDavid du Colombier goto nofmem;
10767dd7cddfSDavid du Colombier t->s->bits = nil; /* don't free it */
10777dd7cddfSDavid du Colombier freesubfont(t->s);
10783e12c5d1SDavid du Colombier f->info = nfc;
10793e12c5d1SDavid du Colombier t->s = f;
10803e12c5d1SDavid du Colombier if(doredraw)
10813e12c5d1SDavid du Colombier redraw(thing);
10823e12c5d1SDavid du Colombier else
10837dd7cddfSDavid du Colombier drawthing(t, 0);
10843e12c5d1SDavid du Colombier t->mod = 1;
10853e12c5d1SDavid du Colombier return;
10863e12c5d1SDavid du Colombier }
10873e12c5d1SDavid du Colombier if(strcmp(tag, "iwidth") == 0){
10883e12c5d1SDavid du Colombier if(buf[0]<'0' || '9'<buf[0] || (w=atoi(buf))<0){
10893e12c5d1SDavid du Colombier mesg("illegal iwidth");
10903e12c5d1SDavid du Colombier return;
10913e12c5d1SDavid du Colombier }
10923e12c5d1SDavid du Colombier w -= Dx(t->b->r);
10933e12c5d1SDavid du Colombier if(w == 0)
10943e12c5d1SDavid du Colombier return;
10953e12c5d1SDavid du Colombier r = t->parent->b->r;
10963e12c5d1SDavid du Colombier r.max.x += w;
10973e12c5d1SDavid du Colombier c = t->c;
10983e12c5d1SDavid du Colombier t = t->parent;
10993e12c5d1SDavid du Colombier f = t->s;
11007dd7cddfSDavid du Colombier b = allocimage(display, r, t->b->chan, 0, 0);
11013e12c5d1SDavid du Colombier if(b == 0)
11023e12c5d1SDavid du Colombier goto nobmem;
11033e12c5d1SDavid du Colombier fc = &f->info[c];
11047dd7cddfSDavid du Colombier draw(b, Rect(b->r.min.x, b->r.min.y,
11057dd7cddfSDavid du Colombier b->r.min.x+(fc[1].x-t->b->r.min.x), b->r.min.y+Dy(t->b->r)),
11067dd7cddfSDavid du Colombier t->b, nil, t->b->r.min);
11077dd7cddfSDavid 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)),
11087dd7cddfSDavid du Colombier t->b, nil, Pt(fc[1].x, t->b->r.min.y));
11093e12c5d1SDavid du Colombier fdx = Dx(editr) - 2*Border;
11103e12c5d1SDavid du Colombier doredraw = 0;
11113e12c5d1SDavid du Colombier if(Dx(t->b->r)/fdx != Dx(b->r)/fdx)
11123e12c5d1SDavid du Colombier doredraw = 1;
11137dd7cddfSDavid du Colombier freeimage(t->b);
11143e12c5d1SDavid du Colombier t->b = b;
11157dd7cddfSDavid du Colombier b = allocimage(display, r, t->b->chan, 0, 0);
11163e12c5d1SDavid du Colombier if(b == 0)
11173e12c5d1SDavid du Colombier goto nobmem;
11187dd7cddfSDavid du Colombier draw(b, b->r, t->b, nil, t->b->r.min);
11193e12c5d1SDavid du Colombier fc = &f->info[c+1];
11203e12c5d1SDavid du Colombier for(i=c+1; i<=f->n; i++, fc++)
11213e12c5d1SDavid du Colombier fc->x += w;
11227dd7cddfSDavid du Colombier f = allocsubfont(t->name, f->n, f->height, f->ascent,
11237dd7cddfSDavid du Colombier f->info, b);
11243e12c5d1SDavid du Colombier if(f == 0)
11253e12c5d1SDavid du Colombier goto nofmem;
11263e12c5d1SDavid du Colombier /* t->s and f share info; free carefully */
11273e12c5d1SDavid du Colombier fc = f->info;
11287dd7cddfSDavid du Colombier t->s->bits = nil;
11293e12c5d1SDavid du Colombier t->s->info = 0;
11307dd7cddfSDavid du Colombier freesubfont(t->s);
11313e12c5d1SDavid du Colombier f->info = fc;
11323e12c5d1SDavid du Colombier t->s = f;
11333e12c5d1SDavid du Colombier if(doredraw)
11343e12c5d1SDavid du Colombier redraw(t);
11353e12c5d1SDavid du Colombier else
11367dd7cddfSDavid du Colombier drawthing(t, 0);
11373e12c5d1SDavid du Colombier /* redraw all affected chars */
11383e12c5d1SDavid du Colombier for(nt=thing; nt; nt=nt->next){
11393e12c5d1SDavid du Colombier if(nt->parent!=t || nt->c<c)
11403e12c5d1SDavid du Colombier continue;
11413e12c5d1SDavid du Colombier fc = &f->info[nt->c];
11423e12c5d1SDavid du Colombier r.min.x = fc[0].x;
11433e12c5d1SDavid du Colombier r.min.y = nt->b->r.min.y;
11443e12c5d1SDavid du Colombier r.max.x = fc[1].x;
11453e12c5d1SDavid du Colombier r.max.y = nt->b->r.max.y;
11467dd7cddfSDavid du Colombier b = allocimage(display, r, nt->b->chan, 0, 0);
11473e12c5d1SDavid du Colombier if(b == 0)
11483e12c5d1SDavid du Colombier goto nobmem;
11497dd7cddfSDavid du Colombier draw(b, r, t->b, nil, r.min);
11503e12c5d1SDavid du Colombier doredraw = 0;
11513e12c5d1SDavid du Colombier if(Dx(nt->b->r)/fdx != Dx(b->r)/fdx)
11523e12c5d1SDavid du Colombier doredraw = 1;
11537dd7cddfSDavid du Colombier freeimage(nt->b);
11543e12c5d1SDavid du Colombier nt->b = b;
11553e12c5d1SDavid du Colombier if(c != nt->c)
11563e12c5d1SDavid du Colombier text(nt);
11573e12c5d1SDavid du Colombier else{
11583e12c5d1SDavid du Colombier if(doredraw)
11593e12c5d1SDavid du Colombier redraw(nt);
11603e12c5d1SDavid du Colombier else
11617dd7cddfSDavid du Colombier drawthing(nt, 0);
11623e12c5d1SDavid du Colombier }
11633e12c5d1SDavid du Colombier }
11643e12c5d1SDavid du Colombier t->mod = 1;
11653e12c5d1SDavid du Colombier return;
11663e12c5d1SDavid du Colombier }
11673e12c5d1SDavid du Colombier mesg("cannot edit %s in file %s", tag, t->name);
11683e12c5d1SDavid du Colombier }
11693e12c5d1SDavid du Colombier
11703e12c5d1SDavid du Colombier void
cntledit(char * tag)11713e12c5d1SDavid du Colombier cntledit(char *tag)
11723e12c5d1SDavid du Colombier {
11733e12c5d1SDavid du Colombier char buf[256];
117422a127bbSDavid du Colombier long l;
11753e12c5d1SDavid du Colombier
11763e12c5d1SDavid du Colombier buttons(Up);
11773e12c5d1SDavid du Colombier if(type(buf, tag) == 0)
11783e12c5d1SDavid du Colombier return;
11793e12c5d1SDavid du Colombier if(strcmp(tag, "mag") == 0){
11803e12c5d1SDavid du Colombier if(buf[0]<'0' || '9'<buf[0] || (l=atoi(buf))<=0 || l>Maxmag){
11813e12c5d1SDavid du Colombier mesg("illegal magnification");
11823e12c5d1SDavid du Colombier return;
11833e12c5d1SDavid du Colombier }
11843e12c5d1SDavid du Colombier mag = l;
11853e12c5d1SDavid du Colombier cntl();
11863e12c5d1SDavid du Colombier return;
11873e12c5d1SDavid du Colombier }
11883e12c5d1SDavid du Colombier if(strcmp(tag, "but1")==0
11897dd7cddfSDavid du Colombier || strcmp(tag, "but2")==0){
11907dd7cddfSDavid du Colombier if(buf[0]<'0' || '9'<buf[0] || (l=atoi(buf))<0 || l>255){
11917dd7cddfSDavid du Colombier mesg("illegal value");
11923e12c5d1SDavid du Colombier return;
11933e12c5d1SDavid du Colombier }
11943e12c5d1SDavid du Colombier if(strcmp(tag, "but1") == 0)
11957dd7cddfSDavid du Colombier but1val = l;
11963e12c5d1SDavid du Colombier else if(strcmp(tag, "but2") == 0)
11977dd7cddfSDavid du Colombier but2val = l;
11987dd7cddfSDavid du Colombier cntl();
11997dd7cddfSDavid du Colombier return;
12007dd7cddfSDavid du Colombier }
12017dd7cddfSDavid du Colombier if(strcmp(tag, "invert-on-copy")==0){
12027dd7cddfSDavid du Colombier if(buf[0]=='y' || buf[0]=='1')
12037dd7cddfSDavid du Colombier invert = 1;
12047dd7cddfSDavid du Colombier else if(buf[0]=='n' || buf[0]=='0')
12057dd7cddfSDavid du Colombier invert = 0;
12067dd7cddfSDavid du Colombier else{
12077dd7cddfSDavid du Colombier mesg("illegal value");
12087dd7cddfSDavid du Colombier return;
12097dd7cddfSDavid du Colombier }
12103e12c5d1SDavid du Colombier cntl();
12113e12c5d1SDavid du Colombier return;
12123e12c5d1SDavid du Colombier }
12133e12c5d1SDavid du Colombier mesg("cannot edit %s", tag);
12143e12c5d1SDavid du Colombier }
12153e12c5d1SDavid du Colombier
12163e12c5d1SDavid du Colombier void
buttons(int ud)12173e12c5d1SDavid du Colombier buttons(int ud)
12183e12c5d1SDavid du Colombier {
12193e12c5d1SDavid du Colombier while((mouse.buttons==0) != ud)
12203e12c5d1SDavid du Colombier mouse = emouse();
12213e12c5d1SDavid du Colombier }
12223e12c5d1SDavid du Colombier
12237dd7cddfSDavid du Colombier Point
screenpt(Thing * t,Point realp)12247dd7cddfSDavid du Colombier screenpt(Thing *t, Point realp)
12253e12c5d1SDavid du Colombier {
12267dd7cddfSDavid du Colombier int fdx, n;
12273e12c5d1SDavid du Colombier Point p;
12283e12c5d1SDavid du Colombier
12297dd7cddfSDavid du Colombier fdx = Dx(editr)-2*Border;
12307dd7cddfSDavid du Colombier if(t->mag > 1)
12317dd7cddfSDavid du Colombier fdx -= fdx%t->mag;
12327dd7cddfSDavid du Colombier p = mulpt(subpt(realp, t->b->r.min), t->mag);
12337dd7cddfSDavid du Colombier if(fdx < Dx(t->b->r)*t->mag){
12347dd7cddfSDavid du Colombier n = p.x/fdx;
12357dd7cddfSDavid du Colombier p.y += n * (Dy(t->b->r)*t->mag+Border);
12367dd7cddfSDavid du Colombier p.x -= n * fdx;
12377dd7cddfSDavid du Colombier }
12387dd7cddfSDavid du Colombier p = addpt(p, t->r.min);
12397dd7cddfSDavid du Colombier return p;
12407dd7cddfSDavid du Colombier }
12417dd7cddfSDavid du Colombier
12427dd7cddfSDavid du Colombier Point
realpt(Thing * t,Point screenp)12437dd7cddfSDavid du Colombier realpt(Thing *t, Point screenp)
12447dd7cddfSDavid du Colombier {
12457dd7cddfSDavid du Colombier int fdx, n, dy;
12467dd7cddfSDavid du Colombier Point p;
12477dd7cddfSDavid du Colombier
12487dd7cddfSDavid du Colombier fdx = (Dx(editr)-2*Border);
12497dd7cddfSDavid du Colombier if(t->mag > 1)
12507dd7cddfSDavid du Colombier fdx -= fdx%t->mag;
12517dd7cddfSDavid du Colombier p.y = screenp.y-t->r.min.y;
12527dd7cddfSDavid du Colombier p.x = 0;
12537dd7cddfSDavid du Colombier if(fdx < Dx(t->b->r)*t->mag){
12547dd7cddfSDavid du Colombier dy = Dy(t->b->r)*t->mag+Border;
12557dd7cddfSDavid du Colombier n = (p.y/dy);
12567dd7cddfSDavid du Colombier p.x = n * fdx;
12577dd7cddfSDavid du Colombier p.y -= n * dy;
12587dd7cddfSDavid du Colombier }
12597dd7cddfSDavid du Colombier p.x += screenp.x-t->r.min.x;
12607dd7cddfSDavid du Colombier p = addpt(divpt(p, t->mag), t->b->r.min);
12617dd7cddfSDavid du Colombier return p;
12627dd7cddfSDavid du Colombier }
12637dd7cddfSDavid du Colombier
12647dd7cddfSDavid du Colombier int
sweep(int but,Rectangle * r)12657dd7cddfSDavid du Colombier sweep(int but, Rectangle *r)
12667dd7cddfSDavid du Colombier {
12677dd7cddfSDavid du Colombier Thing *t;
12687dd7cddfSDavid du Colombier Point p, q, lastq;
12697dd7cddfSDavid du Colombier
12707dd7cddfSDavid du Colombier esetcursor(&sweep0);
12713e12c5d1SDavid du Colombier buttons(Down);
12727dd7cddfSDavid du Colombier if(mouse.buttons != (1<<(but-1))){
12733e12c5d1SDavid du Colombier buttons(Up);
12747dd7cddfSDavid du Colombier esetcursor(0);
12753e12c5d1SDavid du Colombier return 0;
12763e12c5d1SDavid du Colombier }
12773e12c5d1SDavid du Colombier p = mouse.xy;
12787dd7cddfSDavid du Colombier for(t=thing; t; t=t->next)
12797dd7cddfSDavid du Colombier if(ptinrect(p, t->r))
12807dd7cddfSDavid du Colombier break;
12817dd7cddfSDavid du Colombier if(t)
12827dd7cddfSDavid du Colombier p = screenpt(t, realpt(t, p));
12833e12c5d1SDavid du Colombier r->min = p;
12843e12c5d1SDavid du Colombier r->max = p;
12857dd7cddfSDavid du Colombier esetcursor(&box);
12867dd7cddfSDavid du Colombier lastq = ZP;
12877dd7cddfSDavid du Colombier while(mouse.buttons == (1<<(but-1))){
12887dd7cddfSDavid du Colombier edrawgetrect(insetrect(*r, -Borderwidth), 1);
12893e12c5d1SDavid du Colombier mouse = emouse();
12907dd7cddfSDavid du Colombier edrawgetrect(insetrect(*r, -Borderwidth), 0);
12917dd7cddfSDavid du Colombier q = mouse.xy;
12927dd7cddfSDavid du Colombier if(t)
12937dd7cddfSDavid du Colombier q = screenpt(t, realpt(t, q));
12947dd7cddfSDavid du Colombier if(eqpt(q, lastq))
12957dd7cddfSDavid du Colombier continue;
12967dd7cddfSDavid du Colombier *r = canonrect(Rpt(p, q));
12977dd7cddfSDavid du Colombier lastq = q;
12983e12c5d1SDavid du Colombier }
12997dd7cddfSDavid du Colombier esetcursor(0);
13003e12c5d1SDavid du Colombier if(mouse.buttons){
13013e12c5d1SDavid du Colombier buttons(Up);
13023e12c5d1SDavid du Colombier return 0;
13033e12c5d1SDavid du Colombier }
13043e12c5d1SDavid du Colombier return 1;
13053e12c5d1SDavid du Colombier }
13063e12c5d1SDavid du Colombier
13073e12c5d1SDavid du Colombier void
openedit(Thing * t,Point pt,int c)13083e12c5d1SDavid du Colombier openedit(Thing *t, Point pt, int c)
13093e12c5d1SDavid du Colombier {
13103e12c5d1SDavid du Colombier int x, y;
13113e12c5d1SDavid du Colombier Point p;
13123e12c5d1SDavid du Colombier Rectangle r;
13133e12c5d1SDavid du Colombier Rectangle br;
13143e12c5d1SDavid du Colombier Fontchar *fc;
13153e12c5d1SDavid du Colombier Thing *nt;
13163e12c5d1SDavid du Colombier
13177dd7cddfSDavid du Colombier if(t->b->depth > 8){
13187dd7cddfSDavid du Colombier mesg("image has depth %d; can't handle >8", t->b->depth);
13197dd7cddfSDavid du Colombier return;
13207dd7cddfSDavid du Colombier }
13213e12c5d1SDavid du Colombier br = t->b->r;
13223e12c5d1SDavid du Colombier if(t->s == 0){
13233e12c5d1SDavid du Colombier c = -1;
13243e12c5d1SDavid du Colombier /* if big enough to bother, sweep box */
13253e12c5d1SDavid du Colombier if(Dx(br)<=16 && Dy(br)<=16)
13263e12c5d1SDavid du Colombier r = br;
13273e12c5d1SDavid du Colombier else{
13283e12c5d1SDavid du Colombier if(!sweep(1, &r))
13293e12c5d1SDavid du Colombier return;
13307dd7cddfSDavid du Colombier r = rectaddpt(r, subpt(br.min, t->r.min));
13313e12c5d1SDavid du Colombier if(!rectclip(&r, br))
13323e12c5d1SDavid du Colombier return;
13333e12c5d1SDavid du Colombier if(Dx(br) <= 8){
13343e12c5d1SDavid du Colombier r.min.x = br.min.x;
13353e12c5d1SDavid du Colombier r.max.x = br.max.x;
13363e12c5d1SDavid du Colombier }else if(Dx(r) < 4){
13373e12c5d1SDavid du Colombier toosmall:
13383e12c5d1SDavid du Colombier mesg("rectangle too small");
13393e12c5d1SDavid du Colombier return;
13403e12c5d1SDavid du Colombier }
13413e12c5d1SDavid du Colombier if(Dy(br) <= 8){
13423e12c5d1SDavid du Colombier r.min.y = br.min.y;
13433e12c5d1SDavid du Colombier r.max.y = br.max.y;
13443e12c5d1SDavid du Colombier }else if(Dy(r) < 4)
13453e12c5d1SDavid du Colombier goto toosmall;
13463e12c5d1SDavid du Colombier }
13473e12c5d1SDavid du Colombier }else if(c >= 0){
13483e12c5d1SDavid du Colombier fc = &t->s->info[c];
13493e12c5d1SDavid du Colombier r.min.x = fc[0].x;
13503e12c5d1SDavid du Colombier r.min.y = br.min.y;
13513e12c5d1SDavid du Colombier r.max.x = fc[1].x;
13523e12c5d1SDavid du Colombier r.max.y = br.min.y + Dy(br);
13533e12c5d1SDavid du Colombier }else{
13543e12c5d1SDavid du Colombier /* just point at character */
13553e12c5d1SDavid du Colombier fc = t->s->info;
13567dd7cddfSDavid du Colombier p = addpt(pt, subpt(br.min, t->r.min));
13573e12c5d1SDavid du Colombier x = br.min.x;
13583e12c5d1SDavid du Colombier y = br.min.y;
13593e12c5d1SDavid du Colombier for(c=0; c<t->s->n; c++,fc++){
13603e12c5d1SDavid du Colombier again:
13613e12c5d1SDavid du Colombier r.min.x = x;
13623e12c5d1SDavid du Colombier r.min.y = y;
13633e12c5d1SDavid du Colombier r.max.x = x + fc[1].x - fc[0].x;
13643e12c5d1SDavid du Colombier r.max.y = y + Dy(br);
13653e12c5d1SDavid du Colombier if(ptinrect(p, r))
13663e12c5d1SDavid du Colombier goto found;
13673e12c5d1SDavid du Colombier if(r.max.x >= br.min.x+Dx(t->r)){
13683e12c5d1SDavid du Colombier x -= Dx(t->r);
13693e12c5d1SDavid du Colombier y += t->s->height;
13703e12c5d1SDavid du Colombier if(fc[1].x > fc[0].x)
13713e12c5d1SDavid du Colombier goto again;
13723e12c5d1SDavid du Colombier }
13733e12c5d1SDavid du Colombier x += fc[1].x - fc[0].x;
13743e12c5d1SDavid du Colombier }
13753e12c5d1SDavid du Colombier return;
13763e12c5d1SDavid du Colombier found:
13773e12c5d1SDavid du Colombier r = br;
13783e12c5d1SDavid du Colombier r.min.x = fc[0].x;
13793e12c5d1SDavid du Colombier r.max.x = fc[1].x;
13803e12c5d1SDavid du Colombier }
13813e12c5d1SDavid du Colombier nt = malloc(sizeof(Thing));
13823e12c5d1SDavid du Colombier if(nt == 0){
13833e12c5d1SDavid du Colombier nomem:
13843e12c5d1SDavid du Colombier mesg("can't allocate: %r");
13853e12c5d1SDavid du Colombier return;
13863e12c5d1SDavid du Colombier }
13873e12c5d1SDavid du Colombier memset(nt, 0, sizeof(Thing));
13883e12c5d1SDavid du Colombier nt->c = c;
13897dd7cddfSDavid du Colombier nt->b = allocimage(display, r, t->b->chan, 0, DNofill);
13903e12c5d1SDavid du Colombier if(nt->b == 0){
13913e12c5d1SDavid du Colombier free(nt);
13923e12c5d1SDavid du Colombier goto nomem;
13933e12c5d1SDavid du Colombier }
13947dd7cddfSDavid du Colombier draw(nt->b, r, t->b, nil, r.min);
13953e12c5d1SDavid du Colombier nt->name = strdup(t->name);
13963e12c5d1SDavid du Colombier if(nt->name == 0){
13977dd7cddfSDavid du Colombier freeimage(nt->b);
13983e12c5d1SDavid du Colombier free(nt);
13993e12c5d1SDavid du Colombier goto nomem;
14003e12c5d1SDavid du Colombier }
14013e12c5d1SDavid du Colombier nt->parent = t;
14023e12c5d1SDavid du Colombier nt->mag = mag;
14037dd7cddfSDavid du Colombier drawthing(nt, 1);
14043e12c5d1SDavid du Colombier }
14053e12c5d1SDavid du Colombier
14063e12c5d1SDavid du Colombier void
ckinfo(Thing * t,Rectangle mod)14073e12c5d1SDavid du Colombier ckinfo(Thing *t, Rectangle mod)
14083e12c5d1SDavid du Colombier {
14093e12c5d1SDavid du Colombier int i, j, k, top, bot, n, zero;
14103e12c5d1SDavid du Colombier Fontchar *fc;
14113e12c5d1SDavid du Colombier Rectangle r;
14127dd7cddfSDavid du Colombier Image *b;
14133e12c5d1SDavid du Colombier Thing *nt;
14143e12c5d1SDavid du Colombier
14153e12c5d1SDavid du Colombier if(t->parent)
14163e12c5d1SDavid du Colombier t = t->parent;
14173e12c5d1SDavid du Colombier if(t->s==0 || Dy(t->b->r)==0)
14183e12c5d1SDavid du Colombier return;
14193e12c5d1SDavid du Colombier b = 0;
14203e12c5d1SDavid du Colombier /* check bounding boxes */
14213e12c5d1SDavid du Colombier fc = &t->s->info[0];
14223e12c5d1SDavid du Colombier r.min.y = t->b->r.min.y;
14233e12c5d1SDavid du Colombier r.max.y = t->b->r.max.y;
14243e12c5d1SDavid du Colombier for(i=0; i<t->s->n; i++, fc++){
14253e12c5d1SDavid du Colombier r.min.x = fc[0].x;
14263e12c5d1SDavid du Colombier r.max.x = fc[1].x;
14273e12c5d1SDavid du Colombier if(!rectXrect(mod, r))
14283e12c5d1SDavid du Colombier continue;
14293e12c5d1SDavid du Colombier if(b==0 || Dx(b->r)<Dx(r)){
14303e12c5d1SDavid du Colombier if(b)
14317dd7cddfSDavid du Colombier freeimage(b);
14327dd7cddfSDavid du Colombier b = allocimage(display, rectsubpt(r, r.min), t->b->chan, 0, 0);
14333e12c5d1SDavid du Colombier if(b == 0){
14347dd7cddfSDavid du Colombier mesg("can't alloc image");
14353e12c5d1SDavid du Colombier break;
14363e12c5d1SDavid du Colombier }
14373e12c5d1SDavid du Colombier }
14387dd7cddfSDavid du Colombier draw(b, b->r, display->white, nil, ZP);
14397dd7cddfSDavid du Colombier draw(b, b->r, t->b, nil, r.min);
14403e12c5d1SDavid du Colombier top = 100000;
14413e12c5d1SDavid du Colombier bot = 0;
14427dd7cddfSDavid du Colombier n = 2+((Dx(r)/8)*t->b->depth);
14433e12c5d1SDavid du Colombier for(j=0; j<b->r.max.y; j++){
14443e12c5d1SDavid du Colombier memset(data, 0, n);
14457dd7cddfSDavid du Colombier unloadimage(b, Rect(b->r.min.x, j, b->r.max.x, j+1), data, sizeof data);
14463e12c5d1SDavid du Colombier zero = 1;
14473e12c5d1SDavid du Colombier for(k=0; k<n; k++)
14483e12c5d1SDavid du Colombier if(data[k]){
14493e12c5d1SDavid du Colombier zero = 0;
14503e12c5d1SDavid du Colombier break;
14513e12c5d1SDavid du Colombier }
14523e12c5d1SDavid du Colombier if(!zero){
14533e12c5d1SDavid du Colombier if(top > j)
14543e12c5d1SDavid du Colombier top = j;
14553e12c5d1SDavid du Colombier bot = j+1;
14563e12c5d1SDavid du Colombier }
14573e12c5d1SDavid du Colombier }
14583e12c5d1SDavid du Colombier if(top > j)
14593e12c5d1SDavid du Colombier top = 0;
14603e12c5d1SDavid du Colombier if(top!=fc->top || bot!=fc->bottom){
14613e12c5d1SDavid du Colombier fc->top = top;
14623e12c5d1SDavid du Colombier fc->bottom = bot;
14633e12c5d1SDavid du Colombier for(nt=thing; nt; nt=nt->next)
14643e12c5d1SDavid du Colombier if(nt->parent==t && nt->c==i)
14653e12c5d1SDavid du Colombier text(nt);
14663e12c5d1SDavid du Colombier }
14673e12c5d1SDavid du Colombier }
14683e12c5d1SDavid du Colombier if(b)
14697dd7cddfSDavid du Colombier freeimage(b);
14703e12c5d1SDavid du Colombier }
14713e12c5d1SDavid du Colombier
14723e12c5d1SDavid du Colombier void
twidpix(Thing * t,Point p,int set)14733e12c5d1SDavid du Colombier twidpix(Thing *t, Point p, int set)
14743e12c5d1SDavid du Colombier {
14757dd7cddfSDavid du Colombier Image *b, *v;
14767dd7cddfSDavid du Colombier int c;
14773e12c5d1SDavid du Colombier
14783e12c5d1SDavid du Colombier b = t->b;
14793e12c5d1SDavid du Colombier if(!ptinrect(p, b->r))
14803e12c5d1SDavid du Colombier return;
14817dd7cddfSDavid du Colombier if(set)
14827dd7cddfSDavid du Colombier c = but1val;
14837dd7cddfSDavid du Colombier else
14847dd7cddfSDavid du Colombier c = but2val;
14857dd7cddfSDavid du Colombier if(b->chan == GREY8)
14867dd7cddfSDavid du Colombier v = greyvalues[c];
14877dd7cddfSDavid du Colombier else
14887dd7cddfSDavid du Colombier v = values[c];
14897dd7cddfSDavid du Colombier draw(b, Rect(p.x, p.y, p.x+1, p.y+1), v, nil, ZP);
14903e12c5d1SDavid du Colombier p = screenpt(t, p);
14917dd7cddfSDavid du Colombier draw(screen, Rect(p.x, p.y, p.x+t->mag, p.y+t->mag), v, nil, ZP);
14923e12c5d1SDavid du Colombier }
14933e12c5d1SDavid du Colombier
14943e12c5d1SDavid du Colombier void
twiddle(Thing * t)14953e12c5d1SDavid du Colombier twiddle(Thing *t)
14963e12c5d1SDavid du Colombier {
14973e12c5d1SDavid du Colombier int set;
14983e12c5d1SDavid du Colombier Point p, lastp;
14997dd7cddfSDavid du Colombier Image *b;
15003e12c5d1SDavid du Colombier Thing *nt;
15013e12c5d1SDavid du Colombier Rectangle mod;
15023e12c5d1SDavid du Colombier
15033e12c5d1SDavid du Colombier if(mouse.buttons!=1 && mouse.buttons!=2){
15043e12c5d1SDavid du Colombier buttons(Up);
15053e12c5d1SDavid du Colombier return;
15063e12c5d1SDavid du Colombier }
15073e12c5d1SDavid du Colombier set = mouse.buttons==1;
15083e12c5d1SDavid du Colombier b = t->b;
15097dd7cddfSDavid du Colombier lastp = addpt(b->r.min, Pt(-1, -1));
15107dd7cddfSDavid du Colombier mod = Rpt(addpt(b->r.max, Pt(1, 1)), lastp);
15113e12c5d1SDavid du Colombier while(mouse.buttons){
15123e12c5d1SDavid du Colombier p = realpt(t, mouse.xy);
15133e12c5d1SDavid du Colombier if(!eqpt(p, lastp)){
15143e12c5d1SDavid du Colombier lastp = p;
15153e12c5d1SDavid du Colombier if(ptinrect(p, b->r)){
15163e12c5d1SDavid du Colombier for(nt=thing; nt; nt=nt->next)
15173e12c5d1SDavid du Colombier if(nt->parent==t->parent || nt==t->parent)
15183e12c5d1SDavid du Colombier twidpix(nt, p, set);
15193e12c5d1SDavid du Colombier if(t->parent)
15203e12c5d1SDavid du Colombier t->parent->mod = 1;
15213e12c5d1SDavid du Colombier else
15223e12c5d1SDavid du Colombier t->mod = 1;
15233e12c5d1SDavid du Colombier if(p.x < mod.min.x)
15243e12c5d1SDavid du Colombier mod.min.x = p.x;
15253e12c5d1SDavid du Colombier if(p.y < mod.min.y)
15263e12c5d1SDavid du Colombier mod.min.y = p.y;
15273e12c5d1SDavid du Colombier if(p.x >= mod.max.x)
15283e12c5d1SDavid du Colombier mod.max.x = p.x+1;
15293e12c5d1SDavid du Colombier if(p.y >= mod.max.y)
15303e12c5d1SDavid du Colombier mod.max.y = p.y+1;
15313e12c5d1SDavid du Colombier }
15323e12c5d1SDavid du Colombier }
15333e12c5d1SDavid du Colombier mouse = emouse();
15343e12c5d1SDavid du Colombier }
15353e12c5d1SDavid du Colombier ckinfo(t, mod);
15363e12c5d1SDavid du Colombier }
15373e12c5d1SDavid du Colombier
15383e12c5d1SDavid du Colombier void
select(void)15393e12c5d1SDavid du Colombier select(void)
15403e12c5d1SDavid du Colombier {
15413e12c5d1SDavid du Colombier Thing *t;
15423e12c5d1SDavid du Colombier char line[128], buf[128];
15433e12c5d1SDavid du Colombier Point p;
15443e12c5d1SDavid du Colombier
15453e12c5d1SDavid du Colombier if(ptinrect(mouse.xy, cntlr)){
15463e12c5d1SDavid du Colombier scntl(line);
15473e12c5d1SDavid du Colombier if(atline(cntlr.min.x, mouse.xy, line, buf)){
15483e12c5d1SDavid du Colombier if(mouse.buttons == 1)
15493e12c5d1SDavid du Colombier cntledit(buf);
15503e12c5d1SDavid du Colombier else
15513e12c5d1SDavid du Colombier buttons(Up);
15523e12c5d1SDavid du Colombier return;
15533e12c5d1SDavid du Colombier }
15543e12c5d1SDavid du Colombier return;
15553e12c5d1SDavid du Colombier }
15563e12c5d1SDavid du Colombier for(t=thing; t; t=t->next){
15573e12c5d1SDavid du Colombier if(attext(t, mouse.xy, buf)){
15583e12c5d1SDavid du Colombier if(mouse.buttons == 1)
15593e12c5d1SDavid du Colombier textedit(t, buf);
15603e12c5d1SDavid du Colombier else
15613e12c5d1SDavid du Colombier buttons(Up);
15623e12c5d1SDavid du Colombier return;
15633e12c5d1SDavid du Colombier }
15643e12c5d1SDavid du Colombier if(ptinrect(mouse.xy, t->r)){
15653e12c5d1SDavid du Colombier if(t->parent == 0){
15663e12c5d1SDavid du Colombier if(mouse.buttons == 1){
15673e12c5d1SDavid du Colombier p = mouse.xy;
15683e12c5d1SDavid du Colombier buttons(Up);
15693e12c5d1SDavid du Colombier openedit(t, p, -1);
15703e12c5d1SDavid du Colombier }else
15713e12c5d1SDavid du Colombier buttons(Up);
15723e12c5d1SDavid du Colombier return;
15733e12c5d1SDavid du Colombier }
15743e12c5d1SDavid du Colombier twiddle(t);
15753e12c5d1SDavid du Colombier return;
15763e12c5d1SDavid du Colombier }
15773e12c5d1SDavid du Colombier }
15783e12c5d1SDavid du Colombier }
15793e12c5d1SDavid du Colombier
15803e12c5d1SDavid du Colombier void
twrite(Thing * t)15813e12c5d1SDavid du Colombier twrite(Thing *t)
15823e12c5d1SDavid du Colombier {
15833e12c5d1SDavid du Colombier int i, j, x, y, fd, ws, ld;
15843e12c5d1SDavid du Colombier Biobuf buf;
15853e12c5d1SDavid du Colombier Rectangle r;
15863e12c5d1SDavid du Colombier
15873e12c5d1SDavid du Colombier if(t->parent)
15883e12c5d1SDavid du Colombier t = t->parent;
15897dd7cddfSDavid du Colombier esetcursor(&busy);
15903e12c5d1SDavid du Colombier fd = create(t->name, OWRITE, 0666);
15913e12c5d1SDavid du Colombier if(fd < 0){
15923e12c5d1SDavid du Colombier mesg("can't write %s: %r", t->name);
15933e12c5d1SDavid du Colombier return;
15943e12c5d1SDavid du Colombier }
15959a747e4fSDavid du Colombier if(t->face && t->b->depth <= 4){
15963e12c5d1SDavid du Colombier r = t->b->r;
15977dd7cddfSDavid du Colombier ld = log2[t->b->depth];
15983e12c5d1SDavid du Colombier /* This heuristic reflects peculiarly different formats */
15993e12c5d1SDavid du Colombier ws = 4;
16007dd7cddfSDavid du Colombier if(t->face == 2) /* cursor file */
16013e12c5d1SDavid du Colombier ws = 1;
16023e12c5d1SDavid du Colombier else if(Dx(r)<32 || ld==0)
16033e12c5d1SDavid du Colombier ws = 2;
16043e12c5d1SDavid du Colombier Binit(&buf, fd, OWRITE);
16057dd7cddfSDavid du Colombier if(t->face == CURSOR)
16067dd7cddfSDavid du Colombier Bprint(&buf, "{");
16073e12c5d1SDavid du Colombier for(y=r.min.y; y<r.max.y; y++){
16087dd7cddfSDavid du Colombier unloadimage(t->b, Rect(r.min.x, y, r.max.x, y+1), data, sizeof data);
16093e12c5d1SDavid du Colombier j = 0;
16103e12c5d1SDavid du Colombier for(x=r.min.x; x<r.max.x; j+=ws,x+=ws*8>>ld){
16113e12c5d1SDavid du Colombier Bprint(&buf, "0x");
16123e12c5d1SDavid du Colombier for(i=0; i<ws; i++)
16133e12c5d1SDavid du Colombier Bprint(&buf, "%.2x", data[i+j]);
16143e12c5d1SDavid du Colombier Bprint(&buf, ", ");
16153e12c5d1SDavid du Colombier }
16167dd7cddfSDavid du Colombier if(t->face == CURSOR){
16177dd7cddfSDavid du Colombier switch(y){
16187dd7cddfSDavid du Colombier case 3: case 7: case 11: case 19: case 23: case 27:
16197dd7cddfSDavid du Colombier Bprint(&buf, "\n ");
16207dd7cddfSDavid du Colombier break;
16217dd7cddfSDavid du Colombier case 15:
16227dd7cddfSDavid du Colombier Bprint(&buf, "},\n{");
16237dd7cddfSDavid du Colombier break;
16247dd7cddfSDavid du Colombier case 31:
16257dd7cddfSDavid du Colombier Bprint(&buf, "}\n");
16267dd7cddfSDavid du Colombier break;
16277dd7cddfSDavid du Colombier }
16287dd7cddfSDavid du Colombier }else
16293e12c5d1SDavid du Colombier Bprint(&buf, "\n");
16303e12c5d1SDavid du Colombier }
1631219b2ee8SDavid du Colombier Bterm(&buf);
16327dd7cddfSDavid du Colombier }else
16337dd7cddfSDavid du Colombier if(writeimage(fd, t->b, 0)<0 || (t->s && writesubfont(fd, t->s)<0)){
16347dd7cddfSDavid du Colombier close(fd);
16357dd7cddfSDavid du Colombier mesg("can't write %s: %r", t->name);
16363e12c5d1SDavid du Colombier }
16373e12c5d1SDavid du Colombier t->mod = 0;
16383e12c5d1SDavid du Colombier close(fd);
16393e12c5d1SDavid du Colombier mesg("wrote %s", t->name);
16403e12c5d1SDavid du Colombier }
16413e12c5d1SDavid du Colombier
16423e12c5d1SDavid du Colombier void
tpixels(void)16437dd7cddfSDavid du Colombier tpixels(void)
16447dd7cddfSDavid du Colombier {
16457dd7cddfSDavid du Colombier Thing *t;
16467dd7cddfSDavid du Colombier Point p, lastp;
16477dd7cddfSDavid du Colombier
16487dd7cddfSDavid du Colombier esetcursor(&pixel);
16497dd7cddfSDavid du Colombier for(;;){
16507dd7cddfSDavid du Colombier buttons(Down);
16517dd7cddfSDavid du Colombier if(mouse.buttons != 4)
16527dd7cddfSDavid du Colombier break;
16537dd7cddfSDavid du Colombier for(t=thing; t; t=t->next){
16547dd7cddfSDavid du Colombier lastp = Pt(-1, -1);
16557dd7cddfSDavid du Colombier if(ptinrect(mouse.xy, t->r)){
16567dd7cddfSDavid du Colombier while(ptinrect(mouse.xy, t->r) && mouse.buttons==4){
16577dd7cddfSDavid du Colombier p = realpt(t, mouse.xy);
16587dd7cddfSDavid du Colombier if(!eqpt(p, lastp)){
16597dd7cddfSDavid du Colombier if(p.y != lastp.y)
16607dd7cddfSDavid du Colombier unloadimage(t->b, Rect(t->b->r.min.x, p.y, t->b->r.max.x, p.y+1), data, sizeof data);
16617dd7cddfSDavid du Colombier mesg("[%d,%d] = %d=0x%ux", p.x, p.y, value(t->b, p.x), value(t->b, p.x));
16627dd7cddfSDavid du Colombier lastp = p;
16637dd7cddfSDavid du Colombier }
16647dd7cddfSDavid du Colombier mouse = emouse();
16657dd7cddfSDavid du Colombier }
16667dd7cddfSDavid du Colombier goto Continue;
16677dd7cddfSDavid du Colombier }
16687dd7cddfSDavid du Colombier }
16697dd7cddfSDavid du Colombier mouse = emouse();
16707dd7cddfSDavid du Colombier Continue:;
16717dd7cddfSDavid du Colombier }
16727dd7cddfSDavid du Colombier buttons(Up);
16737dd7cddfSDavid du Colombier esetcursor(0);
16747dd7cddfSDavid du Colombier }
16757dd7cddfSDavid du Colombier
16767dd7cddfSDavid du Colombier void
tclose1(Thing * t)16773e12c5d1SDavid du Colombier tclose1(Thing *t)
16783e12c5d1SDavid du Colombier {
16793e12c5d1SDavid du Colombier Thing *nt;
16803e12c5d1SDavid du Colombier
16813e12c5d1SDavid du Colombier if(t == thing)
16823e12c5d1SDavid du Colombier thing = t->next;
16833e12c5d1SDavid du Colombier else{
16843e12c5d1SDavid du Colombier for(nt=thing; nt->next!=t; nt=nt->next)
16853e12c5d1SDavid du Colombier ;
16863e12c5d1SDavid du Colombier nt->next = t->next;
16873e12c5d1SDavid du Colombier }
16883e12c5d1SDavid du Colombier do
16893e12c5d1SDavid du Colombier for(nt=thing; nt; nt=nt->next)
16903e12c5d1SDavid du Colombier if(nt->parent == t){
16913e12c5d1SDavid du Colombier tclose1(nt);
16923e12c5d1SDavid du Colombier break;
16933e12c5d1SDavid du Colombier }
16943e12c5d1SDavid du Colombier while(nt);
16953e12c5d1SDavid du Colombier if(t->s)
16967dd7cddfSDavid du Colombier freesubfont(t->s);
16977dd7cddfSDavid du Colombier else
16987dd7cddfSDavid du Colombier freeimage(t->b);
16993e12c5d1SDavid du Colombier free(t->name);
17003e12c5d1SDavid du Colombier free(t);
17013e12c5d1SDavid du Colombier }
17023e12c5d1SDavid du Colombier
17033e12c5d1SDavid du Colombier void
tclose(Thing * t)17043e12c5d1SDavid du Colombier tclose(Thing *t)
17053e12c5d1SDavid du Colombier {
17063e12c5d1SDavid du Colombier Thing *ct;
17073e12c5d1SDavid du Colombier
17083e12c5d1SDavid du Colombier if(t->mod){
17093e12c5d1SDavid du Colombier mesg("%s modified", t->name);
17103e12c5d1SDavid du Colombier t->mod = 0;
17113e12c5d1SDavid du Colombier return;
17123e12c5d1SDavid du Colombier }
17133e12c5d1SDavid du Colombier /* fiddle to save redrawing unmoved things */
17143e12c5d1SDavid du Colombier if(t == thing)
17153e12c5d1SDavid du Colombier ct = 0;
17163e12c5d1SDavid du Colombier else
17173e12c5d1SDavid du Colombier for(ct=thing; ct; ct=ct->next)
17183e12c5d1SDavid du Colombier if(ct->next==t || ct->next->parent==t)
17193e12c5d1SDavid du Colombier break;
17203e12c5d1SDavid du Colombier tclose1(t);
17213e12c5d1SDavid du Colombier if(ct)
17223e12c5d1SDavid du Colombier ct = ct->next;
17233e12c5d1SDavid du Colombier else
17243e12c5d1SDavid du Colombier ct = thing;
17253e12c5d1SDavid du Colombier redraw(ct);
17263e12c5d1SDavid du Colombier }
17273e12c5d1SDavid du Colombier
17283e12c5d1SDavid du Colombier void
tread(Thing * t)17293e12c5d1SDavid du Colombier tread(Thing *t)
17303e12c5d1SDavid du Colombier {
17313e12c5d1SDavid du Colombier Thing *nt, *new;
17323e12c5d1SDavid du Colombier Fontchar *i;
17333e12c5d1SDavid du Colombier Rectangle r;
17343e12c5d1SDavid du Colombier int nclosed;
17353e12c5d1SDavid du Colombier
17363e12c5d1SDavid du Colombier if(t->parent)
17373e12c5d1SDavid du Colombier t = t->parent;
17383e12c5d1SDavid du Colombier new = tget(t->name);
17393e12c5d1SDavid du Colombier if(new == 0)
17403e12c5d1SDavid du Colombier return;
17413e12c5d1SDavid du Colombier nclosed = 0;
17423e12c5d1SDavid du Colombier again:
17433e12c5d1SDavid du Colombier for(nt=thing; nt; nt=nt->next)
17443e12c5d1SDavid du Colombier if(nt->parent == t){
17453e12c5d1SDavid du Colombier if(!rectinrect(nt->b->r, new->b->r)
17467dd7cddfSDavid du Colombier || new->b->depth!=nt->b->depth){
17473e12c5d1SDavid du Colombier closeit:
17483e12c5d1SDavid du Colombier nclosed++;
17493e12c5d1SDavid du Colombier nt->parent = 0;
17503e12c5d1SDavid du Colombier tclose1(nt);
17513e12c5d1SDavid du Colombier goto again;
17523e12c5d1SDavid du Colombier }
17533e12c5d1SDavid du Colombier if((t->s==0) != (new->s==0))
17543e12c5d1SDavid du Colombier goto closeit;
17553e12c5d1SDavid du Colombier if((t->face==0) != (new->face==0))
17563e12c5d1SDavid du Colombier goto closeit;
17573e12c5d1SDavid du Colombier if(t->s){ /* check same char */
17583e12c5d1SDavid du Colombier if(nt->c >= new->s->n)
17593e12c5d1SDavid du Colombier goto closeit;
17603e12c5d1SDavid du Colombier i = &new->s->info[nt->c];
17613e12c5d1SDavid du Colombier r.min.x = i[0].x;
17623e12c5d1SDavid du Colombier r.max.x = i[1].x;
17633e12c5d1SDavid du Colombier r.min.y = new->b->r.min.y;
17643e12c5d1SDavid du Colombier r.max.y = new->b->r.max.y;
17653e12c5d1SDavid du Colombier if(!eqrect(r, nt->b->r))
17663e12c5d1SDavid du Colombier goto closeit;
17673e12c5d1SDavid du Colombier }
17683e12c5d1SDavid du Colombier nt->parent = new;
17697dd7cddfSDavid du Colombier draw(nt->b, nt->b->r, new->b, nil, nt->b->r.min);
17703e12c5d1SDavid du Colombier }
17713e12c5d1SDavid du Colombier new->next = t->next;
17723e12c5d1SDavid du Colombier if(t == thing)
17733e12c5d1SDavid du Colombier thing = new;
17743e12c5d1SDavid du Colombier else{
17753e12c5d1SDavid du Colombier for(nt=thing; nt->next!=t; nt=nt->next)
17763e12c5d1SDavid du Colombier ;
17773e12c5d1SDavid du Colombier nt->next = new;
17783e12c5d1SDavid du Colombier }
17793e12c5d1SDavid du Colombier if(t->s)
17807dd7cddfSDavid du Colombier freesubfont(t->s);
17817dd7cddfSDavid du Colombier else
17827dd7cddfSDavid du Colombier freeimage(t->b);
17833e12c5d1SDavid du Colombier free(t->name);
17843e12c5d1SDavid du Colombier free(t);
17853e12c5d1SDavid du Colombier for(nt=thing; nt; nt=nt->next)
17863e12c5d1SDavid du Colombier if(nt==new || nt->parent==new)
17873e12c5d1SDavid du Colombier if(nclosed == 0)
17887dd7cddfSDavid du Colombier drawthing(nt, 0); /* can draw in place */
17893e12c5d1SDavid du Colombier else{
17903e12c5d1SDavid du Colombier redraw(nt); /* must redraw all below */
17913e12c5d1SDavid du Colombier break;
17923e12c5d1SDavid du Colombier }
17933e12c5d1SDavid du Colombier }
17943e12c5d1SDavid du Colombier
17953e12c5d1SDavid du Colombier void
tchar(Thing * t)17963e12c5d1SDavid du Colombier tchar(Thing *t)
17973e12c5d1SDavid du Colombier {
1798219b2ee8SDavid du Colombier char buf[256], *p;
17993e12c5d1SDavid du Colombier Rune r;
1800219b2ee8SDavid du Colombier ulong c, d;
18013e12c5d1SDavid du Colombier
18023e12c5d1SDavid du Colombier if(t->s == 0){
18037dd7cddfSDavid du Colombier t = t->parent;
18047dd7cddfSDavid du Colombier if(t==0 || t->s==0){
18053e12c5d1SDavid du Colombier mesg("not a subfont");
18063e12c5d1SDavid du Colombier return;
18073e12c5d1SDavid du Colombier }
18087dd7cddfSDavid du Colombier }
1809219b2ee8SDavid du Colombier if(type(buf, "char (hex or character or hex-hex)") == 0)
18103e12c5d1SDavid du Colombier return;
18113e12c5d1SDavid du Colombier if(utflen(buf) == 1){
18123e12c5d1SDavid du Colombier chartorune(&r, buf);
18133e12c5d1SDavid du Colombier c = r;
1814219b2ee8SDavid du Colombier d = r;
18153e12c5d1SDavid du Colombier }else{
18163e12c5d1SDavid du Colombier if(!strchr(hex, buf[0])){
18173e12c5d1SDavid du Colombier mesg("illegal hex character");
18183e12c5d1SDavid du Colombier return;
18193e12c5d1SDavid du Colombier }
18203e12c5d1SDavid du Colombier c = strtoul(buf, 0, 16);
1821219b2ee8SDavid du Colombier d = c;
1822219b2ee8SDavid du Colombier p = utfrune(buf, '-');
1823219b2ee8SDavid du Colombier if(p){
1824219b2ee8SDavid du Colombier d = strtoul(p+1, 0, 16);
1825219b2ee8SDavid du Colombier if(d < c){
1826219b2ee8SDavid du Colombier mesg("invalid range");
1827219b2ee8SDavid du Colombier return;
1828219b2ee8SDavid du Colombier }
1829219b2ee8SDavid du Colombier }
18303e12c5d1SDavid du Colombier }
18313e12c5d1SDavid du Colombier c -= t->off;
1832219b2ee8SDavid du Colombier d -= t->off;
1833219b2ee8SDavid du Colombier while(c <= d){
1834c93608ccSDavid du Colombier if(c>=t->s->n){
18353e12c5d1SDavid du Colombier mesg("0x%lux not in font %s", c+t->off, t->name);
18363e12c5d1SDavid du Colombier return;
18373e12c5d1SDavid du Colombier }
18383e12c5d1SDavid du Colombier openedit(t, Pt(0, 0), c);
1839219b2ee8SDavid du Colombier c++;
1840219b2ee8SDavid du Colombier }
18413e12c5d1SDavid du Colombier }
18423e12c5d1SDavid du Colombier
18433e12c5d1SDavid du Colombier void
apply(void (* f)(Thing *))18443e12c5d1SDavid du Colombier apply(void (*f)(Thing*))
18453e12c5d1SDavid du Colombier {
18463e12c5d1SDavid du Colombier Thing *t;
18473e12c5d1SDavid du Colombier
18487dd7cddfSDavid du Colombier esetcursor(&sight);
18493e12c5d1SDavid du Colombier buttons(Down);
18503e12c5d1SDavid du Colombier if(mouse.buttons == 4)
18513e12c5d1SDavid du Colombier for(t=thing; t; t=t->next)
18523e12c5d1SDavid du Colombier if(ptinrect(mouse.xy, t->er)){
18533e12c5d1SDavid du Colombier buttons(Up);
18543e12c5d1SDavid du Colombier f(t);
18553e12c5d1SDavid du Colombier break;
18563e12c5d1SDavid du Colombier }
18573e12c5d1SDavid du Colombier buttons(Up);
18587dd7cddfSDavid du Colombier esetcursor(0);
18597dd7cddfSDavid du Colombier }
18607dd7cddfSDavid du Colombier
18617dd7cddfSDavid du Colombier int
complement(Image * t)18627dd7cddfSDavid du Colombier complement(Image *t)
18637dd7cddfSDavid du Colombier {
18647dd7cddfSDavid du Colombier int i, n;
18657dd7cddfSDavid du Colombier uchar *buf;
18667dd7cddfSDavid du Colombier
18677dd7cddfSDavid du Colombier n = Dy(t->r)*bytesperline(t->r, t->depth);
18687dd7cddfSDavid du Colombier buf = malloc(n);
18697dd7cddfSDavid du Colombier if(buf == 0)
18707dd7cddfSDavid du Colombier return 0;
18717dd7cddfSDavid du Colombier unloadimage(t, t->r, buf, n);
18727dd7cddfSDavid du Colombier for(i=0; i<n; i++)
18737dd7cddfSDavid du Colombier buf[i] = ~buf[i];
18747dd7cddfSDavid du Colombier loadimage(t, t->r, buf, n);
18757dd7cddfSDavid du Colombier free(buf);
18767dd7cddfSDavid du Colombier return 1;
18773e12c5d1SDavid du Colombier }
18783e12c5d1SDavid du Colombier
18793e12c5d1SDavid du Colombier void
copy(void)18803e12c5d1SDavid du Colombier copy(void)
18813e12c5d1SDavid du Colombier {
18823e12c5d1SDavid du Colombier Thing *st, *dt, *nt;
18833e12c5d1SDavid du Colombier Rectangle sr, dr, fr;
18847dd7cddfSDavid du Colombier Image *tmp;
18853e12c5d1SDavid du Colombier Point p1, p2;
18863e12c5d1SDavid du Colombier int but, up;
18873e12c5d1SDavid du Colombier
18887dd7cddfSDavid du Colombier if(!sweep(3, &sr))
18893e12c5d1SDavid du Colombier return;
18903e12c5d1SDavid du Colombier for(st=thing; st; st=st->next)
18913e12c5d1SDavid du Colombier if(rectXrect(sr, st->r))
18923e12c5d1SDavid du Colombier break;
18933e12c5d1SDavid du Colombier if(st == 0)
18943e12c5d1SDavid du Colombier return;
18953e12c5d1SDavid du Colombier /* click gives full rectangle */
18963e12c5d1SDavid du Colombier if(Dx(sr)<4 && Dy(sr)<4)
18973e12c5d1SDavid du Colombier sr = st->r;
18983e12c5d1SDavid du Colombier rectclip(&sr, st->r);
18993e12c5d1SDavid du Colombier p1 = realpt(st, sr.min);
19003e12c5d1SDavid du Colombier p2 = realpt(st, Pt(sr.min.x, sr.max.y));
190180ee5cbfSDavid du Colombier up = 0;
19023e12c5d1SDavid du Colombier if(p1.x != p2.x){ /* swept across a fold */
19033e12c5d1SDavid du Colombier onafold:
19043e12c5d1SDavid du Colombier mesg("sweep spans a fold");
190580ee5cbfSDavid du Colombier goto Return;
19063e12c5d1SDavid du Colombier }
19073e12c5d1SDavid du Colombier p2 = realpt(st, sr.max);
19083e12c5d1SDavid du Colombier sr.min = p1;
19093e12c5d1SDavid du Colombier sr.max = p2;
19103e12c5d1SDavid du Colombier fr.min = screenpt(st, sr.min);
19113e12c5d1SDavid du Colombier fr.max = screenpt(st, sr.max);
19127dd7cddfSDavid du Colombier p1 = subpt(p2, p1); /* diagonal */
19137dd7cddfSDavid du Colombier if(p1.x==0 || p1.y==0)
19143e12c5d1SDavid du Colombier return;
19157dd7cddfSDavid du Colombier border(screen, fr, -1, values[Blue], ZP);
19167dd7cddfSDavid du Colombier esetcursor(&box);
19173e12c5d1SDavid du Colombier for(; mouse.buttons==0; mouse=emouse()){
19183e12c5d1SDavid du Colombier for(dt=thing; dt; dt=dt->next)
19193e12c5d1SDavid du Colombier if(ptinrect(mouse.xy, dt->er))
19203e12c5d1SDavid du Colombier break;
19213e12c5d1SDavid du Colombier if(up)
19227dd7cddfSDavid du Colombier edrawgetrect(insetrect(dr, -Borderwidth), 0);
19233e12c5d1SDavid du Colombier up = 0;
19243e12c5d1SDavid du Colombier if(dt == 0)
19253e12c5d1SDavid du Colombier continue;
19263e12c5d1SDavid du Colombier dr.max = screenpt(dt, realpt(dt, mouse.xy));
19277dd7cddfSDavid du Colombier dr.min = subpt(dr.max, mulpt(p1, dt->mag));
19283e12c5d1SDavid du Colombier if(!rectXrect(dr, dt->r))
19293e12c5d1SDavid du Colombier continue;
19307dd7cddfSDavid du Colombier edrawgetrect(insetrect(dr, -Borderwidth), 1);
19313e12c5d1SDavid du Colombier up = 1;
19323e12c5d1SDavid du Colombier }
19333e12c5d1SDavid du Colombier /* if up==1, we had a hit */
19347dd7cddfSDavid du Colombier esetcursor(0);
19353e12c5d1SDavid du Colombier if(up)
19367dd7cddfSDavid du Colombier edrawgetrect(insetrect(dr, -Borderwidth), 0);
19373e12c5d1SDavid du Colombier but = mouse.buttons;
19383e12c5d1SDavid du Colombier buttons(Up);
19393e12c5d1SDavid du Colombier if(!up || but!=4)
19407dd7cddfSDavid du Colombier goto Return;
19413e12c5d1SDavid du Colombier dt = 0;
19423e12c5d1SDavid du Colombier for(nt=thing; nt; nt=nt->next)
19433e12c5d1SDavid du Colombier if(rectXrect(dr, nt->r)){
19443e12c5d1SDavid du Colombier if(dt){
19453e12c5d1SDavid du Colombier mesg("ambiguous sweep");
19463e12c5d1SDavid du Colombier return;
19473e12c5d1SDavid du Colombier }
19483e12c5d1SDavid du Colombier dt = nt;
19493e12c5d1SDavid du Colombier }
19503e12c5d1SDavid du Colombier if(dt == 0)
19517dd7cddfSDavid du Colombier goto Return;
19523e12c5d1SDavid du Colombier p1 = realpt(dt, dr.min);
19533e12c5d1SDavid du Colombier p2 = realpt(dt, Pt(dr.min.x, dr.max.y));
19543e12c5d1SDavid du Colombier if(p1.x != p2.x)
19553e12c5d1SDavid du Colombier goto onafold;
19563e12c5d1SDavid du Colombier p2 = realpt(dt, dr.max);
19573e12c5d1SDavid du Colombier dr.min = p1;
19583e12c5d1SDavid du Colombier dr.max = p2;
19597dd7cddfSDavid du Colombier
19607dd7cddfSDavid du Colombier if(invert){
19617dd7cddfSDavid du Colombier tmp = allocimage(display, dr, dt->b->chan, 0, 255);
19627dd7cddfSDavid du Colombier if(tmp == 0){
19637dd7cddfSDavid du Colombier nomem:
19647dd7cddfSDavid du Colombier mesg("can't allocate temporary");
19657dd7cddfSDavid du Colombier goto Return;
19667dd7cddfSDavid du Colombier }
19677dd7cddfSDavid du Colombier draw(tmp, dr, st->b, nil, sr.min);
19687dd7cddfSDavid du Colombier if(!complement(tmp))
19697dd7cddfSDavid du Colombier goto nomem;
19707dd7cddfSDavid du Colombier draw(dt->b, dr, tmp, nil, dr.min);
19717dd7cddfSDavid du Colombier freeimage(tmp);
19727dd7cddfSDavid du Colombier }else
19737dd7cddfSDavid du Colombier draw(dt->b, dr, st->b, nil, sr.min);
19743e12c5d1SDavid du Colombier if(dt->parent){
19757dd7cddfSDavid du Colombier draw(dt->parent->b, dr, dt->b, nil, dr.min);
19763e12c5d1SDavid du Colombier dt = dt->parent;
19773e12c5d1SDavid du Colombier }
19787dd7cddfSDavid du Colombier drawthing(dt, 0);
19793e12c5d1SDavid du Colombier for(nt=thing; nt; nt=nt->next)
19803e12c5d1SDavid du Colombier if(nt->parent==dt && rectXrect(dr, nt->b->r)){
19817dd7cddfSDavid du Colombier draw(nt->b, dr, dt->b, nil, dr.min);
19827dd7cddfSDavid du Colombier drawthing(nt, 0);
19833e12c5d1SDavid du Colombier }
19843e12c5d1SDavid du Colombier ckinfo(dt, dr);
19853e12c5d1SDavid du Colombier dt->mod = 1;
19867dd7cddfSDavid du Colombier
19877dd7cddfSDavid du Colombier Return:
19887dd7cddfSDavid du Colombier /* clear blue box */
19897dd7cddfSDavid du Colombier drawthing(st, 0);
19903e12c5d1SDavid du Colombier }
19913e12c5d1SDavid du Colombier
19923e12c5d1SDavid du Colombier void
menu(void)19933e12c5d1SDavid du Colombier menu(void)
19943e12c5d1SDavid du Colombier {
19953e12c5d1SDavid du Colombier Thing *t;
19963e12c5d1SDavid du Colombier char *mod;
19973e12c5d1SDavid du Colombier int sel;
19983e12c5d1SDavid du Colombier char buf[256];
19993e12c5d1SDavid du Colombier
20007dd7cddfSDavid du Colombier sel = emenuhit(3, &mouse, &menu3);
20013e12c5d1SDavid du Colombier switch(sel){
20023e12c5d1SDavid du Colombier case Mopen:
20033e12c5d1SDavid du Colombier if(type(buf, "file")){
20043e12c5d1SDavid du Colombier t = tget(buf);
20053e12c5d1SDavid du Colombier if(t)
20067dd7cddfSDavid du Colombier drawthing(t, 1);
20073e12c5d1SDavid du Colombier }
20083e12c5d1SDavid du Colombier break;
20093e12c5d1SDavid du Colombier case Mwrite:
20103e12c5d1SDavid du Colombier apply(twrite);
20113e12c5d1SDavid du Colombier break;
20123e12c5d1SDavid du Colombier case Mread:
20133e12c5d1SDavid du Colombier apply(tread);
20143e12c5d1SDavid du Colombier break;
20153e12c5d1SDavid du Colombier case Mchar:
20163e12c5d1SDavid du Colombier apply(tchar);
20173e12c5d1SDavid du Colombier break;
20183e12c5d1SDavid du Colombier case Mcopy:
20193e12c5d1SDavid du Colombier copy();
20203e12c5d1SDavid du Colombier break;
20217dd7cddfSDavid du Colombier case Mpixels:
20227dd7cddfSDavid du Colombier tpixels();
20237dd7cddfSDavid du Colombier break;
20243e12c5d1SDavid du Colombier case Mclose:
20253e12c5d1SDavid du Colombier apply(tclose);
20263e12c5d1SDavid du Colombier break;
20273e12c5d1SDavid du Colombier case Mexit:
20283e12c5d1SDavid du Colombier mod = 0;
20293e12c5d1SDavid du Colombier for(t=thing; t; t=t->next)
20303e12c5d1SDavid du Colombier if(t->mod){
20313e12c5d1SDavid du Colombier mod = t->name;
20323e12c5d1SDavid du Colombier t->mod = 0;
20333e12c5d1SDavid du Colombier }
20343e12c5d1SDavid du Colombier if(mod){
20353e12c5d1SDavid du Colombier mesg("%s modified", mod);
20363e12c5d1SDavid du Colombier break;
20373e12c5d1SDavid du Colombier }
20387dd7cddfSDavid du Colombier esetcursor(&skull);
20393e12c5d1SDavid du Colombier buttons(Down);
20403e12c5d1SDavid du Colombier if(mouse.buttons == 4){
20413e12c5d1SDavid du Colombier buttons(Up);
20423e12c5d1SDavid du Colombier exits(0);
20433e12c5d1SDavid du Colombier }
20443e12c5d1SDavid du Colombier buttons(Up);
20457dd7cddfSDavid du Colombier esetcursor(0);
20463e12c5d1SDavid du Colombier break;
20473e12c5d1SDavid du Colombier }
20483e12c5d1SDavid du Colombier }
2049