/*ScianFontMapper.c
  Eric Pepke
  Asks user to map special characters in the SGI fonts
*/

#include <stdio.h>
#include <gl.h>
#include <device.h>
#include "machine.h"
#ifdef FONTS4D
#include <fmclient.h>
#endif


#define BLOCKSIZE	40
#define TOPSPACE	200
#define INSTRUCTIONX	(10)
#define INSTRUCTIONY	(9 * BLOCKSIZE + TOPSPACE - 20)
#define INSTRUCTIONLINE	(18)
#define SAMPLEX		(16 * BLOCKSIZE - 60)
#define SAMPLEY		(9 * BLOCKSIZE + TOPSPACE - 60)
#define SAMPLERADIUS	20

#define LINEWIDTH	2
#define NOTFOUNDSIZE	4

#ifdef FONTS4D
#define FONTSIZE	24
#else
#define FONTSIZE	12
#endif


#define CHAR_COPYRIGHT	0	/*Copyright character*/
#define CHAR_REGISTERED	1	/*Registered copyright*/
#define CHAR_CROSS	2	/*Cross product*/
#define CHAR_DOT	3	/*Dot product*/
#define N_CHARS		4	/*Number of chars to assign*/

int charAssignments[N_CHARS];

char *charNames[N_CHARS] =
    {
	"COPYRIGHT    ",
	"REGISTERED   ",
	"CROSS        ",
	"DOT          "
    };

#define ST_BEGIN	0	/*Begin state*/
#define ST_INSTR2	1	/*Second instruction state*/
#define ST_COPYRIGHT	2	/*Get copyright*/
#define ST_REGISTERED	3	/*Get registered*/
#define ST_CROSS	4	/*Get cross*/
#define ST_DOT		5	/*Get dot*/
#define ST_THANKYOU	6	/*Thanks and close*/
#define N_STATES	7	/*# of states*/

int running = 1;	/*True iff running*/
int state = ST_BEGIN;		/*State of the system*/

char tempStr[400];

char *instructions[N_STATES] =
    {
/*                                                                   | */
"SciAn uses characters in the Silicon Graphics font manager which are\n\
outside the normal range of ASCII characters.  Unfortunately, which \n\
character is which tends to change depending on the version of the \n\
font manager.  Your help is required to find and asign characters.\n\n\
Click with the mouse anywhere in the window to continue, or press \n\
the Esc key to abort.",

"You will be presented with a series of characters, described in a\n\
short paragraph with an accompanying approximate illustration.  For \n\
each character, please find the character it most resembles in the \n\
boxes below and click in the appropriate box.  If you cannot find \n\
the character, click in the Not Shown box.\n\n\
If you make a mistake, press the Esc key to go back.\n\n\
Click with the mouse anywhere in the window to continue.",

"Please find and click on the copyright\n\
symbol, which looks like a little 'C' in\n\
a circle and resembles the illustration\n\
on the right.  If the symbol is not shown,\n\
click in the Not Shown box.",

"Please find and click on the registered\n\
copyright symbol, which looks like a \n\
little 'R' in a circle and resembles the\n\
illustration on the right.  If the symbol\n\
is not shown, click in the Not Shown box.",

"Pleas find and click on the cross\n\
product symbol, which looks like a big\n\
'X' centered in the character and resembles\n\
the illustration on the right.  If the\n\
symbol is not shown, click in the Not\n\
Shown box.",

"Pleas find and click on the dot\n\
product symbol, which looks like a dot\n\
centered in the character space and \n\
resembles the illustration on the right.\n\
This one can be hard to find, so look\n\
carefully.  If the symbol is not shown,\n\
click in the Not Shown box.",

"Thank you for filling in the font information for SciAn.  Please \n\
click anywhere in the window to write the configuration file and \n\
exit.  Then proceed to the next step in the installation process."
    };

#if 0
TestBlock(int l, int r, int b, int t, int foreColor, int backColor)
/*Does a test block*/
{
    int lt, rt, x, y, fx, fy;

    color(backColor);
    rectf(l, b, r, t);

    color(foreColor);

    x = l + LINEINSET;
    for (lt = 0; lt < NLINES; ++lt)
    {
	rectf(x, b + LINEINSET, x + lt, t - LINEINSET);
	x += LINESPACE + lt;
    }

    y = b + LINEINSET;
    for (lt = 0; lt < NLINES; ++lt)
    {
	rectf(x, y, r - LINEINSET, y + lt);
	y += LINESPACE + lt;
    }
    fx = x;
    for (rt = 0; rt < NRECTS; ++rt)
    {
	rectf(x, y, x + rt, y + rt);
	x += RECTSPACE + rt;
    }
    fy = y + rt + LINESPACE;
    cmov2i(fx, fy);
    fmprstr("Text");
}

DoTest(int l, int r, int b, int t)
/*Does a test pattern*/
{
    int backColor, foreColor, sl, sr, sb, st, i, j;

    for (i = 0; i < 8; ++i)
    {
	backColor = i;
	foreColor = 0;
	sl = l + i * (r - l) / 8;
	sr = sl + (r - l) / 8;

	for (j = 0; j < 8; ++j)
	{
	    sb = b + j * (t - b) / 8;
	    st = sb + (t - b) / 8;

	    TestBlock(sl, sr, sb, st, foreColor, backColor);

	    ++foreColor;
	}
    } 
}
#endif

int IsAssigned(c)
int c;
/*Returns true iff c is assigned*/
{
    int k;
    for (k = 0; k < N_CHARS; ++k)
    {
	if (charAssignments[k] == c) return 1;
    }
    return 0;
}

void DrawCharBox(c)
int c;
{
    int i, j;
    unsigned char s[2];

    i = c % 16;
    j = c / 16 - 8;

    if (j < 0 || j >= 8) return;

    if (IsAssigned(c))
    {
	color(YELLOW);
    }
    else
    {
	color(WHITE);
    }
    rectfi(i * BLOCKSIZE + 1, (7 - j) * BLOCKSIZE + 2,
		i * BLOCKSIZE + BLOCKSIZE - 2, (8 - j) * BLOCKSIZE - 2);

    color(BLACK);
    s[0] = c;
    s[1] = 0;
    cmov2i(i * BLOCKSIZE + BLOCKSIZE / 2 - FONTSIZE / 2,
		   (7 - j) * BLOCKSIZE + BLOCKSIZE / 2 - FONTSIZE / 2);
#ifdef FONTS4D
    fmprstr((const char *) s);
#else
    charstr(s);
#endif
}

void DrawFontBoxes()
/*Draws all the font boxes*/
{
    int i, j;
#ifdef FONTS4D
    fmfonthandle font;
#endif

    linewidth(LINEWIDTH);

    /*Draw black lines*/
    color(BLACK);
    for (j = 0; j < 8; ++j)
    {
	move2i(0, BLOCKSIZE * 8 - j * BLOCKSIZE);
	draw2i(BLOCKSIZE * 16, BLOCKSIZE * 8 - j * BLOCKSIZE);
    }
    for (i = 1; i < 16; ++i)
    {
	move2i(i * BLOCKSIZE, BLOCKSIZE * 8);
	draw2i(i * BLOCKSIZE, 0);
    }
    move2i(0, BLOCKSIZE * 9);
    draw2i(BLOCKSIZE * NOTFOUNDSIZE, BLOCKSIZE * 9);
    move2i(BLOCKSIZE * NOTFOUNDSIZE, BLOCKSIZE * 9);
    draw2i(BLOCKSIZE * NOTFOUNDSIZE, BLOCKSIZE * 8);

    /*Draw the fonts*/
#ifdef FONTS4D
    font = fmfindfont("Helvetica");
    if (font)
    {
	font = fmscalefont(font, FONTSIZE);
	fmsetfont(font);
    }
    else
    {
	printf("The font Helvetica cannot be found on your system.  There must be \n\
something wrong with your system.  Please check the font system and try\n\
again.  If you cannot fix the problem, you can still install SciAn without\n\
the Silicon Graphics font manager by removing the #define FONTS4D from the\n\
machin.h include file.\n");
	exit(-1);
    }
#else
    font(0);
#endif

    for (j = 0; j < 8; ++j)
    {
	for (i = 0; i < 16; ++i)
	{
	    DrawCharBox(128 + i + j * 16);
	}
    }
    cmov2i(BLOCKSIZE / 2 - FONTSIZE / 2, 8 * BLOCKSIZE + BLOCKSIZE / 2 - FONTSIZE / 2);
#ifdef FONTS4D
    fmprstr("Not Shown");
#else
    charstr("Not Shown");
#endif
}

void PrintString(x, y, s)
int x, y;
char *s;
/*Prints string at x, y with carriage return*/
{
    char *s2;
    while (*s)
    {
	s2 = tempStr;
	while(*s && (*s != '\n'))
	{
	    *s2++ = *s++;
	}
	*s2 = 0;
	if (*s) ++s;
	cmov2i(x, y);
	charstr(tempStr);
	y -= INSTRUCTIONLINE;
    }
}

void DrawInstructions()
/*Draws the instructions*/
{
    int height;
    color(WHITE);
    rectfi(0, 9 * BLOCKSIZE + 1, 16 * BLOCKSIZE, 9 * BLOCKSIZE + TOPSPACE);
    color(BLACK);
    PrintString(INSTRUCTIONX, INSTRUCTIONY, instructions[state]);

    switch(state)
    {
	case ST_COPYRIGHT:
	    /*Draw the copyright symbol*/
	    circi(SAMPLEX, SAMPLEY, SAMPLERADIUS);
	    arci(SAMPLEX, SAMPLEY, SAMPLERADIUS * 0.6, 450, 3150);
	    break;
	case ST_REGISTERED:
	    /*Draw the registered copyright symbol*/
	    circi(SAMPLEX, SAMPLEY, SAMPLERADIUS);
	    height = SAMPLERADIUS * 0.6;
	    move2i(SAMPLEX, SAMPLEY + height);
	    draw2i(SAMPLEX - height / 2, SAMPLEY + height);
	    draw2i(SAMPLEX - height / 2, SAMPLEY - height);
	    move2i(SAMPLEX - height / 2, SAMPLEY);
	    draw2i(SAMPLEX, SAMPLEY);
	    draw2i(SAMPLEX + height / 2, SAMPLEY - height);
	    arci(SAMPLEX, SAMPLEY + height / 2, height / 2, -900, 900);
	    break;
	case ST_CROSS:
	    /*Draw the cross symbol*/
	    move2i(SAMPLEX - SAMPLERADIUS, SAMPLEY - SAMPLERADIUS);
	    draw2i(SAMPLEX + SAMPLERADIUS, SAMPLEY + SAMPLERADIUS);
	    move2i(SAMPLEX - SAMPLERADIUS, SAMPLEY + SAMPLERADIUS);
	    draw2i(SAMPLEX + SAMPLERADIUS, SAMPLEY - SAMPLERADIUS);
	    break;
	case ST_DOT:
	    /*Draw the dot symbol*/
	    cmov2i(SAMPLEX, SAMPLEY);
	    charstr(".");
	    break;
    }
}

void DrawEverything()
/*Draws everything*/
{
    color(WHITE);
    clear();
    DrawFontBoxes();
    DrawInstructions();
}

void IncrementState()
/*Increments the state by 1*/
{
    ++state;
    if (state >= N_STATES)
    {
	running = 0;
    }
    else
    {
	DrawInstructions();
    }
}

void AssignChar(c, v)
int c, v;
/*Assigns character c to value v*/
{
    charAssignments[c] = v;
    DrawCharBox(v);
}

void UnassignChar(c)
int c;
/*Unassigns character c*/
{
    int v;
    v = charAssignments[c];
    charAssignments[c] = 0;
    if (v)
    {
	DrawCharBox(v);
    }
}

void DecrementState()
/*Decrements the state by 1*/
{

    --state;
    if (state < 0)
    {
	running = 0;
    }
    else
    {
	/*Do stuff for decrementing state*/
	switch (state)
	{
	    case ST_COPYRIGHT:
		UnassignChar(CHAR_COPYRIGHT);
		break;
	    case ST_REGISTERED:
		UnassignChar(CHAR_REGISTERED);
		break;
	    case ST_CROSS:
		UnassignChar(CHAR_CROSS);
		break;
	    case ST_DOT:
		UnassignChar(CHAR_DOT);
		break;
	}
	DrawInstructions();
    }
}

int GetCharFromPress(x, y)
long x, y;
/*Gets a character from a press, or 0 if not found*/
{
    int i, j;

    j = x / BLOCKSIZE;
    i = 7 - (y / BLOCKSIZE);
    if (i < 0) return 0;
    return 128 + i * 16 + j;
}

void AssignXYChar(c, x, y)
int c, x, y;
/*Assign a character c in response to a click in x, y*/
{
    int v;
    v = GetCharFromPress(x, y);
    AssignChar(c, v);
}

void MousePress(x, y)
long x, y;
/*Press of the mouse*/
{
    int c;

    switch (state)
    {
	case ST_COPYRIGHT:
	    /*Assign the copyright character*/
	    AssignXYChar(CHAR_COPYRIGHT, x, y);
	    break;
	case ST_REGISTERED:
	    /*Assign the registered character*/
	    AssignXYChar(CHAR_REGISTERED, x, y);
	    break;
	case ST_CROSS:
	    /*Assign the cross character*/
	    AssignXYChar(CHAR_CROSS, x, y);
	    break;
	case ST_DOT:
	    /*Assign the dot character*/
	    AssignXYChar(CHAR_DOT, x, y);
	    break;
	default:
	    break; 
    }
}

main()
{
    int k;
    int width, height;
    long ox, oy;
    long mx, my;
    long win;

    for (k = 0; k < N_CHARS; ++k)
    {
	charAssignments[k] = 0;
    }

#ifdef FONTS4D

    foreground();

    width = BLOCKSIZE * 16;
    height = BLOCKSIZE * 9 + TOPSPACE;

    minsize(width, height);
    maxsize(width, height);

    win = winopen("Font test");
    winset(win);
    wintitle("Font test");
    ortho2(-0.5,width - 0.5,-0.5,height - 0.5);

    fminit();

    DrawEverything();

    qdevice(MOUSE1);
    qdevice(MOUSE2);
    qdevice(MOUSE3);
    qdevice(WINQUIT);
    qdevice(WINCLOSE);
    qdevice(ESCKEY);

    while(running)
    {
	while (qtest())
 	{
	    long whichDevice;
	    short theData;

	    whichDevice = qread(&theData);
	    switch(whichDevice)
	    {
		case REDRAW:
		case PIECECHANGE:
		    DrawEverything();
		    break;
		case WINQUIT:
		case WINCLOSE:
		    running = 0;
		    break;
		case MOUSE1:
		case MOUSE2:
		case MOUSE3:
		    if (theData)
		    {
			mx = getvaluator(MOUSEX);
			my = getvaluator(MOUSEY);
			getorigin(&ox, &oy);
			mx -= ox;
			my -= oy;
			MousePress(mx, my);
		    }
		    else
		    {
			IncrementState();
		    }
		    break;
		case ESCKEY:
		    if (theData)
		    {
			DecrementState();
		    }
		    break;
	    }
	}
    }

    unqdevice(ESCKEY);
    unqdevice(WINCLOSE);
    unqdevice(WINQUIT);
    unqdevice(MOUSE1);
    unqdevice(MOUSE2);
    unqdevice(MOUSE3);

#else
    printf("Your workstation does not have the SGI font manager installed, so the \n");
    printf("default system font and defined raster fonts will be used.  The fonts\n");
    printf("should work correctly.\n");
#endif

    if (state > 0)
    {
	/*Write the file*/
	FILE *outFile;
	outFile = fopen("ScianFontMappings.h", "w");
	if (outFile)
	{
	    fprintf(outFile, "/*ScianFontMappings.h is produced by the ScianFontMapper.c program\n\
  during the make FONTS process.  Do not change this file.\n*/\n\n");
	    for (k = 0; k < N_CHARS; ++k)
	    {
		if (charAssignments[k])
		{
		    fprintf(outFile, "#define ST_%s \"\\%o\"\n",
			charNames[k],
			charAssignments[k]);
		    fprintf(outFile, "#define CH_%s \'\\%o\'\n",
			charNames[k],
			charAssignments[k]);
		}
		else
		{
		    fprintf(outFile, "#define ST_%s\n",
			charNames[k]);
		}
	    }
	    fclose(outFile);
	}
	else
	{
	    printf("The output file ScianFontMappings.h cannot be created.  Check to make\n\
sure that you have write access to this directory, the disk is not full, and\n\
there is currently no file with that name that you cannot overwrite and try\n\
again.");
	}
    }
}
