home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frozen Fish 1: Amiga
/
FrozenFish-Apr94.iso
/
bbs
/
alib
/
d1xx
/
d152
/
blk.lha
/
Blk
/
blk.c
< prev
next >
Wrap
C/C++ Source or Header
|
1987-06-15
|
26KB
|
1,086 lines
/*
* 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);
}