home *** CD-ROM | disk | FTP | other *** search
- /*
- * Automatic Requester formatter and generator
- * Reads a requester description and formats graphically
- * then generates the appropriate C-code to specify the requester.
- * See the examples and the documentaion for using the program.
- **
- * Process flow:
- * Box structure read by recursive-descent
- * Boxes formatted, also recursively
- * Borders generated and resolved into a minimum set of Border structs
- * File written, sometimes linearly, sometimes recursively
- **
- * Problems:
- * The file reading isn't the most elegant in the world, relying on global
- * variables and backspacing to look ahead. A more general lexical approach
- * would be nice so that macros could be included (macros are sorely
- * needed). Also, the file formatted front-end is not the most
- * user-friendly in the world and something more mouse-driven would be
- * neat. The source-code generation is not terribily elegant either. A
- * better approach would be to build the actual structures used in the
- * requester dynamically so the requester in the preview window could
- * actually be played with, and generating source-code would be just a
- * matter of dumping the structures to a file. Borders do this already, and
- * it's somewhat more understandable than the other structures.
- **
- * Disclaimer:
- * This is a tool I hacked up for my own use in creating requesters for
- * Modeler 3D. It works for me, but I make no claim as to the robustness or
- * other quality of the code. Personally I shudder at the thought of
- * re-writing this into a real general-purpose tool just because bulk of
- * the code is so poorly written. It does give a nice example of
- * recursive-decent parsing, and the box layout stuff is kind of neat and
- * can be put to good use in other places.
- **
- * Please inform my of any changes or improvements. Enjoy.
- */
-
- #include <stdio.h>
- #include <functions.h>
- #include <exec/types.h>
- #include <intuition/intuition.h>
-
-
- /* Useful defines */
-
- #define NEW(typ) (typ*)AllocMem((LONG)sizeof(typ),0L)
- #define FREE(p,typ) FreeMem(p,(LONG)sizeof(typ))
- #define NEW_N(typ,n) (typ*)AllocMem((LONG)((n)*sizeof(typ)),0L)
- #define FREE_N(p,typ,n) FreeMem(p,(LONG)((n)*sizeof(typ)))
- #define BACKSPACE if (gc != -1) ungetc(gc,file)
- #define abs(x) ((x)<0 ? -(x) : (x))
-
- /* Box types */
-
- #define HBOX 1
- #define VBOX 2
- #define FILL 3
- #define BLOK 4
- #define TEXT 5
- #define HRULE 6
- #define VRULE 7
-
- /* Dimension limits */
-
- #define MAX_GAD 50
- #define BUF_SIZ 500
-
- /* A requester is constructed from a tree of Boxes
- * Boxes are arranged in a binary tree, one subtree is what is inside the
- * Box (sub), the other is the remaining Boxes at the same level (next).
- */
- typedef struct Box {
- short type, /* box type - possibilities defined above */
- gid, /* Gadget id code (0 if none) */
- col; /* color - for borders and text */
- short xs,ys, /* box size (x,y) */
- x,y, /* box position (x,y) */
- nfil; /* number of filers inside this box */
- char *val; /* string for text boxes */
- struct Box *next,*sub; /* binary tree links */
- } BOX;
-
- /* Information on each gadget, zero-th is default
- */
- struct GadInfo {
- short gid, /* gadget id code */
- str, /* string gadget */
- prp; /* prop gadget */
- char *actf, /* flag string */
- *gnam; /* gadget name (GadgetID field) */
- }
- ginfo[MAX_GAD] = { -1,-1,-1,"v",NULL };
-
- /* GLOBAL */
-
- FILE *file; /* input and output files */
- int gc; /* last character read */
- char buf[BUF_SIZ]; /* big buffer for holding strings */
- short bufpos=0; /* position of free space in buf */
- char base[10]; /* base name */
- short ngad=0,igad=0,ntxt=0,itxt=0, /* counters for gadgets, ituitexts, */
- nstr=0,istr=0,nprp=0,iprp=0; /* string and prop gadgets */
- short lgad=1; /* counter for gadinfo array (0 already defined) */
- short def_bcol=1,def_tcol=1; /* default border and text colors */
- struct Border *blst = NULL; /* list header for border structs */
-
- /* generic border and intuitext structs
- */
- struct Border brd = {0,0,1,0,JAM1,2,NULL,NULL};
- struct IntuiText it = {1,0,JAM2,0,0,NULL,NULL,NULL};
-
- /* the preview window
- */
- struct NewWindow nwin = {
- 0,0,300,150,
- -1,-1,0,WINDOWDEPTH|WINDOWDRAG|SMART_REFRESH,
- NULL,NULL,(UBYTE*)"Blocks",NULL,
- NULL,0,0,0,0,WBENCHSCREEN
- };
-
- struct IntuitionBase *IntuitionBase;
-
-
- /* Returns pointer to string containing box type name
- */
- char *BoxType (typ)
- short typ;
- {
- switch (typ) {
- case HBOX: return ("HBOX");
- case VBOX: return ("VBOX");
- case BLOK: return ("BLOK");
- case TEXT: return ("TEXT");
- case FILL: return ("FILL");
- case HRULE: return ("HRULE");
- case VRULE: return ("VRULE");
- }
- }
-
-
- /* Returns a new, initialized Box struct
- */
- BOX *NewBox (type)
- short type;
- {
- BOX *b;
-
- b = NEW(BOX);
- b->type = type;
- b->nfil = b->gid = 0;
- b->val = NULL;
- b->next = b->sub = NULL;
- }
-
-
- /* Recursively frees Box tree
- */
- FreeBox (box)
- BOX *box;
- {
- if (!box) return;
- FreeBox (box->sub);
- FreeBox (box->next);
- FREE(box,BOX);
- }
-
-
- /* Recursively examine all nodes of Box tree and allocate Border structs
- * for all the HRULE and VRULE boxes. Adds new Borders to the main list.
- */
- CreateBorder (box)
- register BOX *box;
- {
- register struct Border *bd;
-
- if (!box) return;
-
- if (box->type == HRULE || box->type == VRULE) {
- bd = NEW(struct Border);
- *bd = brd;
- bd->FrontPen = box->col;
- bd->XY = NEW_N(SHORT,4);
- bd->XY[0] = bd->XY[2] = box->x;
- bd->XY[1] = bd->XY[3] = box->y;
- if (box->type == HRULE) {
- bd->XY[2] += box->xs-1;
- } else {
- bd->XY[3] += box->ys-1;
- }
- bd->NextBorder = blst;
- blst = bd;
- }
- CreateBorder (box->sub);
- CreateBorder (box->next);
- }
-
-
- /* debug routine
- PrintBorder ()
- {
- struct Border *b;
- short i;
-
- for (b=blst; b; b=b->NextBorder) {
- printf ("%d %d %d %d\n:: ", b->LeftEdge, b->TopEdge, b->FrontPen, b->Count);
- for (i=0; i<b->Count; i++) printf ("%d,%d ", b->XY[i*2],b->XY[i*2+1]);
- printf ("\n");
- }
- }
- */
-
-
- /* Frees all Border structs in main Border list
- */
- FreeBorder ()
- {
- register struct Border *b,*nxt;
-
- for (b=blst; b; b=nxt) {
- nxt = b->NextBorder;
- FREE_N(b->XY,SHORT,b->Count*2);
- FREE(b,struct Border);
- }
- }
-
-
- /* Examines all the Borders in the list for adjacency. Any borders that
- * could use the same set of polyline commands are merged into a single
- * struct.
- */
- MergeBorders ()
- {
- register struct Border *a,*b;
- short i0,i1,x,y,*xy,j;
- register short i,ac,bc,merge;
-
- do {
- merge = -1;
- for (a=blst; a; a=a->NextBorder) {
- for (b=a->NextBorder; b; b=b->NextBorder) {
- if (a->FrontPen != b->FrontPen) continue;
- ac = a->Count;
- bc = b->Count;
- for (i0=0; i0<2; i0++) for (i1=0; i1<2; i1++) {
- x = a->XY[i0*2*(ac-1)] - b->XY[i1*2*(bc-1)];
- y = a->XY[i0*2*(ac-1)+1] - b->XY[i1*2*(bc-1)+1];
- if (abs(x) + abs(y) == 1) merge = (i0<<1) + i1;
- }
- if (merge!=-1) break;
- }
- if (merge!=-1) break;
- }
- if (merge!=-1) {
- xy = NEW_N(SHORT,(bc+ac)*2);
- x = (merge&2) == 0; /* reverse a */
- y = (merge&1) == 1; /* reverse b */
- j = 0;
- for (i=0; i<ac; i++) {
- i0 = (x ? ac-1-i : i) * 2;
- xy[j++] = a->XY[i0];
- xy[j++] = a->XY[i0+1];
- }
- for (i=0; i<bc; i++) {
- i0 = (y ? bc-1-i : i) * 2;
- xy[j++] = b->XY[i0];
- xy[j++] = b->XY[i0+1];
- }
- a->Count = j/2;
- FREE_N(a->XY,SHORT,ac*2);
- a->XY = xy;
- /* free b and remove from list */
- for (a=blst; a && a->NextBorder!=b; a=a->NextBorder);
- a->NextBorder = b->NextBorder;
- FREE_N(b->XY,SHORT,bc*2);
- FREE(b,struct Border);
- }
- } while (merge!=-1);
- }
-
-
- /* Second part of Border merging: Eliminates linear segments from all
- * Borders XY lists.
- */
- MergeLinear ()
- {
- register struct Border *b;
- register short i0,i1,i2,k,*xy;
-
- for (b=blst; b; b=b->NextBorder) {
- if (b->Count < 3) continue;
- xy = b->XY;
- i0 = 0;
- i1 = 1;
- i2 = 2;
- k = 2;
- while (i2 < b->Count) {
- while (i2<b->Count &&
- (xy[i0*2]==xy[i1*2] && xy[i1*2]==xy[i2*2] ||
- xy[i0*2+1]==xy[i1*2+1] && xy[i1*2+1]==xy[i2*2+1])) {
- i1++;
- i2++;
- }
- if (i2<b->Count) {
- xy[k++] = xy[i1*2];
- xy[k++] = xy[i1*2+1];
- i0 = i1;
- i1 = i2;
- i2 = i1+1;
- }
- }
- xy[k++] = xy[i1*2];
- xy[k++] = xy[i1*2+1];
-
- k /= 2;
- if (k == b->Count) continue;
- xy = NEW_N(SHORT,k*2);
- for (i0=0; i0<k*2; i0++) xy[i0] = b->XY[i0];
- FREE_N(b->XY,SHORT,b->Count*2);
- b->XY = xy;
- b->Count = k;
- }
- }
-
-
- /* Set the XSize and YSize fields for this box and all below
- */
- Format (box)
- BOX *box;
- {
- BOX *b;
- short mx,my,sx,sy,nf;
-
- if (!box) {
- printf ("Probably an error\nImproper leaf types\n");
- return;
- }
-
- /* deal with the basis (leaf) cases */
- switch (box->type) {
- case BLOK:
- case TEXT:
- return; /* size already set */
- case FILL:
- /* fill node has no size */
- box->xs = box->ys = 0;
- box->nfil = 1;
- return;
- /* H and VRULES have their Y and X sizes already set */
- case HRULE:
- box->xs = 0;
- return;
- case VRULE:
- box->ys = 0;
- return;
- }
-
- /* only H and VBOXes left
- * Format each internal box
- */
- for (b=box->sub; b; b=b->next) Format (b);
-
- /* compute total and max sizes in each direction
- * total (sx,sy) is sum of all sub-boxes, max (mx,my) is max of sub-boxes
- * also inherit filler count
- */
- my = mx = sx = sy = nf = 0;
- for (b=box->sub; b; b=b->next) {
- sx += b->xs;
- sy += b->ys;
- if (b->type == box->type || b->type == FILL) nf += b->nfil;
- if (b->xs > mx) mx = b->xs;
- if (b->ys > my) my = b->ys;
- }
- box->nfil = nf;
-
- /* For horizontal boxes, bounding box is sum in x and max in y,
- * for vertical, bouding box is max in x and sum in y
- */
- if (box->type == HBOX) {
- box->xs = sx;
- box->ys = my;
- } else if (box->type == VBOX) {
- box->xs = mx;
- box->ys = sy;
- } else printf ("Problem city --\nImpossible case\n");
- }
-
-
- short Layin();
-
- /* Compute the layout of the boxes internal to this box
- * Given that this box has correct location
- * The box size computed by Format() is a minimum size,
- * MX and MY are the max that the box can be expanded by filler
- */
- Layout (box,mx,my)
- BOX *box;
- short mx,my;
- {
- BOX *b;
- short ish,z,nfil;
- long gap,ifil;
-
- /* handle basis cases
- */
- if (!box) {
- printf ("Bad leaf nodes\n");
- return;
- }
- /* rules fill out to their max possible size
- */
- if (box->type == HRULE) {
- box->xs = mx;
- } else if (box->type == VRULE) {
- box->ys = my;
- }
- if (box->type != HBOX && box->type != VBOX) return;
-
- /* process only HBOX and VBOX cases recursively
- * any onther case (a basis case) has its position set correctly
- * (see assumptions at head of function)
- */
- ish = (box->type == HBOX);
- z = (ish ? box->x : box->y);
- gap = (ish ? mx-box->xs : my-box->ys);
-
- /* set positions setting filler sizes
- */
- ifil = 0;
- Layin (box,&ifil,ish,z,box->nfil,gap);
- }
-
-
- /* Layout internal boxes
- * Having this as a recursive function deals with
- * the case of VBOXes within VBOXes
- */
- short Layin (box,ifil,ish,z,nfil,gap)
- BOX *box;
- short *ifil,ish,z,nfil;
- long gap;
- {
- BOX *b;
- short t;
-
- for (b=box->sub; b; b=b->next) {
- if (ish) {
- b->x = z;
- b->y = box->y;
- } else {
- b->x = box->x;
- b->y = z;
- }
- if (b->type == FILL) {
- t = (gap*(*ifil+1))/nfil - (gap**ifil)/nfil;
- (*ifil)++;
- if (ish) b->xs = t; else b->ys = t;
- } else if ((ish && b->type==HBOX) || (!ish && b->type==VBOX)) {
- if (ish) b->ys = box->ys; else b->xs = box->xs;
- t = Layin (b,ifil,ish,z,nfil,gap) - z;
- if (ish) b->xs = t; else b->ys = t;
- } else {
- Layout (b,box->xs,box->ys);
- }
- z += (ish ? b->xs : b->ys);
- }
- return z;
- }
-
-
- /* Recursively prints this box and all its contents
- */
- PrintBox (box,lev)
- BOX *box;
- short lev;
- {
- int i;
-
- if (!box) return;
-
- for (i=0; i<lev; i++) printf (" ");
- printf ("%s (%d,%d) %dx%d", BoxType(box->type),
- box->x,box->y, box->xs,box->ys);
- if (box->type == TEXT) printf (" <%s>", box->val);
- if (box->gid>0) printf (" [%d]", box->gid);
- printf ("\n");
- PrintBox (box->sub,lev+1);
- PrintBox (box->next,lev);
- }
-
-
- /* Renders the text boxes in their correct locations in the window.
- * Recursive.
- */
- DisplayBox (win,box,biasx,biasy)
- struct Window *win;
- struct Box *box;
- short biasx,biasy;
- {
- if (!box) return;
-
- if (box->type == TEXT) {
- it.IText = (UBYTE*)box->val;
- it.LeftEdge = box->x;
- it.TopEdge = box->y;
- it.FrontPen = box->col;
- PrintIText (win->RPort,&it,(LONG)biasx,(LONG)biasy);
- }
- DisplayBox (win,box->sub,biasx,biasy);
- DisplayBox (win,box->next,biasx,biasy);
- }
-
-
-
- /* INPUT SECTION */
-
-
- /* Returns true for "c" a blank
- */
- BOOL Blank(c)
- char c;
- {
- return (c==' ' || c=='\n' || c=='\t');
- }
-
-
- /* Returns next non-blank char
- */
- char NextChar()
- {
- char c;
- while (Blank(c=(char)(gc=getc(file))));
- return c;
- }
-
-
- /* read a number if there is one
- * otherwise return false and don't change n's value
- */
- BOOL Qnum(n,radix)
- short *n,radix;
- {
- char c;
- short i=0;
- BOOL isnum=FALSE;
-
- c = NextChar();
- while (c >= '0' && c <= '9') {
- isnum = TRUE;
- i = i*radix + (c-'0');
- c = (char)(gc=getc(file));
- }
- BACKSPACE;
-
- if (isnum) *n = i;
- return isnum;
- }
-
-
- /* Reads a double-quoted string like
- * "stuff"
- * from the file into a place in the string buffer. Returns
- * pointer to the string constant.
- */
- char *ReadString()
- {
- short oldpos;
- char c,*cp;
-
- oldpos = bufpos;
- cp = &buf[bufpos];
- c = NextChar();
- if (c != '\"') {
- printf ("String not found\n");
- return 0;
- }
- while ((c=(char)(gc=getc(file))) != '\"') buf[bufpos++] = c;
- buf[bufpos++] = '\0';
- return cp;
- }
-
-
- /* Read ID of the form
- * :number
- * if there is one. If not, return 0.
- * Number is read as hex.
- */
- short ReadID()
- {
- short id;
- char c;
-
- c = NextChar();
- if (c == ':') {
- fscanf (file, "%x", &id);
- ngad++;
- return id;
- } else {
- BACKSPACE;
- return 0;
- }
- }
-
-
- BOX *ReadBoxList ();
-
- /* Get a box from the open file
- */
- BOX *ReadBox ()
- {
- char c;
- BOX *b;
-
- c = NextChar();
-
- if (c == 'f') return NewBox (FILL);
- if (c == '-') {
- b = NewBox (HRULE);
- b->ys = 1;
- b->col = def_bcol;
- return b;
- }
- if (c == '|') {
- b = NewBox (VRULE);
- b->xs = 1;
- b->col = def_bcol;
- return b;
- }
- if (c == '(') {
- c = NextChar();
- switch (c) {
- case 'h':
- b = NewBox (HBOX);
- b->sub = ReadBoxList ();
- break;
- case 'v':
- b = NewBox (VBOX);
- b->sub = ReadBoxList ();
- break;
- case 't':
- ntxt++;
- b = NewBox (TEXT);
- b->col = def_tcol;
- Qnum (&b->col,10);
- b->val = ReadString();
- if (!b->val) {
- FreeBox (b);
- return 0;
- }
- b->xs = strlen(b->val)*8;
- b->ys = 8;
- break;
- case 'b':
- b = NewBox (BLOK);
- fscanf (file, "%d%d", &b->xs, &b->ys);
- break;
- case '-':
- b = NewBox (HRULE);
- fscanf (file, "%d", &b->ys);
- b->col = def_bcol;
- Qnum (&b->col,10);
- break;
- case '|':
- b = NewBox (VRULE);
- fscanf (file, "%d", &b->xs);
- b->col = def_bcol;
- Qnum (&b->col,10);
- break;
- default:
- printf ("Unknown Key Char\n");
- return 0;
- }
-
- c = NextChar();
- if (c != ')') {
- printf ("parse problem - expected ')'\n");
- FreeBox (b);
- return 0;
- }
- b->gid = ReadID();
- return b;
-
- } else {
- BACKSPACE;
- return 0;
- }
- }
-
-
- /* Read a list of boxes from the file stream
- * Recursive - read a box, then read a list.
- */
- BOX *ReadBoxList ()
- {
- BOX *b;
-
- b = ReadBox ();
- if (!b) return 0;
-
- b->next = ReadBoxList();
- return b;
- }
-
-
- /* Reads the list of gadget info from the end of the file
- * Reads as much as there is
- * format is:
- * number {s|p} {:string} string
- * stuff in {}'s is optional
- */
- ReadGadInfo()
- {
- char c;
- short i;
-
- i = 0;
- while (Qnum(&i,16)) {
- ginfo[lgad].gid = i;
- ginfo[lgad].gnam = NULL;
- ginfo[lgad].str = -1;
- ginfo[lgad].prp = -1;
- c = NextChar();
- if (c == 's') {
- ginfo[lgad].str = nstr++;
- c = NextChar();
- } else if (c == 'p') {
- ginfo[lgad].prp = nprp++;
- c = NextChar();
- }
- if (c==':') {
- ginfo[lgad].gnam = ReadString();
- } else {
- BACKSPACE;
- }
- ginfo[lgad++].actf = ReadString();
- }
-
- /* print out list of gadget info structs for pure delight
- */
- for (i=0; i<lgad; i++) {
- printf ("gad %d %d, <%s>", i, ginfo[i].gid, ginfo[i].actf);
- if (ginfo[i].gnam) printf (" [%s]", ginfo[i].gnam);
- if (ginfo[i].str != -1) printf (" (string)");
- if (ginfo[i].prp != -1) printf (" (prop)");
- printf ("\n");
- }
- }
-
-
- /* To read file:
- * open, read base name, read optional default border and text colors
- * read a box (a BIG box), read gadget info blocks, close
- */
- BOX *ReadFile (nam)
- char *nam;
- {
- BOX *box;
- short i;
-
- printf ("opening file <%s>\n", nam);
- file = fopen (nam,"r");
- if (!file) {
- printf ("Cannot open %s\n", nam);
- exit(0);
- }
- fscanf (file, "%s", base);
- Qnum (&def_bcol,10);
- Qnum (&def_tcol,10);
- box = ReadBox ();
- ReadGadInfo();
-
- fclose (file);
- return box;
- }
-
-
- /* OUTPUT SECTION (this whole thing is crufty, sorry)
- * (except perhaps the Border stuff)
- */
-
-
- /* Recursively locate and print the string for a given gadget id
- * Truncate trailing spaces
- */
- WriteBufEntry (id,box)
- short id;
- BOX *box;
- {
- int i;
-
- if (!box) return;
-
- if (box->gid == id) {
- for (i=strlen(box->val)-1; i>0; i--) {
- if (box->val[i] == ' ') box->val[i] = '\0';
- else break;
- }
- fprintf (file, "\"%s\"", box->val);
- if (++istr != nstr) fprintf (file, ", ");
- box->val = NULL;
- ntxt--;
- } else {
- WriteBufEntry (id,box->sub);
- WriteBufEntry (id,box->next);
- }
- }
-
-
- /* Output the StringInfo structs for all the string gadgets
- */
- WriteStrInfo ()
- {
- int i;
-
- for (i=0; i<lgad; i++) {
- if (ginfo[i].str != -1) {
- fprintf (file, " {&%s_nbuf[%d][0],undo,0,NUMCHR,0}",base,istr++);
- if (istr == nstr) fprintf (file, "\n");
- else fprintf (file, ",\n");
- }
- }
- }
-
-
- /* Output the PropInfo structs for all the proportional gadgets
- */
- WritePrpInfo ()
- {
- int i;
-
- for (i=0; i<lgad; i++) {
- if (ginfo[i].prp != -1) {
- fprintf (file, " {AUTOKNOB|FREEHORIZ|PROPBORDERLESS,\
- 0x8000,0,0x8000,0x8000}");
- if (++iprp == nprp) fprintf (file, "\n");
- else fprintf (file, ",\n");
- }
- }
- }
-
-
- /* Recursively locate and output Gadget structs for all gadgets
- */
- WriteGad (box)
- BOX *box;
- {
- int i,j,l,t;
-
- if (!box) return;
-
- if (box->gid) {
- /* find the Gadinfo entry for this gadget. search backwards so that a
- * failure to locate lands us on Gadinfo 0, the default
- */
- for (i=lgad-1; i>=0; i--)
- if (ginfo[i].gid == box->gid || i == 0) break;
-
- if (++igad==ngad) {
- fprintf (file, " {NULL");
- } else {
- fprintf (file, " {&%s_gad[%d]", base,igad);
- }
- fprintf (file, ",%d,%d,%d,%d,\n ", box->x,box->y,box->xs,box->ys);
- if (index(ginfo[i].actf, 'B')) fprintf (file, "GADGHBOX,");
- else fprintf (file, "GADGHCOMP,");
-
- t = 0;
- if (l = strlen(ginfo[i].actf)) for (j=0; j<l; j++) {
- switch (ginfo[i].actf[j]) {
- case 't':
- case 'v':
- case 'e':
- case 'i':
- case 'c':
- case 'f':
- if (t) fprintf (file, "|");
- t = 1;
- }
- switch (ginfo[i].actf[j]) {
- case 't': fprintf (file, "TOGGLESELECT"); break;
- case 'v': fprintf (file, "RELVERIFY"); break;
- case 'e': fprintf (file, "ENDGADGET"); break;
- case 'i': fprintf (file, "GADGIMMEDIATE"); break;
- case 'c': fprintf (file, "STRINGCENTER"); break;
- case 'f': fprintf (file, "FOLLOWMOUSE"); break;
- }
- } else fprintf (file, "0");
-
- if (ginfo[i].str != -1) fprintf (file, ",STRGADGET");
- else if (ginfo[i].prp != -1) fprintf (file, ",PROPGADGET");
- else fprintf (file, ",BOOLGADGET");
- fprintf (file, "|REQGADGET,\n ");
- if (ginfo[i].prp != -1)
- fprintf (file, "(APTR)&%s_pimg[%d],", base,ginfo[i].prp);
- else fprintf (file, "NULL,");
- fprintf (file, "NULL,NULL,0,");
- if (ginfo[i].str != -1)
- fprintf (file, "(APTR)&%s_sinfo[%d],", base,ginfo[i].str);
- else if (ginfo[i].prp != -1)
- fprintf (file, "(APTR)&%s_pinfo[%d],", base,ginfo[i].prp);
- else fprintf (file, "NULL,");
-
- if (ginfo[i].gnam) fprintf (file, "%s,NULL}", ginfo[i].gnam);
- else fprintf (file, "0x%x,NULL}", box->gid);
- if (igad==ngad) fprintf (file, "\n");
- else fprintf (file, ",\n");
- }
- WriteGad (box->sub);
- WriteGad (box->next);
- }
-
-
- /* Recursively locate and output IntuiText structs for all TEXT boxes
- */
- WriteText (box)
- BOX *box;
- {
- if (!box) return;
-
- if (box->type == TEXT && box->val) {
- fprintf (file, " {%d,0,JAM2,%d,%d,&ta,(UBYTE*)\"%s\",",
- box->col,box->x,box->y,box->val);
- if (++itxt==ntxt) {
- fprintf (file, "NULL}\n");
- } else {
- fprintf (file, "&%s_txt[%d]},\n", base,itxt);
- }
- }
- WriteText (box->sub);
- WriteText (box->next);
- }
-
-
- /* Write out list of Border structs from main list
- */
- WriteBorder ()
- {
- register struct Border *b;
- register short i=0,j=0;
-
- fprintf (file, "struct Border %s_brd[] = {\n", base);
- for (b=blst; b; b=b->NextBorder) {
- fprintf (file, " {0,0,%d,0,JAM1,%d,&%s_brd_XY[%d],",
- b->FrontPen,b->Count,base,i);
- i += b->Count*2;
- if (b->NextBorder) {
- fprintf (file, "&%s_brd[%d]},\n", base,++j);
- } else {
- fprintf (file, "NULL}\n");
- }
- }
- fprintf (file, "};\n");
- }
-
-
- /* Write out list of XY arrays from Border struct main list
- */
- WriteBorderXY ()
- {
- register struct Border *b;
- register short i;
-
- fprintf (file, "short %s_brd_XY[] = {\n", base);
- for (b=blst; b; b=b->NextBorder) {
- fprintf (file, " ");
- for (i=0; i<b->Count; i++) {
- fprintf (file, "%d,%d", b->XY[i*2],b->XY[i*2+1]);
- if (i!=b->Count-1 || b->NextBorder) fprintf (file, ", ");
- }
- fprintf (file, "\n");
- }
- fprintf (file, "};\n");
- }
-
-
- /* The main output function
- */
- WriteFile (name,box)
- char *name;
- BOX *box;
- {
- short i;
-
- if (!(file = fopen (name, "w"))) {
- printf ("Can't open output file\n");
- return;
- }
-
- /* write optional string gadget structs
- */
- if (nstr) {
- fprintf (file,"UBYTE %s_nbuf[%d][NUMCHR] = {\n ", base,nstr);
- for (i=0; i<lgad; i++)
- if (ginfo[i].str != -1) WriteBufEntry (ginfo[i].gid,box);
- istr = 0;
- fprintf (file,"\n};\n\nstruct StringInfo %s_sinfo[] = {\n", base);
- WriteStrInfo();
- fprintf (file,"\n};\n");
- }
-
- /* write optional prop gadget structs
- */
- if (nprp) {
- fprintf (file,"\nstruct Image %s_pimg[%d];\n", base,nprp);
- fprintf (file,"struct PropInfo %s_pinfo[] = {\n", base);
- WritePrpInfo();
- fprintf (file,"};\n");
- }
-
- /* write gadgets, text and borders (not optional)
- */
- fprintf (file,"\nstruct Gadget %s_gad[] = {\n", base);
- WriteGad (box);
- fprintf (file,"};\n\nstruct IntuiText %s_txt[] = {\n", base);
- WriteText (box);
- fprintf (file, "};\n\n");
- WriteBorderXY ();
- WriteBorder ();
-
- /* the requester itself
- */
- fprintf (file, "\n\nstruct Requester %s_req = {\n\
- NULL,0,0,%d,%d,0,0,%s_gad,%s_brd,%s_txt,0,0,\n\
- NULL,{NULL},NULL,NULL,{NULL}};\n", base,box->xs,box->ys,base,base,base);
-
- fclose (file);
- }
-
-
- main(argc,argv)
- int argc;
- char *argv[];
- {
- if (argc < 2 || argc > 4) {
- printf ("Usage: blk <file> [<outfile> | %%]\n");
- exit(0);
- }
-
- IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",0L);
- if (IntuitionBase) {
- Body (argc,argv);
- CloseLibrary (IntuitionBase);
- }
- }
-
-
- Body(argc,argv)
- int argc;
- char *argv[];
- {
- struct Window *win;
- BOX *b;
- short h,w;
-
- b = ReadFile (argv[1]);
- Format (b);
- b->x = b->y = 0;
- Layout (b,b->xs,b->ys);
- if (argc == 3 && argv[2][0] == '%') PrintBox (b,0);
- CreateBorder (b);
- MergeBorders ();
- MergeLinear ();
-
- /* open a window to preview the requester layout
- */
- w = b->xs+20;
- h = b->ys+20;
- if (w>640 || h>200) printf ("requester too large\n");
- else {
- nwin.Width = w;
- nwin.Height = h;
- win = OpenWindow (&nwin);
- if (win) {
- DrawBorder (win->RPort,blst,(LONG)win->BorderLeft+5,(LONG)win->BorderTop+5);
- DisplayBox (win,b,win->BorderLeft+5,win->BorderTop+5);
- /* if output specified, write it out, otherwise wait */
- if (argc == 3 && argv[2][0] != '%') WriteFile(argv[2],b);
- else Delay (300L);
- CloseWindow (win);
- } else printf ("Unable to open Window\n");
- }
-
- FreeBorder ();
- FreeBox (b);
- }
-