/*************************************************************************************************************************************************************************************************
*
*	File		  : Main.cxx
*
*	Component	  : Main .
*
*	Module		  : Main .
*
*	Description	  : Main - entry - file for Linux . Demonstration of X Windows - X11 - function usage .
*					Please Note :- this is just a quickly thrown together file used to work out how to use the functions . As such coding standards have not been applied .
*
*   Copyright (C) : World Computers Ltd. ( U.K. ) . 2000 - 2010 . All rights reserved !
*					Proprietor :- Mr Kim Lyon .
*
*					This material is subject to the proprietary rights of World Computers Ltd.  ( U.K. ) . Usage of this
*					material is governed by the usage agreement and the associated usage license . The recipient of this
*					software implicitly accepts the terms of the usage agreement . In addition the recipient implicitly
*					accepts that commercial use of this material can only occur on grant of the usage license .
*
*					Documentation for the module and a copy of the usage agreement are available on the company web site
*					at :- http://www.wrldcomp.com .
*
*					Dates are in Day - Month - Year format with the year in 2 digit ( 2000 to 2099 ) format .
*
*	History		  : Date		By			Alteration \ Addition
*
*					01-01-10	Kim Lyon	Version baseline date . Version 0.00 . Created - 2000 - 2010 .
*
*************************************************************************************************************************************************************************************************/

/* ========================================================================================= INCLUDES ========================================================================================= */

#include <X11/Xlib.h>
/* /usr/lib/libX11.a
   /usr/lib/libxcb.a
   /usr/lib/libXau.a
   /usr/lib/libXdmcp.a
*/

#include <stdio.h>
#include <stdlib.h> // prevents error for exit on line 18 when compiling with gcc

/* System */
#include "System.hxx"

// Application
#include "Main.hxx"


/* ======================================================================================== FUNCTIONS ========================================================================================= */

/*

XFontStruct
-----------

typedef struct
{
	short lbearing;			    // origin to left edge of raster
	short rbearing;			    // origin to right edge of raster
	short width;			    // advance to next char's origin
	short ascent;		    	// baseline to top edge of raster
	short descent;	    		// baseline to bottom edge of raster
	unsigned short attributes;	// per char flags (not predefined)
} XCharStruct;

typedef struct
{
	Atom	name;
	unsigned long card32;
} XFontProp;

typedef struct
{	// normal 16 bit characters are two bytes
    unsigned char byte1;
    unsigned char byte2;
} XChar2b;

typedef struct
{
	XExtData *ext_data;		    // hook for extension to hang data
	Font fid;			        // Font id for this font
	unsigned direction;		    // hint about the direction font is painted
	unsigned min_char_or_byte2;	// first character
	unsigned max_char_or_byte2;	// last character
	unsigned min_byte1;		    // first row that exists
	unsigned max_byte1;		    // last row that exists
	Bool all_chars_exist;		// flag if all characters have nonzero size
	unsigned default_char;		// char to print for undefined character
	int n_properties;		    // how many properties there are
	XFontProp *properties;		// pointer to array of additional properties
	XCharStruct min_bounds;		// minimum bounds over all existing char
	XCharStruct max_bounds;		// maximum bounds over all existing char
	XCharStruct *per_char;		// first_char to last_char information
	int ascent;			        // logical extent above baseline for spacing
	int descent;			    // logical decent below baseline for spacing
} XFontStruct;

GC
--

Value Mask Bits
---------------
#define GCFunction		    (1L<<0)
#define GCPlaneMask		    (1L<<1)
#define GCForeground		(1L<<2)
#define GCBackground		(1L<<3)
#define GCLineWidth		    (1L<<4)
#define GCLineStyle		    (1L<<5)
#define GCCapStyle		    (1L<<6)
#define GCJoinStyle		    (1L<<7)
#define GCFillStyle		    (1L<<8)
#define GCFillRule		    (1L<<9)
#define GCTile			    (1L<<10)
#define GCStipple		    (1L<<11)
#define GCTileStipXOrigin	(1L<<12)
#define GCTileStipYOrigin	(1L<<13)
#define GCFont			    (1L<<14)
#define GCSubwindowMode		(1L<<15)
#define GCGraphicsExposures	(1L<<16)
#define GCClipXOrigin		(1L<<17)
#define GCClipYOrigin		(1L<<18)
#define GCClipMask		    (1L<<19)
#define GCDashOffset		(1L<<20)
#define GCDashList		    (1L<<21)
#define GCArcMode		    (1L<<22)

Values
------

typedef struct
{
	int function;			    // logical operation
	unsigned long plane_mask;	// plane mask
	unsigned long foreground;	// foreground pixel
	unsigned long background;	// background pixel
	int line_width;			    // line width (in pixels)
	int line_style;	    		// LineSolid, LineOnOffDash, LineDoubleDash
	int cap_style;		    	// CapNotLast, CapButt, CapRound, CapProjecting
	int join_style; 			// JoinMiter, JoinRound, JoinBevel
	int fill_style; 			// FillSolid, FillTiled, FillStippled FillOpaqueStippled
	int fill_rule;  			// EvenOddRule, WindingRule
	int arc_mode;   			// ArcChord, ArcPieSlice
	Pixmap tile;    			// tile pixmap for tiling operations
	Pixmap stipple;	    		// stipple 1 plane pixmap for stippling
	int ts_x_origin;	    	// offset for tile or stipple operations
	int ts_y_origin;
	Font font;	        		// default text font for text operations
	int subwindow_mode; 		// ClipByChildren, IncludeInferiors
	Bool graphics_exposures;	// boolean, should exposures be generated
	int clip_x_origin;	    	// origin for clipping
	int clip_y_origin;
	Pixmap clip_mask;   		// bitmap clipping; other calls for rects
	int dash_offset;	    	// patterned/dashed line information
	char dashes;
} XGCValues;

*/

int main( void )
{
    Display*     pstDisplay              = NULL ;
    int          iScreen ;
    Window       windowId ;
    GC           stGCDefault ;
    int          iNoOfCurrentFontPaths   = 0 ;
    char**       ptsaCurrentFontPathList = NULL ;
//    char*        ptsFontPath             = "/usr/share/fonts/truetype/msttcorefonts" ;
//    int          iNoOfFontPaths          = 1 ;
//    char**       ptsaFontPathList        = { &ptsFontPath } ;
    XEvent       stEvent ;
    XKeyEvent*   pstKeyEvent             = (XKeyEvent*)&stEvent ;
    KeySym       tKeyChar ;
    KeySym       tKeySymLC ;
    KeySym       tKeySymUC ;
    char         caMessage[ 200 ] ;
    int          iCursor_Y               = 0 ;
    int          iFont ;
    XFontStruct* pstFontArial ;
    XGCValues    stValuesFontArial ;
    GC           stGCFontArial ;
    XFontStruct* pstFontCourier ;
    XGCValues    stValuesFontCourier ;
    GC           stGCFontCourier ;
    XFontStruct* pstFontGaramond ;
    XGCValues    stValuesFontGaramond ;
    GC           stGCFontGaramond ;

    int          iNoOfNames ;
    int          iOffset ;
    int          iIndex ;
    int          iStep ;
    char**       ppcaFontNames ;
    BOOL         bExit              = FALSE ;

    memset( &stValuesFontArial    , 0 , sizeof( stValuesFontArial    ) );
    memset( &stValuesFontCourier  , 0 , sizeof( stValuesFontCourier  ) );
    memset( &stValuesFontGaramond , 0 , sizeof( stValuesFontGaramond ) );

    if( !pstDisplay )
    {
        // open connection with the server
        pstDisplay = XOpenDisplay( NULL ) ;

        if( pstDisplay )
        {
            // get the default screen id.
            iScreen = DefaultScreen( pstDisplay );
            // create the window
            windowId = XCreateSimpleWindow( pstDisplay , RootWindow( pstDisplay , iScreen ) , 10 , 10 , 800 , 640 , 3 , 0x000000 , 0xFFFFFF );
//          windowId = XCreateSimpleWindow( pstDisplay , RootWindow( pstDisplay , iScreen ) , 10 , 10 , 800 , 640 , 1 , frame 0x000000 , background 0xFFFFFF );
//          windowId = XCreateSimpleWindow( pstDisplay , RootWindow( pstDisplay , iScreen ) , 10 , 10 , 800 , 640 , 1 , BlackPixel( pstDisplay , iScreen ) , WhitePixel( pstDisplay , iScreen ) );
            XStoreName( pstDisplay , windowId , "GUI Front End Module" );

            // select the type of events to capture
            XSelectInput( pstDisplay , windowId , ExposureMask | KeyPressMask );

            // map - show - the window
            XMapWindow( pstDisplay , windowId );

            stGCDefault      = DefaultGC( pstDisplay , iScreen );
            stGCFontArial    = stGCDefault ;
            stGCFontCourier  = stGCDefault ;
            stGCFontGaramond = stGCDefault ;

            ptsaCurrentFontPathList = XGetFontPath( pstDisplay , &iNoOfCurrentFontPaths );
/*
            iNoOfFontPaths   = iNoOfCurrentFontPaths + 1 ;
            ptsaFontPathList = (char**)malloc( iNoOfFontPaths * sizeof( char* ) );

            for( iIndex = 0 ; iIndex < iNoOfCurrentFontPaths ; iIndex++ )
            {
                ptsaFontPathList[ iIndex ] = ptsaCurrentFontPathList[ iIndex ] ;
            }
            ptsaFontPathList[ iNoOfCurrentFontPaths ] = ptsFontPath ;

            XFreeFontPath( ptsaCurrentFontPathList );
            XSetFontPath( pstDisplay , ptsaCurrentFontPathList , iNoOfFontPaths - 1 );
*/
            // event loop
            while( !bExit )
            {
                while( XPending( pstDisplay ) )
                {
                    XNextEvent( pstDisplay , &stEvent );
                    // draw or redraw the window
                    if( stEvent.type == Expose )
                    {
                        XFillRectangle( pstDisplay , windowId , stGCDefault , 20 , 20 , 10 , 10 );
                        XDrawString( pstDisplay , windowId , stGCDefault , 40 , 100 , "abc" , 3 );
                        XDrawLine( pstDisplay , windowId , stGCDefault , 50 , 135 , 80 , 185 );
                        XDrawRectangle( pstDisplay , windowId , stGCDefault , 80 , 200 , 50 , 75 );
                        XSetForeground( pstDisplay , stGCDefault , 0xFF0000 );
                        XSetBackground( pstDisplay , stGCDefault , 0x00FF00 );

                        ppcaFontNames = XListFonts( pstDisplay , "*" , 400 , &iNoOfNames );

                        iFont = 20 ;
                        pstFontArial    = XLoadQueryFont( pstDisplay , ppcaFontNames[ iFont ] );

                        if( !pstFontArial )
                        {
                            XDrawString( pstDisplay , windowId , stGCDefault , 320 , 100 , "no arial" , 8 );
                        }
                        else
                        {
                            stGCFontArial = XCreateGC( pstDisplay , windowId , 0 , &stValuesFontArial );
                            XSetForeground( pstDisplay , stGCFontArial , 0x0000FF );
                            XSetFont( pstDisplay , stGCFontArial , pstFontArial->fid );
                            sprintf( caMessage , "%d : %s" , iFont , ppcaFontNames[ iFont ] );
                            XDrawString( pstDisplay , windowId , stGCFontArial , 250 , 100 , caMessage , strlen( caMessage ) );
                            XFreeFont( pstDisplay , pstFontArial );
                        }

                        iFont = 40 ;
                        pstFontCourier  = XLoadQueryFont( pstDisplay , ppcaFontNames[ iFont ] );

                        if( !pstFontCourier )
                        {
                            XDrawString( pstDisplay , windowId , stGCDefault , 320 , 125 , "no courier" , 10 );
                        }
                        else
                        {
                            stGCFontCourier = XCreateGC( pstDisplay , windowId , 0 , &stValuesFontCourier );
                            XSetForeground( pstDisplay , stGCFontCourier , 0x000F0F );
                            XSetFont( pstDisplay , stGCFontCourier , pstFontCourier->fid );
                            sprintf( caMessage , "%d : %s" , iFont , ppcaFontNames[ iFont ] );
                            XDrawString( pstDisplay , windowId , stGCFontCourier , 250 , 125 , caMessage , strlen( caMessage ) );
                            XFreeFont( pstDisplay , pstFontCourier );
                        }

                        iFont = 60 ;
                        pstFontGaramond = XLoadQueryFont( pstDisplay , ppcaFontNames[ iFont ] );

                        if( !pstFontGaramond )
                        {
                            XDrawString( pstDisplay , windowId , stGCDefault , 320 , 150 , "no garamond" , 11 );
                        }
                        else
                        {
                            stGCFontGaramond = XCreateGC( pstDisplay , windowId , 0 , &stValuesFontGaramond );
                            XSetForeground( pstDisplay , stGCFontGaramond , 0x00F00F );
                            XSetFont( pstDisplay , stGCFontGaramond , pstFontGaramond->fid );
                            sprintf( caMessage , "%d : %s" , iFont , ppcaFontNames[ iFont ] );
                            XDrawString( pstDisplay , windowId , stGCFontGaramond , 250 , 150 , caMessage , strlen( caMessage ) );
                            XFreeFont( pstDisplay , pstFontGaramond );
                        }

                        iCursor_Y = 175 ;
                        sprintf( caMessage , "Font Paths : %d" , iNoOfCurrentFontPaths );
                        XDrawString( pstDisplay , windowId , stGCDefault , 20 , iCursor_Y , caMessage , strlen( caMessage ) );
                        iCursor_Y += 25 ;
                        for( iIndex = 0 ; iIndex < iNoOfCurrentFontPaths ; iIndex += 1 , iCursor_Y += 20 )
                        {
                            XDrawString( pstDisplay , windowId , stGCDefault , 20 , iCursor_Y , ptsaCurrentFontPathList[ iIndex ] , strlen( ptsaCurrentFontPathList[ iIndex ] ) );
                        }

//                        ppcaFontNames = XListFonts( pstDisplay , "*" , 400 , &iNoOfNames );

                        if( ppcaFontNames )
                        {
                            sprintf( caMessage , "Font Names : %d" , iNoOfNames  );
                            XDrawString( pstDisplay , windowId , stGCDefault , 20 , iCursor_Y , caMessage , strlen( caMessage ) );
                            iCursor_Y += 25 ;
                            iStep      = iNoOfNames / 20 ;
                            iNoOfNames = 20 ;
                            iOffset    = 0 ;
                            iStep      = 1 ;
                            for( iIndex = 0 ; iIndex < iNoOfNames ; iIndex += iStep , iCursor_Y += 20 )
                            {
                                XDrawString( pstDisplay , windowId , stGCDefault , 20 , iCursor_Y , ppcaFontNames[ iOffset + iIndex ] , strlen( ppcaFontNames[ iOffset + iIndex ] ) );
                            }
                            XFreeFontNames( ppcaFontNames );
                        }

                        iCursor_Y = 50 ;

                    }// if( stEvent.type == Expose )

    //              sprintf( caMessage , "stEvent.type = %X " , stEvent.type );
    //              XDrawString( pstDisplay , windowId , stGCDefault , 10 , 50 + iCursor_Y , caMessage , strlen( caMessage ) );
    //              iCursor_Y += 20 ;
                    // exit on key press
                    if( stEvent.type == KeyPress )
                    {
                        tKeySymLC = XKeycodeToKeysym( pstDisplay , pstKeyEvent->keycode , 0 );
                        tKeySymUC = XKeycodeToKeysym( pstDisplay , pstKeyEvent->keycode , 1 );

                        if( !( pstKeyEvent->state & 0x02 ) )
                        {
                            if( !( pstKeyEvent->state & 0x01 ) )
                            {
                                tKeyChar = tKeySymLC ;
                            }
                            else
                            {
                                tKeyChar = tKeySymUC ;
                            }
                        }// if( !( pstKeyEvent->state & 0x02 ) )
                        else
                        {
                            if( !( pstKeyEvent->state & 0x01 ) )
                            {
                                tKeyChar = tKeySymUC ;
                            }
                            else
                            {
                                tKeyChar = tKeySymLC ;
                            }
                        }// else ( !( pstKeyEvent->state & 0x02 ) )

                        sprintf( caMessage , "pstKeyEvent->state = %4.4X , pstKeyEvent->keycode = %4.4X , tKeySym = %4.4X %4.4X , tKeyChar = %4.4X" , pstKeyEvent->state , pstKeyEvent->keycode , (int)tKeySymUC , (int)tKeySymLC , (int)tKeyChar );
                        XDrawString( pstDisplay , windowId , stGCDefault , 10 , 50 + iCursor_Y , caMessage , strlen( caMessage ) );
                        iCursor_Y += 20 ;

                        if( pstKeyEvent->keycode == 0x1B )
                        {
                            bExit = TRUE ;
                            break ;
                        }// if( pstKeyEvent->keycode == 0x1B )
                    }// if( stEvent.type == KeyPress )

                }// while( XPending( pstDisplay ) )

            }// while( TRUE )

//            XSetFontPath( pstDisplay , NULL , 0 );
            XFreeFontPath( ptsaCurrentFontPathList );
            XDestroyWindow( pstDisplay , windowId );
            XCloseDisplay( pstDisplay );

        }// if( pstDisplay )

    }// if( !pstDisplay )

    return 0 ;

}

