#include <stdio.h>
#include <stdlib.h>
#include <X11/Intrinsic.h>
#include <X11/Shell.h>
#include <X11/StringDefs.h>
#include <X11/Xlib.h>
#include <Xaw3d/Form.h>

Window		win;
Display		*d;
GC         	gc;
Widget		toplevel, drawArea;
XtAppContext	appcon;

typedef    char* charptr;

enum COLORS { BLACK, BLUE, GREEN, CYAN, RED, MAGENTA, BROWN, LIGHTGRAY,
    DARKGRAY, LIGHTBLUE, LIGHTGREEN, LIGHTCYAN, LIGHTRED, LIGHTMAGENTA,
    YELLOW, WHITE, MAXCOL};

charptr colorNames[] = {"black","blue","green","cyan","red","magenta",
"brown","lightgray","darkgray","lightblue","lightgreen","lightcyan",
"red3","magenta4","yellow","white"};

enum FONTS { DEFAULT_FONT, TIMES, HELVETICA, MAXFONT};

#define    MAXSIZE    3
charptr fontNames[MAXSIZE][MAXFONT] = {
    { "6x8",  "*times*-12-*", "*helvetica*-12-*"},
    { "8x8",  "*times*-14-*", "*helvetica*-14-*"},
    { "9x15", "*times*-18-*", "*helvetica*-18-*"}
};

XFontStruct *fontID[MAXSIZE][MAXFONT];

Pixel bg, fg, colorIndex[MAXCOL];

void initColors ()
{
int        i;
XColor      exact, screen;
Colormap    cm;

cm = DefaultColormap (d, 0);
    
for (i=0; i < MAXCOL; ++i)
    {
    if( XAllocNamedColor(d, cm, colorNames[i], &exact, &screen))
        colorIndex[i] = exact.pixel;
    else {
        printf("could not find %d\n", i);
        colorIndex[i] = screen.pixel;
        }
    }
bg = colorIndex[0];
fg = colorIndex[MAXCOL - 1];
}

void initFonts ()
{
    int    i, j;

    for (i=0; i<MAXSIZE; ++i)
       for (j=0; j<MAXFONT; ++j) {
        fontID [i][j] = XLoadQueryFont (d, fontNames [i][j]);
        if (! fontID [i][j]) {
            fprintf (stderr, "Failed to load %s\n", fontNames [i][j]);
            fontID [i][j] = XLoadQueryFont (d, "fixed");
	}
    }
}

void mycode();  // user writes his code inside this

void redraw(Widget w, XtPointer calldata, XEvent *ev, Boolean dis)
{
    mycode();
}

void clearViewport ()
{
    XClearWindow (d, win);
    XFlush (d);
}


void makeWindow(int width, int height)
{
XGCValues     values;  
int    argc = 0;
char    **argv = NULL;

toplevel = XtVaAppInitialize(&appcon, "prog", NULL, 0, &argc, argv,
		NULL, XtNtitle, "Turbo-C Emulator", NULL);
printf("TOP\n");

d = XtDisplay (toplevel);
initColors ();
initFonts ();

drawArea = XtVaCreateManagedWidget("drawArea", 
         formWidgetClass, toplevel,
    XtNbackground, bg,
    XtNforeground, fg,
    XtNwidth, width, 
    XtNheight, height,
    NULL);
    
gc = XtGetGC (drawArea, GCForeground | GCBackground, &values);


XtAddEventHandler (drawArea, ExposureMask , FALSE,
    (XtEventHandler) redraw, (XtPointer)gc);

XtRealizeWidget (toplevel);
win = XtWindow (drawArea);

clearViewport ();
XSetFunction (d, gc, GXcopy);
XSetForeground (d, gc, fg);

XtAppMainLoop (appcon);    // X takes control from here
}

void settextstyle (int font, int dir, int size)
{
//direction ignored
    font = (font >= MAXFONT) ? (MAXFONT-1) : font;
    size = (size >= MAXSIZE) ? (MAXSIZE-1) : size;
    XSetFont (d, gc, fontID [size][font]->fid);
}

void setcolor (int col)
{
    col = (col >= MAXCOL) ? (MAXCOL-1) : col;
    XSetForeground (d, gc, colorIndex [col]);
}

void setbkcolor (int color)
{
    XSetBackground (d, gc, color);
}

void line (int left, int top, int right, int bottom)
{
    XDrawLine(d, win, gc, left, top, right, bottom);
    XFlush (d);
}

void putpixel (int x, int y, int col)
{
    Pixel    old_fg = fg;

    setcolor (col);
    XDrawPoint (d, win, gc, x, y);
    setcolor (old_fg);
    XFlush (d);
}

void rectangle (int left, int top, int right, int bottom)
{
    XDrawRectangle (d, win, gc, left, top, right-left+1, bottom-top+1);
    XFlush (d);
}

void arc (int x, int y, int stangle, int endangle, int radius)
{
    XDrawArc (d, win, gc, x, y, radius, radius,
                stangle*64, endangle*64);
    XFlush (d);
}


void bar (int left, int top, int right, int bottom)
{
    XFillRectangle (d, win, gc, left, top, right-left+1, bottom-top+1);
    XFlush (d);
}


void circle (int x, int y, int radius)
{
    XDrawArc (d, win, gc, x, y, radius, radius, 0, 360*64);
    XFlush (d);
}


void ellipse (int x, int y, int stangle, int endangle,int xradius, int yradius)
{
    XDrawArc (d, win, gc, x, y, xradius, yradius, 0, 360*64);
    XFlush (d);
}

int  getmaxcolor(void)
{
    return MAXCOL;
}

void outtextxy(int x, int y, charptr textstring)
{
    XDrawString (d, win, gc, x, y, textstring, strlen (textstring));
    XFlush (d);
}


/*
Include this file in your program to do write X-Window Graphics without
learning about X. The idea is to get you started quickly and not to
hide the details from you. Programming for a Window environment is different.
The program flow is controlled by the user. Your code should run in response
to the mouse & keyboard inputs by the user. 
This code does the following
1. Creates a Graphics Window using the X library function calls
2. Register a callback function named redraw (that calls the function
named 'mycode', written by you
3. provides some wrapper functions to draw on the window created.
Remember that the control is passed on to X, when you call makeWindow.
X runs your function 'mycode' in response to an expose event, ie. when
your window is displayed on top
*/

