|
|
1.1 root 1: #define bool int
2: #define true 1
3: #define false 0
4:
5: #define NOHIT -1
6:
7: #define I_NULL -1
8: #define I_OR 0
9: #define I_STORE 1
10: #define I_CLR 2
11: #define I_XOR 3
12: #define I_AND 4
13:
14: #include "jerq.h"
15: #include <stdio.h>
16:
17: #define SPACING 24
18:
19: #define sgn(x) ((x)<0 ? -1 : (x)==0 ? 0 : 1)
20:
21: int XSIZE = 50, YSIZE = 50;
22:
23: int horsize(r)
24: Rectangle r;
25: {
26: return(r.corner.x - r.origin.x);
27: }
28:
29: int versize(r)
30: Rectangle r;
31: {
32: return(r.corner.y - r.origin.y);
33: }
34:
35: extern Texture *(imenu[]);
36:
37: int lasthitx = 0, lasthity = 0;
38: #define SRC_ID 0
39: #define SRC_CLR 1
40: char *blitsrctext[] =
41: {"src := src","src := 0",NULL};
42:
43: #define DST_STORE 0
44: #define DST_OR 1
45: #define DST_XOR 2
46: #define DST_AND 3
47: #define DST_CLR 4
48:
49: char *blitdsttext[] =
50: {"dst := src","dst := src or dst","dst := src xor dst","dst := src and dst","dst := 0",NULL};
51:
52: Menu blitsrcmenu = {blitsrctext};
53: Menu blitdstmenu = {blitdsttext};
54:
55: short Cmove_bits[] = {
56: 0x0000, 0x0000, 0x00C0, 0x00E0,
57: 0x00F0, 0x7FF8, 0x7FDC, 0x600E,
58: 0x6007, 0x600E, 0x7FDC, 0x7FF8,
59: 0x00F0, 0x00E0, 0x00C0, 0x0000,
60: };
61: Texture Cmove;
62:
63: short Ccopy_bits[] = {
64: 0x0000, 0x7FE0, 0x4020, 0x4020,
65: 0x473F, 0x4FA1, 0x4DA1, 0x4C39,
66: 0x4FBD, 0x472D, 0x4021, 0x403D,
67: 0x7FF9, 0x0201, 0x0201, 0x03FF,
68: };
69: Texture Ccopy;
70:
71: short Cerase_bits[] = {
72: 0x03FE, 0x0556, 0x0556, 0x0AAE,
73: 0x0AAE, 0x1FFC, 0x101C, 0x2028,
74: 0x2028, 0x4050, 0x4050, 0xFFA0,
75: 0x80A0, 0x80C0, 0x80C0, 0xFF80,
76: };
77: Texture Cerase;
78:
79: short Cinvert_bits[] = {
80: 0x0000, 0x0000, 0x07C0, 0x07C0,
81: 0x07C0, 0x07C0, 0x07C0, 0x783C,
82: 0x783C, 0x783C, 0x07C0, 0x07C0,
83: 0x07C0, 0x07C0, 0x07C0, 0x0000,
84: };
85: Texture Cinvert;
86:
87: short Cblit_bits[] = {
88: 0x0000, 0x7FE0, 0x4020, 0x4020,
89: 0x403F, 0x4021, 0x4021, 0x4021,
90: 0x4021, 0x4021, 0x4021, 0x4021,
91: 0x7FE1, 0x0201, 0x0201, 0x03FF,
92: };
93: Texture Cblit;
94:
95: short Creflx_bits[] = {
96: 0x0000, 0x0000, 0x7FFE, 0x8001,
97: 0x8011, 0xC033, 0xBC5D, 0x8781,
98: 0x8501, 0x8501, 0x4482, 0x3C5C,
99: 0x0030, 0x0010, 0x0000, 0x0000,
100: };
101: Texture Creflx;
102:
103: short Crefly_bits[] = {
104: 0x03F8, 0x0424, 0x0844, 0x0844,
105: 0x0844, 0x0FC4, 0x0084, 0x0384,
106: 0x0484, 0x0844, 0x1024, 0x3874,
107: 0x0844, 0x0844, 0x0424, 0x03F8,
108: };
109: Texture Crefly;
110:
111: short Crotplus_bits[] = {
112: 0x0000, 0x0000, 0x3FE0, 0x2010,
113: 0x2008, 0x2008, 0x2008, 0x3F08,
114: 0x0108, 0x0108, 0x070E, 0x0204,
115: 0x0108, 0x0090, 0x0060, 0x0000,
116: };
117: Texture Crotplus;
118:
119: short Crotminus_bits[] = {
120: 0x0000, 0x0400, 0x0C00, 0x17F0,
121: 0x2008, 0x4004, 0x4004, 0x2004,
122: 0x1784, 0x0C84, 0x0484, 0x0084,
123: 0x0084, 0x00FC, 0x0000, 0x0000,
124: };
125: Texture Crotminus;
126:
127: short Cshearx_bits[] = {
128: 0x0000, 0x0000, 0x0000, 0x0000,
129: 0x0000, 0x03FF, 0x0000, 0x0FFC,
130: 0x0000, 0x3FF0, 0x0000, 0xFFC0,
131: 0x0000, 0x0000, 0x0000, 0x0000,
132: };
133: Texture Cshearx;
134:
135: short Csheary_bits[] = {
136: 0x0800, 0x0800, 0x0A00, 0x0A00,
137: 0x0A80, 0x0A80, 0x0AA0, 0x0AA0,
138: 0x0AA0, 0x0AA0, 0x02A0, 0x02A0,
139: 0x00A0, 0x00A0, 0x0020, 0x0020,
140: };
141: Texture Csheary;
142:
143: short Cstretch_bits[] = {
144: 0x0000, 0x7CAA, 0x7CAA, 0x7CAA,
145: 0x7CAA, 0x7CAA, 0x0000, 0x0000,
146: 0x7CAA, 0x0000, 0x7CAA, 0x0000,
147: 0x7CAA, 0x0000, 0x7CAA, 0x0000,
148: };
149: Texture Cstretch;
150:
151: short Ctexture_bits[] = {
152: 0x4000, 0x7000, 0xE000, 0x2000,
153: 0x0444, 0x0777, 0x0EEE, 0x0222,
154: 0x0444, 0x0777, 0x0EEE, 0x0222,
155: 0x0444, 0x0777, 0x0EEE, 0x0222,
156: };
157: Texture Ctexture;
158:
159: short Cgrid_bits[] = {
160: 0x4040, 0xFFFF, 0x4040, 0x4444,
161: 0x4040, 0x5555, 0x4040, 0x4444,
162: 0x4040, 0xFFFF, 0x4040, 0x4444,
163: 0x4040, 0x5555, 0x4040, 0x4444,
164: };
165: Texture Cgrid;
166:
167: short Ccursor_bits[] = {
168: 0x0000, 0x0000, 0x03E0, 0x17F0,
169: 0x3FF0, 0x5FFE, 0xFFF1, 0x0421,
170: 0x0002, 0x00FC, 0x0100, 0x0080,
171: 0x0040, 0x0080, 0x0000, 0x0000,
172: };
173: Texture Ccursor;
174:
175: short Cread_bits[] = {
176: 0x0000, 0x0FFE, 0x1FFA, 0x1811,
177: 0x0021, 0x8021, 0xC061, 0xC1F1,
178: 0x622A, 0x3414, 0x1810, 0x0810,
179: 0x0420, 0x03C0, 0x0000, 0x0000,
180: };
181: Texture Cread;
182:
183: short Cwrite_bits[] = {
184: 0xF000, 0xFC00, 0x6B00, 0x3580,
185: 0x12C0, 0x1960, 0x0CA0, 0x06B0,
186: 0x0250, 0x0358, 0x01A8, 0x00D8,
187: 0x0074, 0x101C, 0xBB06, 0xEEFB,
188: };
189: Texture Cwrite;
190:
191: short Cresize_bits[] = {
192: 0xFF54, 0x8100, 0x8104, 0x8100,
193: 0x8104, 0x8100, 0x8104, 0xFF00,
194: 0x0004, 0x8000, 0x0014, 0x8038,
195: 0x001D, 0xAAAF, 0x0007, 0x000F,
196: };
197: Texture Cresize;
198:
199: short Chelp_bits[] = {
200: 0x0000, 0x0000, 0x0000, 0x0000,
201: 0xE0E0, 0x6060, 0x7F7E, 0x7DFF,
202: 0x6FFB, 0x6C7B, 0x6FFE, 0xFFF8,
203: 0x003C, 0x0000, 0x0000, 0x0000,
204: };
205: Texture Chelp;
206:
207: short Cundo_bits[] = {
208: 0x001C, 0x0022, 0x0041, 0x0081,
209: 0x0101, 0x0282, 0x0544, 0x0AA8,
210: 0x1550, 0x22A0, 0x4140, 0x8080,
211: 0x8100, 0x8200, 0x4400, 0x3800,
212: };
213: Texture Cundo;
214:
215: short white_bits[] = {
216: 0x0000, 0x0000, 0x0000, 0x0000,
217: 0x0000, 0x0000, 0x0000, 0x0000,
218: 0x0000, 0x0000, 0x0000, 0x0000,
219: 0x0000, 0x0000, 0x0000, 0x0000,
220: };
221: Cursor white;
222: Texture whiteT;
223:
224: short menucursor_bits[] = {
225: 0xFFC0, 0x8040, 0x8040, 0x8040,
226: 0xFFC0, 0xFFC0, 0xFE00, 0xFEF0,
227: 0x80E0, 0x80F0, 0x80B8, 0xFE1C,
228: 0x800E, 0x8047, 0x8042, 0xFFC0,
229: };
230: Cursor menucursor;
231: Texture menucursorT;
232:
233: short sweepcursor_bits[] = {
234: 0x43FF, 0xE001, 0x7001, 0x3801,
235: 0x1D01, 0x0F01, 0x8701, 0x8F01,
236: 0x8001, 0x8001, 0x8001, 0x8001,
237: 0x8001, 0x8001, 0x8001, 0xFFFF,
238: };
239: Cursor sweepcursor;
240: Texture sweepcursorT;
241:
242: short sweeportrack_bits[] = {
243: 0x43FF, 0xE001, 0x70FD, 0x3805,
244: 0x1D05, 0x0F05, 0x8705, 0x8F05,
245: 0xA005, 0xA005, 0xA005, 0xA005,
246: 0xA005, 0xBFFD, 0x8001, 0xFFFF,
247: };
248: Cursor sweeportrack;
249: Texture sweeportrackT;
250:
251: short clock_bits[] = {
252: 0x03C0, 0x3420, 0x37E0, 0x13C0,
253: 0x17F0, 0x1828, 0x2054, 0x20D4,
254: 0x418A, 0x430A, 0x430A, 0x418A,
255: 0x2094, 0x201C, 0x787E, 0x67F6,
256: };
257: Cursor clock;
258: Texture clockT;
259:
260: short deadmouse_bits[] = {
261: 0x0000, 0x0000, 0x0008, 0x0004,
262: 0x0082, 0x0441, 0xFFE1, 0x5FF1,
263: 0x3FFE, 0x17F0, 0x03E0, 0x0000,
264: 0x0000, 0x0000, 0x0000, 0x0000,
265: };
266: Cursor deadmouse;
267: Texture deadmouseT;
268:
269: initicons()
270: {
271: Cmove = ToTexture(Cmove_bits);
272: Ccopy = ToTexture(Ccopy_bits);
273: Cerase = ToTexture(Cerase_bits);
274: Cinvert = ToTexture(Cinvert_bits);
275: Cblit = ToTexture(Cblit_bits);
276: Creflx = ToTexture(Creflx_bits);
277: Crefly = ToTexture(Crefly_bits);
278: Crotplus = ToTexture(Crotplus_bits);
279: Crotminus = ToTexture(Crotminus_bits);
280: Cshearx = ToTexture(Cshearx_bits);
281: Csheary = ToTexture(Csheary_bits);
282: Cstretch = ToTexture(Cstretch_bits);
283: Ctexture = ToTexture(Ctexture_bits);
284: Cgrid = ToTexture(Cgrid_bits);
285: Ccursor = ToTexture(Ccursor_bits);
286: Cread = ToTexture(Cread_bits);
287: Cwrite = ToTexture(Cwrite_bits);
288: Cresize = ToTexture(Cresize_bits);
289: Chelp = ToTexture(Chelp_bits);
290: Cundo = ToTexture(Cundo_bits);
291: whiteT = ToTexture(white_bits);
292: white = ToCursor(white_bits, white_bits, 7, 7);
293: menucursorT = ToTexture(menucursor_bits);
294: menucursor = ToCursor(menucursor_bits, menucursor_bits, 7, 7);
295: sweepcursorT = ToTexture(sweepcursor_bits);
296: sweepcursor = ToCursor(sweepcursor_bits, sweepcursor_bits, 7, 7);
297: sweeportrackT = ToTexture(sweeportrack_bits);
298: sweeportrack = ToCursor(sweeportrack_bits, sweeportrack_bits, 7, 7);
299: clockT = ToTexture(clock_bits);
300: clock = ToCursor(clock_bits, clock_bits, 7, 7);
301: deadmouseT = ToTexture(deadmouse_bits);
302: deadmouse = ToCursor(deadmouse_bits, deadmouse_bits, 7, 7);
303: }
304:
305: #define MOVE 0
306: #define COPY 1
307: #define INVERT 2
308: #define ERASE 3
309:
310: #define REFLECTX 5
311: #define REFLECTY 6
312: #define ROTATEPLUS 7
313: #define ROTATEMINUS 8
314:
315: #define SHEARX 10
316: #define SHEARY 11
317: #define STRETCH 12
318: #define TEXTURE 13
319:
320: #define READ 15
321: #define GRID 16
322: #define RESIZE 17
323: #define WRITE 18
324:
325: #define BLIT 20
326: #define PICK 21
327: #define HELP 22
328: #define UNDO 23
329:
330: Texture *(imenu[]) =
331: {&Cmove,&Ccopy,&Cinvert,&Cerase,0,
332: &Creflx,&Crefly,&Crotplus,&Crotminus,0,
333: &Cshearx,&Csheary,&Cstretch,&Ctexture,0,
334: &Cread,&Cgrid,&Cresize,&Cwrite,0,
335: &Cblit,&Ccursor,&Chelp,&Cundo,0,
336: 0,0,0,0
337: };
338:
339:
340: char exa[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
341: char buf[100],FNAME[50];
342: Point nullpoint, point16x16;
343: Rectangle icon, ICON, sweep, outl, nullrect, rect16x16;
344: int Xsize,Ysize;
345: int Xblocks,Yblocks;
346: int modx,divx,mody,divy;
347:
348: flipring(p)
349: Point p;
350: {
351: outline(&display,raddp(Rect(1,1,SPACING-2,SPACING-2),p));
352: outline(&display,raddp(Rect(2,2,SPACING-3,SPACING-3),p));
353: }
354:
355: drawimenu(xicons,yicons,r)
356: Rectangle r;
357: {
358: Bitmap *textr;
359: int i,j;
360: rectf(&display,r,F_CLR);
361: outline(&display,Rpt(r.origin,sub(r.corner,Pt(1,1))));
362: textr = balloc(Rect(0,0,16,16));
363: if (textr == ((Bitmap *) 0)) return(0);
364: for (j=0; j<yicons; j++) {
365: for (i=0; i<xicons; i++) {
366: texture(textr,textr->rect,imenu[j*(xicons+1)+i],F_STORE);
367: bitblt(textr,textr->rect,
368: &display,
369: add(r.origin,Pt(i*SPACING+(SPACING-16)/2,j*SPACING+(SPACING-16)/2)),
370: F_OR);
371: }
372: }
373: bfree(textr);
374: }
375:
376: Point imenuhit()
377: {
378: Bitmap *offscreen;
379: Point ms,valley,diff,result,menudrift;
380: Rectangle menurect;
381: Cursor *oldcursor;
382: int i,j,hitx,hity, ohitx,ohity;
383: int xicons,yicons;
384: oldcursor = cursswitch(&white);
385: xicons = 0;
386: for (j=0; imenu[xicons*j]; j++) {
387: for (i=0; imenu[xicons*j+i]; i++);
388: i++;
389: xicons = i;
390: }
391: xicons -= 1;
392: yicons = j;
393: /* while (!button3()) wait(MOUSE); */
394: ms = mouse.xy;
395: menurect = raddp(Rect(0,0,SPACING*xicons,SPACING*yicons),ms);
396: menurect = rsubp(menurect,Pt(SPACING*lasthitx,SPACING*lasthity));
397: menudrift.x = min(menurect.corner.x,Drect.corner.x);
398: menudrift.y = min(menurect.corner.y,Drect.corner.y);
399: menudrift = sub(menudrift,menurect.corner);
400: menurect = raddp(menurect,menudrift); cursset(ms=add(ms,menudrift));
401: menudrift.x = max(menurect.origin.x,Drect.origin.x);
402: menudrift.y = max(menurect.origin.y,Drect.origin.y);
403: menudrift = sub(menudrift,menurect.origin);
404: menurect = raddp(menurect,menudrift); cursset(add(ms,menudrift));
405: offscreen = balloc(menurect);
406: if (offscreen != ((Bitmap *) 0)) {
407: bitblt(&display,menurect,offscreen,offscreen->rect.origin,F_STORE);
408: }
409: drawimenu(xicons,yicons,menurect);
410: hitx = hity = -1;
411: while (button3()) {
412: jnap(1);
413: ms = mouse.xy;
414: ohitx = hitx; ohity = hity;
415: if (ptinrect(ms,menurect)) {
416: lasthitx = hitx = (ms.x-menurect.origin.x)/SPACING;
417: lasthity = hity = (ms.y-menurect.origin.y)/SPACING;
418: } else hitx = hity = -1;
419: if (hitx == -1) {
420: if (ohitx != -1) {
421: flipring(valley);
422: cursswitch(oldcursor);
423: }
424: continue;
425: }
426: if (ohitx == -1) {
427: cursswitch(&white);
428: valley = add(menurect.origin,Pt(SPACING*hitx,SPACING*hity));
429: flipring(valley);
430: } else if (ohitx != hitx || ohity != hity){
431: flipring(valley);
432: valley = add(menurect.origin,Pt(SPACING*hitx,SPACING*hity));
433: flipring(valley);
434: }
435: }
436: if (offscreen != ((Bitmap *) 0)) {
437: bitblt(offscreen,offscreen->rect,&display,menurect.origin,F_STORE);
438: bfree(offscreen);
439: }
440: result.x = hitx;
441: result.y = hity;
442: cursswitch(oldcursor);
443: return(result);
444: }
445:
446: Rectangle canonrect(p1, p2)
447: Point p1, p2;
448: {
449: Rectangle r;
450: r.origin.x = min(p1.x, p2.x);
451: r.origin.y = min(p1.y, p2.y);
452: r.corner.x = max(p1.x, p2.x);
453: r.corner.y = max(p1.y, p2.y);
454: return(r);
455: }
456:
457: int pttopt(p,q)
458: /* manhattan topology distance between two points */
459: Point p,q;
460: {
461: return(abs(p.x-q.x)+abs(p.y-q.y));
462: }
463:
464: Point nearestcorner(r,p)
465: Rectangle r;
466: Point p;
467: {
468: int mindist,dist;
469: Point minq,q;
470: q = r.origin;
471: mindist = pttopt(p,q); minq = q;
472: q.x = r.origin.x; q.y = r.corner.y;
473: if ((dist = pttopt(p,q))<mindist) {mindist = dist; minq = q;}
474: q = r.corner;
475: if ((dist = pttopt(p,q))<mindist) {mindist = dist; minq = q;}
476: q.x = r.corner.x; q.y = r.origin.y;
477: if ((dist = pttopt(p,q))<mindist) {mindist = dist; minq = q;}
478: return(minq);
479: }
480:
481: outline(b,r)
482: Bitmap *b;
483: Rectangle r;
484: {
485: rectf(b,Rect(r.origin.x,r.origin.y,r.origin.x+1,r.corner.y),F_XOR);
486: rectf(b,Rect(r.origin.x,r.corner.y,r.corner.x,r.corner.y+1),F_XOR);
487: rectf(b,Rect(r.corner.x,r.origin.y+1,r.corner.x+1,r.corner.y+1),F_XOR);
488: rectf(b,Rect(r.origin.x+1,r.origin.y,r.corner.x+1,r.origin.y+1),F_XOR);
489: }
490:
491: Border(r)
492: Rectangle r;
493: {
494: outline(&display,inset(r,1));
495: outline(&display,inset(r,-1));
496: }
497:
498: Rectangle sweeprect()
499: {
500: Rectangle r;
501: Point p1, p2;
502: Cursor *oldcursor;
503: oldcursor = cursswitch(&sweepcursor);
504: while (!button123()) wait(MOUSE);
505: p1=mouse.xy;
506: p2=p1;
507: r=canonrect(p1, p2);
508: outline(&display,r);
509: for(; button3(); nap(2)){
510: outline(&display,r);
511: p2=mouse.xy;
512: r=canonrect(p1, p2);
513: outline(&display,r);
514: }
515: outline(&display,r);
516: cursswitch(oldcursor);
517: return r;
518: }
519:
520: bool getr(cliprect,sweep)
521: Rectangle cliprect;
522: Rectangle *sweep;
523: {
524: int j;
525: *sweep = sweeprect();
526: return(rectclip(sweep,cliprect));
527: }
528:
529: Point IconPoint(p)
530: /* convert screen coord to icon coord */
531: Point p;
532: {
533: p.x = (p.x+Xsize-modx)/Xsize - divx - 1;
534: p.y = (p.y+Ysize-mody)/Ysize - divy - 1;
535: return(p);
536: }
537:
538: short IconCoordX(x)
539: short x;
540: {
541: return((x+Xsize-modx)/Xsize - divx - 1);
542: }
543:
544: short IconCoordY(y)
545: short y;
546: {
547: return((y+Ysize-mody)/Ysize - divy - 1);
548: }
549:
550: Point ScreenPoint(p)
551: /* convert icon coord to screen coord */
552: Point p;
553: {
554: p.x = p.x*Xsize + ICON.origin.x;
555: p.y = p.y*Ysize + ICON.origin.y;
556: return(p);
557: }
558:
559: short ScreenCoordX(x)
560: short x;
561: {
562: return(x*Xsize + ICON.origin.x);
563: }
564:
565: short ScreenCoordY(y)
566: short y;
567: {
568: return(y*Ysize + ICON.origin.y);
569: }
570:
571:
572: Rectangle IconRect(r)
573: /* convert a screen rectangle to the biggest totally contained icon rectangle */
574: Rectangle r;
575: {
576: r.origin = IconPoint(add(r.origin,Pt(Xsize-1,Ysize-1)));
577: r.corner = IconPoint(r.corner);
578: if (horsize(r)<0) r.origin.x = r.corner.x;
579: if (versize(r)<0) r.origin.y = r.corner.y;
580: return(r);
581: }
582:
583: Rectangle TrackBorder(r,buttonup)
584: /* tracks a rectangle "r" (in icon coords) and returns it as it is
585: at the end of tracking, clipped to the icon */
586: Rectangle r;
587: bool buttonup;
588: {
589: Point newP, oldP;
590: Cursor *oldcursor;
591: oldcursor = cursswitch(&white);
592: outl.origin = nullpoint;
593: outl.corner.x = horsize(r)*Xsize;
594: outl.corner.y = versize(r)*Ysize;
595: newP = ScreenPoint(r.origin);
596: while (buttonup?(button123()):(!button123()))
597: wait(MOUSE);
598: cursset(newP);
599: oldP = newP;
600: Border(raddp(outl,newP));
601: while (buttonup?(!button123()):(button123())) {
602: wait(MOUSE);
603: newP = ScreenPoint(IconPoint(mouse.xy));
604: if (!eqpt(newP,oldP)) {
605: Border(raddp(outl,oldP));
606: Border(raddp(outl,newP));
607: oldP = newP;
608: }
609: }
610: Border(raddp(outl,newP));
611: cursswitch(oldcursor);
612: return(IconRect(raddp(outl,newP)));
613: }
614:
615: bool SweepIconRect(r)
616: Rectangle *r;
617: {
618: Point p;
619: if (!getr(ICON,&sweep)) return(false);
620: *r = IconRect(sweep);
621: if ((horsize(*r)==0) || (versize(*r)==0)) return(false);
622: return(true);
623: }
624:
625: int GetIconRect(r)
626: /* returns: 0 if no rectangle is provided;
627: 2 if button2 is used (tracking a 16x16 rectangle);
628: 3 if button3 is used (sweeping a rectangle);
629: if a rectangle is provided, r returns it in icon coordinates */
630: Rectangle *r;
631: {
632: int result;
633: Cursor *oldcursor;
634: oldcursor = cursswitch(&sweeportrack);
635: while (!button123()) wait(MOUSE);
636: if (button3()) {
637: if (SweepIconRect(r)) result = 3;
638: else result = 0;
639: } else if (button2()) {
640: *r = TrackBorder(raddp(rect16x16,add(IconPoint(mouse.xy),Pt(1,1))),false);
641: result = 2;
642: } else {while(button1())jnap(1); result = 0;}
643: cursswitch(oldcursor);
644: return(result);
645: }
646:
647: bool GetIconPoint(p)
648: Point *p;
649: {
650: Rectangle r;
651: r = TrackBorder(raddp(Rect(0,0,1,1),IconPoint(mouse.xy)),true);
652: while (button123())jnap(1);
653: *p = r.origin;
654: return((horsize(r) == 1) && (versize(r) == 1));
655: }
656:
657: Bitmap *bittester;
658:
659: bool bitmapbit(b,p)
660: Bitmap *b;
661: Point p;
662: {
663: if (!(ptinrect(p,b->rect))) return(false);
664: return (getpoint(b,p));
665: }
666:
667: char getnibble(b,p)
668: Bitmap *b;
669: Point p;
670: {
671: int nibble;
672: nibble = 8*bitmapbit(b,p) + 4*bitmapbit(b,Pt(p.x+1,p.y)) +
673: 2*bitmapbit(b,Pt(p.x+2,p.y)) + bitmapbit(b,Pt(p.x+3,p.y));
674: return(exa[nibble]);
675: }
676:
677: putnibble(ch,b,clipr,p)
678: int ch;
679: Bitmap *b;
680: Rectangle clipr;
681: Point p;
682: {
683: int nibble, mask;
684: if (ch<'0') return;
685: if (ch<='9') nibble = ch - '0';
686: else if (ch<='F') nibble = 10 + (ch - 'A');
687: else nibble = 10 + (ch - 'a');
688: if (nibble != 0)
689: for (mask = 0x10; mask >>= 1; p.x++)
690: if ((mask & nibble) && ptinrect(p, clipr))
691: point(b, p, F_OR);
692: }
693:
694: Bitmap *Source, *Undo;
695:
696: FlipOntoScreen(p)
697: Point p;
698: {
699: Rectangle ICONp;
700: if (!ptinrect(p,Source->rect)) return(0);
701: point(&display,add(icon.origin,p),F_XOR);
702: ICONp.origin = add(Pt(p.x*Xsize,p.y*Ysize),ICON.origin);
703: ICONp.corner = add(Pt((p.x+1)*Xsize,(p.y+1)*Ysize),ICON.origin);
704: if ((ICONp.origin.x > icon.corner.x) ||
705: (ICONp.origin.y > icon.corner.y))
706: rectf(&display,ICONp,F_XOR);
707: }
708:
709: bool geticonpoint(p)
710: Point p;
711: {
712: if (!ptinrect(p,Source->rect)) return(false);
713: return(bitmapbit(Source,p));
714: }
715:
716: flipiconpoint(p)
717: Point p;
718: {
719: point(Source,p,F_XOR);
720: FlipOntoScreen(p);
721: }
722:
723: IconOp(bit,p,op)
724: bool bit;
725: Point p;
726: int op;
727: {
728: if ((p.x>=0) && (p.x<Xblocks) && (p.y>=0) && (p.y<Yblocks))
729: switch (op) {
730: case I_STORE:
731: if (geticonpoint(p) != bit) flipiconpoint(p);
732: break;
733: case I_CLR:
734: if (geticonpoint(p)) flipiconpoint(p);
735: break;
736: case I_OR:
737: if (bit && !geticonpoint(p)) flipiconpoint(p);
738: break;
739: case I_XOR:
740: if (bit) flipiconpoint(p);
741: break;
742: case I_AND:
743: if (!bit && geticonpoint(p)) flipiconpoint(p);
744: break;
745: }
746: }
747:
748: IconBitBlit(from,to,clip,srccode,dstcode)
749: Rectangle from; /* icon coords */
750: Point to; /* icon coords */
751: Rectangle clip; /* icon coords */
752: int srccode,dstcode;
753: {
754: Rectangle region;
755: int dx,dy,di,dj,i,j;
756: int left,up;
757: bool bit;
758: dx = to.x - from.origin.x;
759: dy = to.y - from.origin.y;
760: left = dx<0;
761: up = dy<0;
762: di = (left?1:-1);
763: dj = (up?1:-1);
764: region = from;
765: if (!rectclip(®ion,raddp(clip,sub(from.origin,to))))
766: region = nullrect;
767: for (j=(up?from.origin.y:from.corner.y-1);
768: up?(j<from.corner.y):(j>=from.origin.y); j+=dj) {
769: wait(CPU);
770: for (i=(left?from.origin.x:from.corner.x-1);
771: left?(i<from.corner.x):(i>=from.origin.x); i+=di) {
772: bit = geticonpoint(Pt(i,j));
773: IconOp(false,Pt(i,j),srccode);
774: if (ptinrect(Pt(i,j),region)) IconOp(bit,Pt(i+dx,j+dy),dstcode);
775: }
776: }
777: }
778:
779: horshear(b,r,dx,top)
780: Bitmap *b;
781: Rectangle r;
782: int dx;
783: bool top;
784: {
785: int i,j,hsize,vsize,shift;
786: bool bit,dir;
787: hsize = horsize(r);
788: vsize = versize(r);
789: dir = (dx>0);
790: for (j=0; j<vsize; j++) {
791: wait(CPU);
792: shift = top ? vsize-j-1 : j;
793: bitblt(b,Rect(r.origin.x,r.origin.y+j,r.corner.x,r.origin.y+j+1),
794: b,Pt(r.origin.x+muldiv(shift,dx,vsize),r.origin.y+j),
795: F_STORE);
796: }
797: }
798:
799: vershear(b,r,dy,lft)
800: Bitmap *b;
801: Rectangle r;
802: int dy;
803: bool lft;
804: {
805: int i,j,hsize,vsize,shift;
806: bool bit,dir;
807: hsize = horsize(r);
808: vsize = versize(r);
809: dir = (dy>0);
810: for (i=0; i<hsize; i++) {
811: wait(CPU);
812: shift = lft ? hsize-i-1 : i;
813: bitblt(b,Rect(r.origin.x+i,r.origin.y,r.origin.x+i+1,r.corner.y),
814: b,Pt(r.origin.x+i,r.origin.y+muldiv(shift,dy,hsize)),
815: F_STORE);
816: }
817: }
818:
819: OpRotPlus()
820: {
821: int vsize,hsize,size;
822: Rectangle r,rbuf;
823: Bitmap *buffer;
824: if (GetIconRect(&r)==0) return(0);
825: hsize = horsize(r); vsize = versize(r); size = hsize+vsize;
826: buffer = balloc(Rect(0,0,size,size));
827: if (buffer == ((Bitmap *) 0)) return(0);
828: rectf(buffer,buffer->rect,F_CLR);
829: rbuf = rsubp(r,r.origin);
830: SaveForUndo();
831: cursswitch(&clock);
832: bitblt(&display,raddp(r,icon.origin),buffer,rbuf.origin,F_XOR);
833: horshear(buffer,rbuf,vsize,true);
834: vershear(buffer,
835: Rect(rbuf.origin.x,rbuf.origin.y,rbuf.corner.x+vsize,rbuf.corner.y),
836: size,false);
837: horshear(buffer,
838: Rect(rbuf.origin.x,rbuf.corner.y-1,
839: rbuf.corner.x+vsize,rbuf.corner.y+hsize-1),
840: -hsize,false);
841: Erase(r);
842: OrOntoPicture(buffer,
843: Rect(rbuf.origin.x,rbuf.corner.y-1,
844: rbuf.origin.x+vsize,rbuf.corner.y+hsize-1),
845: add(r.origin,sub(Pt(hsize/2,vsize/2),Pt(vsize/2,hsize/2))));
846: cursswitch((Cursor *) 0);
847: bfree(buffer);
848: }
849:
850: OpRotMinus()
851: {
852: int vsize,hsize,size;
853: Rectangle r,rbuf;
854: Bitmap *buffer;
855: if (GetIconRect(&r)==0) return(0);
856: hsize = horsize(r); vsize = versize(r); size = hsize+vsize;
857: buffer = balloc(Rect(0,0,size,size));
858: if (buffer == ((Bitmap *) 0)) return(0);
859: rectf(buffer,buffer->rect,F_CLR);
860: rbuf = raddp(r,sub(Pt(vsize,0),r.origin));
861: SaveForUndo();
862: cursswitch(&clock);
863: bitblt(&display,raddp(r,icon.origin),buffer,rbuf.origin,F_XOR);
864: horshear(buffer,rbuf,-vsize,true);
865: vershear(buffer,
866: Rect(rbuf.origin.x-vsize,rbuf.origin.y,rbuf.corner.x,rbuf.corner.y),
867: size,true);
868: horshear(buffer,
869: Rect(rbuf.origin.x-vsize,rbuf.corner.y-1,
870: rbuf.corner.x,rbuf.corner.y+hsize-1),
871: hsize,false);
872: Erase(r);
873: OrOntoPicture(buffer,
874: Rect(rbuf.corner.x-vsize,rbuf.corner.y-1,
875: rbuf.corner.x,rbuf.corner.y+hsize-1),
876: add(r.origin,sub(Pt(hsize/2,vsize/2),Pt(vsize/2,hsize/2))));
877: cursswitch((Cursor *) 0);
878: bfree(buffer);
879: }
880:
881: OpReflY()
882: {
883: Rectangle r;
884: int i,j;
885: bool bit1,bit2;
886: if (GetIconRect(&r)==0) return(0);
887: SaveForUndo();
888: cursswitch(&clock);
889: for (i=r.origin.x; i<r.corner.x; i+=1) {
890: wait(CPU);
891: for (j=0; j<(versize(r)/2); j+=1) {
892: bit1 = geticonpoint(Pt(i,r.origin.y+j));
893: bit2 = geticonpoint(Pt(i,r.corner.y-1-j));
894: IconOp(bit1,Pt(i,r.corner.y-1-j),I_STORE);
895: IconOp(bit2,Pt(i,r.origin.y+j),I_STORE);
896: }
897: }
898: cursswitch((Cursor *) 0);
899: }
900:
901: OpReflX()
902: {
903: Rectangle r;
904: int i,j;
905: bool bit1,bit2;
906: if (GetIconRect(&r)==0) return(0);
907: SaveForUndo();
908: cursswitch(&clock);
909: for (i=0; i<(horsize(r)/2); i+=1) {
910: wait(CPU);
911: for (j=r.origin.y; j<r.corner.y; j+=1) {
912: bit1 = geticonpoint(Pt(r.origin.x+i,j));
913: bit2 = geticonpoint(Pt(r.corner.x-1-i,j));
914: IconOp(bit1,Pt(r.corner.x-1-i,j),I_STORE);
915: IconOp(bit2,Pt(r.origin.x+i,j),I_STORE);
916: }
917: }
918: cursswitch((Cursor *) 0);
919: }
920:
921: OpBlit(srcop,dstop)
922: int srcop,dstop;
923: {
924: Rectangle r, r1;
925: Point p;
926: if (GetIconRect(&r)==0) return(0);
927: r1 = TrackBorder(r,true);
928: p = r1.origin;
929: if (button23()) {
930: while (button23())jnap(1);
931: SaveForUndo();
932: cursswitch(&clock);
933: IconBitBlit(r,p,Rect(0,0,Xblocks,Yblocks),srcop,dstop);
934: cursswitch((Cursor *) 0);
935: } else while (button1())jnap(1);
936: }
937:
938:
939: OpGeneralBlit()
940: {
941: int srcop, dstop;
942: cursswitch(&menucursor);
943: while (!button123()) wait(MOUSE);
944: cursswitch((Cursor *) 0);
945: if (!button3()) return(0);
946: switch (menuhit(&blitsrcmenu,3)) {
947: case NOHIT:
948: srcop = I_NULL;
949: break;
950: case SRC_ID:
951: srcop = I_OR;
952: break;
953: case SRC_CLR:
954: srcop = I_CLR;
955: break;
956: }
957: if (srcop==I_NULL) {cursswitch((Cursor *) 0); return(0);}
958: cursswitch(&menucursor);
959: while (!button123()) wait(MOUSE);
960: cursswitch((Cursor *) 0);
961: if (!button3()) return(0);
962: switch (menuhit(&blitdstmenu,3)) {
963: case NOHIT:
964: dstop = I_NULL;
965: break;
966: case DST_STORE:
967: dstop = I_STORE;
968: break;
969: case DST_OR:
970: dstop = I_OR;
971: break;
972: case DST_XOR:
973: dstop = I_XOR;
974: break;
975: case DST_AND:
976: dstop = I_AND;
977: break;
978: case DST_CLR:
979: dstop = I_CLR;
980: break;
981: }
982: if (dstop==I_NULL) {cursswitch((Cursor *) 0); return(0);}
983: OpBlit(srcop,dstop);
984: }
985:
986: Erase(r)
987: Rectangle r;
988: {
989: int i,j;
990: for (j = r.origin.y ; j < r.corner.y ; j++) {
991: wait(CPU);
992: for (i = r.origin.x ; i < r.corner.x ; i++) {
993: if (geticonpoint(Pt(i,j)) == true) flipiconpoint(Pt(i,j));
994: }
995: }
996: }
997:
998: OpErase()
999: {
1000: Rectangle r;
1001: if (GetIconRect(&r)==0) return(0);
1002: SaveForUndo();
1003: cursswitch(&clock);
1004: Erase(r);
1005: cursswitch((Cursor *)0);
1006: }
1007:
1008: OpInvert()
1009: {
1010: Rectangle r;
1011: int i,j;
1012: if (GetIconRect(&r)==0) return(0);
1013: SaveForUndo();
1014: cursswitch(&clock);
1015: for (j = r.origin.y ; j < r.corner.y ; j++) {
1016: wait(CPU);
1017: for (i = r.origin.x ; i < r.corner.x ; i++) {
1018: flipiconpoint(Pt(i,j));
1019: }
1020: }
1021: cursswitch((Cursor *)0);
1022: }
1023:
1024: getstr(s,p)
1025: char *s;
1026: Point p;
1027: {
1028: char c,*t;
1029: static char str[]="x";
1030: t = s;
1031: for (;;) {
1032: wait(KBD);
1033: if (((c=kbdchar()) == '\r') || (c == '\n')) {
1034: *s = '\0';
1035: return;
1036: }
1037: if (c == '\b') {
1038: if (s>t) {
1039: str[0] = *(--s);
1040: string(&defont,str,&display,(p = sub(p,Pt(9,0))),F_XOR);
1041: }
1042: } else if ((c >= '!') && (c <= '~')) {
1043: if (s-t<50) {
1044: *s++ = (str[0] = c);
1045: p = string(&defont,str,&display,p,F_XOR);
1046: }
1047: }
1048: }
1049: }
1050:
1051: GetFNAME()
1052: {
1053: Point p;
1054: Bitmap *b;
1055: cursswitch(&deadmouse);
1056: b = balloc(Rpt(Drect.origin,Pt(Drect.corner.x,Drect.origin.y+18)));
1057: if (b!=0) {
1058: bitblt(&display,b->rect,b,Drect.origin,F_STORE);
1059: rectf(&display,b->rect,F_CLR);
1060: outline(&display,inset(b->rect,1));
1061: }
1062: p = string(&defont,"File: ",&display,add(Drect.origin,Pt(10,3)),F_XOR);
1063: getstr(FNAME,p);
1064: p = string(&defont,"File: ",&display,add(Drect.origin,Pt(10,3)),F_XOR);
1065: string(&defont,FNAME,&display,p,F_XOR);
1066: if (b!=0) {
1067: bitblt(b,b->rect,&display,Drect.origin,F_STORE);
1068: bfree(b);
1069: }
1070: cursswitch((Cursor *) 0);
1071: }
1072:
1073: Bitmap *pickupmap;
1074:
1075: PickUpCursor()
1076: {
1077: /*
1078: Cursor *oldcursor;
1079: Cursor pickuptexture;
1080: Rectangle r;
1081: int i;
1082: r = TrackBorder(raddp(rect16x16,IconPoint(mouse.xy)),true);
1083: r = raddp(r,icon.origin);
1084: bitblt(&display,r,pickupmap,Pt(0,0),F_STORE);
1085: for (i=0; i<16; i++) pickuptexture.bits[i] = (short)(pickupmap->base[i]>>16);
1086: oldcursor = cursswitch(&pickuptexture);
1087: while (button123())jnap(1);
1088: while (!button123())jnap(1);
1089: while (button123())jnap(1);
1090: cursswitch(oldcursor);
1091: */
1092: }
1093:
1094: char SFbuffer[100];
1095: char *SFlist[] = { /* Where to look */
1096: "", /* Look in local directory first */
1097: "/usr/jerq/icon/16x16/", /* Ick! "/usr/jerq/icon" should be a parameter */
1098: "/usr/jerq/icon/texture/",
1099: "/usr/jerq/icon/large/",
1100: "/usr/jerq/icon/face48/",
1101: (char *) 0
1102: };
1103:
1104: FILE *SearchFile(filename,mode,filefound)
1105: char *filename, *mode, **filefound;
1106: {
1107: FILE *fp;
1108: char **sf = SFlist;
1109: int namez = strlen(filename);
1110: *filefound = SFbuffer;
1111: fp = (FILE *) 0;
1112: for (; (fp == (FILE *) 0) && (*sf != (char *) 0); sf++) {
1113: if ((strlen(*sf) + namez) < sizeof(SFbuffer)) {
1114: strcpy(SFbuffer, *sf);
1115: strcat(SFbuffer, filename);
1116: fp = fopen(SFbuffer, mode);
1117: }
1118: }
1119: return(fp);
1120: }
1121:
1122: Rectangle OpLoad(bitmap,filename)
1123: Bitmap *bitmap;
1124: char *filename;
1125: {
1126: FILE *fp;
1127: Rectangle rect;
1128: Cursor *oldcursor;
1129: char *filefound;
1130: int ch,i,j;
1131: int xsize,ysize;
1132: rect = bitmap->rect;
1133: oldcursor = cursswitch(&clock);
1134: fp = SearchFile(filename,"r",&filefound);
1135: if (fp == ((FILE *) 0)) {cursswitch((Cursor *) 0); return(nullrect);}
1136: ch = getc(fp);
1137: if (ch=='0') {
1138: i = rect.origin.x; j = rect.origin.y;
1139: xsize = 0;
1140: for (;;) {
1141: getc(fp); /* 'x' */
1142: putnibble(getc(fp),bitmap,rect,Pt(i,j)); i+=4;
1143: putnibble(getc(fp),bitmap,rect,Pt(i,j)); i+=4;
1144: putnibble(getc(fp),bitmap,rect,Pt(i,j)); i+=4;
1145: putnibble(getc(fp),bitmap,rect,Pt(i,j)); i+=4;
1146: getc(fp); /* ',' */
1147: while ((ch = getc(fp))==' '); /* '0' or '\n' */
1148: if (ch=='\n') {
1149: xsize = max(xsize,i-rect.origin.x);
1150: i = rect.origin.x;
1151: j++;
1152: ch = getc(fp); /* '0' */
1153: } else if (ch == EOF) break;
1154: }
1155: ysize = j-rect.origin.y;
1156: } else {
1157: while ((ch!='{')&&(ch!=EOF)) ch=getc(fp);
1158: for (j=rect.origin.y; j<rect.origin.y+16; j++) {
1159: while (((ch=getc(fp))!='x')&&(ch!='X')&&(ch!=EOF)) {};
1160: putnibble(getc(fp),bitmap,rect,Pt(rect.origin.x,j));
1161: putnibble(getc(fp),bitmap,rect,Pt(rect.origin.x+4,j));
1162: putnibble(getc(fp),bitmap,rect,Pt(rect.origin.x+8,j));
1163: putnibble(getc(fp),bitmap,rect,Pt(rect.origin.x+12,j));
1164: }
1165: xsize = ysize = 16;
1166: }
1167: fclose(fp);
1168: rect.origin.x = 0; rect.origin.y = 0;
1169: rect.corner.x = xsize; rect.corner.y = ysize;
1170: cursswitch(oldcursor);
1171: return(rect);
1172: }
1173:
1174: OpRead()
1175: {
1176: Rectangle rect, r1;
1177: Bitmap *buffer;
1178: Point p;
1179: GetFNAME();
1180: if (!FNAME[0]) return(0);
1181: buffer = balloc(Source->rect);
1182: if (buffer == ((Bitmap *) 0)) {cursswitch((Cursor *) 0); return(0);}
1183: rectf(buffer,buffer->rect,F_CLR);
1184: rect = OpLoad(buffer,FNAME);
1185: if (!eqrect(rect,nullrect)) {
1186: SaveForUndo();
1187: r1 = TrackBorder(raddp(rect,IconPoint(mouse.xy)),true);
1188: p = r1.origin;
1189: while (button3())jnap(1);
1190: cursswitch(&clock);
1191: OrOntoPicture(buffer,rect,p);
1192: cursswitch((Cursor *)0);
1193: }
1194: bfree(buffer);
1195: }
1196:
1197: #ifdef BSD
1198: #define BUFSIZE BUFSIZ
1199: #endif BSD
1200: char buffer[BUFSIZE];
1201: char *bufend;
1202:
1203: bclear()
1204: {
1205: bufend = buffer;
1206: }
1207:
1208: bsend(fp)
1209: FILE *fp;
1210: {
1211: *bufend = '\0';
1212: fputs(buffer,fp);
1213: bclear();
1214: }
1215:
1216: bputc(c,fp)
1217: char c;
1218: FILE *fp;
1219: {
1220: if (bufend >= buffer+BUFSIZE-3) bsend(fp);
1221: *bufend++ = c;
1222: }
1223:
1224: OpWrite()
1225: {
1226: FILE *fp;
1227: Rectangle r;
1228: Point p;
1229: int i,j,butt;
1230: butt = GetIconRect(&r);
1231: if (butt==0) return(0);
1232: if (butt==3) {
1233: GetFNAME();
1234: if (!FNAME[0]) return(0);
1235: fp = fopen(FNAME,"w");
1236: if (fp == ((FILE *) 0)) return(0);
1237: rectf(&display,Drect,F_XOR);
1238: bclear();
1239: for (j = r.origin.y; j<r.corner.y; j++) {
1240: for (i=r.origin.x; i<r.corner.x; i+=16) {
1241: bputc('0',fp);bputc('x',fp);
1242: bputc(getnibble(Source,Pt(i,j)),fp);
1243: bputc(getnibble(Source,Pt(i+4,j)),fp);
1244: bputc(getnibble(Source,Pt(i+8,j)),fp);
1245: bputc(getnibble(Source,Pt(i+12,j)),fp);
1246: bputc(',',fp);
1247: }
1248: bputc('\n',fp);
1249: bsend(fp);
1250: }
1251: fclose(fp);
1252: rectf(&display,Drect,F_XOR);
1253: } else if (butt==2) {
1254: GetFNAME();
1255: if (!FNAME[0]) return(0);
1256: fp = fopen(FNAME,"w");
1257: if (fp == ((FILE *) 0)) return(0);
1258: rectf(&display,Drect,F_XOR);
1259: fputs("Texture ",fp); fputs(FNAME,fp); fputs(" = {\n",fp);
1260: j = r.origin.y; i = r.origin.x;
1261: bclear();
1262: while (j < r.corner.y) {
1263: if (((j-r.origin.y)%4) == 0) bputc('\t',fp);
1264: bputc(' ',fp);bputc('0',fp);bputc('x',fp);
1265: bputc(getnibble(Source,Pt(i,j)),fp);
1266: bputc(getnibble(Source,Pt(i+4,j)),fp);
1267: bputc(getnibble(Source,Pt(i+8,j)),fp);
1268: bputc(getnibble(Source,Pt(i+12,j)),fp);
1269: bputc(',',fp);
1270: if (((j-r.origin.y)%4) == 3) bputc('\n',fp);
1271: j = j+1;
1272: bsend(fp);
1273: }
1274: fputs("};\n",fp);
1275: fclose(fp);
1276: rectf(&display,Drect,F_XOR);
1277: }
1278:
1279: }
1280:
1281: OpTexture()
1282: {
1283: Bitmap *buffer,*buffer1;
1284: Rectangle source,dest;
1285: Point target;
1286: int repx,repy,i,j,hsize,vsize;
1287: if (GetIconRect(&source)==0) return(0);
1288: if (GetIconRect(&dest)==0) return(0);
1289: hsize = horsize(source);
1290: vsize = versize(source);
1291: if ((hsize==0) || (vsize==0)) return(0);
1292: buffer = balloc(source);
1293: if (buffer == ((Bitmap *) 0)) return(0);
1294: buffer1 = balloc(source);
1295: if (buffer1 == ((Bitmap *) 0)) {bfree(buffer); return(0);}
1296: SaveForUndo();
1297: cursswitch(&clock);
1298: bitblt(&display,raddp(source,icon.origin),buffer,buffer->rect.origin,F_STORE);
1299: repx = horsize(dest)/hsize;
1300: repy = versize(dest)/vsize;
1301: for (j=0; j<=repy; j++)
1302: for (i=0; i<=repx; i++) {
1303: bitblt(buffer,buffer->rect,buffer1,buffer1->rect.origin,F_STORE);
1304: OrOntoPictureClipped(buffer1,
1305: buffer1->rect,add(dest.origin,Pt(i*hsize,j*vsize)),dest);
1306: }
1307: cursswitch((Cursor *) 0);
1308: bfree(buffer);
1309: bfree(buffer1);
1310: }
1311:
1312: int GridSwitch=0;
1313:
1314: OpGrid()
1315: {
1316: if ((GridSwitch%2)==0) DrawFineGrid(); else DrawCoarseGrid();
1317: GridSwitch = (GridSwitch+1)%4;
1318: }
1319:
1320: OpResize()
1321: {
1322: Point p;
1323: Rectangle r;
1324: Bitmap *NewSource, *NewUndo;
1325: Cursor *oldcursor;
1326: bool doit;
1327: oldcursor = cursswitch(&clock);
1328: p=mouse.xy;
1329: r=canonrect(icon.origin,p);
1330: outline(&display,r);
1331: for(; !button123(); nap(2)){
1332: outline(&display,r);
1333: p=mouse.xy;
1334: r=canonrect(icon.origin,p);
1335: outline(&display,r);
1336: }
1337: doit = button3();
1338: outline(&display,r);
1339: cursswitch(oldcursor);
1340: while (button123())jnap(1);
1341: if (!doit) return(0);
1342: if (!rectclip(&r,Rpt(icon.origin,ICON.corner))) return(0);
1343: r = rsubp(r,icon.origin);
1344: NewSource = balloc(r); if (NewSource==0) return(0);
1345: NewUndo = balloc(r); if (NewUndo==0) {bfree(NewSource); return(0);}
1346: rectf(NewSource,NewSource->rect,F_CLR);
1347: rectf(NewUndo,NewUndo->rect,F_CLR);
1348: bitblt(Source,Source->rect,NewSource,NewSource->rect.origin,F_XOR);
1349: bitblt(Undo,Undo->rect,NewUndo,NewUndo->rect.origin,F_XOR);
1350: bfree(Source); bfree(Undo);
1351: Source = NewSource; Undo = NewUndo;
1352: rectf(&display,Drect,F_CLR);
1353: XSIZE = horsize(r); YSIZE = versize(r);
1354: Redraw();
1355: }
1356:
1357:
1358: HorShear(r,dx,top)
1359: Rectangle r;
1360: int dx;
1361: bool top;
1362: {
1363: int j,vsize,shift;
1364: vsize = versize(r);
1365: for (j=0; j<vsize; j++) {
1366: shift = top ? vsize-j-1 : j;
1367: IconBitBlit(Rect(r.origin.x,r.origin.y+j,r.corner.x,r.origin.y+j+1),
1368: Pt(r.origin.x+muldiv(shift,dx,vsize),r.origin.y+j),
1369: Rect(0,0,Xblocks,Yblocks),
1370: I_CLR,I_OR);
1371: }
1372: }
1373:
1374: VerShear(r,dy,lft)
1375: Rectangle r;
1376: int dy;
1377: bool lft;
1378: {
1379: int i,hsize,shift;
1380: hsize = horsize(r);
1381: for (i=0; i<hsize; i++) {
1382: shift = lft ? hsize-i-1 : i;
1383: IconBitBlit(Rect(r.origin.x+i,r.origin.y,r.origin.x+i+1,r.corner.y),
1384: Pt(r.origin.x+i,r.origin.y+muldiv(shift,dy,hsize)),
1385: Rect(0,0,Xblocks,Yblocks),
1386: I_CLR,I_OR);
1387: }
1388: }
1389:
1390: OpHorShear()
1391: {
1392: Rectangle r;
1393: int dx;
1394: bool top;
1395: Point p,nearcorner;
1396: if (GetIconRect(&r)==0) return(0);
1397: if ((horsize(r)==0) || (versize(r)==0)) return(0);
1398: if (!GetIconPoint(&p)) return(0);
1399: SaveForUndo();
1400: cursswitch(&clock);
1401: nearcorner = nearestcorner(r,p);
1402: dx = p.x - nearcorner.x;
1403: top = (nearcorner.y == r.origin.y);
1404: HorShear(r,dx,top);
1405: cursswitch((Cursor *) 0);
1406: }
1407:
1408: OpVerShear()
1409: {
1410: Rectangle r;
1411: int dy;
1412: bool lft;
1413: Point p,nearcorner;
1414: if (GetIconRect(&r)==0) return(0);
1415: if ((horsize(r)==0) || (versize(r)==0)) return(0);
1416: if (!GetIconPoint(&p)) return(0);
1417: SaveForUndo();
1418: cursswitch(&clock);
1419: nearcorner = nearestcorner(r,p);
1420: dy = p.y - nearcorner.y;
1421: lft = (nearcorner.x == r.origin.x);
1422: VerShear(r,dy,lft);
1423: cursswitch((Cursor *) 0);
1424: }
1425:
1426: Stretch(sb,sr,db,dr,op)
1427: Bitmap *sb,*db;
1428: Rectangle sr,dr;
1429: Code op;
1430: {
1431: int i,j,shsize,svsize,dhsize,dvsize;
1432: shsize = horsize(sr);
1433: svsize = versize(sr);
1434: dhsize = horsize(dr);
1435: dvsize = versize(dr);
1436: for (j=0; j<svsize; j++) {
1437: wait(CPU);
1438: for (i=0; i<shsize; i++) {
1439: bitblt(sb,
1440: Rect(sr.origin.x+i,sr.origin.y+j,sr.origin.x+i+1,sr.origin.y+j+1),
1441: db,
1442: Pt(dr.origin.x+muldiv(dhsize,i,shsize),
1443: dr.origin.y+muldiv(dvsize,j,svsize)),
1444: op);
1445: }
1446: }
1447: }
1448:
1449: OpStretch()
1450: {
1451: Bitmap *buffer;
1452: Rectangle source,dest;
1453: if (GetIconRect(&source)==0) return(0);
1454: if ((horsize(source)==0) || (versize(source)==0)) return(0);
1455: if (GetIconRect(&dest)==0) return(0);
1456: if ((horsize(dest)==0) || (versize(dest)==0)) return(0);
1457: buffer = balloc(dest);
1458: if (buffer == ((Bitmap *) 0)) return(0);
1459: SaveForUndo();
1460: cursswitch(&clock);
1461: rectf(buffer,buffer->rect,F_CLR);
1462: Stretch(&display,raddp(source,icon.origin),buffer,buffer->rect,F_XOR);
1463: IconBitBlit(source,source.origin,Rect(0,0,0,0),F_CLR,F_CLR);
1464: OrOntoPictureClipped(buffer,buffer->rect,dest.origin,dest);
1465: cursswitch((Cursor *) 0);
1466: bfree(buffer);
1467: }
1468:
1469: DrawHorGridLine(p,op)
1470: Point p;
1471: Code op;
1472: {
1473: if ((p.y < icon.corner.y+2) && (p.x < icon.corner.x+2))
1474: p.x = ScreenCoordX(IconCoordX(icon.corner.x+Xsize));
1475: rectf(&display,Rpt(p,Pt(ICON.corner.x,p.y+1)),op);
1476: }
1477:
1478: DrawVerGridLine(p,op)
1479: Point p;
1480: Code op;
1481: {
1482: if ((p.x < icon.corner.x+2) && (p.y < icon.corner.y+2))
1483: p.y = ScreenCoordY(IconCoordY(icon.corner.y+Ysize));
1484: rectf(&display,Rpt(p,Pt(p.x+1,ICON.corner.y)),op);
1485: }
1486:
1487: DrawGridBorder()
1488: {
1489: DrawHorGridLine(ICON.origin,F_OR);
1490: DrawHorGridLine(add(ICON.origin,Pt(0,Yblocks*Ysize)),F_OR);
1491: DrawVerGridLine(ICON.origin,F_OR);
1492: DrawVerGridLine(add(ICON.origin,Pt(Xblocks*Xsize,0)),F_OR);
1493: point(&display,ICON.corner,F_OR);
1494: }
1495:
1496: DrawFineGrid()
1497: {
1498: register int i,j;
1499: for (j=1; j<Yblocks; j++) DrawHorGridLine(add(ICON.origin,Pt(0,j*Ysize)),F_XOR);
1500: for (i=1; i<Xblocks; i++) DrawVerGridLine(add(ICON.origin,Pt(i*Xsize,0)),F_XOR);
1501: }
1502:
1503: DrawCoarseGrid()
1504: {
1505: Point p;
1506: register int i,j;
1507: for (j=0; j<=Yblocks; j+=16)
1508: DrawHorGridLine(add(ICON.origin,Pt(0,j*Ysize+1)),F_XOR);
1509: for (j=8; j<=Yblocks; j+=16) {
1510: p=add(ICON.origin,Pt(0,j*Ysize+1));
1511: if ((p.y < icon.corner.y+2) && (p.x < icon.corner.x+2))
1512: p.x = ScreenCoordX(IconCoordX(icon.corner.x+Xsize));
1513: for (i=0; i<=Xblocks*Xsize; i+=2)
1514: point(&display,Pt(p.x+i,p.y),F_XOR);
1515: }
1516: for (i=0; i<=Xblocks; i+=16)
1517: DrawVerGridLine(add(ICON.origin,Pt(i*Xsize+1,0)),F_XOR);
1518: for (i=8; i<=Xblocks; i+=16) {
1519: p=add(ICON.origin,Pt(i*Xsize+1,0));
1520: if ((p.x < icon.corner.x+2) && (p.y < icon.corner.y+2))
1521: p.y = ScreenCoordY(IconCoordY(icon.corner.y+Ysize));
1522: for (j=0; j<=Yblocks*Ysize; j+=2)
1523: point(&display,Pt(p.x,p.y+j),F_XOR);
1524: }
1525: }
1526:
1527: Bitmap *HelpBuffer, *HelpTexture;
1528:
1529: helpline(i,icon,str)
1530: int i;
1531: Texture *icon;
1532: char *str;
1533: {
1534: texture(HelpTexture,HelpTexture->rect,icon,F_STORE);
1535: bitblt(HelpTexture,HelpTexture->rect,HelpBuffer,Pt(2,2+16*i),F_XOR);
1536: string(&defont,str,HelpBuffer,Pt(2+32,2+16*i),F_XOR);
1537: }
1538:
1539: HelpSorry()
1540: {
1541: string(&defont,"Not enough space on blit",
1542: &display,add(icon.corner,Pt(15,-20)),F_XOR);
1543: }
1544:
1545: Help()
1546: {
1547: HelpBuffer = balloc(Rect(0,0,302,482));
1548: HelpTexture = balloc(Rect(0,0,16,16));
1549: if ((HelpBuffer==0) || (HelpTexture==0)) {
1550: HelpSorry();
1551: while (!button123()) wait(MOUSE);
1552: HelpSorry();
1553: while (button123())jnap(1);
1554: return(0);
1555: }
1556: rectf(HelpBuffer,HelpBuffer->rect,F_CLR);
1557: outline(HelpBuffer,Rpt(HelpBuffer->rect.origin,sub(HelpBuffer->rect.corner,Pt(1,1))));
1558: helpline(0,&whiteT,"left button: draw");
1559: helpline(1,&whiteT,"middle button: erase");
1560: helpline(2,&whiteT,"");
1561: helpline(3,&Cmove,"move region");
1562: helpline(4,&Ccopy,"copy region");
1563: helpline(5,&Cinvert,"invert region");
1564: helpline(6,&Cerase,"erase region");
1565: helpline(7,&Creflx,"reflect x region");
1566: helpline(8,&Crefly,"reflect y region");
1567: helpline(9,&Crotplus,"rotate + region");
1568: helpline(10,&Crotminus,"rotate - region");
1569: helpline(11,&Cshearx,"shear x region");
1570: helpline(12,&Csheary,"shear y region");
1571: helpline(13,&Cstretch,"stretch region");
1572: helpline(14,&Ctexture,"texture region");
1573: helpline(15,&Cread,"read file");
1574: helpline(16,&Cgrid,"background grids");
1575: helpline(17,&Cresize,"resize drawing area");
1576: helpline(18,&Cwrite,"write file");
1577: helpline(19,&Cblit,"bitblit region");
1578: helpline(20,&Ccursor,"pick cursor icon");
1579: helpline(21,&Chelp,"(press a button to continue)");
1580: helpline(22,&Cundo,"undo last operation");
1581: helpline(23,&whiteT,"");
1582: helpline(24,&clockT,"wait");
1583: helpline(25,&deadmouseT,"mouse inactive");
1584: helpline(26,&menucursorT, "menu on right button");
1585: helpline(27,&sweepcursorT,"sweep rect (right button)");
1586: helpline(28,&sweeportrackT,"sweep rect (right button) or");
1587: helpline(29,&whiteT,"get 16x16 frame (middle butt)");
1588: screenswap(HelpBuffer,HelpBuffer->rect,raddp(HelpBuffer->rect,Drect.origin));
1589: while (!button123())jnap(1);
1590: screenswap(HelpBuffer,HelpBuffer->rect,raddp(HelpBuffer->rect,Drect.origin));
1591: while (button123())jnap(1);
1592: bfree(HelpBuffer);
1593: bfree(HelpTexture);
1594: }
1595:
1596: SaveForUndo()
1597: {
1598: bitblt(Source,Source->rect,Undo,Undo->rect.origin,F_STORE);
1599: }
1600:
1601: OpUndo()
1602: {
1603: Rectangle r;
1604: int hsize,vsize,i,j;
1605: bool bit;
1606: Cursor *oldcursor;
1607: oldcursor = cursswitch(&clock);
1608: r = Source->rect;
1609: bitblt(Undo,r,Source,r.origin,F_XOR);
1610: XorOntoScreen(Source,r,r.origin);
1611: bitblt(Source,r,Undo,r.origin,F_XOR);
1612: bitblt(Undo,r,Source,r.origin,F_XOR);
1613: cursswitch(oldcursor);
1614: }
1615:
1616: XorOntoScreen(b,r,p)
1617: Bitmap *b;
1618: Rectangle r;
1619: Point p;
1620: {
1621: int i,j,h,v;
1622: h = horsize(r); v = versize(r);
1623: for(j=0; j<h; j++) {
1624: wait(CPU);
1625: for (i=0; i<v; i++) {
1626: if (bitmapbit(b,add(r.origin,Pt(j,i))))
1627: FlipOntoScreen(add(p,Pt(j,i)));
1628: }
1629: }
1630: }
1631:
1632: XorOntoPicture(b,r,p)
1633: Bitmap *b;
1634: Rectangle r;
1635: Point p;
1636: {
1637: XorOntoScreen(b,r,p);
1638: bitblt(b,r,Source,p,F_XOR);
1639: }
1640:
1641: OrOntoPicture(b,r,p)
1642: Bitmap *b;
1643: Rectangle r;
1644: Point p;
1645: /* Scrambles the contents of b */
1646: {
1647: rectf(b,r,F_XOR);
1648: bitblt(Source,raddp(rsubp(r,r.origin),p),b,r.origin,F_OR);
1649: rectf(b,r,F_XOR);
1650: XorOntoPicture(b,r,p);
1651: }
1652:
1653: OrOntoPictureClipped(b,r,p,clip)
1654: Bitmap *b;
1655: Rectangle r;
1656: Point p;
1657: Rectangle clip;
1658: {
1659: if (!rectclip(&r,rsubp(clip,sub(p,r.origin)))) r = nullrect;
1660: OrOntoPicture(b,r,p);
1661: }
1662:
1663: bool FirstTime = true;
1664:
1665: Redraw()
1666: {
1667: Xblocks = XSIZE;
1668: Yblocks = YSIZE;
1669:
1670: Xsize = (horsize(Drect)-1)/Xblocks;
1671: Ysize = (versize(Drect)-1)/Yblocks;
1672:
1673: if (Xsize==0) Xsize = 1;
1674: if (Ysize==0) Ysize = 1;
1675:
1676: Ysize = (Xsize = (Xsize<Ysize)?Xsize:Ysize);
1677:
1678: icon.origin = add(Drect.origin,Pt(2,2));
1679: icon.corner = add(icon.origin,Pt(Xblocks,Yblocks));
1680:
1681: ICON.origin = sub(Drect.corner,Pt(1+Xsize*Xblocks,1+Ysize*Yblocks));
1682: ICON.corner = add(ICON.origin,Pt(Xsize*Xblocks,Ysize*Yblocks));
1683: modx = ICON.origin.x % Xsize;
1684: divx = ICON.origin.x / Xsize;
1685: mody = ICON.origin.y % Ysize;
1686: divy = ICON.origin.y / Ysize;
1687:
1688: rectf(&display, Drect, F_CLR);
1689: DrawGridBorder();
1690: outline(&display,inset(Rpt(icon.origin,add(icon.corner,Pt(-1,-1))),-2));
1691: if ((GridSwitch==1)||(GridSwitch==2)) DrawFineGrid();
1692: if ((GridSwitch==2)||(GridSwitch==3)) DrawCoarseGrid();
1693:
1694: if (FirstTime) FirstTime = false;
1695: else {
1696: cursswitch(&clock);
1697: XorOntoScreen(Source,Source->rect,Source->rect.origin);
1698: cursswitch((Cursor *)0);
1699: }
1700: }
1701:
1702: Icon()
1703: {
1704: Bitmap *b;
1705: Point p,cur,hit;
1706: int i,j;
1707:
1708: Redraw();
1709:
1710: cur.x = 0; cur.y = 0;
1711:
1712: for (;;) {
1713: wait(MOUSE);
1714: if (P->state&RESHAPED) return(0);
1715: if (button1()) {
1716: SaveForUndo();
1717: while(button1()) {
1718: if (ptinrect((p=mouse.xy),ICON)) {
1719: p = sub(p,ICON.origin);
1720: cur.x = p.x/Xsize;
1721: cur.y = p.y/Ysize;
1722: if (geticonpoint(cur) == false) flipiconpoint(cur);
1723: }
1724: wait(MOUSE);
1725: }
1726: } else if (button2()) {
1727: SaveForUndo();
1728: while(button2()) {
1729: if (ptinrect((p=mouse.xy),ICON)) {
1730: p = sub(p,ICON.origin);
1731: cur.x = p.x/Xsize;
1732: cur.y = p.y/Ysize;
1733: if (geticonpoint(cur) == true) flipiconpoint(cur);
1734: }
1735: wait(MOUSE);
1736: }
1737: }
1738: if (button3()) {
1739: hit = imenuhit(imenu);
1740: switch (5*hit.y+hit.x) {
1741: case BLIT: OpGeneralBlit(); break;
1742: case MOVE: OpBlit(I_CLR,I_OR); break;
1743: case COPY: OpBlit(I_OR,I_OR); break;
1744: case ERASE: OpErase(); break;
1745: case INVERT: OpInvert(); break;
1746: case REFLECTX: OpReflX(); break;
1747: case REFLECTY: OpReflY(); break;
1748: case ROTATEPLUS: OpRotPlus(); break;
1749: case ROTATEMINUS: OpRotMinus(); break;
1750: case SHEARX: OpHorShear(); break;
1751: case SHEARY: OpVerShear(); break;
1752: case STRETCH: OpStretch(); break;
1753: case TEXTURE: OpTexture(); break;
1754: case GRID: OpGrid(); break;
1755: case PICK: PickUpCursor(); break;
1756: case READ: OpRead(); break;
1757: case WRITE: OpWrite(); break;
1758: case RESIZE: OpResize(); break;
1759: case HELP: Help(); break;
1760: case UNDO: OpUndo(); break;
1761: }
1762: }
1763: }
1764: }
1765:
1766:
1767: main(argc,argv)
1768: char *argv[];
1769: {
1770: request(MOUSE|SEND|KBD);
1771: mousemotion();
1772: initdisplay(argc, argv);
1773: initicons();
1774:
1775: nullpoint.x = 0;
1776: nullpoint.y = 0;
1777: point16x16.x = 16;
1778: point16x16.y = 16;
1779: nullrect.origin = nullpoint;
1780: nullrect.corner = nullpoint;
1781: rect16x16.origin = nullpoint;
1782: rect16x16.corner = point16x16;
1783:
1784: bittester = balloc(Rect(0,0,1,1));
1785: pickupmap = balloc(Rect(0,0,16,16));
1786: Source = balloc(Rect(0,0,XSIZE,YSIZE));
1787: if (Source == ((Bitmap *) 0)) exit();
1788: rectf(Source,Source->rect,F_CLR);
1789: Undo = balloc(Rect(0,0,XSIZE,YSIZE));
1790: if (Undo == ((Bitmap *) 0)) exit();
1791: rectf(Undo,Undo->rect,F_CLR);
1792:
1793: do {
1794: P->state&=~RESHAPED;
1795: Icon();
1796: } while (P->state&RESHAPED);
1797:
1798: exit();
1799:
1800: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.