aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Hulsman <davidhulsmannl@gmail.com>2019-07-05 15:46:03 +0200
committerDavid Hulsman <davidhulsmannl@gmail.com>2019-07-05 15:46:03 +0200
commitc7f4deb533625b9558ba787cd30cedb250ae5fc3 (patch)
tree253364c03bc0375a8e7e5651d78bf0259dbd8775
parent8ae175b75a68701560fb8d1f378cc1a0514a0a01 (diff)
downloadDeluxePaint-c7f4deb533625b9558ba787cd30cedb250ae5fc3.tar.gz
DeluxePaint-c7f4deb533625b9558ba787cd30cedb250ae5fc3.tar.bz2
DeluxePaint-c7f4deb533625b9558ba787cd30cedb250ae5fc3.zip
add original source
-rw-r--r--ACTBMS.C494
-rw-r--r--AIRBRUSH.C65
-rw-r--r--BEND.C189
-rw-r--r--BITMAPS.C238
-rw-r--r--BLEND.C79
-rw-r--r--BLITOPS.C196
-rw-r--r--BLITREGS.H23
-rw-r--r--BMOB.C416
-rw-r--r--BOX.C69
-rw-r--r--BRXFORM.C145
-rw-r--r--CCYCLE.C190
-rw-r--r--CHPROC.C252
-rw-r--r--CLIP.C214
-rw-r--r--CONIC.C238
-rw-r--r--CTRPAN.C528
-rw-r--r--CURBRUSH.C170
-rw-r--r--CURSBMS.C188
-rw-r--r--CURSOR.C73
-rw-r--r--DALLOC.C38
-rw-r--r--DISPNUM.C144
-rw-r--r--DISTANCE.C20
-rw-r--r--DOPALETT.C66
-rw-r--r--DOSYMREQ.C25
-rw-r--r--DOTBMS.C138
-rw-r--r--DPHOOK.H16
-rw-r--r--DPIFF.C341
-rw-r--r--DPIFF.H44
-rw-r--r--DPINIT.C438
-rw-r--r--DPINIT2.C126
-rw-r--r--DPIO.C351
-rw-r--r--FILL.C197
-rw-r--r--FNBMS.C43
-rw-r--r--FNREQ.C794
-rw-r--r--FNREQ.H11
-rw-r--r--FONTINIT.C177
-rw-r--r--GEOM.C119
-rw-r--r--GRDEFS.H330
-rw-r--r--HOOK.C38
-rw-r--r--HSV.C215
-rw-r--r--IFFR.C295
-rw-r--r--IFFW.C310
-rw-r--r--ILBMR.C144
-rw-r--r--ILBMW.C140
-rw-r--r--INITOVS.C10
-rw-r--r--INITREAD.C10
-rw-r--r--INITWRIT.C10
-rw-r--r--INTUALL.H34
-rw-r--r--KEYJUNK.C109
-rw-r--r--MAGBITS.C233
-rw-r--r--MAGOPS.C140
-rw-r--r--MAGWIN.C215
-rw-r--r--MAINMAG.C450
-rw-r--r--MAKEICON.C236
-rw-r--r--MASKBLIT.C155
-rw-r--r--MENU.C454
-rw-r--r--MESSAGE.C28
-rw-r--r--MODES.C456
-rw-r--r--MOUSEBUT.C20
-rw-r--r--PACKER.H36
-rw-r--r--PACKERF.C111
-rw-r--r--PAINTW.C428
-rw-r--r--PALBMS.C41
-rw-r--r--PALETTE.C1336
-rw-r--r--PANE.C416
-rw-r--r--PENMENU.C28
-rw-r--r--PGRAPH.C312
-rw-r--r--PLBM.H100
-rw-r--r--PNTS.H27
-rw-r--r--POLYF.C154
-rw-r--r--POLYH.C56
-rw-r--r--PRINT.C63
-rw-r--r--PRISM.C379
-rw-r--r--PRISM.H415
-rw-r--r--PRISM.txt22
-rw-r--r--PSYM.C132
-rw-r--r--RANDOM.C35
-rw-r--r--REMAP.C170
-rw-r--r--REQCOM.C73
-rw-r--r--ROT90.C78
-rw-r--r--ROTATE.C201
-rw-r--r--SHADE.C194
-rw-r--r--SHEAR.C136
-rw-r--r--SPARE.C108
-rw-r--r--STRETCH.C236
-rw-r--r--SYMREQ.C375
-rw-r--r--SYSTEM.H75
-rw-r--r--TEXT.C199
-rw-r--r--TIMER.C63
-rw-r--r--UNPACKER.C57
89 files changed, 16943 insertions, 0 deletions
diff --git a/ACTBMS.C b/ACTBMS.C
new file mode 100644
index 0000000..152685e
--- /dev/null
+++ b/ACTBMS.C
@@ -0,0 +1,494 @@
+/* Bitmap name = act1, Amiga-BOB format. */
+/* Width = 11, Height = 11 */
+
+short act1[11] = {
+ 0xFFE0,
+ 0xFFE0,
+ 0xEFE0,
+ 0xFBE0,
+ 0xFFE0,
+ 0xFDE0,
+ 0xFFE0,
+ 0xFDE0,
+ 0xFFE0,
+ 0xFFE0,
+ 0xFFE0
+ };
+
+
+
+/* Bitmap name = act2, Amiga-BOB format. */
+/* Width = 11, Height = 11 */
+
+short act2[11] = {
+ 0xFFE0,
+ 0xFFE0,
+ 0xFFE0,
+ 0xE3E0,
+ 0xDBE0,
+ 0xFDE0,
+ 0xFDE0,
+ 0xFDA0,
+ 0xFD60,
+ 0xFCE0,
+ 0xFFE0
+ };
+
+
+
+/* Bitmap name = act3, Amiga-BOB format. */
+/* Width = 11, Height = 11 */
+
+short act3[11] = {
+ 0xFFE0,
+ 0xFFE0,
+ 0xFF60,
+ 0xFEE0,
+ 0xFDE0,
+ 0xFBE0,
+ 0xF7E0,
+ 0xEFE0,
+ 0xDFE0,
+ 0xFFE0,
+ 0xFFE0
+ };
+
+
+
+/* Bitmap name = act4, Amiga-BOB format. */
+/* Width = 11, Height = 11 */
+
+short act4[11] = {
+ 0xFFE0,
+ 0xFFE0,
+ 0x87E0,
+ 0xF9E0,
+ 0xFEE0,
+ 0xFF60,
+ 0xFF60,
+ 0xFFA0,
+ 0xFFA0,
+ 0xFFA0,
+ 0xFFE0
+ };
+
+
+
+/* Bitmap name = act5, Amiga-BOB format. */
+/* Width = 11, Height = 11 */
+
+short act5[11] = {
+ 0xFFE0,
+ 0xFFA0,
+ 0xC060,
+ 0xDE60,
+ 0xDC60,
+ 0xD860,
+ 0xD060,
+ 0xC060,
+ 0xC060,
+ 0xBFE0,
+ 0xFFE0
+ };
+
+
+
+/* Bitmap name = act5H, Amiga-BOB format. */
+/* Width = 11, Height = 11 */
+
+short act5H[11] = {
+ 0x0,
+ 0x0,
+ 0x3F80,
+ 0x2080,
+ 0x2080,
+ 0x2080,
+ 0x2080,
+ 0x2080,
+ 0x3F80,
+ 0x0,
+ 0x0
+ };
+
+
+
+/* Bitmap name = act5F, Amiga-BOB format. */
+/* Width = 11, Height = 11 */
+
+short act5F[11] = {
+ 0x0,
+ 0x0,
+ 0x3F80,
+ 0x3F80,
+ 0x3F80,
+ 0x3F80,
+ 0x3F80,
+ 0x3F80,
+ 0x3F80,
+ 0x0,
+ 0x0
+ };
+
+
+
+/* Bitmap name = act6, Amiga-BOB format. */
+/* Width = 11, Height = 11 */
+
+short act6[11] = {
+ 0xFFE0,
+ 0xF1A0,
+ 0xCE60,
+ 0xDE60,
+ 0xBC20,
+ 0xB820,
+ 0xB020,
+ 0xC060,
+ 0xC060,
+ 0xB1E0,
+ 0xFFE0
+ };
+
+
+
+/* Bitmap name = act6H, Amiga-BOB format. */
+/* Width = 11, Height = 11 */
+
+short act6H[11] = {
+ 0x0,
+ 0x0,
+ 0xE00,
+ 0x1100,
+ 0x2080,
+ 0x2080,
+ 0x2080,
+ 0x1100,
+ 0xE00,
+ 0x0,
+ 0x0
+ };
+
+
+
+/* Bitmap name = act6F, Amiga-BOB format. */
+/* Width = 10, Height = 11 */
+
+short act6F[11] = {
+ 0x0,
+ 0x0,
+ 0xE00,
+ 0x1F00,
+ 0x3F80,
+ 0x3F80,
+ 0x3F80,
+ 0x1F00,
+ 0xE00,
+ 0x0,
+ 0x0
+ };
+
+
+
+/* Bitmap name = act7, Amiga-BOB format. */
+/* Width = 11, Height = 11 */
+
+short act7[11] = {
+ 0xFFE0,
+ 0xFFA0,
+ 0xFF60,
+ 0xE0E0,
+ 0xDC60,
+ 0xB820,
+ 0xD060,
+ 0xE0E0,
+ 0xDFE0,
+ 0xBFE0,
+ 0xFFE0
+ };
+
+
+
+/* Bitmap name = act7H, Amiga-BOB format. */
+/* Width = 11, Height = 11 */
+
+short act7H[11] = {
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x1F00,
+ 0x2080,
+ 0x4040,
+ 0x2080,
+ 0x1F00,
+ 0x0,
+ 0x0,
+ 0x0
+ };
+
+
+
+/* Bitmap name = act7F, Amiga-BOB format. */
+/* Width = 11, Height = 11 */
+
+short act7F[11] = {
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x1F00,
+ 0x3F80,
+ 0x7FC0,
+ 0x3F80,
+ 0x1F00,
+ 0x0,
+ 0x0,
+ 0x0
+ };
+
+
+
+/* Bitmap name = act8, Amiga-BOB format. */
+/* Width = 11, Height = 11 */
+
+short act8[11] = {
+ 0xFFE0,
+ 0xFBA0,
+ 0xF560,
+ 0xEEE0,
+ 0xDC60,
+ 0xB820,
+ 0xD060,
+ 0xE0E0,
+ 0xD1E0,
+ 0xBBE0,
+ 0xFFE0
+ };
+
+
+
+/* Bitmap name = act8H, Amiga-BOB format. */
+/* Width = 11, Height = 11 */
+
+short act8H[11] = {
+ 0x0,
+ 0x400,
+ 0xA00,
+ 0x1100,
+ 0x2080,
+ 0x4040,
+ 0x2080,
+ 0x1100,
+ 0xA00,
+ 0x400,
+ 0x0
+ };
+
+
+
+/* Bitmap name = act8F, Amiga-BOB format. */
+/* Width = 11, Height = 11 */
+
+short act8F[11] = {
+ 0x0,
+ 0x400,
+ 0xE00,
+ 0x1F00,
+ 0x3F80,
+ 0x7FC0,
+ 0x3F80,
+ 0x1F00,
+ 0xE00,
+ 0x400,
+ 0x0
+ };
+
+
+
+/* Bitmap name = act9, Amiga-BOB format. */
+/* Width = 11, Height = 11 */
+
+short act9[11] = {
+ 0xFFE0,
+ 0xFBE0,
+ 0xF5E0,
+ 0xEEE0,
+ 0xDF60,
+ 0xEEE0,
+ 0xF5E0,
+ 0xF3E0,
+ 0xF7E0,
+ 0xC3E0,
+ 0xFFE0
+ };
+
+
+/* Bitmap name = act10, Amiga-BOB format. */
+/* Width = 11, Height = 11 */
+
+short act10[11] = {
+ 0xFFE0,
+ 0xFFE0,
+ 0xFD60,
+ 0xFBE0,
+ 0xF6A0,
+ 0x8BE0,
+ 0xF6A0,
+ 0xFBE0,
+ 0xFD60,
+ 0xFFE0,
+ 0xFFE0
+ };
+
+
+
+
+/* Bitmap name = act11, Amiga-BOB format. */
+/* Width = 11, Height = 11 */
+
+short act11[11] = {
+ 0xFFE0,
+ 0xFFE0,
+ 0xCE60,
+ 0xDF60,
+ 0xFFE0,
+ 0xFFE0,
+ 0xFFE0,
+ 0xDF60,
+ 0xCE60,
+ 0xFFE0,
+ 0xFFE0
+ };
+
+
+
+/* Bitmap name = act12, Amiga-BOB format. */
+/* Width = 11, Height = 11 */
+
+short act12[11] = {
+ 0xFFE0,
+ 0xFFE0,
+ 0xF3E0,
+ 0xE1E0,
+ 0xCCE0,
+ 0xCCE0,
+ 0xC0E0,
+ 0xCCE0,
+ 0xCCE0,
+ 0xFFE0,
+ 0xFFE0
+ };
+
+
+
+/* Bitmap name = act13, Amiga-BOB format. */
+/* Width = 11, Height = 11 */
+
+short act13[11] = {
+ 0xFFE0,
+ 0x8020,
+ 0xBBA0,
+ 0xBBA0,
+ 0xBBA0,
+ 0x8020,
+ 0xBBA0,
+ 0xBBA0,
+ 0xBBA0,
+ 0x8020,
+ 0xFFE0
+ };
+
+
+
+/* Bitmap name = act14, Amiga-BOB format. */
+/* Width = 11, Height = 11 */
+
+short act14[11] = {
+ 0xFFE0,
+ 0xFBE0,
+ 0xF5E0,
+ 0xFBE0,
+ 0xD160,
+ 0xA4A0,
+ 0xD160,
+ 0xFBE0,
+ 0xF5E0,
+ 0xFBE0,
+ 0xFFE0
+ };
+
+
+
+/* Bitmap name = act15, Amiga-BOB format. */
+/* Width = 11, Height = 11 */
+
+short act15[11] = {
+ 0xFFE0,
+ 0xF8E0,
+ 0xF760,
+ 0xEFA0,
+ 0xEFA0,
+ 0xEFA0,
+ 0xE760,
+ 0xC0E0,
+ 0x8FE0,
+ 0x9FE0,
+ 0xFFE0
+ };
+
+
+
+/* Bitmap name = act16, Amiga-BOB format. */
+/* Width = 11, Height = 11 */
+
+short act16[11] = {
+ 0xFFE0,
+ 0x8020,
+ 0xBFA0,
+ 0xA0A0,
+ 0xAEA0,
+ 0xAAA0,
+ 0xAEA0,
+ 0xA0A0,
+ 0xBFA0,
+ 0x8020,
+ 0xFFE0
+ };
+
+
+
+/* Bitmap name = act17, Amiga-BOB format. */
+/* Width = 11, Height = 11 */
+
+short act17[11] = {
+ 0xFFE0,
+ 0xB5A0,
+ 0xB4A0,
+ 0xB520,
+ 0xCDA0,
+ 0xFFE0,
+ 0x8E60,
+ 0xB5A0,
+ 0xB5A0,
+ 0x8E60,
+ 0xFFE0
+ };
+
+
+
+/* Bitmap name = act18, Amiga-BOB format. */
+/* Width = 11, Height = 11 */
+
+short act18[11] = {
+ 0xFFE0,
+ 0xFFE0,
+ 0x9660,
+ 0xB6A0,
+ 0xB6A0,
+ 0xB620,
+ 0xB660,
+ 0xB6A0,
+ 0xB6A0,
+ 0x92A0,
+ 0xFFE0
+ };
+
+
+
diff --git a/AIRBRUSH.C b/AIRBRUSH.C
new file mode 100644
index 0000000..afab09b
--- /dev/null
+++ b/AIRBRUSH.C
@@ -0,0 +1,65 @@
+/*----------------------------------------------------------------------*/
+/* */
+/* airbrush.c */
+/* */
+/*----------------------------------------------------------------------*/
+
+#include <system.h>
+#include <prism.h>
+#include <pnts.h>
+
+extern PointRec pnts;
+extern BOOL abortFlag, symON;
+extern void obmv(), obclr(), (*nop)();
+extern SHORT xShft, yShft;
+
+#define local static
+
+extern SHORT abRadius;
+
+local SHORT ab2Rad = 2*INITABRADIUS, abRad2 = INITABRADIUS*INITABRADIUS;
+
+/* ------ Air Brush Mode ------------------- */
+local Point abpt;
+
+local void abDoDot() { mDispOB(abpt.x, abpt.y); }
+local airbSym(x,y) SHORT x,y; {
+ abortFlag = NO;
+ abpt.x = x;
+ abpt.y = y;
+ SymDo(1,&abpt,abDoDot);
+ }
+
+local void AirBDots(x,y,proc) SHORT x,y; void (*proc)(); {
+ SHORT dx,dy;
+ for(;;) { /* repeat until generate a point */
+ /* first get a r.v. uniform in a square area */
+ dx = ((Rand16()&0x7fff)%ab2Rad) - abRadius;
+ dy = ((Rand16()&0x7fff)%ab2Rad) - abRadius;
+ /* now filter into circular distribution */
+ if ( (Random(abRad2)+Random(abRad2))/2 > ((SHORT)(dx*dx+dy*dy))) {
+ (*proc)(x+PMapX(dx),y+PMapY(dy));
+ break;
+ }
+ }
+ }
+
+local airbsplat() {
+ if (symON) AirBDots(mx,my,airbSym);
+ else AirBDots(mx,my,mDispOB);
+ CycPaint();
+ }
+
+/* ------ Exported procedure calls ----- */
+SetAirBRad(n) int n; {
+ n = MAX(2,n); abRadius = n; ab2Rad = 2*n; abRad2 = n*n;
+ }
+
+ChgABRadius(d) int d; { SetAirBRad(abRadius + d); }
+
+IMAirBrush() {
+ IModeProcs(obmv,obmv,obclr,airbsplat,nop,airbsplat,nop,nop);
+ }
+
+
+
diff --git a/BEND.C b/BEND.C
new file mode 100644
index 0000000..35ff6c3
--- /dev/null
+++ b/BEND.C
@@ -0,0 +1,189 @@
+/*--------------------------------------------------------------*/
+/* Bend.c */
+/*--------------------------------------------------------------*/
+
+#include <system.h>
+#include <prism.h>
+#include <pnts.h>
+
+#define local static
+#define lfHalf 0x8000
+
+extern PointRec pnts;
+extern SHORT curpen;
+extern struct RastPort tempRP;
+extern BMOB curbr,origBr;
+extern void (*nop)();
+extern SHORT usePen;
+extern void frobsh(),frobmv(),frobclr();
+
+local Point p0,p1,p2;
+local Point q0,q1,q2;
+local SHORT topY,botY,leftX,rightX;
+local SHORT crx,cry;
+
+struct BitMap *frombm, *tobm;
+local BOOL isHoriz;
+
+local void hBendOp(x,y) SHORT x,y; {
+ if (y==cry) return;
+ BltBitMap(frombm,0,y,tobm, x, y, origBr.pict.box.w, 1 ,REPOP,0xff,NULL);
+ cry = y;
+ }
+
+local BoxFromPts(bx) Box *bx; {
+ return(BoxThreePts(bx,q0.x,q0.y,q1.x,q1.y,q2.x,q2.y));
+ }
+
+/* horizontal bend */
+local BOOL BMBendH()
+ {
+ SHORT dx,winc;
+ Box bx;
+ frombm = origBr.pict.bm; tobm = curbr.pict.bm;
+ BoxFromPts(&bx);
+ winc = bx.w - 1;
+ if (q0.x == q2.x) {
+ dx = q1.x - q0.x;
+ winc = ABS(dx)/2; /* increase width by this amount */
+ /* if bending to left, move box in from p1 to curve */
+ if (q1.x<q0.x) bx.x += (-dx-winc);
+ }
+ if (NewSizeBitMap(tobm,frombm->Depth, frombm->BytesPerRow*8 + winc,
+ frombm->Rows)) return(FAIL);
+ SetBitMap(tobm,origBr.xpcolor);
+ cry = - 1;
+ PCurve(q0.x-bx.x,0,q1.x-bx.x,q1.y-q0.y,q2.x-bx.x,q2.y-q0.y,64,hBendOp);
+ return(SUCCESS);
+ }
+
+void vBendOp(x,y) SHORT x,y; {
+ if (x==crx) return;
+ BltBitMap(frombm,x,0,tobm, x, y, 1, origBr.pict.box.h,REPOP,0xff,NULL);
+ crx = x;
+ }
+
+/* vertical bend */
+local BOOL BMBendV() {
+ SHORT hinc;
+ Box bx;
+ SHORT dy;
+ frombm = origBr.pict.bm; tobm = curbr.pict.bm;
+ BoxFromPts(&bx);
+ hinc = bx.h -1;
+ if (q0.y == q2.y) {
+ dy = q1.y - q0.y;
+ hinc = ABS(dy)/2;
+ if (q1.y<q0.y) bx.y += (-dy-hinc);
+ }
+ if (NewSizeBitMap(tobm,frombm->Depth, frombm->BytesPerRow*8,
+ frombm->Rows+hinc)) return(FAIL);
+ SetBitMap(tobm,origBr.xpcolor);
+ crx = - 1;
+ PCurve(0, q0.y - bx.y, q1.x - q0.x, q1.y - bx.y, q2.x - q0.x,
+ q2.y - bx.y,64,vBendOp);
+ return(SUCCESS);
+ }
+
+local XorCurve(x0,y0,x1,y1,x2,y2) SHORT x0,y0,x1,y1,x2,y2; {
+ SHORT svUsePen;
+ TempXOR();
+ svUsePen = usePen;
+ usePen = 0;
+ mCurve(x0,y0,x1,y1,x2,y2);
+ usePen = svUsePen;
+ RestoreMode();
+ }
+
+
+local invHbend() {
+ SHORT dx;
+ q0 = p0; q1 = p1; q2 = p2;
+ if (my<topY) q0.x = mx;
+ else if (my>botY) q2.x = mx;
+ else { q1.x = mx; q1.y = my; }
+ dx = origBr.pict.box.w-1;
+ XorLine(q0.x - dx,q0.y, q0.x,q0.y);
+ XorLine(q2.x - dx,q2.y, q2.x,q2.y);
+ XorCurve(q0.x,q0.y,q1.x,q1.y,q2.x,q2.y);
+ XorCurve(q0.x - dx,q0.y,q1.x - dx,q1.y, q2.x - dx,q2.y);
+ }
+
+local invVbend() {
+ SHORT dy;
+ q0 = p0; q1 = p1; q2 = p2;
+ if (mx<leftX) q0.y = my;
+ else if (mx>rightX) q2.y = my;
+ else { q1.x = mx; q1.y = my; }
+ dy = origBr.pict.box.h-1;
+ XorLine(q0.x, q0.y - dy, q0.x, q0.y);
+ XorLine(q2.x, q2.y - dy, q2.x, q2.y);
+ XorCurve(q0.x, q0.y, q1.x, q1.y, q2.x, q2.y);
+ XorCurve(q0.x, q0.y - dy, q1.x, q1.y - dy, q2.x, q2.y - dy);
+ }
+
+/* button down proc */
+
+local void beginHbend() {
+ p0.x = mx; p0.y = my-curbr.yoffs;
+ p1.x = mx; p1.y = my;
+ p2.x = mx; p2.y = p0.y+origBr.pict.box.h -1;
+ topY = p0.y;
+ botY = p2.y;
+ }
+
+local void beginVbend() {
+ p0.y = my; p0.x = mx-curbr.xoffs;
+ p1.y = my; p1.x = mx;
+ p2.y = my; p2.x = p0.x+origBr.pict.box.w -1;
+ leftX = p0.x;
+ rightX = p2.x;
+ }
+
+local BOOL (*bendbm)();
+
+local endbend() { /* button up proc */
+ ZZZCursor();
+ if ((*bendbm)())
+ { /* memory allocation failure or abort */
+ RestoreBrush();
+ AbortIMode();
+ }
+ else {
+ curbr.pict.box.h = curbr.pict.bm->Rows;
+ curbr.pict.box.w = curbr.pict.bm->BytesPerRow*8;
+ curbr.xoffs = curbr.pict.box.w/2; /* not correct but ... */
+ curbr.yoffs = curbr.pict.box.h/2;
+ if (isHoriz) curbr.yoffs = origBr.yoffs;
+ else curbr.xoffs = origBr.xoffs;
+ if (BMOBMask(&curbr)) { RestoreBrush(); AbortIMode(); }
+ }
+ UnZZZCursor();
+ }
+
+local BOOL PrepBend() {
+ if (curpen != USERBRUSH) return(FAIL);
+ if (SaveBrush(BENT)) return(FAIL);
+ if (CopyBMOBPict(&origBr,&curbr)==FAIL) {RestoreBrush(); return(FAIL); }
+ origBr.xoffs = curbr.xoffs; origBr.yoffs = curbr.yoffs;
+ curbr.xoffs = curbr.pict.box.w-1; curbr.yoffs = curbr.pict.box.h-1;
+ return(SUCCESS);
+ }
+
+void IMHBendBrush(){
+ if (PrepBend()==FAIL) { RevertIMode(); return; }
+ curbr.yoffs>>=1;
+ isHoriz = YES;
+ bendbm = &BMBendH;
+ IModeProcs(frobsh,frobmv,frobclr,beginHbend,invHbend,nop,invHbend,endbend);
+ }
+
+
+void IMVBendBrush() {
+ if (PrepBend()==FAIL) { RevertIMode(); return; }
+ curbr.xoffs >>=1;
+ isHoriz = NO;
+ bendbm = &BMBendV;
+ IModeProcs(frobsh,frobmv,frobclr,beginVbend,invVbend,nop,invVbend,endbend);
+ }
+
diff --git a/BITMAPS.C b/BITMAPS.C
new file mode 100644
index 0000000..c929d5f
--- /dev/null
+++ b/BITMAPS.C
@@ -0,0 +1,238 @@
+/*----------------------------------------------------------------------*/
+/* */
+/* bitmaps.c -- BitMap operations (c) Electronic Arts */
+/* */
+/* 6/22/85 Created Dan Silva */
+/* 7/11/85 Added MakeMask Dan Silva */
+/* 8/1/85 Added prism functions Dan Silva */
+/*----------------------------------------------------------------------*/
+/* Note: all Bitmap allocating functions will first try to free */
+/* the planes of the BitMap. Initially all bm.Plane[] values should */
+/* be set to NULL. */
+/*----------------------------------------------------------------------*/
+
+#include <system.h>
+#include <prism.h>
+#define KPrintF printf
+extern struct RastPort tempRP;
+extern struct TmpRas tmpRas;
+extern BOOL haveWBench;
+
+BOOL dbgalloc = NO;
+
+prbm(bm) struct BitMap *bm; {
+#ifdef DBGBM
+ dprintf("BitMap: bpr=%ld, rows= %ld, deep = %ld \n",
+ bm->BytesPerRow, bm->Rows, bm->Depth);
+#endif
+ }
+
+static AllocErr(s) char *s; {
+#ifdef DBGBM
+ if (dbgalloc) dprintf(" Alloc or Freeing error in %s\n",s);
+#endif
+ }
+
+#define MINAVAILMEM 13000
+
+/* Allocate planes seperately-- wont work for BOBs */
+/* This routine Does NOT free planes first */
+TmpAllocBitMap(bm) struct BitMap *bm; {
+ SHORT i;
+ int psize = BMPlaneSize(bm);
+ setmem(bm->Planes, 8*sizeof(LONG), 0);
+ for (i=0; i<bm->Depth; i++) {
+ bm->Planes[i]= (PLANEPTR)ChipAlloc(psize);
+ if (bm->Planes[i]==NULL){
+ if (dbgalloc){
+#ifdef DBGBM
+ dprintf(" AllocBitmap failure: \n");
+ prbm(bm);
+#endif
+ }
+ FreeBitMap(bm);
+ return(FAIL);
+ }
+ }
+ return(SUCCESS);
+ }
+
+AllocBitMap(bm) struct BitMap *bm; {
+ BOOL res = TmpAllocBitMap(bm);
+ if (res==FAIL) return(FAIL);
+ if (AvailMem(MEMF_CHIP|MEMF_PUBLIC) < MINAVAILMEM) {
+ FreeBitMap(bm);
+ return(FAIL);
+ }
+ return(SUCCESS);
+ }
+
+UBYTE *BMAllocMask(bm) struct BitMap *bm; {
+ return( (UBYTE *) ChipAlloc(bm->BytesPerRow * bm->Rows) );
+ }
+
+FreeBitMap(bm) struct BitMap *bm; {
+ SHORT i;
+ for (i=0; i<bm->Depth; i++) if (bm->Planes[i] != NULL) {
+ DFree(bm->Planes[i]);
+ bm->Planes[i] = NULL;
+ }
+ }
+
+NewSizeBitMap(bm,deep,w,h) struct BitMap *bm; SHORT deep,w,h; {
+ int ret;
+ int bw = BytesNeeded(w);
+ if ((bm->Planes[0] != NULL)&&(bm->Depth==deep)&&
+ (bm->BytesPerRow==bw)&&(bm->Rows==h)) return(0);
+ FreeBitMap(bm);
+ bm->Depth = deep;
+ bm->BytesPerRow = bw;
+ bm->Rows = h;
+ ret = AllocBitMap(bm);
+ if (ret) AllocErr("NewSizeBitMap");
+ return(ret);
+ }
+
+ClearBitMap(bm) struct BitMap *bm; {
+ SHORT i;
+ for (i=0; i<bm->Depth; i++)
+ BltClear(bm->Planes[i],(bm->Rows<<16)+bm->BytesPerRow, 3);
+ }
+
+SetBitMap(bm,color) struct BitMap *bm; SHORT color; {
+ tempRP.BitMap = bm;
+ SetRast(&tempRP,color);
+ }
+
+/* USE WITH CAUTION: WILL OVERWRITE Planes[] POINTERS */
+BlankBitMap(bm) struct BitMap *bm; {
+ setmem(bm, sizeof(struct BitMap), 0);
+ }
+
+/* This assures that bitmap b is the same size as a */
+MakeEquivBM(a,b) struct BitMap *a,*b; {
+ int ret;
+ if (ret=NewSizeBitMap(b,a->Depth,a->BytesPerRow*8,a->Rows))
+ AllocErr("MakeEquivBM");
+ return(ret);
+ }
+
+FillBitMap(pb,v) struct BitMap *pb; int v; {
+ SHORT i;
+ for (i=0; i<pb->Depth; i++) setmem(pb->Planes[i],BMPlaneSize(pb),v);
+ }
+
+/* this results in two totally identical BitMap structures */
+/* pointing at the same data */
+DupBitMap(a,b) struct BitMap *a,*b; {
+ FreeBitMap(b);
+ movmem(a,b,sizeof(struct BitMap));
+ }
+
+/* this makes a copy of the data too */
+CopyBitMap(a,b) struct BitMap *a,*b; {
+ if(MakeEquivBM(a,b)){ AllocErr("CopyBitMap"); return(FAIL); }
+ WaitBlit();
+ BltBitMap(a,0,0,b,0,0,a->BytesPerRow*8,a->Rows,REPOP,0xff,NULL);
+ return(SUCCESS);
+ }
+
+/*--------------------------------------------------------------*/
+/* */
+/* Make Mask */
+/* */
+/*--------------------------------------------------------------*/
+/*
+
+This makes masks for a bitmap associated with a particular
+"special" color. It will either make a mask which has 1's in it ONLY
+where the bitmap has that special color (a POSITIVE mask) or it will
+make a mask which has 1's in it where the bitmap is NOT that special
+color ( a NEGATIVE mask ).
+
+To make a positive mask for the special color 10110,
+where p<i> is the <i>th plane of the Bitmap:
+
+ mask = p4 & (^p3) & p2 & p1 & (^p0);
+
+To a negative mask mask for a Bitmap for a particular "transparent"
+color, you want a 1 where the color of the bitmap is NOT the
+transparent color, zero where it IS is the transparent color .
+
+ e.g. if xpcol = 10110 then want
+
+ mask = (^p4) | p3 | (^p2) | (^p1) | p0
+
+---------------------------------------------------------------------**/
+MakeMask(bm,mask,color,sign)
+ struct BitMap *bm; /* bitmap for which mask is to be made*/
+ UBYTE *mask; /* holds the result: should be as big as
+ one plane of bm */
+ SHORT color; /* special color */
+ BOOL sign; /* TRUE = positive, FALSE = negative */
+ {
+ SHORT depth,i,mt,bltSize;
+ UBYTE op1,op2;
+ depth = bm->Depth;
+ bltSize = BlitSize(bm->BytesPerRow,bm->Rows);
+ if (sign) { mt = REPOP; op1 = ANDOP; op2 = NOTANDOP; }
+ else { mt = NOTOP; op1 = NOTOROP; op2 = OROP; }
+ if (!(color&1)) mt ^= 0xff;
+ for (i=0; i<depth; i++) {
+ BltABCD(NULL, bm->Planes[i], mask, mask, bltSize, mt);
+ color >>= 1;
+ mt = (color&1) ? op1: op2;
+ }
+ WaitBlit();
+ }
+
+
+#ifdef theOldWay
+MakeMask(bm,mask,color,pos)
+ struct BitMap *bm; /* bitmapr for which mask is to be made*/
+ UBYTE *mask; /* should be as big as one plane of bm */
+ SHORT color; /* special color */
+ BOOL pos; /* TRUE = positive, FALSE = negative */
+
+ {
+ struct BitMap mbm;
+ SHORT depth,i,mt,w;
+ PLANEPTR plane0;
+ UBYTE op1,op2;
+ mbm.BytesPerRow = bm->BytesPerRow;
+ mbm.Rows = bm->Rows; mbm.Depth = 1; mbm.Flags = 0;
+ mbm.Planes[0] = (PLANEPTR)mask;
+ depth = bm->Depth;
+ w = bm->BytesPerRow*8;
+ if (pos) { SetBitMap(&mbm,0xff); op1 = ANDOP; op2 = NOTANDOP; }
+ else { ClearBitMap(&mbm); op1 = NOTOROP; op2 = OROP; }
+ bm->Depth = 1;
+ plane0 = bm->Planes[0];
+ for (i=0; i<depth; i++) {
+ bm->Planes[0] = bm->Planes[i];
+ mt = (color&1) ? op1: op2;
+ WaitBlit();
+ BltBitMap(bm,0,0,&mbm,0,0,w,mbm.Rows,mt,0x01,NULL);
+ color >>= 1;
+ }
+ WaitBlit();
+ bm->Depth = depth;
+ bm->Planes[0] = plane0;
+ }
+#endif
+/* Changes all pixels in a bitmap which are color number "acol" to
+ be color number "bcol" */
+
+
+BMMapColor(sbm,dbm,acol,bcol) struct BitMap *sbm, *dbm; SHORT acol,bcol; {
+ BYTE *tmpmask = tmpRas.RasPtr;
+ SHORT w = sbm->BytesPerRow*8;
+ MakeMask(sbm,tmpmask,acol,POSITIVE);
+ tempRP.BitMap = dbm;
+ SetAPen(&tempRP,bcol);
+ SetDrMd(&tempRP,JAM1);
+ BltTemplate(tmpmask, 0, sbm->BytesPerRow, &tempRP, 0,0,w,sbm->Rows);
+ }
+
+
+
diff --git a/BLEND.C b/BLEND.C
new file mode 100644
index 0000000..1155820
--- /dev/null
+++ b/BLEND.C
@@ -0,0 +1,79 @@
+/*----------------------------------------------------------------------*/
+/* BLEND mode: */
+/* */
+/*----------------------------------------------------------------------*/
+
+#include <system.h>
+#include <prism.h>
+
+#define local
+extern BoxBM temp;
+extern BOOL erasing,firstDown;
+extern Range *shadeRange;
+extern struct TmpRas tmpRas;
+
+local UBYTE *blSmask, *blDmask=0;/* used by blend to point at the mask for the save.bm */
+
+void DoBlend(ob,canv,clip) BMOB *ob; BoxBM *canv; Box *clip; {
+ UBYTE *wmask, *tmp;
+ if ( BMPlaneSize(ob->pict.bm) > tmpRas.Size/3) return;
+ if (SaveSizeBM(temp.bm, ob)) return;
+ temp.box = ob->pict.box;
+ CopyBoxBM(canv, &temp, &temp.box, clip, REPOP);
+ if (firstDown) {
+ blDmask = tmpRas.RasPtr +tmpRas.Size/3;
+ blSmask = tmpRas.RasPtr + 2*tmpRas.Size/3;
+ }
+ MaskRange(temp.bm, blDmask, tmpRas.RasPtr, shadeRange->low, shadeRange->high);
+ if (!firstDown) {
+ wmask = ob->mask;
+ if (shadeRange!=NULL) {
+ wmask = blSmask;
+ BltABCD(blSmask,blDmask,ob->mask,wmask,BMBlitSize(ob->pict.bm),0x80);
+ }
+ BlendBM(temp.bm, ob->save.bm, tmpRas.RasPtr);
+ MBSaveAtPict(ob,canv,clip,wmask);
+ }
+ else firstDown = NO;
+ tmp = blSmask; blSmask= blDmask; blDmask = tmp;
+ RelocBoxBM(&temp,&ob->save); /* save = temp */
+ }
+
+#define yA 0xf0
+#define yB 0xcc
+#define yC 0xaa
+#define nA 0x0f
+#define nB 0x33
+#define nC 0x55
+#define A_AND_B yA&yB
+
+/* sum bit is on if odd number of sources are 1 */
+#define ADD_ABC (yA&nB&nC)|(nA&yB&nC)|(nA&nB&yC)|(yA&yB&yC)
+
+/* carry if at least 2 of three sources are 1's */
+#define CARRY_ABC (yA&yB&nC)|(yA&nB&yC)|(nA&yB&yC)|(yA&yB&yC)
+#define POST_CARRY_ABC 0xB2 /* black magic.. trust me */
+
+/* b = (a + b)/2 */
+BlendBM(a,b,car)
+ struct BitMap *a, *b;
+ UBYTE *car; /* one plane scratch area( carry bit) */
+ {
+ int i;
+ int bpr = a->BytesPerRow;
+ int h = a->Rows;
+ int depth = a->Depth;
+ int bsz = BlitSize(bpr,h);
+
+ /* AND low order bits to get initial carry */
+ BltABCD(a->Planes[0], b->Planes[0], NULL, car, bsz, A_AND_B);
+
+ for (i=1; i<depth; i++) {
+ /* add i'th bit and carry, store as new i-1'th bit */
+ BltABCD(a->Planes[i], b->Planes[i], car, b->Planes[i-1],bsz, ADD_ABC );
+ /* compute new carry bit */
+ BltABCD(a->Planes[i], b->Planes[i], car,
+ (i == (depth-1))? b->Planes[i] : car, bsz, CARRY_ABC);
+ }
+ }
+
diff --git a/BLITOPS.C b/BLITOPS.C
new file mode 100644
index 0000000..efda755
--- /dev/null
+++ b/BLITOPS.C
@@ -0,0 +1,196 @@
+/*----------------------------------------------------------------------*/
+/* */
+/* Blitops.c (c) Electronic Arts 1985 */
+/* */
+/* */
+/*----------------------------------------------------------------------*/
+
+#include <system.h>
+#include <prism.h>
+
+#undef sx
+#undef sy
+
+#define local static
+
+USHORT masks[17] = {
+ 0xffff,0x7fff,0x3fff,0x1fff,
+ 0x0fff,0x07ff,0x03ff,0x01ff,
+ 0x00ff,0x007f,0x003f,0x001f,
+ 0x000f,0x0007,0x0003,0x0001,0000
+ };
+
+BlitterRegs *ar = (BlitterRegs *)0xDFF040;
+
+#define yA 0xf0
+#define yB 0xcc
+#define yC 0xaa
+#define nA 0x0f
+#define nB 0x33
+#define nC 0x55
+
+#define USEA 0x0800
+#define USEB 0x0400
+#define USEC 0x0200
+#define USED 0x0100
+#define MASKWRITE 0x0F00 /* USEA|USEB|USEC|USED */
+#define CONSTWRITE 0x0B00 /* USEA|USEC|USED */
+
+#define COPYA 0xf0 /* minterm = A */
+
+#define WordOffs(x) (((x)>>3)&0xfffe)
+
+extern UWORD *curFilPat;
+
+/*----------------------------------------------------------------------*/
+/* HLineBlt: fill a horizontal span of pixels with the current area */
+/* fill pattern. */
+/* NOTE: this should be changed to use rp's minterms */
+/*----------------------------------------------------------------------*/
+HLineBlt(rp,lx,y,rx,mint) struct RastPort *rp; int lx,y,rx;SHORT mint; {
+ int bytes,lwrd,i;
+ LONG offset;
+ SHORT blsize,apen;
+ UWORD *patadr;
+ struct BitMap *dbm = rp->BitMap;
+
+ lwrd = WordOffs(lx);
+ bytes = WordOffs(rx)- lwrd + 2;
+ offset = y*dbm->BytesPerRow + lwrd;
+ blsize = (1<<6)|(bytes>>1);
+ WaitBlit();
+ OwnBlitter();
+ ar->fwmask = masks[lx&15];
+ ar->lwmask = ~masks[(rx&15)+1];
+ ar->bltcon0 = USEC|USED|mint;
+ ar->bltcon1 = 0;
+ ar->adata = 0xffff;
+ ar->bltmdd = ar->bltmdc = dbm->BytesPerRow - bytes;
+ if (curFilPat) {
+ patadr = curFilPat + (y&PATMOD);
+ for (i = 0; i< dbm->Depth; i++) {
+ WaitBlit();
+ ar->bdata = curFilPat?*patadr: 0xFFFF;
+ patadr += PATHIGH;
+ ar->bltptd = ar->bltptc = dbm->Planes[i] + offset;
+ ar->bltsize = blsize; /* start the blit */
+ }
+ }
+ else { /* no fill pattern: solid color */
+ apen = rp->FgPen;
+ for (i = 0; i< dbm->Depth; i++) {
+ WaitBlit();
+ ar->bdata = (apen&1)?0xffff: 0;
+ ar->bltptd = ar->bltptc = dbm->Planes[i] + offset;
+ ar->bltsize = blsize; /* start the blit */
+ apen >>= 1;
+ }
+ }
+ WaitBlit();
+ DisownBlitter();
+ }
+
+
+#ifdef oldversion
+/*----------------------------------------------------------------------*/
+/* HLineBlt: fill a horizontal span of pixels with the current area */
+/* fill pattern. */
+/* NOTE: this should be changed to use rp's minterms */
+/*----------------------------------------------------------------------*/
+HLineBlt(rp,lx,y,rx,mint) struct RastPort *rp; int lx,y,rx;SHORT mint; {
+ int bytes,lwrd,i;
+ LONG offset;
+ SHORT pattern,blsize,bit,apen,bpen,wrd;
+ struct BitMap *dbm = rp->BitMap;
+
+ lwrd = WordOffs(lx);
+ bytes = WordOffs(rx)- lwrd + 2;
+ offset = y*dbm->BytesPerRow + lwrd;
+ if (rp->AreaPtrn != NULL)
+ pattern = rp->AreaPtrn[y&((1<<rp->AreaPtSz)-1)];
+ else pattern = 0xffff;
+ apen = rp->FgPen;
+ bpen = rp->BgPen;
+ blsize = (1<<6)|(bytes>>1);
+ WaitBlit();
+ OwnBlitter();
+ ar->fwmask = masks[lx&15];
+ ar->lwmask = ~masks[(rx&15)+1];
+ ar->bltcon0 = USEC|USED|mint;
+ ar->bltcon1 = 0;
+ ar->adata = 0xffff;
+ ar->bltmdd = ar->bltmdc = dbm->BytesPerRow - bytes;
+ bit = 1;
+ for (i = 0; i< dbm->Depth; i++) {
+ wrd = 0;
+ if (bit&apen) wrd = pattern;
+ if (bit&bpen) wrd |= (~pattern);
+ WaitBlit();
+ ar->bdata = wrd;
+ ar->bltptd = ar->bltptc = dbm->Planes[i] + offset;
+ ar->bltsize = blsize; /* start the blit */
+ bit <<= 1;
+ }
+ WaitBlit();
+ DisownBlitter();
+ }
+#endif
+
+BltABCD(a, b, c, d, bltSize, minterm)
+ UBYTE *a,*c,*b,*d;
+ SHORT bltSize;
+ UBYTE minterm;
+ {
+ SHORT con0;
+ con0 = (a?USEA:0)|(b?USEB:0)|(c?USEC:0)|USED|(minterm&0xff);
+ WaitBlit();
+ OwnBlitter();
+ ar->fwmask = 0xffff;
+ ar->lwmask = 0xffff;
+ ar->bltcon0 = con0;
+ ar->bltcon1 = 0;
+ ar->bltmda = ar->bltmdb = ar->bltmdc = ar->bltmdd = 0;
+ ar->bltpta = a;
+ ar->bltptb = b;
+ ar->bltptc = c;
+ ar->bltptd = d;
+ ar->bltsize = bltSize; /* start the hardware blit */
+ WaitBlit();
+ WaitBlit();
+ DisownBlitter();
+ }
+
+#define A_AND_B yA&yB
+
+/* sum bit is on if odd number of sources are 1 */
+#define ADD_ABC (yA&nB&nC)|(nA&yB&nC)|(nA&nB&yC)|(yA&yB&yC)
+
+/* carry if at least 2 of three sources are 1's */
+#define CARRY_ABC (yA&yB&nC)|(yA&nB&yC)|(nA&yB&yC)|(yA&yB&yC)
+#define POST_CARRY_ABC 0xB2 /* black magic.. trust me */
+
+
+
+#ifdef usingAddBM
+/* b += a */
+AddBM(a,b,car)
+ struct BitMap *a, *b;
+ UBYTE *car; /* one plane scratch area( carry bit) */
+ {
+ int i;
+ int bpr = a->BytesPerRow;
+ int h = a->Rows;
+ int depth = a->Depth;
+ int bsz = BlitSize(bpr,h);
+ /* carry = 0 */
+ BltClear(car,(a->Rows<<16)+a->BytesPerRow, 3);
+ for (i=0; i<depth; i++) {
+ /* --- add i'th bit and carry, store as new b[i] */
+ BltABCD(a->Planes[i], b->Planes[i], car, b->Planes[i], bsz, ADD_ABC );
+ /* --- compute new carry bit */
+ BltABCD(a->Planes[i], b->Planes[i], car, car, bsz, POST_CARRY_ABC);
+ }
+ }
+#endif
+
+
diff --git a/BLITREGS.H b/BLITREGS.H
new file mode 100644
index 0000000..5cb6697
--- /dev/null
+++ b/BLITREGS.H
@@ -0,0 +1,23 @@
+
+typedef struct {
+ USHORT bltcon0,bltcon1,fwmask,lwmask;
+ UBYTE *bltptc,*bltptb,*bltpta,*bltptd;
+ USHORT bltsize;
+ SHORT ioskip2[3];
+ SHORT bltmdc,bltmdb,bltmda,bltmdd;
+ SHORT ioskip3[4];
+ USHORT cdata,bdata,adata;
+ } BlitterRegs;
+
+BlitterRegs *ar = (BlitterRegs *)0xDFF040;
+
+struct bltnode myNode;
+
+#define USEA 0x0800
+#define USEB 0x0400
+#define USEC 0x0200
+#define USED 0x0100
+#define MASKWRITE 0x0F00 /* USEA|USEB|USEC|USED */
+#define CONSTWRITE 0x0B00 /* USEA|USEC|USED */
+
+#define COPYA 0xf0 /* minterm = A */
diff --git a/BMOB.C b/BMOB.C
new file mode 100644
index 0000000..a85a343
--- /dev/null
+++ b/BMOB.C
@@ -0,0 +1,416 @@
+/*--------------------------------------------------------------*/
+/* */
+/* bmob.c Movable, Sizable Bitmap Object */
+/* */
+/* 8-14-85 created Dan Silva */
+/* 8-15-85 BoxBM version Dan Silva */
+/*--------------------------------------------------------------*/
+#include <system.h>
+#include <prism.h>
+
+#define local static
+
+extern UBYTE *BMAllocMask();
+
+extern BOOL Painting;
+extern BoxBM canvas;
+extern Box clipBox;
+extern struct RastPort *curRP, tempRP;
+extern SHORT curFormat, curxpc, xShft, yShft, curDepth;
+extern SHORT curpen;
+extern Range *shadeRange;
+extern struct TmpRas tmpRas;
+
+extern SHORT dbgbmob;
+extern struct BitMap tmpbm;
+extern BoxBM temp;
+extern struct BitMap tmpbm2;
+extern BoxBM temp2;
+
+/*--------------------------------------------------------------*/
+/* Debug printout stuff */
+#ifdef DebUG
+
+prlf() { dprintf("\n"); }
+prBox(b) Box *b; {
+ dprintf(" Box :(%ld, %ld, %ld, %ld)\n", b->x, b->y, b->w, b->h);
+ }
+prBoxBM(bbm) BoxBM *bbm;
+ { dprintf("BoxBM:"); prBox(&bbm->box); prbm(bbm->bm); }
+
+XBltBitMap(sbm,sx,sy,dbm,dx,dy,w,h,mint,mask,tmp)
+ struct BitMap *sbm,*dbm; SHORT sx,sy,dx,dy,w,h;
+ UBYTE mint,mask, *tmp; {
+/* if (dbgbmob) */
+ dprintf("BltBitMap, src xy = %ld,%ld, dst xy = %ld, %ld, w,h=%ld,%ld\n",sx,sy,dx,dy,w,h);
+ BltBitMap(sbm,sx,sy,dbm,dx,dy,w,h,mint,mask,tmp);
+ }
+
+#endif
+
+/**
+dbgbm(bm) struct BitMap *bm; {
+ if (dbgbmob)
+ BltBitMap(bm,0,0,canvas.bm,0,0,bm->BytesPerRow*8,bm->Rows,REPOP,0xff,NULL);
+ }
+**/
+
+/*--------------------------------------------------------------*/
+/* all the boxes are relative to the same coordinate system */
+CopyBoxBM(src,dst,mb,clip,mint)
+ BoxBM *src; /* source */
+ BoxBM *dst; /* destination */
+ Box *mb; /* box to be moved */
+ Box *clip; /* clipping box */
+ SHORT mint; /* minterm */
+ {
+ Box cb;
+ BOOL res;
+ if (clip) res = BoxAnd(&cb,mb,clip);
+ else {res = YES; cb = *mb; }
+ if (res) {
+ WaitBlit();
+ BltBitMap(src->bm, cb.x - src->box.x, cb.y - src->box.y, dst->bm,
+ cb.x - dst->box.x, cb.y - dst->box.y, cb.w, cb.h, mint, 0xff, NULL);
+ WaitBlit();
+ }
+ }
+
+/*----------------------------------------------------------------------*/
+/* BoxNot creates an array of four boxes "n" which represent the */
+/* complement of the input box "b": n = NOT(b) */
+/*----------------------------------------------------------------------*/
+#define BIG 25000
+BoxNot(n, b) Box *n, *b; {
+ SHORT xm = b->x + b->w;
+ SHORT ym = b->y + b->h;
+ n->x = b->x; n->y = -BIG; n->w = BIG; n->h = BIG + b->y; n++;
+ n->x = xm; n->y = b->y; n->w = BIG; n->h = BIG; n++;
+ n->x = -BIG; n->y = ym; n->w = BIG + xm; n->h = BIG; n++;
+ n->x = -BIG; n->y = -BIG; n->w = BIG + b->x; n->h = BIG + ym;
+ }
+
+/*----------- Synchronize with the vertical beam motion */
+
+#ifdef awawawa
+void WaitBeam(n) SHORT n; {
+ SHORT vb,tol;
+ /* WaitBeam causes problems with interlace so skip it*/
+ n = MAX(0, MIN(256,n));
+ if (curFormat == 2) return;
+ tol = curFormat?100:50;
+ for (;;) {
+ vb = VBeamPos() - n;
+ if (vb<0) vb += 256;
+ if (( 0 <= vb) && ( vb < tol)) return;
+ }
+ }
+#endif
+
+extern PaintMode paintMode;
+extern BOOL erasing;
+extern BOOL firstDown;
+extern SHORT lastSmX, lastSmY;
+
+/* make bm same size as pict bm of object, curdepth in depth */
+SaveSizeBM(bm,ob) struct BitMap *bm; BMOB *ob; {
+ return(NewSizeBitMap(bm, curDepth, ob->pict.box.w, ob->pict.box.h));
+ }
+
+int BMBlitSize(bm) struct BitMap *bm; {
+ return((int) BlitSize(bm->BytesPerRow, bm->Rows));
+ }
+
+
+/*----------------------------------------------------------------------*/
+/* SMEAR mode: */
+/*----------------------------------------------------------------------*/
+
+/* First some utilities .... */
+
+/* maskblit the save.bm at the CURRENT position */
+MBSaveAtPict(ob,canv,clip,mask)
+ BMOB *ob; BoxBM *canv; Box *clip; UBYTE *mask; {
+ Box b;
+ BoxAnd(&b,&ob->save.box,clip);
+ b.x += ob->pict.box.x - ob->save.box.x;
+ b.y += ob->pict.box.y - ob->save.box.y;
+ MaskBlit( ob->save.bm, &ob->pict.box, mask, canv->bm,
+ &canv->box, &b, clip, COOKIEOP, tmpRas.RasPtr, 0xff,0);
+ }
+
+RelocBoxBM(fr,to) BoxBM *fr,*to; {
+ DupBitMap(fr->bm,to->bm);
+ BlankBitMap(fr->bm);
+ to->box = fr->box;
+ }
+
+void DoSmear(ob,canv,clip) BMOB *ob; BoxBM *canv; Box *clip; {
+ if (SaveSizeBM(temp.bm, ob)) return;
+ temp.box = ob->pict.box;
+ CopyBoxBM(canv, &temp, &temp.box, clip, REPOP);
+ if (!firstDown) MBSaveAtPict(ob,canv,clip,ob->mask);
+ else firstDown = NO;
+ RelocBoxBM(&temp,&ob->save); /* save = temp */
+ }
+
+#ifdef DOADD
+void DoAdd(ob,canv,clip) BMOB *ob; BoxBM *canv; Box *clip; {
+ if (SaveSizeBM(temp.bm, ob)) return;
+ temp.box = ob->pict.box;
+ CopyBoxBM(canv, &temp, &temp.box, clip, REPOP);
+ AddBM(ob->pict.bm, temp.bm, tmpRas.RasPtr);
+ CopyBoxBM(&temp,camv, &temp.box,clip,REPOP);
+ }
+#endif
+
+
+#define USEMSK 0x100
+#define USEPCT 0x200
+#define SPECIAL 0x400
+
+USHORT paintProps[NPaintModes] = {
+ USEPCT| USEMSK| COOKIEOP, /* Mask */
+ USEMSK| COOKIEOP, /* Color */
+ USEPCT| REPOP, /* Replace */
+ SPECIAL, /* Smear */
+ SPECIAL, /* Shade */
+ SPECIAL, /* Blend */
+ USEMSK| COOKIEOP, /* Cycle Paint*/
+ USEPCT| USEMSK| XORMASK /* Xor */
+ };
+
+/* pens don't have Picture: just mask so they do the best they can
+ in Mask and Replace modes */
+USHORT penModes[NPaintModes] = {
+ Color, /* Mask */
+ Color, /* Color */
+ Color, /* Replace */
+ Smear, /* Smear */
+ Shade, /* Shade */
+ Blend, /* Blend */
+ Color, /* Cycle Paint*/
+ Xor /* Xor */
+ };
+
+#define ERASPROPS USEMSK|COOKIEOP
+
+
+
+/*--------------------------------------------------------------*/
+/* Paint the object onto the canvas through the clip box */
+/* using "paintMode", the current global painting mode */
+/*--------------------------------------------------------------*/
+void PaintOb(ob, canv, clip) BMOB *ob; BoxBM *canv; Box *clip; {
+ UBYTE *tmpMask = NULL;
+ SHORT pluse,pldef,props;
+ PaintMode pntMode;
+ tmpMask = tmpRas.RasPtr;
+ pntMode = paintMode;
+ if (curpen!=USERBRUSH) pntMode = penModes[pntMode];
+ if ((pntMode==Smear)||(pntMode==Blend)) {
+ if (erasing||!Painting) pntMode = Color;
+ }
+ props = paintProps[pntMode];
+ pluse = 0;
+ if (erasing) {
+ if (pntMode==Replace) { PFillBox(&ob->pict.box); return; }
+ else if (pntMode!=Shade)
+ { props = ERASPROPS; pldef = curxpc; }
+ }
+ else if (props&USEPCT) pluse = ob->planeUse;
+ else { pldef = curRP->FgPen; }
+ if (props&SPECIAL) switch(pntMode) {
+ case Shade: DoShade(ob,canv,clip); break;
+ case Smear: DoSmear(ob,canv,clip); break;
+ case Blend: DoBlend(ob,canv,clip); break;
+ }
+ else if (props&USEMSK) {
+ if ((pntMode==Xor)&!erasing) pldef = 0xff;
+ MaskBlit(ob->pict.bm, &ob->pict.box,ob->mask,canv->bm,&canv->box,
+ &ob->pict.box,clip, props&0xff, tmpMask,pluse,pldef);
+ }
+ else CopyBoxBM(&ob->pict, canv,&ob->pict.box, clip,props&0xff);
+ }
+
+/*---Create a BoxBM type object, Copying a rectangle of bits from curRP*/
+/* assumes pict.bm and save.bm already point at BitMap structs */
+
+SHORT ExtractBMOB(ob,bx,xoff,yoff)
+ BMOB *ob; /* object to be created */
+ Box *bx; /* bounds of object in curRP */
+ int xoff,yoff; /* offset of handle from u.l. of source */
+ {
+ if (NewSizeBitMap(ob->pict.bm, curDepth, bx->w, bx->h)) return(FAIL);
+
+/** put in AllocMem instead
+ if (AvailMem(MEMF_PUBLIC|MEMF_CHIP) < 12000) {
+ FreeBitMap(ob->pict.bm);
+ return(FAIL);
+ }
+**/
+ ob->pict.box = *bx;
+ ob->save.box = *bx;
+ DFree(ob->mask);
+ ob->mask = BMAllocMask(ob->pict.bm);
+ if (ob->mask == NULL) { FreeBitMap(ob->pict.bm); return(FAIL);}
+
+ SetBitMap(ob->pict.bm, curxpc);
+ CopyBoxBM(&canvas,&ob->pict, &ob->pict.box, &clipBox, REPOP);
+ MakeMask(ob->pict.bm,ob->mask, curxpc, NEGATIVE);
+ ob->minTerm = COOKIEOP;
+ ob->planeUse = 0xff;
+ ob->planeDef = 0;
+ ob->flags = 0;
+ ob->xoffs = xoff; ob->yoffs = yoff;
+ ob->xpcolor = curxpc;
+ return(SUCCESS);
+ }
+
+/*--------------------------------------------------------------*/
+
+FreeBMOB(ob) BMOB *ob; {
+ FreeBitMap(ob->pict.bm);
+ FreeBitMap(ob->save.bm);
+ FreeBitMap(&tmpbm); /* just being compulsive */
+ DFree(ob->mask);
+ }
+
+/* this needs to get called on button up in smear mode */
+BMOBFreeTmp() { FreeBitMap(&tmpbm); }
+
+BMOBMask(ob) BMOB *ob; {
+ DFree(ob->mask);
+ ob->mask = (UBYTE *)BMAllocMask(ob->pict.bm);
+ if (ob->mask==NULL) return(FAIL);
+ MakeMask(ob->pict.bm,ob->mask,ob->xpcolor,NEGATIVE);
+ return(SUCCESS);
+ }
+
+
+BMOBNewSize(ob,d,w,h) BMOB *ob; SHORT d,w,h; {
+ if (NewSizeBitMap(ob->pict.bm,d,w,h)) return(FAIL);
+ ob->pict.box.w = w;
+ ob->pict.box.h = h;
+ DFree(ob->mask);
+ ob->mask = (UBYTE *)BMAllocMask(ob->pict.bm);
+ if (ob->mask==NULL){ FreeBitMap(ob->pict.bm); return(FAIL); }
+ return(SUCCESS);
+ }
+
+
+local InvSaveBox(ob) BMOB *ob; {
+#ifdef DBGSTR
+ dprintf(" InvSaveBox ... \n");
+#endif
+ TempXOR();
+ PThinFrame(&ob->save.box);
+ RestoreMode();
+ }
+
+local void ShowBMOB(ob) BMOB *ob; {
+ if (ob->flags&SHOWING) return;
+ ob->save.box = ob->pict.box;
+ if (NewSizeBitMap(ob->save.bm, curDepth, ob->pict.box.w,ob->pict.box.h))
+ {
+ ob->flags |= TOOBIGTOPAINT;
+ InvSaveBox(ob);
+ }
+ else {
+ CopyBoxBM(&canvas, &ob->save, &ob->save.box, &clipBox, REPOP);
+ PaintOb(ob,&canvas,&clipBox);
+ }
+ ob->flags |= SHOWING;
+ }
+
+
+void ClearBMOB(ob) BMOB *ob; {
+ if (!(ob->flags&SHOWING)) return;
+ if (ob->flags&TOOBIGTOPAINT) {
+ InvSaveBox(ob);
+ ob->flags &= (~TOOBIGTOPAINT);
+ }
+ else CopyBoxBM(&ob->save, &canvas, &ob->save.box, &clipBox, REPOP);
+ FreeBitMap(ob->save.bm);
+ FreeBitMap(&tmpbm);
+ ob->flags &= (~SHOWING);
+ }
+
+CheapMove(ob) BMOB *ob; {
+#ifdef DBGSTR
+ dprintf("Cheap move... \n");
+#endif
+ ClearBMOB(ob); /* so do economy version */
+ ShowBMOB(ob);
+ }
+
+/* updates the screen for a BMOB that has changed position or size
+ pict is it's new position, and saves it's old one */
+
+void ChangeBMOB(ob) BMOB *ob;{
+ SHORT i;
+ Box c, *d, notb[4];
+ Box *new = &ob->pict.box, *old = &ob->save.box;
+ if (!(ob->flags&SHOWING)) ShowBMOB(ob);
+ else {
+ if ((ob->flags&TOOBIGTOPAINT)||
+ ( NewSizeBitMap(temp.bm, curDepth, new->w, new->h)))
+ { CheapMove(ob); return; }
+ temp.box = *new;
+
+ /*----- copy intersection of old and new to new */
+ CopyBoxBM(&ob->save, &temp, old, new, REPOP);
+
+ /* -----copy the newly covered areas (new-old) from scrn to new */
+ BoxNot(&notb, old);
+ for (i=0, d = &notb[0]; i<4; i++,d++) if (BoxAnd(&c,d,new))
+ CopyBoxBM(&canvas, &temp, &c, &clipBox, REPOP);
+
+ /*-----fix up the uncovered areas (old-new) on the screen */
+ BoxNot(&notb, new);
+ for (i=0, d = &notb[0]; i<4; i++,d++) if (BoxAnd(&c,d,old))
+ CopyBoxBM(&ob->save, &canvas, &c, &clipBox, REPOP);
+
+ /*-----save an unpolluted copy of the area the object will cover */
+ if (CopyBitMap(temp.bm,ob->save.bm)) {
+ /* stretching: couldn't alloc save.bm-- must be stretching */
+#ifdef DBGSTR
+ dprintf(" ChangeBM: Couldnt alloc save.bm \n");
+#endif
+ DupBitMap(temp.bm, ob->save.bm);
+ ob->save.box = ob->pict.box;
+ BlankBitMap(temp.bm);
+ CheapMove(ob);
+ return;
+ }
+
+ /*-----paint object onto background in temp */
+ PaintOb(ob,&temp,NULL);
+
+ /*-----copy updated area to screen, synced with vertical retrace */
+/* WaitBeam( new->y + new->h ); */
+
+#ifdef DOLAYERS
+ tempRP.BitMap = &tmpbm;
+ /* ----play the layers game:--- */
+ ClipBlit(&tempRP,0,0,curRP,new->x,new->y,new->w,new->h,REPOP);
+#else
+ /* use my own clipping */
+ CopyBoxBM(&temp, &canvas, new, &clipBox, REPOP);
+#endif
+ }
+ ob->save.box = ob->pict.box;
+ }
+
+local PosBMOB(ob,nx,ny) BMOB *ob; SHORT nx,ny; {
+ ob->pict.box.x = nx - ob->xoffs;
+ ob->pict.box.y = ny - ob->yoffs;
+ }
+
+MoveBMOB(ob,nx,ny) BMOB *ob; SHORT nx,ny; { PosBMOB(ob,nx,ny); ChangeBMOB(ob); }
+
+DispBMOB(ob,nx,ny) BMOB *ob; SHORT nx,ny; {
+ PosBMOB(ob,nx,ny);
+ PaintOb(ob,&canvas, &clipBox);
+ }
+
diff --git a/BOX.C b/BOX.C
new file mode 100644
index 0000000..08235e2
--- /dev/null
+++ b/BOX.C
@@ -0,0 +1,69 @@
+/*--------------------------------------------------------------*/
+/* */
+/* box.c -- operations on boxes */
+/* */
+/*--------------------------------------------------------------*/
+
+#include <system.h>
+#include <prism.h>
+
+Box *MakeBox(bx,x,y,w,h) Box *bx; int x,y,w,h; {
+ bx->x = x; bx->y = y; bx->w = w; bx->h = h;
+ return(bx);
+ }
+
+BOOL BoxContains(b,x,y) Box *b; int x,y; {
+ return((BOOL)((x>=b->x)&&(x<(b->x+b->w))&&(y>=b->y) && (y<(b->y+b->h))));
+ }
+
+/* intersection of two boxes: compute c = intersect(a,b) */
+
+BOOL BoxAnd(c,a,b) Box *c,*a,*b; {
+ BOOL res = YES;
+ SHORT amx,amy,bmx,bmy;
+ amx = a->x + a->w; amy = a->y + a->h;
+ bmx = b->x + b->w; bmy = b->y + b->h;
+ c->w = MIN(amx, bmx) - (c->x = MAX(a->x, b->x));
+ c->h = MIN(amy, bmy) - (c->y = MAX(a->y, b->y));
+ if ( (c->w<=0) || (c->h<=0) ) { c->x = c->y = c->w = c->h = res = 0; }
+ return(res);
+ }
+
+Box *BoxTwoPts(b,x1,y1,x2,y2) Box *b; int x1,y1,x2,y2; {
+ ORDER(x1,x2); ORDER(y1,y2);
+ b->x = x1; b->y = y1; b->w = x2-x1+1; b->h = y2-y1+1;
+ return(b);
+ }
+
+Box *BoxThreePts(b,x1,y1,x2,y2,x3,y3) Box *b; int x1,y1,x2,y2,x3,y3; {
+ ORDER(x1,x2); ORDER(x1,x3); ORDER(x2,x3);
+ ORDER(y1,y2); ORDER(y1,y3); ORDER(y2,y3);
+ b->x = x1; b->y = y1; b->w = x3-x1+1; b->h = y3-y1+1;
+ return(b);
+ }
+
+/* constrain box a to be inside b */
+BoxBeInside(a,b) Box *a,*b; {
+ SHORT nout;
+ a->x = MAX(b->x,a->x);
+ a->y = MAX(b->y,a->y);
+ nout = (a->x + a->w) - (b->x + b->w);
+ if (nout>0) a->x -= nout;
+ nout = (a->y + a->h) - (b->y + b->h);
+ if (nout>0) a->y -= nout;
+ }
+
+/* make box c bigger so it encloses b */
+EncloseBox(c,b) Box *c,*b; {
+ SHORT xm,ym;
+ if (c->w==0) *c = *b; /* w = 0 is null box by convention */
+ else {
+ xm = MAX(c->x+c->w,b->x+b->w);
+ ym = MAX(c->y+c->h,b->y+b->h);
+ c->x = MIN(c->x,b->x);
+ c->y = MIN(c->y,b->y);
+ c->w = xm-c->x;
+ c->h = ym-c->y;
+ }
+ }
+
diff --git a/BRXFORM.C b/BRXFORM.C
new file mode 100644
index 0000000..53b0ca5
--- /dev/null
+++ b/BRXFORM.C
@@ -0,0 +1,145 @@
+/*----------------------------------------------------------------------*/
+/* */
+/* brxform -- Brush transformations */
+/* */
+/* BrFlipX, BrFlipY, BrRot90, BrRemapCols, BrBgToFg */
+/* */
+/*----------------------------------------------------------------------*/
+
+#include <system.h>
+#include <prism.h>
+
+#define local
+
+extern UBYTE *BMAllocMask();
+extern SHORT curxpc;
+extern struct RastPort *curRP;
+extern struct TmpRas tmpRas;
+extern SHORT curpen;
+extern BMOB curbr;
+
+/*----------------------------------------------------------------------*/
+/* Maintain "Original" brush, before transforming */
+/*----------------------------------------------------------------------*/
+extern BMOB origBr;
+extern struct BitMap origBM;
+extern SHORT curBrXform;
+
+/* copy the picture information of a BMOB */
+BOOL CopyBMOBPict(a,b) BMOB *a,*b; {
+ BOOL res = CopyBitMap(a->pict.bm,b->pict.bm);
+ if (res) { /* dprintf(" CopyBMOBPict: alloc err \n");*/ return(FAIL);}
+ b->pict.box = a->pict.box;
+ DFree(b->mask);
+ b->mask = BMAllocMask(curbr.pict.bm);
+ if (b->mask==0) return(FAIL);
+ movmem(a->mask,b->mask, BMPlaneSize(a->pict.bm));
+ b->xoffs = a->xoffs;
+ b->yoffs = a->yoffs;
+ b->xpcolor = a->xpcolor;
+ return(SUCCESS);
+ }
+
+/* save a copy of the brush preparatory to Transorming it */
+BOOL SaveBrush(newxf) {
+ BOOL res=SUCCESS;
+ origBr.pict.bm = &origBM;
+ FreeBitMap(curbr.save.bm);
+ if (curBrXform != newxf) res = CopyBMOBPict(&curbr, &origBr);
+ if (!res) curBrXform = newxf;
+ else curBrXform = NOXFORM;
+ return(res);
+ }
+
+
+/*----Restores the brush to its original state before transforming. */
+/* this frees the storage for the transformed version */
+void RestoreBrush() {
+ if (curBrXform == NOXFORM) return;
+ FreeBitMap(curbr.pict.bm);
+ DFree(curbr.mask);
+ curbr.mask = origBr.mask;
+ origBr.mask = NULL;
+ DupBitMap(origBr.pict.bm, curbr.pict.bm);
+ setmem(origBr.pict.bm,sizeof(struct BitMap),0);
+ curbr.pict.box = origBr.pict.box;
+ curbr.xoffs = origBr.xoffs;
+ curbr.yoffs = origBr.yoffs;
+ curBrXform = NOXFORM;
+ curbr.flags = 0;
+ }
+
+
+/*----------------------------------------------------------------------*/
+/* Map BG color to FG Color */
+/*----------------------------------------------------------------------*/
+
+void BrBgToFg() {
+ if (curpen!=USERBRUSH) return;
+ BMMapColor(curbr.pict.bm,curbr.pict.bm, curxpc, curRP->FgPen);
+ BMOBMask(&curbr);
+ }
+
+
+/*----------------------------------------------------------------------*/
+/* Reverse brush in X - direction */
+/*----------------------------------------------------------------------*/
+
+FlipX(sbm,sw,dbm) struct BitMap *sbm,*dbm; SHORT sw; {
+ SHORT x,h;
+ h = sbm->Rows;
+ for (x = 0; x < sw; x++ )
+ BltBitMap(sbm,x,0,dbm,sw-x-1,0,1,h,REPOP,0xff,tmpRas.RasPtr);
+ }
+
+BOOL ObFlipX(ob) BMOB *ob; {
+ struct BitMap tmpbm;
+ BlankBitMap(&tmpbm);
+ if (CopyBitMap(ob->pict.bm, &tmpbm)) return(FAIL);
+ FlipX(&tmpbm,ob->pict.box.w, ob->pict.bm);
+ ob->xoffs = ob->pict.box.w - ob->xoffs -1;
+ BMOBMask(ob);
+ FreeBitMap(&tmpbm);
+ return(SUCCESS);
+ }
+
+void BrFlipX() {
+ if (curpen!=USERBRUSH) return;
+ ZZZCursor();
+ if (ObFlipX(&curbr)) goto finish;
+ if (curBrXform != NOXFORM) ObFlipX(&origBr);
+ finish: UnZZZCursor();
+ }
+
+/*----------------------------------------------------------------------*/
+/* Reverse brush in Y - direction */
+/*----------------------------------------------------------------------*/
+FlipY(sbm,dbm) struct BitMap *sbm,*dbm; {
+ SHORT y,w,h;
+ w = sbm->BytesPerRow*8;
+ h = sbm->Rows;
+ for (y = 0; y < h; y++ )
+ BltBitMap(sbm,0,y,dbm,0,h-y-1,w,1,REPOP,0xff,tmpRas.RasPtr);
+ }
+
+
+BOOL ObFlipY(ob) BMOB *ob; {
+ struct BitMap tmpbm;
+ BlankBitMap(&tmpbm);
+ if (CopyBitMap(ob->pict.bm, &tmpbm)) return(FAIL);
+ FlipY(&tmpbm, ob->pict.bm);
+ ob->yoffs = ob->pict.box.h - ob->yoffs -1;
+ BMOBMask(ob);
+ FreeBitMap(&tmpbm);
+ return(SUCCESS);
+ }
+
+void BrFlipY() {
+ if (curpen!=USERBRUSH) return;
+ ZZZCursor();
+ if (ObFlipY(&curbr)) goto finish;
+ if (curBrXform != NOXFORM) ObFlipY(&origBr);
+ finish: UnZZZCursor();
+ }
+
+
diff --git a/CCYCLE.C b/CCYCLE.C
new file mode 100644
index 0000000..78e10c7
--- /dev/null
+++ b/CCYCLE.C
@@ -0,0 +1,190 @@
+/*----------------------------------------------------------------------*/
+/* */
+/* ccycle -- Color cycling and cycle paint */
+/* */
+/*----------------------------------------------------------------------*/
+
+#include <system.h>
+#include <prism.h>
+
+extern struct ViewPort *vport;
+extern struct RastPort *curRP;
+extern SHORT nColors;
+extern BOOL erasing;
+
+#define local static
+
+
+/* cycling frame rates */
+#define OnePerTick 16384
+#define OnePerSec OnePerTick/60
+
+Range cycles[MAXNCYCS] = {
+ /* count, rate, active, low, high */
+ {0, 0, YES, 20, 31 }, /* shade range */
+ {0, OnePerSec*10, YES, 3,7 },
+ {0, OnePerSec*10, YES, 0,0 },
+ {0, OnePerSec*10, YES, 0,0 }
+ };
+
+local BOOL cycling = NO;
+local BOOL wasCyc = NO;
+local BOOL paused = NO;
+local LONG timer = 0;
+
+local WORD colors[MAXNCOLORS];
+local WORD saveCols[MAXNCOLORS];
+
+SHORT curlow=0,curhigh=31;
+Range *curCyc = NULL;
+Range *shadeRange = cycles;
+
+extern void SetCycPaint();
+
+
+LoadCols(cols) WORD cols[]; { LoadRGB4(vport,cols,nColors); }
+
+local void StartCCyc() {
+ if (cycling) return;
+ GetColors(saveCols); GetColors(colors);
+ StartVBlank();
+ cycling = YES;
+ }
+
+local void StopCCyc() {
+ if (!cycling) return;
+ StopVBlank();
+ LoadCols(saveCols);
+ cycling = NO;
+ }
+
+KillCCyc() {
+ if (cycling) StopCCyc();
+ else if (paused) wasCyc = NO;
+ }
+
+TogColCyc() {
+ if (paused) wasCyc = !wasCyc; else
+ if (!cycling) StartCCyc(); else StopCCyc();
+ }
+PauseCCyc() { wasCyc = cycling; if (cycling) StopCCyc(); paused = YES; }
+ResumeCCyc() { if (wasCyc) StartCCyc(); paused = NO; }
+
+BOOL NoCycle = NO;
+
+local void CycleColors() {
+ int i,j; Range *cyc;
+ WORD temp;
+ BOOL anyChange = NO;
+ if (!cycling) return;
+ for (i = 1; i<MAXNCYCS; i++) {
+ cyc = &cycles[i];
+ if (cyc->active) {
+ cyc->count += cyc->rate;
+ if (cyc->count >= OnePerTick ) {
+ anyChange = YES;
+ cyc->count -= OnePerTick;
+ temp = colors[cyc->high];
+ for (j = cyc->high; j >cyc->low; j--) colors[j] = colors[j-1];
+ colors[cyc->low] = temp;
+ }
+ }
+ }
+ if (anyChange&&(!NoCycle)) LoadCols(colors);
+ }
+
+/*----------- Vertical Blank Routine to Cycle state.colors --------------*/
+local LONG mystack[64]; /* stack space for the int handler */
+local char myname[]="MyVb"; /* Name of the int handler */
+local struct Interrupt intServ;
+
+typedef void (*VoidFunc)();
+
+local MyVBlank() {
+ timer++;
+ CycleColors();
+ return(0);
+ }
+
+local StartVBlank() {
+ intServ.is_Data = (APTR) mystack;
+ intServ.is_Code = (VoidFunc)&MyVBlank;
+ intServ.is_Node.ln_Succ = NULL;
+ intServ.is_Node.ln_Pred = NULL;
+ intServ.is_Node.ln_Type = NT_INTERRUPT;
+ intServ.is_Node.ln_Pri = 0;
+ intServ.is_Node.ln_Name = myname;
+ AddIntServer(5,&intServ);
+ }
+
+local StopVBlank() { RemIntServer(5,&intServ); }
+
+
+/* ---- Incrementally Change Color table Values --------------- */
+
+local SetCTab(c,i) SHORT c,i;{SetRGB4(vport, i, (c>>8)&0xf, (c>>4)&0xf, c&0xf); }
+
+IncRGB(inc)SHORT inc; {
+ SHORT n = curRP->FgPen;
+ if (!cycling) SetCTab(GetRGB4(vport->ColorMap,n)+inc , n);
+ else {
+ cycling = NO;
+ saveCols[n] += inc;
+ movmem(saveCols,colors,MAXNCOLORS*sizeof(SHORT));
+ LoadCols(colors);
+ cycling = YES;
+ }
+ }
+
+
+BOOL cycPntOn = NO;
+
+
+/*
+TogCycPaint() { cycPntOn = !cycPntOn; SetCycPaint(); }
+*/
+
+
+local Range *FindCycle(n) SHORT n; {
+ int i;
+ Range *cyc;
+ for (i=1; i<MAXNCYCS; i++) {
+ cyc = &cycles[i];
+ if ( (n>=cyc->low) && (n<=cyc->high) ) return(cyc);
+ }
+ return(NULL);
+ }
+
+static SHORT cycFgPen = -1;
+
+void SetCycPaint() {
+ cycFgPen = curRP->FgPen;
+ curCyc = FindCycle(cycFgPen);
+ if (curCyc!=NULL) { curlow = curCyc->low; curhigh = curCyc->high; }
+ else { curlow = 0; curhigh = nColors-1; }
+ }
+
+
+OnCycPaint(){ cycPntOn = YES; SetCycPaint(); }
+OffCycPaint() { cycPntOn = NO; SetCycPaint(); }
+
+/*----------------------------------------------------------------------*/
+/* cycle Painting */
+/*----------------------------------------------------------------------*/
+
+/* calling this routine will increment the current painting color */
+/* You dont want to be updating the control panel every time and this
+doesn't. Call EndCycPaint() to do that. */
+
+CycPaint() {
+ SHORT n;
+ if (cycPntOn&&(curCyc!=NULL)&&(!erasing)) {
+ n = curRP->FgPen + 1;
+ if (n > curhigh) n = curlow;
+ SetFGCol(n);
+ }
+ }
+
+EndCycPaint(){ CPChgCol(curRP->FgPen); }
+
+
diff --git a/CHPROC.C b/CHPROC.C
new file mode 100644
index 0000000..fb29a87
--- /dev/null
+++ b/CHPROC.C
@@ -0,0 +1,252 @@
+/*----------------------------------------------------------------------*/
+/* */
+/* chproc.c -- Main character dispatch proc */
+/* */
+/*----------------------------------------------------------------------*/
+
+#include <system.h>
+#include <prism.h>
+#include <pnts.h>
+
+extern PointRec pnts; /* contains mx,my,sx,sy, etc */
+extern BOOL Ctrl;
+extern BOOL modeHelp;
+extern void ShadMode(),NullMode(),SelBrush(),CircMode();
+extern void FCircMode(),DrawMode(),OvalMode(),FOvalMode();
+extern void AFillMode(),BFillMode(),CurvMode(),RectMode();
+extern void FRectMode(),VectMode(),BrStretch(),TextMode(),ReadMode();
+extern void ToglMagW();
+extern short curpen,curFormat;
+extern struct Window *mainW;
+extern SHORT getch();
+extern BOOL kbhit();
+extern BOOL titleShowing;
+extern BOOL Painting,gridON,inside;
+extern struct RastPort *curRP,tempRP;
+extern struct ViewPort *vport;
+extern struct BitMap hidbm;
+extern struct ViewPort *vport;
+extern SHORT curxpc,nColors,curIMode;
+extern Box screenBox,bigBox;
+extern struct TmpRas tmpRas;
+extern SHORT curPixFmt, xShft, yShft, nColors;
+
+SHORT chgToMode = IM_none;
+
+#define local static
+
+IncFG(inc) SHORT inc; { CPChgCol((nColors-1)&(curRP->FgPen + inc)); }
+
+IncBG(inc) SHORT inc; { CPChgBg((nColors-1)&(curxpc + inc)); }
+
+void (*tempChProc)() = NULL;
+
+PlugChProc(proc) void (*proc)(); { tempChProc = proc; }
+
+whoa() {}
+
+DispAndSetMode(m) int m; {
+ SetModeMenu(m);
+ DispPntMode();
+ }
+
+IncPen() { CPChgPen(curpen?curpen+1:RoundB(1)); }
+
+DecPen() { if ((curpen&0xfff) > 1) CPChgPen(curpen-1);
+ else CPChgPen(0); }
+
+
+HelpMe() {
+ BasicBandW();
+ CPChgPen(0);
+ NewIMode(IM_draw);
+ DispAndSetMode(modeHelp? Color: Mask);
+ SymState(NO);
+ SetGridSt(NO);
+ SetGridXY(8,8);
+ SetGridOrg(0,0);
+ ShowCtrPan(YES);
+ if (!titleShowing) TogTitle();
+ RemoveMag();
+ KillCCyc();
+ }
+
+/* #define accelScroll */ /* BUGGY */
+
+scrollKeys(wh,i,j) Pane *wh; int i,j; {
+ SHORT c;
+ int xs = PMapX(8);
+ int ys = PMapY(8);
+ MWScroll(wh,i*xs,j*ys);
+ while (kbhit()) {
+ i = j = 0;
+ while (kbhit()) if (getch()==0) {
+ c = GetNextCh();
+#ifdef accelScroll
+ switch(c) {
+ case CLeft: i++; break;
+ case CRight: i--; break;
+ case CUp: j++; break;
+ case CDown: j--; break;
+ }
+#endif
+ }
+#ifdef accelScroll
+ if ((i!=0)||(j!=0)) MWScroll(wh,i*xs,j*ys);
+#endif
+ }
+ }
+
+Half() { if (curpen==USERBRUSH) BrHalf();
+ else CPChgPen((curpen&0xf000)|((curpen&0xfff)>>1));
+ }
+
+Dubl() { if (curpen==USERBRUSH) BrDubl();
+ else CPChgPen((curpen&0xf000)|MAX((curpen&0xfff)<<1,1));
+ }
+
+
+/* toggle grid, but adust grid offset so brushes doesn't move */
+extern SHORT gridx,gridy, gridOrgX, gridOrgY;
+extern BOOL gridON;
+extern BMOB *curob;
+extern Point nogrid;
+
+/* move grid is on the grid point so when
+ toggle grid brush doesnt move*/
+void TogGridFixed() {
+ SHORT tx,ty;
+ TogGridSt();
+ if (gridON) {
+ tx = mx; ty = my;
+ Gridify(&tx,&ty);
+ gridOrgX += (mx - tx);
+ gridOrgY += (my - ty);
+ }
+ }
+
+/* --Process keyboard character(s) ----*/
+
+void mainCproc(pn,c) Pane *pn; char c; {
+ BOOL svpnt = Painting;
+ if (tempChProc!=NULL) {
+ (*tempChProc)(c);
+ /* this lets text, when <esc>, change to mode in parallel overlay */
+ if (chgToMode!=IM_none) {
+ NewIMode(chgToMode);
+ chgToMode = IM_none;
+ }
+ return;
+ }
+ ClearFB();
+ switch(c) {
+ /*---------Change Color Pallete( use Keypad ) */
+ case '7': IncRGB(-REDC); break;
+ case '8': IncRGB( REDC); break;
+ case '4': IncRGB(-GREENC); break;
+ case '5': IncRGB( GREENC); break;
+ case '1': IncRGB(-BLUEC); break;
+ case '2': IncRGB( BLUEC); break;
+
+ case '.': CPChgPen(0); break; /* 1 pixel Pen */
+ case '-': if (curIMode == IM_airBrush) ChgABRadius(-1);
+ else DecPen(); break; /* cycle thru pens */
+ case '=': if (curIMode == IM_airBrush) ChgABRadius(1);
+ else IncPen(); break;
+
+ case '[': IncFG(-1); break; /* Cycle thru foreground cols*/
+ case ']': IncFG(1); break;
+
+ case '{': IncBG(-1); break; /* cycle thru background cols*/
+ case '}': IncBG(1); break;
+
+ case '/': TogSymSt(); break; /* Symmetry on and off */
+
+ case ' ': AbortIMode(); break; /* Kills any action */
+
+ case ',': NewIMode(IM_readPix); break; /* Read color from
+ screen-- Left Button for FG col, Right Button for BG */
+
+ case TAB: TogColCyc(); break;
+
+ case 'j': SwapSpare(); break;
+#ifdef agagag
+ /*----- Rudimentary File IO */
+ case 'i': LoadPicNamed("temp.pic"); break;
+ case 'o': SavePicNamed("temp.pic"); break;
+ case 'I': LoadPicNamed("temp1.pic"); break;
+ case 'O': SavePicNamed("temp1.pic"); break;
+#endif
+
+ case 'a': if (Ctrl) DispAvailMem(); else NewIMode(IM_airBrush); break;
+ case 'A': SizeAirBrush(); break;
+
+ case 'b': NewIMode(IM_selBrush); break; /* select a new brush*/
+ case 'B': UserBr(); break; /* use last brush selected */
+
+/* The rest is like PC Prism */
+ case 'c': NewIMode(IM_circ); break; /* draw circle */
+ case 'C': NewIMode(IM_fcirc); break; /* fill circle */
+ case 'd': NewIMode(IM_draw); break; /* draw */
+ case 'D': CPChgPen(0); NewIMode(IM_draw); break; /* draw with 1-pixel pen */
+ case 'e': NewIMode(IM_oval); break; /* ellipse */
+ case 'E': NewIMode(IM_foval); break; /* filled ellipse*/
+ case 'f': NewIMode(IM_fill); break; /* flood area*/
+ case 'g': TogGridSt(); break; /* grid on-off */
+ case 'G': TogGridFixed();break; /* grid on-off, keep pos fixed */
+ case 'h': Half(); break; /* halve brush size */
+ case 'H': Dubl(); break; /* double brush size */
+ case 'K': mClearToBg(); break; /* clear screen to b.g. color */
+#ifdef OWell
+ case 'm': ShowMag(mx,my); break; /* show magnify window*/
+ case 'n': RemoveMag(); break; /* remove mag window */
+#else
+ case 'm': ToggleMag(); break; /* show magnify window*/
+ case 'n': CenterPoint(mx,my); break; /* remove mag window */
+#endif
+ case 'p': ShowPallet(); break; /* Show the RGB-HSV pallet*/
+ case 'q': NewIMode(IM_curve1); break; /* curve */
+ case 'r': NewIMode(IM_rect); break; /* rectangle */
+ case 'R': NewIMode(IM_frect); break; /*filled rectangle */
+ case 's': NewIMode(IM_shade); break; /* shade */
+ case 't': NewIMode(IM_text1); break; /* text */
+ case 'u': Undo(); break; /* Undo */
+ case 'v': NewIMode(IM_vect); break; /* straight lines */
+ case 'x': BrFlipX(); break; /* Flip brush horizontally */
+ case 'y': BrFlipY(); break; /* Flip brush vertically */
+ case 'z': BrRot90(); break; /* Rotate brush 90 degrees */
+ case 'Z': NewIMode(IM_strBrush); break; /* stretch brush */
+ case '>': MWZoom(1); break; /* Zoom mag window in*/
+ case '<': MWZoom(-1); break; /* Zoom mag window out */
+ case 'w': whoa(); break; /* for break points */
+ case 0: switch(c = GetNextCh()) {
+
+ /* Set painting mode with function keys F1..F7 */
+ case F1Key: case F2Key: case F3Key:
+ case F4Key: case F5Key: case F6Key:
+ case F7Key: DispAndSetMode(c-F1Key); break;
+
+ case HELPKEY: HelpMe(); break;
+
+ /* Turn cursor On/Off */
+ case F8Key: TogCursor(); break;
+
+ /* Show/Hide Title Bar */
+ case F9Key: TogTitle(); break;
+
+ /* Show/Hide Graphics Menu (Control panel) */
+ case F10Key: TogBoth(); break;
+
+ /* Scroll Window contents with Arrow keys */
+ case CLeft: scrollKeys(pn,1,0); break;
+ case CRight: scrollKeys(pn,-1,0); break;
+ case CUp: scrollKeys(pn,0,1); break;
+ case CDown: scrollKeys(pn,0,-1); break;
+ }
+ break;
+ }
+ LoadIMode(); /* incase overlay happened */
+ if (svpnt) UpdtON(); else UpdtOFF();
+ PaneFakeMove(); /* make sure the feedback is turned back on*/
+ }
+
diff --git a/CLIP.C b/CLIP.C
new file mode 100644
index 0000000..93f89af
--- /dev/null
+++ b/CLIP.C
@@ -0,0 +1,214 @@
+/*--------------------------------------------------------------*/
+/* */
+/* CLIP.C */
+/* */
+/* Provides a clipping interface to the Amiga area fill. */
+/* Uses a modified verion of the Sutherland-Hodgman */
+/* Reentrant Polygon Clipper. */
+/* */
+/* ClipInit(xmin,ymin,xmax,ymax) -- sets clip box */
+/* ClipDraw -- corresponds to AreaDraw */
+/* ClipMove -- corresponds to AreaMove */
+/* ClipEnd -- corresponds to AreaEnd */
+/* */
+/* Dan Silva 3-6-85 created */
+/* " 3-10-85 changed to 2-stage from 4-stage */
+/* to speed up. */
+/* */
+/* Copyright 1985, Electronic Arts */
+/*--------------------------------------------------------------*/
+
+#include "system.h"
+
+
+/* #define dbgClip */
+
+#define YES 1
+#define NO 0
+#define NIL 0
+#define local static
+
+typedef char Boolean;
+typedef struct { int x,y; } Point;
+
+typedef struct {
+ short lastcode,isFirst,fcode;
+ Point last,f;
+ } clrec;
+
+local clrec ud = {0,YES,0,{0,0},{0,0}};
+local clrec rl = {0,YES,0,{0,0},{0,0}};
+
+local struct RastPort *clrp;
+
+/* ------ clipping box -------*/
+local short clxmin = 0;
+local short clymin = 0;
+local short clxmax = 319;
+local short clymax = 199;
+local short anyOutput = NO;
+
+
+local ClipUD(x,y) int x,y; {
+ short code = 0;
+ short xp,yclip;
+#ifdef dbgClip
+ printf("ClipUD x= %d, y = %d\n",x,y);
+#endif
+ if (y<clymin) code|= 1; else if (y>clymax) code |= 2;
+ if (ud.isFirst) {
+ ud.f.x = x; ud.f.y = y;
+ ud.fcode = 0;
+ ud.isFirst = NO;
+ }
+ else {
+ if (!(code|ud.lastcode)) ClipRL(x,y,0); /* trivial accept */
+ else if (!(code&ud.lastcode)) { /* --cant reject-- */
+ if (ud.lastcode) { /* last point was out of bounds */
+ yclip = (ud.lastcode&1)?clymin: clymax;
+ xp = ud.last.x + (yclip-ud.last.y)*(x-ud.last.x)/(y-ud.last.y);
+ ClipRL(xp,yclip,ud.lastcode);
+ }
+ xp = x; yclip = y;
+ if (code) { /*---- this point is out---- */
+ yclip = (code&1)?clymin: clymax;
+ xp = ud.last.x + (yclip-ud.last.y)*(x-ud.last.x)/(y-ud.last.y);
+ }
+ ClipRL(xp,yclip,code);
+ }
+ }
+ ud.last.x = x;
+ ud.last.y = y;
+ ud.lastcode = code;
+ }
+
+local short lastrlcode;
+
+local ClipRL(x,y,udcode)
+ int x,y; /* point clipped by UD */
+ short udcode; /* records how it was clipped by UD */
+ {
+ short code = 0;
+ short yp,xclip,lcode,ocode;
+#ifdef dbgClip
+ printf("ClipRL x= %d, y = %d, code = d\n",x,y,udcode);
+#endif
+ if (x<clxmin) code|= 4; else if (x>clxmax) code |= 8;
+ if (rl.isFirst) {
+ rl.f.x = x; rl.f.y = y;
+ rl.fcode = udcode;
+ rl.isFirst = NO;
+ }
+ else {
+ if (!(code|lastrlcode)) Output(x,y,udcode); /* trivial accept */
+ else if (!(code&lastrlcode))
+ {/* ---- cant reject ----- */
+ lcode = rl.lastcode&udcode;
+ if (lastrlcode) { /* last point was out of bounds */
+ xclip = (lastrlcode&4)?clxmin: clxmax;
+ yp = rl.last.y+(xclip-rl.last.x)*(y-rl.last.y)/(x-rl.last.x);
+ Output(xclip,yp,lcode|lastrlcode);
+ }
+ yp = y; xclip = x; ocode = udcode;
+ if (code) { /* ----- this point is out -----*/
+ xclip = (code&4)?clxmin: clxmax;
+ ocode = lcode|code;
+ yp = rl.last.y + (xclip-rl.last.x)*(y-rl.last.y)/(x-rl.last.x);
+ }
+ Output(xclip,yp,ocode);
+ }
+ }
+ rl.last.x = x;
+ rl.last.y = y;
+ rl.lastcode = udcode;
+ lastrlcode = code;
+ }
+
+
+/*---- the final stage: output the points to the area fill */
+
+local Boolean lastOutCode;
+local Point first;
+local short firstCode;
+
+
+local Output(x,y,incode) int x,y,incode; {
+ short saveState;
+#ifdef dbgClip
+ printf("Output x= %d, y = %d, code = %d\n",x,y,incode);
+#endif
+ if (!anyOutput) {
+ AreaMove(clrp,x,y);
+ anyOutput= YES;
+ first.x = x;
+ first.y = y;
+ firstCode = incode;
+ }
+ else
+ {
+ if ((lastOutCode&incode))
+ { /* "virtual" edges--ie along screen boundary */
+ saveState = clrp->Flags&AREAOUTLINE;
+ clrp->Flags &= ~AREAOUTLINE;
+ AreaDraw(clrp,x,y);
+ clrp->Flags |= saveState;
+ }
+ else AreaDraw(clrp,x,y);
+ }
+ lastOutCode = incode;
+ }
+
+local Close() {
+#ifdef dbgClip
+ printf(" Close\n");
+#endif
+ if (!ud.isFirst) ClipUD(ud.f.x,ud.f.y);
+ if (!rl.isFirst) ClipRL(rl.f.x,rl.f.y,rl.fcode);
+ if (anyOutput) Output(first.x,first.y,firstCode);
+ ud.isFirst = rl.isFirst = YES;
+ anyOutput = NO;
+ }
+
+/* ---------- Interface to Outside World -------------*/
+
+ClipInit(xmin,ymin,xmax,ymax) short xmin,ymin,xmax,ymax;
+ {
+ clxmin = xmin; clymin = ymin;
+ clxmax = xmax; clymax = ymax;
+ }
+
+local short drawYet = NO;
+
+ClipDraw(rp,x,y) struct RastPort *rp; short x,y; {
+#ifdef dbgClip
+ printf(" ClipDraw: x = %d, y = %d\n",x,y);
+#endif
+ clrp = rp;
+ ClipUD(x,y);
+ drawYet = YES;
+ }
+
+ClipMove(rp,x,y) struct RastPort *rp; short x,y; {
+#ifdef dbgClip
+ printf(" ClipMove: x = %d, y = %d\n",x,y);
+#endif
+ if (drawYet) Close(); else { ud.isFirst = rl.isFirst = YES; }
+ clrp = rp;
+ ClipUD(x,y);
+ drawYet = NO;
+ }
+
+ClipEnd(rp) struct RastPort *rp; {
+ BOOL wasAny = anyOutput;
+#ifdef dbgClip
+ printf(" Clip END -----------------------\n");
+#endif
+
+ if (drawYet) Close();
+ WaitBlit();
+ if (wasAny) AreaEnd(rp);
+ drawYet = NO;
+ }
+
+static short dum;
+static short dum2 = 0;
diff --git a/CONIC.C b/CONIC.C
new file mode 100644
index 0000000..857465b
--- /dev/null
+++ b/CONIC.C
@@ -0,0 +1,238 @@
+/*------------------------------------------------------------- */
+/* */
+/* Conic Curves */
+/* */
+/*------------------------------------------------------------- */
+
+#include <system.h>
+#include <prism.h>
+
+#define local static
+
+extern SHORT xShft, yShft;
+extern void (*CurPWritePix)();
+extern void (*curfunc)();
+extern void quadpts();
+extern SHORT xcen,ycen;
+
+/* table of move increments */
+typedef struct { SHORT dx1,dy1,dx2,dy2;} movRec;
+
+BOOL cncdbg = NO;
+
+local movRec moves[8] = {
+ { 1, 0, 1, 1},
+ { 0, 1, 1, 1},
+ { 0, 1,-1, 1},
+ {-1, 0, -1, 1},
+ {-1, 0, -1,-1},
+ { 0,-1,-1, -1},
+ { 0,-1, 1, -1},
+ { 1, 0, 1,-1}
+ };
+
+local movRec cmv;
+local BYTE nxtdiag[8] = {1,0,3,2,5,4,7,6};
+local BYTE nxtsq[8] = {7,2,1,4,3,6,5,0};
+local SHORT octchgs;
+local LONG w,a,b,d,k1,k2,k3;
+local SHORT eps = 1;
+
+typedef union{
+ LONG l;
+ struct { SHORT hi,lo;} wrd;
+ } LongInt;
+
+BYTE curoct;
+BYTE octTab[8] = {0,1,3,2,7,6,4,5};
+
+#define NFRAC 4
+#define scale(foo) (foo<<NFRAC)
+#define ival(foo) ( (SHORT) (foo>>NFRAC))
+LONG longone = 0x100;
+
+LONG LF(i) SHORT i; {
+ LongInt lf;
+ lf.wrd.lo = 0;
+ lf.wrd.hi = i;
+ return(lf.l);
+ }
+
+LONG lngtmp;
+#define lswap(a,b) {lngtmp = a; a = b; b = lngtmp; }
+#define neg(a) (a = -a)
+
+/*
+static prstate() {
+ if (cncdbg)
+ printf("oct=%d, k1=%d, k2=%d, k3=%d, b=%d, a=%d,d=%d \n",
+ curoct,ival(k1),ival(k2),ival(k3),ival(b),ival(a),ival(d));
+ }
+*/
+
+
+sqOctChange() {
+ curoct = nxtsq[curoct];
+ cmv = moves[curoct];
+ w = k2-k1;
+ k1 = -k1;
+ k2 = k1+w;
+ k3= 4*w-k3;
+ b = -w-b;
+ d = b-a-d;
+ a -= 2*b+w;
+ }
+
+diagOctChange() {
+ curoct = nxtdiag[curoct];
+ cmv = moves[curoct];
+ w = 2*k2-k3;
+ k1 = w-k1;
+ k2 -= k3;
+ k3 = -k3;
+ b += a - (k2>>1);
+ d = b -(a>>1) -d +(k3>>3);
+ a = (w>>1)-a;
+ }
+
+#define cabs(foo) (( (tmp=(foo)) > 0 ) ? tmp : -tmp )
+
+/*--------------------------------------------------------------*/
+/* plot general conic whose equation is */
+/* alpha*y*y + beta*x*x + 2*gamma*x*y + 2*u*y -2*v*x = 0; */
+/* the curve is displaced so that (0,0) maps to (x0,y0) */
+/*--------------------------------------------------------------*/
+
+void Conic(alpha,beta,gamma,u,v,x0,y0,x1,y1,func,maxoct,tol)
+ LONG alpha,beta,gamma,u,v;
+ SHORT x0,y0; /* starting point*/
+ SHORT x1,y1; /* stopping point*/
+ SHORT (*func)(); /* function to call */
+ SHORT maxoct; /* limit on number of octant changes */
+ SHORT tol; /* tolerance for termination test */
+ {
+ SHORT x,y,tmp;
+ x = x0; y = y0;
+/*
+ if (cncdbg) printf("alpha =%d, beta= %d, gamma= %d, u= %d, v= %d \n",
+ ival(alpha),ival(beta),ival(gamma),ival(u),ival(v));
+*/
+ curoct = 0;
+ if (v<0) curoct += 4;
+ if (u<0) curoct += 2;
+ if (ABS(v)>ABS(u)) {curoct+=1; lswap(alpha,beta); lswap(u,v); neg(gamma);}
+ curoct = octTab[curoct];
+ if (curoct&1) { neg(beta); neg(alpha); }
+ if ((curoct>2)&&(curoct<7)) neg(u);
+ if (curoct>3) neg(v); if ( (curoct&3) == 2 ) neg(v);
+ k1 = 2*beta;
+ k2 = k1 + 2*gamma;
+ k3 = 2*alpha + 2*gamma + k2;
+ b = 2*v - beta - gamma;
+ a = 2*u - b;
+ d = b - u - (alpha>>2);
+ cmv = moves[curoct];
+ octchgs = 0;
+ (*func)(x,y);
+ for (;;) {
+ if (d<0){ /* move 1 */
+ x += cmv.dx1; y += cmv.dy1;
+ b -= k1; a += k2; d += b;
+ }
+ else { /* move 2 */
+ x += cmv.dx2; y += cmv.dy2;
+ b -= k2; a += k3; d -= a;
+ }
+ (*func)(x,y);
+ if ((cabs(x-x1)<tol)&&(cabs(y-y1)<tol)) break;
+ if (b<0) { sqOctChange(); if ((++octchgs)>maxoct) break;}
+ else if (a<0) { diagOctChange(); if ((++octchgs)>maxoct) break;}
+ if (CheckAbort()) return;
+ }
+ if ((x!=x1)||(y!=y1)) (*func)(x1,y1);
+ }
+
+
+/*--------------------------------------------------------------*/
+/* Conic Curve given start point, stop point, and middle point */
+/* which defines the tangents at the start and stop point */
+/*--------------------------------------------------------------*/
+PCurve(x0,y0,x1,y1,x2,y2,lam,func)
+ SHORT x0,y0,x1,y1,x2,y2;
+ USHORT lam; /* 8 bit binary fraction between 0 and 1 */
+ SHORT (*func)();
+ {
+ LONG a1,a2,a3,b1,b2,b3,det,lambda,alam,halam;
+ LONG alpha,beta,gamma,u,v;
+/*
+ if (cncdbg) printf("conic x0=%d,y0=%d,x1=%d,y1=%d,x2=%d,y2=%d \n",
+ x0,y0,x1,y1,x2,y2);
+
+*/
+ lambda = lam;
+ alam = longone - lambda;
+ halam = alam>>1;
+ a1 = y0-y1; b1 = x1-x0;
+ a2 = y2-y1; b2 = x1-x2;
+ a3 = y2-y0; b3 = x0-x2;
+ det = a1*b3 - a3*b1;
+/* if (cncdbg) printf(" det = %u|%d \n",det); */
+ if (det==0)
+ { alpha = beta = gamma = (LONG) 0 ; u = -scale(b3); v = scale(a3); }
+ else {
+ alpha = alam*b1*b2 + lambda*b3*b3;
+ beta = alam*a1*a2 + lambda*a3*a3;
+ gamma = halam*(a1*b2+a2*b1) + lambda*a3*b3;
+ u = halam*(b1*det);
+ v = -halam*(a1*det);
+ if (det<0) { neg(alpha); neg(beta); neg(gamma); neg(u); neg(v); }
+ }
+ Conic(alpha,beta,gamma,u,v,x0,y0,x2,y2,func,8,2);
+ }
+
+void PEllpsWith(xc,yc,a,b,func) SHORT xc,yc,a,b; SHORT (*func)(); {
+ LONG alpha,beta,gamma,u,v;
+ if ((a<2)||(b<2)) return;
+ alpha = scale(((LONG)a)*((LONG)a));
+ beta = scale(((LONG)b)*((LONG)b));
+ gamma = (LONG)0;
+ u = ((LONG)b)*alpha;
+ v = (LONG)0;
+ Conic(alpha,beta,gamma,u,v,xc,yc+b,xc,yc+b,func,8,1);
+ }
+
+/* traverse 1 quadrant of ellipse, calling "func" at each point */
+void PQEllps(xc,yc,a,b,func) SHORT xc,yc,a,b; SHORT (*func)(); {
+ LONG alpha,beta,gamma,u,v;
+ if ((a<1)||(b<1)) return;
+ alpha = scale(((LONG)a)*((LONG)a));
+ beta = scale(((LONG)b)*((LONG)b));
+ gamma = (LONG)0;
+ u = ((LONG)b)*alpha;
+ v = (LONG)0;
+ xcen = xc;
+ ycen = yc;
+ Conic(alpha,beta,gamma,u,v,0,b,a,0,func,3,2);
+ }
+
+PQEllpsWith(xc,yc,a,b,func) SHORT xc,yc,a,b; void (*func)(); {
+ curfunc = func;
+ PQEllps(xc,yc,a,b, &quadpts);
+ }
+
+/* fast 1 dot thick ellipse */
+PEllpse(xc,yc,a,b) SHORT xc,yc,a,b; {
+ curfunc = CurPWritePix;
+ PQEllps(xc,yc,a,b, &quadpts);
+ }
+
+static SHORT qfill(x,y) SHORT x,y; {
+ SHORT w = 2*x+1;
+ PatHLine(xcen-x,ycen+y,w);
+ PatHLine(xcen-x,ycen-y,w);
+ }
+
+PFillEllps(xc,yc,a,b) SHORT xc,yc,a,b; { PQEllps(xc,yc,a,b,qfill); }
+
+
+
diff --git a/CTRPAN.C b/CTRPAN.C
new file mode 100644
index 0000000..aef59c9
--- /dev/null
+++ b/CTRPAN.C
@@ -0,0 +1,528 @@
+/*--------------------------------------------------------------*/
+/* */
+/* ctrpan.c -- graphics control panel */
+/* */
+/*--------------------------------------------------------------*/
+
+#include <system.h>
+#include <prism.h>
+
+extern void ToglMagw();
+extern void (*nop)();
+
+extern struct Window *mainW;
+extern Box bigBox, mainBox, screenBox;
+extern struct RastPort screenRP,tempRP;
+extern BOOL symON,gridON,magOn;
+extern SHORT nColors, solidpat[];
+extern SHORT xShft, yShft, curDepth,curFormat;
+extern struct TmpRas tmpRas;
+extern SHORT curIMode, lastPermMode;
+extern IModeDesc imodes[];
+
+extern SHORT act1[],act2[],act3[],act4[],act5[],act6[],act7[];
+extern SHORT act8[],act9[],act10[],act11[],act12[],act13[],act14[];
+extern SHORT act15[],act16[],act17[],act18[];
+extern SHORT act5H[],act5F[];
+extern SHORT act6H[],act6F[];
+extern SHORT act7H[],act7F[];
+extern SHORT act8H[],act8F[];
+extern SHORT penmenu[];
+
+SHORT *actbm[18] = {act1,act2,act3,act4,act9,act10,act5,act6,act7,act8,
+ act11,act12,act13,act14,act15,act16,act17,act18};
+
+SHORT *acthbm[4] = {act5H,act6H,act7H,act8H};
+SHORT *actfbm[4] = {act5F,act6F,act7F,act8F};
+
+#define local
+
+#define BLACK 0
+
+/* Dimensions of activity menu */
+#define actNPL 2
+
+/* Dimensions of Pen Menu*/
+#define penNPL 3
+
+/* Dimensions of Color Pallet*/
+
+SHORT actUH = 24;
+SHORT colNColumns = 4;
+SHORT colNRows = 8;
+SHORT colUH = 6;
+SHORT colDspH = 12;
+SHORT cpWidth,actUW,colUW,penUW;
+SHORT penH,actH;
+
+#define noActBut 128
+
+/*************************************************/
+/* initialize Panes for debugging purposes */
+Pane penwin={0},actwin={0},cdspwin={0},colwin={0};
+SHORT cpfgcol=-1,cpbgcol,activity,cpPen;
+UBYTE actBut = noActBut;
+BOOL cpShowing;
+
+extern void CPInvAct();
+
+/** Dummy Calls **/
+extern void mainCproc();
+/*============== utilities===================== */
+
+ScreenDest() { PushGrDest(&screenRP,&screenBox); }
+
+XorScreenBox(bx) Box *bx; {
+ ScreenDest();
+ SetAPen(&screenRP,1);
+ SetXorFgPen(&screenRP);
+ PFillBox(bx);
+ SetDrMd(&screenRP,JAM2);
+ PopGrDest();
+ }
+
+ColorBox(b,c) Box *b;SHORT c; {
+ ScreenDest();
+ TempMode(Replace,c,solidpat);
+ PFillBox(b);
+ RestoreMode();
+ PopGrDest();
+ }
+
+
+local SHORT downIn;
+local SHORT cpButton;
+SHORT NXMag, NYMag;
+
+/*--------------------------------------------------------------*/
+/* Pen Menu */
+/*--------------------------------------------------------------*/
+#ifdef thisIsInPrism_H
+#define ROUND_B 1
+#define SQUARE_B 2
+#define DOT_B 3
+#define RoundB(n) ((ROUND_B<<12)|n)
+#define SquareB(n) ((SQUARE_B<<12)|n)
+#define DotB(n) ((DOT_B<<12)|n)
+#endif
+
+
+typedef struct {BYTE x,y,w,h; } ByteBox;
+
+#define NPenBoxes 10
+
+/* these coordinates are in VDC */
+ByteBox penBoxes[NPenBoxes] = {
+ {0,0,8,12}, {8,0,10,12}, {18,0,12,14}, {30,0,14,14},
+ {0,14,14,12}, {14,14,12,12}, {26,14,10,10}, {34,14,10,8},
+ {4,26,14,12}, {23,25,22,14}
+ };
+
+
+SHORT penNums[NPenBoxes] = {
+ 0,RoundB(1),RoundB(2), RoundB(3),
+ SquareB(5),SquareB(4),SquareB(3),SquareB(2),
+ DotB(1),DotB(2)
+ };
+
+local void xorPenBox(n) int n; {
+ Box bx;
+ ByteBox *byb;
+ if (!cpShowing) return;
+ if ((n < 0)|| (n>10)) return;
+ byb = &penBoxes[n];
+ bx.x = PMapX(byb->x+2) + penwin.box.x;
+ bx.y = PMapY(byb->y+2) + penwin.box.y;
+ bx.w = PMapX(byb->w);
+ bx.h = PMapY(byb->h);
+ XorScreenBox(&bx);
+ }
+
+Box *BoxFrByteBox(bx,bbx) Box *bx; ByteBox *bbx; {
+ return((Box *)MakeBox(bx,bbx->x,bbx->y,bbx->w,bbx->h));
+ }
+
+BOOL InByteBox(bbx,x,y) ByteBox *bbx; SHORT x,y; {
+ Box bx;
+ return((BOOL)BoxContains(BoxFrByteBox(&bx,bbx),x,y));
+ }
+
+local int GetPenBox(x,y) SHORT x,y; {
+ int i;
+ x = VMapX(x)-2;
+ y = VMapY(y)-4;
+ for (i=0; i<NPenBoxes; i++) if ( InByteBox(&penBoxes[i], x, y) )
+ return(i);
+ return(-1);
+ }
+
+
+local SHORT penForXY(x,y) SHORT x,y; { return(penNums[GetPenBox(x,y)]); }
+
+local penMproc(ph,why,but,x,y) Pane *ph; MouseEvent why; SHORT but,x,y; {
+ SHORT pNum,n;
+ n = GetPenBox(x,y);
+ switch(why) {
+ case BDOWN: cpButton = but; downIn = n; xorPenBox(n); break;
+ case BUP: xorPenBox(downIn);
+ if (downIn>=0) {
+ pNum = penNums[downIn];
+ if (cpButton==1) CPChgPen(pNum);
+ else SizePen(pNum);
+ }
+ break;
+ }
+ }
+
+BoxForPen(pn) SHORT pn; {
+ int i;
+ for (i=0; i<NPenBoxes; i++) if (pn == penNums[i]) return(i);
+ return(-1);
+ }
+
+SHORT cpPenBox = -1;
+
+/* new is a pen# */
+CPChgPen(new) SHORT new; {
+ xorPenBox(cpPenBox);
+ cpPen = new;
+ cpPenBox = BoxForPen(new);
+ xorPenBox(cpPenBox);
+ if (cpPen!=USERBRUSH) if ((curIMode==IM_null)||(imodes[lastPermMode].flags&NOBR))
+ NewIMode(IM_shade);
+ SelPen(new);
+ }
+
+#define PENMENUW 25
+#define PENMENUH 20
+
+void PenWPaint() {
+ struct BitMap tmp;
+ Box sbx;
+ InitBitMap(&tmp,1,PENMENUW,PENMENUH);
+ tmp.Planes[0] = (PLANEPTR)penmenu;
+ if (!cpShowing) return;
+ penwin.box.y = mainBox.y;
+ penwin.box.x = screenBox.w - cpWidth;
+ ColorBox(&penwin.box, BLACK);
+ MagBits(&tmp, MakeBox(&sbx,0,0,PENMENUW,PENMENUH), screenRP.BitMap,
+ penwin.box.x, penwin.box.y, NXMag,NYMag,&screenBox);
+ xorPenBox(cpPenBox);
+ }
+
+
+/*--------------------------------------------------------------*/
+/* Activity Menu */
+/*--------------------------------------------------------------*/
+
+#define NACTBUTS 18
+
+Delay(n) SHORT n; { SHORT i; for (i=0; i<500*n; i++) {} }
+
+
+BOOL LRButton = NO;
+local BOOL LSide;
+local ActButton(but,i) SHORT but,i; {
+ BOOL doLeft = (LRButton)? (but==1) : LSide;
+ switch(i) {
+ case 0: NewIMode(IM_shade); break;
+ case 1: NewIMode(IM_draw); break;
+ case 2: NewIMode(IM_vect); break;
+ case 3: NewIMode(IM_curve1); break;
+ case 4: NewIMode(IM_fill); break;
+ case 5: if (but==1) NewIMode(IM_airBrush);
+ else SizeAirBrush(); break;
+ case 6: NewButIMode(doLeft ? IM_rect:IM_frect, cpButton); break;
+ case 7: NewButIMode(doLeft ? IM_circ:IM_fcirc, cpButton); break;
+ case 8: NewButIMode(doLeft ? IM_oval:IM_foval, cpButton); break;
+ case 9: NewButIMode(doLeft ? IM_poly:IM_fpoly, cpButton); break;
+ case 10: if (but==1) NewIMode(IM_selBrush);
+ else { CPInvAct(selbAct); UserBr();
+ Delay(5); CPInvAct(selbAct);
+ } break;
+ case 11: NewIMode(IM_text1); break;
+ case 12: if (but==1) TogGridSt(); else NewIMode(IM_gridSpec); break;
+ case 13: if (but==1) TogSymSt(); else DoSymReq(); break;
+ case 14: ToglMagw(); break;
+ case 15: MWZoom( (but==1)? 1: -1 ); break;
+ case 16: Undo(); break;
+ case 17: mClearToBg(); break;
+ }
+ }
+
+extern void xorActBut();
+
+/* Im not quite sure why I need (y-1) here but it works */
+
+local SHORT actBoxForXY(x,y) SHORT x,y; {
+ return((SHORT)(MIN(x,cpWidth-2)/actUW+((y-1)/actUH)*actNPL)); }
+
+local actMproc(ph,why,but,x,y) Pane *ph; MouseEvent why; SHORT but,x,y; {
+ SHORT n = actBoxForXY(x,y);
+ switch(why) {
+ case BDOWN: cpButton = but; downIn = n;
+ LSide = (VMapX(x)%24) + (VMapY(y-NYMag)% 24)< 24; xorActBut(n);
+ break;
+ case BUP: xorActBut(downIn);
+ ActButton(cpButton,downIn);
+ break;
+ }
+ }
+
+
+/* the "n" here is button number, not activity */
+actX(n) SHORT n; { return(actwin.box.x + NXMag + actUW*(n%actNPL)); }
+actY(n) SHORT n; { return(actwin.box.y + NYMag + actUH*(n/actNPL)); }
+
+#define actPUH 12
+#define actPUW 12
+
+DispActBut(pic,n)
+ UBYTE *pic; /* pointer to the bits to be diplayed */
+ int n; /* button # */
+ {
+ int x,y;
+ Box sbx;
+ struct BitMap tmp;
+ InitBitMap(&tmp,1,11,11);
+ tmp.Planes[0] = pic;
+ SetDrMd(&screenRP,JAM2);
+ x = actX(n); y = actY(n);
+ MagBits(&tmp,MakeBox(&sbx,0,0,11,11), screenRP.BitMap,
+ x, y, NXMag,NYMag,&screenBox);
+ }
+
+
+/* #define slowway */
+
+#ifdef slowway
+DispActMenu() {
+ SHORT i;
+ ColorBox(&actwin.box, BLACK);
+ for (i=0; i< NACTBUTS; i++ ) DispActBut(actbm[i],i);
+ }
+#endif
+
+#ifdef DBGCP
+SHORT dbgcp = NO;
+tstbm(bm) struct BitMap *bm; {
+ SHORT w,h;
+ w = bm->BytesPerRow*8;
+ h = bm->Rows;
+ SetAPen(&screenRP,0);
+ RectFill(&screenRP,0,20, w-1, 20 + h - 1);
+ BltBitMap(bm,0,0,screenRP.BitMap,0,20,w,h,REPOP,0xff,NULL);
+ }
+#endif
+
+void DispActMenu() {
+ SHORT i; Box sbx;
+ struct BitMap tmp;
+ SHORT h = actPUH*NACTBUTS/actNPL;
+ InitBitMap(&tmp,1,32,h);
+ if (tmpRas.RasPtr==NULL) return;
+ tmp.Planes[0] = tmpRas.RasPtr;
+ ColorBox(&actwin.box,BLACK);
+ ClearBitMap(&tmp);
+ tempRP.BitMap = &tmp;
+ SetDrMd(&tempRP,JAM2);
+ SetAPen(&tempRP,1);
+ for (i=0; i< NACTBUTS; i++ ) {
+ BltTemplate(actbm[i],0,2,&tempRP,
+ actPUW*(i%actNPL)+1, actPUH*(i/actNPL)+1, 11, 11);
+ }
+ MagBits(&tmp,MakeBox(&sbx,0,0,25,h), screenRP.BitMap,
+ actwin.box.x, actwin.box.y, NXMag, NYMag, &screenBox);
+ WaitBlit();
+ }
+
+void xorActBut(but) SHORT but; {
+ Box bx;
+ if (!cpShowing) return;
+ if (but==noActBut) return;
+ XorScreenBox(MakeBox(&bx,actX(but),actY(but),actUW-NXMag,actUH-NYMag));
+ }
+
+/* two different activities are now associated with one button */
+/* given an activity, determine the button # by the following: */
+/* bit 5 denotes left button activity, bit 6 denotes right button*/
+#define LBACT 32
+#define RBACT 64
+
+UBYTE butForAct[] = {
+ noActBut,0,1,2,3,4,5,32+6,64+6,32+7,64+7,32+8,64+8,32+9,64+9,
+ 10,11,12,13,14,15,16,17 };
+
+void CPInvAct(act) SHORT act; { xorActBut((SHORT)butForAct[act]); }
+
+void CPShowBut(abut) SHORT abut; {
+ SHORT butN;
+ if (!cpShowing) return;
+ if (abut==noActBut) return;
+ butN = abut&0x1f;
+ if (abut&LBACT) DispActBut(acthbm[butN-6], butN);
+ else {
+ if (abut&RBACT) DispActBut(actfbm[butN-6], butN);
+ else xorActBut(butN);
+ }
+ }
+
+void CPClearBut() {
+ SHORT butN;
+ if (!cpShowing) return;
+ if (actBut==noActBut) return;
+ butN = actBut&0x1f;
+ if ((actBut&(LBACT|RBACT))) DispActBut(actbm[butN], butN);
+ else xorActBut(butN);
+ }
+
+void CPChgAct(new) SHORT new; {
+ if (new==activity) return;
+ CPClearBut();
+ activity = new;
+ actBut = butForAct[new];
+ CPShowBut(actBut);
+ }
+
+
+CPShowAct(act) { CPShowBut(butForAct[act]); }
+
+void ActWPaint() {
+ if (!cpShowing) return;
+ actwin.box.y = mainBox.y + penH;
+ actwin.box.x = screenBox.w - cpWidth;
+ DispActMenu();
+ if (gridON) CPShowAct(gridAct);
+ if (symON) CPShowAct(symAct);
+ if (magOn) CPShowAct(magAct);
+ CPShowBut(actBut);
+ }
+
+
+/*--------------------------------------------------------------*/
+/* Current Color Display */
+/*--------------------------------------------------------------*/
+local void cDspMproc(ph,why,but,x,y) Pane *ph; MouseEvent why; SHORT but,x,y; {
+ if (why == BUP) if (but==2) ShowPallet();
+ else NewIMode(IM_readPix);
+ }
+
+local void cDspPaint() {
+ SHORT x,y; Box bx;
+ if (!cpShowing) return;
+ cdspwin.box.y = mainBox.y + penH + actH;
+ cdspwin.box.x = screenBox.w - cpWidth;
+ ColorBox(&cdspwin.box, BLACK);
+ ScreenDest();
+ x = cdspwin.box.x;
+ y = cdspwin.box.y;
+ TempMode(Replace,cpbgcol,solidpat);
+ PFillBox(MakeBox(&bx,x+1,y+1,cpWidth-2,PMapY(24)-1));
+ SetFGCol(cpfgcol);
+ PFillCirc(x+(cpWidth-1)/2,y+PMapY(12),cpWidth/6);
+ RestoreMode();
+ PopGrDest();
+ }
+
+
+/*--------------------------------------------------------------*/
+/* Color Menu */
+/*--------------------------------------------------------------*/
+
+/*--- Paint the Color menu --------------------*/
+
+void XorCol() {
+ Box bx;
+ if (!cpShowing) return;
+ bx.x = (cpfgcol/colNRows)*colUW + colwin.box.x;
+ bx.y = (cpfgcol%colNRows)*colUH + colwin.box.y;
+ bx.w = colUW+1;
+ bx.h = colUH+1;
+ ScreenDest();
+ SetAPen(&screenRP,1);
+ TempXOR();
+ PThinFrame(&bx);
+ RestoreMode();
+ PopGrDest();
+ }
+
+void ColWPaint(ph,b) Pane *ph; Box *b; {
+ SHORT pn,x,y,i,j;
+ Box bx;
+ if (!cpShowing) return;
+ colwin.box.y = mainBox.y + penH + actH + colDspH;
+ colUH = (screenBox.h - colwin.box.y)/colNRows;
+ colwin.box.x = screenBox.w - cpWidth;
+ ColorBox(MakeBox(&bx,colwin.box.x,colwin.box.y,colwin.box.w,
+ colwin.box.h), BLACK);
+ x=colwin.box.x+1;
+ y=colwin.box.y+1;
+ pn = 0;
+ bx.w = colUW-1;
+ bx.h = colUH-1;
+ bx.x = x;
+ ScreenDest();
+ SetDrMd(&screenRP,JAM2);
+ for (j=0; j<colNColumns; j++) {
+ bx.y = y;
+ for (i=0; i<colNRows; i++) {
+ SetFGCol(pn++);
+ PFillBox(&bx);
+ bx.y += colUH;
+ }
+ bx.x += colUW;
+ }
+ PopGrDest();
+ XorCol();
+ }
+
+
+local int colForXY(x,y) SHORT x,y; {
+ return(MIN(y,colUH*colNRows-1)/colUH+(MIN(x,cpWidth-2)/colUW)*colNRows);
+ }
+
+local ColNewXY(button,x,y) SHORT button,x,y;{
+ SHORT item = colForXY(x,y);
+ if (button==1) if (item != cpfgcol) CPChgCol(item); else;
+ else if (item!= cpbgcol) CPChgBg(item);
+ }
+
+local colMproc(ph,why,but,x,y) Pane *ph; MouseEvent why; SHORT but,x,y; {
+ if (why == BDOWN) { ColNewXY(but,x,y);
+ if (but==1) SetFGCol(cpfgcol); else SetXPCol(cpbgcol);
+ }
+ }
+
+CPChgCol(new) SHORT new;{
+ SetFGCol(new);
+ if (new!=cpfgcol) {
+ if (cpfgcol>=0) XorCol();
+ cpfgcol = new;
+ cDspPaint();
+ XorCol();
+ }
+ SetCycPaint(); /* keep the current cycle up to date */
+ }
+
+CPChgBg(new) SHORT new; { if (new<nColors) {SetXPCol(cpbgcol=new);
+ cDspPaint();}
+ }
+
+/* ------------------------- */
+InstCP() {
+ PaneInstall(&penwin);
+ PaneInstall(&actwin);
+ PaneInstall(&cdspwin);
+ PaneInstall(&colwin);
+ cpShowing = YES;
+ }
+
+RmvCP() {
+ PaneRemove(&penwin);
+ PaneRemove(&actwin);
+ PaneRemove(&cdspwin);
+ PaneRemove(&colwin);
+ cpShowing = NO;
+ }
+
+ShowCtrPan(st) BOOL st; { if (st!=cpShowing) TogBoth(); }
diff --git a/CURBRUSH.C b/CURBRUSH.C
new file mode 100644
index 0000000..c1bde47
--- /dev/null
+++ b/CURBRUSH.C
@@ -0,0 +1,170 @@
+/*----------------------------------------------------------------------*/
+/* */
+/* curbrush.c -- The current brush & pen */
+/* */
+/*----------------------------------------------------------------------*/
+#include <system.h>
+#include <prism.h>
+
+extern short xShft, yShft;
+extern Box screenBox;
+extern SHORT prevColors[];
+extern SHORT LoadBrColors[32];
+extern struct BitMap brBM,brSVBM;
+extern BMOB curbr;
+extern SHORT curpen;
+extern struct BitMap penBM,penSVBM;
+extern BMOB curpenob;
+extern BOOL modeHelp;
+
+#define local static
+
+BOOL LegalMode(i) int i; {
+ if (modeHelp)
+ return((BOOL)! ( (curpen!=USERBRUSH) && ((i==Mask)||(i==Replace)) ) );
+ else return((BOOL)YES);
+ }
+
+BOOL BrushDefined() { return((BOOL)(curbr.pict.bm->Planes[0] != NULL)); }
+
+UseBrPalette() { if (curpen==USERBRUSH) {
+ GetColors(prevColors);
+ LoadCMap(LoadBrColors);
+ }
+ }
+
+/* Pens have only a MASK and no source bit-planes. FixUpPen
+ fixes pen data structure to reflect this */
+local FixUpPen() {
+ curpenob.xpcolor = 0;
+ curpenob.minTerm = COOKIEOP;
+ DFree(curpenob.mask);
+ curpenob.mask = penBM.Planes[0];
+ penBM.Planes[0] = (APTR)0;
+ penBM.Depth = 0;
+ curpenob.planeUse = 0;
+ curpenob.planeDef = 0;
+ curpenob.xoffs = curpenob.pict.box.w/2;
+ curpenob.yoffs = curpenob.pict.box.h/2;
+ }
+
+local SzPen() { return(NewSizeBitMap(curpenob.pict.bm,1,
+ curpenob.pict.box.w,curpenob.pict.box.h));}
+
+local SizePenBM() {
+ if (SzPen()) {
+ FreeBMOB(&curbr);
+ if (SzPen()) return(FAIL);
+ }
+ ClearBitMap(&penBM);
+ return(SUCCESS);
+ }
+
+/* ------------- Circular Pen radius r:
+ r is in VDC (virtual device coords )
+*/
+RoundPen(r) SHORT r; {
+ struct RastPort crp;
+ SHORT rx,ry;
+ rx = PMapX(r);
+ ry = MAX(PMapY(r),1);
+ MakeBox(&curpenob.pict.box,0,0,2*rx+1,2*ry+1);
+ InitRastPort(&crp);
+ SizePenBM();
+ crp.BitMap = &penBM;
+ SetAPen(&crp,15);
+ PushGrDest(&crp,&screenBox); /* any large box with x=y=0 will do */
+ PFillCirc(rx,ry,rx);
+ PopGrDest();
+ FixUpPen();
+ }
+
+OneBitPen() {
+ MakeBox(&curpenob.pict.box,0,0,1,1);
+ NewSizeBitMap(&penBM,1,1,1);
+ *((SHORT *)penBM.Planes[0]) = 0x8000;
+ FixUpPen();
+ }
+
+
+/*---------------- Square Pen side s ------------- */
+SquarePen(s) SHORT s; {
+ struct RastPort crp;
+ SHORT pw = PMapX(s);
+ SHORT ph = PMapY(s);
+ MakeBox(&curpenob.pict.box,0,0,pw,ph);
+ InitRastPort(&crp);
+ SizePenBM();
+ crp.BitMap = &penBM;
+ SetAPen(&crp,15);
+ WaitBlit();
+ RectFill(&crp,0,0,pw-1,ph-1);
+ FixUpPen();
+ }
+
+#define NPENS 9
+
+#ifdef fromprism_h
+/* Pen TYPE ENcoding */
+#define USERBRUSH -1
+#define ROUND_B 1
+#define SQUARE_B 2
+#define DOT_B 3
+#define AIR_B 4
+#define RoundB(n) ((ROUND_B<<12)|n)
+#define SquareB(n) ((SQUARE_B<<12)|n)
+#define DotB(n) ((DOT_B<<12)|n)
+#define AirB AIR_B<<12
+
+#endif
+
+
+
+/* dot pens ---------------- */
+extern UWORD dots10[],dots20[],dots30[],dots40[],dots50[],dots60[];
+UWORD *dotbms[] = { dots10, dots20, dots30, dots40, dots50, dots60};
+
+DotBFromRad(r) int r; { return( DotB(r/2)); }
+
+DotsPen(s) int s; {
+ int pensz;
+ s = MIN(6, MAX(1,s));
+ pensz = 4*s+1;
+ MakeBox(&curpenob.pict.box,0,0,pensz,pensz);
+ SizePenBM();
+ movmem(dotbms[s-1], penBM.Planes[0], BytesNeeded(pensz)*pensz);
+ FixUpPen();
+ }
+
+/** Select a builtin Pen --------------- */
+
+void SelPen(n) int n; {
+ int type,size;
+ if (n==USERBRUSH) {
+ if (!BrushDefined()) return;
+ else UseBrush();
+ }
+ else {
+ if (n==0) OneBitPen();
+ else {
+ type = (n>>12)&0xf;
+ size = n&0xfff;
+ switch(type) {
+ case ROUND_B: size = MIN(size,50); RoundPen(VMapY(size)); break;
+ case SQUARE_B: size = MIN(size,100); SquarePen(VMapY(size)); break;
+ case DOT_B: DotsPen(size); break;
+ default: break;
+ }
+ n = (n&0xf000)|size;
+ }
+ if (curpen==USERBRUSH){
+ curpen=n; /* have to do this first so LegalMode() works right*/
+ if (modeHelp) SetModeMenu(Color);
+ }
+ UsePen();
+ }
+ curpen = n;
+ FixUsePen(); /* this updates the usePen variable*/
+ ResetCursor();
+ }
+
diff --git a/CURSBMS.C b/CURSBMS.C
new file mode 100644
index 0000000..df3aecc
--- /dev/null
+++ b/CURSBMS.C
@@ -0,0 +1,188 @@
+/*----------------------------------------------------------------------*/
+/* */
+/* cursbms.c -- Sprite Bitmaps for different cursors */
+/* */
+/*----------------------------------------------------------------------*/
+
+/* Bitmap name = fill, Amiga-Sprite format. */
+/* Width = 13, Height = 17 */
+
+short fillCurs[38] = {
+ 0x0000, 0x0000, /* position and control info*/
+ 0x200, 0x0,
+ 0x700, 0x200,
+ 0xF80, 0x700,
+ 0x1FC0, 0xF80,
+ 0x3FE0, 0x1FC0,
+ 0x7FF0, 0x3FE0,
+ 0xFFF8, 0x7FE0,
+ 0x7FF0, 0x3FC0,
+ 0x3FE0, 0x1F80,
+ 0x1FC0, 0xF00,
+ 0xF80, 0x600,
+ 0x700, 0x0,
+ 0x700, 0x200,
+ 0x1740, 0x200,
+ 0xF80, 0x700,
+ 0x700, 0x200,
+ 0x1DC0, 0x1DC0,
+ 0xFFFF, 0xFFFF /* end markers */
+ };
+
+
+
+/* Bitmap name = cross, Amiga-Sprite format. */
+/* Width = 15, Height = 15 */
+
+short crossCurs[34] = {
+ 0x0000, 0x0000, /* position and control info*/
+ 0x100, 0x0,
+ 0x0, 0x100,
+ 0x100, 0x0,
+ 0x0, 0x100,
+ 0x100, 0x0,
+ 0x0, 0x100,
+ 0x0, 0x0,
+ 0xA82A, 0x5454,
+ 0x0, 0x0,
+ 0x0, 0x100,
+ 0x100, 0x0,
+ 0x0, 0x100,
+ 0x100, 0x0,
+ 0x0, 0x100,
+ 0x100, 0x0,
+ 0xFFFF, 0xFFFF /* end markers */
+ };
+
+
+
+/* Bitmap name = zzz, Amiga-Sprite format. */
+/* Width = 16, Height = 25 */
+
+short zzz [54] = {
+ 0x0000, 0x0000, /* position and control info*/
+ 0x0, 0xFE0,
+ 0x740, 0x18B0,
+ 0xFE0, 0x7018,
+ 0x3FF0, 0xC008,
+ 0x7FF0, 0x9E0C,
+ 0x7FF8, 0x8406,
+ 0x7FFC, 0x8802,
+ 0xFFFC, 0x1E03,
+ 0x7FFE, 0x80F1,
+ 0x7FFE, 0x8021,
+ 0x3FFF, 0x4040,
+ 0x7FFE, 0x80F1,
+ 0x3FFE, 0xC001,
+ 0x1FFC, 0x6003,
+ 0xFF8, 0x3006,
+ 0x3F0, 0x1C0C,
+ 0xE0, 0x718,
+ 0x780, 0x870,
+ 0xFE0, 0x1010,
+ 0x740, 0x820,
+ 0x0, 0xFE0,
+ 0x1C0, 0x220,
+ 0x3E0, 0x410,
+ 0xC0, 0x330,
+ 0x0, 0xE0,
+ 0xFFFF, 0xFFFF /* end markers */
+ };
+
+
+
+/* Bitmap name = size, Amiga-Sprite format. */
+/* Width = 8, Height = 31 */
+
+short size[66] = {
+ 0x0000, 0x0000, /* position and control info*/
+ 0x7800, 0x7C00,
+ 0x8400, 0xC600,
+ 0x8000, 0xC000,
+ 0x7800, 0x7C00,
+ 0x400, 0x600,
+ 0x8400, 0xC600,
+ 0x7800, 0x7C00,
+ 0x0, 0x0,
+ 0x3800, 0x3C00,
+ 0x1000, 0x1800,
+ 0x1000, 0x1800,
+ 0x1000, 0x1800,
+ 0x1000, 0x1800,
+ 0x1000, 0x1800,
+ 0x3800, 0x3C00,
+ 0x0, 0x0,
+ 0x7E00, 0x7F00,
+ 0x400, 0x600,
+ 0x800, 0xC00,
+ 0x1000, 0x1800,
+ 0x2000, 0x3000,
+ 0x4000, 0x6000,
+ 0x7E00, 0x7F00,
+ 0x0, 0x0,
+ 0x7E00, 0x7F00,
+ 0x4000, 0x6000,
+ 0x4000, 0x6000,
+ 0x7800, 0x7C00,
+ 0x4000, 0x6000,
+ 0x4000, 0x6000,
+ 0x7E00, 0x7F00,
+ 0xFFFF, 0xFFFF /* end markers */
+ };
+
+
+
+
+/* Bitmap name = pick, Amiga-Sprite format. */
+/* Width = 11, Height = 43 */
+
+short pick[90] = {
+ 0x0000, 0x0000, /* position and control info*/
+ 0x0, 0x7C00,
+ 0x7C00, 0xFE00,
+ 0x7C00, 0x8600,
+ 0x7800, 0x8C00,
+ 0x7C00, 0x8600,
+ 0x5E00, 0xA300,
+ 0xF00, 0xD180,
+ 0x780, 0x8C0,
+ 0x3C0, 0x460,
+ 0x1C0, 0x220,
+ 0x80, 0x140,
+ 0x0, 0x80,
+ 0x7C00, 0x7E00,
+ 0x4200, 0x6300,
+ 0x4200, 0x6300,
+ 0x7C00, 0x7E00,
+ 0x4000, 0x6000,
+ 0x4000, 0x6000,
+ 0x4000, 0x6000,
+ 0x0, 0x0,
+ 0x7000, 0x7800,
+ 0x2000, 0x3000,
+ 0x2000, 0x3000,
+ 0x2000, 0x3000,
+ 0x2000, 0x3000,
+ 0x2000, 0x3000,
+ 0x7000, 0x7800,
+ 0x0, 0x0,
+ 0x7800, 0x7C00,
+ 0x8400, 0xC600,
+ 0x8000, 0xC000,
+ 0x8000, 0xC000,
+ 0x8000, 0xC000,
+ 0x8400, 0xC600,
+ 0x7800, 0x7C00,
+ 0x0, 0x0,
+ 0x8400, 0xC600,
+ 0x8800, 0xCC00,
+ 0x9000, 0xD800,
+ 0xE000, 0xF000,
+ 0x9000, 0xD800,
+ 0x8800, 0xCC00,
+ 0x8400, 0xC600,
+ 0xFFFF, 0xFFFF /* end markers */
+ };
+
+
+
diff --git a/CURSOR.C b/CURSOR.C
new file mode 100644
index 0000000..aa731d0
--- /dev/null
+++ b/CURSOR.C
@@ -0,0 +1,73 @@
+/*----------------------------------------------------------------------*/
+/* */
+/* cursor.c -- Plug in different cursors */
+/* */
+/*----------------------------------------------------------------------*/
+
+#include <system.h>
+#include <prism.h>
+
+extern struct Window *mainW;
+extern BOOL inside;
+extern SHORT curpen;
+
+extern UWORD fillCurs[],crossCurs[],zzz[],size[], pick[];
+
+typedef struct { SHORT w,h,xoffs,yoffs; UWORD *bits; } CursDesc;
+
+CursDesc cursDir[] = {
+ {13,17,7,16, fillCurs},
+ {15,15,8,7, crossCurs},
+ {16,25,8,12, zzz},
+ {8,31,0,0, size},
+ {11,43,1,0, pick}
+ };
+
+
+static SHORT nullSprite[2] = {0};
+
+SHORT curCursor = DEFCURSOR; /* the actual cursor now showing */
+SHORT curPaintCursor = DEFCURSOR; /* the painting cursor */
+SHORT paintCursOn = YES; /* is the painting cursor showing */
+
+
+/* these ignore the Painting cursor */
+HideCursor() { SetPointer(mainW, nullSprite, 0, 0, 0, 0);}
+DefaultCursor() {ClearPointer(mainW);}
+
+JamCursor(n) int n; {
+ CursDesc *cd = &cursDir[n-2];
+ SetPointer(mainW, cd->bits,cd->h,cd->w,-cd->xoffs,-cd->yoffs);
+ }
+
+void SetCursor(n) {
+ curCursor = n;
+ if (n==NOCURSOR) HideCursor();
+ else if (n==DEFCURSOR) DefaultCursor(); else JamCursor(n);
+ }
+
+/* this affects the Painting cursor */
+void SetPaintCursor(n) int n; {
+ curPaintCursor = n;
+ if (!inside) SetCursor(DEFCURSOR);
+ else SetCursor((paintCursOn||!((n==DEFCURSOR)||(n==CROSSCURSOR)))? n: NOCURSOR);
+ }
+
+DefaultPaintCursor() {
+ SetPaintCursor( (curpen==USERBRUSH)? DEFCURSOR: CROSSCURSOR);
+ }
+
+/* restore cursor to current Paint Cursor state */
+ResetCursor() {
+ if ( (curPaintCursor ==DEFCURSOR) || (curPaintCursor == CROSSCURSOR))
+ DefaultPaintCursor();
+ else SetPaintCursor(curPaintCursor);
+ }
+
+/* Change the Paint Cursor from showing to not or vice versa */
+TogCursor() { paintCursOn = !paintCursOn; ResetCursor(); }
+
+/* These must work event outside of paint window */
+
+ZZZCursor() { JamCursor(ZZZCURSOR); }
+UnZZZCursor() { SetCursor(curCursor); }
diff --git a/DALLOC.C b/DALLOC.C
new file mode 100644
index 0000000..7db858c
--- /dev/null
+++ b/DALLOC.C
@@ -0,0 +1,38 @@
+/*--------------------------------------------------------------*/
+/* */
+/* dalloc.c */
+/* */
+/* lets you specify flags but remembers the length for */
+/* freeing. */
+/*--------------------------------------------------------------*/
+
+#include <exec\types.h>
+#include <exec\nodes.h>
+#include <exec\memory.h>
+
+/* first 4 bytes of allocated area contain the length of the area.
+This length is the number of bytes allocated by AllocMem, ie includes
+the 4 bytes for itself */
+
+/* size in bytes */
+UBYTE *DAlloc(size,flags) LONG size; USHORT flags; {
+ LONG *p;
+ LONG asize = size+4;
+ p = (LONG *)AllocMem(asize,flags);
+ if (p==NULL){
+ return((UBYTE *)p);
+ }
+ *p++ = asize; /* post-bump p to point at clients area*/
+ return((UBYTE *)p);
+ }
+
+UBYTE *ChipAlloc(size) LONG size; {
+ return(DAlloc(size,MEMF_PUBLIC|MEMF_CHIP));
+ }
+
+DFree(p) UBYTE *p; {
+ if (p!=NULL) {
+ p -= 4;
+ return(FreeMem(p, *((LONG *)p)));
+ }
+ }
diff --git a/DISPNUM.C b/DISPNUM.C
new file mode 100644
index 0000000..554c0e0
--- /dev/null
+++ b/DISPNUM.C
@@ -0,0 +1,144 @@
+/*----------------------------------------------------------------------*/
+/* */
+/* dispnum.c --Coordinate readout */
+/* */
+/*----------------------------------------------------------------------*/
+
+#include <system.h>
+#include <prism.h>
+
+extern SHORT xShft, yShft;
+extern BOOL titleShowing;
+extern struct RastPort screenRP;
+extern SHORT curFormat;
+extern SHORT curMBarH;
+#define local static
+
+/*--------------------------------------------------- */
+/* pad string a out (on left) to n chars and store in b */
+
+strpad(a,b,n,neg) char *a,*b; SHORT n; BOOL neg; {
+ SHORT i,m,pad;
+ m = MIN(n,strlen(a));
+ pad = n-m;
+ for (i=pad; i<n; i++) b[i] = *a++;
+ b[n] = 0;
+ for(i=0; i<pad; i++) b[i] = ' ';
+ if (neg &&(pad>0)) b[pad-1] = '-';
+ }
+
+TextXY(s,x,y) char *s; SHORT x,y; {
+ Move(&screenRP,PMapX(x),PMapY(y));
+ Text(&screenRP,s,strlen(s));
+ }
+/*
+DispColStr(s,x,y,col) char *s; SHORT x,y,col; {
+ SetAPen(&screenRP,col);
+ SetDrMd(&screenRP,JAM1);
+ TextXY(s,x,y);
+ }
+*/
+
+DispStr(s,x,y) char *s; SHORT x,y; {
+ SetAPen(&screenRP,0);
+ SetBPen(&screenRP,1);
+ SetDrMd(&screenRP,JAM2);
+ TextXY(s,x,y);
+ }
+
+DispNum(n,x,y,ln) {
+ char str[12],rtjust[12];
+ BOOL neg;
+ if (n<0) { neg = YES; n = -n;} else neg = NO;
+ stcu_d(str,n,9);
+ strpad(str,rtjust,ln,neg);
+ DispStr(rtjust,x,y); /* draw text */
+ }
+
+/* Bitmap name = xarrow, Amiga-BOB format. */
+/* Width = 11, Height = 5 */
+
+
+/* Bitmap name = xarrow, Amiga-BOB format. */
+/* Width = 11, Height = 5 */
+
+short xarrow[5] = { 0xFE60, 0xFF20, 0x0, 0xFF20, 0xFE60 };
+
+/* Bitmap name = yarrow, Amiga-BOB format. */
+/* Width = 5, Height = 10 */
+
+short yarrow[10] = { 0xD800, 0xD800, 0xD800, 0xD800, 0xD800,
+ 0xD800, 0x5000, 0x0, 0x8800, 0xD800 };
+
+local struct Image xarrIm = {0,2,11,5,1,xarrow,1,1,NULL};
+local struct Image yarrIm = {0,0,5,10,1,yarrow,1,1,NULL};
+
+UBYTE *modeNames[] = { "Object","Color","Replace","Smear","Shade",
+"Blend","Cycle" };
+
+extern PaintMode userPntMode;
+
+local SHORT pntx[3] = { 232, 134, 158 };
+local SHORT pnty[3] = { 14, 14, 7 };
+
+#define titleY
+DispPntMode() {
+ SHORT vx,vy;
+ if (titleShowing) {
+ SetAPen(&screenRP,1);
+ vx = pntx[curFormat];
+ vy = pnty[curFormat];
+ RectFill(&screenRP,PMapX(vx), 0, PMapX(vx+220), curMBarH-2);
+ DispStr(modeNames[userPntMode], vx, vy);
+/**
+ if (curFormat == 2) {
+ SetAPen(&screenRP,0);
+ Move(&screenRP, 0, curMBarH-2);
+ Draw(&screenRP, 639, curMBarH-2);
+ }
+**/
+ }
+ }
+
+ClearXY() {
+ if (titleShowing) {
+ SetAPen(&screenRP,1);
+ RectFill(&screenRP,PMapX(388), PMapY(0), PMapX(564), curMBarH-2);
+ }
+ }
+
+/***
+extern char dpaintTitle[];
+DispDPaint() {
+ if (titleShowing) DispColStr(dpaintTitle,VMapX(3),VMapY(7),2); }
+***/
+
+extern char version[];
+DispAvailMem() {
+ int m,vy,l;
+ if (titleShowing) {
+ vy = pnty[curFormat];
+ DispStr(version,0,vy);
+ l = TextLength(&screenRP, version, strlen(version));
+ m = AvailMem(MEMF_PUBLIC);
+ DispNum(m,VMapX(l),vy,7);
+ }
+ }
+
+#define XMIDP 452
+#define YMIDP 544
+SHORT numW[] = { 3*8*2,3*8,3*9};
+
+DispXY(x,y) {
+ SHORT vy,w;
+ if (titleShowing) {
+ vy = pnty[curFormat];
+ w = numW[curFormat];
+ DispNum(x, XMIDP - w, vy, 3);
+ DrawImage(&screenRP,&xarrIm, PMapX(XMIDP), PMapY(0));
+ DispNum(y, YMIDP - w, vy, 3);
+ DrawImage(&screenRP,&yarrIm, PMapX(YMIDP), PMapY(0));
+ }
+ }
+
+
diff --git a/DISTANCE.C b/DISTANCE.C
new file mode 100644
index 0000000..a79ffe1
--- /dev/null
+++ b/DISTANCE.C
@@ -0,0 +1,20 @@
+/*----------------------------------------------------------------------*/
+/* */
+/* distance.c -- Euclidean Distance */
+/* */
+/*----------------------------------------------------------------------*/
+#include <exec\types.h>
+
+/*----------------------------------------------------------------------*/
+/* returns sqroot(dx*dx + dy*dy); */
+/*----------------------------------------------------------------------*/
+SHORT Distance(dx,dy) SHORT dx,dy; {
+ SHORT v,t,i;
+ long n;
+ n = (long)dx*(long)dx + (long)dy*(long)dy;
+ i = 1024;
+ v = 0;
+ while (i!=0) { t = v+i; if ( ((long)t*(long)t) <= n ) v = t; i >>= 1; }
+ return(v);
+ }
+
diff --git a/DOPALETT.C b/DOPALETT.C
new file mode 100644
index 0000000..db85b3e
--- /dev/null
+++ b/DOPALETT.C
@@ -0,0 +1,66 @@
+/*----------------------------------------------------------------------*/
+/* */
+/* dopalette -- invoke the palette tool */
+/* */
+/*----------------------------------------------------------------------*/
+
+#include <system.h>
+#include <prism.h>
+
+extern SHORT nColors;
+extern Range cycles[];
+extern struct Window *mainW;
+extern Range *shadeRange;
+extern Box bigBox;
+extern BOOL skipRefresh;
+extern PaletteGlobals *paletteGlobals;
+
+/* map a number i, in [0..63], to logarithmic range */
+/* this maps 63 to 8192(OnePerTick), and maps 0 to 36, about 227 ticks
+ per change, i.e. nearly 4 seconds . */
+
+rateFromIndex(i) int i; {
+ int base;
+ i++;
+ base = 1 << ((i >> 3) + 5);
+ return (base + ((i & 7) * base) / 8);
+ }
+
+/* this is the exact inverse of the above function*/
+indexFromRate(n) int n; {
+ int j;
+ int hibit, mod;
+ hibit = (1 << 15);
+ for (j = 15; j >= 0; j--) {
+ if (hibit & n) {
+ mod = n - hibit;
+ return ((j - 5) * 8 + (mod * 8) / hibit - 1);
+ }
+ hibit >>= 1;
+ }
+ }
+/* ----- Display color pallet Control ----- */
+void ShowPallet() {
+ int i;
+ BOOL res;
+ UndoSave();
+ PauseCCyc();
+ for (i=1; i<MAXNCYCS; i++) cycles[i].rate = indexFromRate(cycles[i].rate);
+ FreeTmpRas();
+ for (;;) {
+ res = PaletteTool(mainW,&paletteGlobals);
+ WaitRefrMessage();
+ if (res) break;
+ UpdtDisplay();
+ }
+ skipRefresh = YES; /* where this extra refresh comes from I don't know */
+ AllocTmpRas();
+ PaneRefresh(&bigBox);
+ for (i=1; i<MAXNCYCS; i++) cycles[i].rate = rateFromIndex(cycles[i].rate);
+ ResumeCCyc();
+ SetCycPaint();
+ DispPntMode();
+ if (cycles[0].low ==cycles[0].high) shadeRange = NULL;
+ else shadeRange = cycles;
+ }
+
diff --git a/DOSYMREQ.C b/DOSYMREQ.C
new file mode 100644
index 0000000..e0bf4ee
--- /dev/null
+++ b/DOSYMREQ.C
@@ -0,0 +1,25 @@
+/*----------------------------------------------------------------------*/
+/* */
+/* dosymreq.c -- */
+/* */
+/*----------------------------------------------------------------------*/
+
+#include <system.h>
+#include <prism.h>
+extern Box screenBox;
+extern struct Window *mainW;
+extern SHORT cpWidth;
+extern SHORT xShft,yShft;
+extern BOOL mirror;
+extern SHORT nSym;
+
+DoSymReq() {
+ BOOL mir = mirror;
+ SHORT n = nSym;
+ FreeTmpRas();
+ UndoSave(); /* because use UpdtDisplay to restore screen */
+ SymRequest(mainW, screenBox.w - cpWidth - 180, PMapY(120), &n, &mir);
+ UpdtDisplay();
+ SymSetNMir(n,mir);
+ AllocTmpRas();
+ }
diff --git a/DOTBMS.C b/DOTBMS.C
new file mode 100644
index 0000000..f4f8f5d
--- /dev/null
+++ b/DOTBMS.C
@@ -0,0 +1,138 @@
+/* Bitmap name = dots1, Amiga-BOB format. */
+/* Width = 5, Height = 5 */
+
+short dots10[5] = {
+ 0x8000,
+ 0x0,
+ 0x800,
+ 0x0,
+ 0x4000
+ };
+
+
+
+/* Bitmap name = dots2, Amiga-BOB format. */
+/* Width = 9, Height = 9 */
+
+short dots20[9] = {
+ 0x800,
+ 0x0,
+ 0x0,
+ 0x80,
+ 0x8800,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x400
+ };
+
+
+
+/* Bitmap name = dots3, Amiga-BOB format. */
+/* Width = 13, Height = 13 */
+
+short dots30[13] = {
+ 0x400,
+ 0x0,
+ 0x40,
+ 0x4000,
+ 0x208,
+ 0x0,
+ 0x0,
+ 0x400,
+ 0x8010,
+ 0x0,
+ 0x0,
+ 0x800,
+ 0x80
+ };
+
+
+
+/* Bitmap name = dots4, Amiga-BOB format. */
+/* Width = 17, Height = 17 */
+
+short dots40[34] = {
+ 0x40, 0x0,
+ 0x0, 0x0,
+ 0x1000, 0x0,
+ 0x4, 0x0,
+ 0x0, 0x0,
+ 0x100, 0x0,
+ 0x0, 0x0,
+ 0x8000, 0x0,
+ 0x0, 0x8000,
+ 0x40, 0x0,
+ 0x0, 0x0,
+ 0x0, 0x0,
+ 0x2000, 0x0,
+ 0x8, 0x0,
+ 0x0, 0x0,
+ 0x0, 0x0,
+ 0x100, 0x0
+ };
+
+
+
+/* Bitmap name = dots5, Amiga-BOB format. */
+/* Width = 21, Height = 21 */
+
+short dots50[42] = {
+ 0x80, 0x0,
+ 0x0, 0x0,
+ 0x1, 0x0,
+ 0x2000, 0x0,
+ 0x0, 0x0,
+ 0x40, 0x0,
+ 0x0, 0x0,
+ 0x4, 0x0,
+ 0x0, 0x800,
+ 0x400, 0x0,
+ 0x0, 0x0,
+ 0x8000, 0x0,
+ 0x0, 0x0,
+ 0x82, 0x0,
+ 0x0, 0x1000,
+ 0x2000, 0x0,
+ 0x0, 0x0,
+ 0x0, 0x0,
+ 0x0, 0x0,
+ 0x8, 0x0,
+ 0x100, 0x0
+ };
+
+
+
+/* Bitmap name = dots6, Amiga-BOB format. */
+/* Width = 25, Height = 25 */
+
+short dots60[50] = {
+ 0x10, 0x0,
+ 0x0, 0x0,
+ 0x0, 0x0,
+ 0x1000, 0x0,
+ 0x0, 0x800,
+ 0x80, 0x0,
+ 0x4, 0x0,
+ 0x0, 0x0,
+ 0x0, 0x2000,
+ 0x0, 0x0,
+ 0x8000, 0x0,
+ 0x80, 0x0,
+ 0x0, 0x80,
+ 0x0, 0x0,
+ 0x801, 0x0,
+ 0x0, 0x0,
+ 0x0, 0x0,
+ 0x0, 0x0,
+ 0x10, 0x0,
+ 0x0, 0x0,
+ 0x800, 0x800,
+ 0x0, 0x0,
+ 0x0, 0x0,
+ 0x0, 0x0,
+ 0x10, 0x0
+ };
+
+
+
diff --git a/DPHOOK.H b/DPHOOK.H
new file mode 100644
index 0000000..bd80843
--- /dev/null
+++ b/DPHOOK.H
@@ -0,0 +1,16 @@
+/*----------------------------------------------------------------------*/
+/* */
+/* dphook.h */
+/* */
+/*----------------------------------------------------------------------*/
+
+typedef struct {
+ struct BitMap *bitmap; /* the bitmap to be shared by DPaint */
+ struct BitMap *dpScreenBitMap; /* DPaint's screen bitmap */
+ struct ViewPort *vport; /* DPaint's ViewPort */
+ SHORT format; /* 0: 320x200, 1:640x200, 2: 640x400 */
+ SHORT refCount; /* initialize to zero: don't free bitmap if > 0 */
+ SHORT version; /* = 1 for DPaint version 1.0 */
+ BMOB *brush; /* pointer to DPaints brush: for possible
+ future enhancements */
+ } DPHook;
diff --git a/DPIFF.C b/DPIFF.C
new file mode 100644
index 0000000..1cb1937
--- /dev/null
+++ b/DPIFF.C
@@ -0,0 +1,341 @@
+/** dpiff.c ******************************************************************/
+/* */
+/* DPAINT IFF file I/O procedures */
+/* */
+/* Date Who Changes */
+/* --------- --- ----------------------------------------------------------- */
+/* 01-Sep-85 mrp created */
+/* 27-Sep-85 jhm & sss rewrote using ilbm.h, packer.h, & iff.h */
+/* 01-Oct-85 dds modified for DPaint. */
+/* 07-Nov-85 sss Dive into non-ILBM FORMs looking for an ILBM. */
+/*****************************************************************************/
+#include "system.h"
+#include "prism.h"
+#include "dpiff.h"
+
+#define MaxDepth 5
+static IFFP ifferror = 0;
+
+extern Box screenBox;
+
+#define CkErr(expression) {if (ifferror == IFF_OKAY) ifferror = (expression);}
+
+/*****************************************************************************/
+/* IffErr */
+/* */
+/* Returns the iff error code and resets it to zero */
+/* */
+/*****************************************************************************/
+IFFP IffErr()
+ {
+ IFFP i;
+ i = ifferror;
+ ifferror = 0;
+ return(i);
+ }
+
+/*------------ ILBM reader -----------------------------------------------*/
+/* DVCS' number of planes in a bitmap. Could use MaxAmDepth. */
+
+/* Here's our "client frame" for reading an IFF file, looking for ILBMs.
+ * We use it to stack BMHD & CMAP properties. */
+typedef struct {
+ ClientFrame clientFrame;
+ UBYTE foundBMHD;
+ UBYTE nColorRegs;
+ BitMapHeader bmHdr;
+ Color4 colorMap[1<<MaxDepth];
+ /* [TBD] Place to store any other shared PROPs encountered in a LIST.*/
+ } ILBMFrame;
+
+
+/* GetPicture communicates with GetFoILBM via these.*/
+static struct BitMap *gpBitmap = NULL;
+static WORD *gpColorMap = NULL;
+static BYTE *gpBuffer = NULL;
+static LONG gpBufsize = 0;
+static BOOL picNotFit = FALSE;
+
+#if 0
+prbmHdr(bmHdr) BitMapHeader *bmHdr; {
+ printf("bmHdr->w %ld ",bmHdr->w); printf("bmHdr->h %ld\n",bmHdr->h);
+ printf("bmHdr->x %ld ",bmHdr->x); printf("bmHdr->y %ld\n",bmHdr->y);
+ printf("bmHdr->depth %ld ",bmHdr->depth); printf("bmHdr->nPlanes %ld\n",bmHdr->nPlanes);
+ printf("bmHdr->masking %ld ",bmHdr->masking);
+ printf("bmHdr->pixelFormat %ld\n",bmHdr->pixelFormat);
+ printf("bmHdr->compression %ld\n",bmHdr->compression);
+ printf("bmHdr->pad1 %ld",bmHdr->pad1);
+ printf("bmHdr->transparentColor %ld\n",bmHdr->transparentColor);
+ }
+#endif
+
+/*----------------------------------------------------------------------*/
+/* */
+/* MBMGetFoILBM() */
+/* Used by GetMaskBM to handle every FORM in an IFF file. */
+/* Reads FORM ILBMs and skips all other FORMs. */
+/* Inside a FORM ILBM, */
+/* ILBMs with no BODY. */
+/* */
+/* Once we find a BODY chunk, we'll start reading into client's BitMap. */
+/* if it turns out to be malformed, we'll be sorry. */
+/*----------------------------------------------------------------------*/
+static MaskBM *gpMaskBM;
+static SHORT rngCnt;
+ResizeProc gpReSize;
+
+IFFP MBMGetFoILBM(parent) GroupContext *parent; {
+ /*compilerBug register*/ IFFP iffp;
+ GroupContext formContext;
+ ILBMFrame ilbmFrame;
+ register int i;
+ BOOL resizeFail;
+
+ /* Dive into any non-ILBM FORM looking for an ILBM.*/
+ if (parent->subtype != ID_ILBM) {
+ /* Open a non-ILBM FORM.*/
+ iffp = OpenRGroup(parent, &formContext);
+ CheckIFFP();
+ do {
+ iffp = GetF1ChunkHdr(&formContext);
+ } while (iffp >= IFF_OKAY);
+ if (iffp == END_MARK)
+ iffp = IFF_OKAY; /* then continue scanning the file */
+ CloseRGroup(&formContext);
+ return(iffp);
+ }
+
+ /* Open an ILBM FORM.*/
+ iffp = OpenRGroup(parent, &formContext);
+ CheckIFFP();
+
+ /* Place to store any ILBM properties that are found, starting from
+ * any values found in ancestors.*/
+ ilbmFrame = *(ILBMFrame *)parent->clientFrame;
+
+ do switch (iffp = GetFChunkHdr(&formContext)) {
+ case ID_BMHD: {
+ ilbmFrame.foundBMHD = TRUE;
+ iffp = GetBMHD(&formContext, &ilbmFrame.bmHdr);
+ break; }
+ case ID_CMAP: {
+ ilbmFrame.nColorRegs = 1 << MaxDepth; /* we have room for this many */
+ iffp = GetCMAP(
+ &formContext, (WORD *)&ilbmFrame.colorMap, &ilbmFrame.nColorRegs);
+ gpMaskBM->flags |= MBM_HAS_CMAP;
+ break;
+ }
+ case ID_GRAB: {
+ iffp = IFFReadBytes(&formContext, (BYTE *)&gpMaskBM->grab,
+ sizeof(Point2D));
+ gpMaskBM->flags |= MBM_HAS_GRAB;
+ break; }
+
+ case ID_CRNG:
+ if (( gpMaskBM->ranges != NULL) && (rngCnt<gpMaskBM->nRange))
+ iffp = IFFReadBytes(&formContext,
+ (BYTE *)&gpMaskBM->ranges[rngCnt++], sizeof(Range));
+ break;
+
+ case ID_BODY: {
+ if (!ilbmFrame.foundBMHD) return(BAD_FORM);
+
+ gpMaskBM->pos.x = ilbmFrame.bmHdr.x;
+ gpMaskBM->pos.y = ilbmFrame.bmHdr.y;
+ gpMaskBM->xAspect = ilbmFrame.bmHdr.xAspect;
+ gpMaskBM->yAspect = ilbmFrame.bmHdr.yAspect;
+ gpMaskBM->masking = ilbmFrame.bmHdr.masking;
+ gpMaskBM->xpcolor = ilbmFrame.bmHdr.transparentColor;
+
+ if (gpMaskBM->grab.x > ilbmFrame.bmHdr.w)
+ gpMaskBM->grab.x = ilbmFrame.bmHdr.w;
+ if (gpMaskBM->grab.y > ilbmFrame.bmHdr.h)
+ gpMaskBM->grab.y = ilbmFrame.bmHdr.h;
+
+ /* Compare bmHdr dimensions with gpBitmap dimensions! */
+ if( (RowBytes(ilbmFrame.bmHdr.w) != gpBitmap->BytesPerRow)||
+ (ilbmFrame.bmHdr.h != gpBitmap->Rows) ||
+ (ilbmFrame.bmHdr.nPlanes != gpBitmap->Depth) ) {
+ /* didn't fit: must resize the destination */
+ resizeFail = (*gpReSize)(gpMaskBM,&ilbmFrame.bmHdr);
+ if (resizeFail ) return(BAD_FIT);
+ }
+
+ iffp = GetBODY(
+ &formContext, gpMaskBM->bitmap, gpMaskBM->mask,
+ &ilbmFrame.bmHdr, gpBuffer, gpBufsize);
+ if (iffp == IFF_OKAY) iffp = IFF_DONE; /* Eureka */
+ break; }
+ case END_MARK: { iffp = BAD_FORM; break; } /* No BODY chunk! */
+ } while (iffp >= IFF_OKAY); /* loop if valid ID of ignored chunk or a
+ * subroutine returned IFF_OKAY, i.e., no errors.*/
+
+ if (iffp != IFF_DONE) return(iffp);
+ CloseRGroup(&formContext);
+
+ /* It's a good ILBM, return the properties to the client.*/
+
+ /* Copy CMAP into client's storage.*/
+ /* nColorRegs is 0 if no CMAP; no data will be copied to gpColorMap.
+ * That's ok; client is left with whatever colors she had before.*/
+ if (gpColorMap!=NULL) for (i = 0; i < ilbmFrame.nColorRegs; i++)
+ gpColorMap[i] = ilbmFrame.colorMap[i];
+ return(iffp);
+ }
+
+/*****************************************************************************/
+/* MBMGetLiILBM() */
+/* Used by GetMaskBM to handle every LIST in an IFF file. */
+/* */
+/*****************************************************************************/
+IFFP MBMGetLiILBM(parent) GroupContext *parent; {
+ ILBMFrame newFrame; /* allocate a new Frame */
+
+ newFrame = *(ILBMFrame *)parent->clientFrame; /* copy parent frame */
+
+ return( ReadIList(parent, (ClientFrame *)&newFrame) );
+ }
+
+/*****************************************************************************/
+/* MBMGetPrILBM() */
+/* Used by GetMaskBM to handle every PROP in an IFF file. */
+/* Reads PROP ILBMs and skips all others. */
+/* */
+/*****************************************************************************/
+IFFP MBMGetPrILBM(parent) GroupContext *parent; {
+ /*compilerBug register*/ IFFP iffp;
+ GroupContext propContext;
+ ILBMFrame *ilbmFrame = (ILBMFrame *)parent->clientFrame;
+
+ iffp = OpenRGroup(parent, &propContext);
+ CheckIFFP();
+
+ switch (parent->subtype) {
+
+ case ID_ILBM: {
+ do switch (iffp = GetPChunkHdr(&propContext)) {
+ case ID_BMHD: {
+ ilbmFrame->foundBMHD = TRUE;
+ iffp = GetBMHD(&propContext, &ilbmFrame->bmHdr);
+ break; }
+ case ID_CMAP: {
+ ilbmFrame->nColorRegs = 1 << MaxDepth; /* room for this many */
+ iffp = GetCMAP(&propContext, (WORD *)&ilbmFrame->colorMap,
+ &ilbmFrame->nColorRegs);
+ gpMaskBM->flags |= MBM_HAS_CMAP;
+ break; }
+ } while (iffp >= IFF_OKAY); /* loop if valid ID of ignored chunk
+ * or a subroutine returned IFF_OKAY, i.e., no errors.*/
+ break;
+ }
+
+ default: iffp = IFF_OKAY; /* just continue scanning the file */
+ }
+
+ CloseRGroup(&propContext);
+ return(iffp == END_MARK ? IFF_OKAY : iffp);
+ }
+
+/*****************************************************************************/
+/* GetMaskBM() */
+/* */
+/* Get a picture from an IFF file */
+/* */
+/*****************************************************************************/
+BOOL GetMaskBM(file, maskBM, colorMap, reSize, buffer, bufsize)
+ LONG file; MaskBM *maskBM; WORD *colorMap;
+ ResizeProc reSize; BYTE *buffer; LONG bufsize;
+ {
+ ILBMFrame iFrame;
+ iFrame.clientFrame.getList = &MBMGetLiILBM;
+ iFrame.clientFrame.getProp = &MBMGetPrILBM;
+ iFrame.clientFrame.getForm = &MBMGetFoILBM;
+ iFrame.foundBMHD = FALSE;
+ iFrame.nColorRegs = 0;
+
+ gpReSize = reSize;
+ gpMaskBM = maskBM;
+ gpBitmap = maskBM->bitmap;
+ gpColorMap = colorMap;
+ gpBuffer = buffer;
+ gpBufsize = bufsize;
+ rngCnt = 0;
+ picNotFit = FALSE;
+ maskBM->grab.x = maskBM->grab.y = 0;
+
+ ifferror = ReadIFF(file, (ClientFrame *)&iFrame);
+ return( (BOOL)(ifferror != IFF_DONE) );
+ }
+
+/*****************************************************************************/
+/* PutMaskBM() */
+/* */
+/* Put a picture into an IFF file */
+/* This procedure is specific to VCS. It writes an entire BitMap. */
+/* Pass in mask == NULL for no mask. */
+/* */
+/* Buffer should be big enough for one packed scan line */
+/* */
+/*****************************************************************************/
+BOOL dorng = YES;
+
+BOOL PutMaskBM(file, maskBM, colorMap, buffer, bufsize)
+ LONG file; MaskBM *maskBM; WORD *colorMap;
+ BYTE *buffer; LONG bufsize;
+
+ {
+ BitMapHeader bmHdr;
+ GroupContext fileContext, formContext;
+ IFFP tmpifferror;
+ int i;
+
+ ifferror = InitBMHdr(&bmHdr,
+ maskBM->bitmap,
+ (int)maskBM->masking,
+ (maskBM->w <= 64)? (int)cmpNone : (int)cmpByteRun1,
+ (int)maskBM->xpcolor,
+ (int)screenBox.w,
+ (int)screenBox.h );
+
+ bmHdr.x = maskBM->pos.x;
+ bmHdr.y = maskBM->pos.y;
+ bmHdr.w = maskBM->w;
+
+#define BODY_BUFSIZE 512
+
+ if (bufsize > 2*BODY_BUFSIZE) {
+ GWriteDeclare(file, buffer+BODY_BUFSIZE, bufsize-BODY_BUFSIZE);
+ bufsize = BODY_BUFSIZE;
+ }
+
+ CkErr(OpenWIFF(file, &fileContext, szNotYetKnown) );
+ CkErr(StartWGroup(&fileContext, FORM, szNotYetKnown, ID_ILBM, &formContext) );
+
+ CkErr(PutCk(&formContext, ID_BMHD, sizeof(BitMapHeader), (BYTE *)&bmHdr));
+
+ if (colorMap!=NULL)
+ CkErr( PutCMAP(&formContext, colorMap, (UBYTE)maskBM->bitmap->Depth) );
+ if (maskBM->flags&MBM_HAS_GRAB) {
+ tmpifferror = PutCk(&formContext, ID_GRAB, sizeof(Point2D),
+ (BYTE *)&maskBM->grab);
+ CkErr(tmpifferror);
+ }
+ if (maskBM->flags&MBM_HAS_RANGES) {
+ for (i=0; i<maskBM->nRange; i++) {
+ tmpifferror = PutCk(&formContext, ID_CRNG, sizeof(Range),
+ (BYTE *)&maskBM->ranges[i]);
+ CkErr(tmpifferror);
+ }
+ }
+ tmpifferror = PutBODY(&formContext, maskBM->bitmap,
+ (BYTE *)((maskBM->masking == mskHasMask)? maskBM->mask: NULL),
+ &bmHdr, buffer, bufsize);
+ CkErr(tmpifferror);
+
+ CkErr( EndWGroup(&formContext) );
+ CkErr( CloseWGroup(&fileContext) );
+ GWriteDeclare(NULL, NULL, 0);
+ return( (BOOL)(ifferror != IFF_OKAY) );
+ }
+
+
diff --git a/DPIFF.H b/DPIFF.H
new file mode 100644
index 0000000..614558d
--- /dev/null
+++ b/DPIFF.H
@@ -0,0 +1,44 @@
+/** dpiff.h ******************************************************************/
+/* */
+/* DPAINT IFF file I/O procedures */
+/* */
+/*****************************************************************************/
+#ifndef DPIFF_H
+#define DPIFF_H
+
+#include "iff\ilbm.h"
+
+#define BAD_FIT -9
+
+extern IFFP IffErr(); /* returns an IFFP error code; see IFF.H */
+
+/* FLAGS */
+#define MBM_HAS_GRAB 1
+#define MBM_HAS_PUSE 2
+#define MBM_HAS_CMAP 4
+#define MBM_HAS_RANGES 8
+
+/* Range id */
+#define ID_CRNG MakeID('C','R','N','G')
+
+typedef BOOL (*ResizeProc)();
+
+typedef struct {
+ LONG flags;
+ struct BitMap *bitmap;
+ SHORT w; /* pixel width of bitmap */
+ UBYTE xAspect, yAspect;
+ Masking masking;
+ UBYTE *mask;
+ UBYTE xpcolor;
+ Point2D pos;
+ Point2D grab;
+ Range *ranges;
+ SHORT nRange;
+ } MaskBM;
+
+extern BOOL PutMaskBM(LONG, MaskBM *, WORD *, BYTE *, LONG);
+/* file, maskBM, colorMap, buffer, bufsize */
+
+extern BOOL GetMaskBM(LONG, MaskBM *, WORD *, ResizeProc, BYTE *,LONG );
+/* file maskBM colorMap reSize() buffer bufsize */
diff --git a/DPINIT.C b/DPINIT.C
new file mode 100644
index 0000000..b36912a
--- /dev/null
+++ b/DPINIT.C
@@ -0,0 +1,438 @@
+/*----------------------------------------------------------------------*/
+/* */
+/* dpinit.c -- initialization code */
+/* */
+/*----------------------------------------------------------------------*/
+
+#include <system.h>
+#include <prism.h>
+#include <librarie\dosexten.h>
+#include <dphook.h>
+#include <workbenc\startup.h>
+
+#define CLOSEWBNCH
+
+#define local static
+#define MaxWidth 640
+#define MaxHeight 400
+
+extern BOOL modeHelp;
+extern void mainRefresh();
+extern struct Menu *MainMenu;
+extern BMOB curpenob,curbr,origBr;
+extern void mainCproc(),mainPproc(),mainMproc();
+extern long GfxBase;
+extern long IntuitionBase;
+extern long IconBase;
+
+struct Window *OpenWindow();
+struct InputEvent *Intuition();
+struct Screen *OpenScreen();
+
+extern struct Window *mainW;
+extern struct Screen *screen;
+extern struct RastPort *mainRP;
+extern struct ViewPort *vport;
+extern BOOL haveWBench;
+extern BOOL underWBench;
+extern Box mainBox;
+extern Pane mainP;
+extern SHORT curFormat; /* current screen format */
+extern SHORT curDepth;
+extern SHORT curMBarH;
+extern SHORT xShft,yShft;
+extern SHORT nColors;
+
+extern SHORT prevColors[32];
+extern UBYTE initBGCol[], initFGCol[];
+extern Box screenBox;
+extern struct BitMap hidbm;
+extern struct TmpRas tmpRas;
+extern struct RastPort tempRP;
+extern struct RastPort screenRP;
+
+extern UBYTE picname[];
+extern struct TextAttr TestFont;
+extern SHORT fmt,deep;
+extern struct Process *myProcess;
+extern struct Window *svWindowPtr;
+extern UBYTE dpaintTitle[];
+
+local struct NewScreen ns = {
+ 0, 0, /* start position */
+ 640, 200, 3, /* width, height, depth */
+ 0, 1, /* detail pen, block pen */
+ HIRES, /* viewing mode */
+ CUSTOMSCREEN, /* screen type */
+ &TestFont, /* font to use */
+ dpaintTitle, /* default title for screen */
+ NULL /* pointer to additional gadgets */
+ };
+
+local struct NewWindow nw = {0};
+
+TryOpenLib(name) char *name; {
+ LONG libadr = OpenLibrary(name, 0);
+ if (libadr == NULL) { InfoMessage("Can't open library",name); exit(); }
+ return(libadr);
+ }
+
+CloseWB() {
+ struct Window *tw,*dosWin;
+ if (!underWBench) {
+ nw.Type = WBENCHSCREEN;
+ nw.Width = nw.Height = 1;
+ tw = OpenWindow(&nw);
+ dosWin = tw->Parent;
+ CloseWindow(tw);
+ CloseWindow(dosWin);
+ }
+ if (CloseWorkBench()) haveWBench = NO;
+ else InfoMessage(" Couldn't close", "WorkBench");
+ }
+
+BailOut() {
+ myProcess->pr_WindowPtr = (APTR)svWindowPtr;
+ OpenWorkBench();
+ CloseLibrary(GfxBase);
+ CloseLibrary(IntuitionBase);
+ exit();
+ }
+
+extern MagContext magCntxt;
+extern Pane magP;
+extern void magRefresh();
+extern void RecChange();
+
+InitMag() {
+ magCntxt.srcRP = mainRP;
+ magCntxt.srcBox = &mainP.box;
+ magCntxt.magBM = mainRP->BitMap;
+ magCntxt.magBox = &magP.box;
+ magCntxt.updtProc = &RecChange;
+ magCntxt.srcPos.x = 0;
+ magCntxt.srcPos.y = curMBarH;
+ magCntxt.magN = PMapX(10);
+ PaneCreate(&magP, &screenBox ,HANGON, mainCproc, mainMproc, magRefresh, MAGWIN);
+ SetMagContext(&magCntxt);
+ MagState(NO);
+ }
+
+struct TextFont *screenFont= NULL;
+
+InitScreenFont() {
+ screenFont = (struct TextFont *)OpenFont(&TestFont);
+ SetFont(&screenRP, screenFont);
+ }
+
+/*------initialize current brush ----------------*/
+extern struct BitMap brSVBM,brBM,penSVBM,penBM;
+extern BMOB curbr,curpenob;
+
+/** init default picture path **/
+extern UBYTE picpath[], *picpths[];
+local UBYTE *picpths[3] = {"lo-res","med-res","hi-res"};
+InitPicPath() {strcpy(picpath,picpths[curFormat]); }
+
+extern struct BitMap *clientBitMap;
+extern DPHook *dphook;
+extern BOOL myDPHook;
+extern UBYTE DPName[];
+extern BOOL largeMemory, loadAFile;
+
+#ifdef DOWB
+extern struct WBStartup *WBenchMsg;
+#endif
+#define HALFMEG (1<<19)
+
+DPInit(argc,argv) int argc; char *argv[]; {
+ SHORT fmt,deep;
+ SHORT initbg,initfg;
+ BOOL closeWB= NO,doOverlay = NO, keepWB = NO;
+ LONG avMem;
+
+ FreeUpMem(); /* free up any memory with 0 ref count */
+
+ avMem = AvailMem(MEMF_PUBLIC);
+ largeMemory = (avMem>(256*1024));
+
+ GfxBase = TryOpenLib("graphics.library");
+ IntuitionBase = TryOpenLib("intuition.library");
+ IconBase = TryOpenLib("icon.library");
+
+ myProcess = (struct Process *)FindTask(0);
+ svWindowPtr = (struct Window *)myProcess->pr_WindowPtr;
+
+ fmt = 0; deep = 5; /* default to LORES, 5 planes */
+
+#ifdef DOWB
+ /* --- Test if we were called from the CLI or WORKBENCH --- */
+ if (argc==0) {
+ underWBench = YES;
+ if (WBenchMsg->sm_NumArgs>0) {
+ strcpy(picname,WBenchMsg->sm_ArgList->wa_Name);
+ loadAFile = YES;
+ }
+ }
+ else { underWBench = NO; }
+#endif
+
+ /* ----- See if Deluxe Video or anybody has planted hook */
+
+ dphook = (DPHook *)FindHook(DPName);
+
+ if ((dphook!=NULL)/*&&largeMemory*/) {
+ fmt = dphook->format;
+ clientBitMap = dphook->bitmap;
+ if (clientBitMap != NULL) {
+ hidbm = *clientBitMap; /* copy record, not pointer */
+ deep = MIN(hidbm.Depth,5);
+ doOverlay = YES;
+ }
+ else InfoMessage(" Null Client"," Bitmap");
+ }
+ else {
+ if (argc>1)
+ switch(*argv[1]) {
+ case 'l': fmt = 0; break;
+ case 'm': fmt = 1; break;
+ case 'h': fmt = 2; break;
+ }
+
+ if (argc>2) deep = MAX(MIN((*argv[2]-'0'),5),1);
+
+ if (argc>3) switch (*argv[3]) {
+ case 'c': closeWB = YES; break;
+ case 'o': doOverlay = YES; break;
+ case 'n': keepWB = YES; break;
+ default: doOverlay = closeWB = YES; break;
+ }
+
+ if (!largeMemory) { /* 256K machine */
+ if (fmt==2) BailOut(); /* no way */
+ else closeWB = doOverlay = YES;
+ }
+
+ else if ((avMem<HALFMEG)&&(fmt==2)&&(deep>3)) closeWB = doOverlay = YES;
+
+ }
+
+ if (closeWB&&(!keepWB)) CloseWB();
+
+ SetOverlay(doOverlay);
+
+ SetFormat(fmt,deep); /* opens Screen, mainW, allocs hidbm, tmpRas */
+
+
+ if (dphook==NULL) { /* --- plant my own hook --- */
+ myDPHook = YES;
+ dphook = (DPHook *)DAlloc(sizeof(DPHook),MEMF_PUBLIC);
+ dphook->bitmap = &hidbm;
+ dphook->dpScreenBitMap = mainRP->BitMap;
+ dphook->format = fmt;
+ dphook->refCount = 0;
+ dphook->version = 1;
+ SetHook(DPName,dphook);
+ }
+ else {
+ myDPHook = NO;
+ dphook->refCount++;
+ }
+
+ dphook->vport = vport;
+ dphook->brush = &curbr;
+
+ InitMenu();
+
+ BasicBandW();
+
+ SetMenuStrip(mainW, MainMenu);
+
+ InitRastPort(&tempRP); /* multi-purpose RasterPort */
+ InitRastPort(&screenRP); /* always points at bare screen bitmap */
+ screenRP.BitMap = mainRP->BitMap;
+
+ InitScreenFont();
+
+ initbg = initBGCol[curDepth];
+ initfg = initFGCol[curDepth];
+ SetRast(mainRP,initbg);
+ tempRP.BitMap = &hidbm;
+
+ if (clientBitMap==NULL) SetRast(&tempRP,initbg);
+
+ PaneCreate(&mainP,&mainBox,HANGON,mainCproc,mainMproc,
+ mainRefresh,MAINWIN);
+ PaneInstall(&mainP);
+
+ InitPGraph();
+ PushGrDest(mainRP,&mainBox);
+ SolidPattern();
+
+ CPInit();
+ InitMag();
+
+ CPChgPen(0);
+ CPChgCol(initfg);
+ CPChgBg(initbg);
+
+ SymSet(6, YES, PMapX(MaxWidth/2), PMapY(MaxHeight/2));
+
+ TogBoth(); /* show the control panel initially */
+ ResetCursor();
+ SetModeMenu(modeHelp ? Color: Mask);
+ DispPntMode();
+ }
+
+local USHORT fmtMode[3] = {0,HIRES,HIRES|LACE};
+local SHORT fmtXShft[3] = {1,0,0};
+local SHORT fmtYShft[3] = {1,1,0};
+
+#ifdef ldkfg
+CloseDisp() {
+ ShowTitle(screen,NO);
+ ClearMenuStrip(mainW);
+ CloseFont(screenFont);
+ KillCCyc();
+ FreeSpare();
+ BMOBFreeTmp();
+ FreeBMOB(&origBr);
+ FreeBMOB(&curbr);
+ FreeBMOB(&curpenob);
+ FreeBitMap(&hidbm);
+ FreeTmpRas();
+ myProcess->pr_WindowPtr = (APTR)svWindowPtr;
+ CloseWindow(mainW);
+ CloseScreen(screen);
+ }
+
+ShutDown() {
+ FreeFonts();
+ CloseLibrary(GfxBase);
+ CloseLibrary(IntuitionBase);
+ OpenWorkBench();
+ }
+
+#endif
+
+CloseDisplay() {
+ ShowTitle(screen,NO);
+ ClearMenuStrip(mainW);
+ FreeFonts();
+ KillCCyc();
+ FreeSpare();
+ BMOBFreeTmp();
+ FreeBMOB(&origBr);
+ FreeBMOB(&curbr);
+ FreeBMOB(&curpenob);
+
+ if (clientBitMap == NULL) FreeBitMap(&hidbm);
+ if (myDPHook){ RemHook(DPName);DFree(dphook);}
+ else dphook->refCount--;
+
+ FreeTmpRas();
+ myProcess->pr_WindowPtr = (APTR)svWindowPtr;
+ CloseWindow(mainW);
+ CloseScreen(screen);
+ CloseLibrary(GfxBase);
+ CloseLibrary(IntuitionBase);
+ OpenWorkBench();
+ }
+
+/*----------------------------------------------------------------------*/
+/* */
+/* Memory requirement */
+/*
+ 2*depth*pagesize for visible display and hidbm
+ pagesize for tmpRas
+ (depth*pagesize)/WorkSpaceFactor for brush (minimal)
+ MINSPACE spare for overlays,menus, etc, fixed size
+
+ total = depth*(2*pagesize + pagesize/WorkSpaceFactor) + MINSPACE + pagesize;
+ max depth = (memavail-pagesize-MINSPACE)/(2*pagesize + pagesize/WorkSpaceFactor);
+
+ (mem-pagesize-MINSPACE)
+ = -----------------------------------------
+ (2*pagesize + pagesize/WorkSpaceFactor)
+------------------------------------------------------------------------*/
+
+/* require 1/3 of screen worth of workspace */
+#define WorkSpaceFactor 3
+
+/* minimum additional space of 12k */
+#define MINSPACE 12*1024
+
+/*----assumes screenBox already setup */
+int MaxDepth(fmt) SHORT fmt; {
+ ULONG psz = PlaneSize(screenBox.w,screenBox.h);
+ ULONG mem = AvailMem(MEMF_CHIP|MEMF_PUBLIC);
+ return((int) ( (mem-psz-MINSPACE)/(2*psz + psz/WorkSpaceFactor)) );
+ }
+
+SetFormat(fmt,depth)
+ SHORT fmt; /* 0 => 320x200xn, 1 => 640x200xn, 2 => 640x400xn*/
+ SHORT depth; /* number of planes */
+ {
+ if (fmt>0) depth = MIN(depth,4);
+ ns.ViewModes = fmtMode[fmt];
+ curFormat = fmt;
+ xShft = fmtXShft[fmt];
+ yShft = fmtYShft[fmt];
+ screenBox.w = ns.Width = PMapX(MaxWidth);
+ screenBox.h = ns.Height = PMapY(MaxHeight);
+ curMBarH = /*(curFormat==2)? 19:*/ 11;
+ mainBox.x = 0;
+ mainBox.y = curMBarH;
+ mainBox.w = screenBox.w;
+ mainBox.h = screenBox.h - mainBox.y;
+
+ depth = MIN(MaxDepth(fmt),depth);
+ if (depth==0) BailOut();
+
+ ns.Depth = curDepth = depth;
+
+ screen = OpenScreen(&ns);
+ if (screen == NULL) BailOut();
+
+ nw.Screen = screen;
+ nw.DetailPen = 0;
+ nw.BlockPen = 1;
+
+#ifdef THEIRWAY
+ nw.LeftEdge = screenBox.x;
+ nw.TopEdge = screenBox.y + curMBarH ;
+ nw.Width = screenBox.w;
+ nw.Height = screenBox.h - curMBarH;
+#else
+ nw.LeftEdge = screenBox.x;
+ nw.TopEdge = screenBox.y;
+ nw.Width = screenBox.w;
+ nw.Height = screenBox.h;
+#endif
+
+ nw.IDCMPFlags = RAWKEY |MOUSEBUTTONS |MENUPICK |
+ MENUVERIFY | REFRESHWINDOW| ACTIVEWINDOW | INACTIVEWINDOW;
+ nw.Flags = ACTIVATE |BACKDROP |BORDERLESS |REPORTMOUSE|
+ /* NOCAREREFRESH |*/ SIMPLE_REFRESH | RMBTRAP;
+ nw.Type = CUSTOMSCREEN; /* type of screen in which to open */
+ mainW = OpenWindow(&nw); /* open a window */
+
+ if (mainW == NULL) BailOut();
+
+ /* fix so Dos message requestors come up in my window */
+ myProcess->pr_WindowPtr = (APTR)mainW;
+
+ mainRP = mainW->RPort;
+ vport = &mainW->WScreen->ViewPort;
+
+ nColors = 1<<depth;
+
+ /* initialize hidden raster */
+ if (clientBitMap==NULL) NewSizeBitMap(&hidbm,depth,screenBox.w,screenBox.h);
+ AllocTmpRas();
+ mainRP->TmpRas = &tmpRas; /* temp raster for area filling*/
+ InitPicPath();
+ DefaultPalette();
+ }
+
+
diff --git a/DPINIT2.C b/DPINIT2.C
new file mode 100644
index 0000000..cbfe0fa
--- /dev/null
+++ b/DPINIT2.C
@@ -0,0 +1,126 @@
+/*----------------------------------------------------------------------*/
+/* */
+/* dpinit2.c -- initialization */
+/* */
+/*----------------------------------------------------------------------*/
+#include <system.h>
+#include <prism.h>
+
+#define local static
+#define fudgeFact 10
+
+extern struct Menu *MainMenu;
+extern SHORT curFormat;
+
+extern struct RastPort *mainRP;
+extern struct TextAttr curMIFont;
+extern SHORT xShft,yShft;
+extern struct Menu menus[];
+extern struct Screen *screen;
+
+SHORT widCorrect[3] = {-4,0,12};
+SHORT menuHeight[3] = {10,10,16};
+SHORT checkW[3] = {LOWCHECKWIDTH,CHECKWIDTH,CHECKWIDTH};
+SHORT curMIH;
+
+SHORT ComWidth() { return((SHORT)( (curFormat>0)? COMMWIDTH: LOWCOMMWIDTH)); }
+
+SHORT MaxMiLength(mi) struct MenuItem *mi; {
+ struct IntuiText *it;
+ SHORT w,max;
+ for (max = 0; mi != NULL; mi = mi->NextItem) {
+ it = (struct IntuiText *)(mi->ItemFill);
+ w = TextLength(mainRP,it->IText,strlen(it->IText))+12;
+ if (mi->Flags&COMMSEQ) w += ComWidth();
+ if (mi->Flags&CHECKIT) w += checkW[curFormat];
+ max = MAX(w,max);
+ }
+ return((SHORT)(max-10));
+ }
+
+InitMItems(mi,minW) struct MenuItem *mi; SHORT minW; {
+ SHORT i , y, x;
+ SHORT wid = MAX(MaxMiLength(mi) /*+widCorrect[curFormat]*/, minW );
+ y = mi->TopEdge;
+ x = mi->LeftEdge;
+ for ( i=0 ; mi != NULL; ++i, mi = mi->NextItem) {
+ if ((mi->Flags&ITEMTEXT)&&(mi->Flags&CHECKIT))
+ ((struct IntuiText *)(mi->ItemFill))->LeftEdge = checkW[curFormat];
+ mi->TopEdge = y;
+ mi->LeftEdge = x;
+ mi->Width = wid;
+ if (mi->Flags&COMMSEQ) mi->Width += ComWidth();
+ mi->Height = curMIH;
+ ((struct IntuiText *)(mi->ItemFill))->ITextFont = &curMIFont;
+ y += curMIH;
+ if (mi->SubItem!=NULL) InitMItems(mi->SubItem,0);
+ }
+ }
+
+
+InitMenu() {
+ SHORT i = 0,xl = PMapX(12);
+ struct Menu *mn = MainMenu;
+ curMIH = menuHeight[curFormat];
+ for (mn = menus; mn != NULL; ++i,mn = mn->NextMenu ) {
+ mn->LeftEdge = xl;
+ mn->Width = TextLength(screen->BarLayer->rp,
+ mn->MenuName,strlen(mn->MenuName)) +
+ widCorrect[curFormat] + fudgeFact;
+ xl += mn->Width;
+ mn->Flags = MENUENABLED;
+ InitMItems(mn->FirstItem, mn->Width);
+ }
+ }
+
+
+
+/* ----------------- Control Panel Inititialization -------------------*/
+
+local BYTE nrowTab[] = {1,2,4,4,8,8};
+local BYTE ncolTab[] = {1,1,1,2,2,4};
+
+extern SHORT NXMag,NYMag;
+extern BOOL cpShowing;
+extern SHORT penH,actH,colDspH,colBoxH,actUH,colNRows,curDepth,colNColumns;
+extern SHORT colUW,penUW,actUW,cpWidth;
+extern Pane penwin,actwin,cdspwin,colwin;
+extern void penMproc(), PenWPaint(), actMproc(), ActWPaint();
+extern void cDspMproc(), cDspPaint(),colMproc();
+extern void mainCproc(), ColWPaint();
+
+/* Initialize the control panel geometry and create Windows */
+
+CPInit(){
+ Box bx;
+ SHORT colBoxH;
+ cpShowing = NO;
+ NXMag = NYMag = 1;
+ if (curFormat==2) NYMag = 2;
+ if (curFormat!=0) NXMag = 2;
+
+ /* penH + actH + colDspH = colBoxH = 400 */
+
+ penH = PMapY(40);
+ actH = PMapY(216);
+
+ colDspH = PMapY(24);
+ colBoxH = PMapY(120);
+
+ actUH = PMapY(24);
+ colNRows = nrowTab[curDepth];
+ colNColumns = ncolTab[curDepth];
+ cpWidth = PMapX(48)+1;
+ colUW = (cpWidth-1)/colNColumns;
+ penUW = (cpWidth-1)/3;
+ actUW = (cpWidth-1)/2;
+ PaneCreate(&penwin,MakeBox(&bx,0,0,cpWidth,penH),HANGON,&mainCproc,
+ penMproc,PenWPaint,NULL);
+ PaneCreate(&actwin,MakeBox(&bx,0,penH,cpWidth,actH),HANGON,&mainCproc,actMproc,
+ ActWPaint,NULL);
+ PaneCreate(&cdspwin,MakeBox(&bx,0,penH+actH,cpWidth,colDspH),HANGON,&mainCproc,
+ cDspMproc, cDspPaint,NULL);
+ PaneCreate(&colwin,MakeBox(&bx,0,penH+actH+colDspH,cpWidth,colBoxH),HANGON,
+ mainCproc,colMproc,ColWPaint,NULL);
+ }
+
diff --git a/DPIO.C b/DPIO.C
new file mode 100644
index 0000000..b62677b
--- /dev/null
+++ b/DPIO.C
@@ -0,0 +1,351 @@
+/*----------------------------------------------------------------------*/
+/* */
+/* dpio.c -- Picture and Brush IO */
+/* */
+/*----------------------------------------------------------------------*/
+
+#include <system.h>
+#include <prism.h>
+#include "librarie\dos.h" /* for file io */
+#include <dpiff.h>
+#include <fnreq.h>
+
+extern struct Window *mainW;
+extern SHORT nColors;
+extern struct TmpRas tmpRas;
+extern SHORT xShft, yShft, nColors;
+extern struct ViewPort *vport;
+extern BMOB curbr;
+extern struct BitMap hidbm;
+extern Box screenBox;
+extern BOOL skipRefresh;
+extern SHORT curFormat,curxpc,curpen,curDepth;
+extern SHORT LoadBrColors[], prevColors[];
+extern Range cycles[];
+
+UBYTE loadStr[] = "Load";
+UBYTE saveStr[] = "Save";
+
+#define local static
+
+
+BOOL CombPathName(comb,path,finame) UBYTE *comb,*path,*finame; {
+ if (strlen(finame) <= 0) return(NO);
+ strcpy(comb,path);
+ ConcatPath(comb,finame);
+ return(YES);
+ }
+
+BOOL DoFnReq(title,doname,path,name) UBYTE *title,*doname,*path,*name; {
+ BOOL res;
+ UndoSave();
+ FreeTmpRas(); /* make room for Intuition to save screen under req*/
+ res = (BOOL)FN_Request(mainW,PMapX(20),PMapY(24),
+ path,name,NULL,title,NULL, doname);
+ AllocTmpRas();
+ magRefresh();
+ mainRefresh();
+ return(res);
+ }
+
+/*----------------------------------------------------------------------*/
+/* Picture */
+/*----------------------------------------------------------------------*/
+extern UBYTE picpath[31];
+extern UBYTE picname[31];
+
+ZapPicName() { picname[0] = 0; }
+
+BOOL MakePicName(nm) UBYTE nm[]; {return(CombPathName(nm,picpath, picname));}
+
+BOOL DoPicFnReq(title,doname) UBYTE *title, *doname;{
+ return(DoFnReq(title,doname,picpath,picname));
+ }
+
+
+/* ILBM IO */
+
+/* try to resize the pic to fit the one being read in */
+local BOOL badFit;
+BOOL ResizePic(mbm,bmhdr) MaskBM *mbm; BitMapHeader *bmhdr; {
+ if ((bmhdr->h == hidbm.Rows)&&(bmhdr->w == hidbm.BytesPerRow*8))
+ {
+ if (bmhdr->nPlanes< hidbm.Depth) ClearBitMap(&hidbm);
+ return(SUCCESS);
+ }
+ else return(FAIL);
+ }
+
+NoOpen(name) char *name; { InfoMessage(" Couldn't Open file:",name); }
+
+NoSave(name) char *name; { InfoMessage(" Couldn't Save to file:",name); }
+
+LoadPicNamed(name) char *name; {
+ LONG file;
+ MaskBM mbm;
+ WORD colors[32];
+ file = Open(name, MODE_OLDFILE);
+ if (file==0) { NoOpen(name); picname[0]=0; return(FAIL);}
+ ZZZCursor();
+ GetColors(colors); /* default values if fewer planes loaded */
+ mbm.flags = MBM_HAS_CMAP;
+ mbm.bitmap = &hidbm;
+ mbm.ranges = cycles;
+ mbm.nRange = MAXNCYCS;
+ badFit = NO;
+ if (SUCCESS == GetMaskBM(file, &mbm, colors,
+ &ResizePic,tmpRas.RasPtr, tmpRas.Size)) {
+ KillCCyc();
+ GetColors(prevColors);
+ LoadRGB4(vport,colors,nColors);
+ }
+ else {
+ if (IffErr()==BAD_FIT) InfoMessage(" Wrong format:", name);
+ else InfoMessage(" Couldn't load file",name);
+ ZapPicName();
+ }
+ Close(file);
+ UnZZZCursor();
+ }
+
+local BYTE xAspRat[3] = {x320x200Aspect,x640x200Aspect,x640x400Aspect};
+local BYTE yAspRat[3] = {y320x200Aspect,y640x200Aspect,y640x400Aspect};
+
+BOOL SavePicNamed(name) char *name; {
+ LONG file;
+ WORD colors[32];
+ BOOL res;
+ MaskBM mbm;
+ GetColors(colors);
+ ZZZCursor();
+ file = Open(name, MODE_NEWFILE);
+ if (file==0) { NoSave(name); return(FAIL); }
+ mbm.flags = MBM_HAS_CMAP|MBM_HAS_RANGES;
+ mbm.nRange = MAXNCYCS;
+ mbm.ranges = cycles;
+ mbm.bitmap = &hidbm;
+ mbm.w = hidbm.BytesPerRow*8;
+ mbm.mask = NULL;
+ mbm.masking = mskHasTransparentColor;
+ mbm.xpcolor = curxpc;
+ mbm.pos.x = mbm.pos.y = 0;
+ res = PutMaskBM(file, &mbm, colors, (UBYTE *)tmpRas.RasPtr, tmpRas.Size);
+ if (res) {
+ InfoMessage(" Couldn't save file",name);
+ ZapPicName();
+ }
+ else WriteProjectIcon(picpath,picname);
+ Close(file);
+ UnZZZCursor();
+ return(res);
+ }
+
+ChkFNRes(res) BOOL res; {
+ if (res== FN_NoSuchDrawer) {
+ InfoMessage(" Non existent drawer","");
+ }
+ }
+
+#ifdef DOWB
+LoadPic() {
+ UBYTE nm[60];
+ OffRefrAfterOv();
+ if (MakePicName(nm)) {
+ LoadPicNamed(nm);
+ Str(picname);
+ }
+ OnRefrAfterOv();
+ PaneRefrAll();
+ }
+#endif
+
+OpenPic() { UBYTE nm[60];
+ BOOL res;
+ InitRead(); /* bring in the reader overlay*/
+ res = DoPicFnReq("Load Picture",loadStr);
+ if (res == FN_OK) {
+ if (MakePicName(nm)) {
+ LoadPicNamed(nm);
+ StuffSaveStr(picname);
+ }
+ }
+ else ChkFNRes(res);
+ PaneRefrAll();
+ }
+
+local UBYTE bkdotpic[] = "backup.pic";
+
+extern BOOL largeMemory;
+
+
+void SaveCurPic() {
+ UBYTE nm[60],bkupname[60];
+ LONG lock;
+ LONG err;
+ if (MakePicName(nm)) {
+ lock = Lock(nm, ACCESS_WRITE);
+ if (lock) {
+ CombPathName(bkupname,picpath,bkdotpic);
+ UnLock(lock);
+ if (DeleteFile(bkupname) == 0) {
+ err = IoErr();
+ if (err != ERROR_OBJECT_NOT_FOUND) return;
+ }
+ if (Rename(nm,bkupname) == 0) return;
+ }
+ SavePicNamed(nm);
+ StuffSaveStr(picname);
+ }
+ else InfoMessage("Invalid File name", "");
+ }
+
+SavePicAs() {
+ BOOL res;
+ InitWrite(); /* bring in the writer overlay*/
+ res = DoPicFnReq("Save Picture", saveStr);
+ if (res == FN_OK) SaveCurPic();
+ else ChkFNRes(res);
+ PaneRefrAll();
+ }
+
+SavePic() {
+ InitWrite(); /* bring in the writer overlay*/
+ UndoSave();
+ if (strlen(picname) == 0) SavePicAs();
+ else {
+ if (!largeMemory) InfoMessage(" Insert data disk","in disk drive");
+ SaveCurPic();
+ }
+ PaneRefrAll();
+ }
+
+/*----------------------------------------------------------------------*/
+/* Brush IO */
+/*----------------------------------------------------------------------*/
+extern UBYTE brspath[31];
+extern UBYTE brsname[31];
+
+ZapBrushName() { brsname[0] = 0; }
+BOOL MakeBrsName(nm) UBYTE nm[]; {return(CombPathName(nm,brspath, brsname));}
+BOOL DoBrsFnReq(title,doname) UBYTE *title,*doname;{return(DoFnReq(title,doname,brspath,
+ brsname));}
+
+
+SaveBrsNamed(name) char *name; {
+ LONG file;
+ BOOL res;
+ WORD colors[32];
+ MaskBM mbm;
+ GetColors(colors);
+ ZZZCursor();
+ file = Open(name, MODE_NEWFILE);
+ if (file==0) { NoSave(name); return(FAIL); }
+ mbm.flags = MBM_HAS_CMAP|MBM_HAS_GRAB;
+ mbm.bitmap = curbr.pict.bm;
+ mbm.w = curbr.pict.box.w;
+ mbm.masking = mskHasTransparentColor;
+ mbm.mask = NULL;
+ mbm.xpcolor = curbr.xpcolor;
+ mbm.pos.x = mbm.pos.y = 0;
+ mbm.grab.x = curbr.xoffs;
+ mbm.grab.y = curbr.yoffs;
+ res = PutMaskBM(file, &mbm, colors,(UBYTE *)tmpRas.RasPtr,tmpRas.Size);
+ if (res) { brsname[0] = 0; InfoMessage(" Couldn't save file",name);}
+ else WriteBrushIcon(brspath,brsname);
+ Close(file);
+ UnZZZCursor();
+ }
+
+/* try to resize the brush to fit the one being read in */
+
+local BOOL cantFit;
+
+#ifdef SIMPLEWAY
+BOOL ResizeBrush(mbm,bmhdr) MaskBM *mbm; BitMapHeader *bmhdr; {
+ if (BMOBNewSize(&curbr, bmhdr->nPlanes, bmhdr->w,bmhdr->h)) {
+ cantFit = YES;
+ return(FAIL);
+ }
+ ClearBitMap(curbr.pict.bm);
+ mbm->mask = curbr.mask;
+ return(SUCCESS);
+ }
+
+#else
+BOOL ResizeBrush(mbm,bmhdr) MaskBM *mbm; BitMapHeader *bmhdr; {
+ SHORT depth = bmhdr->nPlanes;
+ do {if (!BMOBNewSize(&curbr, depth, bmhdr->w, bmhdr->h))
+ goto alldone;
+ } while ((--depth)>=curDepth);
+ cantFit = YES;
+ return(FAIL);
+ alldone:
+ ClearBitMap(curbr.pict.bm);
+ mbm->mask = curbr.mask;
+ return(SUCCESS);
+ }
+#endif
+
+LoadBrsNamed(name) char *name; {
+ LONG file;
+ MaskBM mbm;
+ file = Open(name, MODE_OLDFILE);
+ if (file==0) { NoOpen(name); brsname[0] = 0; return(FAIL); }
+ ZZZCursor();
+ mbm.flags = 0;
+ mbm.bitmap = curbr.pict.bm;
+ mbm.mask = curbr.mask;
+ GetColors(LoadBrColors); /* default values if fewer planes loaded */
+ RestoreBrush();
+ cantFit = NO;
+ if (SUCCESS == GetMaskBM(file, &mbm, LoadBrColors,
+ &ResizeBrush,tmpRas.RasPtr, tmpRas.Size))
+ {
+ if (mbm.flags&MBM_HAS_GRAB) {
+ curbr.xoffs = mbm.grab.x;
+ curbr.yoffs = mbm.grab.y;
+ }
+ else {
+ curbr.xoffs = curbr.pict.bm->BytesPerRow*4;
+ curbr.yoffs = curbr.pict.bm->Rows/2;
+ }
+ curbr.xpcolor = mbm.xpcolor;
+ if (mbm.masking == (UBYTE)mskHasTransparentColor) BMOBMask(&curbr);
+ UserBr();
+ }
+ else {
+ InfoMessage(" Couldn't load brush",name);
+ if (cantFit) {
+ SelPen(0);
+ SetNextIMode(IM_draw);
+ }
+ else ZapBrushName();
+ }
+ Close(file);
+ UnZZZCursor();
+ }
+
+GetBrs() { BOOL res;
+ UBYTE nm[60];
+ InitRead(); /* bring in the reader overlay*/
+ res = DoBrsFnReq("Load Brush",loadStr);
+ if (res==FN_OK) {if (MakeBrsName(nm)) LoadBrsNamed(nm);}
+ else ChkFNRes(res);
+ PaneRefrAll();
+ }
+
+void SaveBrsAs() { UBYTE nm[60];
+ BOOL res;
+ InitWrite(); /* bring in the writer overlay*/
+ if (curpen!=USERBRUSH) {
+ InfoMessage(" Cant save Built-in", " brushes ");
+ }
+ else {
+ res = DoBrsFnReq("Save Brush", saveStr);
+ if (res == FN_OK) {if (MakeBrsName(nm)) SaveBrsNamed(nm);}
+ else ChkFNRes(res);
+ }
+ PaneRefrAll();
+ }
+
+
diff --git a/FILL.C b/FILL.C
new file mode 100644
index 0000000..ea77a3b
--- /dev/null
+++ b/FILL.C
@@ -0,0 +1,197 @@
+/*--------------------------------------------------------------*/
+/* Basic Seed Fill */
+/* */
+/* FillArea: fills all pixels which are the same color as */
+/* and 4-connected to the seed pixel */
+/*--------------------------------------------------------------*/
+
+#include <system.h>
+#include <prism.h>
+
+#define STSIZE 160
+#define UP 1
+#define DN -1
+
+#define local static
+
+extern SHORT ReadPixel();
+
+extern struct TmpRas tmpRas;
+extern struct RastPort *curRP, tempRP;
+extern Box clipBox;
+extern UWORD masks[];
+extern BOOL abortFlag;
+
+local SHORT fxmax,fymax,fxmin,fymin;
+local SHORT intoCol;
+
+
+OvflMsg() { KPrintF(" FILL Overflow"); }
+
+/** --------- Stack ----------------- */
+
+typedef struct{SHORT dir,xl,xr,y;} Span;
+local Span *stack;
+
+
+/* ----------Queue----------------- */
+SHORT oldest, nextVacant;
+local initStack(ps) Span *ps; { stack = ps; oldest = nextVacant = 0; }
+
+#define StackNotEmpty (oldest != nextVacant)
+
+local popSpan(d,xll,xrr,yy) SHORT *d,*xll,*xrr,*yy; {
+ Span *spn = &(stack[oldest]);
+ *d = spn->dir;
+ *xll = spn->xl;
+ *xrr = spn->xr;
+ *yy = spn->y;
+ oldest = (oldest+1)%STSIZE;
+ }
+
+local pushSpan(d,xll,xrr,yy) SHORT d,xll,xrr,yy; {
+ Span *spn = &(stack[nextVacant]);
+ spn->dir = d;
+ spn->xl = xll;
+ spn->xr = xrr;
+ spn->y =yy;
+ nextVacant = (nextVacant+1)%STSIZE;
+ if (nextVacant == oldest) {
+ if (--nextVacant<0) nextVacant = STSIZE-1;
+ OvflMsg();
+ }
+ }
+
+#ifdef slowButCorrect
+
+/* ----- "Inside" test for area fill */
+#define Inside(x,y) (ReadPixel(&tempRP,x,y)==intoCol)
+
+local SHORT firstRight(x,y) SHORT x,y; {
+ while( (x<=fxmax)&&(!Inside(x,y))) x++ ; return(x); }
+local SHORT firstLeft(x,y) SHORT x,y; {
+ while( (x>=fxmin)&&(!Inside(x,y))) x-- ; return(x); }
+local SHORT lastRight(x,y) SHORT x,y; {
+ while( (x<=fxmax)&&Inside(x,y)) x++ ; return((SHORT)(x-1)); }
+local SHORT lastLeft(x,y) SHORT x,y; {
+ while( (x>=fxmin)&&Inside(x,y)) x-- ; return((SHORT)(x+1)); }
+
+#else /* fast and complicated */
+
+local UWORD *WrdAddr(x,y) SHORT x,y; {
+ return((UWORD *)( ((ULONG)(tempRP.BitMap->Planes[0])) +
+ (ULONG)(y*tempRP.BitMap->BytesPerRow) +((x>>3)&0xfffe)));
+ }
+
+/* Search for the first bit not matching 'pat' to the right */
+local SHORT searchRight(x,y,pat) register SHORT x; SHORT y; register UWORD pat; {
+ register UWORD *wp,wrd;
+ wp = WrdAddr(x,y);
+ wrd = (pat^(*wp++))&masks[x&15]; /* turns all pat bits to 0's */
+ x = (x+16)&0xfff0;
+ while ( (wrd == 0) && (x <= fxmax) ) {wrd = pat^(*wp++); x += 16; }
+ x -= 16;
+ if (wrd) while ( (wrd & 0x8000) == 0 ) { wrd <<= 1; x++; }
+ else return((SHORT)(fxmax+1));
+ return((SHORT)MIN(x,fxmax+1));
+ }
+
+/* Search for the first bit not matching 'pat' to the left */
+local SHORT searchLeft(x,y,pat) register SHORT x; SHORT y; register UWORD pat; {
+ register UWORD *wp,wrd;
+ wp = WrdAddr(x,y);
+ wrd = (pat^(*wp--))&(~masks[(x&15)+1]);
+ x = (x&0xfff0) - 1;
+ while ( (wrd == 0) && (x >= fxmin) ) { wrd = pat^(*wp--); x -= 16; }
+ x += 16;
+ if (wrd) while ( (wrd & 1) == 0 ) { wrd >>= 1; x--; }
+ else return((SHORT)(fxmin-1));
+ return((SHORT)MAX(x,fxmin-1));
+ }
+
+/* --- find the first '0' i.e. "inside" bit to left (right) */
+#define firstLeft(x,y) searchLeft(x,y,0xffff)
+#define firstRight(x,y) searchRight(x,y,0xffff)
+
+/* --- find the last contiguous '0' i.e. "inside" bit to left (right) */
+#define lastLeft(x,y) (searchLeft(x,y,0) + 1)
+#define lastRight(x,y) (searchRight(x,y,0) - 1)
+
+#endif
+
+local fillStrip(xl,y,xr) SHORT xl,y,xr; {
+ PatHLine(xl,y,xr-xl+1);
+ Move(&tempRP,xl,y); Draw(&tempRP,xr,y);
+ }
+
+void FillArea(sx,sy)
+ SHORT sx,sy; /* seed point */
+ {
+ SHORT y,xr,xl,yn,xml,xmr,xtl,xtr,dir;
+ struct BitMap tempBM,*curbm;
+ Span dstack[STSIZE];
+
+ intoCol = ReadPixel(curRP,sx,sy);
+ if (intoCol==curRP->FgPen) return;
+ fxmin = clipBox.x;
+ fymin = clipBox.y;
+ fxmax = clipBox.x + clipBox.w -1;
+ fymax = clipBox.y + clipBox.h -1;
+ if ( sx<fxmin || sx>fxmax || sy<fymin || sy>fymax ) return;
+
+/* make a mask in the TmpRas that has 1's where the target bitmap is NOT
+ the color of the area being filled */
+ curbm = curRP->BitMap;
+ MakeMask(curbm, tmpRas.RasPtr, intoCol, NEGATIVE);
+ movmem(curbm,&tempBM,sizeof(struct BitMap));
+ tempBM.Depth = 1;
+ tempBM.Planes[0] = tmpRas.RasPtr;
+ tempRP.BitMap = &tempBM;
+ intoCol = 0;
+ SetAPen(&tempRP,1);
+
+ initStack(&dstack);
+ xl = lastLeft(sx,sy);
+ xr = lastRight(sx,sy);
+ fillStrip(xl,sy,xr);
+ pushSpan(DN,xl,xr,sy);
+ pushSpan(UP,xl,xr,sy);
+ while (StackNotEmpty) {
+
+ if (CheckAbort()) { UnDisplay(); break;}
+
+ popSpan(&dir,&xl,&xr,&y);
+ yn = y + dir;
+ if ((yn<fymin)|(yn>fymax)) continue;
+
+/** Note to me: this search can run all the way to the edge if we are
+ hitting a horiz wall, and the outside is all non fill-color. The
+ solution is to limit the search to the interval xl,xr. **/
+
+ /*-- find first 'inside' pixel on new line at or to right
+ of left pixel of old line */
+ if ((xml = firstRight(xl,yn)) > xr) continue;
+
+/** the firstLeft need not search past xl, and if it hits
+nothing then the lastRight need not be done at all */
+
+ /* -- find last pixel of last interval of 'inside' pixels
+ on new line and adjoining old line */
+ xmr = lastRight(firstLeft(xr,yn),yn);
+
+ /* -- find the left end of the left most adjoining interval*/
+ xtl = xml = lastLeft(xml,yn);
+ for (;;) {
+ xtr = lastRight(xtl,yn);
+ pushSpan(dir,xtl,xtr,yn);
+ fillStrip(xtl,yn,xtr);
+ if (xtr==xmr) break;
+ xtl = firstRight(xtr+1,yn);
+ }
+ xl -=2; xr +=2;
+ /* check for u-turns */
+ if ( (xml<=xl) && (firstLeft(xl,y)>=xml) ) pushSpan(-dir,xml,xl,yn);
+ if ( (xmr>=xr) && (firstRight(xr,y)<=xmr) ) pushSpan(-dir,xr,xmr,yn);
+ }
+ }
+
diff --git a/FNBMS.C b/FNBMS.C
new file mode 100644
index 0000000..20cb7b9
--- /dev/null
+++ b/FNBMS.C
@@ -0,0 +1,43 @@
+/*----------------------------------------------------------------------*/
+/* */
+/* fnbms.c -- Bitmaps for file name requestor arrows */
+/* */
+/*----------------------------------------------------------------------*/
+
+short up0[16] = {
+ 0x0,
+ 0x7FFE,
+ 0x7E7E,
+ 0x7C3E,
+ 0x781E,
+ 0x700E,
+ 0x6006,
+ 0x4002,
+ 0x7E7E,
+ 0x7E7E,
+ 0x7E7E,
+ 0x7E7E,
+ 0x7E7E,
+ 0x7E7E,
+ 0x7FFE,
+ 0x0
+ };
+
+short down0[16] = {
+ 0x0,
+ 0x7FFE,
+ 0x7E7E,
+ 0x7E7E,
+ 0x7E7E,
+ 0x7E7E,
+ 0x7E7E,
+ 0x7E7E,
+ 0x4002,
+ 0x6006,
+ 0x700E,
+ 0x781E,
+ 0x7C3E,
+ 0x7E7E,
+ 0x7FFE,
+ 0x0
+ };
diff --git a/FNREQ.C b/FNREQ.C
new file mode 100644
index 0000000..c99bcc5
--- /dev/null
+++ b/FNREQ.C
@@ -0,0 +1,794 @@
+/** fnreq.c ******************************************************************/
+/* */
+/* A file name requester */
+/* */
+/* Date Who Changes */
+/* --------- --- ----------------------------------------------------------- */
+/* 28-Aug-85 mrp created from imagedit's dos requester */
+/* 15-Sep-85 DDS modified to do own event processing, take x,y coord. */
+/* */
+/*****************************************************************************/
+/* 1) define a file and a drawer */
+/* */
+/* UBYTE mydrawer[31] = {""}; */
+/* UBYTE myfile[31] = {"test.vcs"}; */
+/* */
+/* 2) Issue a request, when the user picks your Load menu item */
+/* */
+/* res = FN_Request(mywindow,x,y,mydrawer,myfile,NULL,NULL,NULL,"Load"); */
+/* where res = TRUE if user did action, FALSE if he cancelled */
+/* */
+/*****************************************************************************/
+
+#include <system.h>
+#include <librarie\dos.h>
+#include <fnreq.h>
+#include <clib\ctype.h>
+
+#define local
+
+#define YES 1
+#define NO 0
+
+#define MAX(a,b) ((a)>(b)?(a):(b))
+#define MIN(a,b) ((a)<(b)?(a):(b))
+
+#define FN_GADGMIN 10 /* minimum gadget number used by this requester */
+#define FN_GADGMAX 29 /* maximum gadget number used by this requester */
+
+#define FN_CANCEL 10 /* user canceled the requester */
+#define FN_GOTNAME 11 /* user pressed return on name or picked OK gadget */
+#define FN_FILE 12 /* user selected filename gadget */
+#define FN_DRAWER 13 /* user selected drawer name gadget */
+#define FN_UP 14 /* user selected up one name gadget */
+#define FN_DOWN 15 /* user selected down one name gadget */
+#define FN_SLIDE 16 /* user did something to proportional gadget */
+
+#define HIWIDTH 320
+#define LOWIDTH 264
+#define REQW LOWIDTH /* width of requester */
+#define REQH 147 /* height of requester */
+
+#define MAXFNAMES 50 /* max number of file names in a dir */
+#define MAXSHOW 8 /* max number of file names visible in req*/
+
+local struct Window *reqwindow; /* window requester is in */
+local struct Requester fn_req = {0}; /* the requester */
+local LONG forbug = 0; /* fix 1.06 Intuition bug */
+local struct IntuiText fn_text[3]; /* requester text */
+local struct IntuiText gadg_text[2]; /* gadget text */
+
+local UBYTE deftitle[] = "FR";
+local UBYTE defcancel[] = "Cancel";
+local UBYTE defdoverb[] = "Ok";
+
+local LONG firstname=0; /* index of first name in the list */
+
+BOOL fndbg = NO;
+
+struct TextAttr reqfont = { /* font to use for requester text */
+ "topaz.font",
+ TOPAZ_SIXTY, /* will be set to user's preference */
+ 0,
+ 0};
+
+local UBYTE undofile[26];
+local UBYTE undodrawer[26];
+
+local SHORT reqX = 0; /* leftedge of requester */
+local SHORT reqY = 0; /* topedge of requester */
+local SHORT reqWidth = LOWIDTH;
+
+local BOOL dosready = FALSE; /* TRUE after requester is initialized */
+
+local UWORD reqpts[] = { /* xy table of border and reqion lines */
+ 2,1,
+ 2,REQH-2,
+ REQW-3,REQH-2,
+ REQW-3,12,
+ 2,12,
+ 2,1,
+ REQW-3,1,
+ REQW-3,93,
+ 2,93
+ };
+
+local struct Border reqborder = { /* border for the requester */
+ 0,0,
+ 0,1,
+ JAM1,
+ 9,
+ (SHORT *)&reqpts,
+ NULL};
+
+/*=======================*/
+/*== CANCEL GADGET ======*/
+/*=======================*/
+
+local UWORD dt0box1[] = {0,0,0,0,0,0,0,0,0,0};
+local UWORD dt0box2[] = {1,2,0,2,0,0,1,0,1,2};
+
+local struct Border dt0bor2 = { /* Blue box */
+ 0,0,
+ 0,1,
+ JAM1,
+ 5,
+ (SHORT *)&dt0box2,
+ NULL};
+local struct Border dt0bor1 = { /* Orange box */
+ 0,0,
+ 3,0,
+ JAM1,
+ 5,
+ (SHORT *)&dt0box1,
+ &dt0bor2};
+
+local struct Gadget cancelgadget = {
+ NULL,
+ -58,-20,
+ 48,17,
+ GADGHCOMP | GRELBOTTOM | GRELRIGHT,
+ RELVERIFY | GADGIMMEDIATE | ENDGADGET,
+ REQGADGET | BOOLGADGET,
+ (APTR)&dt0bor1,
+ NULL,
+ &gadg_text[0],
+ 0,
+ NULL,
+ FN_CANCEL,
+ NULL };
+
+/*=========================*/
+/*== GOTNAME, GADGET ======*/
+/*=========================*/
+
+local UWORD dt1box1[] = {0,0,0,0,0,0,0,0,0,0};
+local UWORD dt1box2[] = {1,2,0,2,0,0,1,0,1,2};
+
+local struct Border dt1bor2 = { /* Blue box */
+ 0,0,
+ 0,1,
+ JAM1,
+ 5,
+ (SHORT *)&dt1box2,
+ NULL};
+local struct Border dt1bor1 = { /* Orange box */
+ 0,0,
+ 3,0,
+ JAM1,
+ 5,
+ (SHORT *)&dt1box1,
+ &dt1bor2};
+
+local struct Gadget gotnamegadget = {
+ &cancelgadget,
+ 10,-20,
+ 64,17,
+ GADGHCOMP | GRELBOTTOM,
+ RELVERIFY | GADGIMMEDIATE | ENDGADGET,
+ REQGADGET | BOOLGADGET,
+ (APTR)&dt1bor1,
+ NULL,
+ &gadg_text[1],
+ 0,
+ NULL,
+ FN_GOTNAME,
+ NULL };
+
+
+/*======================*/
+/*== FILE, GADGET ======*/
+/*======================*/
+
+#define FG_WIDTH 184
+#define FG_HEIGHT 13
+
+
+local UWORD dt2box1[] = {
+ -2,-2,
+ FG_WIDTH+1,-2,
+ FG_WIDTH+1,FG_HEIGHT-3,
+ -2,FG_HEIGHT-3,
+ -2,-2};
+
+local struct Border dt2bor1 = {
+ 0,0,
+ 0,1,
+ JAM1,
+ 5,
+ (SHORT *)&dt2box1,
+ NULL};
+
+local struct StringInfo filestr = {
+ NULL, /* default and final string */
+ &undofile[0], /* optional undo buffer (later) */
+ 0, /* character position in buffer */
+ 25, /* max characters in buffer */
+ 0, /* buffer position of first displayed character */
+ 0,0,0,0,0,NULL,0,NULL }; /* intuition local variables */
+
+local struct Gadget filegadget = {
+ &gotnamegadget,
+ -FG_WIDTH-12,-33,
+ FG_WIDTH,FG_HEIGHT,
+ GADGHCOMP | GRELBOTTOM | GRELRIGHT,
+ RELVERIFY | GADGIMMEDIATE /* | ENDGADGET */ ,
+ REQGADGET | STRGADGET,
+ (APTR) &dt2bor1,
+ NULL,
+ NULL,
+ 0,
+ (APTR)&filestr,
+ FN_FILE,
+ NULL };
+
+/*========================*/
+/*== DRAWER, GADGET ======*/
+/*========================*/
+
+#define DG_WIDTH 184
+#define DG_HEIGHT 13
+
+
+local UWORD dt3box1[] = {
+ -2,-2,
+ DG_WIDTH+1,-2,
+ DG_WIDTH+1,DG_HEIGHT-3,
+ -2,DG_HEIGHT-3,
+ -2,-2};
+
+local struct Border dt3bor1 = {
+ 0,0,
+ 0,1,
+ JAM1,
+ 5,
+ (SHORT *)&dt3box1,
+ NULL};
+
+local struct StringInfo drawerstr = {
+ NULL,
+ &undodrawer[0],
+ 0,
+ 25,
+ 0,
+ 0,0,0,0,0,NULL,0,NULL };
+
+local struct Gadget drawergadget = {
+ &filegadget,
+ -DG_WIDTH-12,-48,
+ DG_WIDTH,DG_HEIGHT,
+ GADGHCOMP | GRELBOTTOM | GRELRIGHT,
+ RELVERIFY | GADGIMMEDIATE,
+ REQGADGET | STRGADGET,
+ (APTR) &dt3bor1,
+ NULL,
+ NULL,
+ 0,
+ (APTR)&drawerstr,
+ FN_DRAWER,
+ NULL };
+
+
+/*========================*/
+/*== SLIDER, GADGET ======*/
+/*========================*/
+
+local struct Image slideknob = {
+ 0,0,
+ 0,
+ 0,0,
+ 0,
+ 0,
+ 0,
+ NULL};
+
+local struct PropInfo slideprop =
+ {
+ AUTOKNOB | FREEVERT,
+ 0,0,
+ 0xffff,0x5555,
+ 12,52,
+ 0,0,
+ 2,0
+ };
+
+struct Gadget slidegadget =
+ {
+ &drawergadget,
+ -19,27,
+ 20,52,
+ GRELRIGHT | GADGIMAGE | GADGHCOMP | GADGHBOX,
+ RELVERIFY | GADGIMMEDIATE,
+ PROPGADGET| REQGADGET,
+ (APTR) &slideknob,
+ NULL,
+ NULL,
+ NULL,
+ (APTR) &slideprop,
+ FN_SLIDE,
+ NULL
+ };
+
+/*====================*/
+/*== UP, GADGET ======*/
+/*====================*/
+extern SHORT up0[];
+
+local struct Image uparrow = {
+ 0,0,
+ 16,
+ 16,1,
+ (USHORT *)&up0,
+ 0x01,
+ 0x00,
+ NULL};
+
+local struct Gadget upgadget = {
+ &slidegadget,
+ -17,12,
+ 16,16,
+ GADGHCOMP | GRELRIGHT | GADGIMAGE,
+ RELVERIFY | GADGIMMEDIATE,
+ REQGADGET | BOOLGADGET,
+ (APTR)&uparrow,
+ NULL,
+ NULL,
+ 0,
+ NULL,
+ FN_UP,
+ NULL };
+
+/*======================*/
+/*== DOWN, GADGET ======*/
+/*======================*/
+extern SHORT down0[];
+
+local struct Image downarrow = {
+ 0,0,
+ 16,
+ 16,1,
+ (USHORT *)&down0,
+ 0x01,
+ 0x00,
+ NULL};
+
+local struct Gadget downgadget = {
+ &upgadget,
+ -17,78,
+ 16,16,
+ GADGHCOMP | GRELRIGHT | GADGIMAGE,
+ RELVERIFY | GADGIMMEDIATE,
+ REQGADGET | BOOLGADGET,
+ (APTR)&downarrow,
+ NULL,
+ NULL,
+ 0,
+ NULL,
+ FN_DOWN,
+ NULL };
+
+
+/*========================*/
+/*== NAMES, GADGETS ======*/
+/*========================*/
+
+SHORT NFNames = 0; /* The number of file names in currren dir */
+UBYTE *names[MAXFNAMES] = {NULL};
+UBYTE namedir[MAXFNAMES];
+
+local struct IntuiText nametext[MAXSHOW];
+
+#define MAXCHARS 30
+typedef UBYTE NameStr[MAXCHARS];
+NameStr *showNames;
+
+local struct Gadget namegadget[MAXSHOW] = {0};
+
+AllocShowNames() {
+ showNames = (NameStr *)DAlloc(MAXSHOW*sizeof(NameStr), MEMF_PUBLIC);
+ }
+
+FreeShowNames() { DFree(showNames); }
+
+FN_InitReq()
+ {
+ LONG n;
+ InitRequester(&fn_req);
+ fn_req.LeftEdge = reqX;
+ fn_req.TopEdge = reqY;
+ fn_req.Width = reqWidth;
+ fn_req.Height = REQH;
+ fn_req.ReqGadget = &namegadget[MAXSHOW-1];
+ fn_req.ReqBorder = &reqborder;
+ fn_req.ReqText = &fn_text[2];
+ fn_req.BackFill = 1;
+
+ fn_text[0].FrontPen = 3;
+ fn_text[0].BackPen = 1;
+ fn_text[0].DrawMode = JAM2;
+ fn_text[0].ITextFont = &reqfont;
+ fn_text[0].NextText = NULL;
+ fn_text[0].IText = NULL;
+ fn_text[0].LeftEdge = 0;
+ fn_text[0].TopEdge = 3;
+
+ fn_text[1].FrontPen = 0;
+ fn_text[1].BackPen = 1;
+ fn_text[1].DrawMode = JAM2;
+ fn_text[1].ITextFont = &reqfont;
+ fn_text[1].NextText = &fn_text[0];
+ fn_text[1].LeftEdge = 5;
+ fn_text[1].TopEdge = REQH-49;
+ fn_text[1].IText = (UBYTE *)"Drawer:";
+
+ fn_text[2].FrontPen = 0;
+ fn_text[2].BackPen = 1;
+ fn_text[2].DrawMode = JAM2;
+ fn_text[2].ITextFont = &reqfont;
+ fn_text[2].NextText = &fn_text[1];
+ fn_text[2].LeftEdge = 21;
+ fn_text[2].TopEdge = REQH-34;
+ fn_text[2].IText = (UBYTE *)"File:";
+
+ for(n=0;n<MAXSHOW;n++) {
+ nametext[n].FrontPen = 0;
+ nametext[n].BackPen = 1;
+ nametext[n].DrawMode = JAM2;
+ nametext[n].ITextFont = &reqfont;
+ nametext[n].NextText = NULL;
+ nametext[n].LeftEdge = 2;
+ nametext[n].TopEdge = 1;
+ }
+ reqpts[4] = reqpts[6] = reqpts[12] = reqpts[14] = reqWidth-3;
+ }
+
+/*****************************************************************************/
+/* FN_FixBox */
+/* */
+/* Adjust a box's corners to a specified width and height */
+/* */
+/*****************************************************************************/
+
+VOID FN_FixBox(box1,box2,width,height)
+UWORD box1[],box2[];
+UWORD width,height;
+ {
+ box1[2] = width-1;
+ box1[4] = width-1;
+ box1[5] = height-1;
+ box1[7] = height-1;
+ box2[2] = width-2;
+ box2[4] = width-2;
+ box2[5] = height-3;
+ box2[7] = height-3;
+ }
+
+/*****************************************************************************/
+/* FN_InitText */
+/* */
+/* Initialize text used in this requester */
+/* */
+/*****************************************************************************/
+VOID FN_InitText()
+ {
+ SHORT n;
+ for(n=0; n<2; n++)
+ {
+ gadg_text[n].FrontPen = 0;
+ gadg_text[n].BackPen = 1;
+ gadg_text[n].DrawMode = JAM2;
+ gadg_text[n].ITextFont = &reqfont;
+ gadg_text[n].NextText = NULL;
+ gadg_text[n].LeftEdge = 4;
+ gadg_text[n].TopEdge = 4;
+ }
+ gadg_text[0].IText = NULL;
+ gadg_text[1].IText = NULL;
+
+ for(n=0;n<MAXSHOW;n++)
+ {
+ if (n==0) namegadget[n].NextGadget = &downgadget;
+ else namegadget[n].NextGadget = &namegadget[n-1];
+ namegadget[n].LeftEdge = 3;
+ namegadget[n].TopEdge = 13+(n*10);
+ namegadget[n].Width = REQW-22;
+ namegadget[n].Height = 9;
+ namegadget[n].Flags = GADGHCOMP;
+ namegadget[n].Activation = RELVERIFY | GADGIMMEDIATE;
+ namegadget[n].GadgetType = REQGADGET | BOOLGADGET;
+ namegadget[n].GadgetID = FN_SLIDE + 1 + n;
+ namegadget[n].GadgetText = &nametext[n];
+ }
+ }
+
+UBYTE emptyName[] = "";
+int nrange = 0;
+#define MAXCHWIDE 20
+StuffReqNames() {
+ int i,n,j;
+ int newpot,newbody;
+ if (firstname<0) firstname = 0;
+ if (NFNames<=MAXSHOW) firstname = 0;
+ else if (firstname > (NFNames-MAXSHOW)) firstname = NFNames-MAXSHOW;
+ n = firstname;
+ for (i=0; i<MAXSHOW; i++) {
+ if (n<NFNames) strncpy(showNames[i],names[n],MAXCHARS);
+ else showNames[i][0] = 0;
+ nametext[i].IText = showNames[i];
+ for (j = strlen(showNames[i]); j<MAXCHARS-1; j++)
+ showNames[i][j] = ' ';
+ showNames[i][MAXCHARS-1] = 0;
+ n++;
+ }
+ nrange = NFNames - MAXSHOW + 1;
+ if (nrange<=0) { newpot = 0x0; newbody = 0xffff; }
+ else {
+ newpot = (firstname<<16)/nrange;
+ newbody = (MAXSHOW<<16)/NFNames;
+ }
+#ifdef foob
+ printf("newpot, newbody = %4lx %4lx\n",newpot,newbody);
+ printf("NFNames = %ld\n",NFNames);
+ printf("firstname = %ld\n",firstname);
+#endif
+ slideprop.VertBody = newbody;
+ slideprop.VertPot = newpot;
+ }
+
+
+FreeFileNames() {
+ int n;
+ for(n=0; n<MAXFNAMES; n++) {
+ if (names[n] != NULL) DFree(names[n]);
+ names[n] = NULL;
+ namedir[n] = FALSE;
+ }
+ }
+
+local BOOL okDrawer;
+
+strToLower(d,s) char *d,*s; {
+ char c;
+ do { c = *s++; *d++ = tolower(c); } while(c!=0);
+ }
+
+CmpStr(s,t) char *s,*t; {
+ char a[40],b[40];
+ strToLower(a,s);
+ strToLower(b,t);
+ return(stscmp(a,b));
+ }
+
+local UBYTE dotinfo[] = ".info";
+
+DotInfo(nm) char *nm; {
+ int l = strlen(nm);
+ if (l<5) return(NO);
+ return( strcmp(dotinfo,nm+l-5) == 0);
+ }
+/*----------------------------------------------------------------------*/
+/* GetFileNames */
+/* Read in all the file names, allocating space for them */
+/*----------------------------------------------------------------------*/
+VOID GetFileNames(drawername) UBYTE drawername[]; {
+ BOOL success;
+ LONG lock;
+ LONG n, ln, t, bound;
+ UBYTE *tmp, tmpb;
+ struct FileInfoBlock *fib;
+
+ ZZZCursor();
+ FreeFileNames();
+ okDrawer = NO;
+ NFNames = 0;
+ lock = Lock(drawername,SHARED_LOCK);
+ success = (lock!=0);
+ if (success) {
+ fib = (struct FileInfoBlock *)DAlloc(sizeof(struct FileInfoBlock),MEMF_PUBLIC);
+ success = Examine(lock,fib);
+ if (success) {
+ okDrawer = YES;
+ n = 0;
+ while (success) {
+ success = ExNext(lock,fib);
+ if (success&&(n<MAXFNAMES)) {
+ ln = strlen(fib->fib_FileName);
+ if (fib->fib_DirEntryType>0) {
+ namedir[n] = TRUE;
+ ln += 6;
+ }
+ else {
+ if (DotInfo(fib->fib_FileName)) continue;
+ namedir[n] = FALSE;
+ }
+ names[n] = (UBYTE *)DAlloc(ln+1,MEMF_PUBLIC);
+ strcpy(names[n],fib->fib_FileName);
+ if (namedir[n]) strcat(names[n]," (Dir)");
+ n++;
+ }
+ } /* end while */
+ NFNames = n;
+ }
+ DFree(fib);
+ UnLock(lock);
+ }
+ /** bubble sort file names **/
+ t = NFNames-1;
+ while (t>0) {
+ bound = t;
+ t = 0;
+ for (n=0; n<bound; n++) {
+ if (CmpStr(names[n],names[n+1])>0) {
+ tmp = names[n]; names[n] = names[n+1]; names[n+1] = tmp;
+ tmpb = namedir[n]; namedir[n] = namedir[n+1];
+ namedir[n+1] = tmpb;
+ t = n;
+ }
+ }
+ }
+ UnZZZCursor();
+ } /* end GetFileNames() */
+
+local BOOL doAction;
+
+/*****************************************************************************/
+/* FN_GadgUp */
+/* */
+/* Handle gadget up events */
+/* */
+/*****************************************************************************/
+
+RedoNames() {
+ StuffReqNames();
+ RefreshGadgets(&namegadget[MAXSHOW-1],reqwindow,&fn_req);
+ }
+
+VOID FN_GadgUp(gid,x,y) UWORD gid; int x,y; {
+ LONG n;
+ UBYTE tmp[31];
+ /* ---- names in the directory display */
+ if ((gid >= (FN_SLIDE+1)) && (gid <= (FN_SLIDE+MAXSHOW))) {
+ n = gid - FN_SLIDE - 1 + firstname;
+ if (namedir[n]) {
+ strncpy(tmp,names[n],strlen(names[n])-6);
+ ConcatPath(drawerstr.Buffer,tmp);
+ GetFileNames(drawerstr.Buffer);
+ drawerstr.BufferPos = 0; /*strlen(drawerstr.Buffer);*/
+ filestr.DispPos = 0;
+ firstname = 0;
+ StuffReqNames();
+ }
+ else {
+ strcpy(filestr.Buffer,names[n]);
+ filestr.BufferPos = 0; /*strlen(filestr.Buffer);*/
+ filestr.DispPos = 0;
+ }
+ /*RefreshGadgets(&namegadget[MAXSHOW-1],reqwindow,&fn_req); */
+ /* try to keep it from redrawing whole thing-- didnt work */
+ RefreshGadgets(&filegadget,reqwindow,&fn_req);
+ }
+ if (gid==FN_SLIDE) {
+ firstname = ((slideprop.VertPot*nrange)>>16);
+ RedoNames();
+ }
+ if (gid==FN_DRAWER) {
+ GetFileNames(drawerstr.Buffer);
+ firstname = 0;
+ RedoNames();
+ }
+ if ((gid==FN_UP)||(gid==FN_DOWN) ) {
+ if (gid==FN_UP) firstname--; else firstname++;
+ RedoNames();
+ }
+ }
+
+/*****************************************************************************/
+/* Handle events for the File Name requester */
+/*****************************************************************************/
+local BOOL FN_HandleEvent(event) struct IntuiMessage *event; {
+ WORD gadgetid;
+ BOOL keepGoing = YES;
+ switch(event->Class)
+ {
+ case GADGETUP:
+ gadgetid = ((struct Gadget *)event->IAddress)->GadgetID;
+ if (gadgetid == FN_CANCEL) keepGoing = NO;
+ else if (gadgetid==FN_GOTNAME) { doAction = TRUE;
+ keepGoing = NO;
+ }
+ else if ((gadgetid>=FN_GADGMIN) && (gadgetid<=FN_GADGMAX))
+ FN_GadgUp(gadgetid);
+ break;
+ }
+ return(keepGoing);
+ }
+
+
+/*****************************************************************************/
+/* FN_Request */
+/* */
+/* Initialize and display the requester */
+/* Returns TRUE if do, FALSE if cancel */
+/*****************************************************************************/
+BOOL FN_Request(w,x,y,drawername,filename,extension,title,cancelverb,doverb)
+struct Window *w; SHORT x,y;
+ UBYTE drawername[]; UBYTE filename[]; UBYTE extension[]; UBYTE title[];
+ UBYTE doverb[]; UBYTE cancelverb[];
+ {
+ UWORD width0,width1,width,height;
+ ULONG saveIDCMP;
+
+
+ FixMenCols();
+ AllocShowNames();
+ reqX = x;
+ reqY = y;
+ reqwindow = w;
+ saveIDCMP = w->IDCMPFlags;
+
+ reqWidth = ( (w->WScreen->ViewPort.Modes & (HIRES|LACE)) ==
+ (HIRES|LACE)) ? HIWIDTH: LOWIDTH;
+
+ /* --- What class of events do we want to know about? --- */
+
+ ModifyIDCMP( reqwindow, RAWKEY | MOUSEBUTTONS | GADGETUP | GADGETDOWN);
+
+ if (!dosready) {
+ /* Initialize stuff the first time through */
+ GetPrefs(&reqfont.ta_YSize,2);
+ FN_InitReq();
+ FN_InitText();
+ dosready = TRUE;
+ }
+ drawerstr.Buffer = drawername;
+ filestr.Buffer = filename;
+
+ if (title==NULL) fn_text[0].IText = deftitle;
+ else fn_text[0].IText = title;
+ fn_text[0].LeftEdge = (reqWidth-10*strlen(fn_text[0].IText))/2;
+
+ if (cancelverb==NULL) gadg_text[0].IText = defcancel;
+ else gadg_text[0].IText = cancelverb;
+
+ if (doverb==NULL) gadg_text[1].IText = defdoverb;
+ else gadg_text[1].IText = doverb;
+
+ width0 = strlen(gadg_text[0].IText)*10+10;
+ width1 = strlen(gadg_text[1].IText)*10+10;
+ width = MAX(width0,width1);
+ height = 17;
+
+ cancelgadget.LeftEdge = -10-width;
+ cancelgadget.Width = width;
+ cancelgadget.Height = height;
+ FN_FixBox(&dt0box1,&dt0box2,width,height);
+
+ gotnamegadget.Width = width;
+ gotnamegadget.Height = height;
+ FN_FixBox(&dt1box1,&dt1box2,width,height);
+
+ GetFileNames(drawerstr.Buffer);
+
+ StuffReqNames();
+
+ ZZZCursor();
+
+ Request(&fn_req,w);
+
+ UnZZZCursor();
+
+ doAction = FALSE;
+
+ ReqListen(w->UserPort,&FN_HandleEvent);
+
+ FreeFileNames();
+
+ /* restore the IDCMP to its original state */
+ ModifyIDCMP(reqwindow, saveIDCMP);
+
+ FreeShowNames();
+ UnFixMenCols();
+ return( (BOOL)
+ (doAction? ( okDrawer? FN_OK: FN_NoSuchDrawer): FN_Cancel ));
+ }
+
diff --git a/FNREQ.H b/FNREQ.H
new file mode 100644
index 0000000..02f468f
--- /dev/null
+++ b/FNREQ.H
@@ -0,0 +1,11 @@
+/** fnreq.h ******************************************************************/
+/* */
+/* A module that opens and handles a file name requester. */
+/* */
+/* */
+/*****************************************************************************/
+
+/* Error values returned :*/
+#define FN_OK 0
+#define FN_Cancel 1
+#define FN_NoSuchDrawer 2
diff --git a/FONTINIT.C b/FONTINIT.C
new file mode 100644
index 0000000..63b94e8
--- /dev/null
+++ b/FONTINIT.C
@@ -0,0 +1,177 @@
+/*----------------------------------------------------------------------*/
+/* */
+/* fontinit.c */
+/* */
+/*----------------------------------------------------------------------*/
+
+#include <system.h>
+#include <librarie\dosexten.h>
+#include <prism.h>
+#include <librarie\diskfont.h>
+
+#define local static
+extern LONG DiskfontBase;
+extern struct TmpRas tmpRas;
+extern struct AvailFonts *fontDir;
+extern SHORT nFonts;
+extern SHORT curFontNum;
+extern struct TextFont *font;
+extern struct Menu *FontMenu;
+extern struct Window *mainW;
+extern struct Menu *MainMenu;
+
+#ifdef junkjunkjunkjunk
+
+------- STUFF from <librarie\diskfont.h> for reference :
+
+#define AFB_MEMORY 0
+#define AFF_MEMORY 1
+#define AFB_DISK 1
+#define AFF_DISK 2
+/****** TextAttr node, matches text attributes in RastPort **********/
+struct TextAttr {
+ STRPTR ta_Name; /* name of the font */
+ UWORD ta_YSize; /* height of the font */
+ UBYTE ta_Style; /* intrinsic font style */
+ UBYTE ta_Flags; /* font preferences and flags */
+};
+
+struct AvailFonts {
+ UWORD af_Type; /* MEMORY or DISK */
+ struct TextAttr af_Attr; /* text attributes for font */
+ };
+
+struct AvailFontsHeader {
+ UWORD afh_NumEntries; /* number of AvailFonts elements */
+ /* struct AvailFonts afh_AF[]; */
+ };
+#endif
+/*----------------------------------------------------------------------*/
+
+#define BUFSIZE 800
+
+
+local CopyPrefix(to,from) UBYTE *to,*from; {
+ UBYTE c;
+ while ( (c = *from++) != '.') *to++ = c;
+ *to++ = '-';
+ *to = '\0';
+ }
+
+/* -----------initialize font directory */
+local void InitFonts() {
+ int i,err,fontType;
+ UBYTE *str, name[20], sHigh[5],*buffer;
+ struct AvailFonts *avFonts;
+ struct AvailFontsHeader *avh = (struct AvailFontsHeader *)tmpRas.RasPtr;
+ buffer = (UBYTE *)tmpRas.RasPtr;
+
+ fontType = AFF_MEMORY;
+ DiskfontBase = OpenLibrary("diskfont.library",0);
+ if (DiskfontBase== NULL){
+ InfoMessage("Couldn't open","diskfont.library" );
+ return;
+ }
+ else fontType |= AFF_DISK;
+
+ ZZZCursor();
+ err = AvailFonts(avh, tmpRas.Size, fontType);
+ nFonts = avh->afh_NumEntries;
+
+#if 0
+ printf("err = %ld, #found = %ld\n", err, nFonts);
+#endif
+
+ avFonts = (struct AvailFonts *)&(buffer[2]);
+ fontDir = (struct AvailFonts *)DAlloc(nFonts*sizeof(struct AvailFonts), MEMF_PUBLIC);
+
+ movmem(avFonts,fontDir,nFonts*sizeof(struct AvailFonts));
+
+ /* copy the font names into strings allocated with AllocMem,
+ adding the size to the name */
+ for (i=0; i<nFonts; i++) {
+
+#if 0
+ printf("Font '%s', type = %lx\n",avFonts[i].af_Attr.ta_Name,
+ avFonts[i].af_Type);
+#endif
+
+#define SAVINGSPACE
+
+#ifdef SAVINGSPACE
+ CopyPrefix(name, avFonts[i].af_Attr.ta_Name);
+ stcu_d(sHigh,avFonts[i].af_Attr.ta_YSize,3);
+ strcat(name,sHigh);
+ str =(UBYTE *)AllocMem(strlen(name)+1,MEMF_PUBLIC);
+ strcpy(str,name);
+#else
+ str =(UBYTE *)AllocMem(strlen(avFonts[i].af_Attr.ta_Name)+1,MEMF_PUBLIC);
+ strcpy(str,avFonts[i].af_Attr.ta_Name);
+#endif
+ fontDir[i].af_Attr.ta_Name = str;
+ }
+ InitFontMenu();
+ UnZZZCursor();
+ }
+
+static struct IntuiText itInit = {0,1,JAM1,0,1,NULL,NULL,NULL};
+
+#define AllocStruct(astr) (struct astr *)AllocMem( sizeof(struct astr), MEMF_PUBLIC);
+
+
+/* Build a font menu, allocating a MenuItem and IntuiText (which points
+at the same name as the font Directory) */
+local InitFontMenu() {
+ int i;
+ struct MenuItem *mi, *nextMI;
+ struct IntuiText *it;
+ LONG mutExSet = (1 << nFonts) -1;
+ nextMI = NULL;
+ for (i = nFonts-1; i>=0; i--) {
+ mi = (struct MenuItem *)AllocStruct(MenuItem);
+ it = (struct IntuiText *)AllocStruct(IntuiText);
+ movmem(&itInit,it,sizeof(struct IntuiText));
+ it->IText = fontDir[i].af_Attr.ta_Name,
+ mi->TopEdge = 0;
+ mi->SelectFill = (APTR)NULL;
+ mi->ItemFill = (APTR)it;
+ mi->Flags = (CHECKIT | ITEMTEXT | ITEMENABLED | HIGHCOMP);
+ mi->MutualExclude = mutExSet & ( ~(1<<i) );
+ mi->NextItem = nextMI;
+ mi->SubItem = NULL;
+ nextMI = mi;
+ }
+ FontMenu->FirstItem = nextMI;
+ FontMenu->FirstItem->NextItem->Flags |= CHECKED;
+ }
+
+#define FreeString(s) FreeMem((s),strlen(s)+1)
+
+void FreeFonts() {
+ int i;
+ struct MenuItem *mi, *nextMI=NULL;
+ MyCloseFont(font);
+ if (fontDir == NULL) return;
+ /* free the font MenuItems and IntuiText's */
+ for (mi = FontMenu->FirstItem; mi != NULL; mi = nextMI) {
+ nextMI = mi->NextItem;
+ FreeMem( mi->ItemFill, sizeof(struct IntuiText));
+ FreeMem( mi, sizeof(struct MenuItem));
+ }
+ FontMenu->FirstItem = NULL;
+ for (i=0; i<nFonts; i++) FreeString(fontDir[i].af_Attr.ta_Name);
+ DFree(fontDir);
+ CloseLibrary(DiskfontBase);
+ }
+
+void LoadFontDir() {
+ UndoSave();
+ InitFonts();
+ ClearMenuStrip(mainW);
+ InitMenu();
+ SetMenuStrip(mainW, MainMenu);
+ PaneRefrAll(); /* in case it put up requestor to switch disks*/
+ /* may have made storage tight by loading the font directory:
+ if so deallocate the brush */
+ if (AvailMem(MEMF_PUBLIC|MEMF_CHIP) < 17000) GunTheBrush();
+ }
diff --git a/GEOM.C b/GEOM.C
new file mode 100644
index 0000000..fb68044
--- /dev/null
+++ b/GEOM.C
@@ -0,0 +1,119 @@
+/*--------------------------------------------------------------*/
+/* geom.c -- geometric primitives */
+/* lines, circles, filled circles */
+/* Coordinates are in Virtual Device Coords (640x400) */
+/*--------------------------------------------------------------*/
+
+#include <system.h>
+#include <prism.h>
+
+extern SHORT xShft,yShft;
+extern void (*CurPWritePix)();
+#define local
+
+extern struct RastPort *curRP;
+
+
+/*-----------Line drawing functions------------------*/
+/* note: fun must take Physical Device coords */
+
+void PLineWith(x1,y1,x2,y2,fun) SHORT (*fun)(), x1,y1,x2,y2; {
+ SHORT i,dx,dy,incr1,incr2,del,xinc,yinc,linex,liney;
+ dx = x2-x1;
+ dy = y2-y1;
+ if (dx<0) {xinc = -1; dx = -dx;} else xinc = 1;
+ if (dy<0) {yinc = -1; dy = -dy;} else yinc = 1;
+ linex=x1; liney=y1;
+ (*fun)(linex,liney);
+ if (dx>dy) {
+ incr1 = dy+dy; del = incr1-dx; incr2= del-dx;
+ for (i=0; i<dx; i++) {
+ linex += xinc;
+ if (del<0) del += incr1; else { liney += yinc; del += incr2; }
+ (*fun)(linex,liney);
+ if (CheckAbort()) return;
+ }
+ }
+ else {
+ incr1 = dx+dx; del = incr1-dy; incr2= del-dy;
+ for (i=0; i<dy; i++) {
+ liney += yinc;
+ if (del<0) del += incr1; else { linex += xinc; del += incr2; }
+ (*fun)(linex,liney);
+ if (CheckAbort()) return;
+ }
+ }
+ }
+
+/* some cheapo clipping */
+extern SHORT clipMaxX;
+void PLine(x1,y1,x2,y2) SHORT x1,y1,x2,y2; {
+ if (x2>clipMaxX) {
+ if (x1>clipMaxX) return;
+ y2 = y1 +(clipMaxX-x1)*(y2-y1)/(x2-x1);
+ x2 = clipMaxX;
+ }
+ else if (x1>clipMaxX) {
+ y1 = y2 + (clipMaxX-x2)*(y1-y2)/(x1-x2);
+ x1 = clipMaxX;
+ }
+ Move(curRP,x1,y1); Draw(curRP,x2,y2);
+ }
+
+/* ---------------- Circle Drawing -----------------------*/
+SHORT xcen,ycen;
+SHORT (*curfunc)();
+
+void quadpts(x,y) SHORT x,y; {
+ (*curfunc)(xcen+x,ycen+y);
+ if (y) (*curfunc)(xcen+x,ycen-y);
+ if (x) {
+ (*curfunc)(xcen-x,ycen+y);
+ if (y) (*curfunc)(xcen-x,ycen-y);
+ }
+ }
+
+local octpts(x,y) SHORT x,y; { quadpts(x,y); if (x!=y) quadpts(y,x); }
+
+local octfillfunc(x,y) SHORT x,y; {
+ SHORT w = 2*x+1; SHORT h = 2*y+1;
+ PatHLine(xcen-x,ycen+y,w);
+ PatHLine(xcen-x,ycen-y,w);
+ PatHLine(xcen-y,ycen+x,h);
+ PatHLine(xcen-y,ycen-x,h);
+ }
+
+/* generates 1/8 of a circle and calls func at each point */
+/* this should ONLY be called if xShft == yShft */
+/* ie square pixels */
+
+void PCircOct(xc,yc,rad,func) SHORT xc,yc,rad,(*func)(); {
+ SHORT d,x,y;
+ y = rad; x=0;
+ xcen=xc; ycen = yc;
+ for (d = 3 - (rad<<1); x<y; x++) {
+ (*func)(x,y);
+ if (d<0) d += (x<<2) + 5;
+ else { d += ((x-y)<<2) + 10; y--; }
+ if (CheckAbort()) return;
+ }
+ if (x == y) (*func)(x,y);
+ }
+
+PCircWith(xc,yc,rad,func) SHORT xc,yc,rad,(*func)(); {
+ if (xShft==yShft) { curfunc = func; PCircOct(xc,yc,rad,octpts);}
+ else PEllpsWith(xc,yc,rad,PMapY(VMapX(rad)),func);
+ }
+
+PFillCirc(xc,yc,rad) SHORT xc,yc,rad; {
+ if (xShft==yShft) PCircOct(xc,yc,rad,octfillfunc);
+ else PFillEllps(xc,yc,rad,PMapY(VMapX(rad)));
+ }
+
+PCircle(xc,yc,rad) SHORT xc,yc,rad; {
+ if (xShft==yShft) PCircWith(xc,yc,rad,CurPWritePix);
+ else PEllpse(xc,yc,rad,PMapY(VMapX(rad)));
+ }
+
+
+ \ No newline at end of file
diff --git a/GRDEFS.H b/GRDEFS.H
new file mode 100644
index 0000000..2feea40
--- /dev/null
+++ b/GRDEFS.H
@@ -0,0 +1,330 @@
+/*----------------------------------------------------------------------*/
+/* */
+/* grdefs.h -- Graphics Definitions */
+/* */
+/*----------------------------------------------------------------------*/
+
+#define BIGNUM 32767
+#define ALLONES 0xffff
+#define NIL 0
+#define MXLWRD 160 /* number of words in line buffers */
+
+typedef char Boolean;
+#define TRUE 0xff
+#define FALSE 0
+#define YES 0xff
+#define NO 0
+#define local static
+#define FAIL -1
+#define SUCCESS 0
+
+typedef char Byte;
+typedef unsigned int Word;
+typedef char *String;
+typedef long longFrac;
+
+/* Utility functions */
+#define BitNot(v) (v^0xffff)
+#define swap(a,b) a ^= b; b ^= a; a ^= b;
+#define order(a,b) if ((a)>(b)) {swap(a,b); }
+#define max(a,b) ((a)>(b)?(a):(b))
+#define min(a,b) ((a)<(b)?(a):(b))
+#define abs(a) ((a)>0?(a):-(a))
+#define signum(a) ((a)>0)
+
+/* ----------------Rasterop Modes ---------- */
+#define REPMODE 0 /* REPLACE pixels with new values */
+#define XORMODE 1 /* XOR source into dest */
+#define ORMODE 2 /* OR source into dest */
+#define XPMODE 3 /* current transparent color doesnt paint,
+ other colors write */
+#define ANDMODE 4 /* AND source into dest */
+#define ERSMODE 5 /* ERASE: and complement of source into dest */
+#define COLMODE 6 /* use source as mask through which current
+ color is painted into dest */
+
+
+#define BLACK 0
+#define WHITE 0xffff
+#define BLUE 0x5555
+#define MAGENTA 0xaaaa
+#define BGROUND 0xc3c3
+
+/* ------ offset in bytes of word containing pixel #x */
+
+#define xword(x) (((x)>>LGPPB)&0xfffe)
+
+/* ------ offset in bytes of byte containing pixel #x */
+
+#define xbyte(x) (x>>LGPPB)
+
+/* ------ words required for w pixels */
+
+#define wrdsrqd(w) ((w+PPWM1)>>LGPPW)
+
+/* ------ set up current color word for scan line y */
+
+#define colForY(y) colw = curpat[y&3]
+
+
+
+/*--------------------------------------------------------------*/
+/* */
+/* Graphics Data Structures */
+/* */
+/*--------------------------------------------------------------*/
+
+typedef union {
+ struct { char lo,hi; } b;
+ int w;
+ } Wrdovl;
+
+typedef struct{ int x,y; } Point;
+
+typedef struct{ int w,h; } Dims;
+
+typedef struct{ int x,y,w,h; } Box;
+
+typedef struct{
+ Word segment; /* segment addr of bitmap */
+ Word *base; /* addr of start of data */
+ Word width; /* width in words */
+ Box box; /* image bounds */
+ Word *ytab; /* pointer to table of y offsets */
+ Byte xpcolor; /* transparent color */
+ Byte mode; /* paint mode */
+ } Bitmap;
+
+#define INITBM {NIL,NIL,0,{0,0,0,0},NIL,0,XPMODE}
+
+/* General Displayable Object DOB */
+
+typedef struct {
+ int (*display)(); /* pointer to display proc */
+ int x,y; /* present coords of upper left */
+ int xoffs,yoffs; /* offset of grab point */
+ Boolean showing; /* is it displayed? */
+ Bitmap svbm; /* save bitmap */
+ } DOB;
+
+/* Bitmap Object: if mbm is defined (segment != NIL) */
+typedef struct {
+ DOB hdr; /* header inherited from DOB */
+ Bitmap sbm; /* source bitmap */
+ Bitmap mbm; /* mask bitmap(optional) */
+ } BMObj;
+
+#define INITDOB {NIL,0,0,0,0,FALSE,INITBM}
+#define INITPSB {INITBM,INITBM,INITBM,INITBM}
+#define INITBMOB {INITDOB,INITBM,INITBM}
+
+typedef struct{
+ int curcol;
+ int curxpc;
+ Box box;
+ int curmode;
+ Bitmap *curbm;
+ } GrState;
+
+/* window: definitions */
+typedef struct {
+ unsigned border : 1; /* draw border */
+ unsigned always : 1; /* call even if mouse didnt move */
+ unsigned hangOn : 1; /* keep control while button down */
+ } WFlags;
+
+struct Winrec{
+ Word client; /* client context */
+ Box box; /* rectangle on screen */
+ WFlags flags; /* booleans */
+ Boolean border; /* does it have a border */
+ int (*charProc)(); /* called with all typing */
+ int (*mouseProc)(); /* called on all mouse actions */
+ int (*paintProc)(); /* called to repaint window */
+ struct Winrec *next;
+ };
+
+typedef struct Winrec Window;
+
+typedef Byte MouseEvent;
+
+/* mouse events: you can choose to be called when the program loops
+ even though the mouse didnt move */
+
+#define NONE 0 /* nothing happened (i dont call you) */
+#define LOOPED 1 /* you wanted me to call you every time*/
+#define MOVED 2 /* the mouse moved while in this window */
+#define BDOWN 3 /* button went down */
+#define BUP 4 /* button went up */
+#define ENTER 5 /* entered window */
+#define LEAVE 6 /* left window */
+
+/* Magnified Bitmap window (subclassed off of Window) */
+
+struct MagWinGr {
+ Bitmap *bbm;
+ struct MagWinRec *first;
+ };
+
+struct MagWinRec{
+ Window win;
+ Point wb; /* coords of window rel to bitmap */
+ int mag; /* magnification */
+ struct MagWinGr *group; /* pointer to group sharing backing bitmap */
+ struct MagWinRec *sib; /* sister in group */
+ };
+
+typedef struct MagWinGr MWGroup;
+typedef struct MagWinRec MagWindow;
+
+typedef struct {
+ Bitmap *bm;
+ Box box;
+ int xorg,yorg;
+ } GrCntxt;
+
+/* ----- Activities -------*/
+#define nullAct 0
+#define shadeAct 1
+#define drawAct 2
+#define vectAct 3
+#define curvAct 4
+#define rectAct 5
+#define frectAct 6
+#define circAct 7
+#define fcircAct 8
+#define ovalAct 9
+#define fovalAct 10
+#define selbAct 11
+#define magAct 12
+#define fillAct 13
+#define textAct 14
+#define gridAct 15
+#define symAct 16
+#define ioAct 17
+#define clearAct 18
+
+#define NPENS 9
+#define USERPEN -1
+
+
+/*--------------------------------------------------------------*/
+/* */
+/* Menu Box */
+/* */
+/*--------------------------------------------------------------*/
+
+struct MenuRec {
+ Box box; /*window - relative */
+ int type; /* what kind of item */
+ struct MenuRec *next;
+ };
+
+typedef struct MenuRec MenuItem, *MIPtr;
+
+typedef struct {
+ Window win;
+ Boolean showing; /* is it on the screen? */
+ Boolean isTemp;
+ MenuItem *curmi;
+ MenuItem *items;
+ int effNWIDE; /* set to 320 initially */
+ } MBox;
+
+/*------ Passive Types----- */
+
+#define LablTyp 0
+typedef struct {
+ MenuItem hdr;
+ char *name;
+ } Labl;
+
+#define ColBoxTyp 1
+typedef struct {
+ MenuItem hdr;
+ Word fillPat;
+ } ColBx;
+
+/* ------- Active Types----- */
+
+#define ButnTyp 2
+typedef struct {
+ MenuItem hdr;
+ char *name;
+ Boolean islit;
+ int (*proc)();
+ } Butn;
+
+#define TBoxTyp 3
+typedef struct {
+ MenuItem hdr;
+ char *string;
+ int nmax;
+ int (*proc)();
+ } TBox;
+
+#define MarTyp 4
+typedef struct {
+ MenuItem hdr;
+ char **names;
+ Boolean dolines;
+ Boolean vertical;
+ int spacing; /* used only by horizontal */
+ int (*proc)();
+ int curitem,lit,nitems; /* used by menu processr */
+ } Mar;
+
+#define ScBarTyp 5
+typedef struct {
+ MenuItem hdr;
+ int (*proc)();
+ } ScBar;
+
+#define NBoxTyp 6
+typedef struct {
+ MenuItem hdr;
+ int pval; /* value to be displayed*/
+ int nmax; /* max num of chars */
+ int (*proc)();
+ } NBox;
+
+#define MAXCHRS 9
+#define NEWITEM 10
+#define NullItem -1
+
+
+#define USERBRUSH 255
+
+/* configuration */
+#define NCONFIG 6
+
+#define MED2 0
+#define ART4 1
+#define LOW4 2
+#define HRBW 3
+#define TEC1 4 /* 320x200x4 */
+#define TEC2 5 /* 640x200x4 */
+
+typedef int CursID;
+#define Arrow 0
+#define FillCan 1
+#define Pencil 2
+
+/* input device types */
+#define NoDev 0
+#define Joystick 1
+#define Koala 2
+#define MMouse 3
+
+/* input device vector*/
+
+extern int (*rdInDev)();
+#define rdmouse(xaddr,yaddr) ((*rdInDev)(xaddr,yaddr))
+
+/* Hardware Type*/
+#define PCSR 0 /* IBM PC */
+#define PCJR 1 /* IBM PC/jr */
+#define PCXT 2 /* IBM PC/XT */
+#define IBMAT 3 /* IBM AT */
+#define TA1000 4 /* Tandy 1000 */
+
diff --git a/HOOK.C b/HOOK.C
new file mode 100644
index 0000000..4da80a6
--- /dev/null
+++ b/HOOK.C
@@ -0,0 +1,38 @@
+/*--------------------------------------------------------------*/
+/* */
+/* hook.c */
+/* */
+/*--------------------------------------------------------------*/
+
+#include <system.h>
+
+typedef struct {
+ struct MsgPort msgport;
+ UWORD *pointer;
+ } Hook;
+
+SetHook(name,ptr) char *name; UWORD *ptr; {
+ Hook *hook = (Hook *)AllocMem(sizeof(Hook),MEMF_CLEAR|MEMF_PUBLIC);
+ struct MsgPort *p = (struct MsgPort *)hook;
+ p->mp_Flags = 0;
+ p->mp_Node.ln_Pri = 0;
+ p->mp_Node.ln_Name = name;
+ p->mp_Node.ln_Type = NT_MSGPORT;
+ AddPort(p);
+ hook->pointer = ptr;
+ }
+
+UWORD *FindHook(name) UBYTE *name; {
+ Hook *hook = (Hook *)FindPort(name);
+ return((hook != NULL)? hook->pointer: NULL);
+ }
+
+RemHook(name) UBYTE *name; {
+ Hook *hook = (Hook *)FindPort(name);
+ if (hook!=NULL) {
+ RemPort(hook);
+ FreeMem(hook,sizeof(Hook));
+ }
+ }
+
+
diff --git a/HSV.C b/HSV.C
new file mode 100644
index 0000000..64e867b
--- /dev/null
+++ b/HSV.C
@@ -0,0 +1,215 @@
+/*--------------------------------------------------------------------*/
+/*
+ RGB - HSV Conversion
+
+ Author: Gordon Knopes.
+
+ Calling Seq.: rgb2hsv (src, dst)
+ Description: Convert RGB color to HSV.
+ Input: src = Pointer to source RGB color structure.
+ dst = Pointer to source HSV color structure.
+ Returns: Nothing.
+
+
+ Calling Seq.: hsv2rgb (src, dst)
+ Description: Convert HSV color to RGB.
+ Input: src = Pointer to source HSV color structure.
+ dst = Pointer to source RGB color structure.
+ Returns: Nothing.
+
+ Creation Date: 8/6/85 */
+/*----------------------------------------------------------------------*/
+
+#include <exec\types.h>
+#define local static
+
+#define SCLEXP 8
+ /* normalize factor = 256 */
+
+#define MAXINT 0xefff
+#define MAXRGB 15
+#define MAXH 255
+ /* normalized max h = 6 << SCLEXP */
+#define MAXSV 255
+#define SCLH ((6 << SCLEXP) / MAXH)
+
+#define LMAXRGB 15L
+#define LMAXSV 255L
+
+#define LROUND 0x80L
+ /* (1 << (SCLEXP - 1))L */
+#define UNDEFINED -1
+#define F1 (1 << SCLEXP)
+#define F2 (2 << SCLEXP)
+#define F4 (4 << SCLEXP)
+
+typedef struct { SHORT r, g, b; } rgb;
+typedef struct { SHORT h, s, v; } hsv;
+
+local long r,g,b;
+local long tmp;
+
+local int mul(a, b) int a, b; {
+ tmp = ((long) a * (long) b) >> SCLEXP;
+ return ((int) tmp);
+ }
+
+local int div(a, b) int a, b; {
+ if (b == 0) tmp = MAXINT;
+ else tmp = ((long) a << SCLEXP) / (long) b;
+ return ((int) tmp);
+ }
+
+/* assign triplet to RGB. */
+local void triplet(x, y, z) int x, y, z; {
+ r = x; g = y; b = z;
+ }
+
+local int normrgb(x) SHORT x; {
+ tmp = ((long) x << SCLEXP) / LMAXRGB;
+ return ((int) tmp);
+ }
+
+local SHORT unnormrgb(x) int x; {
+ tmp = ((long) x * LMAXRGB + LROUND) >> SCLEXP;
+ return ((SHORT) tmp);
+ }
+
+local int normsv(x) SHORT x; {
+ tmp = ((long) x << SCLEXP) / LMAXSV;
+ return ((int) tmp);
+ }
+
+local SHORT unnormsv(x) int x; {
+ tmp = ((long) x * LMAXSV + LROUND) >> SCLEXP;
+ if (tmp > LMAXSV) tmp = LMAXSV;
+ return ((SHORT) tmp);
+ }
+
+local int normh(h) SHORT h; {
+ if (h >= MAXH) h = 0;
+ return ((int) (h * SCLH) ); /* h is now [0, 6] */
+ }
+
+local SHORT unnormh(h) int h; {
+ h /= SCLH; /* convert to degrees */
+ if (h < 0) /* make nonnegative */
+ h +=MAXH;
+ if (h >= MAXH) h = 0;
+ return ((SHORT) h);
+ }
+
+/*----------------------------------------------------------------------*/
+/*
+ RGB_TO_HSV.
+
+ Given: r, g, b, each in [0, 255]
+ Desired: h, s and v in [0, 255], except if s = 0,
+ then h = UNDEFINED which is a definrd constant not in [0, 255].
+ */
+/*----------------------------------------------------------------------*/
+
+rgb2hsv(src, dst) rgb *src; hsv *dst; {
+ int h, s, v, rc, gc, bc, max, min, diff;
+
+ r = normrgb (src->r);
+ g = normrgb (src->g);
+ b = normrgb (src->b);
+ max = (r > g) ? ((r > b) ? r : b) : (g > b) ? g : b;
+ min = (r < g) ? ((r < b) ? r : b) : (g < b) ? g : b;
+ v = max; /* value */
+ diff = div (F1, max-min);
+ if (max != 0)
+ s = div (F1, mul (diff, max)); /* saturation */
+ else s = 0;
+ s = (int) unnormsv(s);
+ if (s == 0)
+ h = (SHORT) UNDEFINED;
+ else
+ { /* saturation not zero, so determine hue */
+ rc = mul (max - r, diff); /* rc measures distance of color from red */
+ gc = mul (max - g, diff);
+ bc = mul (max - b, diff);
+ if (r == max)
+ h = bc - gc; /* color between yellow & magenta */
+ else
+ {
+ if (g == max)
+ h = F2 + rc - bc; /* color between cyan & yellow */
+ else
+ {
+ if (b == max)
+ h = F4 + gc - rc; /* color between magenta & cyan */
+ }
+ }
+ h = unnormh(h);
+ } /* chromatic case */
+ dst->h = h;
+ dst->s = (SHORT) s;
+ dst->v = unnormsv (v);
+
+ if (dst->h < 3) /* Rgb2hsv doesn't return 0. */
+ dst->h = 0;
+ if (dst->s < 3)
+ dst->s = 0;
+ if (dst->s < 3)
+ dst->s = 0;
+ }
+
+/*----------------------------------------------------------------------*/
+/*
+ HSV_TO_RGB.
+
+ Given: h, s and v in [0, 255]
+ Desired: r, g, b, each in [0, 255]. */
+/*----------------------------------------------------------------------*/
+hsv2rgb(src, dst) hsv *src; rgb *dst; {
+ int h, s, v, f, p, q, t;
+ int i;
+
+ if (src->h >= MAXH)
+ src->h = 0;
+ h = (int) src->h;
+ s = normsv (src->s);
+ v = normsv (src->v);
+ if (s == 0)
+ triplet (v, v, v); /* achromatic case */
+/*
+ { * achromatic color: no hue *
+ if (h < 0)
+ triplet (v, v, v); * achromatic case *
+ else
+ {
+ printf ("\n*** error (if s = 0 and h has value) ***\n");
+ exit (0);
+ }
+ }
+*/
+ else
+ { /* chromatic color: hue */
+ h = normh(h);
+ i = (int) (h >> SCLEXP); /* largest integer <= h */
+ f = h - (i << SCLEXP); /* fractional part of h */
+ p = mul (v, F1 - s);
+ q = mul (v, F1 - mul (s, f));
+ t = mul (v, F1 - mul (s, F1 - f));
+ switch (i)
+ { /* triplet assignment */
+ case 0: triplet (v, t, p);
+ break;
+ case 1: triplet (q, v, p);
+ break;
+ case 2: triplet (p, v, t);
+ break;
+ case 3: triplet (p, q, v);
+ break;
+ case 4: triplet (t, p, v);
+ break;
+ case 5: triplet (v, p, q);
+ } /* case */
+ } /* hue */
+ dst->r = unnormrgb (r);
+ dst->g = unnormrgb (g);
+ dst->b = unnormrgb (b);
+
+ }
diff --git a/IFFR.C b/IFFR.C
new file mode 100644
index 0000000..26cb214
--- /dev/null
+++ b/IFFR.C
@@ -0,0 +1,295 @@
+/*----------------------------------------------------------------------*/
+/* IFFR.C Support routines for reading IFF-85 files. 10/10/85 */
+/* (IFF is Interchange Format File.) */
+/* */
+/* By Jerry Morrison and Steve Shaw, Electronic Arts. */
+/* This software is in the public domain. */
+/*----------------------------------------------------------------------*/
+#include "iff\iff.h"
+
+/* ---------- Read -----------------------------------------------------*/
+
+/* ---------- OpenRIFF --------------------------------------------------*/
+IFFP OpenRIFF(file0, new0, clientFrame)
+ BPTR file0; GroupContext *new0; ClientFrame *clientFrame; {
+ register BPTR file = file0;
+ register GroupContext *new = new0;
+ IFFP iffp = IFF_OKAY;
+
+ new->parent = NULL; /* "whole file" has no parent.*/
+ new->clientFrame = clientFrame;
+ new->file = file;
+ new->position = 0;
+ new->ckHdr.ckID = new->subtype = NULL_CHUNK;
+ new->ckHdr.ckSize = new->bytesSoFar = 0;
+
+ /* Set new->bound. AmigaDOS specific code.*/
+ if (file <= 0) return(NO_FILE);
+ Seek(file, 0, OFFSET_END); /* Seek to end of file.*/
+ new->bound = Seek(file, 0, OFFSET_CURRENT); /* Pos'n == #bytes in file.*/
+ if (new->bound < 0) return(DOS_ERROR); /* DOS being absurd.*/
+ Seek(file, 0, OFFSET_BEGINNING); /* Go to file start.*/
+ /* Would just do this if Amiga DOS maintained fh_End: */
+ /* new->bound = (FileHandle *)BADDR(file)->fh_End; */
+
+ if ( new->bound < sizeof(ChunkHeader) )
+ iffp = NOT_IFF;
+ return(iffp);
+ }
+
+/* ---------- OpenRGroup -----------------------------------------------*/
+IFFP OpenRGroup(parent0, new0) GroupContext *parent0, *new0; {
+ register GroupContext *parent = parent0;
+ register GroupContext *new = new0;
+ IFFP iffp = IFF_OKAY;
+
+ new->parent = parent;
+ new->clientFrame = parent->clientFrame;
+ new->file = parent->file;
+ new->position = parent->position;
+ new->bound = parent->position + ChunkMoreBytes(parent);
+ new->ckHdr.ckID = new->subtype = NULL_CHUNK;
+ new->ckHdr.ckSize = new->bytesSoFar = 0;
+
+ if ( new->bound > parent->bound || IS_ODD(new->bound) )
+ iffp = BAD_IFF;
+ return(iffp);
+ }
+
+/* ---------- CloseRGroup -----------------------------------------------*/
+IFFP CloseRGroup(context) GroupContext *context; {
+ register LONG position;
+
+ if (context->parent == NULL) {
+ } /* Context for whole file.*/
+ else {
+ position = context->position;
+ context->parent->bytesSoFar += position - context->parent->position;
+ context->parent->position = position;
+ }
+ return(IFF_OKAY);
+ }
+
+/* ---------- SkipFwd --------------------------------------------------*/
+/* Skip over bytes in a context. Won't go backwards.*/
+/* Updates context->position but not context->bytesSoFar.*/
+/* This implementation is AmigaDOS specific.*/
+IFFP SkipFwd(context, bytes) GroupContext *context; LONG bytes; {
+ IFFP iffp = IFF_OKAY;
+
+ if (bytes > 0) {
+ if (-1 == Seek(context->file, bytes, OFFSET_CURRENT))
+ iffp = BAD_IFF; /* Ran out of bytes before chunk complete.*/
+ else
+ context->position += bytes;
+ }
+ return(iffp);
+ }
+
+/* ---------- GetChunkHdr ----------------------------------------------*/
+ID GetChunkHdr(context0) GroupContext *context0; {
+ register GroupContext *context = context0;
+ register IFFP iffp;
+ LONG remaining;
+
+ /* Skip remainder of previous chunk & padding. */
+ iffp = SkipFwd(context,
+ ChunkMoreBytes(context) + IS_ODD(context->ckHdr.ckSize));
+ CheckIFFP();
+
+ /* Set up to read the new header. */
+ context->ckHdr.ckID = BAD_IFF; /* Until we know it's okay, mark it BAD.*/
+ context->subtype = NULL_CHUNK;
+ context->bytesSoFar = 0;
+
+ /* Generate a psuedo-chunk if at end-of-context. */
+ remaining = context->bound - context->position;
+ if (remaining == 0) {
+ context->ckHdr.ckSize = 0;
+ context->ckHdr.ckID = END_MARK;
+ }
+
+ /* BAD_IFF if not enough bytes in the context for a ChunkHeader.*/
+ else if (sizeof(ChunkHeader) > remaining) {
+ context->ckHdr.ckSize = remaining;
+ }
+
+ /* Read the chunk header (finally). */
+ else {
+ switch (Read(context->file, &context->ckHdr, sizeof(ChunkHeader))) {
+ case -1: return(context->ckHdr.ckID = DOS_ERROR);
+ case 0: return(context->ckHdr.ckID = BAD_IFF);
+ }
+
+ /* Check: Top level chunk must be LIST or FORM or CAT. */
+ if (context->parent == NULL)
+ switch(context->ckHdr.ckID) {
+ case FORM: case LIST: case CAT: break;
+ default: return(context->ckHdr.ckID = NOT_IFF);
+ }
+
+ /* Update the context. */
+ context->position += sizeof(ChunkHeader);
+ remaining -= sizeof(ChunkHeader);
+
+ /* Non-positive ID values are illegal and used for error codes.*/
+ /* We could check for other illegal IDs...*/
+ if (context->ckHdr.ckID <= 0)
+ context->ckHdr.ckID = BAD_IFF;
+
+ /* Check: ckSize negative or larger than # bytes left in context? */
+ else if (context->ckHdr.ckSize < 0 ||
+ context->ckHdr.ckSize > remaining) {
+ context->ckHdr.ckSize = remaining;
+ context->ckHdr.ckID = BAD_IFF;
+ }
+
+ /* Automatically read the LIST, FORM, PROP, or CAT subtype ID */
+ else switch (context->ckHdr.ckID) {
+ case LIST: case FORM: case PROP: case CAT: {
+ iffp = IFFReadBytes(context,
+ (BYTE *)&context->subtype,
+ sizeof(ID));
+ if (iffp != IFF_OKAY)
+ context->ckHdr.ckID = iffp;
+ break; }
+ }
+
+ }
+ return(context->ckHdr.ckID);
+ }
+
+/* ---------- IFFReadBytes ---------------------------------------------*/
+IFFP IFFReadBytes(context, buffer, nBytes)
+ GroupContext *context; BYTE *buffer; LONG nBytes; {
+ register IFFP iffp = IFF_OKAY;
+
+ if (nBytes < 0)
+ iffp = CLIENT_ERROR;
+ else if (nBytes > ChunkMoreBytes(context))
+ iffp = SHORT_CHUNK;
+ else if (nBytes > 0)
+ switch ( Read(context->file, buffer, nBytes) ) {
+ case -1: {iffp = DOS_ERROR; break; }
+ case 0: {iffp = BAD_IFF; break; }
+ default: {
+ context->position += nBytes;
+ context->bytesSoFar += nBytes;
+ }
+ }
+
+ return(iffp);
+ }
+
+/* ---------- SkipGroup ------------------------------------------------*/
+IFFP SkipGroup(context) GroupContext *context; {
+ } /* Nothing to do, thanks to GetChunkHdr */
+
+/* ---------- ReadIFF --------------------------------------------------*/
+IFFP ReadIFF(file, clientFrame) BPTR file; ClientFrame *clientFrame; {
+ /*CompilerBug register*/ IFFP iffp;
+ GroupContext context;
+
+ iffp = OpenRIFF(file, &context);
+ context.clientFrame = clientFrame;
+
+ if (iffp == IFF_OKAY)
+ switch (iffp = GetChunkHdr(&context)) {
+ case FORM: { iffp = (*clientFrame->getForm)(&context); break; }
+ case LIST: { iffp = (*clientFrame->getList)(&context); break; }
+ case CAT : { iffp = (*clientFrame->getCat )(&context); break; }
+ /* default: Includes IFF_DONE, BAD_IFF, NOT_IFF... */
+ }
+
+ CloseRGroup(&context);
+
+ if (iffp > 0) /* Make sure we don't return an ID.*/
+ iffp = NOT_IFF; /* GetChunkHdr should've caught this.*/
+ return(iffp);
+ }
+
+/* ---------- ReadIList ------------------------------------------------*/
+IFFP ReadIList(parent, clientFrame)
+ GroupContext *parent; ClientFrame *clientFrame; {
+ GroupContext listContext;
+ IFFP iffp;
+ BOOL propOk = TRUE;
+
+ iffp = OpenRGroup(parent, &listContext);
+ CheckIFFP();
+
+ /* One special case test lets us handle CATs as well as LISTs.*/
+ if (parent->ckHdr.ckID == CAT)
+ propOk = FALSE;
+ else
+ listContext.clientFrame = clientFrame;
+
+ do {
+ switch (iffp = GetChunkHdr(&listContext)) {
+ case PROP: {
+ if (propOk)
+ iffp = (*clientFrame->getProp)(&listContext);
+ else
+ iffp = BAD_IFF;
+ break;
+ }
+ case FORM: { iffp = (*clientFrame->getForm)(&listContext); break; }
+ case LIST: { iffp = (*clientFrame->getList)(&listContext); break; }
+ case CAT : { iffp = (*clientFrame->getCat )(&listContext); break; }
+ /* default: Includes END_MARK, IFF_DONE, BAD_IFF, NOT_IFF... */
+ }
+ if (listContext.ckHdr.ckID != PROP)
+ propOk = FALSE; /* No PROPs allowed after this point.*/
+ } while (iffp == IFF_OKAY);
+
+ CloseRGroup(&listContext);
+
+ if (iffp > 0) /* Only chunk types above are allowed in a LIST/CAT.*/
+ iffp = BAD_IFF;
+ return(iffp == END_MARK ? IFF_OKAY : iffp);
+ }
+
+/* ---------- ReadICat -------------------------------------------------*/
+/* By special arrangement with the ReadIList implement'n, this is trivial.*/
+IFFP ReadICat(parent) GroupContext *parent; {
+ return( ReadIList(parent, NULL) );
+ }
+
+/* ---------- GetFChunkHdr ---------------------------------------------*/
+ID GetFChunkHdr(context) GroupContext *context; {
+ register ID id;
+
+ id = GetChunkHdr(context);
+ if (id == PROP)
+ context->ckHdr.ckID = id = BAD_IFF;
+ return(id);
+ }
+
+/* ---------- GetF1ChunkHdr ---------------------------------------------*/
+ID GetF1ChunkHdr(context) GroupContext *context; {
+ register ID id;
+ register ClientFrame *clientFrame = context->clientFrame;
+
+ switch (id = GetChunkHdr(context)) {
+ case PROP: { id = BAD_IFF; break; }
+ case FORM: { id = (*clientFrame->getForm)(context); break; }
+ case LIST: { id = (*clientFrame->getList)(context); break; }
+ case CAT : { id = (*clientFrame->getCat )(context); break; }
+ /* Default: let the caller handle other chunks */
+ }
+ return(context->ckHdr.ckID = id);
+ }
+
+/* ---------- GetPChunkHdr ---------------------------------------------*/
+ID GetPChunkHdr(context) GroupContext *context; {
+ register ID id;
+
+ id = GetChunkHdr(context);
+ switch (id) {
+ case LIST: case FORM: case PROP: case CAT: {
+ id = context->ckHdr.ckID = BAD_IFF;
+ break; }
+ }
+ return(id);
+ }
+
diff --git a/IFFW.C b/IFFW.C
new file mode 100644
index 0000000..7969317
--- /dev/null
+++ b/IFFW.C
@@ -0,0 +1,310 @@
+/*----------------------------------------------------------------------*
+ * IFFW.C Support routines for writing IFF-85 files. 12/02/85
+ * (IFF is Interchange Format File.)
+ *
+ * By Jerry Morrison and Steve Shaw, Electronic Arts.
+ * This software is in the public domain.
+ *
+ * This version for the Commodore-Amiga computer.
+ *----------------------------------------------------------------------*/
+#include "iff/iff.h"
+
+/* ---------- IFF Writer -----------------------------------------------*/
+
+/* A macro to test if a chunk size is definite, i.e. not szNotYetKnown.*/
+#define Known(size) ( (size) != szNotYetKnown )
+
+/* Yet another weird macro to make the source code simpler...*/
+#define IfIffp(expr) {if (iffp == IFF_OKAY) iffp = (expr);}
+
+
+/* ---------- Generic I/O Speed Up Package -----------------------------*/
+
+#define local /*TBD static*/
+
+local BPTR wFile = NULL;
+local BYTE *wBuffer = NULL;
+local LONG wNBytes=0; /* buffer size in bytes.*/
+local LONG wIndex=0; /* index of next available byte.*/
+local LONG wWaterline=0; /* Count of # bytes to be written.
+ * Different than wIndex because of GSeek.*/
+
+/* ---------- GWriteFlush ----------------------------------------------*/
+/* Writes out any data in write buffer above.
+ * NOTE WHEN have Seeked into middle of buffer:
+ * GWriteFlush causes current position to be the end of the data written.
+ * -1 on error from Write.*/
+int GWriteFlush() {
+ int gWrite = 0;
+ if (wFile != NULL && wBuffer != NULL && wIndex > 0)
+ gWrite = Write(wFile, wBuffer, wWaterline);
+ wWaterline = wIndex = 0; /* No matter what, make sure this happens.*/
+ return( gWrite );
+ }
+
+/* ---------- GWriteDeclare --------------------------------------------*/
+/* Sets up variables above to describe a write buffer.*/
+/* -1 on error from Write.*/
+int GWriteDeclare(file, buffer, nBytes)
+ BPTR file; BYTE *buffer; LONG nBytes; {
+ int gWrite = GWriteFlush();
+ if ( file==NULL || buffer==NULL || nBytes<=3) {
+ wFile = NULL; wBuffer = NULL; wNBytes = 0; }
+ else {
+ wFile = file; wBuffer = buffer; wNBytes = nBytes; }
+ return( gWrite );
+ }
+
+/* ---------- GWrite ---------------------------------------------------*/
+/* ANY PROGRAM WHICH USES "GWrite" MUST USE "GSeek" rather than "Seek"
+ * TO SEEK ON A FILE BEING WRITTEN WITH "GWrite".
+ * "Write" with Generic speed-up.
+ * -1 on error from Write. else returns # bytes written to disk.*/
+int GWrite(file, buffer, nBytes) BPTR file; BYTE *buffer; int nBytes; {
+ int gWrite = 0;
+
+ if (file == wFile && wBuffer != NULL) {
+ if (wNBytes >= wIndex + nBytes) {
+ /* Append to wBuffer.*/
+ movmem(buffer, wBuffer+wIndex, nBytes);
+ wIndex += nBytes;
+ if (wIndex > wWaterline)
+ wWaterline = wIndex;
+ nBytes = 0; /* Indicate data has been swallowed.*/
+ }
+ else {
+ wWaterline = wIndex; /* We are about to overwrite any
+ * data above wIndex, up to at least the buffer end.*/
+ gWrite = GWriteFlush(); /* Write data out in proper order.*/
+ }
+ }
+ if (nBytes > 0 && gWrite >= 0)
+ gWrite += Write(file, buffer, nBytes);
+ return( gWrite );
+ }
+
+/* ---------- GSeek ----------------------------------------------------*/
+/* "Seek" with Generic speed-up, for a file being written with GWrite.*/
+/* Returns what Seek returns, which appears to be the position BEFORE
+ * seeking, though the documentation says it returns the NEW position.*/
+/* CURRENTLY RETURNS 0 WHEN SEEKING WITHIN THE BUFFER.*/
+int GSeek(file, position, mode)
+ BPTR file; BYTE *position; int mode; {
+ int gSeek = -2;
+ int newWIndex = wIndex + (int)position;
+
+ if (file == wFile && wBuffer != NULL) {
+ if (mode == OFFSET_CURRENT &&
+ newWIndex >= 0 && newWIndex <= wWaterline) {
+ wIndex = newWIndex;
+ gSeek = 0; /* Okay */
+ }
+ else {
+ /* Can't optimize it.*/
+ gSeek = GWriteFlush();
+ if (gSeek >= 0) gSeek = -2; /* OK so far */
+ }
+ }
+ if (gSeek == -2)
+ gSeek = Seek(file, position, mode);
+ return( gSeek );
+ }
+
+/* ---------- OpenWIFF -------------------------------------------------*/
+
+IFFP OpenWIFF(file, new0, limit) BPTR file; GroupContext *new0; LONG limit; {
+ register GroupContext *new = new0;
+ register IFFP iffp = IFF_OKAY;
+
+ new->parent = NULL;
+ new->clientFrame = NULL;
+ new->file = file;
+ new->position = 0;
+ new->bound = limit;
+ new->ckHdr.ckID = NULL_CHUNK; /* indicates no current chunk */
+ new->ckHdr.ckSize = new->bytesSoFar = 0;
+
+ if (0 > Seek(file, 0, OFFSET_BEGINNING)) /* Go to start of the file.*/
+ iffp = DOS_ERROR;
+ else if ( Known(limit) && IS_ODD(limit) )
+ iffp = CLIENT_ERROR;
+ return(iffp);
+ }
+
+/* ---------- StartWGroup ----------------------------------------------*/
+IFFP StartWGroup(parent, groupType, groupSize, subtype, new)
+ GroupContext *parent, *new; ID groupType, subtype; LONG groupSize; {
+ register IFFP iffp;
+
+ iffp = PutCkHdr(parent, groupType, groupSize);
+ IfIffp( IFFWriteBytes(parent, (BYTE *)&subtype, sizeof(ID)) );
+ IfIffp( OpenWGroup(parent, new) );
+ return(iffp);
+ }
+
+/* ---------- OpenWGroup -----------------------------------------------*/
+IFFP OpenWGroup(parent0, new0) GroupContext *parent0, *new0; {
+ register GroupContext *parent = parent0;
+ register GroupContext *new = new0;
+ register LONG ckEnd;
+ register IFFP iffp = IFF_OKAY;
+
+ new->parent = parent;
+ new->clientFrame = parent->clientFrame;
+ new->file = parent->file;
+ new->position = parent->position;
+ new->bound = parent->bound;
+ new->ckHdr.ckID = NULL_CHUNK;
+ new->ckHdr.ckSize = new->bytesSoFar = 0;
+
+ if ( Known(parent->ckHdr.ckSize) ) {
+ ckEnd = new->position + ChunkMoreBytes(parent);
+ if ( new->bound == szNotYetKnown || new->bound > ckEnd )
+ new->bound = ckEnd;
+ };
+
+ if ( parent->ckHdr.ckID == NULL_CHUNK || /* not currently writing a chunk*/
+ IS_ODD(new->position) ||
+ (Known(new->bound) && IS_ODD(new->bound)) )
+ iffp = CLIENT_ERROR;
+ return(iffp);
+ }
+
+/* ---------- CloseWGroup ----------------------------------------------*/
+IFFP CloseWGroup(old0) GroupContext *old0; {
+ register GroupContext *old = old0;
+
+ if ( old->ckHdr.ckID != NULL_CHUNK ) /* didn't close the last chunk */
+ return(CLIENT_ERROR);
+ if ( old->parent == NULL ) { /* top level file context */
+ /* [TBD] set logical EOF */
+ /* [TBD] GWriteEOF(old->file); */
+ GWriteFlush(); /* Good enough.*/
+ }
+ else {
+ old->parent->bytesSoFar += old->position - old->parent->position;
+ old->parent->position = old->position;
+ };
+ return(IFF_OKAY);
+ }
+
+/* ---------- EndWGroup ------------------------------------------------*/
+IFFP EndWGroup(old) GroupContext *old; {
+ register GroupContext *parent = old->parent;
+ register IFFP iffp;
+
+ iffp = CloseWGroup(old);
+ IfIffp( PutCkEnd(parent) );
+ return(iffp);
+ }
+
+/* ---------- PutCk ----------------------------------------------------*/
+IFFP PutCk(context, ckID, ckSize, data)
+ GroupContext *context; ID ckID; LONG ckSize; BYTE *data; {
+ register IFFP iffp = IFF_OKAY;
+
+ if ( ckSize == szNotYetKnown )
+ iffp = CLIENT_ERROR;
+ IfIffp( PutCkHdr(context, ckID, ckSize) );
+ IfIffp( IFFWriteBytes(context, data, ckSize) );
+ IfIffp( PutCkEnd(context) );
+ return(iffp);
+ }
+
+/* ---------- PutCkHdr -------------------------------------------------*/
+IFFP PutCkHdr(context0, ckID, ckSize)
+ GroupContext *context0; ID ckID; LONG ckSize; {
+ register GroupContext *context = context0;
+ LONG minPSize = sizeof(ChunkHeader); /* physical chunk >= minPSize bytes*/
+
+ /* CLIENT_ERROR if we're already inside a chunk or asked to write
+ * other than one FORM, LIST, or CAT at the top level of a file */
+ /* Also, non-positive ID values are illegal and used for error codes.*/
+ /* (We could check for other illegal IDs...)*/
+ if ( context->ckHdr.ckID != NULL_CHUNK || ckID <= 0 )
+ return(CLIENT_ERROR);
+ else if (context->parent == NULL) {
+ switch (ckID) {
+ case FORM: case LIST: case CAT: break;
+ default: return(CLIENT_ERROR);
+ }
+ if (context->position != 0)
+ return(CLIENT_ERROR);
+ }
+
+ if ( Known(ckSize) ) {
+ if ( ckSize < 0 )
+ return(CLIENT_ERROR);
+ minPSize += ckSize;
+ };
+ if ( Known(context->bound) &&
+ context->position + minPSize > context->bound )
+ return(CLIENT_ERROR);
+
+ context->ckHdr.ckID = ckID;
+ context->ckHdr.ckSize = ckSize;
+ context->bytesSoFar = 0;
+ if (0 > GWrite(context->file, &context->ckHdr, sizeof(ChunkHeader)))
+ return(DOS_ERROR);
+ context->position += sizeof(ChunkHeader);
+ return(IFF_OKAY);
+ }
+
+/* ---------- IFFWriteBytes ---------------------------------------------*/
+IFFP IFFWriteBytes(context0, data, nBytes)
+ GroupContext *context0; BYTE *data; LONG nBytes; {
+ register GroupContext *context = context0;
+
+ if ( context->ckHdr.ckID == NULL_CHUNK || /* not in a chunk */
+ nBytes < 0 || /* negative nBytes */
+ (Known(context->bound) && /* overflow context */
+ context->position + nBytes > context->bound) ||
+ (Known(context->ckHdr.ckSize) && /* overflow chunk */
+ context->bytesSoFar + nBytes > context->ckHdr.ckSize) )
+ return(CLIENT_ERROR);
+
+ if (0 > GWrite(context->file, data, nBytes))
+ return(DOS_ERROR);
+
+ context->bytesSoFar += nBytes;
+ context->position += nBytes;
+ return(IFF_OKAY);
+ }
+
+/* ---------- PutCkEnd -------------------------------------------------*/
+IFFP PutCkEnd(context0) GroupContext *context0; {
+ register GroupContext *context = context0;
+ WORD zero = 0; /* padding source */
+
+ if ( context->ckHdr.ckID == NULL_CHUNK ) /* not in a chunk */
+ return(CLIENT_ERROR);
+
+ if ( context->ckHdr.ckSize == szNotYetKnown ) {
+ /* go back and set the chunk size to bytesSoFar */
+ if ( 0 > GSeek(context->file,
+ -(context->bytesSoFar + sizeof(LONG)),
+ OFFSET_CURRENT) ||
+ 0 > GWrite(context->file, &context->bytesSoFar, sizeof(LONG)) ||
+ 0 > GSeek(context->file, context->bytesSoFar, OFFSET_CURRENT) )
+ return(DOS_ERROR);
+ }
+ else { /* make sure the client wrote as many bytes as planned */
+ if ( context->ckHdr.ckSize != context->bytesSoFar )
+ return(CLIENT_ERROR);
+ };
+
+ /* Write a pad byte if needed to bring us up to an even boundary.
+ * Since the context end must be even, and since we haven't
+ * overwritten the context, if we're on an odd position there must
+ * be room for a pad byte. */
+ if ( IS_ODD(context->bytesSoFar) ) {
+ if ( 0 > GWrite(context->file, &zero, 1) )
+ return(DOS_ERROR);
+ context->position += 1;
+ };
+
+ context->ckHdr.ckID = NULL_CHUNK;
+ context->ckHdr.ckSize = context->bytesSoFar = 0;
+ return(IFF_OKAY);
+ }
+
diff --git a/ILBMR.C b/ILBMR.C
new file mode 100644
index 0000000..1e126bb
--- /dev/null
+++ b/ILBMR.C
@@ -0,0 +1,144 @@
+/*----------------------------------------------------------------------*/
+/* ILBMR.C Support routines for reading ILBM files. 11/07/85 */
+/* (IFF is Interchange Format File.) */
+/* */
+/* By Jerry Morrison and Steve Shaw, Electronic Arts. */
+/* This software is in the public domain. */
+/*----------------------------------------------------------------------*/
+#include "iff\packer.h"
+#include "iff\ilbm.h"
+
+
+/* ---------- GetCMAP ------------------------------------------------*/
+/* pNColorRegs is passed in as a pointer to the number of ColorRegisters
+ * caller has space to hold. GetCMAP sets to the number actually read.*/
+IFFP GetCMAP(ilbmContext, colorMap, pNColorRegs)
+ GroupContext *ilbmContext; WORD *colorMap; UBYTE *pNColorRegs;
+ {
+ register int nColorRegs;
+ register IFFP iffp;
+ ColorRegister colorReg;
+
+ nColorRegs = ilbmContext->ckHdr.ckSize / sizeofColorRegister;
+ if (*pNColorRegs < nColorRegs) nColorRegs = *pNColorRegs;
+ *pNColorRegs = nColorRegs; /* Set to the number actually there.*/
+
+ for ( ; nColorRegs > 0; --nColorRegs) {
+ iffp = IFFReadBytes(ilbmContext, (BYTE *)&colorReg,sizeofColorRegister);
+ CheckIFFP();
+ *colorMap++ = ( ( colorReg.red >> 4 ) << 8 ) |
+ ( ( colorReg.green >> 4 ) << 4 ) |
+ ( ( colorReg.blue >> 4 ) );
+ }
+ return(IFF_OKAY);
+ }
+
+/*---------- GetBODY ---------------------------------------------------*/
+/* NOTE: This implementation could be a LOT faster if it used more of the
+ * supplied buffer. It would make far fewer calls to IFFReadBytes (and
+ * therefore to DOS Read) and to movemem. */
+IFFP GetBODY(context, bitmap, mask, bmHdr, buffer, bufsize)
+ GroupContext *context; struct BitMap *bitmap; BYTE *mask;
+ BitMapHeader *bmHdr; BYTE *buffer; LONG bufsize;
+ {
+ register IFFP iffp;
+ UBYTE srcPlaneCnt = bmHdr->nPlanes; /* Haven't counted for mask plane yet*/
+ LONG srcRowBytes = RowBytes(bmHdr->w);
+ LONG bufRowBytes = MaxPackedSize(srcRowBytes);
+ int nRows = bmHdr->h;
+ Compression compression = bmHdr->compression;
+ register int iPlane, iRow, nEmpty, nFilled;
+ BYTE *buf, *nullDest, *nullBuf, **pDest;
+ BYTE *planes[MaxSrcPlanes]; /* array of ptrs to planes & mask */
+
+ if (compression > cmpByteRun1)
+ return(CLIENT_ERROR);
+
+ /* Complain if client asked for a conversion GetBODY doesn't handle.*/
+ if ( srcRowBytes != bitmap->BytesPerRow ||
+ bufsize < bufRowBytes * 2 ||
+ srcPlaneCnt > MaxSrcPlanes )
+ return(CLIENT_ERROR);
+
+ if (nRows > bitmap->Rows)
+ nRows = bitmap->Rows;
+
+ /* Initialize array "planes" with bitmap ptrs; NULL in empty slots.*/
+ for (iPlane = 0; iPlane < bitmap->Depth; iPlane++)
+ planes[iPlane] = (BYTE *)bitmap->Planes[iPlane];
+ for ( ; iPlane < MaxSrcPlanes; iPlane++)
+ planes[iPlane] = NULL;
+
+ /* Copy any mask plane ptr into corresponding "planes" slot.*/
+ if (bmHdr->masking == mskHasMask) {
+ if (mask != NULL)
+ planes[srcPlaneCnt] = mask; /* If there are more srcPlanes than
+ * dstPlanes, there will be NULL plane-pointers before this.*/
+ else
+ planes[srcPlaneCnt] = NULL; /* In case more dstPlanes than src.*/
+ srcPlaneCnt += 1; /* Include mask plane in count.*/
+ }
+
+ /* Setup a sink for dummy destination of rows from unwanted planes.*/
+ nullDest = buffer;
+ buffer += srcRowBytes;
+ bufsize -= srcRowBytes;
+
+ /* Read the BODY contents into client's bitmap.
+ * De-interleave planes and decompress rows.
+ * MODIFIES: Last iteration modifies bufsize.*/
+ buf = buffer + bufsize; /* Buffer is currently empty.*/
+ for (iRow = nRows; iRow > 0; iRow--) {
+ for (iPlane = 0; iPlane < srcPlaneCnt; iPlane++) {
+
+ pDest = &planes[iPlane];
+
+ /* Establish a sink for any unwanted plane.*/
+ if (*pDest == NULL) {
+ nullBuf = nullDest;
+ pDest = &nullBuf;
+ }
+
+ /* Read in at least enough bytes to uncompress next row.*/
+ nEmpty = buf - buffer; /* size of empty part of buffer.*/
+ nFilled = bufsize - nEmpty; /* this part has data.*/
+ if (nFilled < bufRowBytes) {
+ /* Need to read more.*/
+
+ /* Move the existing data to the front of the buffer.*/
+ /* Now covers range buffer[0]..buffer[nFilled-1].*/
+ movmem(buf, buffer, nFilled); /* Could be moving 0 bytes.*/
+
+ if (nEmpty > ChunkMoreBytes(context)) {
+ /* There aren't enough bytes left to fill the buffer.*/
+ nEmpty = ChunkMoreBytes(context);
+ bufsize = nFilled + nEmpty; /* heh-heh */
+ }
+
+ /* Append new data to the existing data.*/
+ iffp = IFFReadBytes(context, &buffer[nFilled], nEmpty);
+ CheckIFFP();
+
+ buf = buffer;
+ nFilled = bufsize;
+ nEmpty = 0;
+ }
+
+ /* Copy uncompressed row to destination plane.*/
+ if (compression == cmpNone) {
+ if (nFilled < srcRowBytes) return(BAD_FORM);
+ movmem(buf, *pDest, srcRowBytes);
+ buf += srcRowBytes;
+ *pDest += srcRowBytes;
+ }
+ else
+ /* Decompress row to destination plane.*/
+ if ( UnPackRow(&buf, pDest, nFilled, srcRowBytes) )
+ /* pSource, pDest, srcBytes, dstBytes */
+ return(BAD_FORM);
+ }
+ }
+
+ return(IFF_OKAY);
+ }
+
diff --git a/ILBMW.C b/ILBMW.C
new file mode 100644
index 0000000..c5ec37b
--- /dev/null
+++ b/ILBMW.C
@@ -0,0 +1,140 @@
+/*----------------------------------------------------------------------*/
+/* ILBMW.C Support routines for writing ILBM files. 11/06/85 */
+/* (IFF is Interchange Format File.) */
+/* */
+/* By Jerry Morrison and Steve Shaw, Electronic Arts. */
+/* This software is in the public domain. */
+/*----------------------------------------------------------------------*/
+#include "iff\packer.h"
+#include "iff\ilbm.h"
+
+/*---------- InitBMHdr -------------------------------------------------*/
+IFFP InitBMHdr(bmHdr0, bitmap, masking, compression, transparentColor,
+ pageWidth, pageHeight)
+ BitMapHeader *bmHdr0; struct BitMap *bitmap;
+ int masking, compression, transparentColor, pageWidth, pageHeight;
+ /* Masking, Compression, UWORD, WORD, WORD */
+ {
+ register BitMapHeader *bmHdr = bmHdr0;
+ register WORD rowBytes = bitmap->BytesPerRow;
+
+ bmHdr->w = rowBytes << 3;
+ bmHdr->h = bitmap->Rows;
+ bmHdr->x = bmHdr->y = 0; /* Default position is (0,0).*/
+ bmHdr->nPlanes = bitmap->Depth;
+ bmHdr->masking = masking;
+ bmHdr->compression = compression;
+ bmHdr->pad1 = 0;
+ bmHdr->transparentColor = transparentColor;
+ bmHdr->xAspect = bmHdr->yAspect = 1;
+ bmHdr->pageWidth = pageWidth;
+ bmHdr->pageHeight = pageHeight;
+
+ if (pageWidth = 320)
+ switch (pageHeight) {
+ case 200: {bmHdr->xAspect = x320x200Aspect;
+ bmHdr->yAspect = y320x200Aspect; break;}
+ case 400: {bmHdr->xAspect = x320x400Aspect;
+ bmHdr->yAspect = y320x400Aspect; break;}
+ }
+ else if (pageWidth = 640)
+ switch (pageHeight) {
+ case 200: {bmHdr->xAspect = x640x200Aspect;
+ bmHdr->yAspect = y640x200Aspect; break;}
+ case 400: {bmHdr->xAspect = x640x400Aspect;
+ bmHdr->yAspect = y640x400Aspect; break;}
+ }
+
+ return( IS_ODD(rowBytes) ? CLIENT_ERROR : IFF_OKAY );
+ }
+
+/*---------- PutCMAP ---------------------------------------------------*/
+IFFP PutCMAP(context, colorMap, depth)
+ GroupContext *context; WORD *colorMap; UBYTE depth;
+ {
+ register LONG nColorRegs;
+ IFFP iffp;
+ ColorRegister colorReg;
+
+ if (depth > MaxAmDepth) depth = MaxAmDepth;
+ nColorRegs = 1 << depth;
+
+ iffp = PutCkHdr(context, ID_CMAP, nColorRegs * sizeofColorRegister);
+ CheckIFFP();
+
+ for ( ; nColorRegs; --nColorRegs) {
+ colorReg.red = ( *colorMap >> 4 ) & 0xf0;
+ colorReg.green = ( *colorMap ) & 0xf0;
+ colorReg.blue = ( *colorMap << 4 ) & 0xf0;
+ iffp = IFFWriteBytes(context, (BYTE *)&colorReg, sizeofColorRegister);
+ CheckIFFP();
+ ++colorMap;
+ }
+
+ iffp = PutCkEnd(context);
+ return(iffp);
+ }
+
+/*---------- PutBODY ---------------------------------------------------*/
+/* NOTE: This implementation could be a LOT faster if it used more of the
+ * supplied buffer. It would make far fewer calls to IFFWriteBytes (and
+ * therefore to DOS Write). */
+IFFP PutBODY(context, bitmap, mask, bmHdr, buffer, bufsize)
+ GroupContext *context; struct BitMap *bitmap; BYTE *mask;
+ BitMapHeader *bmHdr; BYTE *buffer; LONG bufsize;
+ {
+ IFFP iffp;
+ LONG rowBytes = bitmap->BytesPerRow;
+ int dstDepth = bmHdr->nPlanes;
+ Compression compression = bmHdr->compression;
+ int planeCnt; /* number of bit planes including mask */
+ register int iPlane, iRow;
+ register LONG packedRowBytes;
+ BYTE *buf;
+ BYTE *planes[MaxAmDepth + 1]; /* array of ptrs to planes & mask */
+
+ if ( bufsize < MaxPackedSize(rowBytes) || /* Must buffer a comprsd row*/
+ compression > cmpByteRun1 || /* bad arg */
+ bitmap->Rows != bmHdr->h || /* inconsistent */
+ rowBytes != RowBytes(bmHdr->w) || /* inconsistent*/
+ bitmap->Depth < dstDepth || /* inconsistent */
+ dstDepth > MaxAmDepth ) /* too many for this routine*/
+ return(CLIENT_ERROR);
+
+ planeCnt = dstDepth + (mask == NULL ? 0 : 1);
+
+ /* Copy the ptrs to bit & mask planes into local array "planes" */
+ for (iPlane = 0; iPlane < dstDepth; iPlane++)
+ planes[iPlane] = (BYTE *)bitmap->Planes[iPlane];
+ if (mask != NULL)
+ planes[dstDepth] = mask;
+
+ /* Write out a BODY chunk header */
+ iffp = PutCkHdr(context, ID_BODY, szNotYetKnown);
+ CheckIFFP();
+
+ /* Write out the BODY contents */
+ for (iRow = bmHdr->h; iRow > 0; iRow--) {
+ for (iPlane = 0; iPlane < planeCnt; iPlane++) {
+
+ /* Write next row.*/
+ if (compression == cmpNone) {
+ iffp = IFFWriteBytes(context, planes[iPlane], rowBytes);
+ planes[iPlane] += rowBytes;
+ }
+
+ /* Compress and write next row.*/
+ else {
+ buf = buffer;
+ packedRowBytes = PackRow(&planes[iPlane], &buf, rowBytes);
+ iffp = IFFWriteBytes(context, buffer, packedRowBytes);
+ }
+
+ CheckIFFP();
+ }
+ }
+
+ /* Finish the chunk */
+ iffp = PutCkEnd(context);
+ return(iffp);
+ }
diff --git a/INITOVS.C b/INITOVS.C
new file mode 100644
index 0000000..7dc9623
--- /dev/null
+++ b/INITOVS.C
@@ -0,0 +1,10 @@
+/*----------------------------------------------------------------------*/
+/* */
+/* initovs.c */
+/* */
+/*----------------------------------------------------------------------*/
+
+/* Dummy call which is trapped by the overlay manager to setup
+the overlay parameters. */
+
+InitOVS() {}
diff --git a/INITREAD.C b/INITREAD.C
new file mode 100644
index 0000000..dfa0f43
--- /dev/null
+++ b/INITREAD.C
@@ -0,0 +1,10 @@
+/*----------------------------------------------------------------------*/
+/* */
+/* initread.c -- */
+/* */
+/*----------------------------------------------------------------------*/
+
+/* the sole purpose is to bring in the reader overlay BEFORE the user
+ puts in his data disk */
+
+InitRead() {} \ No newline at end of file
diff --git a/INITWRIT.C b/INITWRIT.C
new file mode 100644
index 0000000..0809441
--- /dev/null
+++ b/INITWRIT.C
@@ -0,0 +1,10 @@
+/*----------------------------------------------------------------------*/
+/* */
+/* initwrite.c -- */
+/* */
+/*----------------------------------------------------------------------*/
+
+/* the sole purpose is to bring in the writer overlay BEFORE the user
+ puts in his data disk */
+
+InitWrite() {} \ No newline at end of file
diff --git a/INTUALL.H b/INTUALL.H
new file mode 100644
index 0000000..96882ee
--- /dev/null
+++ b/INTUALL.H
@@ -0,0 +1,34 @@
+#include <exec\types.h>
+#include <exec\nodes.h>
+#include <exec\lists.h>
+#include <exec\interrupts.h>
+#include <exec\memory.h>
+#include <exec\tasks.h>
+#include <exec\ports.h>
+#include <exec\libraries.h>
+#include <exec\io.h>
+#include <exec\devices.h>
+#include <clib\macros.h>
+#include <devices\timer.h>
+#include <librarie\dos.h>
+#include <graphics\gfx.h>
+#include <hardware\blit.h>
+#include <graphics\copper.h>
+#include <graphics\display.h>
+#include <graphics\gels.h>
+#include <graphics\regions.h>
+#include <graphics\clip.h>
+#include <graphics\rastport.h>
+#include <graphics\view.h>
+#include <graphics\gfxbase.h>
+#include <graphics\text.h>
+#include <graphics\gfxmacros.h>
+#include <graphics\layers.h>
+#include <intuition\intuition.h>
+#include <devices\inputevent.h>
+#include <devices\keymap.h>
+#include <workbench\startup.h>
+
+
+
+
diff --git a/KEYJUNK.C b/KEYJUNK.C
new file mode 100644
index 0000000..0138391
--- /dev/null
+++ b/KEYJUNK.C
@@ -0,0 +1,109 @@
+/*----------------------------------------------------------------------*/
+/* */
+/* keyjunk.c */
+/* */
+/*----------------------------------------------------------------------*/
+
+#include "system.h"
+
+#define local static
+
+SHORT ShiftKey = 0;
+SHORT AltKey = 0;
+SHORT Lshift = 0, Rshift = 0;
+SHORT Ctrl = 0;
+SHORT Caps = 0;
+SHORT LeftAlt = 0;
+SHORT RightAlt = 0;
+SHORT LeftCom = 0;
+SHORT RightCom = 0;
+
+local char unshChars[] = {
+/*0 1 2 3 4 5 6 7 8 9 a b c d e f */
+0x60,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x30,0x2d,0x3d,0x5c,0x08,0x00,
+0x71,0x77,0x65,0x72,0x74,0x79,0x75,0x69,0x6f,0x70,0x5b,0x5d,0x0d,0x31,0x32,0x33,
+0x61,0x73,0x64,0x66,0x67,0x68,0x6a,0x6b,0x6c,0x3b,0x27,0x00,0x00,0x34,0x35,0x36,
+0x00,0x7a,0x78,0x63,0x76,0x62,0x6e,0x6d,0x2c,0x2e,0x2f,0x00,0x2e,0x37,0x38,0x39,
+0x20,0x08,0x09,0x0d,0x0d,0x1b,0x7f,0x00,0x00,0x00,0x2d,0x00,0x00,0x00,0x00,0x00
+};
+
+local char shftChars[] = {
+0x7e,0x21,0x40,0x23,0x24,0x25,0x5e,0x26,0x2a,0x28,0x29,0x5f,0x2b,0x7c,0x08,0x00,
+0x51,0x57,0x45,0x52,0x54,0x59,0x55,0x49,0x4f,0x50,0x7b,0x7d,0x0d,0x31,0x32,0x33,
+0x41,0x53,0x44,0x46,0x47,0x48,0x4a,0x4b,0x4c,0x3a,0x22,0x00,0x00,0x34,0x35,0x36,
+0x00,0x5a,0x58,0x43,0x56,0x42,0x4e,0x4d,0x3c,0x3e,0x3f,0x00,0x2e,0x37,0x38,0x39,
+0x20,0x08,0x09,0x0d,0x0d,0x1b,0x7f,0x00,0x00,0x00,0x2d,0x00,0x00,0x00,0x00,0x00
+};
+
+#define NoChar 0xff
+
+
+InitBoard() {}
+
+/****************************************************************/
+/* */
+/* MGetCh: equivalent to the old MayGetCh(); */
+/* returns(0xff) if no keys have been hit, otherwise */
+/* returns the key. */
+/* */
+/* Special Keys (non-ascii) are returned as 2 chars: */
+/* a null (0) character, followed by a character specific */
+/* to the key hit. The codes returned following the */
+/* null are: */
+/* Function Key Fn: 0x3a + n */
+/* Cursor Up: 0x50 */
+/* Cursor Down: 0x48 */
+/* Cursor Right: 0x4d */
+/* Cursor Left: 0x4b */
+/* */
+/****************************************************************/
+SHORT dbgkbd = 0;
+
+local SHORT specChar;
+local SHORT specialKey = FALSE;
+local BYTE cursChar[4] = {0x50,0x48,0x4d,0x4b};
+local Special(c) BYTE c; { specialKey = TRUE; specChar = c; }
+
+#define ESC 0x1b
+
+/* use this for getting second char of 2 char sequence */
+SHORT GetNextCh() {
+ if (specialKey) { specialKey = FALSE; return(specChar); }
+ else return(NoChar);
+ }
+
+SHORT CharFromKeyCode(rcode) UBYTE rcode; {
+ UBYTE code,key;
+ SHORT downStroke;
+/* if (rcode ==NULL) return(NoChar); */
+ if (dbgkbd) KPrintF(" rcode = %lx \n",rcode);
+ code = 0x7f&rcode;
+ if ( (code&0x70) == 0x70) return(NoChar);
+ downStroke = ((rcode&0x80)==0);
+ if (code<0x4b) {
+ if (!downStroke) return(NoChar);
+ key = (Caps||(Lshift|Rshift))? shftChars[code]: unshChars[code];
+ return((SHORT)key);
+ }
+ switch (code) {
+ case 0x45: return(ESC); break;
+ case 0x60: Lshift = downStroke; ShiftKey = Lshift|Rshift; return(NoChar); break;
+ case 0x61: Rshift = downStroke; ShiftKey = Lshift|Rshift;return(NoChar); break;
+ case 0x62: Caps = downStroke; return(NoChar); break;
+ case 0x63: Ctrl = downStroke; return(NoChar); break;
+ case 0x64: LeftAlt = downStroke; AltKey = LeftAlt|RightAlt; return(NoChar); break;
+ case 0x65: RightAlt = downStroke; AltKey = LeftAlt|RightAlt;return(NoChar); break;
+ case 0x66: LeftCom = downStroke; return(NoChar); break;
+ case 0x67: RightCom = downStroke; return(NoChar); break;
+ case 0x5f: Special(0x01); return(NULL); break; /*HELP key*/
+ default:
+ if (!downStroke) return(NoChar);
+ if ((0x50<=code)&&(code <= 0x59)) /* function keys */
+ { Special(0x3b + code-0x50); return(NULL); }
+ if ((0x4c<=code)&&(code <= 0x4f)) /* cursor keys */
+ { Special(cursChar[code - 0x4c]); return(NULL); }
+ return(NoChar);
+ break;
+ }
+ }
+
diff --git a/MAGBITS.C b/MAGBITS.C
new file mode 100644
index 0000000..7407f4e
--- /dev/null
+++ b/MAGBITS.C
@@ -0,0 +1,233 @@
+/*----------------------------------------------------------------------*/
+/* */
+/* magbits.c -- Integer Bitmap Magnification (c)Electronic Arts */
+/* */
+/* */
+/* 6/26/85 Created Dan Silva -- Electronic Arts */
+/* 7/13/85 v27 Mods Dan Silva -- Electronic Arts */
+/* */
+/*----------------------------------------------------------------------*/
+
+#include <system.h>
+#include <prism.h>
+
+#define method1
+
+#ifdef method1
+/* CLIPPED stretch by integer multiple in X and Y direction --
+
+ This version does the final y-stretch by "tricking" BltBitMap into
+ outputting each line N times in one call. It requires H calls to
+ BltBitMap, wher H is the number of "fat bit" scan lines visible in
+ the clipping window. It is thus slow for small magnifications,
+ but quite fast for high magnifications. Even at small
+ magnifications the updates have a much smoother appearance than the
+ other algorithm. */
+
+short MagBits(sbm,sbox,dbm,dx,dy,NX,NY,clip)
+ struct BitMap *sbm, *dbm;
+ Box *sbox;
+ int dx,dy; /* upper left corner in dbm */
+ int NX,NY; /* magnify factor */
+ Box *clip; /* clip box in destination bm */
+ {
+ SHORT xs,xd,yd,ys,sxmax,i,nout,lx,clymax, depth,bpr,nrep,ydcl;
+ static SHORT dw;
+ static Box c,fr;
+ struct BitMap tmpBM,tmpBM2;
+ depth = dbm->Depth;
+
+ /* clip in source bitmap to avoid unnecessary work */
+
+ fr.x = (clip->x - dx)/NX + sbox->x;
+ fr.y = (clip->y - dy)/NY + sbox->y;
+ fr.w = (clip->w + NX - 1)/NX;
+ fr.h = (clip->h + NY - 1)/NY;
+
+ if (!BoxAnd(&c,&fr,sbox)) return(0);
+
+ dx += NX*(c.x - sbox->x);
+ dy += NY*(c.y - sbox->y);
+ dw = c.w*NX;
+
+ if ( (NX==1)&&(NY==1))
+ { BltBitMap(sbm,c.x,c.y,dbm,dx,dy,c.w,c.h,REPOP,0xff,NULL); return(0); }
+
+ tmpBM.Planes[0] = tmpBM2.Planes[0] = 0;
+
+ InitBitMap(&tmpBM,depth,dw,c.h);
+ InitBitMap(&tmpBM2,depth,dw,c.h);
+
+ if (TmpAllocBitMap(&tmpBM)) {
+ GunTheBrush();
+ if (TmpAllocBitMap(&tmpBM));
+ return(FAIL);
+ }
+ if (TmpAllocBitMap(&tmpBM2)) {
+ GunTheBrush();
+ if (TmpAllocBitMap(&tmpBM2)) {
+ FreeBitMap(&tmpBM);
+ return(FAIL);
+ }
+ }
+ ClearBitMap(&tmpBM); ClearBitMap(&tmpBM2);
+
+ /*--------- stretch horizontally first--------------*/
+ sxmax = c.x + c.w;
+ xd = 0;
+ for (xs = c.x; xs < sxmax; xs++ ) {
+ BltBitMap(sbm,xs,c.y,&tmpBM,xd,0,1,c.h,REPOP,0xff,NULL);
+ xd += NX;
+ }
+ for (i=0; i<NX; i++)
+ BltBitMap(&tmpBM,0,0,&tmpBM2,i,0,dw-NX+1,c.h,OROP,0xff,NULL);
+
+ /*--------- prepare to stretch Vertically--------------*/
+ lx = 0;
+ if ( (nout = clip->x - dx) >0) { lx += nout; dx+=nout; dw -= nout; }
+ if ( (nout = dx+dw - (clip->x+clip->w)) > 0) { dw -= nout; }
+
+ yd = dy;
+ clymax = clip->y + clip->h;
+
+ /**--------- Stretch vertically into destination Raster Port -----***/
+ /* Mess around with width of tmpBM2 to trick BltBitMap ----- */
+ /* into outputting the same line many times */
+
+ bpr = tmpBM2.BytesPerRow;
+ tmpBM2.BytesPerRow = 0;
+
+ for (ys = 0; ys < c.h; ys++) {
+ nrep = NY;
+ ydcl = yd;
+ if (ys==0) if (( nout=(clip->y-ydcl))>0) { nrep-= nout; ydcl += nout;}
+ if (ys==c.h-1) if (( nout = ( yd+NY - clymax)) > 0) nrep -= nout;
+ BltBitMap(&tmpBM2,lx,0,dbm,dx,ydcl,dw,nrep, REPOP,0xff,NULL);
+ for (i = 0; i<depth; i++) tmpBM2.Planes[i] += bpr;
+ yd += NY;
+ }
+
+ /* --------- restore bitmap pointers to original state -----*/
+ for (i=0; i<depth; i++) tmpBM2.Planes[i] -= c.h*bpr;
+ tmpBM2.BytesPerRow = bpr;
+ FreeBitMap(&tmpBM);
+ FreeBitMap(&tmpBM2);
+ return(SUCCESS);
+ }
+
+
+/* CLIPPED stretch by integer multiple in X and Y direction --
+
+ This version does the final y-stretch by "tricking" BltRaster into
+ spacing scan lines out by N lines. Thus it only takes N calls to
+ BltRaster, and is quite fast, especially for low magnifications.
+ The resulting updates to the screen have a ragged appearance
+ however, since the changes occur to every Nth scan line on each
+ blit.
+
+*/
+
+#else
+
+SHORT dbgmgb = NO;
+
+short MagBits(sbm,sbox,dbm,dx,dy,NX,NY,clip)
+ struct BitMap *sbm, *dbm;
+ Box *sbox;
+ int dx,dy; /* upper left corner in dbm */
+ int NX,NY; /* magnify factor */
+ Box *clip; /* clip box in destination bm */
+ {
+
+ SHORT xs,xd,yd,ys,sxmax,i,nout,lx,clymax, depth;
+ SHORT svbpr,magbpr,magyd,pixper,magpixper,magydcl,shcl,ydbot;
+ static SHORT dw;
+ static Box c,fr;
+ struct BitMap tmpBM,tmpBM2;
+
+
+ depth = dbm->Depth;
+
+ /* clip in source bitmap to avoid unnecessary work */
+
+ fr.x = (clip->x - dx)/NX + sbox->x;
+ fr.y = (clip->y - dy)/NY + sbox->y;
+ fr.w = (clip->w + NX - 1)/NX;
+ fr.h = (clip->h + NY - 1)/NY;
+
+ if (!BoxAnd(&c,&fr,sbox)) return(0);
+
+ dx += NX*(c.x - sbox->x);
+ dy += NY*(c.y - sbox->y);
+ dw = c.w*NX;
+
+ if ( (NX==1)&&(NY==1)) { BltBitMap(sbm,c.x,c.y,dbm,dx,dy,c.w,c.h,REPOP,0xff,NULL); return(0); }
+
+ tmpBM.Planes[0] = tmpBM2.Planes[0] = 0;
+
+ InitBitMap(&tmpBM,depth,dw,c.h);
+ InitBitMap(&tmpBM2,depth,dw,c.h);
+
+ if (TmpAllocBitMap(&tmpBM)) return(-1);
+ if (TmpAllocBitMap(&tmpBM2)) {FreeBitMap(&tmpBM); return(-1);}
+
+ ClearBitMap(&tmpBM); ClearBitMap(&tmpBM2);
+
+ /*--------- stretch horizontally first--------------*/
+ sxmax = c.x + c.w;
+ xd = 0;
+ for (xs = c.x; xs < sxmax; xs++ ) {
+ BltBitMap(sbm,xs,c.y,&tmpBM,xd,0,1,c.h,REPOP,0xff,NULL);
+ xd += NX;
+ }
+ for (i=0; i<NX; i++)
+ BltBitMap(&tmpBM,0,0,&tmpBM2,i,0,dw-NX+1,c.h,OROP,0xff,NULL);
+
+
+ /*--------- prepare to stretch Vertically--------------*/
+ lx = 0;
+ if ( (nout = clip->x - dx) >0) { lx += nout; dx+=nout; dw -= nout; }
+ if ( (nout = dx+dw - (clip->x+clip->w)) > 0) { dw -= nout; }
+ yd = dy;
+ clymax = clip->y + clip->h;
+
+ /*---- mess around with width of dbm to trick BltBitMap----- */
+
+ svbpr = dbm->BytesPerRow;
+ magbpr = svbpr*NY;
+ dbm->BytesPerRow = magbpr; /* Make it skip N lines at a time
+ by saying the destination bitmap is NY times as wide
+ as it really is */
+
+ yd = dy;
+ magyd = (yd>=0) ? yd/NY : yd/NY - 1;
+ pixper = 8*svbpr;
+ magpixper = 8*magbpr;
+ dx += pixper*(yd - magyd*NY);
+ ydbot = yd + NY*(c.h-1);
+
+#ifdef asdas
+ if (dbgmgb) printf("NY=%ld,yd=%ld,magyd=%ld,dx=%ld,svbpr=%ld\n",
+ NY,yd,magyd,dx,svbpr);
+#endif
+
+ /**--------- Stretch vertically into destination Raster Port ***/
+ for (i = 0; i < NY; i++) {
+ magydcl = magyd; shcl = c.h; ys = 0;
+ if (yd < clip->y) { magydcl++; shcl--; ys++; }
+ if (ydbot >= clymax) shcl--;
+ BltBitMap(&tmpBM2,lx,ys,dbm,dx,magydcl, dw,shcl,REPOP,0xff,NULL);
+ dx += pixper;
+ if (dx>magpixper) { dx -= magpixper; ++magyd; }
+ ++yd;
+ ++ydbot;
+ }
+
+ dbm->BytesPerRow = svbpr;
+ FreeBitMap(&tmpBM);
+ FreeBitMap(&tmpBM2);
+ return(0);
+ }
+
+#endif
+
diff --git a/MAGOPS.C b/MAGOPS.C
new file mode 100644
index 0000000..2159997
--- /dev/null
+++ b/MAGOPS.C
@@ -0,0 +1,140 @@
+/*----------------------------------------------------------------------*/
+/* */
+/* magops.c -- this is essentially an extension to cgraph */
+/* which implements the graphics ops in magnified windows. */
+/* */
+/*----------------------------------------------------------------------*/
+
+#include <system.h>
+#include <prism.h>
+
+#define local static
+
+extern SHORT curxpc;
+extern BMOB *curob;
+extern Box bigBox;
+extern struct RastPort *curRP;
+extern BOOL usePen;
+extern void (*CurPWritePix)();
+extern SHORT xorg,yorg,magN;
+extern BOOL firstDown;
+extern SHORT clipMaxX;
+
+Box bx;
+
+mReadPix(x,y) SHORT x,y; { return(PReadPix(x+xorg,y+yorg)); }
+
+/*------------ Paint current object------------*/
+
+dispob(x,y) SHORT x,y; { DispBMOB(curob,x,y); }
+
+ProcHandle SplatOp() {
+ return((usePen==0)? CurPWritePix: &dispob);
+ }
+
+UpdtPtBox(x,y) SHORT x,y; { UpdtSibs(MakeBox(&bx,x,y,1,1)); }
+
+mDispOB(x,y) SHORT x,y; {
+ (*SplatOp())(x+xorg,y+yorg);
+ UpdtPtBox(x,y);
+ }
+
+mDrawDot(x,y) { (*CurPWritePix)(x+xorg,y+yorg); UpdtPtBox(x,y); }
+
+mMoveOB(x,y) SHORT x,y; {
+ SHORT oldx,oldy;
+ oldx = curob->pict.box.x - xorg + curob->xoffs;
+ oldy = curob->pict.box.y - yorg + curob->yoffs;
+ MoveBMOB(curob, x+xorg, y+yorg); /*go to screen directly*/
+ UpdtSibs(BoxTwoPts(&bx,x,y,oldx,oldy));
+ }
+
+mClearOB() {
+ SHORT oldx,oldy;
+ oldx = curob->pict.box.x - xorg + curob->xoffs;
+ oldy = curob->pict.box.y - yorg + curob->yoffs;
+ ClearBMOB(curob);
+ UpdtPtBox(oldx,oldy);
+ }
+
+/*---------------magnified Line ------------*/
+mLine(x1,y1,x2,y2) SHORT x1,y1,x2,y2; {
+ firstDown = YES;
+ if (usePen==0) PLine(x1+xorg, y1+yorg, x2+xorg, y2+yorg);
+ else PLineWith(x1+xorg,y1+yorg, x2+xorg, y2 +yorg, SplatOp());
+ UpdtSibs(BoxTwoPts(&bx,x1,y1,x2,y2));
+ }
+
+/* --------------magnified Rectangle -----------*/
+mRect(b) Box *b; {
+ PFillBox(MakeBox(&bx,b->x+xorg, b->y+yorg,b->w,b->h));
+ UpdtSibs(b);
+ }
+
+/*---------------magnified Curve ------------*/
+mCurve(x0,y0,x1,y1,x2,y2) SHORT x0,y0,x1,y1,x2,y2; {
+ firstDown = YES;
+ PCurve(x0+xorg,y0+yorg,x1+xorg,y1+yorg,x2+xorg,y2+yorg,64,SplatOp());
+ UpdtSibs(BoxThreePts(&bx,x0,y0,x1,y1,x2,y2));
+ }
+
+local OvalUpdt(x,y,a,b) SHORT x,y,a,b; {
+ UpdtSibs(MakeBox(&bx,x-a,y-b,2*a+4,2*b+4));
+ }
+
+/*---------------magnified Circle ------------*/
+mCircle(x,y,rad) SHORT x,y,rad; {
+ firstDown = YES;
+ PCircWith(x + xorg, y + yorg, rad, SplatOp());
+ OvalUpdt(x,y,rad,rad);
+ }
+
+mFillCircle(x,y,rad) SHORT x,y,rad; {
+ PFillCirc(x + xorg, y + yorg ,rad);
+ OvalUpdt(x,y,rad,rad);
+ }
+
+iabs(x) int x; { return( (x>0)? x: -x ); }
+
+/*---------------magnified Ellipse ------------*/
+mOval(x1,y1,x2,y2) SHORT x1,y1,x2,y2; {
+ SHORT halfw,halfh;
+ firstDown = YES;
+ halfw = iabs(x2-x1); halfh = iabs(y2-y1);
+ PEllpsWith(x1 +xorg, y1 + yorg, halfw, halfh, SplatOp());
+ OvalUpdt(x1,y1,halfw,halfh);
+ }
+
+mFillOval(x1,y1,x2,y2) SHORT x1,y1,x2,y2; {
+ SHORT halfw,halfh;
+ halfw = iabs(x2-x1); halfh = iabs(y2-y1);
+ PFillEllps(x1 +xorg, y1 + yorg, halfw, halfh);
+ OvalUpdt(x1,y1,halfw,halfh);
+ }
+
+/*---------------Magnified Area Flood ------------*/
+mFillArea(Bndry,x,y) BOOL Bndry;SHORT x,y; {
+ UpdtON();
+ if (Bndry) PFloodBndry(x+xorg,y+yorg); else PFloodArea(x+xorg,y+yorg);
+ UpdtSibs(&bigBox);
+ UpdtOFF();
+ }
+
+/* Frame rectangle with border of thickness 1 */
+mFrame(b) Box *b; {
+ firstDown = YES;
+ MakeBox(&bx,b->x + xorg,b->y + yorg,b->w,b->h);
+ PThinFrame(&bx);
+ UpdtSibs(b);
+ }
+
+/* Frame rectangle with border using current brush */
+mOBFrame(b) Box *b; {
+ SHORT xm = b->x + b->w -1;
+ SHORT ym = b->y + b->h -1;
+ mLine(b->x, b->y, xm, b->y);
+ mLine(xm, b->y, xm, ym);
+ mLine(xm, ym, b->x, ym);
+ mLine(b->x,ym, b->x, b->y);
+ }
+
diff --git a/MAGWIN.C b/MAGWIN.C
new file mode 100644
index 0000000..ba10f63
--- /dev/null
+++ b/MAGWIN.C
@@ -0,0 +1,215 @@
+/*----------------------------------------------------------------------*/
+/* magwin.c -- implements a magnify window object */
+/*----------------------------------------------------------------------*/
+#include <system.h>
+#include <prism.h>
+
+extern Pane mainP;
+extern SHORT curpen,curxpc;
+extern BMOB *curob;
+extern struct BitMap hidbm;
+extern Box bigBox;
+extern SHORT xShft,yShft;
+extern SHORT xcen,ycen;
+extern void PWritePix();
+extern Box screenBox;
+extern struct RastPort *mainRP,*curRP,tempRP;
+extern Box clipBox,bigBox;
+extern SHORT curIMFlags;
+extern SHORT usePen;
+
+#define local static;
+
+SHORT xorg=0, yorg=0;
+/* This Boolean tells whether we are actually painting or just showing
+feedback while the user adjusts the graphic */
+BOOL Painting =NO;
+
+
+SHORT curWin = MAINWIN; /* = MAGWIN or MAINWIN */
+
+short magN = 1;
+
+/*----------------------------------------------------------------------*/
+/*----------------------------------------------------------------------
+All coordinates passed to the routines mLine, etc are backing bitmap
+relative (bbmX, bbmY). To get view relative coordinates
+ srcX = bbmX - srcPos.x;
+ srcY = bbmY - srcPos.y;
+
+To get screen coordinates:
+ screenX = bbmX + xorg;
+ screenY = bbmY + yorg;
+
+Where
+ xorg = srcBox.x - srcPos.x;
+ yorg = srcBox.y - srcPos.y;
+
+The backing bitmap is not necessary: it is used for implementing
+scrolling and undo in the main painting window. In the case of using
+the magnifier to edit a tile pattern, the updtBackBM() call could
+display an array of NxM tiles.
+----------------------------------------------------------------------*/
+
+#ifdef floofloo
+/*----------------------------------------------------------------------*/
+/* magnify Context */
+/*----------------------------------------------------------------------*/
+typedef struct {
+SHORT magN; /* magnification factor */
+struct RastPort *srcRP; /* The source RasterPort */
+Box *srcBox; /* The clip box of source in its Raster */
+Point srcPos; /* The position of the view box relative*/
+ /* to the backing bitmap */
+struct BitMap *magBM; /* The magnify BitMap */
+Box *magBox; /* Clip Box of magnify view in magBM. */
+Point magPos; /* The position of magnify view rel */
+ /* to backing bitmap */
+void (*updtProc)(); /* Procedure to call to update the */
+ /* backing bitmap. (takes *Box as */
+ /* parameter, BBM relative); */
+} MagContext;
+/*----------------------------------------------------------------------*/
+#endif
+
+BOOL magShowing = NO;
+MagContext *mgc = NULL;
+
+MagErr(s) char *s; { KPrintF(" Null magcontext in %s \n",s); }
+
+UpdtCach() {
+ if (mgc == NULL) MagErr("UpdtCache");
+ FixUsePen();
+ xorg = mgc->srcBox->x - mgc->srcPos.x;
+ yorg = mgc->srcBox->y - mgc->srcPos.y;
+ PopGrDest();
+ PushGrDest(mgc->srcRP,mgc->srcBox);
+ }
+
+
+UpdtOFF() { Painting = NO; UpdtCach(); }
+UpdtON() { Painting = YES; UpdtCach(); }
+
+static void noop(){}
+ProcHandle curUpdt = &noop;
+
+/*----------------------------------------------------------------------*/
+/* Plug in a new Magnify context */
+/*----------------------------------------------------------------------*/
+void SetMagContext(magc) MagContext *magc; {
+ mgc = magc;
+ magN = mgc->magN;
+ curUpdt = magc->updtProc;
+ if (curUpdt==NULL) curUpdt = &noop;
+ UpdtOFF();
+ }
+
+SetMag(nmag) SHORT nmag; {
+ mgc->magN = magN = nmag;
+ }
+
+MagState(onoff) BOOL onoff; {
+ if (mgc == NULL) MagErr("Magstate");
+ magShowing = onoff;
+ }
+
+UnMag(z) SHORT z; { return (( z + magN - 1)/magN); }
+
+/*----------- Box "b" is in Backing Bitmap coords ---------------------*/
+
+void MagUpdate(b) Box *b; {
+ Box sbox;
+ SHORT dx,dy,pix;
+ if (!magShowing) return;
+ sbox.x = b->x + xorg; sbox.y = b->y + yorg;
+ sbox.w = b->w; sbox.h = b->h;
+ dx = (b->x - mgc->magPos.x) * magN + mgc->magBox->x;
+ dy = (b->y - mgc->magPos.y) * magN + mgc->magBox->y;
+
+/* this does give a fair speedup, and costs about 240 Bytes */
+
+ if ((sbox.w == 1) && (sbox.h==1)) { /* special speedup for dots */
+ pix = ReadPixel(mgc->srcRP, sbox.x,sbox.y);
+ tempRP.BitMap = mgc->magBM;
+ SetAPen(&tempRP,pix);
+ PushGrDest(&tempRP, mgc->magBox);
+ PFillBox(MakeBox(&sbox,dx,dy,magN,magN));
+ PopGrDest();
+ return;
+ }
+
+ MagBits(
+ mgc->srcRP->BitMap, /* source bitmap */
+ &sbox, /* box on screen in unMagnified source window*/
+ mgc->magBM, /* bitmap containing mag window */
+ dx, /* position of the magnified version of */
+ dy, /* sbox in mag bitmap */
+ magN,magN, /* amount of magnification */
+ mgc->magBox /* clipping box of the Mag window */
+ );
+ }
+
+/*------- b is in Physical coords, in the screen bitmap----*/
+UpdtSibs(b) Box *b; {
+ Box updtBox;
+ updtBox = *b;
+ if ((usePen!=0)&& ((curIMFlags&NOBR)==0)) {
+ updtBox.x -= curob->xoffs;
+ updtBox.y -= curob->yoffs;
+ updtBox.w += curob->pict.box.w-1;
+ updtBox.h += curob->pict.box.h-1;
+ }
+ if (magShowing) MagUpdate(&updtBox);
+ (*curUpdt)(&updtBox);
+ }
+
+/* clip a point to the CurrentBBM box */
+SHORT limit(a,l,u,d) SHORT a,l,u,d; { if (a<l) a+=d; if (a>u) a-=d;
+ return(a); }
+
+/* not yet implemented
+MWClipPt(x,y,dx,dy) SHORT *x,*y,dx,dy; {
+ Box *bx = &screenBox;
+ *x = limit(*x,0,bx->w-1,dx);
+ *y = limit(*y,0,bx->h-1,dy);
+ }
+*/
+
+SetCurWin(pn) Pane *pn; { curWin = pn->client; }
+
+/* convert window rel coords to bbm-rel magnified coords */
+MagCoords(x,y) SHORT *x,*y; {
+ if (curWin == MAGWIN) {
+ *x = mgc->magPos.x + (*x)/magN;
+ *y = mgc->magPos.y + (*y)/magN;
+ }
+ else { *x += mgc->srcPos.x; *y += mgc->srcPos.y; }
+ }
+
+#define BIG 4000
+magRect(b) Box *b; {
+ Box c,d;
+ c.x = (b->x - mgc->magPos.x) * magN + mgc->magBox->x;
+ c.y = (b->y - mgc->magPos.y) * magN + mgc->magBox->y;
+ c.w = magN * b->w;
+ c.h = magN * b->h;
+ BoxAnd(&d,mgc->magBox,&c);
+ c = clipBox;
+ SetClipBox(&bigBox);
+ PFillBox(&d);
+ SetClipBox(&c);
+ }
+
+minvXHair(x,y) SHORT x,y; {
+ Box bx;
+ WaitTOF();
+ if (curWin == MAINWIN) PInvertXHair(x + xorg, y + yorg);
+ else {
+ TempXOR();
+ magRect(MakeBox(&bx,0,y,screenBox.w,1));
+ magRect(MakeBox(&bx,x,0,1,screenBox.h));
+ RestoreMode();
+ }
+ }
+
+
diff --git a/MAINMAG.C b/MAINMAG.C
new file mode 100644
index 0000000..e6fa58b
--- /dev/null
+++ b/MAINMAG.C
@@ -0,0 +1,450 @@
+/*----------------------------------------------------------------------*/
+/* Main magnify window */
+/*----------------------------------------------------------------------*/
+
+#include <system.h>
+#include <prism.h>
+#include <pnts.h>
+
+extern PointRec pnts; /* contains mx,my,sx,sy, etc */
+
+extern void (*thisMode)(), (*nop)(), (*killMode)();
+extern struct Window *mainW;
+extern Box bigBox,screenBox;
+extern struct RastPort tempRP, *mainRP, tempRP, *curRP,screenRP;
+extern struct BitMap hidbm;
+extern Pane mainP;
+extern SHORT xorg,yorg,curMBarH,curxpc;
+extern void mainCproc(), mainMproc();
+extern Box mainBox;
+extern SHORT xShft;
+extern SHORT checkpat[];
+extern struct Screen *screen;
+extern BOOL wasCtrl;
+extern BOOL Painting;
+extern PaintMode paintMode;
+
+BOOL isUndoOn = NO;
+UndoOn() { isUndoOn = YES; }
+UndoOff() { isUndoOn = NO; }
+
+MagContext magCntxt = {0};
+Pane magP = {0};
+BOOL magOn = NO;
+BOOL updatePending; /* have changed the screen but not copied to hidbm yet */
+Box chgB = {0};
+Box tmpChgBox = {0};
+
+SHORT didClearCol;
+
+/* clips a change box against the non-magnified window */
+/* this is done in backing bitmap coords */
+ClipChgBox(clip,chgbx) {
+ Box b;
+ b.x = magCntxt.srcPos.x; b.y = magCntxt.srcPos.y;
+ b.w = magCntxt.srcBox->w; b.h = magCntxt.srcBox->h;
+ return(BoxAnd(clip,chgbx,&b));
+ }
+
+/* records changes so UndoSave knows how big a rectangle to save */
+
+void RecChange(b) Box *b; {
+ EncloseBox(Painting ? & chgB: &tmpChgBox,b);
+ updatePending = YES;
+ }
+
+void RecTempChg(b) Box *b; { EncloseBox(&tmpChgBox,b); }
+
+CopyBack(b,op) Box *b; SHORT op; {
+ tempRP.BitMap = &hidbm;
+ ClipBlit(mainRP, b->x +xorg, b->y + yorg,
+ &tempRP, b->x, b->y, b->w, b->h, op);
+ }
+
+CopyFwd(b,op) Box *b; SHORT op; {
+ tempRP.BitMap = &hidbm;
+ ClipBlit( &tempRP, b->x, b->y,
+ mainRP,b->x +xorg, b->y + yorg, b->w, b->h, op);
+ }
+
+/* make previous change permanent */
+SHORT didType = DIDNothing;
+
+#ifdef hobaaaho
+UndoSave() {
+ Box cb;
+ if (didClear) {
+ tempRP.BitMap = &hidbm; SetRast(&tempRP,didClearCol);
+ didClear = NO;
+ }
+ else if (didMerge) MrgSpareUpdt();
+ if (ClipChgBox(&cb,&chgB)) CopyBack(&cb,REPOP); chgB.w = 0;
+ }
+#endif
+
+/* this should be called "MakeChangePermanent" */
+/* it copies changed area from the screen to the hidbm */
+UndoSave() {
+ Box cb;
+ ClearFB();
+ switch(didType) {
+ case DIDClear:
+ tempRP.BitMap = &hidbm; SetRast(&tempRP,didClearCol);
+ break;
+ case DIDMerge: MrgSpareUpdt(); break;
+ }
+ if (ClipChgBox(&cb,&chgB)) CopyBack(&cb,REPOP); chgB.w = 0;
+ didType = DIDNothing;
+ updatePending = NO;
+ }
+
+/* swap hidden bitmap and screen in chgB */
+SwapHidScr() {
+ Box cb;
+ if (ClipChgBox(&cb,&chgB)) {
+ CopyFwd(&cb,XOROP);
+ CopyBack(&cb,XOROP);
+ CopyFwd(&cb,XOROP);
+ MagUpdate(&chgB);
+ }
+ }
+
+Undo() {
+ switch(didType) {
+ case DIDClear: case DIDMerge: UpdtDisplay(); didType = DIDNothing; break;
+ case DIDHPoly: SwapHidScr(); UndoHPoly(); didType = DIDNothing; break;
+ case DIDNothing: SwapHidScr(); break;
+ }
+ }
+
+/* this is called when operations are aborted in midstream */
+UnDisplay() { UpdtDisplay(); UndoSave(); }
+
+EraseBox(b) Box *b; {
+ Box clb;
+ if (ClipChgBox(&clb,b)) { CopyFwd(&clb,REPOP); MagUpdate(&clb);}
+ }
+
+/* this erases feedback from the screen */
+EraseTempChg() {
+ if (wasCtrl) { EncloseBox(&chgB, &tmpChgBox);
+ CycPaint(); /* A cheap effect... */
+ }
+ else EraseBox(&tmpChgBox);
+ tmpChgBox.w = 0;
+ }
+
+/**-------------------------- **/
+
+#define BIG 1000;
+
+
+void magPaint() {
+ Box sbx;
+ if (magOn) {
+ sbx.x = magCntxt.magPos.x;
+ sbx.y = magCntxt.magPos.y;
+ sbx.w = sbx.h = BIG;
+ MagBits(&hidbm, &sbx, mainRP->BitMap,magP.box.x, magP.box.y,
+ magCntxt.magN, magCntxt.magN, &magP.box);
+ }
+ }
+
+mClearToBg() {
+ UndoSave();
+ TempErase();
+ PFillBox(&screenBox);
+ ClearErase();
+ didType = DIDClear;
+ didClearCol = curxpc;
+ MagUpdate(&screenBox);
+ }
+
+#define DivWidth 6
+PaintDivider() {
+ Box dbox;
+ if (magOn) {
+ dbox.x = mainBox.w/3;
+ dbox.y = mainBox.y;
+ dbox.w = DivWidth;
+ dbox.h = mainBox.h;
+
+ PushGrDest(&screenRP,&screenBox);
+ PPatternBox(&dbox, checkpat, 1, 0, 0);
+ PopGrDest();
+ }
+ }
+
+
+void magRefresh() { magPaint(); PaintDivider(); }
+
+void mainRefresh() {
+ tempRP.BitMap = &hidbm;
+ ClipBlit(&tempRP,magCntxt.srcPos.x,magCntxt.srcPos.y,
+ mainRP, mainP.box.x, mainP.box.y, mainP.box.w, mainP.box.h, REPOP);
+ }
+
+UpdtDisplay() {ClearFB(); mainRefresh(); magPaint(); }
+
+
+#ifdef THEIRWAY /*---------------------------------*/
+MoveWinTo(win,x,y) struct Window *win; int x,y; {
+ MoveWindow(win, x - win->LeftEdge, y - win->TopEdge);
+ }
+
+SizeWinTo(win,w,h) struct Window *win; int w,h; {
+ SizeWindow(win, w - win->Width, h - win->Height);
+ }
+
+SizeAndMove(win,b) struct Window *win; Box *b; {
+ if (win->Height != b->h) {
+ if (b->h > win->Height) { /* getting higher: move first */
+ MoveWinTo(win, win->LeftEdge, b->y);
+ SizeWinTo(win, win->Height, b->h);
+ }
+ else {
+ SizeWinTo(win, win->Height, b->h);
+ MoveWinTo(win, win->LeftEdge, b->y);
+ }
+ }
+ if (win->Width != b->w)
+ {
+ if (b->w > win->Width) { /* getting wider:move first */
+ MoveWinTo(win, b->x, win->TopEdge);
+ SizeWinTo(win, b->w, win->Height);
+ }
+ else {
+ SizeWinTo(win, b->w, win->Height);
+ MoveWinTo(win, b->x, win->TopEdge);
+ }
+ }
+ }
+
+#endif /* ------------------------------------------ */
+
+ResizeWins() {
+ SHORT magx;
+ Box mbox;
+ mbox = mainBox;
+ mbox.w = (magOn)? mainBox.w/3: mainBox.w;
+
+#ifdef THEIRWAY
+ SizeAndMove(mainW,&mbox);
+ KPrintF(" After SizeAndMOve mainW = %ld, %ld, %ld, %ld\n",
+ mainW->LeftEdge,mainW->TopEdge,mainW->Width, mainW->Height);
+#endif
+
+ PaneSize(&mainP, mainBox.x, mainBox.y, mbox.w, mainBox.h);
+ magx = mbox.w + DivWidth;
+ PaneSize(&magP, magx, mainBox.y, mainBox.w - magx, mainBox.h);
+ }
+
+MagCnst(b,p) Box *b; Point *p; {
+ Box c;
+ c.x = p->x; c.y = p->y;
+ c.w = b->w; c.h = b->h;
+ BoxBeInside(&c,&screenBox);
+ p->x = c.x; p->y = c.y;
+ b->w = c.w; b->h = c.h;
+ }
+
+/* make sure that the magnified portion of the bitmap is visible in
+ the main window */
+
+BOOL FixMag() {
+ SHORT nout;
+ Box mf;
+ BOOL srcChg = NO;
+ /* first make sure mag and src views are inside the hidbm*/
+ MagCnst(magCntxt.srcBox,&magCntxt.srcPos);
+ if (magOn) {
+ mf.x = magCntxt.magPos.x;
+ mf.y = magCntxt.magPos.y;
+ mf.w = UnMag(magCntxt.magBox->w);
+ mf.h = UnMag(magCntxt.magBox->h);
+
+ BoxBeInside(&mf,&screenBox);
+ magCntxt.magPos.x = mf.x;
+ magCntxt.magPos.y = mf.y;
+
+ if (magCntxt.magPos.x < magCntxt.srcPos.x)
+ { srcChg = YES; magCntxt.srcPos.x = magCntxt.magPos.x; }
+
+ if (magCntxt.magPos.y < magCntxt.srcPos.y)
+ { srcChg = YES; magCntxt.srcPos.y = magCntxt.magPos.y; }
+
+ nout = (mf.x + mf.w) - (magCntxt.srcPos.x + magCntxt.srcBox->w);
+ if (nout>0) { srcChg = YES; magCntxt.srcPos.x += nout; }
+
+ nout = (mf.y + mf.h) - (magCntxt.srcPos.y + magCntxt.srcBox->h);
+ if (nout>0) { srcChg = YES; magCntxt.srcPos.y += nout; }
+
+ }
+ UpdtCach();
+ return(srcChg);
+ }
+
+FixMagAndPaint(p) Pane *p; {
+ BOOL srcChg = FixMag();
+ if (p == &magP) { magPaint(); if (srcChg) mainRefresh(); }
+ else mainRefresh();
+ }
+
+Point svSrcPos;
+
+CenterPoint(x,y) SHORT x,y; {
+ UndoSave();
+ /*------- center mag box at x,y----*/
+ magCntxt.magPos.x = x - ( UnMag(magP.box.w) >> 1);
+ magCntxt.magPos.y = y - ( UnMag(magP.box.h) >> 1);
+
+ /* -- and try to center main box at x,y--- */
+ magCntxt.srcPos.x = x - magCntxt.srcBox->w/2;
+ magCntxt.srcPos.y = y - magCntxt.srcBox->h/2;
+
+ MagState(YES);
+ FixMag();
+
+ UpdtDisplay();
+ }
+
+ShowMag(x,y) SHORT x,y; {
+ if (!magOn) {
+ UndoSave();
+ svSrcPos = magCntxt.srcPos;
+ magOn = YES;
+ ResizeWins();
+ PaneInstall(&magP);
+ PaintDivider();
+ }
+ CenterPoint(x,y);
+ }
+
+void RemoveMag() {
+ if (!magOn) return;
+ UndoSave();
+ magOn = NO;
+ PaneRemove(&magP);
+ ResizeWins();
+ MagState(NO);
+ magCntxt.srcPos = svSrcPos;
+ FixMag();
+ PaneRefresh(&bigBox);
+ UpdtCach();
+ }
+
+ToggleMag() {if (magOn) RemoveMag(); else ShowMag(mx,my); }
+
+BOOL titleShowing = YES;
+static BOOL titleWasUp = YES;
+BOOL skipRefresh = NO;
+RepaintEverything() {
+ ResizeWins();
+ FixMag();
+ PaneRefresh(&bigBox);
+ skipRefresh = YES;
+ UpdtCach();
+ DispPntMode();
+/* DispDPaint(); */
+ }
+
+FixTitle() {
+ ShowTitle(screen,titleShowing);
+ if (titleShowing) {
+ mainBox.y = curMBarH;
+ mainBox.h = screenBox.h - curMBarH;
+ magCntxt.srcPos.y += curMBarH;
+ }
+ else {
+ mainBox.y = 0;
+ mainBox.h = screenBox.h;
+ magCntxt.srcPos.y -= curMBarH;
+ }
+ }
+
+TogTitle() {
+ titleWasUp = titleShowing = !titleShowing;
+ UndoSave();
+ FixTitle();
+ RepaintEverything();
+ }
+
+extern SHORT cpWidth;
+extern BOOL cpShowing;
+TogBoth() {
+ cpShowing = !cpShowing;
+ UndoSave();
+ if (cpShowing) {
+ titleShowing = titleWasUp;
+ mainBox.w -= cpWidth;
+ InstCP();
+ }
+ else {
+ titleWasUp = titleShowing;
+ titleShowing = NO;
+ RmvCP();
+ mainBox.w += cpWidth;
+ }
+ FixTitle();
+ RepaintEverything();
+ }
+
+/* scroll window: dx and dy are the amount the contents of the window
+will slide to the right and down respectively */
+MWScroll(p,dx,dy) Pane *p; SHORT dx,dy; {
+ UndoSave();
+ if (p == &mainP ) {
+ magCntxt.srcPos.x -= dx;
+ magCntxt.srcPos.y -= dy;
+ }
+ else if ( p == &magP) {
+ magCntxt.magPos.x -=dx;
+ magCntxt.magPos.y -=dy;
+ }
+ FixMagAndPaint(p);
+ }
+
+/* Zoom window: */
+void MWZoom(dmag) SHORT dmag;
+ {
+ SHORT x,y;
+ SHORT newmag = magCntxt.magN + dmag;
+ newmag = MAX(2,newmag);
+ if (newmag>24) return;
+ UndoSave();
+ x = magCntxt.magPos.x + UnMag(magCntxt.magBox->w)/2;
+ y = magCntxt.magPos.y + UnMag(magCntxt.magBox->h)/2;
+ SetMag(newmag);
+ magCntxt.magPos.x = x - UnMag(magCntxt.magBox->w)/2;
+ magCntxt.magPos.y = y - UnMag(magCntxt.magBox->h)/2;
+ FixMag();
+ UpdtDisplay();
+ }
+
+
+/**-----(From Menu) Specify Magnify Window Position */
+
+static SHORT mgw,mgh;
+
+domag() { UpdtOFF(); ShowMag(mx,my); }
+
+void killMag() { CPInvAct(magAct); }
+xmagbox() {
+ Box bx;
+ TempXOR();
+ mFrame(MakeBox(&bx,mx-mgw/2,my-mgh/2,mgw,mgh));
+ RestoreMode();
+ }
+
+void IMMagSpec() {
+ mgw = UnMag(2*mainBox.w/3);
+ mgh = UnMag(mainBox.h);
+ killMode = killMag;
+ IModeProcs(&xmagbox,nop,&xmagbox,nop,&xmagbox,nop,&xmagbox,&domag);
+ }
+
+ToglMagw(){
+ CPInvAct(magAct);
+ if (magOn) RemoveMag(); else NewIMode(IM_magSpec);
+ }
+
diff --git a/MAKEICON.C b/MAKEICON.C
new file mode 100644
index 0000000..22e1e1b
--- /dev/null
+++ b/MAKEICON.C
@@ -0,0 +1,236 @@
+/****************************************************************************/
+/* */
+/* FILENAME: makeicon.c */
+/* */
+/* FUNCTION: Project Icon Routines */
+/* */
+/* REVISION: tomc */
+/* REVISION: dans -- modified for DPaint -- 11/16/85 */
+/* */
+/****************************************************************************/
+#include <system.h>
+
+/****************************************************************************/
+/* */
+/* This stuff modified from "workbenc.h" because of compiling problems such */
+/* as enum and bit fields. */
+/* */
+/****************************************************************************/
+#define WB_DISKMAGIC 0xE310
+#define WB_DISKVERSION 1
+#define WBPROJECT 0x0400
+#define NO_ICON_POSITION (0x80000000)
+#define GADGBACKFILL 0x0001
+
+struct DiskObject
+ {
+ UWORD do_Magic; /* a magic number at the start of the file */
+ UWORD do_Version; /* a version number, so we can change it */
+ struct Gadget do_Gadget; /* a copy of in core gadget */
+ UWORD do_Type; /* enum WBObjectType */
+ char *do_DefaultTool;
+ char **do_ToolTypes;
+ LONG do_CurrentX;
+ LONG do_CurrentY;
+ APTR do_DrawerData; /* struct DrawerData * */
+ char *do_ToolWindow; /* only applies to tools */
+ LONG do_StackSize; /* only applies to tools */
+ };
+
+/****************************************************************************/
+/* */
+/* All the data needed for ProjectIcon */
+/* */
+/****************************************************************************/
+#define PROJECT_WIDTH 58
+#define PROJECT_HEIGHT 20
+#define PROJECT_DEPTH 2
+
+/* Bitmap name = picicon, Amiga-BOB format. */
+/* Width = 58, Height = 20 */
+
+short picicon0[80] = {
+ 0x0, 0x0, 0x0, 0x0,
+ 0x7FFF, 0xFFFF, 0xFFFF, 0xFF80,
+ 0x6000, 0x0, 0x0, 0x180,
+ 0x6000, 0x7FF, 0xFFFF, 0x8180,
+ 0x6000, 0x401F, 0xFFC0, 0x180,
+ 0x6002, 0xE000, 0x0, 0x180,
+ 0x6003, 0x6002, 0x8, 0x180,
+ 0x600B, 0xF807, 0x5E, 0x180,
+ 0x6001, 0xFC03, 0x809F, 0x8180,
+ 0x6000, 0xE07, 0xC2FF, 0xE180,
+ 0x600D, 0xAF05, 0xE017, 0xF980,
+ 0x6021, 0x2F83, 0xC057, 0xF980,
+ 0x6025, 0xFF1F, 0x24C7, 0xF980,
+ 0x6097, 0xFA6E, 0x881F, 0xF980,
+ 0x601E, 0xFCEC, 0x3B5B, 0xF980,
+ 0x6055, 0xFFBA, 0x559F, 0xF980,
+ 0x60EF, 0xFFFF, 0xFFFF, 0xF980,
+ 0x6000, 0x0, 0x0, 0x180,
+ 0x7FFF, 0xFFFF, 0xFFFF, 0xFF80,
+ 0x0, 0x0, 0x0, 0x0
+ };
+short picicon1[80] = {
+ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFC0,
+ 0x8000, 0x0, 0x0, 0x40,
+ 0x9FFF, 0xFFFF, 0xFFFF, 0xFE40,
+ 0x9800, 0x0, 0x0, 0x640,
+ 0x9800, 0x0, 0x0, 0x640,
+ 0x9801, 0x0, 0x0, 0x640,
+ 0x9804, 0x8004, 0x0, 0x640,
+ 0x9804, 0x8008, 0x20, 0x640,
+ 0x981F, 0xC0C, 0x160, 0x640,
+ 0x983F, 0xFE1F, 0x8D00, 0x640,
+ 0x98FF, 0xFF7F, 0xDFE8, 0x640,
+ 0x9BFF, 0xFFFF, 0xFFFF, 0x640,
+ 0x9FFF, 0xFFFF, 0xFFFF, 0x8640,
+ 0x9FFF, 0xFFFF, 0xFFFF, 0xFE40,
+ 0x9FFF, 0xFFFF, 0xFFFF, 0xFE40,
+ 0x9FFF, 0xFFFF, 0xFFFF, 0xFE40,
+ 0x9FFF, 0xFFFF, 0xFFFF, 0xFE40,
+ 0x9FFF, 0xFFFF, 0xFFFF, 0xFE40,
+ 0x8000, 0x0, 0x0, 0x40,
+ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFC0
+ };
+
+
+
+
+static struct Image projectImage=
+ {
+ 0,0,
+ PROJECT_WIDTH,PROJECT_HEIGHT,
+ PROJECT_DEPTH,
+ (USHORT *)&picicon0[0],
+ 3,0,
+ NULL
+ };
+
+static struct Gadget projectGadget=
+ {
+ NULL,
+ 0,0,
+ PROJECT_WIDTH,PROJECT_HEIGHT,
+ GADGIMAGE | GADGHCOMP,
+ RELVERIFY | GADGIMMEDIATE,
+ BOOLGADGET,
+ (APTR)&projectImage,
+ NULL,
+ NULL,
+ 0,
+ NULL,
+ 0,
+ NULL
+ };
+
+
+/****************************************************************************/
+/* */
+/* All the data needed for BrushIcon */
+/* */
+/****************************************************************************/
+#define BRUSH_WIDTH 43
+#define BRUSH_HEIGHT 8
+#define BRUSH_DEPTH 2
+
+/* Bitmap name = brushico, Amiga-BOB format. */
+/* Width = 43, Height = 8 */
+
+short brushico0[24] = {
+ 0x1FF0, 0x0, 0x0,
+ 0x7FF8, 0x0, 0x0,
+ 0xFFFB, 0xFFFF, 0xFF80,
+ 0xFFFB, 0xFFFF, 0xFF80,
+ 0xFFF8, 0x0, 0x0,
+ 0xFFF0, 0x0, 0x0,
+ 0xE000, 0x0, 0x0,
+ 0x8000, 0x0, 0x0
+ };
+short brushico1[24] = {
+ 0x1FFC, 0x0, 0x0,
+ 0x7FFE, 0x0, 0x0,
+ 0xFFFC, 0x0, 0x60,
+ 0xFFFC, 0x0, 0x60,
+ 0xFFFF, 0xFFFF, 0xFFE0,
+ 0xFFFC, 0x0, 0x0,
+ 0xFFF8, 0x0, 0x0,
+ 0xE000, 0x0, 0x0
+ };
+
+
+static struct Image brushImage=
+ {
+ 0,0,
+ BRUSH_WIDTH,BRUSH_HEIGHT,
+ BRUSH_DEPTH,
+ (USHORT *)&brushico0[0],
+ 3,0,
+ NULL
+ };
+
+static struct Gadget brushGadget=
+ {
+ NULL,
+ 0,0,
+ BRUSH_WIDTH,BRUSH_HEIGHT,
+ GADGIMAGE | GADGHCOMP,
+ RELVERIFY | GADGIMMEDIATE,
+ BOOLGADGET,
+ (APTR)&brushImage,
+ NULL,
+ NULL,
+ 0,
+ NULL,
+ 0,
+ NULL
+ };
+
+#define PICTURE 0
+#define BRUSH 1
+/****************************************************************************/
+/* */
+/* WriteIcon() */
+/* */
+/****************************************************************************/
+static BOOL WriteIcon(drawer,name,type)
+ UBYTE *drawer,*name; SHORT type;
+ {
+ BOOL success=TRUE;
+ LONG newlock,oldlock;
+
+ struct DiskObject myDiskObject;
+
+ myDiskObject.do_Magic=WB_DISKMAGIC;
+ myDiskObject.do_Version=WB_DISKVERSION;
+ myDiskObject.do_Type=WBPROJECT;
+ myDiskObject.do_ToolTypes=NULL;
+ myDiskObject.do_CurrentX=NO_ICON_POSITION;
+ myDiskObject.do_CurrentY=NO_ICON_POSITION;
+ myDiskObject.do_DrawerData=NULL;
+ myDiskObject.do_ToolWindow=NULL;
+ myDiskObject.do_StackSize=NULL;
+
+ if (type==PICTURE) {
+ myDiskObject.do_Gadget=projectGadget;
+ myDiskObject.do_DefaultTool=":dpaintx";
+ }
+ else {
+ myDiskObject.do_Gadget=brushGadget;
+ myDiskObject.do_DefaultTool="";
+ }
+ newlock=Lock(drawer,SHARED_LOCK);
+ success=(newlock!=NULL);
+ if (success) {
+ oldlock = CurrentDir(newlock);
+ success=(BOOL)PutDiskObject(name,&myDiskObject);
+ newlock = CurrentDir(oldlock);
+ }
+ return(success);
+ }
+
+BOOL WriteProjectIcon(drawer,name) UBYTE *drawer,*name;
+ { return (WriteIcon(drawer,name,PICTURE)); }
+
+BOOL WriteBrushIcon(drawer,name) UBYTE *drawer,*name;
+ { return (WriteIcon(drawer,name,BRUSH)); }
diff --git a/MASKBLIT.C b/MASKBLIT.C
new file mode 100644
index 0000000..77d66b8
--- /dev/null
+++ b/MASKBLIT.C
@@ -0,0 +1,155 @@
+/*----------------------------------------------------------------------*/
+/* */
+/* MaskBlit (c) Electronic Arts 1985 */
+/* */
+/* 7/12/85 created Dan Silva */
+/* 7/14/85 added clipping Dan Silva */
+/* 7/19/85 added planeUse,planeDef Dan Silva */
+/* */
+/* */
+/*----------------------------------------------------------------------*/
+
+#include <system.h>
+#include <prism.h>
+
+#undef sx
+#undef sy
+
+#define local static
+
+extern SHORT masks[];
+
+extern BlitterRegs *ar;
+
+#define yA 0xf0
+#define yB 0xcc
+#define yC 0xaa
+#define nA 0x0f
+#define nB 0x33
+#define nC 0x55
+
+#define USEA 0x0800
+#define USEB 0x0400
+#define USEC 0x0200
+#define USED 0x0100
+#define MASKWRITE 0x0F00 /* USEA|USEB|USEC|USED */
+#define CONSTWRITE 0x0B00 /* USEA|USEC|USED */
+
+#define COPYA 0xf0 /* minterm = A */
+
+#define WordOffs(x) (((x)>>3)&0xfffe)
+#define LeftMask(x) (masks[(x)&15])
+#define RightMask(x) (~masks[((x)&15)+1])
+
+/*----------------------------------------------------------------------*/
+/* MaskBlit -- Takes control of the blitter to do a blit of a source */
+/* bitmap through a mask into a destination bitmap, clipped to an */
+/* optional clipping rectangle. Also lets you specify which */
+/* planes of the destination to operate on and default bits for */
+/* the other planes. */
+/*----------------------------------------------------------------------*/
+
+void MaskBlit(sbm,spos,mask, dbm, dpos, copyBox, clip, minTerm,tmpmsk,planeUse,planeDef)
+ struct BitMap *sbm; /* source bitmap */
+ Point *spos; /* where in space is the source bitmap located */
+ UBYTE *mask; /* mask plane (same dimensions as sbm) */
+ struct BitMap *dbm; /* destination bitmap */
+ Point *dpos; /* where is dest bitmap located */
+ Box *copyBox; /* area to be copied */
+ Box *clip; /* optional clip box */
+ BYTE minTerm; /* normally = 0xCA for cookie cut */
+ UBYTE *tmpmsk; /* should be as big as the mask plane */
+ UBYTE planeUse,planeDef; /* which planes to do in the destination and
+ the default bits for the other planes */
+ {
+ LONG ash,shift,slWrd,srWrd,dlWrd,drWrd;
+ LONG blsize,bytWidth,soffset,doffset,sdepth,ddepth,ns,nd,sBytes,dBytes,srx;
+ UBYTE *clmask = mask,bit;
+ UWORD con0_use,con0_def;
+ Box cBox;
+ BOOL hclip = NO;
+ int dx,dy,sx,sy,w,h;
+ if (clip) { if (!BoxAnd(&cBox,clip,copyBox)) return;}
+ else cBox = *copyBox;
+
+ sx = cBox.x - spos->x; sy = cBox.y - spos->y;
+ dx = cBox.x - dpos->x; dy = cBox.y - dpos->y;
+ w = cBox.w;
+ h = cBox.h;
+ slWrd = WordOffs(sx);
+ srx = sx+w-1;
+ srWrd = WordOffs(srx);
+ sBytes = srWrd-slWrd+2;
+ soffset = sy*sbm->BytesPerRow + slWrd;
+ ddepth = dbm->Depth;
+ sdepth = sbm->Depth;
+ dlWrd = WordOffs(dx);
+ drWrd = WordOffs(dx+w-1);
+ shift = (dx&15) - (sx&15);
+ if (shift<0) { shift = 16+shift; dlWrd -= 2;}
+ dBytes = drWrd-dlWrd+2;
+ if (dBytes>dbm->BytesPerRow) {
+ /* patch the "Destination Wrap-Around Bug" by breaking
+ into two halves -----*/
+ cBox = *copyBox;
+ cBox.w = cBox.w/2;
+ MaskBlit(sbm,spos,mask, dbm, dpos, &cBox, clip, minTerm,tmpmsk,planeUse,planeDef);
+ cBox.x += cBox.w;
+ cBox.w = copyBox->w - cBox.w;
+ MaskBlit(sbm,spos,mask, dbm, dpos, &cBox, clip, minTerm,tmpmsk,planeUse,planeDef);
+ return;
+ }
+ if (((sx&15)!=0)||((srx&15)!=15))
+ { /* Apply clip rectangle to the mask plane */
+ hclip = YES;
+ WaitBlit();
+ OwnBlitter();
+ ar->fwmask = LeftMask(sx);
+ ar->lwmask = RightMask(srx);
+ ar->bltcon0 = USEA|USED|COPYA;
+ ar->bltcon1 = 0;
+ ar->bdata = 0;
+ ar->bltmda = ar->bltmdd = sbm->BytesPerRow - sBytes;
+ ar->bltpta = mask+soffset;
+ ar->bltptd = tmpmsk+soffset;
+ ar->bltsize = (h<<6)|(sBytes>>1); /* start the blit */
+ clmask = tmpmsk;
+ }
+ ash = shift<<12;
+ bytWidth = MAX(sBytes,dBytes);
+ doffset = dy*dbm->BytesPerRow + dlWrd;
+ blsize = (h<<6)|(bytWidth>>1);
+
+ con0_use = ash|MASKWRITE|(minTerm&0xff);
+ con0_def = ash|CONSTWRITE|(minTerm&0xff);
+
+ WaitBlit();
+ if (!hclip) OwnBlitter();
+
+ ar->fwmask = LeftMask(sx);
+ ar->lwmask = (dBytes>sBytes)? 0 : RightMask(srx);
+ ar->bltmda = ar->bltmdb = sbm->BytesPerRow - bytWidth;
+ ar->bltmdc = ar->bltmdd = dbm->BytesPerRow - bytWidth;
+ bit = 1;
+
+ for (ns = nd = 0; nd<ddepth; nd++) {
+ WaitBlit();
+ ar->bltpta = clmask + soffset; /* a-data address */
+ ar->bltptd = ar->bltptc = dbm->Planes[nd] + doffset; /* c-data address */
+ if ((bit&planeUse)&&(ns<sdepth)) { /* use b source */
+ ar->bltcon1 = ash;
+ ar->bltcon0 = con0_use;
+ ar->bltptb = sbm->Planes[ns++] + soffset; /* b-data address */
+ }
+ else { /* default */
+ ar->bltcon1 = 0;
+ ar->bltcon0 = con0_def;
+ ar->bdata = (bit & planeDef ) ? 0xffff : 0;
+ }
+ ar->bltsize = blsize; /* trigger blitter */
+ bit <<= 1;
+ }
+ WaitBlit();
+ DisownBlitter();
+ }
+
diff --git a/MENU.C b/MENU.C
new file mode 100644
index 0000000..56bf351
--- /dev/null
+++ b/MENU.C
@@ -0,0 +1,454 @@
+/*----------------------------------------------------------------------*/
+/* */
+/* menu.c -- Pull Down Menus */
+/* */
+/*----------------------------------------------------------------------*/
+
+#include "system.h"
+#include "prism.h"
+#include <librarie\diskfont.h>
+
+#define fudgeFact 12 /* make this 12 for V1.1 */
+
+extern SHORT xShft,yShft,curFormat;
+extern struct RastPort *mainRP;
+extern void Undo(),TogGridSt();
+extern void DoFontMI();
+extern struct Window *mainW;
+extern Box bigBox;
+extern BOOL midHandle;
+extern SHORT curpen;
+extern PaintMode paintMode;
+extern struct Screen *screen;
+
+#define local static
+
+#define TXHEIGHT 8
+
+struct TextAttr curMIFont = { "topaz.font",TXHEIGHT,0,0 };
+
+#define NMEN 4
+
+#define NOCOM 0 /* indicates no command key */
+#define NOEXCL 0 /* indicates no mutual exclusion */
+#define NOSELFILL NULL /* indicates no selection highlite bitmap */
+#define NOFONT NULL /* no font defined yet */
+#define NOSUBIT NULL /* no sub items defined */
+
+#define TXTFLAGS (ITEMTEXT | ITEMENABLED | HIGHCOMP) /* or HIGHBOX*/
+#define COMFLAGS (TXTFLAGS | COMMSEQ)
+#define ITInit(name) {0,1,JAM1,0,1,NOFONT,name,NULL}
+
+#define MIW 64
+#define MIH 20 /* in 640x400 coords */
+
+void NopMI(item,subi) SHORT item,subi; {
+ KPrintF(" NopMI: item = %ld, subi = %ld \n",item,subi);
+ }
+
+#define SUBXOFFS 46
+#define MIInit(next,itname) {next,0,0,MIW,MIH,TXTFLAGS,NOEXCL,(APTR)itname,NOSELFILL,NOCOM, NULL,0}
+#define SubInit(next,itext,subm) {next,0,0,MIW,MIH,TXTFLAGS,NOEXCL, (APTR)itext,NOSELFILL,NOCOM,subm,0}
+#define FirstSub(next,itname) {next,SUBXOFFS,10,MIW,MIH,TXTFLAGS,NOEXCL, (APTR)itname,NOSELFILL,NOCOM,NULL,0}
+
+/*----------------------------------------------------------------------*/
+/* Picture Menu */
+/*----------------------------------------------------------------------*/
+
+
+UBYTE saveString[] = "Save ";
+StuffSaveStr(s) UBYTE *s; { strncpy(&saveString[5], s, 8);}
+
+local struct IntuiText itOp = ITInit("Load...");
+local struct IntuiText itSav = ITInit(saveString);
+local struct IntuiText itSavAs = ITInit("Save As...");
+local struct IntuiText itUndo = ITInit("Undo");
+local struct IntuiText itSet = ITInit("Settings");
+local struct IntuiText itSymCent = ITInit("Symmetry Center");
+local struct IntuiText itColCon = ITInit("Color Control");
+
+local struct IntuiText itUsePal = ITInit("Use Brush Palette");
+local struct IntuiText itRestPal = ITInit("Restore Palette");
+local struct IntuiText itDefPal = ITInit("Default Palette");
+local struct IntuiText itPalette = ITInit("Palette p");
+local struct IntuiText itCCycle = ITInit("Cycle TAB");
+
+local struct IntuiText itSpare = ITInit("Spare");
+local struct IntuiText itSwap = ITInit("Swap j");
+local struct IntuiText itCopyTo = ITInit("Picture To Spare");
+local struct IntuiText itMrgSpFront = ITInit("Merge in front");
+local struct IntuiText itMrgSpBack = ITInit("Merge in back");
+
+local struct IntuiText itPrint = ITInit("Print");
+local struct IntuiText itQuit = ITInit("Quit");
+
+#ifdef doraw
+local struct IntuiText itRawIO = ITInit("Raw Bitmap IO");
+local struct MenuItem rawIOsub[3] = {
+ FirstSub(&rawIOsub[1],&itOp),
+ MIInit(&rawIOsub[2], &itSav),
+ MIInit(NULL, &itSavAs)
+ };
+
+void doRawIO(item,subi) int item,subi; {
+ switch(subi) {
+ case 0: OpenRaw(); break;
+ case 1: SaveRaw(); break;
+ case 2: SaveRawAs(); break;
+ }
+ }
+#endif
+
+local struct MenuItem colConSub[5] = {
+ FirstSub(&colConSub[1], &itPalette),
+ MIInit(&colConSub[2], &itUsePal),
+ MIInit(&colConSub[3], &itRestPal),
+ MIInit(&colConSub[4], &itDefPal),
+ MIInit(NULL, &itCCycle)
+ };
+
+local struct MenuItem spareSub[4] = {
+ FirstSub(&spareSub[1], &itSwap),
+ MIInit(&spareSub[2], &itCopyTo),
+ MIInit(&spareSub[3], &itMrgSpFront),
+ MIInit(NULL, &itMrgSpBack)
+ };
+
+local struct MenuItem picMI[8] = {
+ MIInit(&picMI[1], &itOp),
+ MIInit(&picMI[2], &itSav),
+ MIInit(&picMI[3], &itSavAs),
+ MIInit(&picMI[4], &itSymCent),
+ SubInit(&picMI[5], &itColCon, colConSub),
+ SubInit(&picMI[6], &itSpare, spareSub),
+ MIInit(&picMI[7], &itPrint),
+ MIInit(NULL,&itQuit)
+ };
+
+extern void OpenPic(), SavePic(), SavePicAs();
+extern void PaneStop(), PrintPic(), DoSymReq();
+extern void TogColCyc(), SwapSpare();
+extern void ShowPallet();
+
+void SpecSymCenter(){ NewIMode(IM_symCent); }
+
+local void doColCon(item,subi) int item,subi; {
+ switch(subi) {
+ case 0: ShowPallet(); break;
+ case 1: UseBrPalette(); break;
+ case 2: RestorePalette(); break;
+ case 3: DefaultPalette(); break;
+ case 4: TogColCyc(); break;
+ }
+ }
+
+local void doSpare(item,subi) int item,subi; {
+ switch(subi) {
+ case 0: SwapSpare(); break;
+ case 1: CopyToSpare(); break;
+ case 2: MrgSpareFront(); break;
+ case 3: MrgSpareBack(); break;
+ }
+ }
+
+/* disable refreshing after overlays, since I do it as a matter of
+course after all io operations */
+void DoOpen() { OffRefrAfterOv(); OpenPic(); OnRefrAfterOv(); }
+void DoSave() { OffRefrAfterOv(); SavePic(); OnRefrAfterOv();}
+void DoSaveAs() { OffRefrAfterOv(); SavePicAs(); OnRefrAfterOv(); }
+local void (*picProc[])() = { DoOpen, DoSave, DoSaveAs,
+ SpecSymCenter, doColCon, doSpare, PrintPic, PaneStop };
+
+local void DoPic(item,subi) int item,subi; { (*picProc[item])(item,subi); }
+
+/*----------------------------------------------------------------------*/
+/* Brush Menu */
+/*----------------------------------------------------------------------*/
+local struct IntuiText itSize = ITInit("Size");
+local struct IntuiText itRot = ITInit("Rotate");
+local struct IntuiText itFlip = ITInit("Flip");
+local struct IntuiText itChgCol = ITInit("Change Color");
+local struct IntuiText itBrHFlip = ITInit("Horiz x");
+local struct IntuiText itBrVFlip = ITInit("Vert y");
+local struct IntuiText itBrRot90 = ITInit("90 Degrees z");
+local struct IntuiText itAny = ITInit("Any Angle");
+local struct IntuiText itBrStretch = ITInit("Stretch Z");
+local struct IntuiText itBrHalf = ITInit("Halve h");
+local struct IntuiText itBrDubl = ITInit("Double H");
+local struct IntuiText itBrDublX = ITInit("Double Horiz");
+local struct IntuiText itBrDublY = ITInit("Double Vert");
+local struct IntuiText itBrShr = ITInit("Shear");
+local struct IntuiText itBrBgToFg = ITInit("Bg -> Fg");
+local struct IntuiText itRemap = ITInit("Remap ");
+local struct IntuiText itBend = ITInit("Bend");
+local struct IntuiText itHoriz = ITInit("Horiz");
+local struct IntuiText itVert = ITInit("Vert");
+
+local struct MenuItem brSizeSub[5] = {
+ FirstSub(&brSizeSub[1], &itBrStretch),
+ MIInit(&brSizeSub[2], &itBrHalf),
+ MIInit(&brSizeSub[3], &itBrDubl),
+ MIInit(&brSizeSub[4], &itBrDublX),
+ MIInit(NULL, &itBrDublY)
+ };
+
+local struct MenuItem brFlipSub[2] = {
+ FirstSub(&brFlipSub[1], &itBrHFlip),
+ MIInit(NULL, &itBrVFlip)
+ };
+
+local struct MenuItem brRotSub[3] = {
+ FirstSub(&brRotSub[1], &itBrRot90),
+ MIInit(&brRotSub[2], &itAny),
+ MIInit(NULL, &itBrShr)
+ };
+
+local struct MenuItem chgColSub[2] = {
+ FirstSub(&chgColSub[1], &itBrBgToFg),
+ MIInit(NULL, &itRemap),
+ };
+
+local struct MenuItem bendSub[2] = {
+ FirstSub(&bendSub[1], &itHoriz),
+ MIInit(NULL, &itVert),
+ };
+
+local struct MenuItem brushMI[7] = {
+ MIInit(&brushMI[1], &itOp),
+ MIInit(&brushMI[2], &itSavAs),
+ SubInit(&brushMI[3], &itSize, brSizeSub),
+ SubInit(&brushMI[4], &itFlip, brFlipSub),
+ SubInit(&brushMI[5], &itRot, brRotSub),
+ SubInit(&brushMI[6], &itChgCol, chgColSub),
+ SubInit(NULL, &itBend, bendSub)
+ };
+
+extern void GetBrs(), SaveBrsAs(), BrFlipX(), BrFlipY();
+extern void BrRot90(), BrHalf(), BrDubl(),BrBgToFg(), BrRemapCols();
+
+void DoBrs(item,subi) int item,subi; {
+ switch(item) {
+ case 0: OffRefrAfterOv(); GetBrs(); OnRefrAfterOv(); break;
+ case 1: OffRefrAfterOv(); SaveBrsAs(); OnRefrAfterOv(); break;
+ case 2: switch(subi) {
+ case 0: NewIMode(IM_strBrush); break;
+ case 1: BrHalf(); break;
+ case 2: BrDubl(); break;
+ case 3: BrDublX(); break;
+ case 4: BrDublY(); break;
+ } break;
+ case 3: switch(subi) {
+ case 0: BrFlipX(); break;
+ case 1: BrFlipY(); break;
+ } break;
+ case 4: switch(subi) {
+ case 0: BrRot90(); break;
+ case 1: NewIMode(IM_rotBrush); break;
+ case 2: NewIMode(IM_shrBrush); break;
+ } break;
+ case 5: switch(subi) {
+ case 0: BrBgToFg(); break;
+ case 1: BrRemapCols();break;
+ } break;
+ case 6: switch(subi) {
+ case 0: NewIMode(IM_hbendBrush); break;
+ case 1: NewIMode(IM_vbendBrush);break;
+ } break;
+ }
+ }
+
+/*----------------------------------------------------------------------*/
+/* Paint Mode Menu */
+/*----------------------------------------------------------------------*/
+
+extern UBYTE *modeNames[];
+
+#define ONES 0xffffffff
+#define MICheck(next,itname,itnum,checkme) {next,0,0,MIW,MIH,TXTFLAGS|CHECKIT|(checkme), ONES^(1<<(itnum)),(APTR)itname,NOSELFILL,NOCOM, NULL,0}
+
+local struct IntuiText itMask = ITInit("Object F1 ");
+local struct IntuiText itColor = ITInit("Color F2 ");
+local struct IntuiText itRplc = ITInit("Replace F3 ");
+local struct IntuiText itSmear = ITInit("Smear F4 ");
+local struct IntuiText itShade = ITInit("Shade F5 ");
+local struct IntuiText itBlend = ITInit("Blend F6 ");
+local struct IntuiText itCycPaint = ITInit("Cycle F7 ");
+
+local struct MenuItem modeMI[7] = {
+ MICheck(&modeMI[1], &itMask,0,0),
+ MICheck(&modeMI[2], &itColor,1,0),
+ MICheck(&modeMI[3], &itRplc,2,0),
+ MICheck(&modeMI[4], &itSmear,3,0),
+ MICheck(&modeMI[5], &itShade,4,0),
+ MICheck(&modeMI[6], &itBlend,5,0),
+ MICheck(NULL, &itCycPaint,6,0)
+ };
+
+SHORT userPntMode = 0;
+
+UserPaintMode(m) int m; {
+ int pntmd;
+ if ((m==Blend)||(m==Smear)||(m==Shade)) NewIMode(IM_shade);
+ if (m==CyclePaint) { OnCycPaint(); pntmd = Color;}
+ else { OffCycPaint(); pntmd = m; }
+ SetPaintMode(pntmd);
+ userPntMode = m;
+ }
+
+void DoMode(item,subi) int item,subi; {
+ if (!LegalMode(item)) {
+ modeMI[item].Flags &= (~CHECKED);
+ modeMI[userPntMode].Flags |= CHECKED;
+ return;
+ }
+ UserPaintMode(item);
+ }
+
+#define MODEMENNUM 2
+ModeMINum(m) int m; { return((m<<5)+MODEMENNUM ); }
+
+void SetModeMenu(i) int i; {
+ int j,miNum;
+ if (!LegalMode(i)) return;
+ modeMI[userPntMode].Flags &= (~CHECKED);
+ modeMI[i].Flags |= CHECKED;
+ for (j=0; j<7; j++) {
+ miNum = ModeMINum(j);
+ if (LegalMode(j)) OnMenu(mainW,miNum);
+ else OffMenu(mainW,miNum);
+ }
+ UserPaintMode(i);
+ DispPntMode();
+ }
+
+
+/*----------------------------------------------------------------------*/
+/* Font Menu */
+/*----------------------------------------------------------------------*/
+local struct IntuiText itLoadFonts = ITInit("Load Fonts");
+local struct MenuItem miLoadFonts = MIInit(NULL, &itLoadFonts);
+
+extern struct AvailFonts *fontDir;
+local void DoFontMI(item,subi) int item,subi; {
+ if (fontDir == NULL) LoadFontDir();
+ else LoadAFont(item);
+ }
+
+
+/*----------------------------------------------------------------------*/
+/* Prefs Menu */
+/*----------------------------------------------------------------------*/
+local struct IntuiText prefIT[] = {
+ ITInit(" Brush Handle"),
+ ITInit(" Coordinates"),
+ ITInit(" Fast Feedback")
+ };
+
+#define CKFLAGS TXTFLAGS/*|CHECKIT*/
+#define CkInit(next,itname) {next,0,0,MIW,MIH,CKFLAGS,NOEXCL,(APTR)itname,NOSELFILL,NOCOM, NULL,0}
+
+local struct MenuItem prefsMI[3] = {
+ MIInit(&prefsMI[1], &prefIT[0]),
+ MIInit(&prefsMI[2], &prefIT[1]),
+ MIInit(NULL, &prefIT[2]),
+ };
+
+extern BOOL dispCoords, fastFB, modeHelp;
+
+local UWORD prefState = 0;
+
+local void TogCoords() { dispCoords = !dispCoords; }
+local void TogMidHandle() { midHandle = !midHandle; }
+local void TogFFB() { fastFB = !fastFB; FixUsePen(); }
+
+local void (*prefsProc[])() = {TogMidHandle, TogCoords, TogFFB};
+local void DoPrefs(item,subi) SHORT item,subi; {
+ UWORD bit;
+ (*prefsProc[item])(subi);
+ bit = 1<<item;
+ prefState ^= bit;
+ prefIT[item].IText[0] = (prefState&bit) ? '*': ' ';
+ }
+
+/*----------------------------------------------------------------------*/
+/* Main Menu Bar */
+/*----------------------------------------------------------------------*/
+#define MenW 48
+
+/* initializer for Menu */
+struct Menu menus[5] = {
+ { &menus[1],0,0,MenW,10,MENUENABLED,"Picture",picMI},
+ { &menus[2],0,0,MenW,10,MENUENABLED,"Brush",brushMI},
+ { &menus[3],0,0,MenW,10,MENUENABLED,"Mode",modeMI},
+/* FontMenu must point at this: */
+ { &menus[4],0,0,MenW,10,MENUENABLED,"Font",&miLoadFonts},
+ { NULL,0,0,MenW,10,MENUENABLED,"Prefs",prefsMI}
+ };
+
+struct Menu *FontMenu = &menus[3];
+struct Menu *MainMenu = menus;
+
+void (*MenProcs[])() = {DoPic,DoBrs,DoMode,DoFontMI,DoPrefs};
+
+DoMenEvent(code) SHORT code; {
+ SHORT item,subi;
+ if (code != (SHORT)MENUNULL ) {
+ item = ITEMNUM(code);
+ subi = SUBNUM(code);
+ (*MenProcs[MENUNUM(code)])(item,subi);
+ }
+ DispPntMode();
+ LoadIMode(); /*bring in overlay */
+ }
+
+#ifdef nowInDpinit /***##################### */
+
+ComWidth() { return( (curFormat>0)? COMMWIDTH: LOWCOMMWIDTH); }
+
+SHORT MaxMiLength(mi) struct MenuItem *mi; {
+ struct IntuiText *it;
+ SHORT w,max;
+ for (max = 0; mi != NULL; mi = mi->NextItem) {
+ it = (struct IntuiText *)(mi->ItemFill);
+ w = TextLength(mainRP,it->IText,strlen(it->IText)) + fudgeFact;
+ if (mi->Flags&COMMSEQ) w += ComWidth();
+ max = MAX(w,max);
+ }
+ return((SHORT)(max-10));
+ }
+
+InitMItems(mi,minW) struct MenuItem *mi; SHORT minW; {
+ SHORT i , y, x;
+ SHORT wid = MAX(MaxMiLength(mi) + widCorrect[curFormat], minW );
+ y = mi->TopEdge;
+ x = mi->LeftEdge;
+ for ( i=0 ; mi != NULL; ++i, mi = mi->NextItem) {
+ if ((mi->Flags&ITEMTEXT)&&(mi->Flags&CHECKIT))
+ ((struct IntuiText *)(mi->ItemFill))->LeftEdge = checkW[curFormat];
+ mi->TopEdge = y;
+ mi->LeftEdge = x;
+ mi->Width = wid;
+ if ((mi->Flags)&COMMSEQ) mi->Width += ComWidth();
+ mi->Height = curMIH;
+ ((struct IntuiText *)(mi->ItemFill))->ITextFont = &curMIFont;
+ y += curMIH;
+ if (mi->SubItem!=NULL) InitMItems(mi->SubItem,0);
+ }
+ }
+
+InitMenu() {
+ SHORT i = 0,xl = PMapX(12);
+ struct Menu *mn = MainMenu;
+ curMIH = menuHeight[curFormat];
+ for (mn = menus; mn != NULL; ++i,mn = mn->NextMenu ) {
+ mn->LeftEdge = xl;
+ mn->Width = TextLength(screen->BarLayer->rp,
+ mn->MenuName,strlen(mn->MenuName)) +
+ widCorrect[curFormat] + fudgeFact;
+ xl += mn->Width;
+ mn->Flags = MENUENABLED;
+ InitMItems(mn->FirstItem, mn->Width);
+ }
+ }
+
+#endif \ No newline at end of file
diff --git a/MESSAGE.C b/MESSAGE.C
new file mode 100644
index 0000000..c7c030f
--- /dev/null
+++ b/MESSAGE.C
@@ -0,0 +1,28 @@
+/*----------------------------------------------------------------------*/
+/* */
+/* message.c -- Error and Informative messages */
+/* */
+/*----------------------------------------------------------------------*/
+
+#include <system.h>
+extern struct Window *mainW;
+
+#define local static
+local struct BitMap sparebm = {0};
+local struct IntuiText itInfo2 = {0,0,JAM1,10,20,NULL,NULL,NULL};
+local struct IntuiText itInfo1 = {0,0,JAM1,10,10,NULL,NULL,&itInfo2};
+
+local UBYTE proceed[] = "Proceed";
+local struct IntuiText itProceed = {0,0,JAM1,4,4,NULL,proceed,NULL};
+
+#define idcmpFlags MOUSEBUTTONS | GADGETUP | MOUSEMOVE
+
+InfoMessage(str1,str2) UBYTE *str1, *str2;{
+ itInfo1.IText = str1;
+ itInfo2.IText = str2;
+ UndoSave();
+ AutoRequest(mainW, &itInfo1, NULL, &itProceed,
+ idcmpFlags, idcmpFlags, 240,70);
+ UpdtDisplay();
+ }
+
diff --git a/MODES.C b/MODES.C
new file mode 100644
index 0000000..d74f8b6
--- /dev/null
+++ b/MODES.C
@@ -0,0 +1,456 @@
+/*----------------------------------------------------------------------*/
+/* */
+/* modes.c -- Painting Modes 1 */
+/* */
+/*----------------------------------------------------------------------*/
+#include <system.h>
+#include <prism.h>
+#include <pnts.h>
+
+#define local static
+
+extern NewMode();
+extern struct RastPort *curRP;
+extern Box clipBox, screenBox;
+extern struct BitMap hidbm;
+extern SHORT Distance();
+extern SHORT(*nop)();
+extern void (*killMode)();
+extern void (*WentDn)(), (*WentUp)();
+extern UWORD curIMFlags;
+extern SHORT curIMode,paintMode;
+extern PointRec pnts; /* contains mx,my,sx,sy, etc */
+extern void ClearXY();
+extern SHORT curpen,usePen;
+extern SHORT button,butwas;
+extern BOOL Painting;
+extern SHORT curbgcol;
+extern BMOB curpenob,curbr;
+extern BOOL gridON,everyTime,wasShift;
+extern SHORT xorg,yorg; /* These shouldn't really be referenced here */
+extern void mDispOB(), mMoveOB();
+extern BOOL goToPerm,loadedBrush;
+extern Box mainBox;
+extern SHORT LoadBrColors[];
+extern SHORT xShft,yShft;
+extern IModeDesc imodes[];
+extern SHORT lastPermMode;
+
+extern void SymPts(); /* forward declaration */
+
+SHORT npts = 6;
+BOOL symON = NO;
+BOOL abortFlag = NO;
+Point bp;
+
+BMOB *curob;
+
+/* make a box with the start button point and current point as corners*/
+Box *BoxFromSM(bx) Box *bx; { BoxTwoPts(bx,sx,sy,mx,my); }
+
+SHORT RadSM() { return((SHORT) PMapX(Distance(VMapX(mx-sx),VMapY(my-sy)))); }
+
+
+/* Atomic graphic functions that happen with mouse motion and button events */
+
+extern void EraseTempChg();
+
+#define eraseFB EraseTempChg
+
+void obsplat() { mDispOB(mx,my); }
+void obmv() { mMoveOB(mx,my); }
+void obclr() { mClearOB(mx,my); }
+
+local void incline( ) {mLine(lx,ly,mx,my); }
+void vec() { mLine(sx,sy,mx,my); }
+
+local void crv() { mCurve(psx,psy,mx,my,pex,pey); }
+
+local void cir() {mCircle(sx,sy,RadSM());}
+local void fcir() {mFillCircle(sx,sy,RadSM());}
+
+local void doval() { mOval(sx,sy,mx,my); }
+local void foval() { mFillOval(sx,sy,mx,my);}
+
+
+local void invXH() { minvXHair(mx,my); }
+
+showXHAndOb() { obmv(); invXH(); }
+clrXHAndOb() {minvXHair(mx,my); obclr(); }
+movXHAndOb() {minvXHair(lx,ly); obmv(); minvXHair(mx,my); }
+
+UsePen() { curob = &curpenob; }
+UseBrush() { curob = &curbr; }
+
+local BOOL abortable = YES;
+DisableAbort() { abortable = NO; }
+EnableAbort() { abortable = YES; }
+
+BOOL CheckAbort() {
+ if (AbortKeyHit()&&abortable){
+ /*ClearPushB();*/ UnDisplay(); abortFlag = YES;}
+ return(abortFlag);
+ }
+
+/*------------ Misc functionals ----*/
+void (*doit)(),(*xorit)();
+void PaintIt() { UpdtON(); (*doit)(); UpdtOFF(); CycPaint(); }
+void PaintSym() { UpdtON(); SymPts(); UpdtOFF(); }
+void FlipIt() { TempXOR(); (*xorit)(); RestoreMode(); }
+
+/*-------------- Symmetry ------------------*/
+
+SymState(s) BOOL s; { if (symON!=s) TogSymSt(); }
+TogSymSt() { symON = !symON; CPInvAct(symAct); }
+TurnSymOn() { if (!symON) TogSymSt(); }
+
+void SymPts() {
+ abortFlag = NO;
+ if (symON) SymDo(npts,&pnts, doit); else { (*doit)();}
+ CycPaint();
+ }
+
+/*========Some "pre-fabricated" mode types =============*/
+
+SimpleOps(atproc) void (*atproc)(); { WentDn = atproc; }
+
+/* ------
+ is up: cursor;
+ is down: paint(atproc);
+-------*/
+PaintWith(atproc) void (*atproc)(); {
+ doit = atproc;
+ IModeProcs(obmv,obmv,obclr,SymPts,nop,SymPts,nop,nop);
+ }
+
+/* ------
+ is up: brush;
+ is down: current geom;
+ goes up: paint(dof);
+-------*/
+VTypeOps(shof,clrf,dof) void (*shof)(),(*clrf)(),(*dof)(); {
+ doit = dof;
+ UpdtOFF();
+ IModeProcs(obmv,obmv,obclr,nop,shof,nop,clrf,PaintSym);
+ }
+
+/* ------
+ is up: crosshair;
+ is down: xorfeedback(xorf);
+ goes up: paint(dof);
+-------*/
+XHTypeOps(xorf,dof) void (*xorf)(),(*dof)(); {
+ void (*afunc)() = (curIMFlags&NOSYM)? &PaintIt: &PaintSym;
+ doit = dof; xorit=xorf;
+ IModeProcs(&invXH,nop,&invXH,nop,&FlipIt,nop,&FlipIt,afunc);
+ }
+
+/* This shows the object AND the XHairs during button up */
+CircTypeOps(shof,clrf,dof) void (*shof)(),(*clrf)(),(*dof)(); {
+ doit = dof;
+ UpdtOFF();
+ IModeProcs(showXHAndOb,movXHAndOb,clrXHAndOb,nop,shof,nop,clrf,PaintSym);
+ }
+
+FCircTypeOps(shof,clrf,dof) void (*shof)(),(*clrf)(),(*dof)(); {
+ doit = dof;
+ IModeProcs(invXH,nop,invXH,nop,shof,nop,clrf,PaintSym);
+ }
+
+
+/* --- Mode Specifications ----*/
+
+void IMDraw() { PaintWith(incline);}
+
+void IMShade() {PaintWith(obsplat);}
+
+
+/* ------ Vector Mode ------------------- */
+
+void IMVect() { VTypeOps(vec,eraseFB,vec); }
+
+/* Conic Curve ===========================================================*/
+clrcrv() { RecTempChg(&screenBox); EraseTempChg(); }
+
+void IMCurve1(){ UpdtOFF();
+ IModeProcs(obmv,obmv,obclr,nop,vec,nop,eraseFB,nop);
+ }
+
+void IMCurve2(){ doit = &crv;
+ IModeProcs(crv,nop,clrcrv,nop,crv,nop,clrcrv,PaintSym);
+ }
+
+/* Circle ==============================================================*/
+void IMCirc() { CircTypeOps(cir,eraseFB,cir); }
+
+/* Filled Circle ========================================================*/
+void IMFCirc() { FCircTypeOps(fcir,eraseFB,fcir); }
+
+
+/* Rectangle ============================================================*/
+
+Box *ConstBoxFromSM(b) Box *b; {
+ SHORT s;
+ BoxFromSM(b);
+ if (wasShift) {
+ s = MAX(VMapX(b->w), VMapY(b->h));
+ b->w = PMapX(s);
+ b->h = PMapY(s);
+ }
+ return(b);
+ }
+
+local void frbox() {
+ Box bx; ConstBoxFromSM(&bx); mOBFrame(&bx);
+ }
+void IMRect() { CircTypeOps(frbox,eraseFB,frbox); }
+
+
+/* Filled Rectangle ======================================================*/
+
+local void filbox() { Box bx; ConstBoxFromSM(&bx); mRect(&bx); }
+void IMFRect() { FCircTypeOps(filbox,eraseFB,filbox); }
+
+void IMOval() { CircTypeOps(doval,eraseFB,doval); }
+
+/* Filled Ellipse ==========================================================*/
+void IMFOval() { FCircTypeOps(foval,eraseFB,foval); }
+
+
+/* Flood Fill =============================================================*/
+void afillproc() { mFillArea(NO,mx,my);}
+IMFill() { doit = &afillproc; WentUp = &SymPts; }
+
+/* ----- null mode (used to abort operations) ------*/
+
+IMNull(){ SimpleOps(nop); }
+
+/* ReadPixel =============================================================*/
+doRead() {
+ SHORT px = mReadPix(mx,my);
+ if (butwas==2) CPChgBg(px); else CPChgCol(px);
+ }
+
+IMReadPix(){ SimpleOps(&doRead); JamCursor(PICKCURSOR); }
+
+
+/* Select Brush ==========================================================*/
+
+SHORT brx,bry;
+BOOL exclBox = NO;
+
+BrBox(bx) Box *bx; {
+ BoxFromSM(bx);
+ if (exclBox) { bx->w = MAX(1,bx->w-1); bx->h = MAX(1,bx->h-1); }
+ }
+
+BOOL midHandle = YES;
+
+
+void DoSelBr() {
+ SHORT midx,midy;
+ SHORT xoff,yoff;
+ Box bx;
+ BrBox(&bx);
+ if (midHandle) {
+ midx = bx.x + bx.w/2;
+ midy = bx.y + bx.h/2;
+ Gridify(&midx,&midy);
+ xoff = midx-bx.x; yoff = midy-bx.y;
+ }
+ else { xoff = MAX(0,mx - sx); yoff = MAX(0,my - sy); }
+ bx.x += xorg;
+ bx.y += yorg;
+ if (ExtractBMOB(&curbr,&bx,0,0)) { /* --- failed --- */
+ SelPen(0);
+ SetNextIMode(IM_draw);
+ return;
+ }
+ CPChgPen(USERBRUSH);
+ UpdtON();
+ if (butwas == 2) {
+ mx = bx.x - xorg; my = bx.y - yorg;
+ obsplat();
+ mx = ex; my = ey;
+ }
+ curbr.xoffs = xoff;
+ curbr.yoffs = yoff;
+ ClearBrXform();
+ GetColors(LoadBrColors);
+ UserBr();
+ }
+
+local void sbfrbox() { Box bx; BrBox(&bx); mFrame(&bx); }
+
+void IMSelBrush(){ XHTypeOps(&sbfrbox,&DoSelBr); }
+
+
+/* == Specify Grid Location and spacing ======================================*/
+
+extern SHORT gridx,gridy;
+extern BOOL dispCoords;
+
+local SHORT tgridx,tgridy;
+local SHORT grXorg,grYorg;
+local BOOL svDispCoords;
+
+/* show a 4x4 piece of grid */
+local drawGrid() {
+ int i,x,y,dx,dy;
+ SHORT svUsePen = usePen;
+ usePen = 0; /* make it draw thin lines */
+ TempXOR();
+ dx = 4*tgridx;
+ dy = 4*tgridy;
+ x = grXorg; y = grYorg;
+ for (i=0; i<5; i++) {
+ mLine(grXorg, y, grXorg + dx, y );
+ mLine(x, grYorg, x, grYorg + dy );
+ x += tgridx;
+ y += tgridy;
+ }
+ RestoreMode();
+ usePen = svUsePen;
+ }
+
+setGrOrg() {
+ grXorg = mx - 4*tgridx;
+ grYorg = my - 4*tgridy;
+ }
+
+showgrid() { setGrOrg(); drawGrid(); DispXY(grXorg, grYorg);
+ /* minvXHair(grXorg, grYorg); */ }
+
+strgrid() {
+ tgridx = (mx - grXorg)/4;
+ tgridy = (my - grYorg)/4;
+ drawGrid();
+ DispXY(tgridx,tgridy);
+ }
+
+dogrid() {
+ SetGridXY(tgridx,tgridy);
+ dispCoords = svDispCoords;
+ SetGridOrg(grXorg,grYorg);
+ ClearXY();
+ }
+
+void IMGridSpec(){
+ tgridx = gridx;
+ tgridy = gridy;
+ svDispCoords = dispCoords;
+ dispCoords = NO;
+ killMode = &ClearXY;
+ IModeProcs(showgrid,nop,showgrid,setGrOrg,strgrid,nop,strgrid,dogrid);
+ }
+
+
+/* == Specify Symmetry Center ======================================*/
+
+void doSymCenter() { SymCenter(mx,my); }
+void IMSymCent(){IModeProcs(invXH,nop,invXH,doSymCenter,nop,nop,nop,nop); }
+
+/* == Size Pen ======================================*/
+/* should only be called with pen as current object */
+local SHORT siz, pnType = 0;
+local BOOL sizingAirB = NO;
+local SHORT svPen, svABMode;
+
+szSet() {
+ if (sizingAirB) {
+ SetAirBRad(VMapY(siz));
+ CPChgPen(svPen);
+ SetModeMenu(svABMode);
+ }
+ else CPChgPen( (pnType == DOT_B)? DotBFromRad(siz) : (pnType<<12)|siz);
+ dispCoords = svDispCoords;
+ ClearXY();
+ }
+
+pnDraw() {
+ SHORT svmd = paintMode;
+ SHORT pen, x,y, svUsePen;
+ SetPaintMode(Color);
+ DispXY(siz,siz);
+ x = bp.x; y = bp.y;
+ pen = (pnType<<12)|siz;
+ if (pnType == SQUARE_B) {x = bp.x+siz/2; y = bp.y+siz/2; }
+ else if (pnType == DOT_B) pen = DotBFromRad(siz);
+ SelPen(pen);
+ svUsePen = usePen;
+ usePen = curpen;
+ mDispOB(x,y);
+ usePen = svUsePen;
+ SetPaintMode(svmd);
+ }
+
+void pnUpMv() {bp.x = mx - siz; bp.y = my - siz; pnDraw(); }
+
+void pnDnMv() { siz = MAX(ABS(mx-bp.x),ABS(my-bp.y)); pnDraw(); }
+
+void IMSizePen(){
+ IModeProcs(pnUpMv,nop,eraseFB, nop, pnDnMv, nop,eraseFB, szSet);
+ }
+
+SizeAirOrPen() {
+ NewIMode(IM_sizePen);
+ svDispCoords = dispCoords;
+ dispCoords = NO;
+ JamCursor(SIZECURSOR);
+ killMode = &ClearXY;
+ UndoSave();
+ }
+
+SizePen(pn) SHORT pn; {
+ CPChgPen(pn);
+ sizingAirB = NO;
+ if ((pn==0)||(pn==USERBRUSH)) pnType = ROUND_B;
+ else pnType = (pn>>12)&15;
+ siz = MAX(pn&0xfff,1);
+ SizeAirOrPen();
+ }
+
+SHORT abRadius = INITABRADIUS;
+
+SizeAirBrush() {
+ svABMode = paintMode;
+ svPen = curpen;
+ siz = PMapY(abRadius);
+ pnType = ROUND_B;
+ sizingAirB = YES;
+ SizeAirOrPen();
+ }
+
+/* == Specify Fill Pattern ======================================*/
+#ifdef dothis
+void fpSet() {
+ }
+
+void showFPBox() {
+ Box b;
+ mFrame(MakeBox(&b, mx - PATWIDE + 1, my - PATHIGH + 1, PATWIDE, PATHIGH));
+ }
+
+void IMGetFPat(){
+ xorit = showFPBox;
+ IModeProcs(FlipIt,nop,FlipIt, nop, FlipIt, nop,FlipIt, fpSet);
+ }
+#endif
+
+void IMGetFPat(){}
+
+/* =============================================================*/
+
+extern BOOL modeHelp;
+
+UserBr() {CPChgPen(USERBRUSH);
+ RestoreBrush();
+ SetModeMenu(Mask);
+ NewIMode(IM_shade);
+ }
+
+
+
+
+
+
diff --git a/MOUSEBUT.C b/MOUSEBUT.C
new file mode 100644
index 0000000..8a9eba7
--- /dev/null
+++ b/MOUSEBUT.C
@@ -0,0 +1,20 @@
+/*----------------------------------------------------------------------*/
+/* */
+/* MouseBut.c */
+/* */
+/*----------------------------------------------------------------------*/
+
+#include <exec\types.h>
+#include <hardware\cia.h>
+#include <hardware\custom.h>
+
+extern struct Custom custom;
+extern struct CIA ciaa;
+
+SHORT MouseBut() {
+ register SHORT v = 0;
+ if ( (ciaa.ciapra & 0x40) == 0) v |= 1;
+ if ( (custom.potinp & 0x400) == 0) v |= 2;
+ return(v);
+ }
+
diff --git a/PACKER.H b/PACKER.H
new file mode 100644
index 0000000..41dd404
--- /dev/null
+++ b/PACKER.H
@@ -0,0 +1,36 @@
+#ifndef PACKER_H
+#define PACKER_H
+/*----------------------------------------------------------------------*/
+/* PACKER.H typedefs for Data-Compresser. 8/30/85 */
+/*----------------------------------------------------------------------*/
+#ifndef EXEC_TYPES_H
+#include "exec/types.h"
+#endif
+
+typedef enum {cmpNone = 0, cmpByteRun1 = 1} _Compression;
+typedef UBYTE Compression;
+ /* Choice of compression algorithm applied to the rows of all */
+ /* source and mask planes. "cmpByteRun1" is the byte run encoding */
+ /* generated by Mac's PackBits. Do not compress across rows! */
+
+/* Converts data to packed format "cmpByteRun1".*/
+extern LONG Packer(BYTE *, BYTE *, LONG, LONG);
+ /* source, destination, size in bytes, row size */
+ /* RETURNs packed size in bytes */
+ /* Assumes buffer is same size as source. In theory, could
+ get a data pattern that expands rather than compressing.
+ Will run off the end of your buffer in that case.*/
+
+/* Given POINTERS TO POINTERS, packs one row, updating the source and
+ destination pointers. */
+extern PackRow(BYTE **, BYTE **, LONG);
+ /* pSource, pDest, rowSize */
+
+/* Unpacks from format "cmpByteRun1".*/
+extern LONG Unpacker(BYTE *, BYTE *, LONG, LONG);
+ /* source, destination, packedSize, bufferLimit */
+ /* RETURNs actual unpacked size */
+ /* If reachs buffer's end, stops there and returns its
+ size as "unpacked size". */
+
+#endif
diff --git a/PACKERF.C b/PACKERF.C
new file mode 100644
index 0000000..50585be
--- /dev/null
+++ b/PACKERF.C
@@ -0,0 +1,111 @@
+/*----------------------------------------------------------------------*/
+/* packer.c Convert data to "cmpByteRun1" run compression. 11/06/85 */
+/* */
+/* By Jerry Morrison and Steve Shaw, Electronic Arts. */
+/* This software is in the public domain. */
+/* */
+/* control bytes: */
+/* [0..127] : followed by n+1 bytes of data. */
+/* [-1..-127] : followed by byte to be repeated (-n)+1 times */
+/* -128 : NOOP. */
+/*----------------------------------------------------------------------*/
+#include "iff\packer.h"
+
+#define DUMP 0
+#define RUN 1
+
+#define MinRun 3
+#define MaxRun 128
+#define MaxDat 128
+
+LONG putSize;
+#define GetByte() (*source++)
+#define PutByte(c) { *dest++ = (c); ++putSize; }
+
+char buf[256]; /* [TBD] should be 128? on stack?*/
+
+BYTE *PutDump(dest, nn) BYTE *dest; int nn; {
+ PutByte(nn-1);
+ CopyMem(buf,dest,nn);
+ putSize += nn;
+ return(dest += nn);
+ }
+
+BYTE *PutRun(dest, nn, cc) BYTE *dest; int nn, cc; {
+ PutByte(-(nn-1));
+ PutByte(cc);
+ return(dest);
+ }
+
+
+#define OutDump(nn) dest = PutDump(dest, nn)
+#define OutRun(nn,cc) dest = PutRun(dest, nn, cc)
+
+/*----------- PackRow --------------------------------------------------*/
+/* Given POINTERS TO POINTERS, packs one row, updating the source and
+ destination pointers. RETURNs count of packed bytes.*/
+LONG PackRow(pSource, pDest, rowSize)
+ BYTE **pSource, **pDest; LONG rowSize; {
+ register BYTE *source, *dest;
+ register char c,lastc = '\0';
+ BOOL mode = DUMP;
+ register short nbuf = 0; /* number of chars in buffer */
+ register short rstart = 0; /* buffer index current run starts */
+
+ source = *pSource;
+ dest = *pDest;
+ putSize = 0;
+ buf[0] = lastc = c = GetByte(); /* so have valid lastc */
+ nbuf = 1; rowSize--; /* since one byte eaten.*/
+
+ for (; rowSize; --rowSize) {
+ buf[nbuf++] = c = GetByte();
+ if (mode) { /* mode == RUN */
+ if ( (c != lastc)|| ( nbuf-rstart > MaxRun)) {
+ /* output run */
+ /* OutRun(nbuf-1-rstart,lastc) */
+ PutByte(rstart-nbuf+2);
+ PutByte(lastc);
+ buf[0] = c;
+ nbuf = 1; rstart = 0;
+ mode = DUMP;
+ }
+ }
+ else { /* mode == DUMP */
+ /* If the buffer is full, write the length byte,
+ then the data */
+ if (nbuf>MaxDat) {
+ OutDump(nbuf-1);
+ buf[0] = c;
+ nbuf = 1; rstart = 0;
+ }
+ else {
+ if (c == lastc) {
+ if (nbuf-rstart >= MinRun) {
+ if (rstart > 0) { /* OutDump(rstart) */
+ PutByte(rstart-1);
+ CopyMem(buf,dest,rstart);
+ putSize += rstart;
+ dest += rstart;
+ }
+ mode = RUN;
+ }
+ else if (rstart == 0) mode = RUN; /* no dump in progress,
+ so can't lose by making these 2 a run.*/
+ }
+ else rstart = nbuf-1; /* first of run */
+ }
+ }
+
+ lastc = c;
+ }
+
+ switch (mode) {
+ case DUMP: OutDump(nbuf); break;
+ case RUN: OutRun(nbuf-rstart,lastc); break;
+ }
+ *pSource = source;
+ *pDest = dest;
+ return(putSize);
+ }
+
diff --git a/PAINTW.C b/PAINTW.C
new file mode 100644
index 0000000..8d671f9
--- /dev/null
+++ b/PAINTW.C
@@ -0,0 +1,428 @@
+/*-------------------------------------------------------------------*/
+/* paintw -- Painting Window */
+/*-------------------------------------------------------------------*/
+
+#include <system.h>
+#include <prism.h>
+#include <pnts.h>
+
+#define local
+#define UP 0
+#define DN 1
+
+extern Pane mainP,magP;
+extern BOOL ShiftKey, Ctrl;
+extern SHORT dbgpane;
+extern SHORT curxpc;
+extern BOOL titleShowing, abortFlag;
+extern SHORT npts;
+
+BOOL firstDown = YES; /* for modes that need to know its the
+ first call on a button down drag (like blend & smear)
+ or in a LineWith etc */
+BOOL dispCoords= NO;
+BOOL goToPerm = NO;/* for falling out of extended modes like poly*/
+void nada() {}
+void (*nop)() = &nada;
+
+/* the following 8 proc vars are plugged to install a mode */
+local void (*upShow)(),(*upMove)(),(*upClear)(),(*WentDn)();
+local void (*dnShow)(),(*dnMove)(),(*dnClear)(),(*WentUp)();
+
+/* state of program */
+PointRec pnts; /* contains mx,my,sx,sy,etc */
+SHORT nx,ny;
+SHORT butwas=0, button=0;
+void (*killMode)() = &nada;
+void (*completeMode)() = &nada;
+local BOOL gridded=NO;
+local BOOL fbOn = NO;
+local BOOL updn = UP;
+local BOOL inside = NO;
+SHORT gridOrgX = 0;
+SHORT gridOrgY = 0;
+SHORT gridx=8;
+SHORT gridy=8;
+SHORT gridx2=4;
+SHORT gridy2=4;
+BOOL gridON = NO;
+BOOL wasShift = NO;
+BOOL wasCtrl = NO;
+
+BOOL everyTime = NO;
+SHORT curbgcol=0;
+
+/* IMode state */
+SHORT lastPermMode= IM_none, curIMode=IM_none;
+UWORD curIMFlags= 0;
+IModeDesc *curIMDesc = NULL;
+
+SetGridXY(gx,gy) SHORT gx,gy; {
+ gx = MAX(1,gx); gy= MAX(1,gy);
+ gridx = gx; gridy = gy;
+ gridx2 = gx/2; gridy2=gy/2;
+ }
+
+SetGridOrg(ox,oy) SHORT ox,oy; {
+ gridOrgX = ox;
+ gridOrgY = oy;
+ }
+
+SetGridSt(g) BOOL g; { if (gridON!=g) TogGridSt(); }
+TogGridSt() { gridON = !gridON; CPInvAct(gridAct); }
+
+Gridify(x,y) SHORT *x,*y;{
+ SHORT rx,ry;
+ if (gridded&gridON) {
+ rx = *x - gridOrgX + gridx2;
+ if (rx<0) rx -= gridx;
+ *x = gridOrgX + (rx/gridx)*gridx;
+ ry = *y - gridOrgY + gridy2;
+ if (ry<0) ry -= gridy;
+ *y = gridOrgY + (ry/gridy)*gridy;
+ }
+/* MWClipPt(x,y,gridx,gridy); */
+ }
+
+nxtpoint() {lx = mx; ly = my; mx = nx; my = ny; }
+
+/*--- XOR Feedback to tell the user what's happening under symmetry */
+extern BOOL symON;
+extern SHORT usePen;
+short symcount = 0;
+
+void symsplat() { if (++symcount>1) mDispOB(mx,my); }
+
+SymShowOb(upOrDn) WORD upOrDn; {
+ SHORT saveUsePen;
+ if ((curIMFlags&upOrDn)&&(symON)) {
+ TempXOR();
+ saveUsePen = usePen;
+ if (curIMFlags&NOBR) usePen = 0;
+ symcount = 0;
+ DisableAbort();
+ SymDo(1,&pnts,symsplat);
+ EnableAbort();
+ usePen = saveUsePen;
+ RestoreMode();
+ }
+ }
+
+void ShowFB(){ if (fbOn||(!inside)) return;
+ if (updn==UP) { (*upShow)(); SymShowOb(SYMUP);}
+ else { (*dnShow)(); SymShowOb(SYMDN);}
+ fbOn = YES;
+ }
+
+void ClearFB(){ if (!fbOn) return;
+ if (updn==UP) { SymShowOb(SYMUP); (*upClear)(); }
+ else { SymShowOb(SYMDN); (*dnClear)(); }
+ fbOn = NO;
+ }
+
+local EnterW(pn,x,y) Pane *pn; SHORT x,y; {
+ inside = YES;
+ LoadIMode();
+ ResetCursor();
+ SetCurWin(pn);
+ nx = x; ny = y; /* have to recompute coords for new window */
+ MagCoords(&nx,&ny);
+ Gridify(&nx,&ny);
+ updn = button;
+ nxtpoint();
+ nxtpoint();
+ sx = mx; sy = my;
+ ShowFB();
+ }
+
+local LeaveW(pn,x,y) Pane *pn; {
+ ClearFB();
+ SetCursor(DEFCURSOR);
+ inside = FALSE;
+ }
+
+local TrackUp() {
+ if (!fbOn) { nxtpoint(); ShowFB(); }
+ else if ((nx!=mx)||(ny!=my)||everyTime) {
+ SymShowOb(SYMUP);
+ if (upMove!=nop) { nxtpoint(); (*upMove)(); }
+ else { (*upClear)(); nxtpoint(); (*upShow)(); }
+ SymShowOb(SYMUP);
+ }
+ }
+
+SetEveryTime() {
+ everyTime = YES;
+ mainP.flags |= ALWAYS;
+ magP.flags |= ALWAYS;
+ }
+
+ClrEveryTime() {
+ everyTime = NO;
+ mainP.flags &= ~ALWAYS;
+ magP.flags &= ~ALWAYS;
+ }
+
+local GoDown() {
+ ClearFB();
+ updn = DN;
+ FixUsePen();
+ butwas = button;
+
+ wasShift = ShiftKey;
+ wasCtrl = Ctrl;
+ nxtpoint();
+ sx = mx; sy = my;
+ if ((button==2)&&((NOERASE&curIMFlags) == 0)) TempErase();
+ UndoSave();
+ firstDown = YES;
+ if (curIMFlags&EVTIM) SetEveryTime();
+ if (curIMFlags&PNTWDN) UpdtON();
+ (*WentDn)();
+ ShowFB();
+ }
+
+local TrackDown() {
+ if (!fbOn) { nxtpoint(); ShowFB(); }
+ else if (((nx!=mx)||(ny!=my))||everyTime) {
+ SymShowOb(SYMDN);
+ if (dnMove!=nop) { nxtpoint(); (*dnMove)(); }
+ else { (*dnClear)(); nxtpoint(); (*dnShow)(); }
+ SymShowOb(SYMDN);
+ }
+ }
+
+void GoUp() {
+ ClrEveryTime();
+ ClearFB();
+ updn = UP;
+ ex = mx; ey = my;
+ (*WentUp)();
+ UpdtOFF();
+ ClearErase();
+ EndCycPaint(); /* this updates ctr panel if color changed*/
+ BMOBFreeTmp(); /* in case smear was going */
+ psx = sx; psy = sy;
+ pex = ex; pey = ey;
+ NextIMode();
+ ShowFB();
+ }
+
+/*----------------------------------------------------------------------*/
+/* Interaction Modes */
+/*----------------------------------------------------------------------*/
+
+extern void IMNull(), IMShade(), IMDraw(), IMVect(), IMCurve1(), IMCurve2();
+extern void IMRect(), IMFRect(), IMCirc(), IMFCirc(), IMOval(), IMFOval();
+extern void IMSelBrush(), IMMagSpec(), IMFill(), IMText1(), IMText2();
+extern void IMGridSpec(), IMReadPix(), IMStrBrush(), IMSymCent();
+extern void IMRotBrush(), IMShrBrush(), IMSizePen();
+extern void IMPoly(), IMPoly2(), IMFPoly(), IMFPoly2(), IMAirBrush();
+extern void IMGetFPat(), IMHBendBrush(),IMVBendBrush();
+
+#if 0
+typedef UBYTE IMode;
+typedef struct {
+ WORD flags; /* see below */
+ UBYTE cursor; /* what cursor to use */
+ UBYTE activity; /* ctr panel activity for this imode */
+ UBYTE symNpoints; /* number of points to be transformed*/
+ IMode nextIMode; /* for chaining */
+ void (*startProc)(); /* call this to plug mode procs*/
+ } IModeDesc;
+#endif
+
+/* Master IMODE table */
+
+IModeDesc imodes[NIMODES] = {
+/*-- Flags, cursor, activity, nextIMode, startProc -------*/
+ { NOLOCK|NOSYM|NOBR, DEFC, nullAct,1,IM_none, &IMNull}, /* IM_null */
+ { PERM|SYMUP|PNTWDN, DEFC, shadeAct,1, IM_none, &IMShade}, /* IM_shade */
+ { PERM|NOGR|SYMUP|PNTWDN, DEFC, drawAct,2, IM_none, &IMDraw}, /* IM_draw */
+ { PERM|SYMALL, DEFC, vectAct, 3, IM_none, &IMVect}, /* IM_vect */
+ { PERM|SYMALL, DEFC, curvAct, 3, IM_curve2, &IMCurve1}, /* IM_curve1 */
+ { SLAVE, DEFC, curvAct, 6, IM_none, &IMCurve2}, /* IM_curve2 */
+ { NOCON|SYMALL, DEFC, rectAct, 3, IM_none, &IMRect}, /* IM_rect */
+ { NOCON|NOBR|SYMALL, DEFC, frectAct, 3, IM_none, &IMFRect}, /* IM_frect */
+ { SYMALL, DEFC, circAct, 3, IM_none, &IMCirc}, /* IM_circ */
+ { NOBR|SYMALL, DEFC, fcircAct, 3, IM_none, &IMFCirc}, /* IM_fcirc */
+ { SYMALL, DEFC, ovalAct, 3, IM_none, &IMOval}, /* IM_oval */
+ { NOBR|SYMALL, DEFC, fovalAct, 3, IM_none, &IMFOval}, /* IM_foval */
+ { NOSYM|NOLOCK, DEFC, selbAct, 1, IM_none, &IMSelBrush}, /* IM_selBrush */
+ { NOBR|NOGR|NOSYM|NOLOCK, DEFC, nullAct, 1, IM_none, &IMMagSpec},/* IM_magSpec */
+ { NOBR|NOGR|SYMALL, FILLCURSOR, fillAct, 1, IM_none, &IMFill}, /* IM_fill */
+ { NOLOCK|NOBR|NOSYM, DEFC, textAct, 1, IM_text2, &IMText1}, /* IM_text1 */
+ { NOBR|NOSYM|SLAVE, DEFC, textAct, 1, IM_text2, &IMText2}, /* IM_text2 */
+ { NOBR|NOGR|NOSYM|NOLOCK, DEFC, nullAct, 1, IM_none, &IMGridSpec}, /* IM_gridSpec */
+ { NOBR|NOSYM|NOLOCK, DEFC, nullAct, 1, IM_none, &IMSymCent}, /* IM_symCent */
+ { NOBR|NOGR|NOSYM|NOLOCK, PICKCURSOR, nullAct,1,IM_none, &IMReadPix},/* IM_readPix */
+ { NOCON|NOSYM|NOLOCK, SIZECURSOR, nullAct, 1, IM_none, &IMStrBrush}, /* IM_strBrush */
+ { NOGR|NOSYM|NOLOCK, DEFC, nullAct, 1, IM_none, &IMRotBrush}, /* IM_rotBrush */
+ { NOSYM|NOLOCK, DEFC, nullAct, 1, IM_none, &IMShrBrush}, /* IM_shrBrush */
+ { NOERASE|NOSYM|NOGR|NOLOCK,SIZECURSOR, nullAct, 1, IM_none, &IMSizePen}, /* IM_sizePen */
+ { SYMALL,DEFC, polyAct, 6, IM_poly2, &IMPoly}, /* IM_poly */
+ { SYMALL|SLAVE,DEFC, polyAct, 6, IM_poly2, &IMPoly2}, /* IM_poly2 */
+ { NOBR|SYMALL,DEFC, fpolyAct, 6, IM_fpoly2, &IMFPoly}, /* IM_fpoly */
+ { COMPLETE|NOBR|SYMALL|SLAVE,DEFC, fpolyAct, 6, IM_fpoly2, &IMFPoly2}, /* IM_fpoly2 */
+ { PERM|SYMUP|NOGR|PNTWDN|EVTIM, DEFC, airbAct, 1, IM_none, &IMAirBrush}, /* IM_airBrush */
+ { NOSYM|NOBR, DEFC, nullAct, 1, IM_none, &IMGetFPat}, /* IM_getFPat */
+ { NOGR|NOSYM|NOLOCK, DEFC, nullAct, 1, IM_none, &IMHBendBrush},/* IM_hbendBrush */
+ { NOGR|NOSYM|NOLOCK, DEFC, nullAct, 1, IM_none, &IMVBendBrush} /* IM_vbendBrush */
+ };
+
+BOOL allPerm = YES;
+
+BOOL fastFB = NO;
+SHORT usePen = 0;
+extern SHORT curpen;
+extern BOOL Painting;
+
+SetUsePen(p) SHORT p; { usePen = p; }
+
+/* if we arent updating the drawing, in fast feedback mode, if the
+button is down or this is a no brush or slave mode use the 1 dot pen*/
+FixUsePen() {
+ usePen = curpen;
+ if (!Painting && fastFB)
+ if ((updn==DN) || (curIMFlags&(NOBR|SLAVE))) usePen = 0;
+ }
+
+/* Call this to change mode */
+
+void NewIMode(im) IMode im; {
+ if (im==IM_none) return;
+ abortFlag = NO;
+ everyTime = NO;
+ (*killMode)();
+ curIMDesc = &imodes[im];
+ curIMFlags = curIMDesc->flags;
+ if (!(curIMFlags&SLAVE)) { /* a "master" mode */
+ if ( (curIMFlags&PERM)||
+ ( ((im==curIMode)||allPerm) && (!(curIMFlags&NOLOCK)) ) )
+ lastPermMode = im; /* lock this mode in */
+ }
+ curIMFlags &= (~RIGHTBUT);
+ gridded = ((curIMFlags&NOGR) == 0);
+ npts = curIMDesc->symNpoints;
+ completeMode = killMode = upShow = upMove = upClear = WentDn= nop;
+ dnShow = dnMove = dnClear = WentUp = nop;
+ curIMode = im;
+ if (curIMDesc->cursor==DEFC) DefaultPaintCursor();
+ else SetPaintCursor(curIMDesc->cursor);
+ CPChgAct(curIMDesc->activity);
+ FixUsePen();
+ (*curIMDesc->startProc)(NO);
+ }
+/* start proc called only these 2 places,above and --*/
+LoadIMode() { (*curIMDesc->startProc)(YES); }
+
+RevertIMode() { NewIMode(lastPermMode); }
+
+
+/* this is called after button up, to go to next mode. */
+NextIMode() {
+ IMode next = curIMDesc->nextIMode;
+ killMode = nop;
+ if ((!goToPerm)&&(next!=IM_none)) NewIMode(next);
+ else { goToPerm = NO; RevertIMode();}
+ }
+
+void NewButIMode(im,but) IMode im; short but; {
+ NewIMode(im);
+ if (but==2) curIMFlags |= RIGHTBUT; else curIMFlags &= (~RIGHTBUT);
+ }
+
+AbortIMode() {
+ abortFlag = NO;
+ if (MouseBut()) NewIMode(IM_null);
+ else {
+ if (curIMFlags&COMPLETE) {
+ (*completeMode)(); /* hack for fill poly */
+ completeMode = &nada;
+ }
+ else { (*killMode)(); goToPerm = YES;}
+ NextIMode();
+ }
+ }
+
+/* This is typically to set up a mode from within the button down or up
+ proc of the current mode */
+
+SetNextIMode(m) IMode m; { lastPermMode = m; }
+
+/* This is typically called by the start proc to stuff procs */
+/* They all default to "nop" so only the necessary ones need
+ be stuffed */
+
+IModeProcs(upSh,upMv,upCl,wdn,dnSh,dnMv,dnCl,wup)
+ void (*upSh)(),(*upMv)(),(*upCl)(),(*wdn)(),
+ (*dnSh)(),(*dnMv)(),(*dnCl)(),(*wup)(); {
+ upShow = upSh; upMove = upMv; upClear = upCl; WentDn= wdn;
+ dnShow = dnSh; dnMove = dnMv; dnClear = dnCl; WentUp= wup;
+ }
+
+local void (*periodicCall)() = NULL;
+SetPeriodicCall(proc) void (*proc)(); { periodicCall = proc; }
+
+#define CONS_NOT 0
+#define CONS_INIT 1
+#define CONS_HORIZ 2
+#define CONS_VERT 3
+
+SHORT conStartX, conStartY;
+SHORT consState = CONS_NOT;
+
+void Constrain(px,py) SHORT *px,*py; {
+ SHORT dx,dy;
+ if (curIMFlags&NOCON) { consState= CONS_NOT; return; }
+ switch(consState) {
+ case CONS_NOT: if (ShiftKey) {
+ conStartX = *px;
+ conStartY = *py;
+ consState = CONS_INIT;
+ }
+ break;
+ case CONS_INIT:
+ dx = *px - conStartX;
+ dy = *py - conStartY;
+ if ((dx!=0)||(dy!=0)){
+ if (dx==0) consState = CONS_VERT;
+ else if (dy==0) consState = CONS_HORIZ;
+ else consState = CONS_NOT;
+ }
+ break;
+ default:
+ if (!ShiftKey) consState = CONS_NOT;
+ else switch(consState) {
+ case CONS_HORIZ: *py = conStartY; break;
+ case CONS_VERT: *px = conStartX; break;
+ }
+ break;
+ }
+ }
+
+Point nogrid;
+
+/* ------------------------------------------*/
+mainMproc(pn,why,but,x,y) Pane *pn; MouseEvent why; SHORT but,x,y; {
+ nx = x;
+ ny = y;
+ button = but;
+ MagCoords(&nx,&ny); /* convert to backing bitmap coords */
+ nogrid.x = nx;
+ nogrid.y = ny;
+ Gridify(&nx,&ny); /* constrain to grid */
+ Constrain(&nx,&ny);
+ if (dispCoords&&titleShowing) if (updn==DN) DispXY(nx-sx,ny-sy);
+ else DispXY(nx,ny);
+ switch(why) {
+ case ENTER: EnterW(pn,x,y); break;
+ case LOOPED:
+ case MOVED: if (but) TrackDown(); else TrackUp();break;
+ case BDOWN: GoDown(); break;
+ case BUP: GoUp(); break;
+ case LEAVE: LeaveW(pn,x,y); break;
+ }
+ if (periodicCall) (*periodicCall)();
+ }
+
diff --git a/PALBMS.C b/PALBMS.C
new file mode 100644
index 0000000..46182aa
--- /dev/null
+++ b/PALBMS.C
@@ -0,0 +1,41 @@
+/*----------------------------------------------------------------------*/
+/* */
+/* palbms.c -- Bitmaps for palette requestor arrows */
+/* */
+/*----------------------------------------------------------------------*/
+#include "system.h"
+
+#define STICKY_HEIGHT 18
+#define STICKY_HOT_X 1
+#define STICKY_HOT_Y 1
+
+/* Arrow plus letters "to". Cursor during sticky modes.*/
+UWORD stickyPointer[STICKY_HEIGHT*2+4] = {
+ 0x0000, 0x0000, /* position and control info*/
+ 0x0, 0x7C00, 0x7C00, 0xFE00,
+ 0x7C00, 0x8600, 0x7800, 0x8C00,
+ 0x7C00, 0x8600, 0x6E00, 0x9300,
+ 0x700, 0x6980, 0x380, 0x4C0,
+ 0x1C0, 0x260, 0x80, 0x140,
+ 0x0, 0x80, 0x0, 0x7E38,
+ 0x7E38, 0x8144, 0x186C, 0x6692,
+ 0x1844, 0x24AA, 0x186C, 0x2492,
+ 0x1838, 0x2444, 0x0, 0x1838,
+ 0xFFFF, 0xFFFF /* end markers */
+ };
+
+UWORD diamond[5] = {
+ 0x2000, /* first plane of image */
+ 0x7000,
+ 0xf800,
+ 0x7000,
+ 0x2000 }; /* forms a diamond pointer */
+
+UWORD diamond2[5] = {
+ 0x0800, /* first plane of image */
+ 0x3e00,
+ 0xff80,
+ 0x3e00,
+ 0x0800 }; /* forms a wider diamond pointer */
+
+
diff --git a/PALETTE.C b/PALETTE.C
new file mode 100644
index 0000000..e0abec1
--- /dev/null
+++ b/PALETTE.C
@@ -0,0 +1,1336 @@
+/*----------------------------------------------------------------------*/
+/* Palette.c: A window used for modifying a color palette. */
+/* Usage: error = PaletteTool(struct Window *, PaletteGlobals *); */
+/* Returns 0 if window moved; client should call again. */
+/* Returns -1 if couldn't allocate enough RAM. */
+/* */
+/* 8/28/85 Gordon Knopes Created. */
+/* 11/02/85 Steve Shaw New layout; many internal changes; less */
+/* static RAM; added Spread,Copy,Range,Cancel. */
+/*----------------------------------------------------------------------*/
+#include "system.h"
+
+extern struct Window *OpenWindow();
+extern struct IntuiMessage *GetMsg();
+extern SHORT AddGadget();
+extern void RefreshGadgets(),
+ ReplyMsg(),
+ SetRGB4(),
+ CloseWindow(),
+ SetRast();
+
+#define local /*TBD*/ static /**/
+
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#define ABS(a) ((a) >= 0 ? (a) : -(a))
+
+#define ALLOC(n) AllocMem(n, MEMF_PUBLIC | MEMF_CLEAR)
+#define FREE(addr, n) if (addr) FreeMem(addr, n)
+#define DEPTH 5
+
+#define LIM_SLIDERS 7 /* Includes SPEED */
+#define MODIFYRED 0
+#define MODIFYGREEN 1
+#define MODIFYBLUE 2
+#define MODIFYHUE 3
+#define MODIFYSATURATION 4
+#define MODIFYVALUE 5
+#define MODIFYSPEED 6
+
+#define LIM_COLORS 32
+
+#define LIM_RANGES 4 /* 4 cycle-ranges */
+#define SH_RANGE 0 /* Shade Paint */
+#define C1_RANGE 1 /* Color Cycle 1 */
+#define C2_RANGE 2 /* Color Cycle 2 */
+#define C3_RANGE 3 /* Color Cycle 3 */
+
+#define trans(val) (val * (SH - 8))
+#define inRange(a,low,width) ( ((a) >= (low)) && ((a) < (low+width)) )
+
+ /* starting gadget number for gadget id's */
+
+#define COLORGADGETS 0x10 /* Leave a few lower ids available. Why? */
+#define SLIDERGADGETS (COLORGADGETS + LIM_COLORS)
+#define CANCEL_GADGET (SLIDERGADGETS + LIM_SLIDERS)
+#define OK_GADGET (CANCEL_GADGET + 1)
+#define SPREAD_GADGET (OK_GADGET + 1)
+#define COPY_GADGET (OK_GADGET + 2)
+#define RANGE_GADGET (OK_GADGET + 3)
+#define MIX_GADGET (OK_GADGET + 4)
+#define EXCHANGE_GADGET (OK_GADGET + 5)
+#define UNDO_GADGET (OK_GADGET + 6)
+#define RANGE_GADGETS (UNDO_GADGET + 1)
+#define LIM_GADGETS (RANGE_GADGETS + LIM_RANGES) /* End of gadget list.*/
+
+
+#define TXHEIGHT 8
+
+#define RSCALE (TXHEIGHT + 2)
+#define TWSCALE (TXHEIGHT + 1) /* Width per character */
+#define THSCALE (TXHEIGHT + 4) /* Height per boxed character */
+
+#define SXRGB (15)
+#define SXHSV (SXRGB + 2)
+#define SY (RSCALE + 9)
+#define SH (60+10)
+#define SDX 12 /* Separation between sliders.*/
+
+local int sdx = SDX;
+local int sw = SDX;
+
+#define IDCMPFLAGS GADGETUP | GADGETDOWN | MOUSEBUTTONS | RAWKEY
+ /* "MOUSEBUTTONS" to do DrawWhich on window reentry when button in limbo.*/
+ /* "RAWKEY" so can do "u" undo-key.*/
+#define UCODE 0x16 /* RAWKEY for the letter "u".*/
+#define DOWNFLAG 0x80 /* Down-transition of a key.*/
+
+#define PX (SXRGB + 6 * SDX + 6) /* Palette's X,Y,W,H */
+#define PY (RSCALE + 13)
+#define PW 10
+#define PH 8
+#define PHs 8 /* # color squares per column. (Numbered from the top.) */
+#define PWs 4 /* # color squares per row. */
+
+#define OKFLAGS GADGHCOMP, RELVERIFY | ENDGADGET, BOOLGADGET
+#define DFFLAGS GADGHCOMP, RELVERIFY, BOOLGADGET
+#define STICKY_FLAGS GADGHCOMP, RELVERIFY, BOOLGADGET
+
+#define COMX 5 /* Command Area's X,Y,H */
+#define COMY (PY + PHs * PH + 4)
+#define COMH (4 * THSCALE + 6)
+
+#define RW (PX + PWs * PW + 4) /* Requestor Window's Width */
+#define RH (COMY + COMH) /* Requestor Window's Height */
+
+#define OKX (RW - 3 * TWSCALE + 4)
+#define OKY (COMY + 3 * THSCALE + 5)
+#define OKH (RSCALE-1)
+
+#define CANCELX COMX
+#define UNDOX (CANCELX + 7 * TWSCALE - 2)
+
+#define COPYX (OKX - 2 * TWSCALE)
+#define EXCHANGEX (COPYX - 2 * TWSCALE - 2)
+#define SPREADX (COMX + TWSCALE)
+#define SPREADY COMY
+#define SPREADW (6 * TWSCALE)
+
+#define RANGEX COMX
+#define RANGEY (COMY + 1 * THSCALE + 3)
+#define SHADEX (COMX + 6 * TWSCALE - 4)
+#define CYCLE1X (COMX + 8 * TWSCALE - 2)
+#define CYCLE2X (COMX + 10 * TWSCALE + 0)
+#define CYCLE3X (COMX + 12 * TWSCALE + 2)
+#define RANGEW (2 * TWSCALE)
+
+#define SPEEDX (COMX + 10)
+#define SPEEDY (COMY + 2 * THSCALE + 3)
+
+#define TXRGB (SXRGB + 3)
+#define TXHSV (SXHSV + 3)
+#define TY (RSCALE + 2)
+
+
+#define MAXINT 0x7fff
+#define SCLEXP 8
+/* normalize factor = 256 */
+
+#define MAXRGB 15
+#define MAXHSV 255 /* From "rgb2hsv()".*/
+#define MAXH 63 /*WANTED: 89*/
+#define MAXSV 15
+#define MAXSP 63
+
+#define RGBBODY (MAXBODY / MAXRGB)
+#define SVBODY (MAXBODY / MAXSV)
+#define HBODY (MAXBODY / MAXH)
+#define SPEED_BODY (MAXBODY / MAXSP)
+
+#define UNDEFINED -1
+
+typedef struct {
+ SHORT r, g, b;
+ } RGB;
+
+typedef struct {
+ SHORT h, s, v;
+ } HSV;
+
+/* ---------- Color Ranges -------------------------------------------------*/
+typedef struct {
+ SHORT count;
+ SHORT rate;
+ BOOL active;
+ UBYTE low,high; /* upper and lower bounds of range */
+ } Range;
+
+local Range originalRanges[LIM_RANGES] = { 0 };
+ /* Local copy of pGlobals->ranges[0]..[LIM_RANGES-1] */
+local Range *ranges = NULL; /* pGlobals->ranges.*/
+local Range *range = NULL; /* points to current Range w/i "ranges".*/
+
+/* --------- Globals preserved across invocations, provided by client ----- */
+typedef struct {
+ WORD paletteX, paletteY;
+ /* LeftEdge,TopEdge for palette window.
+ * Client can change these to force window to appear elsewhere.
+ * If user drags window, these are updated before return to client.*/
+ WORD paletteRange; /* Index of range currently examined.*/
+ Range *ranges; /* LIM_RANGES Range's */
+ } PaletteGlobals;
+
+local PaletteGlobals *pGlobals = NULL;
+
+#define PALETTE_X pGlobals->paletteX
+#define PALETTE_Y pGlobals->paletteY
+#define PALETTE_RANGE pGlobals->paletteRange
+
+#define PANEL_WIDTH 25 /* Width of control strip on the right side.*/
+#define TITLE_HEIGHT 11 /* Height of title bar at top of screen.*/
+
+/* ---------- ------------ -------------------------------------------------*/
+/* there are LIM_SLIDERS porportional gadgets, one for the red, green, blue,
+ * hue, saturation, value, and speed.
+ *
+ * Each points to the same image data for rendering the gadget
+ */
+
+local struct Window *_wp = NULL;
+local struct Window *userwp = NULL;
+local struct RastPort *_rp = NULL;
+local struct RastPort *userrp = NULL;
+local SHORT depth = 0;
+local no_of_colors = 0;
+local maxColor = 0;
+
+local cx = 0, cy = 0; /* Coordinates of current color square in palette.*/
+
+local int isWide = FALSE; /* TRUE when 640 H.*/
+local int isTall = FALSE; /* TRUE when 400 V.*/
+local int px = PX;
+local int pw = PW;
+local int phs = PHs;
+
+typedef struct {
+ SHORT m[LIM_COLORS];
+ } ColorMap;
+local ColorMap *colorMapOriginal = NULL;
+local ColorMap *colorMapUndo = NULL;
+local ColorMap *colorMapNow = NULL;
+
+/* Hack to keep colors 0 and 1 from being too close together.*/
+/* These will quickly get set to the correct colors.*/
+local RGB c0 = {0x20,0x20,0x20}, c1 = {0x2f,0x2f,0x2f};
+local RGB undoC0 = {0x20,0x20,0x20}, undoC1 = {0x2f,0x2f,0x2f};
+#define MIN_MENU_INTENSITY 8 /* At least one of (r,g,b) must differ by this.*/
+
+local struct Gadget *colors = NULL;
+local struct Image *colorImages = NULL;
+
+
+#define TxWrite(rp, str) Text(rp, str, strlen(str))
+
+local struct TextAttr _TestFont = { "topaz.font", TXHEIGHT, 0, 0, };
+
+/* Specifies place and text.*/
+typedef struct {
+ WORD x, y;
+ char *body;
+ } PlacedText;
+
+#define LIM_DECOR_TEXT 15
+/* decorText: "decorative" text; that is, not part of any gadget; painted
+ * directly on the palette window.*/
+local PlacedText decorText[LIM_DECOR_TEXT] = {
+ { 2 * TWSCALE, 2, "Color Palette" },
+ { TXRGB, TY, "R" },
+ { TXRGB + SDX, TY, "G" },
+ { TXRGB + 2 * SDX, TY, "B", },
+ { TXHSV + 3 * SDX, TY, "H", },
+ { TXHSV + 4 * SDX, TY, "S", },
+ { TXHSV + 5 * SDX, TY, "V", },
+ { 1, SY, "1", },
+ { 7, SY, "5", },
+ { 5, SY + SH - 9, "0", },
+ { SPEEDX, SPEEDY, "SPEED:", },
+ { 5, SY + 45, "4", },
+ { 5, SY + 29, "8", },
+ { 1, SY + 12, "1", },
+ { 7, SY + 12, "2", } };
+
+#define LIM_COMMANDS 11 /* # Command Gadgets.*/
+#define COM_SHADE 3
+#define COM_SPREAD 7 /* offset for Command Spread.*/
+#define COM_EXCHANGE 8 /* must match mode's enumeration.*/
+#define COM_COPY 9
+#define COM_RANGE 10
+
+/* Some buttons put palette into a mode.*/
+#define MO_NORMAL 0
+#define MO_SPREAD 1
+#define MO_EXCHANGE 2
+#define MO_COPY 3
+#define MO_RANGE 4
+local int mode = MO_NORMAL;
+
+local char *gStrings[LIM_COMMANDS] = {
+ "OK", "CANCEL", "UNDO",
+ "SH", "C1", "C2", "C3",
+ "SPREAD", "Ex", "COPY", "RANGE:" };
+
+local struct IntuiText InitGText = {
+ 0,1,JAM1, 2,1, &_TestFont, NULL,NULL };
+
+/* gText stands for gadget text */
+local struct IntuiText *gText = NULL;
+
+
+#define STICKY_HEIGHT 18
+#define STICKY_HOT_X 1
+#define STICKY_HOT_Y 1
+
+/*------------ icon bitmaps are now in palbms.c */
+extern USHORT stickyPointer[],diamond[],diamond2[];
+
+local struct Image InitSliderImage = {
+ 0, 0, 5, 5, 1, &diamond[0], 0x1, 0 };
+/* left edge,top edge, width,height, depth, predrawn image, ppick,pponoff */
+
+local struct Image *sliderImages = NULL;
+
+local WORD sliderPIBody[LIM_SLIDERS] = {
+ RGBBODY, RGBBODY, RGBBODY, HBODY, SVBODY, SVBODY, SPEED_BODY };
+
+local struct PropInfo *sliderPI = NULL;
+
+/* Here is the gadget set for changing red, green, and blue components
+ * (can also vary hue, saturation, and value) of a currently selected color.
+ * Also speed. */
+#define SPEED_PROPX (SPEEDX + 6*TWSCALE - 10)
+local int speed_tickx = SPEED_PROPX;
+
+local struct Gadget *sliderGadgets = NULL;
+
+/* Command Gadget Initialize */
+#define CGadInit(x,y,w, flags, id) { NULL, x,y, w,OKH, \
+ flags, NULL,NULL, NULL, 0, \
+ NULL, id, NULL }
+/* next gadget, left,top, width,height of hitbox, */
+/* flags, BORDER,SELECT descriptor, text(later), mutual exclude, */
+/* special info, gadget's identifier for client, client data */
+
+local struct Gadget comGadgets[LIM_COMMANDS] = {
+ CGadInit(OKX, OKY, 2*TWSCALE, OKFLAGS, OK_GADGET),
+ CGadInit(CANCELX, OKY, 6*TWSCALE, OKFLAGS, CANCEL_GADGET),
+ CGadInit(UNDOX, OKY, 4*TWSCALE, DFFLAGS, UNDO_GADGET),
+ CGadInit(SHADEX, RANGEY, RANGEW, DFFLAGS, RANGE_GADGETS+0),
+ CGadInit(CYCLE1X, RANGEY, RANGEW, DFFLAGS, RANGE_GADGETS+1),
+ CGadInit(CYCLE2X, RANGEY, RANGEW, DFFLAGS, RANGE_GADGETS+2),
+ CGadInit(CYCLE3X, RANGEY, RANGEW, DFFLAGS, RANGE_GADGETS+3),
+ CGadInit(SPREADX, SPREADY,SPREADW, STICKY_FLAGS, SPREAD_GADGET),
+ CGadInit(EXCHANGEX,SPREADY,2*TWSCALE, STICKY_FLAGS, EXCHANGE_GADGET),
+ CGadInit(COPYX, SPREADY,4*TWSCALE, STICKY_FLAGS, COPY_GADGET),
+ CGadInit(RANGEX, RANGEY, 5*TWSCALE, STICKY_FLAGS, RANGE_GADGET) };
+
+local struct NewWindow newcolorwindow = {
+ 0, 0, /* start position (later) */
+ RW, RH, /* width, height */
+ 0, 1, /* detail pen, block pen */
+ /* IDCMP Flags:-----*/
+ IDCMPFLAGS,
+ /* Window Flags:----*/
+ BORDERLESS | ACTIVATE | WINDOWDRAG | RMBTRAP | NOCAREREFRESH,
+ NULL, /* pointer to first user gadget */
+ NULL, /* pointer to user checkmark */
+ " Color Palette ", /* window title */
+ NULL, /* pointer to screen (later) */
+ NULL, /* pointer to superbitmap */
+ 0,0,0,0, /* ignored/not a sized window so
+ * dont have to specify min/max
+ * size to allow */
+ CUSTOMSCREEN /* type of screen in which to open */
+ };
+
+local struct ViewPort *_vp = NULL;
+
+local SHORT color_being_modified = 2; /* Palette color #.*/
+local SHORT currentColor = 0; /* 4bits each r-g-b in ColorRegister format.*/
+local RGB rgb = { 0 }; /* for currentColor */
+local HSV hsv = { 0 };
+
+local USHORT _class = 0;
+local USHORT _code = 0;
+local USHORT _qualifier = 0;
+local USHORT _mode = 0;
+
+local SHORT _gadgetid = 0;
+
+local APTR _address = NULL;
+local APTR oldaddress = NULL;
+
+local testcode = 0;
+
+local struct IntuiMessage *_message = NULL;
+
+local void NoEvent() { _code = -1; _class = -1; _qualifier = -1; }
+
+local int waiting_for_gadget_up() {
+
+ _message = GetMsg(_wp->UserPort);
+ if (_message == NULL)
+ return(TRUE); /* Yes, still waiting for a mouse-up event.*/
+
+ _class = _message->Class;
+ ReplyMsg(_message);
+ return( _class != GADGETUP );
+ }
+
+/* ---------- LookColor --------------------------------------------------- */
+/* Set (cx,cy) to coordinates of color # id's square in the palette.*/
+local void LookColor(id) int id; {
+ cx = px + pw * (id / phs);
+ cy = PY + PH * (id % phs);
+ }
+
+/* ---------- Dash, HLine, Vline, DrawBox, DrawBoxAround, BoxText ---------*/
+/* Some routines to help DrawWhich, and other drawers.*/
+
+local int _y = 0;
+local void Dash(x, w) int x, w; { /* Draw a dash on the current line.*/
+ Move(_rp, x, _y);
+ Draw(_rp, x+w-1, _y);
+ }
+
+/* Draw a horizontal line.*/
+#define HLine(x,y, w) { _y = y; Dash(x, w); }
+
+local void VLine(x,y, h) int x,y, h; { /* Draw a vertical line.*/
+ Move(_rp, x, y);
+ Draw(_rp, x, y+h-1);
+ }
+
+local void DrawBox(x,y, w,h) int x,y, w,h; { /* Draw hollow box.*/
+ register int x2 = x+w-1;
+ register int y2 = y+h-1;
+
+ Move(_rp, x, y);
+ Draw(_rp, x2, y);
+ Draw(_rp, x2, y2);
+ Draw(_rp, x, y2);
+ Draw(_rp, x, y);
+ }
+
+local void DrawBoxAround(x,y, w,h) int x,y, w,h; { /* Draw box around item.*/
+ DrawBox(x-1,y-1, w+2,h+2);
+ }
+
+local void BoxText(x,y, w) int x,y, w; { /* Draw box around text.*/
+ DrawBoxAround(x,y, w,RSCALE-1);
+ }
+
+/* ---------- DrawRange --------------------------------------------------- */
+/* Four routines for drawing range-marker on palette.*/
+
+/* Bar to left of intermediate color in range.*/
+local void DrawInRange(id) int id; { LookColor(id); VLine(cx-1,cy,PH); }
+
+/* Angle to upper-left of low color in range.*/
+#define DrawLow(id) { DrawInRange(id); HLine(cx-1,cy-1,5); }
+
+/* Angle to lower-left of high color in range.*/
+#define DrawHigh(id) { DrawInRange(id); HLine(cx-1,cy+PH,5); }
+
+/* Draw current range. Caller must set pen color to 1 to draw or 0 to erase.*/
+local void DrawRange() {
+ register int i;
+
+ if (range == NULL) return; /* No range yet.*/
+
+ if (range->low > maxColor)
+ range->low = maxColor;
+ if (range->high > maxColor)
+ range->high = maxColor;
+ DrawLow(range->low);
+ DrawHigh(range->high);
+ for (i = range->low + 1; i < range->high; i++)
+ DrawInRange(i);
+ }
+
+/* Draw a major mark around the Speed Proportional Gadget.*/
+Stroke3(i) int i; {
+ VLine(speed_tickx+i,SPEEDY-1, 1);
+ VLine(speed_tickx+i,SPEEDY+7, 3);
+ }
+
+/* ---------- DrawWhich --------------------------------------------------- */
+
+#define DW_NONE 0
+#define DW_TICKS 1
+#define DW_HSV 2
+#define DW_RGB 3
+#define DW_SPEED 4
+#define DW_STICKY 5
+local int drawWhich = DW_SPEED;
+ /* Determines which set of gadgets (& their ticks) needs updating.*/
+
+/* Accumulate needed gadget drawing. The gadgets are in a list,
+ * when RefreshGadgets is called, gadgets from the selected one through
+ * the end of the list get redrawn.*/
+NewDrawWhich(newDrawWhich) int newDrawWhich; {
+ if (newDrawWhich > drawWhich)
+ drawWhich = newDrawWhich;
+ }
+
+local BOOL reentry = FALSE; /* So know when re-entering the window.*/
+
+/* Draw all the marks on the window that get damaged by RefreshGadgets(),
+ * or by ResetColor().*/
+local void DrawWhich()
+ {
+ int i, iPower, tickx, tickw;
+
+ drawWhich = DW_NONE;
+
+ /* ----- draw HSV ticks ----- */
+
+ SetAPen(_rp, 0);
+ /* Dashes at sixths of HSV.*/
+ _y = SY + SH - 6;
+ for (i = 0; i < 7; i++) {
+ Dash(SXHSV + 4 * sdx - 2, 5+1);
+ Dash(SXHSV + 5 * sdx - 2, 5+1);
+ if (i == 0 || i == 3 || i == 6) { /* Extra dashes */
+ Dash(SXHSV + 3 * sdx - 1 + isWide, 3+1);
+ Dash(SXHSV + 6 * sdx - 3, 3+1);
+ }
+ _y -= 10;
+ }
+
+ if (drawWhich == DW_HSV)
+ return;
+
+ /* ----- draw RGB ticks ----- */
+
+ /* Narrow sliders. */
+ if (!isWide) {
+ SetAPen(_rp, 1);
+ VLine(SXRGB + 0 * SDX + 2, SY + 1, SH - 1);
+ VLine(SXRGB + 1 * SDX + 2, SY + 1, SH - 1);
+ VLine(SXRGB + 2 * SDX + 2, SY + 1, SH - 1);
+ }
+
+ SetAPen(_rp, 0);
+ for (i = 0; i < 16; i++) {
+ iPower = (i % 4 ? (i % 2 ? 0 : 1) : 2); /* 1<<iPower == i */
+ _y = SY + 4 + ((15 - i) * (SH - 10)) / 15; /* 0..15 marks for RGB.*/
+ tickx = SXRGB - iPower;
+ tickw = iPower * 2 + 1;
+ if (isWide)
+ tickw += 1;
+ Dash(tickx, tickw); /* by RGB sliders */
+ Dash(tickx += sdx, tickw);
+ Dash(tickx += sdx, tickw);
+ }
+
+ if (drawWhich == DW_RGB)
+ return;
+
+ /* ----- Draw marks around Speed Proportional Gadget ----- */
+ SetAPen(_rp, 0);
+ Stroke3(0);
+ for (i = 1; i <= MAXSP; i += 2) { /* Marks at 1,3,5,7...*/
+ switch ((i+1) % 8) {
+ case 0:
+ Stroke3(i); break;
+ case 4:
+ VLine(speed_tickx+i,SPEEDY+7, 2); break;
+ default:
+ VLine(speed_tickx+i,SPEEDY+7, 1);
+ }
+ }
+
+ }
+
+
+local void ForceDrawWhich() {
+ register struct Gadget *gadgetToDraw;
+
+ switch (drawWhich) {
+ case DW_RGB: gadgetToDraw = &sliderGadgets[0]; goto YesRefresh;
+ case DW_HSV: gadgetToDraw = &sliderGadgets[3]; goto YesRefresh;
+ case DW_SPEED: gadgetToDraw = &sliderGadgets[6]; goto YesRefresh;
+ case DW_STICKY: gadgetToDraw = &comGadgets[COM_SPREAD];
+YesRefresh:
+ RefreshGadgets(gadgetToDraw, _wp, NULL);
+ case DW_TICKS:
+ DrawWhich();
+ /* FALL THRU */
+ case DW_NONE:
+ }
+ }
+
+InCaseOfReentry() {
+ if (reentry) {
+ reentry = FALSE;
+ NewDrawWhich(DW_TICKS);
+ ForceDrawWhich();
+ }
+ }
+
+/* ---------- SetCurrentColor ----------------------------------------------*/
+
+/* convert a 12bit rgb value to separate (r,g,b) values.*/
+SplitRGB4(colorRegister, rgb) WORD colorRegister; RGB *rgb; {
+ rgb->r = (colorRegister >> 8) & 0xf;
+ rgb->g = (colorRegister >> 4) & 0xf;
+ rgb->b = colorRegister & 0xf;
+ }
+
+/* Check delta of each color component to see if that contrast allows readable
+ * menus */
+local int minReadable = 0;
+local int Readable(delta) int delta; {
+ return ( ABS(delta) >= minReadable );
+ }
+
+/* Set CurrentColor on the screen.*/
+local void _SetCC() {
+ RGB other;
+
+ /* Hack to keep colors 0 and 1 from being too close together.*/
+ switch (color_being_modified) {
+ case 0: other = c1; goto menuColorHack;
+ case 1: other = c0;
+menuColorHack:
+ minReadable = MIN_MENU_INTENSITY;
+ if ( !Readable(other.r - rgb.r) && !Readable(other.g - rgb.g) &&
+ !Readable(other.b - rgb.b) ) {
+ /* Don't make the color change; restore data to what it was.*/
+ currentColor = colorMapNow->m[color_being_modified];
+ SplitRGB4(currentColor, &rgb);
+ rgb2hsv(&rgb, &hsv);
+ NewDrawWhich(DW_RGB); /* All 6 sliders.*/
+ return;
+ }
+ }
+
+ /* Remember the accepted color.*/
+ switch (color_being_modified) {
+ case 0: c0 = rgb; break;
+ case 1: c1 = rgb; break;
+ }
+
+ /* Affect the screen.*/
+ colorMapNow->m[color_being_modified] = currentColor;
+ SetRGB4(_vp, color_being_modified, rgb.r, rgb.g, rgb.b);
+ }
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
+/* Set current_color_no to 12b r-g-b "value".*/
+/* Sets HSV to match.*/
+SetCurrentColor(value) int value; {
+ currentColor = value;
+ SplitRGB4(currentColor, &rgb);
+ rgb2hsv(&rgb, &hsv);
+ NewDrawWhich(DW_RGB /*DW_HSV*/); /* Also force RGB to line up with ticks.*/
+ if (hsv.h == UNDEFINED) hsv.h = 0; /* [TBD] move this to rgb2hsv? */
+ _SetCC();
+ }
+
+RGBSetsCurrentColor() {
+ SetCurrentColor( (rgb.r << 8) | (rgb.g << 4) | rgb.b );
+ }
+
+/* Preserves HSV.*/
+HSVSetsCurrentColor() {
+ hsv2rgb(&hsv, &rgb);
+ NewDrawWhich(DW_RGB);
+ currentColor = (rgb.r << 8) | (rgb.g << 4) | rgb.b;
+ _SetCC();
+ }
+
+
+#define ToPot15(n) ( 0xffff - 0x1111 * ((n) & 0xf) )
+#define ToPot255(n) ( 0xffff - 0x0101 * (n) )
+#define FromVertPotXXXX(n) ( 0xffff - (n) )
+#define FromHorizPotXXXX(n) (n)
+
+local void ModifyRGBHSVSliders() {
+ /* convert 4 bits into 16 bits by replicating it in 4 positions.*/
+ sliderPI[MODIFYRED].VertPot = ToPot15(rgb.r);
+ sliderPI[MODIFYGREEN].VertPot = ToPot15(rgb.g);
+ sliderPI[MODIFYBLUE].VertPot = ToPot15(rgb.b);
+ /* convert 8 bits to 16 bits by replicating it.*/
+ sliderPI[MODIFYHUE].VertPot = ToPot255(hsv.h);
+ sliderPI[MODIFYSATURATION].VertPot = ToPot255(hsv.s);
+ sliderPI[MODIFYVALUE].VertPot = ToPot255(hsv.v);
+ if (range != NULL)
+ sliderPI[MODIFYSPEED].HorizPot = range->rate * SPEED_BODY;
+ }
+
+/*---------- WInvertGadget ------------------------------------------------*/
+#define XORMASK 0x6a
+#define NOOP 0xaa
+
+local void SetXorFgPen(rp) struct RastPort *rp; {
+ SHORT pen = rp->FgPen;
+ SHORT bit = 1;
+ SHORT i;
+ for (i=0; i<rp->BitMap->Depth; i++) {
+ rp->minterms[i] = (bit&pen) ? XORMASK : NOOP;
+ bit <<=1;
+ }
+ }
+
+/* Does highlighting of gadgets using only colors 0 and 1.
+ * Caution: Leaves draw mode and pen modified.
+ * After, do "SetDrMd(_rp,JAM1 or JAM2)" and "SetAPen(_rp,color)".*/
+local void WInvertGadget(gad) struct Gadget *gad; {
+ int x,y,temp;
+ struct IntuiText *text = gad->GadgetText;
+
+ x = gad->LeftEdge,
+ y = gad->TopEdge;
+ SetAPen(_rp,1);
+ SetXorFgPen(_rp);
+ RectFill(_rp, x, y, x + gad->Width-1, y + gad->Height-1);
+ /* Tell system to use inverted rendering for this gadget in case
+ * window reentered.*/
+ if (text) {
+ temp = text->FrontPen;
+ text->FrontPen = text->BackPen;
+ text->BackPen = temp;
+ }
+ }
+
+/* ---------- ResetRange ---------------------------------------------------*/
+/* Caller must do "ModifyRGBHSVSliders" to have new range's speed show up.*/
+local void ResetRange(index) int index; {
+
+ /* Force "index" to be valid.*/
+ if (index < 0)
+ index = 0;
+ if (index >= LIM_RANGES)
+ index = LIM_RANGES-1;
+
+ if (range) /* turn off previous highlight.*/
+ WInvertGadget(&comGadgets[COM_SHADE+PALETTE_RANGE]);
+ /* Highlight selected range.*/
+ WInvertGadget(&comGadgets[COM_SHADE+index]);
+ SetDrMd(_rp, JAM1); /* WInvertGadget altered draw mode.*/
+
+ SetAPen(_rp, 0); DrawRange(); /* Erase old range.*/
+ range = &ranges[PALETTE_RANGE = index];
+ SetAPen(_rp, 1); DrawRange(); /* Draw current range.*/
+ DrawColorsBorder(color_being_modified);
+ /* May have been smashed when range erased.*/
+ }
+
+/* ---------- ResetColor ---------------------------------------------------*/
+/* Make the sliders jump out to the RGB values for the color that was
+ * selected.
+ * When mode==MO_COPY, it first copies the previous color's RGB values to
+ * the new color.
+ * When mode==MO_SPREAD, it first alters the colors inbetween to be
+ * an HSV spread between the previous color and the newly selected color.
+ */
+
+/* Draw white border around newly selected palette square.*/
+local DrawColorsBorder(id) int id; {
+ SetAPen(_rp, 1);
+ LookColor(id);
+ DrawBox(cx, cy, pw - 1, PH);
+ }
+
+/* New state for "mode".*/
+local void NewMode(newMode) int newMode; {
+ int sticky = newMode - 1 + COM_SPREAD;
+ int oldSticky = mode - 1 + COM_SPREAD;
+ int oldMode;
+
+ oldMode = mode;
+ mode = newMode;
+
+ if (newMode == MO_NORMAL)
+ ClearPointer(_wp);
+ else
+ SetPointer(_wp, &stickyPointer, STICKY_HEIGHT, 16,
+ -STICKY_HOT_X, -STICKY_HOT_Y);
+
+ if (oldMode != MO_NORMAL)
+ WInvertGadget(&comGadgets[oldSticky]);
+ if (newMode != MO_NORMAL)
+ WInvertGadget(&comGadgets[sticky]);
+ SetDrMd(_rp, JAM1); /* WInvertGadget alters draw mode.*/
+ }
+
+local void ResetColor(id) SHORT id; {
+ register int i, rounder, limitI, dI, newColor, oldColor;
+ int rounder1, rounder2, rounder3;
+ HSV firstHsv, dHsv; /* first color, total delta for HSV color-spread.*/
+ RGB tempRgb; /* temp color for swapping with undo.*/
+
+ *colorMapUndo = *colorMapNow; /* So can undo any changes that follow.*/
+ undoC0 = c0; undoC1 = c1;
+
+ /* Erase border around previous palette square by drawing in black.*/
+ SetAPen(_rp, 0);
+ LookColor(color_being_modified);
+ DrawBox(cx, cy, pw - 1, PH);
+
+ oldColor = currentColor;
+ currentColor = newColor = colorMapNow->m[id]; /*GetRGB4(_vp->ColorMap,id);*/
+
+ switch(mode) {
+ case MO_NORMAL: {
+ /*ALREADY DID ABOVE: currentColor = newColor; */
+ break; }
+ case MO_COPY: {
+ currentColor = oldColor; /* Uses color from PREVIOUS */
+ break; } /* color_being_modified. */
+ case MO_EXCHANGE: {
+ /* Hack to counter c0/c1 hack in _SetCC */
+ /* This avoids a moment when both c0 & c1 attempt to be newColor.*/
+ if ( (color_being_modified == 0 && id == 1) ||
+ (color_being_modified == 1 && id == 0) ) {
+ tempRgb = c0; c0 = c1; c1 = tempRgb; /* Exchange c0,c1 */
+ }
+
+ SetCurrentColor(newColor); /* Set previous id's color to
+ * new id's color.*/
+ currentColor = oldColor; /* Uses color from PREVIOUS */
+ break; } /* color_being_modified. */
+ case MO_SPREAD: {
+ limitI = id - color_being_modified;
+ rounder = limitI / 2; /* For rounding below.*/
+ dI = (limitI >= 0 ? 1 : -1);
+ SplitRGB4(newColor, &rgb);
+ /* dHSV = new color's HSV */
+ rgb2hsv(&rgb, &dHsv);
+ if (dHsv.s == 0) /* Set new H to match previous, */
+ dHsv.h = hsv.h; /* since H was really "UNDEFINED".*/
+ if (hsv.s == 0) /* Set previous H to match new.*/
+ hsv.h = dHsv.h;
+ if (dHsv.v == 0) /* Set new S to match previous, */
+ dHsv.s = hsv.s; /* since S was really "UNDEFINED".*/
+ if (hsv.v == 0) /* Set previous S to match new.*/
+ hsv.s = dHsv.s;
+ firstHsv = hsv; /* Previous "color_being_modified".*/
+
+#define FAVOR_ARC (256/12) /* Distance between Yellow and Orange.*/
+#define MAIN_ARC (128+FAVOR_ARC)
+
+ /* dHSV = newHSV - previousHSV */
+ dHsv.h -= hsv.h;
+ if (dHsv.h > MAIN_ARC) /* Choose the smaller arc around hue.*/
+ dHsv.h -= 256; /* Values related to MAXHSV.*/
+ if (dHsv.h < -MAIN_ARC) /* Favor Y..G..B over Y..R..B arc.*/
+ dHsv.h += 256;
+ dHsv.s -= hsv.s; dHsv.v -= hsv.v;
+ /* round with same sign as each component.*/
+ rounder1 = (dHsv.h > 0 ? rounder : -rounder);
+ rounder2 = (dHsv.s > 0 ? rounder : -rounder);
+ rounder3 = (dHsv.v > 0 ? rounder : -rounder);
+
+ /* Starts at one-end, so can detect case where ends are same id.*/
+ for (i = 0; i != limitI; i += dI) {
+ /* Each color is fractionally farther from firstHsv.*/
+ hsv.h = MAXHSV &
+ ( firstHsv.h + (dHsv.h * i + rounder1) / limitI );
+ hsv.s = firstHsv.s + (dHsv.s * i + rounder2) / limitI;
+ hsv.v = firstHsv.v + (dHsv.v * i + rounder3) / limitI;
+ HSVSetsCurrentColor();
+ color_being_modified += dI;
+ }
+ currentColor = newColor;
+ break; }
+ case MO_RANGE: {
+ if (range == NULL)
+ break;
+ SetAPen(_rp, 0); DrawRange(); /* Erase old range.*/
+
+ if (color_being_modified <= id) {
+ range->low = color_being_modified;
+ range->high = id;
+ }
+ else {
+ range->low = id;
+ range->high = color_being_modified;
+ }
+ break; }
+ }
+ NewMode(MO_NORMAL); /* Ends MO_COPY, etc. */
+
+ /* Draw white border around newly selected palette square.*/
+ /* Done after any range-change, since range-erase may hit border.*/
+ DrawColorsBorder(id);
+
+ color_being_modified = id; /* An implicit parameter to many routines!*/
+ SetCurrentColor(currentColor);
+ NewDrawWhich(DW_RGB); /* So get all 6 sliders.*/
+
+ SetAPen(_rp, 1); DrawRange(); /* Draw current range.*/
+
+ /* Draw enlarged current-color rectangle above the palette array.*/
+ SetAPen(_rp, color_being_modified);
+ RectFill(_rp, px, TY+1, px+2*pw -1, TY+1 + PH-1 -1);
+
+ ModifyRGBHSVSliders();
+ }
+
+/* ---------- getvalue -----------------------------------------------------*/
+/* "oldaddress" points to the proportional gadget which is down.
+ * RETURN the pot value in a range dependent on "sig".
+ * sig is # significant bits; 4 yields 0..15, 8 yields 0..255.
+ * 16 yields 0..0xFFFF, which is MAXBODY.
+ * Pass in negated sig to get "HorizPot".
+ * [TBD] Should ROUND rather than TRUNCATE? Or is that problem internal
+ * to PropGadget ROM code? Or maybe ROM code is including inaccessible
+ * ends of slider region in the computation?
+ */
+local int getvalue(sig) SHORT sig; {
+ register struct PropInfo *p;
+ register int colorpar;
+
+ p = (struct PropInfo *)( ((struct Gadget *)oldaddress)->SpecialInfo);
+ colorpar = FromVertPotXXXX(p->VertPot);
+ if (sig < 0) {
+ sig = -sig;
+ colorpar = FromHorizPotXXXX(p->HorizPot);
+ }
+ colorpar = colorpar >> (16 - sig);
+
+ if ((sig == 8) && (colorpar < 2)) /* VertPot doesn't return 0 for HSV. */
+ colorpar = 0; /* [TBD] is this a ROM bug to report? Still true?*/
+ return(colorpar);
+ }
+
+/* ---------- syscolorfix -------------------------------------------------*/
+/* Handles sliders R,G,B, H,S,V, SPEED */
+local void syscolorfix(whichslider) SHORT whichslider; {
+ do {
+ switch (whichslider) {
+ case MODIFYRED:
+ rgb.r = getvalue(4);
+ goto RGBSets;
+ case MODIFYGREEN:
+ rgb.g = getvalue(4);
+ goto RGBSets;
+ case MODIFYBLUE:
+ rgb.b = getvalue(4);
+RGBSets: RGBSetsCurrentColor();
+ break;
+ case MODIFYHUE:
+ hsv.h = getvalue(8);
+ goto HSVSets;
+ case MODIFYSATURATION:
+ hsv.s = getvalue(8);
+ goto HSVSets;
+ case MODIFYVALUE:
+ hsv.v = getvalue(8);
+HSVSets: HSVSetsCurrentColor();
+ break;
+ case MODIFYSPEED:
+ if (range != NULL)
+ range->rate = getvalue(-6);
+ break;
+ }
+ } while (waiting_for_gadget_up());
+
+ if (drawWhich != DW_NONE)
+ ModifyRGBHSVSliders();
+ }
+
+/* ---------- _Undo --------------------------------------------------------*/
+/* UNDO command-button activated, or "u" key pressed.*/
+local void _Undo() {
+ int i, colorid;
+
+ NewMode(MO_NORMAL); /* Ends MO_COPY, etc. */
+ /* Restore colors to just before last palette selection.
+ * This undoes any slider action on this color; it also undoes
+ * any MIX,GLOW,Exchange,COPY */
+ colorid = color_being_modified; /* hold */
+ c0 = undoC0; c1 = undoC1;
+ for (i = 0; i < no_of_colors; i++) {
+ SetCurrentColor(colorMapUndo->m[color_being_modified = i]);
+ }
+ SetCurrentColor(colorMapNow->m[color_being_modified = colorid]);
+ ModifyRGBHSVSliders();
+ }
+
+/* ---------- EventHandler ------------------------------------------------*/
+local EventHandler() {
+ int i, colorid, newMode;
+
+ WaitTOF(); /* yield control to other processes */
+
+ _message = GetMsg (userwp->UserPort);
+ if (_message) {
+ ReplyMsg(_message);
+
+ if ((_message->Class == MOUSEBUTTONS) & (_message->Code == SELECTDOWN))
+ {
+ colorid = ReadPixel (userrp, _message->MouseX, _message->MouseY);
+ ResetColor(colorid);
+ reentry = TRUE; /* Will be re-entering the window.*/
+ }
+ }
+
+ _message = GetMsg(_wp->UserPort);
+ if (_message == NULL) {
+ ForceDrawWhich();
+ return(PALETTE_X == _wp->LeftEdge && PALETTE_Y == _wp->TopEdge);
+ /* FALSE if window moved. EXIT.*/
+ }
+
+ _class = _message->Class;
+ _code = _message->Code;
+ _qualifier = _message->Qualifier;
+ _address = _message->IAddress;
+ oldaddress = _address;
+ ReplyMsg(_message);
+ testcode = TRUE; /* closewindow test for neil ~~~~~~*/
+
+ InCaseOfReentry();
+ if (_class != GADGETDOWN && _class != GADGETUP) {
+ if (_class == MOUSEBUTTONS && _code == SELECTDOWN)
+ InCaseOfReentry();
+ else if (_class == RAWKEY && _code == (UCODE|DOWNFLAG))
+ _Undo();
+ return(testcode);
+ }
+ _gadgetid = ((struct Gadget *)_address)->GadgetID;
+
+ if (inRange(_gadgetid, SLIDERGADGETS, LIM_SLIDERS)) {
+ syscolorfix(_gadgetid - (SLIDERGADGETS));
+ }
+
+ else if (inRange(_gadgetid, COLORGADGETS, LIM_COLORS)) {
+ ResetColor(_gadgetid - (COLORGADGETS));
+ }
+ else if (inRange(_gadgetid, RANGE_GADGETS, LIM_RANGES)) {
+ ResetRange(_gadgetid - RANGE_GADGETS);
+ ModifyRGBHSVSliders();
+ NewDrawWhich(DW_SPEED); /* So get all 7 sliders drawn.*/
+ }
+ else switch (_gadgetid) {
+ case UNDO_GADGET:
+ _Undo();
+ break;
+ case CANCEL_GADGET:
+ /* Restore original ranges.*/
+ for (i = 0; i < LIM_RANGES; i++)
+ ranges[i] = originalRanges[i];
+ /* Restore original colors.*/
+ colorid = color_being_modified; /* hold */
+ for (i = 0; i < no_of_colors; i++)
+ SetCurrentColor(colorMapOriginal->m[color_being_modified = i]);
+ SetCurrentColor(colorMapNow->m[color_being_modified = colorid]);
+ /* FALL THRU to OK_GADGET */
+ case OK_GADGET:
+ testcode = FALSE; break; /* Exit PaletteTool */
+ case SPREAD_GADGET:
+ newMode = MO_SPREAD; /* Previous and next colors chosen span HSV */
+ goto NewSticky; /* range within which colors are blended */
+ case EXCHANGE_GADGET:
+ newMode = MO_EXCHANGE; goto NewSticky;
+ case COPY_GADGET:
+ newMode = MO_COPY; goto NewSticky;
+ case RANGE_GADGET:
+ newMode = MO_RANGE; /* Previous and next colors chosen become */
+ /* the new span for currently selected range.*/
+
+NewSticky: /* These are infix operators, indicated by making
+ * corresponding boolean be sticky.
+ * Next color chosen is destination, or end of range.*/
+ NewMode(newMode);
+ break;
+ }
+
+ NoEvent();
+ return(testcode);
+ }
+
+/* ---------- InitPaletteGadgets -------------------------------------------*/
+local void InitPaletteGadgets(depth) SHORT depth; {
+ SHORT n;
+
+ for(n=0; n < no_of_colors; n++) {
+ colors[n].LeftEdge = px + (pw) * (n / phs);
+ colors[n].TopEdge = PY + (PH) * (n % phs);
+ colors[n].Width = pw-1;
+ colors[n].Height = PH;
+ colors[n].Flags = GADGHNONE | GADGIMAGE;
+ colors[n].Activation = GADGIMMEDIATE;
+ colors[n].GadgetType = BOOLGADGET;
+ colors[n].GadgetRender = (APTR)&colorImages[n];
+ colors[n].GadgetID = COLORGADGETS + n;
+/*ALLOC filled with zeroes already.
+ colors[n].NextGadget = NULL;
+ colors[n].SelectRender = NULL;
+ colors[n].GadgetText = NULL;
+ colors[n].MutualExclude = 0;
+ colors[n].SpecialInfo = NULL;
+ colors[n].UserData = NULL;
+ */
+ /* Make hit box smaller for outside. */
+ colorImages[n].LeftEdge = 1;
+ colorImages[n].TopEdge = 1;
+ colorImages[n].Width = pw-3;
+ colorImages[n].Height = PH-2;
+ colorImages[n].PlaneOnOff = n;
+/*ALLOC filled with zeroes already.
+ colorImages[n].Depth = 0;
+ colorImages[n].ImageData = NULL;
+ colorImages[n].PlanePick = 0;
+ */
+
+ AddGadget (_wp, &colors[n], -1);
+ }
+ }
+
+/* ---------- InitSliderGadgets --------------------------------------------*/
+local void InitSliderGadgets() {
+ register int i, x;
+
+ InitSliderImage.ImageData = (isWide ? &diamond2[0] : &diamond[0]);
+ InitSliderImage.Width = (isWide ? 9 : 5);
+
+ x = SXRGB;
+ for (i = 0; i < LIM_SLIDERS; i++) {
+
+ sliderImages[i] = InitSliderImage;
+
+ sliderPI[i].Flags = FREEVERT;
+ sliderPI[i].VertBody = sliderPIBody[i];
+
+ if (i == MODIFYHUE)
+ x = SXHSV;
+ sliderGadgets[i].LeftEdge = x + i * sdx + 2*isWide;
+ sliderGadgets[i].TopEdge = SY;
+ sliderGadgets[i].Width = sw;
+ sliderGadgets[i].Height = SH;
+ sliderGadgets[i].Flags = GADGIMAGE | GADGHNONE;
+ sliderGadgets[i].Activation = RELVERIFY | GADGIMMEDIATE;
+ sliderGadgets[i].GadgetType = PROPGADGET;
+ sliderGadgets[i].GadgetRender = (APTR)&sliderImages[i];
+ sliderGadgets[i].SpecialInfo = (APTR)&sliderPI[i];
+ sliderGadgets[i].GadgetID = SLIDERGADGETS+i;
+ if (i == MODIFYSPEED) {
+ sliderPI[i].Flags = FREEHORIZ;
+ sliderPI[i].HorizBody = sliderPI[i].VertBody;
+
+ sliderGadgets[i].LeftEdge = SPEED_PROPX - 2;
+ sliderGadgets[i].TopEdge = SPEEDY - 1;
+ sliderGadgets[i].Width = (isWide ? MAXSP+17 : MAXSP+13);
+ sliderGadgets[i].Height = 9;
+ }
+ }
+
+/* Speed gadget first, so can re-draw rgbhsv without redrawing speed.*/
+ AddGadget(_wp, &sliderGadgets[MODIFYSPEED], -1);
+ for (i = 0; i < MODIFYSPEED; i++)
+ AddGadget(_wp, &sliderGadgets[i], -1);
+ }
+
+/* ---------- PaletteTool --------------------------------------------------*/
+
+FreeAllRAM() {
+ FREE( colors, LIM_COLORS * sizeof(struct Gadget) );
+ FREE( colorImages, LIM_COLORS * sizeof(struct Image) );
+ FREE( colorMapOriginal, sizeof(ColorMap) );
+ FREE( colorMapUndo, sizeof(ColorMap) );
+ FREE( colorMapNow, sizeof(ColorMap) );
+ FREE( sliderGadgets, LIM_SLIDERS * sizeof(struct Gadget) );
+ FREE( sliderImages, LIM_SLIDERS * sizeof(struct Image) );
+ FREE( sliderPI, LIM_SLIDERS * sizeof(struct PropInfo) );
+ FREE( gText, LIM_COMMANDS * sizeof(struct IntuiText) );
+ }
+
+/* windowptr is client's window, in which to bring up palette window.
+ * paletteGlobals allows Palette.c to be an overlay, yet retain information
+ * between calls.
+ * Returns 0 if window moved. Client should call again, will reopen in
+ * new position. Returns -1 if not enough RAM.
+ */
+int PaletteTool(windowptr, paletteGlobals)
+ struct Window *windowptr; PaletteGlobals *paletteGlobals; {
+ int i, minY, rw, returnCode, enoughRAM;
+
+ pGlobals = paletteGlobals; /* So can access globals from subroutines.*/
+
+ _wp = windowptr;
+ _rp = _wp->RPort;
+ _vp = &_wp->WScreen->ViewPort;
+ depth = _rp->BitMap->Depth;
+ if (depth > DEPTH)
+ {
+/* KPrintF ("\nDEPTH of Color Palette > %d\n", DEPTH); */
+ exit (0);
+ }
+
+ colors = (struct Gadget *)ALLOC(LIM_COLORS * sizeof(struct Gadget));
+ colorImages = (struct Image *)ALLOC(LIM_COLORS * sizeof(struct Image));
+ colorMapOriginal = (ColorMap *)ALLOC(sizeof(ColorMap));
+ colorMapUndo = (ColorMap *)ALLOC(sizeof(ColorMap));
+ colorMapNow = (ColorMap *)ALLOC(sizeof(ColorMap));
+ sliderGadgets =(struct Gadget *)ALLOC(LIM_SLIDERS * sizeof(struct Gadget));
+ sliderImages = (struct Image *)ALLOC(LIM_SLIDERS * sizeof(struct Image));
+ sliderPI = (struct PropInfo *)ALLOC(LIM_SLIDERS * sizeof(struct PropInfo));
+ gText = (struct IntuiText *)ALLOC(LIM_COMMANDS * sizeof(struct IntuiText));
+ enoughRAM = (colors && colorImages && colorMapOriginal && colorMapUndo &&
+ colorMapNow && sliderGadgets && sliderImages && sliderPI && gText);
+
+ if (!enoughRAM) {
+ FreeAllRAM();
+ return(-1);
+ }
+
+ mode = MO_NORMAL;
+
+ no_of_colors = 1 << depth;
+ maxColor = no_of_colors - 1;
+ if (color_being_modified > maxColor)
+ color_being_modified = maxColor;
+
+ for (i = 0; i < no_of_colors; i++)
+ colorMapOriginal->m[i] = GetRGB4(_vp->ColorMap, i);
+ *colorMapUndo = *colorMapNow = *colorMapOriginal;
+
+ isWide = (_wp->Width > 320);
+
+ px = (isWide ? PX+38 : PX);
+ pw = (isWide ? 2*PW : PW);
+
+ /* With 16 or 32 colors, 8 color-squares per column.
+ * With 8 colors, 4 per column. With 2 or 4 colors, 2 per column.*/
+ phs = ( depth > 3 ? 8 : (depth == 3 ? 4 : 2) );
+
+ speed_tickx = (isWide ? SPEED_PROPX+4+2 : SPEED_PROPX+4);
+
+ /* Double palette window width when 640 H.*/
+ newcolorwindow.Width = rw = (isWide ? px + 2*pw + 4 : RW);
+
+ if ((_wp->Width < rw) | (_wp->Height < RH))
+ {
+/* KPrintF ("\nWindow Too Small For NewWindow\n"); */
+ exit (0);
+ }
+
+ sdx = (isWide ? SDX+6 : SDX);
+ sw = (isWide ? SDX+4 : SDX);
+
+ /* Double PANEL_WIDTH when 640 H.*/
+/* maxX = _wp->Width - rw -
+ (isWide ? 2*PANEL_WIDTH : PANEL_WIDTH);*/
+ if ((PALETTE_X + rw) > _wp->Width)
+ PALETTE_X = _wp->Width - rw - 1;
+
+ /* Double TITLE_HEIGHT in INTERLACE mode.*/
+ minY = (_wp->Height > 200 ? 2*TITLE_HEIGHT : TITLE_HEIGHT);
+ if (PALETTE_Y < minY)
+ PALETTE_Y = minY;
+ if ((PALETTE_Y + RH) > _wp->Height)
+ PALETTE_Y = _wp->Height - RH - 1;
+
+ newcolorwindow.LeftEdge = PALETTE_X;
+ newcolorwindow.TopEdge = PALETTE_Y;
+ newcolorwindow.Screen = _wp->WScreen;
+
+ userwp = _wp;
+ userrp = _rp;
+ _wp = OpenWindow(&newcolorwindow); /* open a window */
+ _rp = _wp->RPort;
+ _vp = &_wp->WScreen->ViewPort;
+
+ SetRast(_rp, 1); /* White window background.*/
+
+ SetAPen(_rp, 0);
+ RectFill(_rp, px-2,PY-1,
+ px+((maxColor+phs)/phs)*pw,
+ PY+MIN(phs,no_of_colors)*PH); /* Black behind palette.*/
+ BoxText(COPYX, SPREADY, 4*TWSCALE);
+ BoxText(EXCHANGEX, SPREADY, 2*TWSCALE);
+ BoxText(SPREADX, SPREADY, SPREADW); /* Black border around text.*/
+ BoxText(RANGEX, RANGEY, 5*TWSCALE-2);
+ BoxText(SHADEX, RANGEY, RANGEW);
+ BoxText(CYCLE1X, RANGEY, RANGEW);
+ BoxText(CYCLE2X, RANGEY, RANGEW);
+ BoxText(CYCLE3X, RANGEY, RANGEW);
+ BoxText(CANCELX, OKY, 6*TWSCALE);
+ BoxText(UNDOX, OKY, 4*TWSCALE);
+ BoxText(OKX, OKY, 2*TWSCALE);
+ DrawBoxAround(OKX-1, OKY-1, 2*TWSCALE+2,RSCALE+1); /* Double-thick box.*/
+
+ /* Border around enlarged current-color rectangle above palette array.*/
+ SetAPen(_rp, 0); /* Black border.*/
+ DrawBoxAround(px, TY+1, 2*pw, PH-1);
+
+ InitPaletteGadgets();
+
+ for (i = 0; i < LIM_COMMANDS; i++) {
+ gText[i] = InitGText;
+ gText[i].IText = gStrings[i];
+ comGadgets[i].GadgetText = &gText[i];
+ AddGadget(_wp, &comGadgets[i], -1);
+ }
+
+ RefreshGadgets(&colors[0], _wp, NULL);
+
+/* After RefreshGadgets, so not displayed until have correct values, later.*/
+ InitSliderGadgets();
+
+ /* After InitSliderGadgets, so can pick up x for "R","G","B","H","S","V".*/
+ for (i = 0; i < 6; i++)
+ decorText[i+1].x = sliderGadgets[i].LeftEdge + 2 + 2 * isWide;
+ SetAPen(_rp, 0);
+ SetDrMd(_rp, JAM1);
+ for (i = 0; i < LIM_DECOR_TEXT; i++) {
+ Move(_rp, decorText[i].x, decorText[i].y+6);
+ TxWrite(_rp, decorText[i].body);
+ }
+
+ ranges = pGlobals->ranges;
+ /* Make local copy, so can CANCEL without having lost client's values.*/
+ for (i = 0; i < LIM_RANGES; i++)
+ originalRanges[i] = ranges[i];
+
+ range = NULL; /* No previous range to erase.*/
+ ResetRange(PALETTE_RANGE);
+
+ SetAPen(_rp, 0);
+ DrawBox(0,0, rw,RH); /* black border around window.*/
+ DrawBox(0,0, rw,RSCALE+1); /* line under title.*/
+
+ oldaddress = (APTR) &sliderPI[0];
+
+ /* Hack to keep colors 0 and 1 from being too close together.
+ * This code forces colors 0 & 1 to be examined;
+ * so c0, c1 get set to correct values.
+ */
+ i = color_being_modified; /* hold */
+ SetCurrentColor(colorMapNow->m[color_being_modified = 0]);
+ SetCurrentColor(colorMapNow->m[color_being_modified = 1]);
+
+ ResetColor(i);
+ NewDrawWhich(DW_SPEED); /* So get all 7 sliders drawn.*/
+ while (EventHandler());
+
+
+ returnCode = (PALETTE_X == _wp->LeftEdge && PALETTE_Y == _wp->TopEdge);
+ /* 0 if window moved.*/
+
+ /* Remember where window ended up.*/
+ PALETTE_X = _wp->LeftEdge;
+ PALETTE_Y = _wp->TopEdge;
+
+ CloseWindow(_wp);
+
+ FreeAllRAM();
+
+ return (returnCode); /* 0 if window moved.*/
+ }
+
diff --git a/PANE.C b/PANE.C
new file mode 100644
index 0000000..b75e0e5
--- /dev/null
+++ b/PANE.C
@@ -0,0 +1,416 @@
+/*--------------------------------------------------------------*/
+/* */
+/* Pane.c -- Pane manager */
+/* */
+/*--------------------------------------------------------------*/
+
+#include <system.h>
+#include <prism.h>
+#include <librarie\dos.h>
+
+#define local static
+
+extern Box mainBox;
+extern short xShft,yShft;
+extern struct RastPort *mainRP;
+extern Box screenBox;
+extern SHORT checkpat[];
+extern struct Window *mainW;
+extern struct ViewPort *vport;
+extern SHORT nColors;
+extern BOOL skipRefresh,updatePending;
+
+BOOL inMenu = NO;
+
+Pane *paneList = NULL;
+Pane *actPane = NULL, *newPane = NULL;
+BOOL stopFlag = FALSE;
+
+local SHORT but=0,lastBut=0,msx=0,msy=0;
+
+PaneInit() { paneList = NULL; }
+
+/* #define DBGPANE */
+
+/*===============================================================*/
+#ifdef frogofog
+PaneClear(p,col) Pane *p; SHORT col; {
+ PushGrDest(mainRP,&screenBox);
+ PFillBox(&p->box);
+ PopGrDest();
+ }
+
+/*** The frame in PC Prism was OUTSIDE the pane's box **/
+void PaneUnDisplay(ph) Pane *ph; {
+ Box b;
+ b = ph->box;
+ if (ph->flags&BORDER) { b.x--; b.y--; b.w +=2; b.h += 2; }
+ if (!PaneClearing) return;
+ PushGrDest(mainRP,&screenBox);
+ PFillBox(&b);
+ PopGrDest();
+ }
+
+PaneFrame(ph) Pane *ph; {
+ Box b;
+ b = ph->box;
+ b.x--; b.y--; b.w +=2; b.h += 2;
+ PushGrDest(mainRP,&screenBox);
+ SetFGCol(0);
+ PThinFrame(&b);
+ PopGrDest();
+ }
+#endif
+
+/*===============================================================*/
+
+PaneInstall(ph) Pane *ph; {
+ PaneDelete(ph);
+ ph->next = paneList;
+ paneList = ph;
+ }
+
+PaneSize(ph,x,y,w,h) Pane *ph; SHORT x,y,w,h; {
+ ph->box.x = x; ph->box.y = y;
+ ph->box.w = w; ph->box.h = h;
+ }
+
+BOOL PaneClearing = NO;
+PaneSetClear(b) BOOL b; { PaneClearing = b; }
+local PaneDelete(ph) Pane *ph; {
+ Pane *p;
+ Pane *prv = NULL;
+ for (p=paneList; (p!=NULL)&&(p!=ph); p= p->next) prv=p;
+ if (p!=NULL) if (prv) prv->next = p->next; else paneList = p->next;
+ if (ph==actPane) {
+ actPane = NULL;
+ while(MouseBut()) ;
+ }
+ }
+
+PaneRemove(ph) Pane *ph; { PaneDelete(ph); }
+
+Pane *PaneFindPlace(x,y) SHORT x,y; {
+ Pane *p;
+ for (p=paneList; p!=NULL; p = p->next) if (BoxContains(&p->box,x,y)) return(p);
+ return(NULL);
+ }
+
+PaneStop() { stopFlag = TRUE; }
+
+PaneRefresh(bx) Box *bx; {
+ Pane *p; Box c;
+ for(p=paneList; p!=NULL; p=p->next)
+ if (BoxAnd(&c,bx,&p->box)) PanePaint(p,&c);
+ }
+
+local PanePaintList(p) Pane *p; {
+ if (p->next!=NULL) PanePaintList(p->next);
+ PanePaint(p,&screenBox);
+ }
+
+PaneRefrAll() {
+ if (paneList!=NULL) PanePaintList(paneList); /* paints in bottom up order */
+ }
+
+PanePaint(ph,bx) Pane *ph; Box *bx; {
+ if (ph->paintProc!=NULL) (*(ph->paintProc))(ph,bx);
+ }
+
+/* note: box is the extent of the active area: the border, if
+ any will lie outside of this */
+PaneCreate(ph,box,flags,cProc,mProc,pProc,context)
+ Pane *ph;
+ Box *box; /* extent of Pane on screen */
+ SHORT flags;
+ ProcHandle cProc; /* pointer to proc phich gets typing action*/
+ ProcHandle mProc; /* pointer to proc phich gets mouse action*/
+ ProcHandle pProc; /* pointer to proc to repaint Pane contents*/
+ ULONG context; /* client data */
+ {
+ ph->box = *box;
+ ph->flags = flags;
+ ph->charProc = cProc;
+ ph->mouseProc = mProc;
+ ph->paintProc = pProc;
+ ph->client = context;
+ ph->next = NULL;
+ }
+
+BOOL fakeMv = NO;
+BOOL active = YES;
+
+PaneReset() { actPane = NULL; }
+PaneFakeMove() { fakeMv=YES; }
+
+CursInst() {}
+
+SHORT dbgpane = NO;
+
+struct IntuiMessage *pushBMsg = NULL;
+
+struct IntuiMessage *GetPushBMsg() {
+ return((pushBMsg!=NULL)? pushBMsg:
+ (struct IntuiMessage *)GetMsg(mainW->UserPort));
+ }
+
+LONG CheckForKey() {
+ struct IntuiMessage *message;
+ LONG class,code;
+ message = GetPushBMsg();
+ if (message==NULL) return(-1);
+ class = message->Class;
+ code = message->Code;
+ pushBMsg = message;
+ return((class==RAWKEY)? code: -1);
+ }
+
+LONG kbhit() { return(CheckForKey() != -1); }
+
+/***
+ClearPushB() {
+ if (pushBMsg!=NULL) ReplyMsg(pushBMsg);
+ pushBMsg = NULL;
+ }
+***/
+
+AbortKeyHit() {
+ LONG code = CheckForKey();
+ int res = 0;
+ if (code != -1) if (CharFromKeyCode(code) == ' ') {
+ res = TRUE;
+ };
+ return(res);
+ }
+
+SHORT getch() {
+ struct IntuiMessage *message;
+ SHORT c = NoChar;
+ message = GetPushBMsg();
+ if (message) {
+ if (pushBMsg->Class==RAWKEY)
+ c = CharFromKeyCode(pushBMsg->Code);
+ else c = NoChar;
+ ReplyMsg(pushBMsg);
+ }
+ pushBMsg = NULL;
+ return(c);
+ }
+
+BOOL WaitRefrMessage() {
+ struct IntuiMessage *message;
+ LONG class;
+ for (;;) {
+ Wait(1 << mainW->UserPort->mp_SigBit);
+ message = (struct IntuiMessage *)GetMsg(mainW->UserPort);
+ if (message!=NULL) {
+ class = message->Class;
+ if (class==REFRESHWINDOW) {
+ ReplyMsg(message);
+ return(YES);
+ }
+ pushBMsg = message;
+ return(NO);
+ }
+ }
+ }
+
+MakeButtonBeUp() { lastBut = but = 0; }
+
+CallMouseProc(ev,but) MouseEvent ev; SHORT but; {
+ if (!inMenu)
+ (*actPane->mouseProc) (actPane,ev,but,msx-actPane->box.x, msy-actPane->box.y);
+ }
+
+ChgPane(new) Pane *new; {
+ if (actPane) CallMouseProc(LEAVE,but);
+ if (new==NULL) CursInst(Arrow);
+ actPane = new;
+ if (actPane) {
+#ifdef DBGPANE
+ dprintf("ChgPane: new pane = %lx\n", new);
+#endif
+ CallMouseProc(ENTER,but);
+ }
+ }
+
+#define doTimer
+
+#ifdef doTimer
+static struct timerequest timermsg = {0};
+#endif
+
+#define WAITTIME 6000 /* 6 milliseconds */
+
+/* Check for change in current pane based on (msx,msy) **/
+/* returns TRUE if changed */
+BOOL ChkChgPane() {
+ Pane *new;
+ if (inMenu) return(FALSE);
+ if (actPane==NULL) {
+ new = PaneFindPlace(msx,msy);
+ if (new == NULL) return(FALSE);
+ }
+ else if ( (BoxContains(&actPane->box,msx,msy))||
+ (lastBut&&actPane->flags&HANGON)) return(FALSE);
+ else new = PaneFindPlace(msx,msy);
+ ChgPane(new);
+ return(TRUE);
+ }
+
+PListen() {
+ SHORT lastx=0,lasty=0;
+ struct IntuiMessage *message;
+ struct MsgPort *mp = mainW->UserPort;
+
+
+#ifdef doTimer
+ ULONG wakeup;
+ InitTimer(&timermsg);
+ SetTimer(&timermsg, 0, WAITTIME);
+#endif
+
+ but = lastBut = 0;
+ stopFlag = FALSE;
+
+ for (;;) {
+ if (stopFlag) {
+ if (HookActive()){
+ InfoMessage("Can't quit--","bitmap in use.");
+ stopFlag = NO;
+ }
+ else break;
+ }
+
+ /* --- Read cursor coordinates out of Window structure ---*/
+ Forbid();
+ msx = mainW->MouseX + mainW->LeftEdge;
+ msy = mainW->MouseY + mainW->TopEdge;
+ Permit();
+
+ /*---- see if we can make right button do the correct thing */
+ if (msy < mainBox.y) mainW->Flags &= (~RMBTRAP);
+ else mainW->Flags |= RMBTRAP;
+
+ /* (1) ----- Check message port */
+ message = GetPushBMsg();
+ pushBMsg = NULL;
+ if (message != NULL) {
+ DoMessage(message); goto finish;
+ }
+
+ /* (2) ----- Check for entering or leaving Panes */
+ if (ChkChgPane()) goto finish;
+ if (!inMenu) {
+ if (actPane != NULL) {
+ /* (3) ----- Check for mouse motion */
+ if ((msx!=lastx)||(msy!=lasty)||fakeMv) {
+ CallMouseProc(MOVED,but); goto finish;
+ }
+ /* (4) ----- Check for "always" flag */
+ if (actPane->flags&ALWAYS) {
+ CallMouseProc(LOOPED,but); goto finish;
+ }
+ }
+ }
+#ifdef doTimer
+ /* (5) ---- Nothing happened: so wait a while */
+ wakeup = Wait( (1 << mp->mp_SigBit) | TimerSigBit(&timermsg));
+ if (wakeup&mp->mp_SigBit) {
+ message = (struct IntuiMessage *)GetMsg(mainW->UserPort);
+ if (message != NULL) DoMessage(message);
+ }
+ if (wakeup&TimerSigBit(&timermsg)) {
+ GetTimerMsg(&timermsg); /* no reply ??? */
+ SetTimer(&timermsg, 0,WAITTIME);
+ }
+#endif
+ finish:
+ lastBut = but;
+ lastx = msx; lasty = msy;
+ } /* End of main loop */
+#ifdef doTimer
+ KillTimer(&timermsg);
+#endif
+ }
+
+DoMessage(message) struct IntuiMessage *message; {
+ MouseEvent event;
+ LONG class,code,qualifier,ch;
+ event = NONE;
+ but = lastBut;
+ class = message->Class;
+ code = message->Code;
+ qualifier = message->Qualifier;
+ msx = message->MouseX + mainW->LeftEdge;
+ msy = message->MouseY + mainW->TopEdge;
+ ChkChgPane(); /* dont want event going to wrong window */
+
+#ifdef DBGPANE
+ dprintf("Msg: class=%6lx, code=%4lx, qual=%4lx, x=%ld, y=%ld\n",
+ class,code,qualifier,msx,msy);
+#endif
+
+ switch(class) {
+ case MENUVERIFY:
+ inMenu = YES;
+#ifdef DBGPANE
+ dprintf(" MENUVERIFY message \n");
+#endif
+ FixMenCols();
+ break;
+ case RAWKEY:
+ ch = CharFromKeyCode(code);
+ if ((ch!=NoChar)&&actPane&&(!inMenu))
+ (*actPane->charProc)(actPane, ch);
+ break;
+ case MOUSEBUTTONS:
+ skipRefresh = NO; /* just in case it got left on*/
+
+ /* disallow 2 buttons down at once. if one button
+ goes down, ignore other until first goes up
+ but = , 1, or 2, never 3 */
+ switch (code) {
+ case SELECTDOWN: if (but==0)
+ { lastBut = but= 1; event = BDOWN;} break;
+ case SELECTUP: if (but == 1) {
+ but = 0; event = BUP;} break;
+ case MENUDOWN: if (but==0)
+ { lastBut = but = 2; event = BDOWN;} break;
+ case MENUUP: if (but == 2) {
+ but = 0; event = BUP;} break;
+ }
+ if ((event!=NONE)&&actPane) CallMouseProc(event,lastBut);
+ break;
+ case MENUPICK:
+ inMenu = NO;
+ UnFixMenCols();
+ skipRefresh = YES;
+ DoMenEvent(code);
+ break;
+ case REFRESHWINDOW:
+#ifdef DBGPANE
+ dprintf(" REFRESHWINDOW \n");
+#endif
+ if ((!skipRefresh)&&(!updatePending)){
+/*
+ ClearFB();
+ PaneRefrAll();
+*/
+ }
+ skipRefresh = NO;
+ break;
+ case ACTIVEWINDOW:
+ active = YES;
+ if (SharingBitMap()) UpdtDisplay(); /* In case process is sharing bitmap*/
+ break;
+ case INACTIVEWINDOW:
+ if (SharingBitMap()) UndoSave(); /* In case process is sharing bitmap*/
+ active = NO;
+ break;
+ case CLOSEWINDOW: stopFlag = FALSE; break;
+ }
+ ReplyMsg(message);
+ /* done processing IDCMP message */
+ }
+
diff --git a/PENMENU.C b/PENMENU.C
new file mode 100644
index 0000000..2742671
--- /dev/null
+++ b/PENMENU.C
@@ -0,0 +1,28 @@
+/* Bitmap name = penmenu, Amiga-BOB format. */
+/* Width = 25, Height = 20 */
+
+short penmenu[40] = {
+ 0x7FFF, 0xFF00,
+ 0x7FFF, 0xC700,
+ 0x7FE3, 0x8300,
+ 0x7EC1, 0x100,
+ 0x6C41, 0x100,
+ 0x7EC1, 0x100,
+ 0x7FE3, 0x8300,
+ 0x7FFF, 0xC700,
+ 0x7FFF, 0xFF00,
+ 0x4186, 0x3300,
+ 0x4186, 0x3300,
+ 0x4186, 0x3F00,
+ 0x4187, 0xFF00,
+ 0x41FF, 0xEF00,
+ 0x7FFF, 0xFF00,
+ 0x7EFF, 0x7F00,
+ 0x7BFF, 0xED00,
+ 0x7EFF, 0xFF00,
+ 0x7FFF, 0xEF00,
+ 0x7FFF, 0xFF00
+ };
+
+
+
diff --git a/PGRAPH.C b/PGRAPH.C
new file mode 100644
index 0000000..c839ba1
--- /dev/null
+++ b/PGRAPH.C
@@ -0,0 +1,312 @@
+/*----------------------------------------------------------------------*/
+/* */
+/* pgraph.c -- prism graphics primitives */
+/* */
+/* routines starting with "P" take Physical Device Coords */
+/* routines starting with "V" take Virtual Device Coords */
+/* */
+/*----------------------------------------------------------------------*/
+
+#include <system.h>
+#include <prism.h>
+
+#define local static
+
+extern SHORT xShft,yShft;
+
+/* ------ The Current Destination RastPort and Clip Box ---- */
+#define NGRSTACK 4
+
+struct RastPort *rpStack[NGRSTACK];
+Box clbStack[NGRSTACK];
+struct RastPort *curRP = NULL;
+
+
+Box bigBox = {-1000,-1000, 2000, 2000};
+
+Box clipBox = {0}; /* THIS IS IN SCREEN COORDS */
+BoxBM canvas = { {0,0,400,640},NULL};
+SHORT grStPtr = 0;
+SHORT clipMaxX=0,clipMaxY=0;
+
+SetClipBox(r) Box *r; {
+ clipBox = *r;
+ clipMaxX = clipBox.x + clipBox.w - 1;
+ clipMaxY = clipBox.y + clipBox.h - 1;
+ }
+
+PushGrDest(rp,clBox) struct RastPort *rp; Box *clBox; {
+ rpStack[grStPtr] = curRP;
+ clbStack[grStPtr] = clipBox;
+ curRP = rp;
+ canvas.bm = rp->BitMap;
+ SetClipBox(clBox);
+ grStPtr++;
+ }
+
+PopGrDest() {
+ grStPtr--;
+ curRP = rpStack[grStPtr];
+ canvas.bm = curRP->BitMap;
+ SetClipBox(&clbStack[grStPtr]);
+ }
+
+/* ------------ MultiColor Fill Pattern ------------- */
+UWORD *curFilPat = NULL;
+SetFPat(pattern) UWORD *pattern; { curFilPat = pattern; }
+
+/* ------------ Current Pattern ------------------*/
+#define PATSIZE 3
+UWORD solidpat[1]={0xffff};
+UWORD checkpat[8]={0xaaaa,0x5555,0xaaaa,0x5555,0xaaaa,0x5555,0xaaaa,0x5555};
+SetPattern(pattern) USHORT *pattern; {
+ SetAfPt(curRP, pattern, (pattern==solidpat)? 0: PATSIZE);
+ }
+
+SolidPattern() { SetPattern(solidpat); }
+
+/* ------------ Current Pattern, FGCol, BGCol ------ */
+SetFGCol(c) int c; { SetAPen(curRP,c); }
+SetBGCol(c) int c; { SetBPen(curRP,c); }
+
+/* general subroutine to replace one pixel value with another in table */
+/* replpix(xtab,oldpx,newpx) UBYTE *xtab; UBYTE oldpx,newpx; { } */
+
+InitPGraph() {
+ curRP = NULL;
+ grStPtr = 0;
+ }
+
+/* --------- the Paint Mode: how are bits combined in painting ----*/
+PaintMode paintMode=Color, svPntMd=Color;
+BYTE svmode,svfgpen;
+UBYTE curMinterm = COOKIEOP;
+SHORT curxpc = 0; /* the current transparent color */
+USHORT *svpat;
+
+UBYTE drModes[NPaintModes] = {
+ JAM2, /* Mask */
+ JAM2, /* Color */
+ JAM2, /* Replace */
+ JAM2, /* Smear */
+ JAM2, /* Shade */
+ JAM2, /* Blend */
+ JAM2, /* Cycle Paint*/
+ COMPLEMENT /* Xor */
+ };
+
+void PWritePix(), PShadePix(), PSmearPix(), PBlendPix();
+
+void (*CurPWritePix)();
+void (*wrPixTable[])() = { PWritePix,PWritePix,PWritePix,
+ PSmearPix , PShadePix, PBlendPix, PWritePix, PWritePix};
+
+void SetPaintMode(mode) PaintMode mode; {
+ paintMode = mode;
+ SetDrMd(curRP,drModes[mode]);
+ CurPWritePix = wrPixTable[mode];
+ curMinterm = (mode==Xor)? XORMASK: COOKIEOP;
+ }
+
+/**--------- Temporary Erase mode for right button -----*/
+
+BOOL erasing = NO;
+
+JamSvPntMd(md) SHORT md;{ svPntMd = md; }
+
+TempErase() {
+ SetDrMd(curRP,JAM2);
+ svfgpen = curRP->FgPen;
+ SetAPen(curRP,curxpc);
+ erasing = YES;
+ }
+
+ClearErase() {
+ if (erasing) {
+ SetDrMd(curRP,drModes[paintMode]);
+ SetAPen(curRP,svfgpen);
+ erasing = NO;
+ }
+ }
+
+/* The transparent color */
+SetXPCol(col) SHORT col; { curxpc = col; }
+PaintMode tsvPntMd;
+SHORT tsvfgpen;
+#define WHITE 31
+
+TempMode(md,fg,ptrn) PaintMode md; SHORT fg; USHORT *ptrn; {
+ tsvfgpen = curRP->FgPen;
+ svpat = curRP->AreaPtrn;
+ tsvPntMd = paintMode;
+ SetAPen(curRP,fg);
+ SetPaintMode(md);
+ SetPattern(ptrn);
+ }
+
+TempXOR() { TempMode(Xor,WHITE,solidpat); }
+
+RestoreMode() {
+ SetAPen(curRP,tsvfgpen);
+ SetPaintMode(tsvPntMd);
+ SetPattern(svpat);
+ }
+
+/*------------------ Graphical Operations ----------------------*/
+/* operations beginning with "V" take Virtual coordinates */
+/* operations beginning with "P" take Physical coordinates */
+/*--------------------------------------------------------------*/
+
+#ifdef THEIRWAY
+#define FixX(x) ( (x) - clipBox.x )
+#define FixY(y) ( (y) - clipBox.y )
+#else
+#define FixX(x) (x)
+#define FixY(y) (y)
+#endif
+
+/*----- Physical Coordinate write pixel */
+void PWritePix(x,y) int x,y; {
+#ifndef THEIRWAY
+ if (BoxContains(&clipBox,x,y))
+#endif
+ WritePixel(curRP,FixX(x),FixY(y));
+ }
+
+/*----- Physical Coordinate read pixel */
+int PReadPix(x,y) int x,y; { return(ReadPixel(curRP,FixX(x),FixY(y))); }
+
+TempColWrPix(x,y,col) SHORT x,y,col; {
+ SHORT sv = curRP->FgPen;
+ SetAPen(curRP,col);
+ PWritePix(x,y);
+ SetAPen(curRP,sv);
+ }
+
+extern Range *shadeRange, cycles;
+
+void PShadePix(x,y) {
+ SHORT newc = PReadPix(x,y);
+ if (erasing) {
+ if (shadeRange) if ((newc<=cycles.low)||(newc>cycles.high)) return;
+ newc--;
+ }
+ else {
+ if (shadeRange) if ((newc<cycles.low)||(newc>=cycles.high)) return;
+ newc++;
+ }
+ TempColWrPix(x,y,newc);
+ }
+
+extern BOOL firstDown;
+SHORT smlast;
+void PSmearPix(x,y) {
+ SHORT sv = PReadPix(x,y);
+ if (!firstDown) TempColWrPix(x,y,smlast);
+ else firstDown = NO;
+ smlast = sv;
+ }
+
+local BOOL lastIn;
+void PBlendPix(x,y) {
+ SHORT sv = PReadPix(x,y);
+ BOOL thisIn = (shadeRange==0)||(sv>=cycles.low)&&(sv<=cycles.high);
+ if (!firstDown) {
+ if (thisIn&&lastIn)
+ TempColWrPix(x,y,(sv+smlast)/2);
+ }
+ else firstDown = NO;
+ smlast = sv;
+ lastIn = thisIn;
+ }
+
+/* ------------ Horizontal line ---------------- */
+
+void PHorizLine(x1,y,w) SHORT x1,y,w; {
+#ifdef THEIRWAY
+ x1 -= clipBox.x; y -= clipBox.y;
+#endif
+ Move(curRP,x1,y); Draw(curRP,x1+w-1,y);
+ }
+
+void PatHLine(x1,y,w) int x1,y,w; {
+ int x2;
+#ifdef THEIRWAY
+ x1 -= clipBox.x; y -= clipBox.y;
+#endif
+ if ((y<clipBox.y)||(y>clipMaxY)) return;
+ x2 = x1 + w -1;
+ x1=MAX(x1,clipBox.x); x2 = MIN(x2,clipMaxX);
+ if (x1>x2) return;
+ HLineBlt(curRP,x1,y,x2,curMinterm);
+ }
+
+/* ------------ Vertical line ---------------- */
+void PVertLine(x1,y,h) SHORT x1,y,h; {
+#ifdef THEIRWAY
+ x1 -= clipBox.x; y -= clipBox.y;
+#endif
+ if ((x1>= clipBox.x)&&(x1<=clipMaxX)) {
+ Move(curRP,x1,y); Draw(curRP,x1,y+h-1);
+ }
+ }
+
+#ifdef THEIRWAY
+PFillBox(b) Box *b;{
+ RectFill(curRP, b->x- clipBox.x, b->y - clipBox.y, b->x + b->w - 1, b->y + b->h - 1);
+ }
+#else
+PFillBox(b) Box *b; {
+ Box c;
+ if (BoxAnd(&c,b,&clipBox))
+ RectFill(curRP, c.x, c.y,c.x+c.w-1,c.y+c.h-1);
+ }
+#endif
+
+PPatternBox(b,pat,fg,bg,op) Box *b; SHORT *pat,fg,bg,op; {
+ USHORT *svpat,svfg,svbg,svop;
+ svpat = curRP->AreaPtrn;
+ svfg = curRP->FgPen;
+ svbg = curRP->BgPen;
+ svop = curRP->AOlPen;
+ SetPattern(pat);
+ SetFGCol(fg);
+ SetBGCol(bg);
+ SetOPen(curRP,op);
+ PFillBox(b);
+ SetPattern(svpat);
+ SetFGCol(svfg);
+ SetBGCol(svbg);
+ SetOPen(curRP,svop);
+ BNDRYOFF(curRP);
+ }
+
+PThinFrame(bx) Box *bx;{
+ PatHLine(bx->x,bx->y,bx->w);
+ PatHLine(bx->x,bx->y+bx->h-1,bx->w);
+ PVertLine(bx->x,bx->y+1, bx->h-2);
+ PVertLine(bx->x + bx->w -1,bx->y+1, bx->h-2);
+ }
+
+PInvertBox(b) Box *b; {
+ TempXOR();
+ PFillBox(b);
+ RestoreMode();
+ }
+
+PInvertXHair(x,y) int x,y; {
+ TempXOR();
+ PHorizLine(clipBox.x,y,clipBox.w);
+ PVertLine(x,clipBox.y,clipBox.h);
+ RestoreMode();
+ }
+
+PFloodArea(x,y) {
+ FillArea(x,y);
+
+/* Flood(curRP, 1, FixX(x), FixY(y)); */
+ }
+
+/* set to flood area now */
+PFloodBndry(x,y) { Flood(curRP, 1, FixX(x), FixY(y)); }
+
diff --git a/PLBM.H b/PLBM.H
new file mode 100644
index 0000000..6d80fdf
--- /dev/null
+++ b/PLBM.H
@@ -0,0 +1,100 @@
+#ifndef PLBM_H
+#define PLBM_H
+/*----------------------------------------------------------------------*/
+/* PLBM.H typedefs for PLane-oriented BitMap. 8/31/85 */
+/*----------------------------------------------------------------------*/
+#include "exec/types.h"
+#include "packer.h"
+
+typedef enum {cmpNone = 0, cmpByteRun1 = 1} _Compression;
+typedef UBYTE Compression;
+ /* Choice of compression algorithm. "cmpByteRun1" is the byte run
+ * encoding generated by Mac's PackBits. See Packer.h . */
+
+
+/* ---------- ID, Chunk, FORM ------------------------------------------*/
+
+typedef char _ID[4]; /* An identifier is four printable ASCII chars.*/
+typedef LONG ID; /* but stored as a long, so can copy, compare,
+ * as a whole value.*/
+
+/* All chunks start with a type id and a count of the data bytes that
+ follow. That is, the "valid" data bytes; if that number is odd,
+ the number of bytes written is incremented using WordAlign(size). */
+typedef struct {
+ ID ckID;
+ LONG ckSize;
+ } ChunkHeader;
+
+typedef struct {
+ ID ckID;
+ LONG ckSize;
+ UBYTE ckData[ 1 /*ckSize*/ ];
+ } Chunk;
+
+/* ALL CHUNKS MUST BE PADDED TO EVEN NUMBER OF BYTES */
+#define WordAlign(size) ((size+1)&~1)
+
+/* The Grouping chunks (LIST,FORM,PROP) guarantee that their bodies
+ are a concatenation of chunks. They all have a SubType ID to further
+ identify their contents. "LIST of chunks of type XXXX", "FORM XXXX",
+ "PROPerties associated with chunks of type XXXX".*/
+typedef struct {
+ ID ckID;
+ LONG ckSize;
+ ID grpSubID;
+ } GroupHeader;
+
+typedef struct {
+ ID ckID;
+ LONG ckSize;
+ ID grpSubID;
+ UBYTE grpData[ 1 /*ckSize-4*/ ];
+ } GroupChunk;
+
+#define FORM SToLong("FORM")
+#define PLBM SToLong("PLBM")
+#define BMHD SToLong("BMHD")
+#define CMAP SToLong("CMAP")
+#define BITP SToLong("BITP")
+
+/* ---------- BitMapHeader ---------------------------------------------*/
+
+typedef enum {mskNone = 0, mskHasMask = 1, mskHasTransparentColor = 2}
+ _Masking;
+typedef UBYTE Masking; /* Lattice makes enum's LONG. what a crock.*/
+ /* Choice of masking technique.*/
+
+typedef enum {pix320x200 = 0, pix640x200 = 1, pix320x400 = 2, pix640x400 = 3,
+ pixMacintosh = 4} _PixelFormat;
+typedef UBYTE PixelFormat;
+ /* Pixel size & aspect. The first four are common television &
+ RGB resolutions. "pixMacintosh" means 72 pixels per inch (square). */
+ /* (We'll have to assign values to formats used by other cpus).*/
+
+typedef struct {
+ UWORD rowWords; /* # words in an uncompressed row */
+ UWORD w, h; /* raster width & height in pixels */
+ UBYTE depth; /* # destination bitplanes */
+ UBYTE nPlanes; /* # source bitplanes (BITP chunks) */
+ Masking masking; /* masking technique */
+ PixelFormat pixelFormat; /* pixel size and aspect */
+ Compression compression;
+ UBYTE pad1; /* UNUSED. For consistency, put 0 here.*/
+ UWORD transparentColor; /* transparent "color number" */
+ } BitMapHeader;
+
+/* ---------- SavePLBM -------------------------------------------------*/
+
+/* Save a whole screen as a PLBM. Later, modify to take a BitMap.
+ This hack is to get Greg going. Returns TRUE if error. */
+extern BOOL SavePLBM(char *, APTR, PixelFormat, WORD *, LONG);
+ /* name, screen, mode, colorMap, # planes */
+
+extern BOOL LoadPLBM(char *, struct ViewPort *, APTR,
+ PixelFormat *, WORD *, LONG *);
+ /* name, viewPort, screen,
+ ptr to mode, colorMap, ptr to #planes */
+ /* Writes to all parameters except name.*/
+
+#endif
diff --git a/PNTS.H b/PNTS.H
new file mode 100644
index 0000000..1aea495
--- /dev/null
+++ b/PNTS.H
@@ -0,0 +1,27 @@
+/*----------------------------------------------------------------------*/
+/* */
+/* pnts.h */
+/* */
+/*----------------------------------------------------------------------*/
+
+typedef struct {
+ SHORT pntmx,pntmy; /* (mx,my) current point */
+ SHORT pntlx,pntly; /* (lx,ly) last point */
+ SHORT pntsx,pntsy; /* (sx,sy) start coord (button down) */
+ SHORT pntex,pntey; /* (ex,ey) end coord (button up) */
+ SHORT pntpsx,pntpsy; /* (psx,psy) previous button down */
+ SHORT pntpex,pntpey; /* (pex,pey) previous button up */
+ } PointRec;
+
+#define mx pnts.pntmx
+#define my pnts.pntmy
+#define lx pnts.pntlx
+#define ly pnts.pntly
+#define sx pnts.pntsx
+#define sy pnts.pntsy
+#define ex pnts.pntex
+#define ey pnts.pntey
+#define psx pnts.pntpsx
+#define psy pnts.pntpsy
+#define pex pnts.pntpex
+#define pey pnts.pntpey
diff --git a/POLYF.C b/POLYF.C
new file mode 100644
index 0000000..a522d0b
--- /dev/null
+++ b/POLYF.C
@@ -0,0 +1,154 @@
+/*----------------------------------------------------------------------*/
+/* */
+/* polyf.c -- Filled Polygon drawing */
+/* */
+/*----------------------------------------------------------------------*/
+
+#include <system.h>
+#include <prism.h>
+#include <pnts.h>
+
+#define local static
+extern struct RastPort *curRP;
+extern BOOL goToPerm, symON, abortFlag;
+extern void (*doit)(), (*xorit)(), (*nop)(), (*killMode)();
+extern void FlipIt(), PaintSym(), obmv(), obclr(), vec(), EraseTempChg();
+extern PointRec pnts;
+extern Point bp;
+extern SHORT butwas,usePen;
+extern Box clipBox;
+extern SHORT clipMaxX, clipMaxY;
+extern SHORT xorg,yorg;
+extern void (*completeMode)();
+
+#define eraseFB EraseTempChg
+
+local void dotmv() {mDrawDot(mx,my); }
+
+local void chvec() { mLine(pex,pey,mx,my); }
+
+local void thinvec() {
+ SHORT svusePen = usePen; usePen = 0; vec();
+ usePen =svusePen;
+ }
+
+local void thinChVec() {
+ SHORT svusePen = usePen; usePen = 0; chvec();
+ usePen =svusePen;
+ }
+
+
+/* Filled Polygon ==========================================================*/
+
+/*---------------Magnified Area Flood ------------*/
+mFillPoly(points,np) Point *points; int np; {
+ SHORT xmin,xmax,ymin,ymax,px,py;
+ int i;
+ Box b;
+ xmin = xmax = points->x;
+ ymin = ymax = points->y;
+ UpdtON();
+ ClipInit(clipBox.x,clipBox.y, clipMaxX, clipMaxY );
+ ClipMove(curRP,points[np-1].x+xorg, points[np-1].y+yorg, bp.y);
+ for (i=0; i<np; i++) {
+ px = points->x;
+ py = points->y;
+ ClipDraw(curRP, px+xorg, py+yorg);
+ xmin = MIN(xmin,px); xmax = MAX(xmax,px);
+ ymin = MIN(ymin,py); ymax = MAX(ymax,py);
+ points++;
+ }
+ ClipEnd(curRP);
+ UpdtSibs(MakeBox(&b,xmin,ymin,xmax-xmin+1, ymax-ymin+1));
+ UpdtOFF();
+ }
+
+
+#define MAXPOLPNTS 50
+
+extern SHORT nPolPnts;
+extern Point *polPnts;
+extern struct AreaInfo areaInfo;
+extern WORD *areaBuff;
+
+void RecPnt(x,y) int x,y; {
+ if (nPolPnts>=MAXPOLPNTS) return;
+ polPnts[nPolPnts].x = x;
+ polPnts[nPolPnts].y = y;
+ nPolPnts++;
+ }
+
+FreePoly() { DFree(polPnts); polPnts = NULL; DFree(areaBuff);
+ areaBuff = NULL; }
+
+void killFPoly() {
+ int i;
+ SHORT svusePen = usePen;
+ usePen = 0;
+ TempXOR();
+ for (i=0; i<nPolPnts; i++) {
+ mLine(bp.x,bp.y, polPnts[i].x, polPnts[i].y);
+ bp.x = polPnts[i].x;
+ bp.y = polPnts[i].y;
+ }
+ FreePoly();
+ RestoreMode();
+ usePen =svusePen;
+ }
+
+local void drPoly() { mFillPoly(polPnts,nPolPnts);}
+
+local void fpolyBup() {
+ if ((nPolPnts>1)&&(Distance(mx-bp.x,my-bp.y) < 3)) {
+ goToPerm = YES;
+ mx = bp.x; my = bp.y;
+ RecPnt(mx,my);
+ if (symON){
+ abortFlag = NO;
+ SymDo(nPolPnts, polPnts, drPoly);
+ CycPaint();
+ }
+ else drPoly();
+ FreePoly();
+ }
+ else {
+ FlipIt(); /* display the current line */
+ RecPnt(mx,my); /* record the point */
+ }
+ }
+
+void complPoly() {
+ mx = bp.x; my = bp.y;
+ fpolyBup();
+ }
+
+XorMode(xorproc,down,up) void (*xorproc)(), (*down)(), (*up)(); {
+ xorit = xorproc;
+ IModeProcs(FlipIt,nop,FlipIt,down,FlipIt,nop,FlipIt, up);
+ }
+
+void IMFPoly2() {
+ xorit = thinChVec;
+ killMode = killFPoly;
+ completeMode = complPoly;
+ XorMode(thinChVec,nop,fpolyBup);
+ }
+
+local void markFStart() {
+ bp.x = mx; bp.y = my;
+ RecPnt(mx,my);
+ xorit = thinvec;
+ }
+
+void IMFPoly(restart) BOOL restart; {
+ killMode = killFPoly;
+ if (!restart) {
+ polPnts = (Point *)ChipAlloc(MAXPOLPNTS*sizeof(Point));
+ areaBuff = (WORD *)ChipAlloc(MAXPOLPNTS*5);
+ nPolPnts = 0;
+ InitArea(&areaInfo, areaBuff, MAXPOLPNTS);
+ curRP->AreaInfo = &areaInfo;
+ }
+ XorMode(dotmv,markFStart,fpolyBup);
+ }
+
diff --git a/POLYH.C b/POLYH.C
new file mode 100644
index 0000000..9aacf12
--- /dev/null
+++ b/POLYH.C
@@ -0,0 +1,56 @@
+/*----------------------------------------------------------------------*/
+/* */
+/* polyh.c -- Hollow Polygon */
+/* */
+/*----------------------------------------------------------------------*/
+
+#include <system.h>
+#include <prism.h>
+#include <pnts.h>
+
+#define local static
+
+extern BOOL goToPerm;
+extern void (*doit)(), (*xorit)(), (*nop)();
+extern void FlipIt(), PaintSym(), obmv(), obclr(), vec(), EraseTempChg();
+extern PointRec pnts;
+extern SHORT usePen, didType;
+
+#define eraseFB EraseTempChg
+
+/* Hollow Polygon ================================================================*/
+local Point bp, prevp;
+
+UndoHPoly() { pex = prevp.x; pey = prevp.y; }
+
+local void chvec() { mLine(pex,pey,mx,my); }
+local void thinChVec() {
+ SHORT svusePen = usePen; usePen = 0; chvec();
+ usePen =svusePen;
+ }
+
+local void polyBup() {
+ if (Distance(mx-bp.x,my-bp.y) < 3) {
+ goToPerm = YES;
+ mx = bp.x; my = bp.y;
+ }
+ didType = DIDHPoly;
+ PaintSym();
+ prevp.x = pex;
+ prevp.y = pey;
+ }
+
+void IMPoly2() {
+ xorit = thinChVec;
+ doit = chvec;
+ UpdtOFF();
+ IModeProcs(FlipIt,nop,FlipIt,nop,chvec,nop,eraseFB, polyBup);
+ }
+
+local void markStart() {bp.x = mx; bp.y = my; }
+
+void IMPoly() {
+ doit = &vec;
+ IModeProcs(obmv,obmv,obclr,markStart,vec,nop,eraseFB,PaintSym);
+ }
+
diff --git a/PRINT.C b/PRINT.C
new file mode 100644
index 0000000..2eb5219
--- /dev/null
+++ b/PRINT.C
@@ -0,0 +1,63 @@
+/*--------------------------------------------------------------*/
+/* */
+/* print.c */
+/* */
+/*--------------------------------------------------------------*/
+#include <system.h>
+#include <prism.h>
+#include <devices\printer.h>
+
+extern struct RastPort tempRP;
+extern struct ViewPort *vport;
+extern Box screenBox;
+extern struct BitMap hidbm;
+
+static union {
+ struct IOStdReq ios;
+ struct IODRPReq iodrp;
+ struct IOPrtCmdReq iopc;
+ } printerIO;
+
+static struct MsgPort *replyport;
+
+int pDumpRPort(rastPort, colorMap, modes, sx,sy, sw,sh, dc,dr, special)
+ struct RastPort *rastPort;
+ struct ColorMap *colorMap;
+ ULONG modes;
+ int sx, sy, sw, sh, dc, dr;
+ UWORD special;
+ {
+ int error;
+ if ((error = OpenDevice("printer.device", 0, &printerIO, 0)) != 0)
+ {
+ dprintf("EventInit \"printer.device\" OpenDevice error: %d.\n", error);
+ return(error);
+ }
+ replyport = (struct MsgPort *)CreatePort(0,0);
+ if (replyport == NULL) return(0);
+ printerIO.ios.io_Message.mn_ReplyPort = replyport;
+
+ printerIO.iodrp.io_Command = PRD_DUMPRPORT;
+ printerIO.iodrp.io_RastPort = rastPort;
+ printerIO.iodrp.io_ColorMap = colorMap;
+ printerIO.iodrp.io_Modes = modes;
+ printerIO.iodrp.io_SrcX = sx;
+ printerIO.iodrp.io_SrcY = sy;
+ printerIO.iodrp.io_SrcWidth = sw;
+ printerIO.iodrp.io_SrcHeight = sh;
+ printerIO.iodrp.io_DestCols = dc;
+ printerIO.iodrp.io_DestRows = dr;
+ printerIO.iodrp.io_Special = special;
+ DoIO(&printerIO);
+ CloseDevice(&printerIO);
+ DeletePort(replyport);
+ }
+
+PrintPic() {
+ ZZZCursor();
+ UndoSave();
+ tempRP.BitMap = &hidbm;
+ pDumpRPort(&tempRP, vport->ColorMap, vport->Modes, 0,0,
+ screenBox.w, screenBox.h, 0,0,0);
+ UnZZZCursor();
+ }
diff --git a/PRISM.C b/PRISM.C
new file mode 100644
index 0000000..053d17b
--- /dev/null
+++ b/PRISM.C
@@ -0,0 +1,379 @@
+/*----------------------------------------------------------------------*/
+/* */
+/* prism.c -- Main program */
+/* */
+/*----------------------------------------------------------------------*/
+
+#include <system.h>
+#include <librarie\dosexten.h>
+#include <prism.h>
+#include <librarie\diskfont.h>
+#include <dphook.h>
+
+#define local static
+
+extern void mainRefresh();
+extern struct Menu *MainMenu;
+extern BMOB curpenob,curbr;
+extern void mainCproc(),mainPproc(),mainMproc(),DrawMode(),ShadMode();
+extern Range cycles[];
+extern void ZZZCursor(), UnZZZCursor(), Panic();
+
+/* free up system memory which is in Limbo */
+#define MEGA (1<<20)
+
+FreeUpMem() {
+ UWORD *ptr = (UWORD *)AllocMem( MEGA, MEMF_PUBLIC );
+ if (ptr!=NULL) FreeMem(ptr, MEGA);
+ }
+
+/* ------- Procs called before and after overlay loading */
+BOOL refrAfterOverlay = YES;
+BOOL loaded = NO;
+OffRefrAfterOv() { refrAfterOverlay = NO; }
+OnRefrAfterOv() { refrAfterOverlay = YES; }
+
+void OvsPrepare() {
+ if (loaded) {UndoSave(); ZZZCursor();} }
+void OvsEnd() {
+ if (loaded) {
+ if (refrAfterOverlay) {
+ PaneRefrAll();
+ }
+ UnZZZCursor();
+ }
+ }
+
+/*------------ Lots of Global Variables -----*/
+
+OVSInfo ovsInfo = {OVS_LOAD_ALL, OvsPrepare, OvsEnd, Panic};
+
+BOOL modeHelp = YES;
+BOOL underWBench= NO,loadAFile = NO;
+
+long GfxBase = 0;
+long IntuitionBase=0;
+long IconBase=0;
+
+/* for "hook" */
+struct BitMap *clientBitMap = NULL;
+BOOL myDPHook;
+DPHook *dphook = NULL;
+UBYTE DPName[] = "DeluxePaint";
+
+SharingBitMap() { return(!myDPHook ||(dphook->refCount>0)); }
+HookActive() {return(myDPHook && (dphook->refCount>0));}
+
+struct Window *mainW;
+struct Screen *screen;
+struct RastPort *mainRP;
+struct ViewPort *vport;
+BOOL haveWBench = YES;
+Box mainBox;
+Pane mainP = {0};
+BOOL largeMemory = NO; /* yes means 512 machine */
+SHORT curFormat = 0; /* current screen format */
+SHORT curDepth = 5;
+SHORT curMBarH = 11;
+SHORT xShft,yShft;
+
+Box screenBox = {0};
+struct BitMap hidbm = {0};
+struct TmpRas tmpRas = {0};
+struct RastPort tempRP = {0};
+struct RastPort screenRP = {0};
+
+UBYTE version[] = "(1.0)";
+UBYTE dpaintTitle[] = "DPaint";
+
+PaletteGlobals paletteGlobals = {0, 11, 1, cycles};
+
+/* ----------- Palettes ------------------------------------- */
+SHORT nColors;
+
+SHORT default5[32]= {
+ 0, 0xfff, 0xe00, 0xa00, 0xd80, 0xfe0, 0x8f0, 0x080,
+ 0x0b6, 0x0dd, 0x0af, 0x07c, 0x00f, 0x70f, 0xc0e, 0xc08,
+ 0x620, 0xe52, 0xa52, 0xfca, 0x333, 0x444, 0x555, 0x666,
+ 0x777, 0x888, 0x999, 0xaaa, 0xbbb, 0xccc, 0xddd, 0xeee};
+
+#ifdef stevespalette
+SHORT default5[32]= {
+ 0, 0xfff, 0xddd, 0xaaa, 0x888, 0x666, 0x444, 0x222,
+ 0xf88, 0xfb8, 0xff8, 0xbf8, 0x8f8, 0x8ff, 0x88f, 0xf8f,
+ 0xf00, 0xf80, 0xff0, 0x8f0, 0x0f0, 0x0af, 0x00f, 0xf0f,
+ 0xa00, 0x940, 0x880, 0x590, 0x060, 0x077, 0x007, 0x808};
+#endif
+SHORT default4[16]= { 0, 0xfff, 0xc00, 0xf60, 0x090, 0x3f1,0x00f,0x2cd,
+ 0xf0c, 0xa0f, 0x950, 0xfca, 0xfe0, 0xccc,0x888,0x444};
+SHORT default3[8] = { 0, 0xfff, 0xb00, 0x080, 0x24c, 0xeb0, 0xb52, 0x0cc};
+SHORT default2[4] = {0,0xfff,0x55f,0xf80};
+SHORT default1[2] = {0,0xfff};
+
+#ifdef dansway
+UBYTE initBGCol[]= {0,0,0,0,14,25}; /* initial background color [depth] */
+UBYTE initFGCol[]= {1,1,1,1,0,0}; /* initial forground color [depth] */
+#else /*grady's way */
+UBYTE initBGCol[]= {0,0,0,0,0,0}; /* initial background color [depth] */
+UBYTE initFGCol[]= {1,1,1,1,1,1}; /* initial forground color [depth] */
+#endif
+
+SHORT *defPals[] = {NULL,default1,default2,default3,default4,default5};
+SHORT LoadBrColors[32]; /* colors loaded with the brush */
+SHORT prevColors[32]; /* previous palette before loading picture
+ or doing Use Brush Palette */
+
+/* ---- Current Brush ---------------------------------------- */
+SHORT curpen;
+struct BitMap brBM={0},brSVBM={0};
+struct BitMap penBM={0},penSVBM={0};
+BMOB curpenob = { { INITBOX, &penBM}, {INITBOX,&penSVBM},
+ NULL,0,0,NO,0, COOKIEOP, 0xff,0};
+BMOB curbr = { { INITBOX, &brBM}, {INITBOX,&brSVBM},
+ NULL,0,0,NO,0, COOKIEOP, 0xff,0};
+
+/* ----- Text and font Info -------------------------------------*/
+
+/* ----- Text data ---------- */
+SHORT cx,cy,cwidth;
+char textBuf[80];
+SHORT textX, textY;
+SHORT textX0,cw,ch,cyoffs;
+SHORT ptext = 0;
+SHORT svmd = 0;
+BOOL tblinkOn = NO;
+SHORT tbCount = 0;
+
+#define TXHEIGHT 8
+struct TextAttr TestFont = { "topaz.font", TXHEIGHT, 0, 0, };
+LONG DiskfontBase= NULL;
+struct AvailFonts *fontDir = NULL;
+SHORT nFonts = 0;
+SHORT curFontNum = -1;
+struct TextFont *font = NULL;
+
+MyCloseFont(font) struct TextFont *font; {
+ struct Node *nd;
+ if (font!=NULL) {
+ if ( (font->tf_Flags&(FPF_ROMFONT|FPF_DISKFONT)) == FPF_DISKFONT) {
+ nd = &font->tf_Message.mn_Node;
+ if ((nd->ln_Pred->ln_Succ == nd) &&
+ (nd->ln_Succ->ln_Pred == nd)) RemFont(font);
+ }
+ CloseFont(font);
+ }
+ }
+
+/*--- file io pathnames and filenames ---------- */
+UBYTE picpath[31] = "";
+UBYTE picname[31] = "";
+UBYTE brspath[31] = "brush";
+UBYTE brsname[31] = "";
+
+/*---- Original brush and transform ( brxform )-----------*/
+struct BitMap origBM = {0};
+BMOB origBr = { { INITBOX, &origBM}, {INITBOX,NULL},
+ NULL,0,0,NO,0, COOKIEOP, 0xff,0};
+SHORT curBrXform = NOXFORM;
+
+/* This gets rid of the "original" bitmap and sets the state to
+ " no transform" */
+ClearBrXform() {
+ FreeBitMap(&origBM);
+ DFree(origBr.mask);
+ origBr.mask = NULL;
+ curBrXform = NOXFORM;
+ }
+
+/* --- BMOB stuff ------ */
+SHORT lastSmX, lastSmY;
+SHORT dbgbmob = 0;
+struct BitMap tmpbm = {0};
+BoxBM temp = {{0,0,0,0},&tmpbm};
+struct BitMap tmpbm2 = {0};
+BoxBM temp2 = {{0,0,0,0},&tmpbm2};
+
+/* --------------spare bitmap----------------*/
+BOOL spareThere = NO;
+BOOL newSpare = YES;
+BOOL didMerge = NO;
+SHORT spareXPCol = 0;
+struct BitMap sparebm = {0};
+FreeSpare() {
+ if (spareThere) FreeBitMap(&sparebm);
+ spareThere = NO;
+ }
+
+
+/* --------------Filled polygon----------------*/
+SHORT nPolPnts = 0;
+Point *polPnts = NULL;
+struct AreaInfo areaInfo;
+WORD *areaBuff = NULL;
+
+GunTheBrush() { /* dump the current brush to free storage */
+ RestoreBrush();
+ FreeBMOB(&curbr);
+ SelPen(0);
+ }
+
+void Panic() {
+ GunTheBrush();
+ }
+
+SetOverlay(tight) BOOL tight; {
+ ovsInfo.type = tight? OVS_DUMB: OVS_LOAD_ALL;
+ InitOVS(&ovsInfo);
+ }
+
+
+/*---------- Copyright Notice ------------------*/
+DoText(s,x,y) char *s; int x,y; {
+ Move(&screenRP,x,y);
+ Text(&screenRP,s,strlen(s));
+ }
+
+CopyWText(x,y) {
+ DoText(" -- Deluxe Paint -- ", x,y);
+ DoText(" by Daniel Silva ", x,y+30);
+ DoText(" (c) 1986 by Electronic Arts", x,y+60);
+ }
+
+#define CW_WIDTH 280
+#define CW_HEIGHT 120
+CopyWNotice() {
+ int x,y;
+ x = (screenBox.w-PMapX(48) - CW_WIDTH)/2;
+ y = (screenBox.h - CW_HEIGHT)/2;
+ SetOPen(&screenRP,1);
+ SetAPen(&screenRP,3);
+ RectFill(&screenRP, x, y, x+CW_WIDTH-1, y+CW_HEIGHT-1);
+ BNDRYOFF(&screenRP);
+ SetAPen(&screenRP,0);
+ SetDrMd(&screenRP,JAM1);
+ CopyWText(x+6, y + 30);
+ SetAPen(&screenRP,1);
+ CopyWText(x+5, y + 29);
+ }
+
+
+/* -------------------------------------------------------- */
+struct Process *myProcess;
+struct Window *svWindowPtr;
+
+/*----------------------------------------------------------------------*/
+/* Yes, this is it, the MAIN PROGRAM: */
+/*----------------------------------------------------------------------*/
+main(argc,argv) int argc; char *argv[]; {
+ DPInit(argc,argv); /* initialization code */
+ NewIMode(IM_draw);
+ SetAirBRad(PMapX(24)); /* also brings in the drawing overlay*/
+#ifdef DOWB
+ if (loadAFile) LoadPic();
+#endif
+ CopyWNotice();
+ loaded = YES;
+ PListen(); /* this is the program */
+ if (!haveWBench) BootIT();
+ else CloseDisplay();
+ }
+
+/* Allocate and Free temp Raster --------------- */
+AllocTmpRas() {
+ int plsize = mainRP->BitMap->BytesPerRow*mainRP->BitMap->Rows;
+ DFree(tmpRas.RasPtr);
+ tmpRas.RasPtr = (BYTE *)ChipAlloc(plsize);
+ if (tmpRas.RasPtr==NULL) InfoMessage(" Couldnt alloc", "tmpRas. ");
+ tmpRas.Size = plsize;
+ mainRP->TmpRas = &tmpRas; /* temp raster for area filling*/
+ }
+
+FreeTmpRas() {
+ DFree(tmpRas.RasPtr);
+ tmpRas.RasPtr = NULL;
+ }
+
+/** misc utilities that should probably be elsewhere ----- */
+
+ConcatPath(path,ext) UBYTE *path,*ext; {
+ int lp;
+ lp = strlen(path);
+ if ( (lp>0)&& (path[lp-1] != ':')) strcat(path,"/");
+ strcat(path,ext);
+ }
+
+/** Set raster port for xor-ing with current foreground
+ color (instead of with 0xffff as COMPLEMENT mode does */
+#define NOOP 0xaa
+SetXorFgPen(rp) struct RastPort *rp; {
+ SHORT pen = rp->FgPen;
+ SHORT bit = 1;
+ SHORT i;
+ for (i=0; i<rp->BitMap->Depth; i++) {
+ rp->minterms[i] = (bit&pen) ? XORMASK : NOOP;
+ bit <<=1;
+ }
+ }
+
+
+/** ------ Palette operations ----- */
+
+GetColors(cols) SHORT *cols; {
+ int i;
+ for (i = 0; i<nColors; i++) cols[i] = GetRGB4(vport->ColorMap,i);
+ }
+
+LoadCMap(cols) SHORT *cols; { LoadRGB4(vport,cols,nColors); }
+
+BasicBandW() { SetRGB4(vport,0,0,0,0); SetRGB4(vport,1,15,15,15);}
+
+InitPalette() { GetColors(prevColors); }
+RestorePalette() { LoadCMap(prevColors);}
+DefaultPalette() { InitPalette(); LoadCMap(defPals[curDepth]); }
+
+SetColReg(n,col) int n, col; {
+ SetRGB4(vport, n, (col>>8)&15, (col>>4)&15, col&15);
+ }
+
+local SHORT svcol0,svcol1,svcol2,svcol3;
+
+/** this gets called before going into menu (at MenuVerify) */
+FixMenCols() {
+ SHORT colors[32];
+ FreeTmpRas();/* make room for menu to save under area*/
+ PauseCCyc();
+ if (curDepth>2) {
+ GetColors(colors);
+ svcol0 = colors[0];
+ svcol1 = colors[1];
+ svcol2 = colors[nColors-2];
+ svcol3 = colors[nColors-1];
+ SetColReg(0,0);
+ SetColReg(1,0xfff);
+ SetColReg(nColors-2,0x8ac); /* 0 */
+ SetColReg(nColors-1,0x900); /* 0xfff */
+ }
+ }
+
+/** ---- This gets called after menu */
+UnFixMenCols() {
+ AllocTmpRas();
+ if (curDepth>2) {
+ SetColReg(0,svcol0);
+ SetColReg(1,svcol1);
+ SetColReg(nColors-2,svcol2);
+ SetColReg(nColors-1,svcol3);
+ }
+ ResumeCCyc();
+ }
+
+local ULONG lastAvMem = NULL;
+
+/**
+PrAvail(s) char *s; {
+ ULONG avmem = AvailMem(MEMF_PUBLIC|MEMF_CHIP);
+ printf("Avail Mem %-27s = %ld (%7ld)\n",s,avmem, avmem - lastAvMem);
+ lastAvMem = avmem;
+ }
+**/
+
diff --git a/PRISM.H b/PRISM.H
new file mode 100644
index 0000000..1de1bab
--- /dev/null
+++ b/PRISM.H
@@ -0,0 +1,415 @@
+/*----------------------------------------------------------------------*/
+/* */
+/* prism.h */
+/* */
+/*----------------------------------------------------------------------*/
+
+/* this affects <prism,pgraph,mainmag,.. > */
+/*#define THEIRWAY*/
+
+#define FIXALIGN static short d1; static short d2=2; static short d3 = 0;
+
+#define F1Key 0x3b
+#define F2Key 0x3c
+#define F3Key 0x3d
+#define F4Key 0x3e
+#define F5Key 0x3f
+#define F6Key 0x40
+#define F7Key 0x41
+#define F8Key 0x42
+#define F9Key 0x43
+#define F10Key 0x44
+#define HELPKEY 0x01
+#define CLeft 0x4b
+#define CRight 0x4d
+#define CUp 0x50
+#define CDown 0x48
+
+
+#define ESC 0x1b
+#define CR 0xd
+#define BS 8
+#define TAB 9
+#define NoChar 0xff
+#define YES 1
+#define NO 0
+#define POSITIVE 1
+#define NEGATIVE 0
+#define FAIL 1
+#define SUCCESS 0
+
+/*----------------------------------------------------------------------*/
+/* Paint Modes */
+/*----------------------------------------------------------------------*/
+#define NPaintModes 8
+typedef SHORT PaintMode;
+
+/* changing this enumerated type requires changes to arrays
+ in menu,pgraph,dispnum, bmob */
+
+#define Mask 0
+#define Color 1
+#define Replace 2
+#define Smear 3
+#define Shade 4
+#define Blend 5
+#define CyclePaint 6 /* same as Color, but paint colors cycle*/
+#define Xor 7
+
+
+/*----------------------------------------------------------------------*/
+/* Blitter Address */
+/*----------------------------------------------------------------------*/
+#define BLTADDR 0xDFF040
+
+/*----------------------------------------------------------------------*/
+/* Blitter Op Codes (for BltBitMap and BltRaster) */
+/*----------------------------------------------------------------------*/
+#define REPOP 0xCC /* B */
+#define NOTOP 0x33 /* !B */
+#define XOROP 0x66 /* B xor C */
+#define XORMASK 0x6A
+#define OROP 0xEE /* B+C */
+#define NOTOROP 0xBB /* (!B)+C */
+#define ANDOP 0x88 /* BC */
+#define NOTANDOP 0x22 /* (!B)C */
+#define COOKIEOP 0xca /* AB + (!A)C */
+#define BMINUSC 0x44
+#define CMINUSB 0x22
+
+#define PLUSOP CMINUSB
+#define MINUSOP ANDOP
+
+/*--- blitter size word ----- */
+#define BlitSize(bpr,h) ((h<<6)|(bpr>>1))
+
+
+/* CONSTANTS for incrementing Color table values */
+#define REDC 0x100
+#define GREENC 0x10
+#define BLUEC 0x1
+
+
+#define BITNOT(v) (v^0xffff)
+#define SWAP(a,b) a ^= b; b ^= a; a ^= b;
+#define ORDER(a,b) if ((a)>(b)) {SWAP(a,b); }
+#define MAX(a,b) ((a)>(b)?(a):(b))
+#define MIN(a,b) ((a)<(b)?(a):(b))
+#define ABS(a) ((a)>0?(a):-(a))
+#define SIGNUM(a) ((a)>0)
+
+#define WordsNeeded(w) (((w)+15)>>4)
+#define BytesNeeded(w) ( (((w)+15)>>3)&0xfffe)
+#define PlaneSize(w,h) (BytesNeeded(w)*(h))
+#define BMPlaneSize(bm) ((bm)->BytesPerRow*(bm)->Rows)
+
+/*----------------------------------------------------------------------*/
+/* Virtual Coordinate System */
+/*----------------------------------------------------------------------*/
+/* convert "virtual coords" to "physical device coords" */
+#define PMapX(x) ( (x) >> xShft )
+#define PMapY(y) ( (y) >> yShft )
+
+/* convert "physical device coords" to "virtual coords" */
+#define VMapX(x) ( (x) << xShft )
+#define VMapY(y) ( (y) << yShft )
+
+/*----------------------------------------------------------------------*/
+/* Graphics Data Structures */
+/*----------------------------------------------------------------------*/
+typedef LONG LongFrac;
+typedef struct { SHORT x,y; } Point;
+typedef struct { SHORT w,h; } Dims;
+typedef struct { SHORT x,y,w,h; } Box;
+
+#ifndef GRAPHICS_GFX_H
+#include <graphics\gfx.h>
+#endif
+
+/*----------------------------------------------------------------------*/
+/* FIll patterns */
+/*----------------------------------------------------------------------*/
+#define PATHIGH 8
+#define PATWIDE 8
+#define PATMOD 7
+
+/*----------------------------------------------------------------------*/
+/* BoxBM -- Box + Bitmap */
+/*----------------------------------------------------------------------*/
+typedef struct { Box box; struct BitMap *bm; } BoxBM;
+
+#define INITBOX {0,0,0,0}
+#define INITBoxBM { INITBOX, NULL}
+
+/*----------------------------------------------------------------------*/
+/* BMOB -- Masked Bitmap Object */
+/*----------------------------------------------------------------------*/
+#define SHOWING 1
+#define TOOBIGTOPAINT 2
+typedef struct {
+ BoxBM pict,save;
+ UBYTE *mask;
+ SHORT xoffs,yoffs;
+ UBYTE flags;
+ UBYTE xpcolor;
+ UBYTE minTerm;
+ UBYTE planeUse,planeDef;
+ } BMOB;
+
+#define INITBMOB { INITBoxBM, INITBoxBM, NULL, 0, 0, NO, 0, COOKIEOP, 0xff, 0 }
+
+/*----------------------------------------------------------------------*/
+/* Pane -- A Sub-window Object */
+/*----------------------------------------------------------------------*/
+/* flag values */
+#define ALWAYS 1
+#define HANGON 2
+#define BORDER 4
+
+typedef void (*ProcHandle)();
+
+typedef struct Pane0 {
+ USHORT flags;
+ Box box;
+ ProcHandle charProc,mouseProc,paintProc;
+ ULONG client;
+ struct Pane0 *next;
+ } Pane;
+
+/* mouse events: you can choose to be called when the program loops
+ even though the mouse didnt move */
+
+typedef enum { NONE,LOOPED,MOVED,BDOWN,BUP,ENTER,LEAVE } MouseEvent;
+
+/* ----- Activities -------*/
+#define nullAct 0
+#define shadeAct 1
+#define drawAct 2
+#define vectAct 3
+#define curvAct 4
+#define fillAct 5
+#define airbAct 6
+#define rectAct 7
+#define frectAct 8
+#define circAct 9
+#define fcircAct 10
+#define ovalAct 11
+#define fovalAct 12
+#define polyAct 13
+#define fpolyAct 14
+#define selbAct 15
+#define textAct 16
+#define gridAct 17
+#define symAct 18
+#define magAct 19
+#define zoomAct 20
+#define undoAct 21
+#define clrAct 22
+
+
+typedef SHORT CursID;
+#define Arrow 0
+#define FillCan 1
+#define Pencil 2
+
+
+/* Pen TYPE ENcoding */
+#define USERBRUSH -1
+#define ROUND_B 1
+#define SQUARE_B 2
+#define DOT_B 3
+#define AIR_B 4
+#define RoundB(n) ((ROUND_B<<12)|n)
+#define SquareB(n) ((SQUARE_B<<12)|n)
+#define DotB(n) ((DOT_B<<12)|n)
+
+/*----------------------------------------------------------------------*/
+/* Magnify Context */
+/*----------------------------------------------------------------------*/
+typedef struct {
+ SHORT magN; /* Magnification factor */
+ struct RastPort *srcRP; /* The source RasterPort */
+ Box *srcBox; /* The clip box of source in its Raster */
+ Point srcPos; /* The position of the view box relative*/
+ /* to the backing bitmap */
+ struct BitMap *magBM; /* The magnify BitMap */
+ Box *magBox; /* Clip Box of magnify view in magBM. */
+ Point magPos; /* The position of magnify view rel */
+ /* to backing bitmap */
+ void (*updtProc)(); /* Procedure to call to update the */
+ /* backing bitmap. (takes *Box as */
+ /* parameter, BBM relative); */
+ } MagContext;
+
+
+/* kinds of window */
+#define MAINWIN 1
+#define MAGWIN 2
+
+/* Brush Transform states */
+#define NOXFORM 0
+#define STRETCHED 1
+#define ROTATED 2
+#define SHEARED 3
+#define BENT 4
+
+/*** CURSOR TYPES *********/
+#define NOCURSOR 0
+#define DEFCURSOR 1
+#define FILLCURSOR 2
+#define CROSSCURSOR 3
+#define ZZZCURSOR 4
+#define SIZECURSOR 5
+#define PICKCURSOR 6
+
+/*----------------------------------------------------------------------*/
+/* -Interaction Modes (IMODES) */
+/*----------------------------------------------------------------------*/
+#define IM_none 0xff
+#define IM_null 0
+#define IM_shade 1
+#define IM_draw 2
+#define IM_vect 3
+#define IM_curve1 4
+#define IM_curve2 5
+#define IM_rect 6
+#define IM_frect 7
+#define IM_circ 8
+#define IM_fcirc 9
+#define IM_oval 10
+#define IM_foval 11
+#define IM_selBrush 12
+#define IM_magSpec 13
+#define IM_fill 14
+#define IM_text1 15
+#define IM_text2 16
+#define IM_gridSpec 17
+#define IM_symCent 18
+#define IM_readPix 19
+#define IM_strBrush 20
+#define IM_rotBrush 21
+#define IM_shrBrush 22
+#define IM_sizePen 23
+#define IM_poly 24
+#define IM_poly2 25
+#define IM_fpoly 26
+#define IM_fpoly2 27
+#define IM_airBrush 28
+#define IM_getFPat 29
+#define IM_hbendBrush 30
+#define IM_vbendBrush 31
+
+#define NIMODES 32
+
+typedef UBYTE IMode;
+
+typedef struct {
+ UWORD flags; /* see below */
+ UBYTE cursor; /* what cursor to use */
+ UBYTE activity; /* ctr panel activity for this */
+ UBYTE symNpoints; /* number of points to be transformed*/
+ IMode nextIMode; /* for chaining */
+ void (*startProc)(); /* call this to plug mode procs*/
+ } IModeDesc;
+
+
+/* Flag Definitions */
+#define PERM 1 /* for permanent modes */
+#define NOGR (1<<1) /* dont do grid for this mode */
+#define NOBR (1<<2) /* this mode doesn't use the brush (e.g. frect )
+ this is used in determining how big of a rectangle has
+ been touched on the screen*/
+#define NOSYM (1<<3) /* dont do symmetry at all */
+#define SYMUP (1<<4) /* show symmetry feedback when button is up*/
+#define SYMDN (1<<5) /* show symmetry feedback when button is down*/
+#define SLAVE (1<<6) /* not a "master" mode */
+#define NOLOCK (1<<7) /* Cant lock by double clicking */
+#define EVTIM (1<<8) /* Call every time while button down*/
+#define PNTWDN (1<<9) /* Turn on paint (UpdtON) while button is down*/
+#define COMPLETE (1<<10) /* Call completeMode when space bar hit */
+#define RIGHTBUT (1<<11) /* Set later if mode invoked w/right button*/
+#define NOERASE (1<<12) /* Dont erase with right button*/
+#define NOCON (1<<13) /* Dont constrain with shift key*/
+#define SYMALL SYMUP|SYMDN
+#define DEFC DEFCURSOR
+
+
+/*----------------------------------------------------------------------*/
+/* Color Cycles */
+/*----------------------------------------------------------------------*/
+#define MAXNCOLORS 32
+#define MAXNCYCS 4
+typedef struct {
+ SHORT count;
+ SHORT rate;
+ BOOL active;
+ UBYTE low,high; /* bounds of range */
+ } Range;
+
+
+/*----------------------------------------------------------------------*/
+/* Air Brush */
+/*----------------------------------------------------------------------*/
+
+#define INITABRADIUS 12
+
+extern BOOL haveWBench;
+
+#define dprintf if (haveWBench) printf
+
+
+/*----------------------------------------------------------------------*/
+/* Palette interface */
+/*----------------------------------------------------------------------*/
+
+/* A typical client.*/
+/* Usage: PaletteTool(struct Window *, PaletteGlobals *); */
+
+typedef struct {
+ WORD paletteX, paletteY;
+ /* LeftEdge,TopEdge for palette window.
+ * Client can change these to force window to appear elsewhere.
+ * If user drags window, these are updated before return to client.*/
+ WORD paletteRange; /* Index of range currently examined.*/
+ Range *ranges; /* LIM_RANGES Range's */
+ } PaletteGlobals;
+
+
+/*----------------------------------------------------------------------*/
+/* Blitter registers */
+/*----------------------------------------------------------------------*/
+
+typedef struct {
+ USHORT bltcon0,bltcon1,fwmask,lwmask;
+ UBYTE *bltptc,*bltptb,*bltpta,*bltptd;
+ USHORT bltsize;
+ SHORT ioskip2[3];
+ SHORT bltmdc,bltmdb,bltmda,bltmdd;
+ SHORT ioskip3[4];
+ USHORT cdata,bdata,adata;
+ } BlitterRegs;
+
+/*----------------------------------------------------------------------*/
+/* DID types ( for UNDO ) */
+/*----------------------------------------------------------------------*/
+
+#define DIDNothing 0
+#define DIDClear 1
+#define DIDMerge 2
+#define DIDHPoly 3
+
+
+/*----------------------------------------------------------------------*/
+/* OVSInfo : for configuring the overlay system */
+/*----------------------------------------------------------------------*/
+#define OVS_DUMB 0
+#define OVS_SMART 1
+#define OVS_LOAD_ALL 2
+
+typedef struct {
+ LONG type;
+ void (*sleepCursor)();
+ void (*wakeCursor)();
+ void (*panic)();
+ } OVSInfo;
+ \ No newline at end of file
diff --git a/PRISM.txt b/PRISM.txt
new file mode 100644
index 0000000..de98631
--- /dev/null
+++ b/PRISM.txt
@@ -0,0 +1,22 @@
+ROOT astartup.o, prism.o, menu.o, chproc.o, curbrush.o*
+paintw.o, modes.o, geom.o, conic.o*
+psym.o, lfmult.o, pane.o*
+mainmag.o, magops.o, magwin.o, magbits.o*
+pgraph.o, bitmaps.o, bmob.o*
+blitops.o, maskblit.o, dalloc.o, box.o*
+dispnum.o,keyjunk.o, distance.o, mousebut.o, ctrpan.o*
+penmenu.o, actbms.o, cursor.o, cursbms.o, dotbms.o*
+message.o, ccycle.o, reqcom.o, timer.o, brxform.o
+OVERLAY
+initovs.o, dpinit.o, dpinit2.o, fontinit.o, bootit.o, hook.o,
+fill.o, airbrush.o, random.o, polyh.o, blend.o, shade.o, polyf.o, clip.o, text.o
+rot90.o, stretch.o, rotate.o, shear.o, remap.o, bend.o, print.o, spare.o
+dopalett.o, palette.o, palbms.o hsv.o
+dosymreq.o,symreq.o
+dpio.o, fnreq.o, fnbms.o, dpiff.o
+*initread.o, ilbmr.o, unpacker.o,iffr.o
+*initwrite.o, ilbmw.o, packerf.o, copymem.o, iffw.o, makeicon.o
+#
+LIBRARY amiga.lib, lc.lib, debug.lib
+TO prism
+
diff --git a/PSYM.C b/PSYM.C
new file mode 100644
index 0000000..2ef6d13
--- /dev/null
+++ b/PSYM.C
@@ -0,0 +1,132 @@
+/*--------------------------------------------------------------*/
+/* */
+/* Symmetry */
+/* */
+/* 2/26/85 ------ D.Silva */
+/*--------------------------------------------------------------*/
+#include <system.h>
+#include <prism.h>
+
+extern SHORT xShft, yShft;
+
+#define local
+
+#define min(a,b) ( (a)<(b) ? (a): (b) )
+#define max(a,b) ( (a)>(b) ? (a): (b) )
+#define abs(a) ( (a>0) ? (a): -(a) )
+
+/* define a 32 bit fixed point number with 16 bits of fraction */
+
+typedef struct{SHORT x,y;} SPoint;
+
+extern LongFrac LFMULT();
+
+#define epsi 2
+local LongFrac pi =0x3243FL;
+local LongFrac halfpi =0x1921FL;
+local LongFrac twopi = 0x6487EL;
+
+/* sin of x (x in radians ) */
+LongFrac lfsin(x) LongFrac x; {
+ int n;
+ LongFrac res,inc,xsq;
+ BOOL neg = NO;
+ if (x<0) {x = -x; neg = !neg;}
+ x = x%twopi;
+ if (x>pi) {x -= pi; neg = !neg;}
+ if (x>halfpi) x = pi-x;
+ res = inc = x;
+ xsq = LFMULT(x,x);
+ n = 2;
+ while (abs(inc)>epsi) {
+ inc = -LFMULT(inc,xsq)/(n*(n+1));
+ res += inc;
+ n += 2;
+ }
+ return(neg?-res:res);
+ }
+
+/* cos of x (x in radians ) */
+#define lfcos(x) lfsin(x+halfpi)
+
+#define NSYMMAX 40
+
+SHORT nSym;
+
+local SHORT pxsym,xsym,ysym,nSymhalf;
+
+local SHORT sintab[20],costab[20];
+
+#define ISin(ang) ((ang>nSymhalf)? -sintab[nSym-ang]: sintab[ang])
+#define ICos(ang) ((ang>nSymhalf)? costab[nSym-ang]: costab[ang])
+
+#define SCF 14
+#define oneHalf (1<<(SCF-1))
+
+BOOL mirror = NO;
+
+SymSetNMir(n,mir) int n; BOOL mir; {
+ LongFrac a;
+ int i;
+ mirror = mir;
+ nSym=max(min(n,NSYMMAX),1);
+ nSymhalf = nSym/2;
+ for (i=0; i<=nSymhalf; i++) {
+ a = (i*twopi)/n;
+ sintab[i]= (SHORT) (lfsin(a) >> (16-SCF)) ;
+ costab[i]= (SHORT) (lfcos(a) >> (16-SCF)) ;
+ }
+ }
+
+SymSet(n,mir,xc,yc) int n,xc,yc; BOOL mir; {
+ mirror = mir;
+ pxsym = xc;
+ xsym = VMapX(xc);
+ ysym = VMapY(yc);
+ SymSetNMir(n,mir);
+ }
+
+SymCenter(xc,yc) int xc,yc; { pxsym = xc; xsym = VMapX(xc); ysym = VMapY(yc); }
+
+/*--------------------------------------------------------------*/
+/* SymDo */
+/* */
+/* Calls proc for each symmetry position, with the array */
+/* pts[] updated to reflect the symmetry */
+/* */
+/*--------------------------------------------------------------*/
+
+void SymDo(np,pts,proc)
+ int np; /* Number of Points */
+ SPoint *pts; /* Array of points to update */
+ int(*proc)(); /* Proc to call for each symmetry pos */
+ {
+ SPoint dp[20],svpts[20];
+ SHORT sj,cj,i,j;
+ SHORT ddx,ddy;
+ LONG lx,ly;
+ movmem(pts,svpts,np*sizeof(SPoint));
+ for (i=0; i<np; i++) {
+ dp[i].x = VMapX(pts[i].x)-xsym;
+ dp[i].y = VMapY(pts[i].y)-ysym;
+ }
+ for (j=0; j<nSym; j++) {
+ sj = ISin(j); cj = ICos(j);
+ for (i=0; i<np; i++) {
+ ddx = dp[i].x; ddy = dp[i].y;
+ lx = PMapX(xsym + ( (ddx*cj+ddy*sj+oneHalf) >> SCF ));
+ ly = PMapY(ysym +( (-ddx*sj+ddy*cj+oneHalf) >> SCF ));
+ pts[i].x = lx;
+ pts[i].y = ly;
+ }
+ (*proc)();
+ if (CheckAbort()) break;
+ if (mirror) {
+ for (i=0; i<np; i++) pts[i].x = 2*pxsym - pts[i].x;
+ (*proc)();
+ }
+ if (CheckAbort()) break;
+ }
+ movmem(svpts,pts,np*sizeof(SPoint));
+ }
+
diff --git a/RANDOM.C b/RANDOM.C
new file mode 100644
index 0000000..5daca72
--- /dev/null
+++ b/RANDOM.C
@@ -0,0 +1,35 @@
+/*--------------------------------------------------------------*/
+/* */
+/* random.c */
+/* */
+/*--------------------------------------------------------------*/
+#include <exec\types.h>
+
+/* ---- Random Number Generator ----- */
+
+static SHORT rvect[32] = {
+ 0x3d52,0x7f31,0x80a2,0xed16,0x42bf,0x5c41,0x0c5e,0x9226,
+ 0xa58b,0x482d,0x64d9,0x82ad,0xe179,0x214b,0x814c,0xd736,
+ 0x97cf,0xaeb1,0xf7cb,0x6a9b,0x0c59,0x8534,0x7189,0x1593,
+ 0x6bc5,0x07ac,0x3c7f,0xa43e,0xda69,0x181e,0x9bd1,0xd57f
+ };
+
+static randi1=0;
+static randi2=15;
+
+/* dont need to call this unless want to get different series of nums */
+InitRand(seed) SHORT seed; { int i; for (i=0; i<32; i++) rvect[i] += seed; }
+
+/* Return a 16 bit random bit pattern */
+SHORT Rand16() {
+ SHORT res = rvect[randi1] = rvect[randi1] + rvect[randi2];
+ randi1 = (randi1+1)&31; randi2 = (randi2+1)&31;
+ return(res);
+ }
+
+/* Returns a 15 bit random number in range [0..n-1] */
+
+SHORT Random(n) int n; { return((SHORT)((Rand16()&0x7fff)%n)); }
+
+static SHORT dummy;
+
diff --git a/REMAP.C b/REMAP.C
new file mode 100644
index 0000000..1b03720
--- /dev/null
+++ b/REMAP.C
@@ -0,0 +1,170 @@
+/*----------------------------------------------------------------------*/
+/* */
+/* ReMap Brush colors to better fit current color palette */
+/* */
+/*----------------------------------------------------------------------*/
+
+#include <system.h>
+#include <prism.h>
+
+extern SHORT nColors, curpen, curDepth;
+extern struct RastPort tempRP;
+extern BMOB curbr;
+extern short LoadBrColors[];
+
+/* A simple minded distance measure */
+#ifdef linearsum
+SHORT cdist(a,b) SHORT a,b; {
+ int i;
+ SHORT sum = 0;
+ for (i=0; i<3; i++) {
+ sum += ABS((a&0xf) - (b&0xf));
+ a>>=4; b>>=4;
+ }
+ return(sum);
+ }
+
+#else
+
+/* Another distance measure: sum of square R G B deltas */
+SHORT cdist(a,b) SHORT a,b;{
+ SHORT t, sum = 0;
+ int i;
+ for (i=0; i<3; i++) {
+ t = (a&0xf) - (b&0xf);
+ sum += t*t;
+ a>>=4; b>>=4;
+ }
+ return(sum);
+ }
+
+#endif
+
+SHORT dbgcmap = 1;
+
+
+/* This maps bitmap colors to a good fit in the current color palette.
+ if the brush has more planes than the current format, it will be
+ reduced to the correct number of planes
+
+ The algorithm is: first sort the colors in the source bitmap by
+ number of occurences in the bitmap. Then, starting with the most
+ commonly occuring color, find the closed color in the current
+ palette and assign it to that color, eliminating it from further
+ use. Repeat this for the sorted list of source colors, until all are
+ assigned. If mapping down to fewer planes, use this algorithm
+ until all the colors in the color palette are used up, then
+ continue but no thenceforth let ALL the colors in the color
+ pallet be candidates for the closest match.*/
+
+/* returns new transparent color */
+SHORT BMRemapCols(sbm,oldpal,oldxpc, newpal, newDepth)
+ struct BitMap *sbm;
+ SHORT *oldpal, oldxpc, *newpal, newDepth;
+ {
+ int x,y,i,j,k, jmax;
+ SHORT col,cbit,mindist,minj,maxv,d;
+ SHORT newxpc = -1;
+ SHORT sort[32], nSrcCols, nDstCols, w,h;
+ LONG histog[32];
+ struct BitMap tmpbm;
+ ULONG used = 0;
+
+ if (curpen!=USERBRUSH) return(-1);
+
+ ZZZCursor();
+ w = sbm->BytesPerRow*8;
+ h = sbm->Rows;
+
+ /* count number of instances of each color in brush*/
+ tempRP.BitMap = sbm;
+ setmem(histog,32*sizeof(LONG),0);
+ nSrcCols = (1<<sbm->Depth);
+ nDstCols = (1<<newDepth);
+ for (x = 0; x < w; x++)
+ for (y=0; y < h; y++) histog[ReadPixel(&tempRP,x,y)]++;
+
+#ifdef DBGCM
+ if (dbgcmap) {
+ dprintf("Histogram: \n");
+ for (i=0; i<nSrcCols; i++) dprintf(" %ld,",histog[i]);
+ dprintf("\n");
+ }
+#endif
+ /* sort (dumbly) the colors in order of decreasing incidence*/
+
+ for (i=0; i<nSrcCols; i++) {
+ maxv = -1;
+ for (j=0;j<nSrcCols; j++)
+ if (histog[j] > maxv) { jmax = j; maxv = histog[j]; }
+ if (maxv<=0) { sort[i] = -1; break; }
+ sort[i] = jmax;
+ histog[jmax] = -1;
+ }
+
+#ifdef DBGCM
+ if (dbgcmap) {
+ dprintf("Sort: \n");
+ for (i=0; i<nSrcCols; i++) dprintf(" %ld,",sort[i]);
+ dprintf("\n");
+ }
+#endif
+
+ /* now work from most common colors, finding the closest match
+ in current color map */
+
+ BlankBitMap(&tmpbm); /* zero data structure out */
+
+ if (CopyBitMap(sbm, &tmpbm)) goto finish;
+
+ /* change to current depth */
+ if (NewSizeBitMap(sbm, newDepth, w, h)) goto finish;
+
+ for (k=0; k<nSrcCols; k++) {
+ i = sort[k];
+ if (i<0) break;
+ col = oldpal[i];
+ cbit = 1;
+ mindist = 30000;
+ minj = -1;
+
+ /*---search for the best remaining match in current pallet */
+
+ /* After all of the palette colors are used up, then make them
+ all available for further selection */
+ if (k >= nDstCols) used = 0;
+ for(j=0; j<nDstCols; j++) {
+ if ((used&cbit)==0) {
+ d = cdist(col,newpal[j]);
+ if (d<mindist) { minj = j; mindist = d; }
+ }
+ cbit <<= 1;
+ }
+
+#ifdef DBGCM
+ if (dbgcmap) dprintf("Changing %ld to %ld \n", i, minj);
+#endif
+
+ BMMapColor(&tmpbm, sbm, i, minj);
+ if (i== oldxpc) newxpc = minj;
+ used |= (1<<minj);
+ }
+ FreeBitMap(&tmpbm);
+
+ finish: UnZZZCursor();
+ return(newxpc);
+ }
+
+
+void BrRemapCols()
+ {
+ SHORT xpc, colors[32];
+ GetColors(colors);
+ xpc = BMRemapCols(curbr.pict.bm, LoadBrColors, curbr.xpcolor, colors, curDepth);
+ if (xpc == -1) return;
+ curbr.xpcolor = xpc;
+ BMOBMask(&curbr);
+ /* set the brush colors to the current palette */
+ GetColors(LoadBrColors);
+ }
+
diff --git a/REQCOM.C b/REQCOM.C
new file mode 100644
index 0000000..ee5b404
--- /dev/null
+++ b/REQCOM.C
@@ -0,0 +1,73 @@
+/****************************************************************************/
+/* reqcom.c -- common code used by requestors */
+/* */
+/* Initialize the timer device */
+/* */
+/****************************************************************************/
+#include <system.h>
+#include <librarie\dos.h>
+
+#define NO 0
+#define YES 1
+
+#define useTimer
+
+struct timerequest timermsg = {0};
+
+/****************************************************************************/
+/* FN_Listen() */
+/* */
+/****************************************************************************/
+
+#define WAITTIME 40000
+
+ReqListen(mailbox,handleEvent)
+ struct MsgPort *mailbox;
+ BOOL (*handleEvent)();
+ {
+ struct IntuiMessage *message = NULL;
+ struct IntuiMessage event;
+ ULONG wakeupbit = NULL; /* Used to see what woke us up */
+
+ /* Set the timer so we will get a message sooner or later */
+#ifdef useTimer
+ InitTimer(&timermsg);
+ SetTimer(&timermsg,0,WAITTIME);
+#endif
+
+ /* --- This is it! LOOP getting Intuition messages --- */
+ do {
+ event.Class=-1;
+ event.Code=-1;
+ event.Qualifier=-1;
+
+ /* See if we have a message */
+ message = (struct IntuiMessage *)GetMsg(mailbox);
+ if (message==NULL) {
+ /* No message, wait for mailbox or timer */
+#ifdef useTimer
+ wakeupbit = Wait( 1<<mailbox->mp_SigBit | TimerSigBit(&timermsg));
+#else
+ wakeupbit = Wait( 1 << mailbox->mp_SigBit);
+#endif
+ if( wakeupbit & (1 << mailbox->mp_SigBit )) {
+ /* Got some mail, get the message */
+ message = (struct IntuiMessage *)GetMsg(mailbox);
+ if (message != NULL) { event=*message; ReplyMsg(message); }
+ }
+#if useTimer
+ if (wakeupbit & TimerSigBit(&timermsg)) {
+ /* Time's up, set the timer again */
+ GetTimerMsg(&timermsg);
+ SetTimer(&timermsg,0,WAITTIME);
+ }
+#endif
+ }
+ else { event=*message; ReplyMsg(message); }
+ } while ( (*handleEvent)(&event) );
+
+#ifdef useTimer
+ KillTimer(&timermsg);
+#endif
+ }
+
diff --git a/ROT90.C b/ROT90.C
new file mode 100644
index 0000000..04b96fd
--- /dev/null
+++ b/ROT90.C
@@ -0,0 +1,78 @@
+/*----------------------------------------------------------------------*/
+/* */
+/* BMRot90 -- Rotate Bitmap By 90 Degrees */
+/* */
+/*----------------------------------------------------------------------*/
+
+#include "system.h"
+#include "graphics\gfx.h"
+#include <prism.h>
+
+extern SHORT curpen;
+extern BMOB curbr;
+
+
+BOOL BMRot90(source,sw, destination)
+ struct BitMap *source; /* pointer to source bitmap */
+ int sw; /* width of source bitmap data in pixels*/
+ struct BitMap *destination;
+ {
+ register UBYTE src, *dst_row, dbit;
+ UBYTE *src_plane, *dst_plane, *src_row;
+ int p, dx, dy, nx, ny;
+ int sh,sbpr,dbpr;
+ sbpr = source->BytesPerRow;
+ dbpr = destination->BytesPerRow;
+ sh = source->Rows;
+ for (p = 0; p < source->Depth; p++) {
+ src_plane = (UBYTE *) ( source->Planes[p] + sh*sbpr );
+ dst_plane = (UBYTE *) destination->Planes[p];
+ nx = 0;
+ dbit = 0x80;
+ if (CheckAbort()) return(FAIL);
+ for (dx = sh; dx > 0 ; dx--) {
+ src_plane -= sbpr;
+ dst_row = dst_plane;
+ src_row = src_plane;
+ src = *src_row++;
+ ny = 0;
+ for (dy = 0; dy < sw; dy++) {
+ if ( src & 0x80) *dst_row |= dbit;
+ src <<= 1;
+ dst_row += dbpr;
+ if ( ++ny == 8 ) { ny = 0; src = *src_row++; }
+ }
+ if (++nx == 8) { nx = 0; dst_plane++; dbit = 0x80; }
+ else dbit >>= 1;
+ }
+ }
+ return(SUCCESS);
+ }
+
+/*----------------------------------------------------------------------*/
+/* 90 Degree Rotation of brush */
+/*----------------------------------------------------------------------*/
+
+void BrRot90() {
+ SHORT sav;
+ struct BitMap tmp;
+ if (curpen!=USERBRUSH) return;
+ ZZZCursor();
+ ClearBrXform(); /* could be smarter than this, but.. */
+
+ InitBitMap(&tmp,curbr.pict.bm->Depth,curbr.pict.bm->Rows,curbr.pict.box.w);
+ if (AllocBitMap(&tmp)) return;
+ ClearBitMap(&tmp);
+ if (BMRot90(curbr.pict.bm, curbr.pict.box.w, &tmp)==SUCCESS) {
+ DupBitMap(&tmp,curbr.pict.bm);
+ sav = curbr.pict.box.w;
+ curbr.pict.box.w = curbr.pict.box.h;
+ curbr.pict.box.h = sav;
+ sav = curbr.yoffs;
+ curbr.yoffs = curbr.xoffs;
+ curbr.xoffs = curbr.pict.box.w - 1 - sav;
+ BMOBMask(&curbr);
+ }
+ else FreeBitMap(&tmp);
+ UnZZZCursor();
+ }
diff --git a/ROTATE.C b/ROTATE.C
new file mode 100644
index 0000000..89a86e7
--- /dev/null
+++ b/ROTATE.C
@@ -0,0 +1,201 @@
+/*--------------------------------------------------------------*/
+/* rotate.c */
+/* Arbitrary rotation of current object */
+/* */
+/* 9-8-85 DDS Ported to Amiga (68000) */
+/*--------------------------------------------------------------*/
+
+#include <system.h>
+#include <prism.h>
+#include <pnts.h>
+
+
+#define local
+#define lfHalf 0x8000
+
+extern PointRec pnts;
+extern SHORT curpen;
+extern LongFrac LFMULT();
+extern struct RastPort tempRP;
+extern BMOB curbr,origBr;
+extern void (*nop)();
+extern SHORT usePen;
+
+#define highHalf(lf) ( (lf)>>16)
+
+typedef union { LongFrac lf; SHORT s[2]; } lfOvl;
+
+#ifdef DBGROTATE
+local BOOL rotdbg = 0;
+#endif
+
+#define longf(x) ((x)<<16)
+
+/* Size new object for rotation */
+
+local BMOBRotSize(old,new,sin,cos)
+ BMOB *old,*new;
+ LongFrac sin,cos;
+ {
+ SHORT w,h,neww,newh;
+ w = old->pict.box.w;
+ h = old->pict.bm->Rows;
+ newh = highHalf(h*ABS(cos) + w*ABS(sin) + lfHalf);
+ neww = highHalf(w*ABS(cos) + h*ABS(sin) + lfHalf);
+ return(BMOBNewSize(new,old->pict.bm->Depth,neww,newh));
+ }
+
+local Point pin;
+
+/* rotate bitmap: assumes nbm is already sized and allocated */
+
+local BMRot(obm,nbm,sin,cos,width,xpcol)
+ struct BitMap *obm,*nbm;
+ LongFrac sin,cos;
+ SHORT width,xpcol;
+ {
+ SHORT w,h,neww,newh,xn,yn,xi,yi,pix;
+ LongFrac xs,ys,x,y;
+ struct RastPort destRP;
+ InitRastPort(&destRP);
+ destRP.BitMap = nbm;
+ SetDrMd(&destRP,JAM1);
+ w = width;
+ h = obm->Rows;
+ newh = highHalf(h*ABS(cos) + w*ABS(sin) + lfHalf);
+ neww = highHalf(w*ABS(cos) + h*ABS(sin) + lfHalf);
+
+#ifdef DBGROTATE
+ if (rotdbg) printf(" sin = %lx, cos = %lx \n",sin,cos);
+ if (rotdbg) printf("w=%d,h=%d, neww=%d, newh=%d\n",w,h,neww,newh);
+#endif
+
+ SetBitMap(nbm,xpcol); /* watch out-- this uses tempRP */
+ tempRP.BitMap = obm;
+ if (sin>=0)
+ if (cos>=0) { xs = -h*LFMULT(sin,cos); ys = h*LFMULT(sin,sin); }
+ else { xs = w*LFMULT(cos,cos); ys = longf(h) - w*LFMULT(sin,cos); }
+ else
+ if (cos>=0) { xs = w*LFMULT(sin,sin); ys = w*LFMULT(sin,cos); }
+ else { xs = longf(w) + h*LFMULT(sin,cos); ys = h*LFMULT(cos,cos); }
+ xs += lfHalf;
+ ys += lfHalf;
+ for (yn=0; yn<newh; yn++) {
+ x = xs; y = ys;
+ for (xn = 0; xn<neww; xn++) {
+ xi = highHalf(x);
+ yi = highHalf(y);
+ if ((xi>=0)&&(xi<w)&&(yi>=0)&&(yi<h)) {
+ pix = ReadPixel(&tempRP,xi,yi);
+ SetAPen(&destRP,ReadPixel(&tempRP,xi,yi));
+ WritePixel(&destRP,xn,yn);
+ }
+ x += cos; y -= sin;
+ }
+ if (CheckAbort()) return(FAIL);
+ xs += sin; ys += cos;
+ }
+ return(SUCCESS);
+ }
+
+
+#define AssgnLfrac(plf,hi,lo) ((SHORT *)plf)[0] = hi; ((SHORT *)plf)[1] = lo
+
+local sincos(dx,dy,sn,cs) SHORT dx,dy; LongFrac *sn,*cs; {
+ SHORT hyp = Distance(dx,dy);
+ AssgnLfrac(sn,dy,0);
+ AssgnLfrac(cs,dx,0);
+ *sn /=hyp;
+ *cs /=hyp;
+#ifdef DBGROTATE
+ if (rotdbg) printf("Sincos: dx= %d, dy = %d, sn = %lx, cs = %lx \n",
+ dx,dy,*sn,*cs);
+#endif
+ }
+
+XorLine(x0,y0,x1,y1) SHORT x0,y0,x1,y1; {
+ SHORT svUsePen;
+ TempXOR();
+ svUsePen = usePen;
+ usePen = 0;
+ mLine(x0,y0,x1,y1);
+ usePen = svUsePen;
+ RestoreMode();
+ }
+
+#define lfmulint(lf,i) (highHalf((lf)*(i)+lfHalf))
+
+local XorRotB1(x,y,w,h) SHORT x,y,w,h; {
+ LongFrac sn,cs;
+ SHORT x1,y1,x2,y2,x3,y3;
+#ifdef DBGROTATE
+ if (rotdbg) printf("XorRotBox: x,y,w,h = %d, %d, %d, %d \n",x,y,w,h);
+#endif
+ sincos(x-pin.x,y-pin.y,&sn,&cs);
+ x1 = pin.x + lfmulint(w,cs);
+ y1 = pin.y + lfmulint(w,sn);
+ x2 = x1 + lfmulint(h,sn);
+ y2 = y1 + lfmulint(-h,cs);
+ x3 = pin.x + lfmulint(h,sn);
+ y3 = pin.y + lfmulint(-h,cs);
+ XorLine(pin.x,pin.y,x1,y1);
+ XorLine(x1,y1,x2,y2);
+ XorLine(x2,y2,x3,y3);
+ XorLine(x3,y3,pin.x,pin.y);
+ }
+
+local XorRotBox(x,y) SHORT x,y; {
+ XorRotB1(x,y,curbr.pict.box.w,curbr.pict.box.h);
+ }
+
+/* button down proc */
+local beginrot() { pin.x = mx-curbr.xoffs; pin.y = my; }
+
+local rotob() { XorRotBox(lx,ly); XorRotBox(mx,my); }
+
+local invrotb() { XorRotBox(mx,my); }
+
+local void endrot() { /* button up proc */
+ LongFrac sn,cs;
+ sincos( mx-pin.x, my-pin.y, &sn, &cs);
+ if (BMOBRotSize(&origBr, &curbr, sn, cs)) {
+ RestoreBrush();
+ AbortIMode();
+ return;
+ }
+ ZZZCursor();
+ BMRot( origBr.pict.bm, curbr.pict.bm, sn, cs, origBr.pict.box.w, origBr.xpcolor);
+ BMOBMask(&curbr);
+ curbr.pict.box.h = curbr.pict.bm->Rows;
+ curbr.pict.box.w = curbr.pict.bm->BytesPerRow*8;
+ curbr.xoffs = curbr.pict.box.w/2; /* not correct but ... */
+ curbr.yoffs = curbr.pict.box.h/2;
+ UnZZZCursor();
+ }
+
+local invbrbox(x,y) SHORT x,y; {
+ Box bx;
+ TempXOR();
+ mFrame(MakeBox(&bx,x-curbr.xoffs,y-curbr.yoffs,
+ curbr.pict.box.w,curbr.pict.box.h));
+ RestoreMode();
+ }
+
+local frobsh() { obmv(); invbrbox(mx,my); }
+
+local frobmv() { invbrbox(lx,ly); frobsh(); }
+
+local frobclr() { invbrbox(mx,my); obclr(); }
+
+void IMRotBrush(restart) BOOL restart; {
+ if (!restart) {
+ if (curpen != USERBRUSH) { RevertIMode(); return; }
+ if (SaveBrush(ROTATED)) { RevertIMode(); return; }
+ if (CopyBMOBPict(&origBr,&curbr)==FAIL) {RestoreBrush();
+ RevertIMode(); return; }
+ origBr.xoffs = curbr.xoffs; origBr.yoffs = curbr.yoffs;
+ curbr.xoffs = curbr.pict.box.w; curbr.yoffs = curbr.pict.box.h;
+ }
+ IModeProcs(frobsh,frobmv,frobclr,beginrot,invrotb,nop,invrotb,endrot);
+ }
+
diff --git a/SHADE.C b/SHADE.C
new file mode 100644
index 0000000..d4699ba
--- /dev/null
+++ b/SHADE.C
@@ -0,0 +1,194 @@
+/*----------------------------------------------------------------------*/
+/* */
+/* shade.c -- */
+/* */
+/*----------------------------------------------------------------------*/
+
+#include <system.h>
+#include <prism.h>
+
+#define local
+extern BoxBM temp;
+extern BOOL erasing;
+extern Range *shadeRange;
+extern struct TmpRas tmpRas;
+extern BoxBM canvas;
+
+void MaskRange();
+
+/*----------------------------------------------------------------------*/
+/* SHADE mode: */
+/*----------------------------------------------------------------------*/
+void DoShade(ob,canv,clip) BMOB *ob; BoxBM *canv; Box *clip; {
+ Box b;
+ BOOL res;
+ int lo,hi;
+ if (BMPlaneSize(ob->pict.bm)> (tmpRas.Size/2)) return;
+ if (SaveSizeBM(temp.bm, ob)) return;
+ temp.box = ob->pict.box;
+ CopyBoxBM(canv, &temp, &temp.box, clip, REPOP);
+ if (erasing) { lo = shadeRange->low+1; hi = shadeRange->high; }
+ else {lo = shadeRange->low; hi = shadeRange->high - 1; }
+ if (shadeRange==NULL) setmem(tmpRas.RasPtr,BMPlaneSize(ob->pict.bm),0xff);
+ else MaskRange(temp.bm, tmpRas.RasPtr,tmpRas.RasPtr +tmpRas.Size/2,lo,hi);
+ if (clip) res = BoxAnd(&b,&ob->pict.box,clip);
+ else { res = YES; b = ob->pict.box; }
+ if (res) ShadePaint(ob->pict.bm,ob->mask, b.x - ob->pict.box.x,b.y - ob->pict.box.y,
+ canv->bm, b.x - canv->box.x, b.y - canv->box.y,
+ b.w, b.h, erasing? MINUSOP: PLUSOP, tmpRas.RasPtr);
+ }
+
+
+/*----------------------------------------------------------------------*/
+/* MaskRange: Build a mask for a bitmap which has 1's for every pixel */
+/* in [lower..upper] inclusive. */
+/* */
+/* Thanks to David Maynard for suggesting this */
+/* algorithm. */
+/*----------------------------------------------------------------------*/
+
+#define yA 0xf0
+#define yB 0xcc
+#define yC 0xaa
+#define nA 0x0f
+#define nB 0x33
+#define nC 0x55
+
+UBYTE mints[4] =
+ { nA&nB&yC, nA&yB&yC, yA&nB&yC, yA&yB&yC };
+
+UBYTE mints4P[2] = {nB&yC, yB&yC};
+
+#ifdef DBUG
+dbgmask(msk,bpr,h) UBYTE *msk; int bpr,h; {
+ struct RastPort rp;
+ InitRastPort(&rp);
+ rp.BitMap = canvas.bm;
+ SetAPen(&rp,1);
+ SetBPen(&rp,0);
+ SetDrMd(&rp,JAM2);
+ BltTemplate(msk,0,bpr,&rp,0,30,bpr*8,h);
+ }
+
+dbgbm(bm) struct BitMap *bm; {
+BltBitMap(bm,0,0,canvas.bm,0,80,bm->BytesPerRow*8,bm->Rows,REPOP,0xff,NULL);
+ }
+#endif
+
+void MaskRange(bm, mask, tmp, lower, upper)
+ struct BitMap *bm; /* bitmap for which mask is being created */
+ UBYTE *mask; /* to receive mask */
+ UBYTE *tmp; /* temp storage */
+ int lower,upper; /* defines range for mask */
+ {
+ int minterm, i, octstart, octend, lastInOct,oct,depth;
+ int bpr = bm->BytesPerRow;
+ int h = bm->Rows;
+ int bltsize = BlitSize(bpr,h);
+
+ octstart = lower>>3;
+ octend = upper>>3;
+ lastInOct = (octstart<<3)+7;
+ depth = bm->Depth;
+
+ for (oct = octstart; oct<=octend; oct++) {
+ minterm = 0;
+ /* find subset of ALL pixels whose lower order 3 bits
+ are in this octaves subrange */
+ for (i = lower; i<= MIN(upper, lastInOct); ++i)
+ minterm |= ( 1 << (i&7) );
+
+ BltABCD(bm->Planes[2],bm->Planes[1],bm->Planes[0],tmp, bltsize, minterm);
+
+ /* filter out the pixels not in this 8 color "octave" */
+
+ if (depth==5)
+ BltABCD(bm->Planes[4],bm->Planes[3], tmp, tmp, bltsize, mints[oct]);
+ else if (depth==4)
+ BltABCD(NULL,bm->Planes[3], tmp, tmp, bltsize, mints4P[oct]);
+
+ /* OR in to mask being built up */
+ BltABCD(tmp,mask,NULL,mask, bltsize, (oct==octstart)?yA : yA|yB);
+
+ lower = lastInOct+1;
+ lastInOct += 8;
+ }
+ }
+
+
+#ifdef newway
+
+ShadePaint(sbm, spos, mask, dbm, dpos, copyBox, incop,tmpbuf)
+ struct BitMap *sbm;
+ Point *spos;
+ UBYTE *mask;
+ struct BitMap *dbm;
+ Point *dpos;
+ Box *copyBox;
+ UBYTE incop;
+ UBYTE *tmpbuf;
+ {
+ struct BitMap tmp,carry;
+ int i, depth;
+ int sx,sy,dx,dy,w,h;
+ PLANEPTR svp0;
+ sx = copyBox->x - spos->x; sy = copyBox->y - spos->y;
+ dx = copyBox->x - dpos->x; dy = copyBox->y - dpos->y;
+ w = copyBox->w; h = copyBox->h;
+ depth = dbm->Depth;
+ dbm->Depth = 1;
+ svp0 = dbm->Planes[0];
+ InitBitMap(&carry,1,sbm->BytesPerRow*8, sbm->Rows);
+ carry.Planes[0] = tmpbuf;
+ tmp = carry;
+ tmp.Planes[0] = mask;
+ BltBitMap(&tmp,sx,sy,&carry,sx,sy,w,h,ANDOP,0xff,NULL);
+ WaitBlit();
+ for (i = 0; i< depth; i++) {
+ dbm->Planes[0] = dbm->Planes[i];
+ BltBitMap(&carry,sx,sy,dbm,dx,dy,w,h, XOROP, 0xff, NULL);
+ WaitBlit();
+ BltBitMap(dbm,dx,dy,&carry,sx,sy,w,h, incop, 0xff, NULL);
+ WaitBlit();
+ }
+ dbm->Planes[0] = svp0;
+ dbm->Depth = depth;
+ }
+
+#else
+
+ShadePaint(sbm, mask, sx, sy, dbm, dx, dy, w,h, incop,tmpbuf)
+ struct BitMap *sbm;
+ UBYTE *mask;
+ SHORT sx,sy;
+ struct BitMap *dbm;
+ SHORT dx,dy,w,h;
+ UBYTE incop;
+ UBYTE *tmpbuf;
+ {
+ struct BitMap tmp,carry;
+ int i, depth;
+ PLANEPTR svp0;
+
+ depth = dbm->Depth;
+ dbm->Depth = 1;
+ svp0 = dbm->Planes[0];
+ InitBitMap(&carry,1,sbm->BytesPerRow*8, sbm->Rows);
+ carry.Planes[0] = tmpbuf;
+ tmp = carry;
+ tmp.Planes[0] = mask;
+ BltBitMap(&tmp,sx,sy,&carry,sx,sy,w,h,ANDOP,0xff,NULL);
+ WaitBlit();
+ for (i = 0; i< depth; i++) {
+ dbm->Planes[0] = dbm->Planes[i];
+ BltBitMap(&carry,sx,sy,dbm,dx,dy,w,h, XOROP, 0xff, NULL);
+ WaitBlit();
+ BltBitMap(dbm,dx,dy,&carry,sx,sy,w,h, incop, 0xff, NULL);
+ WaitBlit();
+ }
+ dbm->Planes[0] = svp0;
+ dbm->Depth = depth;
+ }
+#endif
+
+
diff --git a/SHEAR.C b/SHEAR.C
new file mode 100644
index 0000000..91af0e0
--- /dev/null
+++ b/SHEAR.C
@@ -0,0 +1,136 @@
+/*--------------------------------------------------------------*/
+/* shear.c */
+/* */
+/*--------------------------------------------------------------*/
+#include <system.h>
+#include <prism.h>
+#include <pnts.h>
+
+#define local static
+
+extern void RestoreBrush();
+extern PointRec pnts;
+extern BMOB curbr, origBr;
+extern void (*nop)(), (*killMode)();
+extern void obmv(), obclr();
+extern SHORT curpen;
+
+BOOL BMShearX(oldbm,newbm,oldwidth, xpcolor,dx)
+ struct BitMap *oldbm, *newbm;
+ SHORT oldwidth, xpcolor, dx;
+ {
+ SHORT sum,x,y,h,w,xinc;
+ if (dx==0) return(CopyBitMap(oldbm,newbm));
+ if (dx<0) { dx = -dx; xinc = -1; x = dx; }
+ else { xinc = 1; x = 0; }
+ if (NewSizeBitMap(newbm, oldbm->Depth, oldwidth + dx, oldbm->Rows))
+ return(FAIL);
+ SetBitMap(newbm, xpcolor);
+ h = oldbm->Rows;
+ w = oldwidth;
+ sum = h/2;
+ for (y=0; y<h; y++) {
+ BltBitMap(oldbm,0,y,newbm,x,y,w,1,REPOP,0xff,NULL);
+ sum += dx;
+ while (sum>h) { x += xinc; sum -= h; }
+ }
+ return(SUCCESS);
+ }
+
+
+/* ----------- Shear Brush ------------------ */
+
+
+local Point bpl;
+local PaintMode svPntMode;
+extern PaintMode paintMode;
+
+void killShear() {
+ SetPaintMode(svPntMode);
+ RestoreBrush();
+ }
+
+/* Begin stretching brush (button down) */
+
+local beginshr() {
+ /* remember the upper left corner */
+ bpl.x = mx-curbr.xoffs;
+ bpl.y = my-curbr.yoffs;
+ }
+
+local GiveUp() { ClearFB(); RestoreBrush(); AbortIMode(); }
+
+local shrob() {
+ short dx,dy;
+ dx = mx - bpl.x - origBr.pict.box.w;
+ dy = my - bpl.y - origBr.pict.box.h;
+ if (BMShearX( origBr.pict.bm, curbr.pict.bm, origBr.pict.box.w,
+ origBr.xpcolor, dx)) GiveUp();
+ else {
+ curbr.pict.box.w = origBr.pict.box.w + ABS(dx);
+ if (BMOBMask(&curbr)) GiveUp();
+ else {
+ curbr.xoffs = origBr.pict.box.w + MAX(dx,0);
+ curbr.yoffs = my - bpl.y;
+ obmv();
+ }
+ }
+ }
+
+void endShrob() {
+ SetPaintMode(svPntMode);
+ curbr.yoffs = origBr.yoffs;
+ curbr.xoffs = curbr.pict.box.w/2;
+ }
+
+
+/* first change the handle to the lower right corner for stretching */
+void IMShrBrush(){ if ((curpen!=USERBRUSH)||
+ (SaveBrush(SHEARED))) {RevertIMode(); return;}
+ if (CopyBMOBPict(&origBr,&curbr)) { RevertIMode(); RestoreBrush(); return;}
+ curbr.xoffs = curbr.pict.box.w; curbr.yoffs = curbr.pict.box.h;
+ IModeProcs(obmv, obmv, obclr, beginshr, obmv, shrob, obclr, endShrob);
+ killMode = &killShear;
+ svPntMode = paintMode;
+ SetPaintMode(Mask);
+ }
+
+
+#ifdef oidoidoid
+/********************************************************************/
+ This code not yet converted
+
+BMShearY(oldbm,newbm,dy) struct BitMap *oldbm, *newbm; SHORT dy; {
+ SHORT sum,x,y,h,w,yinc;
+ if (dy==0){ CopyBitMap(oldbm,newbm); return; }
+ if (dy<0) { dy = -dy; yinc = -1; y = dy; }
+ else { yinc = 1; y = 0; }
+ NewShBM(newbm, oldbm->box.w, oldbm->box.h + dy);
+ BMLike(oldbm,newbm);
+ FillBitMap(newbm,compcolw(oldbm->xpcolor));
+ h = oldbm->box.h;
+ w = oldbm->box.w;
+ sum = w/2;
+ for (x=0; x<w; x++) {
+ rop(REPMODE,NIL,oldbm,newbm,1,h,x,0,x,y);
+ sum += dy;
+ while (sum>w) { y += yinc; sum -= w; }
+ }
+ return(SUCCESS);
+ }
+
+BMShear(obm,nbm,dx,dy) struct BitMap *obm,*nbm; SHORT dx,dy; {
+ struct BitMap tmp;
+ tmp.segment= 0;
+ if (dx==0) BMShearY(obm,nbm,dy);
+ else if (dy==0) BMShearX(obm,nbm,dx);
+ else {
+ BMShearY(obm,&tmp,dy);
+ BMShearX(&tmp,nbm,dx);
+ FreeBitMap(&tmp);
+ }
+ return(SUCCESS);
+ }
+
+#endif
+
diff --git a/SPARE.C b/SPARE.C
new file mode 100644
index 0000000..1426049
--- /dev/null
+++ b/SPARE.C
@@ -0,0 +1,108 @@
+/*----------------------------------------------------------------------*/
+/* */
+/* spare.c - Spare screen */
+/* */
+/*----------------------------------------------------------------------*/
+
+#include "system.h"
+#include "prism.h"
+
+#define local static
+
+extern struct BitMap hidbm;
+extern struct ViewPort *vport;
+extern SHORT nColors, curxpc;
+
+extern struct RastPort *curRP;
+extern MagContext magCntxt;
+extern struct TmpRas tmpRas;
+extern Box screenBox, clipBox;
+extern SHORT curDepth;
+
+
+extern BOOL spareThere;
+extern BOOL newSpare;
+extern SHORT spareXPCol;
+extern struct BitMap sparebm;
+extern SHORT didType;
+
+local void NotEnough() {
+ UndoSave();
+ InfoMessage("Insufficient Memory","for Spare Screen");
+ }
+
+local BOOL AllocSpare() {
+ LONG freeMem,imSize;
+ if (!spareThere) {
+ freeMem = AvailMem(MEMF_CHIP|MEMF_PUBLIC);
+ imSize = hidbm.BytesPerRow*hidbm.Rows*hidbm.Depth;
+ if (freeMem < (2*imSize)) { NotEnough(); return((BOOL)FAIL); }
+ InitBitMap(&sparebm,curDepth,screenBox.w,screenBox.h);
+ if (AllocBitMap(&sparebm)) { NotEnough(); return((BOOL)FAIL);}
+ SetBitMap(&sparebm,0);
+ spareThere = YES;
+ }
+ return(SUCCESS);
+ }
+
+void SwapSpare() {
+ struct BitMap mytemp;
+ SHORT tmp;
+ if (AllocSpare()) return;
+ UndoSave();
+ KillCCyc();
+ mytemp = hidbm;
+ hidbm = sparebm;
+ sparebm = mytemp;
+ tmp = spareXPCol;
+ spareXPCol = curxpc;
+ if (!newSpare) { CPChgBg(tmp); }
+ newSpare = NO;
+ UpdtDisplay();
+ }
+
+void CopyToSpare() {
+ if (AllocSpare()) return;
+ UndoSave();
+ CopyBitMap(&hidbm,&sparebm);
+ spareXPCol = curxpc;
+ newSpare = NO;
+ }
+
+
+extern SHORT xorg,yorg;
+
+local BOOL inFront;
+
+local MakeMrgMask() {
+ if (inFront)
+ MakeMask(&sparebm, tmpRas.RasPtr, spareXPCol, NEGATIVE);
+ else MakeMask(&hidbm, tmpRas.RasPtr, curxpc, POSITIVE);
+ }
+
+void MergeSpare() {
+ BYTE *mask = tmpRas.RasPtr;
+ Point spos,dpos;
+ if (spareThere) {
+ UndoSave();
+ spos.x = xorg; spos.y = yorg;
+ dpos.x = dpos.y = 0;
+ MakeMrgMask();
+ MaskBlit(&sparebm, &spos, mask, curRP->BitMap,&dpos, &screenBox,
+ &clipBox, COOKIEOP, mask, 0xff, 0);
+ MagUpdate(&screenBox);
+ didType = DIDMerge;
+ }
+ }
+
+void MrgSpareFront() { inFront = YES; MergeSpare(); }
+void MrgSpareBack() { inFront = NO; MergeSpare(); }
+
+MrgSpareUpdt() {
+ Point pos;
+ pos.x = pos.y = 0;
+ MakeMrgMask();
+ MaskBlit(&sparebm, &pos, tmpRas.RasPtr, &hidbm, &pos, &screenBox,
+ &screenBox, COOKIEOP, tmpRas.RasPtr, 0xff, 0);
+ }
+
diff --git a/STRETCH.C b/STRETCH.C
new file mode 100644
index 0000000..9a37a3e
--- /dev/null
+++ b/STRETCH.C
@@ -0,0 +1,236 @@
+/*----------------------------------------------------------------------*/
+/* */
+/* stretch.c -- Brush Stretching Operations */
+/* */
+/*----------------------------------------------------------------------*/
+
+#include <system.h>
+#include <prism.h>
+#include <pnts.h>
+
+extern SHORT curpen;
+extern Dims newDim;
+extern BMOB origBr,curbr;
+extern PointRec pnts;
+extern BOOL wasShift;
+extern void (*killMode)(), (*nop)();
+extern void obclr();
+extern Box screenBox;
+extern PaintMode paintMode;
+
+/* #define DBGSTRCH */
+
+#define local
+
+Dims newDim;
+SHORT savePntMode=0;
+
+LONG MulDiv(a,b,c) LONG a,b,c; { return( (a*b)/c ); }
+
+void FixOffs() {
+ SetPaintMode(savePntMode);
+ curbr.xoffs = MulDiv(origBr.xoffs,newDim.w,origBr.pict.box.w);
+ curbr.yoffs = MulDiv(origBr.yoffs,newDim.h,origBr.pict.box.h);
+ }
+
+SHORT StrBMOB(src,dst,newW,newH) BMOB *src,*dst; SHORT newW,newH; {
+ Box sbox,dbox;
+ if ( BMOBNewSize(dst,src->pict.bm->Depth,newW,newH)) {
+#ifdef DBGSTRCH
+ dprintf(" StrBMOB: couldnt alloc bm \n");
+#endif
+ return(FAIL);
+ }
+ sbox.x = sbox.y = dbox.x = dbox.y = 0;
+ sbox.w = src->pict.box.w;
+ sbox.h = src->pict.box.h;
+ dbox.w = newW;
+ dbox.h = newH;
+ if( StrBits(src->pict.bm,&sbox,dst->pict.bm,&dbox,REPOP)){
+#ifdef DBGSTRCH
+ dprintf(" StrBMOB: couldnt do stretch \n");
+#endif
+ return(FAIL);
+ }
+ MakeMask(dst->pict.bm,dst->mask,dst->xpcolor,NEGATIVE);
+ return(SUCCESS);
+ }
+
+
+void StrBrTo(w,h) int w,h; {
+ if (curpen!=USERBRUSH) return;
+ /* let it be stretched up to 1/2 screen size in area */
+ if ((w<1)||(h<1)||(w*h >(screenBox.w*screenBox.h/2))) return;
+ if (SaveBrush(STRETCHED)) return;
+ ZZZCursor();
+ newDim.w = w;
+ newDim.h = h;
+ if (StrBMOB(&origBr,&curbr,newDim.w,newDim.h)) RestoreBrush();
+ else FixOffs();
+ UnZZZCursor();
+ }
+
+void BrHalf() { StrBrTo(curbr.pict.box.w/2, curbr.pict.box.h/2); }
+void BrDubl() { StrBrTo(curbr.pict.box.w*2, curbr.pict.box.h*2); }
+void BrDublX() { StrBrTo(curbr.pict.box.w*2, curbr.pict.box.h); }
+void BrDublY() { StrBrTo(curbr.pict.box.w, curbr.pict.box.h*2); }
+
+/* ---------------Stretch brush----------------- */
+
+Point bpl={0};
+
+/* Begin stretching brush (button down) */
+
+/* remember the upper left corner */
+beginstr() {
+ bpl.x = mx-curbr.xoffs;
+ bpl.y = my-curbr.yoffs;
+ }
+
+#define oldW origBr.pict.box.w
+#define oldH origBr.pict.box.h
+
+LONG LongMult(a,b,c) LONG a,b,c; { return( a*b); }
+
+local void doStretch() {
+ newDim.w = mx-bpl.x + 1;
+ newDim.h = my-bpl.y + 1;
+ if ( (newDim.w<=0) || (newDim.h<=0) ) return;
+ if (wasShift) {
+ if (LongMult(newDim.h,oldW) > LongMult(newDim.w,oldH))
+ newDim.w = MulDiv(oldW,newDim.h,oldH);
+ else newDim.h = MulDiv(oldH,newDim.w,oldW);
+ }
+ if (StrBMOB(&origBr,&curbr,newDim.w,newDim.h)) {
+#ifdef DBGSTRCH
+ dprintf(" Can't make the brush that big! (w= %d, h = %d)\n",
+ newDim.w, newDim.h);
+#endif
+ ClearFB();
+ RestoreBrush();
+ killMode = nop;
+ SetPaintMode(savePntMode);
+ AbortIMode();
+ return;
+ }
+ curbr.xoffs = (mx - bpl.x);
+ curbr.yoffs = (my - bpl.y);
+ obmv();
+ }
+
+void IMStrBrush(restart) BOOL restart; {
+ if (!restart) {
+ if (curpen!=USERBRUSH) {RevertIMode(); return;}
+ if (SaveBrush(STRETCHED)) {RevertIMode(); return;}
+ /* hold at the lower right for stretching */
+ curbr.xoffs = curbr.pict.box.w - 1;
+ curbr.yoffs = curbr.pict.box.h - 1;
+ savePntMode = paintMode;
+ SetPaintMode(Mask);
+ }
+ IModeProcs(&obmv,&obmv,&obclr,&beginstr,&obmv,
+ &doStretch,&obclr, FixOffs);
+ killMode = &FixOffs;
+ }
+
+/*----------------------------------------------------------------------*/
+/* << StrBits >> Stretching BltBitMap */
+/* Does not handle negative stretches (use FlipX, FlipY first) */
+/* since X stretching is slower, order the X- and Y- stretching to */
+/* minimize the X stretching */
+/* */
+/*----------------------------------------------------------------------*/
+
+#undef sx
+#undef sy
+
+local SHORT sx,sy,sw,sh,dx,dy,dw,dh;
+
+StrX(sbm,sbox,dbm,dbox,minterm)
+ struct BitMap *sbm,*dbm;
+ Box *sbox,*dbox;
+ SHORT minterm;
+ {
+ SHORT xs,xd,xs0,xd0,xslast,s,dxmax;
+ sy = sbox->y; dy = dbox->y;
+ sw = sbox->w-1; dw = dbox->w-1; sh = sbox->h;
+ dxmax = dbox->x + dw;
+ xs0 = xs = xslast = sbox->x; xd0 = dbox->x;
+ s = dw/2;
+ for (xd = dbox->x+1 ; xd <= dxmax; xd++ ) {
+ s += sw;
+ while ( s >= dw ) { s -= dw; xs++; }
+ if (xs != xslast + 1 ) {
+ BltBitMap(sbm,xs0,sy,dbm,xd0,dy,xd-xd0,sh,minterm,0xff,NULL);
+ xs0 = xs; xd0 = xd;
+ }
+ xslast = xs;
+ }
+ BltBitMap(sbm,xs0,sy,dbm,xd0,dy,xd-xd0,sh,minterm,0xff,NULL);
+ }
+
+StrY(sbm,sbox,dbm,dbox,minterm)
+ struct BitMap *sbm,*dbm;
+ Box *sbox,*dbox;
+ SHORT minterm;
+ {
+ SHORT ys,yd,ys0,yd0,yslast,s,dymax;
+ sx = sbox->x; dx = dbox->x;
+ sh = sbox->h-1; dh = dbox->h -1; sw = sbox->w;
+ dymax = dbox->y + dh;
+ ys0 = ys = yslast = sbox->y; yd0 = dbox->y;
+ s = dh/2;
+ for (yd = dbox->y+1; yd <= dymax; yd++ ) {
+ s += sh;
+ while ( s >= dh ) { s -= dh; ys++; }
+ if (ys != yslast + 1) {
+ BltBitMap(sbm,sx,ys0,dbm,dx,yd0,sw,yd-yd0,minterm,0xff,NULL);
+ ys0 = ys; yd0 = yd;
+ }
+ yslast = ys;
+ }
+ BltBitMap(sbm,sx,ys0,dbm,dx,yd0,sw,yd-yd0,minterm,0xff,NULL);
+ }
+
+StrBits(srcBM,sbox,dstBM,dbox,mint)
+ struct BitMap *srcBM; /* source bimap */
+ Box *sbox; /* source rectangle */
+ struct BitMap *dstBM; /* destination bitmap */
+ Box *dbox; /* destination rectangle */
+ SHORT mint; /* minterm for blitter */
+ {
+ SHORT depth;
+ Box tbox;
+ struct BitMap tmpBM;
+ if ( (sbox->w == dbox->w) && (sbox->h == dbox->h)) {
+ BltBitMap(srcBM,sbox->x,sbox->y,dstBM,dbox->x,dbox->y,
+ sbox->w,sbox->h,mint,0xff,NULL);
+ return(0);
+ }
+ if ((dbox->h == 0)||(dbox->w == 0)) return(0);
+ if ( dbox->w == sbox->w) {StrY(srcBM,sbox,dstBM,dbox,mint); return(0); }
+ if ( dbox->h == sbox->h) {StrX(srcBM,sbox,dstBM,dbox,mint); return(0); }
+
+ depth = dstBM->Depth;
+
+ if (dbox->h > sbox->h) { /*--- Getting Taller ---*/
+ InitBitMap(&tmpBM,depth,dbox->w,sbox->h);
+ if (TmpAllocBitMap(&tmpBM)) return(FAIL);
+ tbox.x = 0; tbox.y = 0; tbox.w = dbox->w; tbox.h = sbox->h;
+ StrX(srcBM, sbox, &tmpBM, &tbox, REPOP);
+ StrY(&tmpBM, &tbox, dstBM, dbox, mint);
+ }
+ else { /*---- Getting Shorter ----*/
+ InitBitMap(&tmpBM,depth,sbox->w,dbox->h);
+ if (TmpAllocBitMap(&tmpBM)) return(FAIL);
+ tbox.x = 0; tbox.y = 0; tbox.w = sbox->w; tbox.h = dbox->h;
+ StrY(srcBM, sbox, &tmpBM, &tbox, REPOP);
+ StrX(&tmpBM, &tbox, dstBM, dbox, mint);
+ }
+ FreeBitMap(&tmpBM);
+ return(SUCCESS);
+ }
+
+static SHORT dum;
+static SHORT dum1 = 2;
+
diff --git a/SYMREQ.C b/SYMREQ.C
new file mode 100644
index 0000000..689cb05
--- /dev/null
+++ b/SYMREQ.C
@@ -0,0 +1,375 @@
+/** symReq.c ******************************************************************/
+/* */
+/*****************************************************************************/
+
+#include <system.h>
+#include <librarie\dos.h>
+
+extern struct RastPort screenRP;
+
+#define NO 0
+#define YES 1
+
+#define local static
+
+#define SYM_CYCLIC 10
+#define SYM_MIRROR 11
+#define SYM_CANCEL 12
+#define SYM_OK 13
+#define SYM_ORDER 14
+
+#define MAX(a,b) ((a)>(b)?(a):(b))
+
+#define REQW 160 /* width of requester */
+#define REQH 84 /* height of requester */
+
+#define ORDX 20
+#define ORDY 40
+
+local struct Window *reqwindow; /* window requester is in */
+local struct Requester Sym_Req= {0}; /* the requester */
+local LONG bugfix = 0; /* temp fix to the V1.07 Requester struct bug */
+
+local UBYTE title[] = "Symmetry";
+local UBYTE cyclic[] = "Cyclic";
+local UBYTE mirrorStr[] = "Mirror";
+local UBYTE order[] = "Order:";
+local UBYTE cancel[] = "Cancel";
+local UBYTE okStr[] = "Ok";
+
+#define NOFONT NULL
+#define ITInit(name) {3,4,JAM2,0,0,NOFONT,name,NULL}
+
+local struct IntuiText cycText = { 0,1,JAM1,3,1,NOFONT,cyclic,NULL};
+local struct IntuiText mirText = { 0,1,JAM1,3,1,NOFONT,mirrorStr,NULL};
+local struct IntuiText ordText = { 0,1,JAM1,ORDX,ORDY,NOFONT,order,NULL};
+local struct IntuiText cancText = { 0,1,JAM1,4,4,NOFONT,cancel,NULL};
+local struct IntuiText okText = { 0, 1,JAM1,4,4,NOFONT,okStr,NULL};
+
+local struct IntuiText titleText = {0,1,JAM1,36,3,NOFONT,title,&ordText};
+
+local SHORT reqX = 0; /* leftedge of requester */
+local SHORT reqY = 0; /* topedge of requester */
+
+local UWORD reqpts[] = { /* xy table of border and reqion lines */
+ 2,1,
+ 2,REQH-2,
+ REQW-3,REQH-2,
+ REQW-3,12,
+ 2,12,
+ 2,1,
+ REQW-3,1,
+ REQW-3,12
+ };
+
+local struct Border reqborder = { /* border for the requester */
+ 0,0,
+ 0,1,
+ JAM1,
+ 8,
+ (SHORT *)&reqpts,
+ NULL
+ };
+
+/*=======================*/
+/*== CYCLIC GADGET ====3=*/
+/*=======================*/
+#define CYC_W 66
+#define CYC_H 15
+
+local SHORT cycbox[] = {
+ -2,-2,
+ CYC_W+1,-2,
+ CYC_W+1,CYC_H-3,
+ -2,CYC_H-3,
+ -2,-2
+ };
+
+local struct Border cycbor = { 0,0, 0,1, JAM1, 5, cycbox, NULL };
+
+local struct Gadget cyclicGadget = {
+ NULL,
+ 10,20,
+ CYC_W,11,
+ 0, /* no highlighting */
+ RELVERIFY | GADGIMMEDIATE ,
+ REQGADGET | BOOLGADGET,
+ (APTR)&cycbor,
+ NULL,
+ &cycText,
+ 0, /* exclude this guy*/
+ NULL,
+ SYM_CYCLIC,
+ NULL
+ };
+
+/*=======================*/
+/*== MIRROR GADGET ====2=*/
+/*=======================*/
+
+local struct Gadget mirrorGadget = {
+ &cyclicGadget,
+ 80,20,
+ CYC_W,11,
+ 0, /* no highlighting */
+ RELVERIFY | GADGIMMEDIATE,
+ REQGADGET | BOOLGADGET,
+ (APTR)&cycbor,
+ NULL,
+ &mirText,
+ 0, /* exclude this guy*/
+ NULL,
+ SYM_MIRROR,
+ NULL
+ };
+
+
+/*======================*/
+/*== ORDER GADGET ======*/
+/*======================*/
+
+#define ORD_WIDTH 30
+#define ORD_HEIGHT 13
+
+local UWORD dt2box1[] = {
+ -2,-2,
+ ORD_WIDTH+1,-2,
+ ORD_WIDTH+1,ORD_HEIGHT-3,
+ -2,ORD_HEIGHT-3,
+ -2,-2};
+
+local struct Border dt2bor1 = {
+ 0,0,
+ 0,1,
+ JAM1,
+ 5,
+ (SHORT *)&dt2box1,
+ NULL};
+
+local struct StringInfo ordInfo = {
+ NULL, /* default and final string */
+ NULL, /* optional undo buffer (later) */
+ 0, /* character position in buffer */
+ 3, /* max characters in buffer */
+ 0, /* buffer position of first displayed character */
+ 0,0,0,0,0,NULL,0,NULL }; /* intuition local variables */
+
+
+local struct Gadget ordGadget = {
+ &mirrorGadget,
+ ORDX+50, ORDY,
+ ORD_WIDTH,ORD_HEIGHT,
+ GADGHCOMP,
+ RELVERIFY | GADGIMMEDIATE | LONGINT,
+ REQGADGET | STRGADGET,
+ (APTR) &dt2bor1,
+ NULL,
+ NULL,
+ 0,
+ (APTR)&ordInfo,
+ SYM_ORDER,
+ NULL };
+
+
+
+/*=======================*/
+/*== CANCEL GADGET ====1=*/
+/*=======================*/
+
+local SHORT dt0box1[] = {0,0,0,0,0,0,0,0,0,0};
+local SHORT dt0box2[] = {1,2,0,2,0,0,1,0,1,2};
+
+/* -- Blue Box -- */
+local struct Border dt0bor2 = { 0,0, 0,1, JAM1, 5, dt0box2, NULL};
+
+/* -- Orange Box -- */
+local struct Border dt0bor1 = { 0,0, 3,0, JAM1, 5, dt0box1, &dt0bor2};
+
+local struct Gadget cancelGadget = {
+ &ordGadget,
+ 10,-24,
+ 72,15,
+ GADGHCOMP | GRELBOTTOM ,
+ RELVERIFY | GADGIMMEDIATE | ENDGADGET,
+ REQGADGET | BOOLGADGET,
+ (APTR)&dt0bor1,
+ NULL,
+ &cancText,
+ 0,
+ NULL,
+ SYM_CANCEL,
+ NULL
+ };
+
+/*=======================*/
+/*==== OK GADGET =====0==*/
+/*=======================*/
+
+local SHORT dt1box1[] = {0,0,0,0,0,0,0,0,0,0};
+local SHORT dt1box2[] = {1,2,0,2,0,0,1,0,1,2};
+
+/* Blue Box */
+local struct Border dt1bor2 = { 0,0, 0,1, JAM1, 5, dt1box2, NULL};
+
+/* Orange Box */
+local struct Border dt1bor1 = { 0,0, 3,0, JAM1, 5, dt1box1, &dt1bor2};
+
+local struct Gadget okGadget = {
+ &cancelGadget,
+ -40,-24,
+ 30,15,
+ GADGHCOMP | GRELBOTTOM | GRELRIGHT,
+ RELVERIFY | GADGIMMEDIATE | ENDGADGET,
+ REQGADGET | BOOLGADGET,
+ (APTR)&dt1bor1,
+ NULL,
+ &okText,
+ 0,
+ NULL,
+ SYM_OK,
+ NULL
+ };
+
+
+/*****************************************************************************/
+/* SYM_FixBox */
+/* */
+/* Adjust a box's corners to a specified width and height */
+/* */
+/*****************************************************************************/
+
+local VOID SYM_FixBox(box1,box2,width,height)
+UWORD box1[],box2[];
+UWORD width,height;
+ {
+ box1[2] = width-1;
+ box1[4] = width-1;
+ box1[5] = height-1;
+ box1[7] = height-1;
+ box2[2] = width-2;
+ box2[4] = width-2;
+ box2[5] = height-3;
+ box2[7] = height-3;
+ }
+
+local SymInitReq() {
+ InitRequester(&Sym_Req);
+ Sym_Req.LeftEdge = reqX;
+ Sym_Req.TopEdge = reqY;
+ Sym_Req.Width = REQW;
+ Sym_Req.Height = REQH;
+ Sym_Req.ReqGadget = &okGadget;
+ Sym_Req.ReqBorder = &reqborder;
+ Sym_Req.ReqText = &titleText;
+ Sym_Req.BackFill = 1;
+ SYM_FixBox(&dt0box1,&dt0box2,strlen(cancel)*10+10,15);
+ SYM_FixBox(&dt1box1,&dt1box2,strlen(okStr)*10+10,15);
+ }
+
+local BOOL SymHandleEvent(); /* forward declaration */
+
+local BOOL doAction;
+local BOOL *symMirror= NULL;
+local SHORT *symN = NULL;
+local UBYTE ordUndo[5];
+local UBYTE ordStr[5];
+
+local BOOL mirrorSet;
+
+local InvGadg(req,gad)
+ struct Requester *req;
+ struct Gadget *gad;
+ {
+ int x,y;
+ SHORT svpen;
+ x = req->LeftEdge + gad->LeftEdge,
+ y = req->TopEdge + gad->TopEdge;
+ svpen = screenRP.FgPen;
+ SetAPen(&screenRP,1);
+ SetXorFgPen(&screenRP);
+ RectFill(&screenRP, x, y, x + gad->Width-1, y + gad->Height-1);
+ SetDrMd(&screenRP,JAM2);
+ SetAPen(&screenRP,svpen);
+ }
+
+local InvOne(){ if (mirrorSet) InvGadg(&Sym_Req,&mirrorGadget);
+ else InvGadg(&Sym_Req,&cyclicGadget); }
+
+local SetMirror(ms) BOOL ms; {
+ InvOne(); mirrorSet = ms; InvOne(); }
+
+/*****************************************************************************/
+/* SymRequest */
+/* */
+/* Initialize and display the requester */
+/*****************************************************************************/
+BOOL SymRequest(w,x,y, nsym, isMirror) struct Window *w; SHORT x,y;
+ SHORT *nsym; BOOL *isMirror;
+ {
+ ULONG saveIDCMP;
+ FixMenCols();
+ reqX = x;
+ reqY = y;
+ symN = nsym;
+ symMirror = isMirror;
+ reqwindow = w;
+ saveIDCMP = w->IDCMPFlags;
+
+ /* --- What class of events do we want to know about? --- */
+ ModifyIDCMP(reqwindow, GADGETUP | GADGETDOWN);
+ SymInitReq();
+
+ stcu_d(ordStr, *nsym, 3);
+ ordInfo.Buffer = ordStr;
+ ordInfo.UndoBuffer = ordUndo;
+ ordInfo.LongInt = *nsym;
+
+ Request(&Sym_Req,w);
+
+ mirrorSet = *isMirror;
+ InvOne();
+
+ doAction = NO;
+
+ ReqListen(w->UserPort,&SymHandleEvent);
+
+ /* restore the IDCMP to its original state */
+
+ ModifyIDCMP(reqwindow, saveIDCMP);
+
+ UnFixMenCols();
+ return(doAction);
+ }
+
+/*****************************************************************************/
+/* Handle events for the this requester */
+/*****************************************************************************/
+
+/* #define SYMDBG */
+
+local BOOL SymHandleEvent(event) struct IntuiMessage *event; {
+ WORD gadgetid;
+ BOOL keepGoing = YES;
+#ifdef SYMDBG
+ printf("SymHandleEvent, event = %lx \n",event);
+#endif
+ if (event->Class== GADGETUP) {
+#ifdef SYMDBG
+ printf(" SymHandlEvent: GADGETUP \n");
+#endif
+
+ gadgetid = ((struct Gadget *)event->IAddress)->GadgetID;
+ if (gadgetid == SYM_CANCEL) keepGoing = NO;
+ else if (gadgetid==SYM_OK) {
+ *symMirror = mirrorSet;
+ *symN = ordInfo.LongInt;
+ doAction = YES; keepGoing = NO;
+ }
+ else if (gadgetid== SYM_CYCLIC) { SetMirror(NO); }
+ else if (gadgetid== SYM_MIRROR) { SetMirror(YES); }
+ }
+ return(keepGoing);
+ }
+
+
+
diff --git a/SYSTEM.H b/SYSTEM.H
new file mode 100644
index 0000000..f78af4d
--- /dev/null
+++ b/SYSTEM.H
@@ -0,0 +1,75 @@
+/*
+ * system.h, general includer for intuition
+ *
+ * Confidential Information: Commodore-Amiga, Inc.
+ * Copyright (c) Commodore-Amiga, Inc.
+ *
+ * Modification History
+ * date author : Comments
+ * ------ ------ -------------------------------------
+ * 1-30-85 -=RJ=- created this file!
+ *
+*******************************************************************/
+
+#include <exec\types.h>
+#include <exec\nodes.h>
+#include <exec\lists.h>
+#include <exec\libraries.h>
+#include <exec\tasks.h>
+#include <exec\ports.h>
+
+#include <exec\devices.h>
+
+#include <exec\interrupts.h>
+
+#include <exec\io.h>
+#include <exec\memory.h>
+/* #include <exec\alerts.h> */
+
+/* ALWAYS INCLUDE GFX.H before any other amiga includes */
+
+#include <hardware\blit.h>
+
+#define blitNode bltnode
+
+#include <graphics\gfx.h>
+
+#include <graphics\regions.h>
+#include <graphics\collide.h>
+#include <graphics\copper.h>
+#include <graphics\display.h>
+#include <hardware\dmabits.h>
+#include <graphics\gels.h>
+
+#include <graphics\clip.h>
+
+#include <graphics\rastport.h>
+#include <graphics\view.h>
+#include <graphics\gfxbase.h>
+/*#include <hardware\intbits.h>*/
+#include <graphics\gfxmacros.h>
+
+#include <graphics\layers.h>
+
+#include <graphics\text.h>
+#include <graphics\sprite.h>
+/*#include <hardware\custom.h>*/
+
+#include <librarie\dos.h>
+/* #include <libraries\dosexten.h> */
+
+/*???extern struct Custom Custom;*/
+/*extern struct Custom custom;*/
+
+#include <devices\timer.h>
+
+#define TimeVal timeval
+
+#include <devices\inputevent.h>
+#include <devices\keymap.h>
+
+/*???#define IECLASS_NULL 0*/
+#include <intuitio\intuitio.h>
+
+/*???#include "intuitionbase.h"*/
+/* #include "intuinternal.h" */
diff --git a/TEXT.C b/TEXT.C
new file mode 100644
index 0000000..5b88a55
--- /dev/null
+++ b/TEXT.C
@@ -0,0 +1,199 @@
+/*--------------------------------------------------------------*/
+/* */
+/* text.c -- text manager */
+/* */
+/*--------------------------------------------------------------*/
+#include <system.h>
+#include <prism.h>
+#include <pnts.h>
+#include <librarie\diskfont.h>
+
+extern struct Window *mainW;
+extern struct Menu *MainMenu;
+extern struct TextFont *OpenDiskFont();
+extern struct TextFont *OpenFont();
+extern struct Menu *FontMenu;
+extern PointRec pnts;
+extern struct RastPort *mainRP;
+extern BOOL everyTime;
+extern SHORT curxpc;
+extern struct RastPort *curRP;
+extern void (*nop)();
+extern SHORT lastPermMode, chgToMode;
+extern void (*killMode)();
+extern BOOL fbOn;
+
+#define local static
+
+/* Text data (in root ) */
+extern SHORT cx,cy,cwidth;
+extern char textBuf[80];
+extern SHORT textX, textY;
+extern SHORT textX0,cw,ch,cyoffs;
+extern SHORT ptext;
+extern SHORT svmd;
+extern BOOL tblinkOn;
+extern SHORT tbCount;
+
+InvTxtBox() { InvTxtXY(mx,my); }
+
+local InvTxtXY(x,y) SHORT x,y; {
+ Box bx;
+ TempXOR();
+ mFrame(MakeBox(&bx,x,y-cyoffs,cw,ch));
+ RestoreMode();
+ }
+
+/* TextBlinker */
+local InvBlink() { InvTxtXY(textX,textY); }
+local TBlink() { if (++tbCount == 300) {
+ tbCount = 0; tblinkOn = !tblinkOn; InvBlink();}
+ }
+
+
+local TBlinkClear() { if (tblinkOn) InvBlink(); tblinkOn = NO; fbOn = NO; }
+local TBlinkShow() { if (!tblinkOn) InvBlink(); tblinkOn = YES; }
+
+local int CLength(c) char c; { return(TextLength(curRP, &c, 1 )); }
+
+local void killText() {
+ TBlinkClear();
+ PlugChProc(NULL);
+ SetPeriodicCall(NULL);
+ }
+
+local void DoTextChar(c) char c; {
+ Box bx;
+ TBlinkClear(); UpdtON();
+ switch(c) {
+ case ESC: UpdtOFF(); killText(); chgToMode = svmd;
+ return; break;
+ case BS: if (ptext>0) {
+ c = textBuf[--ptext];
+ bx.w = CLength(c);
+ textX -= bx.w;
+ bx.x = textX; bx.y = textY - cyoffs;
+ bx.h = ch;
+ EraseBox(&bx);
+ } break;
+ case CR: textX = textX0; textY += ch; ptext = 0; break;
+ case 0: switch(GetNextCh()) {
+ case CLeft: textX -= cw; break;
+ case CRight: textX += cw; break;
+ case CDown: textY += ch; break;
+ case CUp: textY -= ch; break;
+ } break;
+ default:mDispChar(c,textX,textY); textX += CLength(c); textBuf[ptext++]=c; break;
+ }
+ textX0 = MIN(textX0,textX);
+ UpdtOFF();
+ TBlinkShow();
+ }
+
+local void dummy(){}
+
+local void stopBlink() { SetPeriodicCall(NULL); PlugChProc(nop); }
+
+local void StartText() {
+ ptext = 0;
+ textX0 = textX = mx;
+ textY = my;
+ }
+
+void IMText2() {
+ killMode = &killText;
+ SetPeriodicCall(&TBlink);
+ PlugChProc(&DoTextChar);
+ IModeProcs(TBlinkShow,dummy,TBlinkClear,stopBlink,
+ InvTxtBox,nop,InvTxtBox,StartText);
+ }
+
+local GetTextSizeParams() {
+ cw = curRP->TxWidth; ch = curRP->TxHeight;
+ cyoffs = curRP->TxBaseline;
+ }
+
+IMText1() {
+ svmd = lastPermMode;
+ GetTextSizeParams();
+ killMode = &killText;
+ PlugChProc(nop);
+ IModeProcs(&InvTxtBox,nop,&InvTxtBox,nop,
+ &InvTxtBox,nop,&InvTxtBox,&StartText);
+ }
+
+
+extern struct AvailFonts *fontDir;
+extern SHORT nFonts;
+extern SHORT curFontNum;
+extern struct TextFont *font;
+
+LoadAFont(item) SHORT item; {
+ struct TextAttr *fa;
+ UBYTE fontName[20], *dispName, *nm, *fn;
+ SHORT type;
+ struct TextFont *oldFont = font;
+
+ fa = &fontDir[item].af_Attr;
+
+/* restore name to its original 'foo.font' form */
+ dispName = fa->ta_Name; /* save the name */
+ for (nm = dispName, fn = fontName; *nm != '-'; nm++) *fn++ = *nm;
+ *fn = 0;
+ strcat(fontName,".font");
+ fa->ta_Name = fontName;
+
+ type = fontDir[item].af_Type;
+ ZZZCursor();
+
+ if (type == AFF_DISK) {
+ UndoSave(); /* it may put up requestor */
+ font = OpenDiskFont(fa);
+ PaneRefrAll(); /* in case put up requestor */
+ }
+
+ else font = OpenFont(fa);
+
+#ifdef DBGFONT
+ printf(" Opened font named %s, access = %ld \n",fontName,
+ font->tf_Accessors);
+
+ if (oldFont!=NULL)
+ printf(" Closing font named %s, access = %ld. \n",
+ oldFont->tf_Message.mn_Node.ln_Name, oldFont->tf_Accessors);
+#endif
+
+ MyCloseFont(oldFont);
+
+ curFontNum = -1;
+
+ if (font == NULL) InfoMessage(" Couldn't open font", "");
+ else { SetFont(mainRP,font); curFontNum = item; }
+
+ FreeUpMem();
+ if (AvailMem(MEMF_PUBLIC|MEMF_CHIP) < 12000) GunTheBrush();
+
+ fa->ta_Name = dispName;
+
+ GetTextSizeParams();
+ UnZZZCursor();
+ }
+
+extern SHORT clipMaxX, xorg,yorg;
+
+mDispChar(c,x,y) char c; SHORT x,y; {
+ Box bx;
+ SHORT svmd;
+ char s[2];
+ s[0] = c; s[1] = 0;
+ if ( (x+xorg+CLength(c)) <= clipMaxX) {
+ Move(curRP,x +xorg,y + yorg);
+ svmd = curRP->DrawMode;
+ SetDrMd(curRP,JAM1);
+ Text(curRP, s, 1);
+ SetDrMd(curRP,svmd);
+ UpdtSibs(MakeBox(&bx, x , y-curRP->TxBaseline,
+ curRP->TxWidth, curRP->TxHeight));
+ }
+ }
+
diff --git a/TIMER.C b/TIMER.C
new file mode 100644
index 0000000..ecfc6c9
--- /dev/null
+++ b/TIMER.C
@@ -0,0 +1,63 @@
+/****************************************************************************/
+/* timer.c -- implements timer */
+/* */
+/* */
+/****************************************************************************/
+#include <system.h>
+#include <librarie\dos.h>
+
+#define NO 0
+#define YES 1
+
+/****************************************************************************/
+/* InitTimer() */
+/* */
+/* Initialize the timer device */
+/* */
+/****************************************************************************/
+
+BOOL InitTimer(timermsg) struct timerequest *timermsg; {
+ LONG error;
+ struct MsgPort *timerport = NULL;
+ /* --- Create the timer message and port --- */
+ timerport = (struct MsgPort *)CreatePort(0,0);
+ if (timerport == NULL) return(NO);
+ timermsg->tr_node.io_Message.mn_ReplyPort = timerport;
+ error = OpenDevice(TIMERNAME,UNIT_VBLANK,timermsg,0);
+ return ((BOOL)(error==0));
+ }
+
+/****************************************************************************/
+/* SetTimer() */
+/* */
+/* Set the timer so we will be awakened later on */
+/* */
+/****************************************************************************/
+SetTimer(timermsg,sec,micro)
+ struct timerequest *timermsg;ULONG sec,micro;
+ {
+ timermsg->tr_node.io_Command=TR_ADDREQUEST;
+ timermsg->tr_time.tv_secs=sec;
+ timermsg->tr_time.tv_micro=micro;
+ SendIO(timermsg);
+ }
+
+/****************************************************************************/
+/* KillTimer() */
+/* */
+/* Free storage from timerport */
+/* */
+/****************************************************************************/
+KillTimer(timermsg) struct timerequest *timermsg; {
+ struct MsgPort *timerport = timermsg->tr_node.io_Message.mn_ReplyPort;
+ if (timerport!=NULL) DeletePort(timerport);
+ timermsg->tr_node.io_Message.mn_ReplyPort = NULL;
+ }
+
+TimerSigBit(timermsg) struct timerequest *timermsg; {
+ return(1 << timermsg->tr_node.io_Message.mn_ReplyPort->mp_SigBit);
+ }
+
+struct IntuiMessage *GetTimerMsg(timermsg) struct timerequest *timermsg; {
+ return((struct IntuiMessage *)GetMsg(timermsg->tr_node.io_Message.mn_ReplyPort));
+ } \ No newline at end of file
diff --git a/UNPACKER.C b/UNPACKER.C
new file mode 100644
index 0000000..b33fd15
--- /dev/null
+++ b/UNPACKER.C
@@ -0,0 +1,57 @@
+/*----------------------------------------------------------------------*/
+/* unpacker.c Convert data from "cmpByteRun1" run compression. 11/08/85 */
+/* */
+/* By Jerry Morrison and Steve Shaw, Electronic Arts. */
+/* This software is in the public domain. */
+/* */
+/* control bytes: */
+/* [0..127] : followed by n+1 bytes of data. */
+/* [-1..-127] : followed by byte to be repeated (-n)+1 times */
+/* -128 : NOOP. */
+/*----------------------------------------------------------------------*/
+#include "iff\packer.h"
+
+
+/*----------- UnPackRow ------------------------------------------------*/
+
+#define UGetByte() (*source++)
+#define UPutByte(c) (*dest++ = (c))
+
+/* Given POINTERS to POINTER variables, unpacks one row, updating the source
+ * and destination pointers until it produces dstBytes bytes. */
+BOOL UnPackRow(pSource, pDest, srcBytes0, dstBytes0)
+ BYTE **pSource, **pDest; WORD srcBytes0, dstBytes0; {
+ register BYTE *source = *pSource;
+ register BYTE *dest = *pDest;
+ register WORD n;
+ register BYTE c;
+ register WORD srcBytes = srcBytes0, dstBytes = dstBytes0;
+ BOOL error = TRUE; /* assume error until we make it through the loop */
+ WORD minus128 = -128; /* get the compiler to generate a CMP.W */
+
+ while( dstBytes > 0 ) {
+ if ( (srcBytes -= 1) < 0 ) goto ErrorExit;
+ n = UGetByte();
+
+ if (n >= 0) {
+ n += 1;
+ if ( (srcBytes -= n) < 0 ) goto ErrorExit;
+ if ( (dstBytes -= n) < 0 ) goto ErrorExit;
+ do { UPutByte(UGetByte()); } while (--n > 0);
+ }
+
+ else if (n != minus128) {
+ n = -n + 1;
+ if ( (srcBytes -= 1) < 0 ) goto ErrorExit;
+ if ( (dstBytes -= n) < 0 ) goto ErrorExit;
+ c = UGetByte();
+ do { UPutByte(c); } while (--n > 0);
+ }
+ }
+ error = FALSE; /* success! */
+
+ ErrorExit:
+ *pSource = source; *pDest = dest;
+ return(error);
+ }
+