ref: cb58dbb4fbfa61c2b361daa05c48397dd8c7ead0
parent: 14954e6bc2186ae7ad03766006fcfe058b3b752d
author: David Turner <[email protected]>
date: Mon Jan 17 06:04:55 EST 2000
Some important changes were performed : - the graphics drivers were moved from "demos/config/*" to "demos/graph/*" - a Win32 graphics driver was added. (note that keyboard management is a bit buggy, but it's really usable). - the "demos/Makefile" and "demos/graph/rules.mk" were seriously modified - the demo programs now compile AND run with gcc, Visual C++ and LCC-Win32 !! The other ones should be really easy to add now, as LCC was the really smart ass in this list...
--- a/demos/graph/gpm_os2.def
+++ /dev/null
@@ -1,5 +1,0 @@
-NAME WINDOWCOMPAT
-
-DESCRIPTION 'FreeType Graphics'
-HEAPSIZE 8192
-STACKSIZE 40888
--- a/demos/graph/grdevice.c
+++ b/demos/graph/grdevice.c
@@ -1,6 +1,7 @@
#include "grobjs.h"
#include "grdevice.h"
#include <stdlib.h>
+#include <string.h>
grDeviceChain gr_device_chain[ GR_MAX_DEVICES ];
int gr_num_devices = 0;
--- a/demos/graph/grfont.c
+++ b/demos/graph/grfont.c
@@ -1,4 +1,5 @@
#include "grfont.h"
+#include <string.h>
/* font characters */
@@ -329,11 +330,14 @@
{
if (string)
{
+ grColor color;
+
+ color.value = 127;
grWriteCellString( gr_text_bitmap,
gr_margin_right + (gr_cursor_x << 3),
gr_margin_top + (gr_cursor_y << 3),
string,
- (grColor)127L );
+ color );
gr_cursor_x += strlen(string);
}
--- a/demos/graph/grinit.c
+++ b/demos/graph/grinit.c
@@ -13,6 +13,9 @@
#include "gros2pm.h"
#endif
+#ifdef DEVICE_WIN32
+#include "grwin32.h"
+#endif
/**********************************************************************
--- a/demos/graph/grobjs.c
+++ b/demos/graph/grobjs.c
@@ -1,6 +1,6 @@
#include "grobjs.h"
#include <stdlib.h>
-
+#include <memory.h>
int grError = 0;
--- a/demos/graph/gros2pm.c
+++ /dev/null
@@ -1,895 +1,0 @@
-#include "gros2pm.h"
-
-
-#define INCL_DOS
-#define INCL_WIN
-#define INCL_GPI
-#define INCL_SUB
-
-#include <os2.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
-
- static void Panic( const char* message )
- {
- fprintf( stderr, "%s", message );
- exit(1);
- }
-
- typedef struct Translator
- {
- ULONG os2key;
- grKey grkey;
-
- } Translator;
-
-
- static
- Translator key_translators[] =
- {
- { VK_BACKSPACE, grKeyBackSpace },
- { VK_TAB, grKeyTab },
- { VK_ENTER, grKeyReturn },
- { VK_ESC, grKeyEsc },
- { VK_HOME, grKeyHome },
- { VK_LEFT, grKeyLeft },
- { VK_UP, grKeyUp },
- { VK_RIGHT, grKeyRight },
- { VK_DOWN, grKeyDown },
- { VK_PAGEUP, grKeyPageUp },
- { VK_PAGEDOWN, grKeyPageDown },
- { VK_END, grKeyEnd },
- { VK_F1, grKeyF1 },
- { VK_F2, grKeyF2 },
- { VK_F3, grKeyF3 },
- { VK_F4, grKeyF4 },
- { VK_F5, grKeyF5 },
- { VK_F6, grKeyF6 },
- { VK_F7, grKeyF7 },
- { VK_F8, grKeyF8 },
- { VK_F9, grKeyF9 },
- { VK_F10, grKeyF10 },
- { VK_F11, grKeyF11 },
- { VK_F12, grKeyF12 }
- };
-
-
-#define MAX_PIXEL_MODES 32
-
- static int num_pixel_modes = 0;
- static grPixelMode pixel_modes[ MAX_PIXEL_MODES ];
- static int pixel_depth[ MAX_PIXEL_MODES ];
-
- static HAB gr_anchor; /* device anchor block */
-
- typedef POINTL PMBlitPoints[4];
-
-
- typedef struct grPMSurface_
- {
- grSurface root;
- grBitmap image;
-
- HAB anchor; /* handle to anchor block for surface's window */
- HWND frame_window; /* handle to window's frame */
- HWND client_window; /* handle to window's client */
- HWND title_window; /* handle to window's title bar */
-
- HPS image_ps; /* memory presentation space used to hold */
- /* the surface's content under PM */
- HDC image_dc; /* memory device context for the image */
-
- HEV event_lock; /* semaphore used in listen_surface */
- HMTX image_lock; /* a mutex used to synchronise access */
- /* to the memory presentation space */
- /* used to hold the surface */
-
- TID message_thread; /* thread used to process this surface's */
- /* messages.. */
-
- PBITMAPINFO2 bitmap_header;/* os/2 bitmap descriptor */
- HBITMAP os2_bitmap; /* Handle to OS/2 bitmap contained in image */
- BOOL ready; /* ??? */
-
- long shades[256]; /* indices of gray levels in pixel_mode_gray */
-
- POINTL surface_blit[4]; /* surface blitting table */
- POINTL magnify_blit[4]; /* magnifier blitting table */
- int magnification; /* level of magnification */
- POINTL magnify_center;
- SIZEL magnify_size;
-
- grEvent event;
-
- PMBlitPoints blit_points;
-
- } grPMSurface;
-
-
-
- static
- void enable_os2_iostreams( void )
- {
- PTIB thread_block;
- PPIB process_block;
-
- /* XXX : This is a very nasty hack, it fools OS/2 and let the program */
- /* call PM functions, even though stdin/stdout/stderr are still */
- /* directed to the standard i/o streams.. */
- /* The program must be compiled with WINDOWCOMPAT */
- /* */
- /* Credits go to Michal for finding this !! */
- /* */
- DosGetInfoBlocks( &thread_block, &process_block );
- process_block->pib_ultype = 3;
- }
-
-
-
- static
- int init_device( void )
- {
- enable_os2_iostreams();
-
- /* create an anchor block. This will allow this thread (i.e. the */
- /* main one) to call Gpi functions.. */
- gr_anchor = WinInitialize(0);
- if (!gr_anchor)
- {
- /* could not initialise Presentation Manager */
- return -1;
- }
-
- return 0;
- }
-
-
-
- static
- void done_device( void )
- {
- /* Indicates that we do not use the Presentation Manager, this */
- /* will also release all associated resources.. */
- WinTerminate( gr_anchor );
- }
-
-
-
- /* close a given window */
- static
- void done_surface( grPMSurface* surface )
- {
- if ( surface->frame_window )
- WinDestroyWindow( surface->frame_window );
-
- WinReleasePS( surface->image_ps );
-
- grDoneBitmap( &surface->image );
- grDoneBitmap( &surface->root.bitmap );
- }
-
-
-
-
-
- static
- void add_pixel_mode( grPixelMode pixel_mode,
- int depth )
- {
- if ( num_pixel_modes >= MAX_PIXEL_MODES )
- Panic( "X11.Too many pixel modes\n" );
-
- pixel_modes[ num_pixel_modes ] = pixel_mode;
- pixel_depth[ num_pixel_modes ] = depth;
-
- num_pixel_modes++;
- }
-
-
-#define LOCK(x) DosRequestMutexSem( x, SEM_INDEFINITE_WAIT );
-#define UNLOCK(x) DosReleaseMutexSem( x )
-
-
- static
- const int pixel_mode_bit_count[] =
- {
- 0,
- 1,
- 4,
- 8, /* pal8 */
- 8, /* gray */
- 15,
- 16,
- 24,
- 32
- };
-
-
- /************************************************************************
- *
- * Technical note : how the OS/2 Presntation Manager driver works
- *
- * PM is, in my opinion, a bloated and over-engineered graphics
- * sub-system, even though it has lots of nice features. Here are
- * a few tidbits about it :
- *
- *
- * - under PM, a "bitmap" is a device-specific object whose bits are
- * not directly accessible to the client application. This means
- * that we must use a scheme like the following to display our
- * surfaces :
- *
- * - hold, for each surface, its own bitmap buffer where the
- * rest of MiGS writes directly.
- *
- * - create a PM bitmap object with the same dimensions (and
- * possibly format).
- *
- * - copy the content of each updated rectangle into the
- * PM bitmap with the function 'GpiSetBitmapBits'.
- *
- * - finally, "blit" the PM bitmap to the screen calling
- * 'GpiBlitBlt'
- *
- * - but there is more : you cannot directly blit a PM bitmap to the
- * screen with PM. The 'GpiBlitBlt' only works with presentation
- * spaces. This means that we also need to create, for each surface :
- *
- * - a memory presentation space, used to hold the PM bitmap
- * - a "memory device context" for the presentation space
- *
- * The blit is then performed from the memory presentation space
- * to the screen's presentation space..
- *
- *
- * - because each surface creates its own event-handling thread,
- * we must protect the surface's presentation space from concurrent
- * accesses (i.e. calls to 'GpiSetBitmapBits' when drawing to the
- * surface, and calls to 'GpiBlitBlt' when drawing it on the screen
- * are performed in two different threads).
- *
- * we use a simple mutex to do this.
- *
- *
- * - we also use a semaphore to perform a rendez-vous between the
- * main and event-handling threads (needed in "listen_event").
- *
- ************************************************************************/
-
- static
- void RunPMWindow( grPMSurface* surface );
-
-
-
-
-
-
-
-
-
-
-
-
- static
- void convert_gray_to_pal8( grPMSurface* surface,
- int x,
- int y,
- int w,
- int h )
- {
- grBitmap* target = &surface->image;
- grBitmap* source = &surface->root.bitmap;
- byte* write = (byte*)target->buffer + y*target->pitch + x;
- byte* read = (byte*)source->buffer + y*source->pitch + x;
- long* palette = surface->shades;
-
- while (h > 0)
- {
- byte* _write = write;
- byte* _read = read;
- byte* limit = _write + w;
-
- for ( ; _write < limit; _write++, _read++ )
- *_write = (byte) palette[ *_read ];
-
- write += target->pitch;
- read += source->pitch;
- h--;
- }
- }
-
-
- static
- void convert_gray_to_16( grPMSurface* surface,
- int x,
- int y,
- int w,
- int h )
- {
- grBitmap* target = &surface->image;
- grBitmap* source = &surface->root.bitmap;
- byte* write = (byte*)target->buffer + y*target->pitch + 2*x;
- byte* read = (byte*)source->buffer + y*source->pitch + x;
- long* palette = surface->shades;
-
- while (h > 0)
- {
- byte* _write = write;
- byte* _read = read;
- byte* limit = _write + 2*w;
-
- for ( ; _write < limit; _write += 2, _read++ )
- *(short*)_write = (short)palette[ *_read ];
-
- write += target->pitch;
- read += source->pitch;
- h--;
- }
- }
-
-
- static
- void convert_gray_to_24( grPMSurface* surface,
- int x,
- int y,
- int w,
- int h )
- {
- grBitmap* target = &surface->image;
- grBitmap* source = &surface->root.bitmap;
- byte* write = (byte*)target->buffer + y*target->pitch + 3*x;
- byte* read = (byte*)source->buffer + y*source->pitch + x;
-
- while (h > 0)
- {
- byte* _write = write;
- byte* _read = read;
- byte* limit = _write + 3*w;
-
- for ( ; _write < limit; _write += 3, _read++ )
- {
- byte color = *_read;
-
- _write[0] =
- _write[1] =
- _write[2] = color;
- }
-
- write += target->pitch;
- read += source->pitch;
- h--;
- }
- }
-
-
- static
- void convert_gray_to_32( grPMSurface* surface,
- int x,
- int y,
- int w,
- int h )
- {
- grBitmap* target = &surface->image;
- grBitmap* source = &surface->root.bitmap;
- byte* write = (byte*)target->buffer + y*target->pitch + 4*x;
- byte* read = (byte*)source->buffer + y*source->pitch + x;
-
- while (h > 0)
- {
- byte* _write = write;
- byte* _read = read;
- byte* limit = _write + 4*w;
-
- for ( ; _write < limit; _write += 4, _read++ )
- {
- byte color = *_read;
-
- _write[0] =
- _write[1] =
- _write[2] =
- _write[3] = color;
- }
-
- write += target->pitch;
- read += source->pitch;
- h--;
- }
- }
-
-
- static
- void convert_rectangle( grPMSurface* surface,
- int x,
- int y,
- int w,
- int h )
- {
- int z;
-
- /* first of all, clip to the surface's area */
- if ( x >= surface->image.width ||
- x+w <= 0 ||
- y >= surface->image.rows ||
- y+h <= 0 )
- return;
-
- if ( x < 0 )
- {
- w += x;
- x = 0;
- }
-
- z = (x + w) - surface->image.width;
- if (z > 0)
- w -= z;
-
- z = (y + h) - surface->image.rows;
- if (z > 0)
- h -= z;
-
- /* convert the rectangle to the target depth for gray surfaces */
- if (surface->root.bitmap.mode == gr_pixel_mode_gray)
- {
- switch (surface->image.mode)
- {
- case gr_pixel_mode_pal8 :
- convert_gray_to_pal8( surface, x, y, w, h );
- break;
-
- case gr_pixel_mode_rgb555:
- case gr_pixel_mode_rgb565:
- convert_gray_to_16 ( surface, x, y, w, h );
- break;
-
- case gr_pixel_mode_rgb24:
- convert_gray_to_24 ( surface, x, y, w, h );
- break;
-
- case gr_pixel_mode_rgb32:
- convert_gray_to_32 ( surface, x, y, w, h );
- break;
-
- default:
- ;
- }
- }
- }
-
-
- static
- void refresh_rectangle( grPMSurface* surface,
- int x,
- int y,
- int w,
- int h )
- {
- convert_rectangle( surface, x, y, w, h );
-
- WinInvalidateRect( surface->client_window, NULL, FALSE );
- WinUpdateWindow( surface->frame_window );
- }
-
-
- static
- void set_title( grPMSurface* surface,
- const char* title )
- {
- WinSetWindowText( surface->title_window, (PSZ)title );
- }
-
-
-
- static
- void listen_event( grPMSurface* surface,
- int event_mask,
- grEvent* grevent )
- {
- ULONG ulRequestCount;
-
- (void) event_mask; /* ignored for now */
-
- /* the listen_event function blocks until there is an event to process */
- DosWaitEventSem( surface->event_lock, SEM_INDEFINITE_WAIT );
- DosQueryEventSem( surface->event_lock, &ulRequestCount );
- *grevent = surface->event;
- DosResetEventSem( surface->event_lock, &ulRequestCount );
-
- return;
- }
-
-
- static
- int init_surface( grPMSurface* surface,
- grBitmap* bitmap )
- {
- PBITMAPINFO2 bit;
- SIZEL sizl = { 0, 0 };
- LONG palette[256];
-
- /* create the bitmap - under OS/2, we support all modes as PM */
- /* handles all conversions automatically.. */
- if ( grNewBitmap( surface->root.bitmap.mode,
- surface->root.bitmap.grays,
- surface->root.bitmap.width,
- surface->root.bitmap.rows,
- bitmap ) )
- return grError;
-
- surface->root.bitmap = *bitmap;
-
- /* create the image and event lock */
- DosCreateEventSem( NULL, &surface->event_lock, 0, TRUE );
- DosCreateMutexSem( NULL, &surface->image_lock, 0, FALSE );
-
- /* create the image's presentation space */
- surface->image_dc = DevOpenDC( gr_anchor,
- OD_MEMORY, (PSZ)"*", 0L, 0L, 0L );
-
- surface->image_ps = GpiCreatePS( gr_anchor,
- surface->image_dc,
- &sizl,
- PU_PELS | GPIT_MICRO |
- GPIA_ASSOC | GPIF_DEFAULT );
-
- GpiSetBackMix( surface->image_ps, BM_OVERPAINT );
-
- /* create the image's PM bitmap */
- bit = (PBITMAPINFO2)grAlloc( sizeof(BITMAPINFO2) + 256*sizeof(RGB2) );
- surface->bitmap_header = bit;
-
- bit->cbFix = sizeof( BITMAPINFOHEADER2 );
- bit->cx = surface->root.bitmap.width;
- bit->cy = surface->root.bitmap.rows;
- bit->cPlanes = 1;
-
- bit->argbColor[0].bBlue = 0;
- bit->argbColor[0].bGreen = 0;
- bit->argbColor[0].bRed = 0;
-
- bit->argbColor[1].bBlue = 255;
- bit->argbColor[1].bGreen = 255;
- bit->argbColor[1].bRed = 255;
-
- bit->cBitCount = pixel_mode_bit_count[ surface->root.bitmap.mode ];
-
- surface->os2_bitmap = GpiCreateBitmap( surface->image_ps,
- (PBITMAPINFOHEADER2)bit,
- 0L, NULL, NULL );
-
- GpiSetBitmap( surface->image_ps, surface->os2_bitmap );
-
- bit->cbFix = sizeof( BITMAPINFOHEADER2 );
- GpiQueryBitmapInfoHeader( surface->os2_bitmap,
- (PBITMAPINFOHEADER2)bit );
-
- /* for gr_pixel_mode_gray, create a gray-levels logical palette */
- if ( bitmap->mode == gr_pixel_mode_gray )
- {
- int x, count;
-
- count = bitmap->grays;
- for ( x = 0; x < count; x++ )
- palette[x] = (((count-x)*255)/count) * 0x010101;
-
- /* create logical color table */
- GpiCreateLogColorTable( surface->image_ps,
- (ULONG) LCOL_PURECOLOR,
- (LONG) LCOLF_CONSECRGB,
- (LONG) 0L,
- (LONG) count,
- (PLONG) palette );
-
- /* now, copy the color indexes to surface->shades */
- for ( x = 0; x < count; x++ )
- surface->shades[x] = GpiQueryColorIndex( surface->image_ps,
- 0, palette[x] );
- }
-
- /* set up the blit points array */
- surface->blit_points[1].x = surface->root.bitmap.width;
- surface->blit_points[1].y = surface->root.bitmap.rows;
- surface->blit_points[3] = surface->blit_points[1];
-
- /* Finally, create the event handling thread for the surface's window */
- DosCreateThread( &surface->message_thread,
- (PFNTHREAD) RunPMWindow,
- (ULONG) surface,
- 0UL,
- 32920 );
-
- surface->root.done = (grDoneSurfaceFunc) done_surface;
- surface->root.refresh_rect = (grRefreshRectFunc) refresh_rectangle;
- surface->root.set_title = (grSetTitleFunc) set_title;
- surface->root.listen_event = (grListenEventFunc) listen_event;
-
- convert_rectangle( surface, 0, 0, bitmap->width, bitmap->rows );
- return 0;
- }
-
-
-
- MRESULT EXPENTRY Message_Process( HWND handle,
- ULONG mess,
- MPARAM parm1,
- MPARAM parm2 );
-
-
- static
- void RunPMWindow( grPMSurface* surface )
- {
- unsigned char class_name[] = "DisplayClass";
- ULONG class_flags;
-
- static HMQ queue;
- QMSG message;
-
- /* create an anchor to allow this thread to use PM */
- surface->anchor = WinInitialize(0);
- if (!surface->anchor)
- {
- printf( "Error doing WinInitialize()\n" );
- return;
- }
-
- /* create a message queue */
- queue = WinCreateMsgQueue( surface->anchor, 0 );
- if (!queue)
- {
- printf( "Error doing >inCreateMsgQueue()\n" );
- return;
- }
-
- /* register the window class */
- if ( !WinRegisterClass( surface->anchor,
- (PSZ) class_name,
- (PFNWP) Message_Process,
- CS_SIZEREDRAW,
- 0 ) )
- {
- printf( "Error doing WinRegisterClass()\n" );
- return;
- }
-
- /* create the PM window */
- class_flags = FCF_TITLEBAR | FCF_MINBUTTON | FCF_DLGBORDER |
- FCF_TASKLIST | FCF_SYSMENU;
-
- surface->frame_window = WinCreateStdWindow(
- HWND_DESKTOP,
- WS_VISIBLE,
- &class_flags,
- (PSZ) class_name,
- (PSZ) "FreeType PM Graphics",
- WS_VISIBLE,
- 0, 0,
- &surface->client_window );
- if (!surface->frame_window)
- {
- printf( "Error doing WinCreateStdWindow()\n" );
- return;
- }
-
- /* find the title window handle */
- surface->title_window = WinWindowFromID( surface->frame_window,
- FID_TITLEBAR );
-
- /* set Window size and position */
- WinSetWindowPos( surface->frame_window,
- 0L,
- (SHORT) 60,
- (SHORT) WinQuerySysValue( HWND_DESKTOP, SV_CYSCREEN ) -
- surface->root.bitmap.rows + 100,
-
- (SHORT) WinQuerySysValue( HWND_DESKTOP, SV_CYDLGFRAME )*2 +
- surface->root.bitmap.width,
-
- (SHORT) WinQuerySysValue( HWND_DESKTOP, SV_CYTITLEBAR ) +
- WinQuerySysValue( HWND_DESKTOP, SV_CYDLGFRAME )*2 +
- surface->root.bitmap.rows,
-
- SWP_SIZE | SWP_MOVE );
-
- /* save the handle to the current surface within the window words */
- WinSetWindowPtr( surface->frame_window,QWL_USER, surface );
-
- /* run the message queue till the end */
- while ( WinGetMsg( surface->anchor, &message, (HWND)NULL, 0, 0 ) )
- WinDispatchMsg( surface->anchor, &message );
-
- /* clean-up */
- WinDestroyWindow( surface->frame_window );
- surface->frame_window = 0;
-
- WinDestroyMsgQueue( queue );
- WinTerminate( surface->anchor );
-
- /* await death... */
- while ( 1 )
- DosSleep( 100 );
- }
-
-
-
-
- /* Message processing for our PM Window class */
- MRESULT EXPENTRY Message_Process( HWND handle,
- ULONG mess,
- MPARAM parm1,
- MPARAM parm2 )
- {
- static HDC screen_dc;
- static HPS screen_ps;
- static BOOL minimized;
-
- SIZEL sizl;
- SWP swp;
-
- grPMSurface* surface;
-
- /* get the handle to the window's surface */
- surface = (grPMSurface*)WinQueryWindowPtr( handle, QWL_USER );
-
- switch( mess )
- {
- case WM_DESTROY:
- /* warn the main thread to quit if it didn't know */
- surface->event.type = gr_event_key;
- surface->event.key = grKeyEsc;
- DosPostEventSem( surface->event_lock );
- break;
-
- case WM_CREATE:
- /* set original magnification */
- minimized = FALSE;
-
- /* create Device Context and Presentation Space for screen. */
- screen_dc = WinOpenWindowDC( handle );
- screen_ps = GpiCreatePS( surface->anchor,
- screen_dc,
- &sizl,
- PU_PELS | GPIT_MICRO |
- GPIA_ASSOC | GPIF_DEFAULT );
-
- /* take the input focus */
- WinFocusChange( HWND_DESKTOP, handle, 0L );
- break;
-
- case WM_MINMAXFRAME:
- /* to update minimized if changed */
- swp = *((PSWP) parm1);
- if ( swp.fl & SWP_MINIMIZE )
- minimized = TRUE;
- if ( swp.fl & SWP_RESTORE )
- minimized = FALSE;
- return WinDefWindowProc( handle, mess, parm1, parm2 );
- break;
-
- case WM_ERASEBACKGROUND:
- case WM_PAINT:
- /* copy the memory image of the screen out to the real screen */
- DosRequestMutexSem( surface->image_lock, SEM_INDEFINITE_WAIT );
- WinBeginPaint( handle, screen_ps, NULL );
-
- /* main image and magnified picture */
- GpiBitBlt( screen_ps,
- surface->image_ps,
- 4L,
- surface->blit_points,
- ROP_SRCCOPY, BBO_AND );
-
- WinEndPaint( screen_ps );
- DosReleaseMutexSem( surface->image_lock );
- break;
-
- case WM_CHAR:
- if ( CHARMSG( &mess )->fs & KC_KEYUP )
- break;
-
- /* look for a specific vkey */
- {
- int count = sizeof( key_translators )/sizeof( key_translators[0] );
- Translator* trans = key_translators;
- Translator* limit = trans + count;
-
- for ( ; trans < limit; trans++ )
- if ( CHARMSG(&mess)->vkey == trans->os2key )
- {
- surface->event.key = trans->grkey;
- goto Do_Key_Event;
- }
- }
-
- /* otherwise, simply record the character code */
- if ( (CHARMSG( &mess )->fs & KC_CHAR) == 0 )
- break;
-
- surface->event.key = CHARMSG(&mess)->chr;
-
- Do_Key_Event:
- surface->event.type = gr_event_key;
- DosPostEventSem( surface->event_lock );
- break;
-
- default:
- return WinDefWindowProc( handle, mess, parm1, parm2 );
- }
-
- return (MRESULT) FALSE;
- }
-
-
-
-
-
-
-
-#if 0
- static
- grKey KeySymTogrKey( key )
- {
- grKey k;
- int count = sizeof(key_translators)/sizeof(key_translators[0]);
- Translator* trans = key_translators;
- Translator* limit = trans + count;
-
- k = grKeyNone;
-
- while ( trans < limit )
- {
- if ( trans->xkey == key )
- {
- k = trans->grkey;
- break;
- }
- trans++;
- }
-
- return k;
- }
-
-
-
- static
- void listen_event( grPMSurface* surface,
- int event_mask,
- grEvent* grevent )
- {
- grKey grkey;
-
- /* XXXX : For now, ignore the event mask, and only exit when */
- /* a key is pressed.. */
- (void)event_mask;
-
-
- /* Now, translate the keypress to a grKey */
- /* If this wasn't part of the simple translated keys, simply get the charcode */
- /* from the character buffer */
- grkey = grKEY(key_buffer[key_cursor++]);
-
- Set_Key:
- grevent->type = gr_key_down;
- grevent->key = grkey;
- }
-
-#endif
-
-
-
- grDevice gr_os2pm_device =
- {
- sizeof( grPMSurface ),
- "os2pm",
-
- init_device,
- done_device,
-
- (grDeviceInitSurfaceFunc) init_surface,
-
- 0,
- 0
-
- };
-
-
--- a/demos/graph/gros2pm.h
+++ /dev/null
@@ -1,23 +1,0 @@
-#ifndef GROS2PM_H
-#define GROS2PM_H
-
-#include "grobjs.h"
-
- extern
- grDevice gr_os2pm_device;
-
-#ifdef GR_INIT_BUILD
- static
- grDeviceChain gr_os2pm_device_chain =
- {
- "os2pm",
- &gr_os2pm_device,
- GR_INIT_DEVICE_CHAIN
- };
-
-#undef GR_INIT_DEVICE_CHAIN
-#define GR_INIT_DEVICE_CHAIN &gr_os2pm_device_chain
-
-#endif /* GR_INIT_BUILD */
-
-#endif /* GROS2PM_H */
--- a/demos/graph/grx11.c
+++ /dev/null
@@ -1,936 +1,0 @@
-#include "grx11.h"
-
-
-#ifdef TEST
-#include "grfont.h"
-#endif
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-#include <X11/cursorfont.h>
-#include <X11/keysym.h>
-
- static void Panic( const char* message )
- {
- fprintf( stderr, "%s", message );
- exit(1);
- }
-
- typedef struct Translator
- {
- KeySym xkey;
- grKey grkey;
-
- } Translator;
-
- static
- Translator key_translators[] =
- {
- { XK_BackSpace, grKeyBackSpace },
- { XK_Tab, grKeyTab },
- { XK_Return, grKeyReturn },
- { XK_Escape, grKeyEsc },
- { XK_Home, grKeyHome },
- { XK_Left, grKeyLeft },
- { XK_Up, grKeyUp },
- { XK_Right, grKeyRight },
- { XK_Down, grKeyDown },
- { XK_Page_Up, grKeyPageUp },
- { XK_Page_Down, grKeyPageDown },
- { XK_End, grKeyEnd },
- { XK_Begin, grKeyHome },
- { XK_F1, grKeyF1 },
- { XK_F2, grKeyF2 },
- { XK_F3, grKeyF3 },
- { XK_F4, grKeyF4 },
- { XK_F5, grKeyF5 },
- { XK_F6, grKeyF6 },
- { XK_F7, grKeyF7 },
- { XK_F8, grKeyF8 },
- { XK_F9, grKeyF9 },
- { XK_F10, grKeyF10 },
- { XK_F11, grKeyF11 },
- { XK_F12, grKeyF12 }
- };
-
-
-#ifdef TEST
-
-#define grAlloc malloc
-
-#endif
-
-
- static Display* display;
- static char* displayname = "";
-
- static Cursor idle;
- static Cursor busy;
-
-#define MAX_PIXEL_MODES 32
-
- typedef XPixmapFormatValues XDepth;
-
- static int num_pixel_modes = 0;
- static grPixelMode pixel_modes[ MAX_PIXEL_MODES ];
- static XDepth pixel_depth[ MAX_PIXEL_MODES ];
-
- typedef struct grXSurface_
- {
- grSurface root;
- grBitmap image;
-
- Window win;
- Visual* visual;
- Colormap colormap;
- int depth;
- Bool gray;
-
- GC gc;
-
- XColor color[256]; /* gray levels palette for 8-bit modes */
- XImage* ximage;
-
- int win_org_x;
- int win_org_y;
- int win_width;
- int win_height;
-
- int image_width;
- int image_height;
-
- } grXSurface;
-
-
-
-
- /* close a given window */
- static
- void done_surface( grXSurface* surface )
- {
- XUnmapWindow( display, surface->win );
- }
-
-
-
- /* close the device, i.e. the display connection */
- static
- void done_device( void )
- {
- XCloseDisplay( display );
- }
-
-
-
- static
- void add_pixel_mode( grPixelMode pixel_mode,
- XDepth* depth )
- {
- if ( num_pixel_modes >= MAX_PIXEL_MODES )
- Panic( "X11.Too many pixel modes\n" );
-
- pixel_modes[ num_pixel_modes ] = pixel_mode;
- pixel_depth[ num_pixel_modes ] = *depth;
-
- num_pixel_modes++;
- }
-
-
-
- static
- int init_device( void )
- {
- XDepth dummy;
-
- XrmInitialize();
-
- display = XOpenDisplay( displayname );
- if (!display)
- {
- return -1;
- /* Panic( "Gr:error: cannot open X11 display\n" ); */
- }
-
- idle = XCreateFontCursor( display, XC_left_ptr );
- busy = XCreateFontCursor( display, XC_watch );
-
- num_pixel_modes = 0;
-
- /* always enable the 8-bit gray levels pixel mode */
- /* even if its display is emulated through a constrained palette */
- /* or another color mode */
- dummy.depth = 8;
- dummy.bits_per_pixel = 8;
- dummy.scanline_pad = 8;
- add_pixel_mode( gr_pixel_mode_gray, &dummy );
-
- {
- int count;
- XDepth* format;
- XDepth* formats;
- XVisualInfo template;
-
- formats = XListPixmapFormats( display, &count );
- format = formats;
-
-#ifdef TEST
- printf( "available pixmap formats\n" );
- printf( "depth pixbits scanpad\n" );
-#endif
-
- while ( count-- > 0 )
- {
-#ifdef TEST
- printf( " %3d %3d %3d\n",
- format->depth,
- format->bits_per_pixel,
- format->scanline_pad );
-#endif
-
- if ( format->depth == 1 )
- /* usually, this should be the first format */
- add_pixel_mode( gr_pixel_mode_mono, format );
-
- else if ( format->depth == 8 )
- add_pixel_mode( gr_pixel_mode_pal8, format );
-
- /* note, the 32-bit modes return a depth of 24, and 32 bits per pixel */
- else if ( format->depth == 24 )
- {
- if ( format->bits_per_pixel == 24 )
- add_pixel_mode( gr_pixel_mode_rgb24, format );
-
- else if ( format->bits_per_pixel == 32 )
- add_pixel_mode( gr_pixel_mode_rgb32, format );
- }
-
- else if ( format->depth == 16 )
- {
- int count2;
- XVisualInfo* visuals;
- XVisualInfo* visual;
-
- template.depth = format->depth;
- visuals = XGetVisualInfo( display,
- VisualDepthMask,
- &template,
- &count2 );
- visual = visuals;
-
- while ( count2-- > 0 )
- {
-#ifdef TEST
- const char* string = "unknown";
-
- switch (visual->class)
- {
- case TrueColor: string = "TrueColor"; break;
- case DirectColor: string = "DirectColor"; break;
- case PseudoColor: string = "PseudoColor"; break;
- case StaticGray : string = "StaticGray"; break;
- case StaticColor: string = "StaticColor"; break;
- case GrayScale: string = "GrayScale"; break;
- }
-
- printf( "> RGB %02x:%02x:%02x, colors %3d, bits %2d %s\n",
- visual->red_mask,
- visual->green_mask,
- visual->blue_mask,
- visual->colormap_size,
- visual->bits_per_rgb,
- string );
-#endif
- if ( visual->red_mask == 0xf800 &&
- visual->green_mask == 0x07e0 &&
- visual->blue_mask == 0x001f )
- add_pixel_mode( gr_pixel_mode_rgb565, format );
-
- else if ( visual->red_mask == 0x7c00 &&
- visual->green_mask == 0x03e0 &&
- visual->blue_mask == 0x001f )
- add_pixel_mode( gr_pixel_mode_rgb555, format );
-
- /* other 16-bit modes are ignored */
- visual++;
- }
-
- XFree( visuals );
- }
-
- format++;
- }
-
- XFree( formats );
- }
-
- gr_x11_device.num_pixel_modes = num_pixel_modes;
- gr_x11_device.pixel_modes = pixel_modes;
-
- return 0;
- }
-
-
-
-
-
-
-
-
-
-
-
-
- static
- void convert_gray_to_pal8( grXSurface* surface,
- int x,
- int y,
- int w,
- int h )
- {
- grBitmap* target = &surface->image;
- grBitmap* source = &surface->root.bitmap;
- byte* write = (byte*)target->buffer + y*target->pitch + x;
- byte* read = (byte*)source->buffer + y*source->pitch + x;
- XColor* palette = surface->color;
-
- while (h > 0)
- {
- byte* _write = write;
- byte* _read = read;
- byte* limit = _write + w;
-
- for ( ; _write < limit; _write++, _read++ )
- *_write = (byte) palette[ *_read ].pixel;
-
- write += target->pitch;
- read += source->pitch;
- h--;
- }
- }
-
-
- static
- void convert_gray_to_16( grXSurface* surface,
- int x,
- int y,
- int w,
- int h )
- {
- grBitmap* target = &surface->image;
- grBitmap* source = &surface->root.bitmap;
- byte* write = (byte*)target->buffer + y*target->pitch + 2*x;
- byte* read = (byte*)source->buffer + y*source->pitch + x;
- XColor* palette = surface->color;
-
- while (h > 0)
- {
- byte* _write = write;
- byte* _read = read;
- byte* limit = _write + 2*w;
-
- for ( ; _write < limit; _write += 2, _read++ )
- *(short*)_write = (short)palette[ *_read ].pixel;
-
- write += target->pitch;
- read += source->pitch;
- h--;
- }
- }
-
-
- static
- void convert_gray_to_24( grXSurface* surface,
- int x,
- int y,
- int w,
- int h )
- {
- grBitmap* target = &surface->image;
- grBitmap* source = &surface->root.bitmap;
- byte* write = (byte*)target->buffer + y*target->pitch + 3*x;
- byte* read = (byte*)source->buffer + y*source->pitch + x;
-
- while (h > 0)
- {
- byte* _write = write;
- byte* _read = read;
- byte* limit = _write + 3*w;
-
- for ( ; _write < limit; _write += 3, _read++ )
- {
- byte color = *_read;
-
- _write[0] =
- _write[1] =
- _write[2] = color;
- }
-
- write += target->pitch;
- read += source->pitch;
- h--;
- }
- }
-
-
- static
- void convert_gray_to_32( grXSurface* surface,
- int x,
- int y,
- int w,
- int h )
- {
- grBitmap* target = &surface->image;
- grBitmap* source = &surface->root.bitmap;
- byte* write = (byte*)target->buffer + y*target->pitch + 4*x;
- byte* read = (byte*)source->buffer + y*source->pitch + x;
-
- while (h > 0)
- {
- byte* _write = write;
- byte* _read = read;
- byte* limit = _write + 4*w;
-
- for ( ; _write < limit; _write += 4, _read++ )
- {
- byte color = *_read;
-
- _write[0] =
- _write[1] =
- _write[2] =
- _write[3] = color;
- }
-
- write += target->pitch;
- read += source->pitch;
- h--;
- }
- }
-
-
- static
- void convert_rectangle( grXSurface* surface,
- int x,
- int y,
- int w,
- int h )
- {
- int z;
-
- /* first of all, clip to the surface's area */
- if ( x >= surface->image.width ||
- x+w <= 0 ||
- y >= surface->image.rows ||
- y+h <= 0 )
- return;
-
- if ( x < 0 )
- {
- w += x;
- x = 0;
- }
-
- z = (x + w) - surface->image.width;
- if (z > 0)
- w -= z;
-
- z = (y + h) - surface->image.rows;
- if (z > 0)
- h -= z;
-
- /* convert the rectangle to the target depth for gray surfaces */
- if (surface->gray)
- {
- switch (surface->depth)
- {
- case 8 : convert_gray_to_pal8( surface, x, y, w, h ); break;
- case 16: convert_gray_to_16 ( surface, x, y, w, h ); break;
- case 24: convert_gray_to_24 ( surface, x, y, w, h ); break;
- case 32: convert_gray_to_32 ( surface, x, y, w, h ); break;
- }
- }
- }
-
-
- static
- void refresh_rectangle( grXSurface* surface,
- int x,
- int y,
- int w,
- int h )
- {
- if (surface->gray)
- convert_rectangle( surface, x, y, w, h );
-
- XPutImage( display,
- surface->win,
- surface->gc,
- surface->ximage,
- x, y, x, y, w, h );
- }
-
-
- static
- void set_title( grXSurface* surface,
- const char* title )
- {
- XStoreName( display, surface->win, title );
- }
-
-
-
- static
- grKey KeySymTogrKey( KeySym key )
- {
- grKey k;
- int count = sizeof(key_translators)/sizeof(key_translators[0]);
- Translator* trans = key_translators;
- Translator* limit = trans + count;
-
- k = grKeyNone;
-
- while ( trans < limit )
- {
- if ( trans->xkey == key )
- {
- k = trans->grkey;
- break;
- }
- trans++;
- }
-
- return k;
- }
-
-
-
- static
- void listen_event( grXSurface* surface,
- int event_mask,
- grEvent* grevent )
- {
- static char key_buffer[10];
- static int key_cursor = 0;
- static int key_number = 0;
- static XEvent x_event;
- KeySym key;
-
- int bool_exit;
- grKey grkey;
-
- XComposeStatus compose;
-
- /* XXXX : For now, ignore the event mask, and only exit when */
- /* a key is pressed.. */
- (void)event_mask;
-
- bool_exit = key_cursor < key_number;
-
- XDefineCursor( display, surface->win, idle );
-
- while ( !bool_exit )
- {
- XNextEvent( display, &x_event );
-
- switch ( x_event.type )
- {
- case KeyPress:
- key_number = XLookupString( &x_event.xkey,
- key_buffer,
- sizeof ( key_buffer ),
- &key,
- &compose );
- key_cursor = 0;
-
- if ( key_number == 0 ||
- key > 512 )
- {
- /* this may be a special key like F1, F2, etc.. */
- grkey = KeySymTogrKey(key);
- if (grkey != grKeyNone)
- goto Set_Key;
- }
- else
- bool_exit = 1;
- break;
-
- case MappingNotify:
- XRefreshKeyboardMapping( &x_event.xmapping );
- break;
-
- case Expose:
- refresh_rectangle( surface,
- x_event.xexpose.x,
- x_event.xexpose.y,
- x_event.xexpose.width,
- x_event.xexpose.height );
- break;
-
- /* You should add more cases to handle mouse events, etc. */
- }
- }
-
- XDefineCursor( display, surface->win, busy );
- XFlush ( display );
-
- /* Now, translate the keypress to a grKey */
- /* If this wasn't part of the simple translated keys, simply get the charcode */
- /* from the character buffer */
- grkey = grKEY(key_buffer[key_cursor++]);
-
- Set_Key:
- grevent->type = gr_key_down;
- grevent->key = grkey;
- }
-
-
-
-
- grXSurface* init_surface( grXSurface* surface,
- grBitmap* bitmap )
- {
- int screen;
- grBitmap* image;
- char grays;
- XDepth* format;
- int image_depth;
-
- screen = DefaultScreen( display );
-
- surface->colormap = DefaultColormap( display, screen );
- surface->depth = DefaultDepth( display, screen );
- surface->visual = DefaultVisual( display, screen );
-
- image = &surface->image;
-
- /* force the surface image depth to 1 if necessary */
- /* as this should be supported by all windows */
- image_depth = surface->depth;
- if (bitmap->mode == gr_pixel_mode_mono)
- image_depth = 1;
-
- grays = ( bitmap->mode == gr_pixel_mode_gray &&
- bitmap->grays >= 2 );
-
- surface->gray = grays;
-
- /* copy dimensions */
- image->width = bitmap->width;
- image->rows = bitmap->rows;
- image->mode = bitmap->mode;
- image->pitch = 0;
- image->grays = 0;
- image->buffer = 0;
-
- /* find the supported format corresponding to the request */
- format = 0;
-
- if (grays)
- {
- /* choose the default depth in case of grays rendering */
- int i;
- for ( i = 0; i < num_pixel_modes; i++ )
- if ( image_depth == pixel_depth[i].depth )
- {
- format = pixel_depth + i;
- break;
- }
- }
- else
- {
- /* otherwise, select the format depending on the pixel mode */
- int i;
-
- format = 0;
- for ( i = 0; i < num_pixel_modes; i++ )
- if ( pixel_modes[i] == bitmap->mode )
- {
- format = pixel_depth + i;
- break;
- }
- }
-
- if (!format)
- {
- grError = gr_err_bad_argument;
- return 0;
- }
-
-
- /* correct surface.depth. This is required because in the case */
- /* of 32-bits pixels, the value of "format.depth" is 24 under X11 */
- if ( format->depth == 24 &&
- format->bits_per_pixel == 32 )
- image_depth = 32;
-
- /* allocate surface image */
- {
- int bits, over;
-
- bits = image->width * format->bits_per_pixel;
- over = bits % format->scanline_pad;
-
- if (over)
- bits += format->scanline_pad - over;
-
- if (!grays)
- {
- image->width = bits;
- bitmap->width = bits;
- }
- image->pitch = bits >> 3;
- }
-
- image->buffer = grAlloc( image->pitch * image->rows );
- if (!image->buffer) return 0;
-
- /* now, allocate a gray pal8 pixmap, only when we asked */
- /* for an 8-bit pixmap */
- if ( grays )
- {
- /* pad pitch to 32 bits */
- bitmap->pitch = (bitmap->width + 3) & -4;
- bitmap->buffer = grAlloc( bitmap->pitch * bitmap->rows );
- if (!bitmap->buffer)
- Panic( "grX11: could not allocate surface bitmap!\n" );
- }
- else /* otherwise */
- {
- *bitmap = *image;
- }
-
- surface->root.bitmap = *bitmap;
-
- /* Now create the surface X11 image */
- surface->ximage = XCreateImage( display,
- surface->visual,
- format->depth,
- format->depth == 1 ? XYBitmap : ZPixmap,
- 0,
- (char*)image->buffer,
- image->width,
- image->rows,
- 8,
- 0 );
- if ( !surface->ximage )
- Panic( "grX11: cannot create surface X11 image\n" );
-
-
- /* allocate gray levels in the case of gray surface */
- if ( grays )
- {
- XColor* color = surface->color;
- int i;
-
- for ( i = 0; i < bitmap->grays; i++, color++ )
- {
- color->red =
- color->green =
- color->blue = 65535 - ( i * 65535 ) / bitmap->grays;
-
- if ( !XAllocColor( display, surface->colormap, color ) )
- Panic( "ERROR: cannot allocate Color\n" );
- }
- }
- else if ( image_depth == 1 )
- {
- surface->ximage->byte_order = MSBFirst;
- surface->ximage->bitmap_bit_order = MSBFirst;
- }
-
- {
- XTextProperty xtp;
- XSizeHints xsh;
- XSetWindowAttributes xswa;
-
- xswa.border_pixel = BlackPixel( display, screen );
- xswa.background_pixel = WhitePixel( display, screen );
- xswa.cursor = busy;
-
- xswa.event_mask = KeyPressMask | ExposureMask;
-
- surface->win = XCreateWindow( display,
- RootWindow( display, screen ),
- 0,
- 0,
- image->width,
- image->rows,
- 10,
- surface->depth,
- InputOutput,
- surface->visual,
- CWBackPixel | CWBorderPixel |
- CWEventMask | CWCursor,
- &xswa );
-
- XMapWindow( display, surface->win );
-
- surface->gc = XCreateGC( display, RootWindow( display, screen ), 0L, NULL );
- XSetForeground( display, surface->gc, xswa.border_pixel );
- XSetBackground( display, surface->gc, xswa.background_pixel );
-
-
- /* make window manager happy :-) */
- xtp.value = (unsigned char*)"FreeType";
- xtp.encoding = 31;
- xtp.format = 8;
- xtp.nitems = strlen( (char*)xtp.value );
-
- xsh.x = 0;
- xsh.y = 0;
-
- xsh.width = image->width;
- xsh.height = image->rows;
- xsh.flags = (PPosition | PSize);
- xsh.flags = 0;
-
- XSetWMProperties( display, surface->win, &xtp, &xtp, NULL, 0, &xsh, NULL, NULL );
- }
-
- surface->root.done = (grDoneSurfaceFunc) done_surface;
- surface->root.refresh_rect = (grRefreshRectFunc) refresh_rectangle;
- surface->root.set_title = (grSetTitleFunc) set_title;
- surface->root.listen_event = (grListenEventFunc) listen_event;
-
- convert_rectangle( surface, 0, 0, bitmap->width, bitmap->rows );
- return surface;
- }
-
-
-
-
- grDevice gr_x11_device =
- {
- sizeof( grXSurface ),
- "x11",
-
- init_device,
- done_device,
-
- (grDeviceInitSurfaceFunc) init_surface,
-
- 0,
- 0
-
- };
-
-#ifdef TEST
-
-typedef struct grKeyName
-{
- grKey key;
- const char* name;
-
-} grKeyName;
-
-
-static
-const grKeyName key_names[] =
-{
- { grKeyF1, "F1" },
- { grKeyF2, "F2" },
- { grKeyF3, "F3" },
- { grKeyF4, "F4" },
- { grKeyF5, "F5" },
- { grKeyF6, "F6" },
- { grKeyF7, "F7" },
- { grKeyF8, "F8" },
- { grKeyF9, "F9" },
- { grKeyF10, "F10" },
- { grKeyF11, "F11" },
- { grKeyF12, "F12" },
- { grKeyEsc, "Esc" },
- { grKeyHome, "Home" },
- { grKeyEnd, "End" },
-
- { grKeyPageUp, "Page_Up" },
- { grKeyPageDown, "Page_Down" },
- { grKeyLeft, "Left" },
- { grKeyRight, "Right" },
- { grKeyUp, "Up" },
- { grKeyDown, "Down" },
- { grKeyBackSpace, "BackSpace" },
- { grKeyReturn, "Return" }
-};
-
-int main( void )
-{
- grSurface* surface;
- int n;
-
- grInit();
- surface = grNewScreenSurface( 0, gr_pixel_mode_gray, 320, 400, 128 );
- if (!surface)
- Panic("Could not create window\n" );
- else
- {
- grColor color;
- grEvent event;
- const char* string;
- int x;
-
- grSetSurfaceRefresh( surface, 1 );
- grSetTitle(surface,"X11 driver demonstration" );
-
- for ( x = -10; x < 10; x++ )
- {
- for ( n = 0; n < 128; n++ )
- {
- color.value = (n*3) & 127;
- grWriteCellChar( surface,
- x + ((n % 60) << 3),
- 80 + (x+10)*8*3 + ((n/60) << 3), n, color );
- }
-
- }
- color.value = 64;
- grWriteCellString( surface, 0, 0, "just an example", color );
-
- do
- {
- listen_event((grXSurface*)surface, 0, &event);
-
- /* return if ESC was pressed */
- if ( event.key == grKeyEsc )
- return 0;
-
- /* otherwise, display key string */
- color.value = (color.value + 8) & 127;
- {
- int count = sizeof(key_names)/sizeof(key_names[0]);
- grKeyName* name = key_names;
- grKeyName* limit = name + count;
- const char* kname = 0;
- char kname_temp[16];
-
- while (name < limit)
- {
- if ( name->key == event.key )
- {
- kname = name->name;
- break;
- }
- name++;
- }
-
- if (!kname)
- {
- sprintf( kname_temp, "char '%c'", (char)event.key );
- kname = kname_temp;
- }
-
- grWriteCellString( surface, 30, 30, kname, color );
- grRefreshSurface(surface);
- paint_rectangle( surface, 0, 0, surface->bitmap.width, surface->bitmap.rows );
- }
- } while (1);
- }
-
- return 0;
-
-
-}
-#endif /* TEST */
-
--- a/demos/graph/grx11.h
+++ /dev/null
@@ -1,24 +1,0 @@
-#ifndef GRX11_H
-#define GRX11_H
-
-#include "grobjs.h"
-#include "grdevice.h"
-
- extern
- grDevice gr_x11_device;
-
-#ifdef GR_INIT_BUILD
- static
- grDeviceChain gr_x11_device_chain =
- {
- "x11",
- &gr_x11_device,
- GR_INIT_DEVICE_CHAIN
- };
-
-#undef GR_INIT_DEVICE_CHAIN
-#define GR_INIT_DEVICE_CHAIN &gr_x11_device_chain
-
-#endif /* GR_INIT_BUILD */
-
-#endif /* GRX11_H */
--- /dev/null
+++ b/demos/graph/os2/gros2pm.c
@@ -1,0 +1,754 @@
+#include "gros2pm.h"
+#include "grdevice.h"
+
+#define INCL_DOS
+#define INCL_WIN
+#define INCL_GPI
+#define INCL_SUB
+
+#include <os2.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+#define DEBUGxxx
+
+#ifdef DEBUG
+#define LOG(x) LogMessage##x
+#else
+#define LOG(x) /* rien */
+#endif
+
+#ifdef DEBUG
+ static void LogMessage( const char* fmt, ... )
+ {
+ va_list ap;
+
+ va_start( ap, fmt );
+ vfprintf( stderr, fmt, ap );
+ va_end( ap );
+ }
+#endif
+
+ typedef struct Translator
+ {
+ ULONG os2key;
+ grKey grkey;
+
+ } Translator;
+
+
+ static
+ Translator key_translators[] =
+ {
+ { VK_BACKSPACE, grKeyBackSpace },
+ { VK_TAB, grKeyTab },
+ { VK_ENTER, grKeyReturn },
+ { VK_ESC, grKeyEsc },
+ { VK_HOME, grKeyHome },
+ { VK_LEFT, grKeyLeft },
+ { VK_UP, grKeyUp },
+ { VK_RIGHT, grKeyRight },
+ { VK_DOWN, grKeyDown },
+ { VK_PAGEUP, grKeyPageUp },
+ { VK_PAGEDOWN, grKeyPageDown },
+ { VK_END, grKeyEnd },
+ { VK_F1, grKeyF1 },
+ { VK_F2, grKeyF2 },
+ { VK_F3, grKeyF3 },
+ { VK_F4, grKeyF4 },
+ { VK_F5, grKeyF5 },
+ { VK_F6, grKeyF6 },
+ { VK_F7, grKeyF7 },
+ { VK_F8, grKeyF8 },
+ { VK_F9, grKeyF9 },
+ { VK_F10, grKeyF10 },
+ { VK_F11, grKeyF11 },
+ { VK_F12, grKeyF12 }
+ };
+
+
+#define MAX_PIXEL_MODES 32
+
+ static HAB gr_anchor; /* device anchor block */
+
+ typedef POINTL PMBlitPoints[4];
+
+ typedef struct grPMSurface_
+ {
+ grSurface root;
+ grBitmap image;
+
+ HAB anchor; /* handle to anchor block for surface's window */
+ HWND frame_window; /* handle to window's frame */
+ HWND client_window; /* handle to window's client */
+ HWND title_window; /* handle to window's title bar */
+
+ HPS image_ps; /* memory presentation space used to hold */
+ /* the surface's content under PM */
+ HDC image_dc; /* memory device context for the image */
+
+ HEV event_lock; /* semaphore used in listen_surface */
+ HMTX image_lock; /* a mutex used to synchronise access */
+ /* to the memory presentation space */
+ /* used to hold the surface */
+
+ TID message_thread; /* thread used to process this surface's */
+ /* messages.. */
+
+ PBITMAPINFO2 bitmap_header;/* os/2 bitmap descriptor */
+ HBITMAP os2_bitmap; /* Handle to OS/2 bitmap contained in image */
+ BOOL ready; /* ??? */
+
+ long shades[256]; /* indices of gray levels in pixel_mode_gray */
+
+ POINTL surface_blit[4]; /* surface blitting table */
+ POINTL magnify_blit[4]; /* magnifier blitting table */
+ int magnification; /* level of magnification */
+ POINTL magnify_center;
+ SIZEL magnify_size;
+
+ grEvent event;
+
+ PMBlitPoints blit_points;
+
+ } grPMSurface;
+
+ /* we use a static variable to pass a pointer to the PM Surface */
+ /* to the client window. This is a bit ugly, but it makes things */
+ /* a lot more simple.. */
+ static grPMSurface* the_surface;
+
+ static int window_created = 0;
+
+
+ static
+ void enable_os2_iostreams( void )
+ {
+ PTIB thread_block;
+ PPIB process_block;
+
+ /* XXX : This is a very nasty hack, it fools OS/2 and let the program */
+ /* call PM functions, even though stdin/stdout/stderr are still */
+ /* directed to the standard i/o streams.. */
+ /* The program must be compiled with WINDOWCOMPAT */
+ /* */
+ /* Credits go to Michal for finding this !! */
+ /* */
+ DosGetInfoBlocks( &thread_block, &process_block );
+ process_block->pib_ultype = 3;
+ }
+
+
+
+ static
+ int init_device( void )
+ {
+ enable_os2_iostreams();
+
+ /* create an anchor block. This will allow this thread (i.e. the */
+ /* main one) to call Gpi functions.. */
+ gr_anchor = WinInitialize(0);
+ if (!gr_anchor)
+ {
+ /* could not initialise Presentation Manager */
+ return -1;
+ }
+
+ return 0;
+ }
+
+
+
+ static
+ void done_device( void )
+ {
+ /* Indicates that we do not use the Presentation Manager, this */
+ /* will also release all associated resources.. */
+ WinTerminate( gr_anchor );
+ }
+
+
+
+ /* close a given window */
+ static
+ void done_surface( grPMSurface* surface )
+ {
+ LOG(( "Os2PM: done_surface(%08lx)\n", (long)surface ));
+
+ if ( surface->frame_window )
+ WinDestroyWindow( surface->frame_window );
+
+ WinReleasePS( surface->image_ps );
+
+ grDoneBitmap( &surface->image );
+ grDoneBitmap( &surface->root.bitmap );
+ }
+
+
+
+
+
+#define LOCK(x) DosRequestMutexSem( x, SEM_INDEFINITE_WAIT );
+#define UNLOCK(x) DosReleaseMutexSem( x )
+
+
+ static
+ const int pixel_mode_bit_count[] =
+ {
+ 0,
+ 1, /* mono */
+ 4, /* pal4 */
+ 8, /* pal8 */
+ 8, /* grays */
+ 15, /* rgb15 */
+ 16, /* rgb16 */
+ 24, /* rgb24 */
+ 32 /* rgb32 */
+ };
+
+
+ /************************************************************************
+ *
+ * Technical note : how the OS/2 Presntation Manager driver works
+ *
+ * PM is, in my opinion, a bloated and over-engineered graphics
+ * sub-system, even though it has lots of nice features. Here are
+ * a few tidbits about it :
+ *
+ *
+ * - under PM, a "bitmap" is a device-specific object whose bits are
+ * not directly accessible to the client application. This means
+ * that we must use a scheme like the following to display our
+ * surfaces :
+ *
+ * - hold, for each surface, its own bitmap buffer where the
+ * rest of the graph library writes directly.
+ *
+ * - create a PM bitmap object with the same dimensions (and
+ * possibly format).
+ *
+ * - copy the content of each updated rectangle into the
+ * PM bitmap with the function 'GpiSetBitmapBits'.
+ *
+ * - finally, "blit" the PM bitmap to the screen calling
+ * 'GpiBlitBlt'
+ *
+ * - but there is more : you cannot directly blit a PM bitmap to the
+ * screen with PM. The 'GpiBlitBlt' only works with presentation
+ * spaces. This means that we also need to create, for each surface :
+ *
+ * - a memory presentation space, used to hold the PM bitmap
+ * - a "memory device context" for the presentation space
+ *
+ * The blit is then performed from the memory presentation space
+ * to the screen's presentation space..
+ *
+ *
+ * - because each surface creates its own event-handling thread,
+ * we must protect the surface's presentation space from concurrent
+ * accesses (i.e. calls to 'GpiSetBitmapBits' when drawing to the
+ * surface, and calls to 'GpiBlitBlt' when drawing it on the screen
+ * are performed in two different threads).
+ *
+ * we use a simple mutex to do this.
+ *
+ *
+ * - we also use a semaphore to perform a rendez-vous between the
+ * main and event-handling threads (needed in "listen_event").
+ *
+ ************************************************************************/
+
+ static
+ void RunPMWindow( grPMSurface* surface );
+
+
+
+
+ static
+ void refresh_rectangle( grPMSurface* surface,
+ int x,
+ int y,
+ int w,
+ int h )
+ {
+ LOG(( "Os2PM: refresh_rectangle( %08lx, %d, %d, %d, %d )\n",
+ (long)surface, x, y, w, h ));
+
+ (void)x;
+ (void)y;
+ (void)w;
+ (void)h;
+
+ /*
+ convert_rectangle( surface, x, y, w, h );
+ */
+ DosRequestMutexSem( surface->image_lock, SEM_INDEFINITE_WAIT );
+ GpiSetBitmapBits( surface->image_ps,
+ 0,
+ surface->root.bitmap.rows,
+ surface->root.bitmap.buffer,
+ surface->bitmap_header );
+ DosReleaseMutexSem( surface->image_lock );
+
+ WinInvalidateRect( surface->client_window, NULL, FALSE );
+ WinUpdateWindow( surface->frame_window );
+ }
+
+
+ static
+ void set_title( grPMSurface* surface,
+ const char* title )
+ {
+ ULONG rc;
+
+#if 1
+ LOG(( "Os2PM: set_title( %08lx == %08lx, %s )\n",
+ (long)surface, surface->client_window, title ));
+#endif
+ LOG(( " -- frame = %08lx\n",
+ (long)surface->frame_window ));
+
+ LOG(( " -- client parent = %08lx\n",
+ (long)WinQueryWindow( surface->client_window, QW_PARENT ) ));
+
+ rc = WinSetWindowText( surface->client_window, (PSZ)title );
+ LOG(( " -- returned rc = %ld\n",rc ));
+ }
+
+
+
+ static
+ void listen_event( grPMSurface* surface,
+ int event_mask,
+ grEvent* grevent )
+ {
+ ULONG ulRequestCount;
+
+ (void) event_mask; /* ignored for now */
+
+ /* the listen_event function blocks until there is an event to process */
+ DosWaitEventSem( surface->event_lock, SEM_INDEFINITE_WAIT );
+ DosQueryEventSem( surface->event_lock, &ulRequestCount );
+ *grevent = surface->event;
+ DosResetEventSem( surface->event_lock, &ulRequestCount );
+
+ return;
+ }
+
+
+ static
+ grPMSurface* init_surface( grPMSurface* surface,
+ grBitmap* bitmap )
+ {
+ PBITMAPINFO2 bit;
+ SIZEL sizl = { 0, 0 };
+ LONG palette[256];
+
+ LOG(( "Os2PM: init_surface( %08lx, %08lx )\n",
+ (long)surface, (long)bitmap ));
+
+ LOG(( " -- input bitmap =\n" ));
+ LOG(( " -- mode = %d\n", bitmap->mode ));
+ LOG(( " -- grays = %d\n", bitmap->grays ));
+ LOG(( " -- width = %d\n", bitmap->width ));
+ LOG(( " -- height = %d\n", bitmap->rows ));
+
+ /* create the bitmap - under OS/2, we support all modes as PM */
+ /* handles all conversions automatically.. */
+ if ( grNewBitmap( bitmap->mode,
+ bitmap->grays,
+ bitmap->width,
+ bitmap->rows,
+ bitmap ) )
+ return 0;
+
+ LOG(( " -- output bitmap =\n" ));
+ LOG(( " -- mode = %d\n", bitmap->mode ));
+ LOG(( " -- grays = %d\n", bitmap->grays ));
+ LOG(( " -- width = %d\n", bitmap->width ));
+ LOG(( " -- height = %d\n", bitmap->rows ));
+
+ bitmap->pitch = -bitmap->pitch;
+ surface->root.bitmap = *bitmap;
+
+ /* create the image and event lock */
+ DosCreateEventSem( NULL, &surface->event_lock, 0, TRUE );
+ DosCreateMutexSem( NULL, &surface->image_lock, 0, FALSE );
+
+ /* create the image's presentation space */
+ surface->image_dc = DevOpenDC( gr_anchor,
+ OD_MEMORY, (PSZ)"*", 0L, 0L, 0L );
+
+ surface->image_ps = GpiCreatePS( gr_anchor,
+ surface->image_dc,
+ &sizl,
+ PU_PELS | GPIT_MICRO |
+ GPIA_ASSOC | GPIF_DEFAULT );
+
+ GpiSetBackMix( surface->image_ps, BM_OVERPAINT );
+
+ /* create the image's PM bitmap */
+ bit = (PBITMAPINFO2)grAlloc( sizeof(BITMAPINFO2) + 256*sizeof(RGB2) );
+ surface->bitmap_header = bit;
+
+ bit->cbFix = sizeof( BITMAPINFOHEADER2 );
+ bit->cx = surface->root.bitmap.width;
+ bit->cy = surface->root.bitmap.rows;
+ bit->cPlanes = 1;
+
+ bit->argbColor[0].bBlue = 255;
+ bit->argbColor[0].bGreen = 0;
+ bit->argbColor[0].bRed = 0;
+
+ bit->argbColor[1].bBlue = 0;
+ bit->argbColor[1].bGreen = 255;
+ bit->argbColor[1].bRed = 0;
+
+ bit->cBitCount = (bitmap->mode == gr_pixel_mode_gray ? 8 : 1 );
+
+ if (bitmap->mode == gr_pixel_mode_gray)
+ {
+ RGB2* color = bit->argbColor;
+ int x, count;
+
+ count = bitmap->grays;
+ for ( x = 0; x < count; x++, color++ )
+ {
+ color->bBlue =
+ color->bGreen =
+ color->bRed = (((count-x)*255)/count);
+ }
+ }
+ else
+ {
+ RGB2* color = bit->argbColor;
+
+ color[0].bBlue =
+ color[0].bGreen =
+ color[0].bRed = 0;
+
+ color[1].bBlue =
+ color[1].bGreen =
+ color[1].bRed = 255;
+ }
+
+ surface->os2_bitmap = GpiCreateBitmap( surface->image_ps,
+ (PBITMAPINFOHEADER2)bit,
+ 0L, NULL, NULL );
+
+ GpiSetBitmap( surface->image_ps, surface->os2_bitmap );
+
+ bit->cbFix = sizeof( BITMAPINFOHEADER2 );
+ GpiQueryBitmapInfoHeader( surface->os2_bitmap,
+ (PBITMAPINFOHEADER2)bit );
+ surface->bitmap_header = bit;
+
+ /* for gr_pixel_mode_gray, create a gray-levels logical palette */
+ if ( bitmap->mode == gr_pixel_mode_gray )
+ {
+ int x, count;
+
+ count = bitmap->grays;
+ for ( x = 0; x < count; x++ )
+ palette[x] = (((count-x)*255)/count) * 0x010101;
+
+ /* create logical color table */
+ GpiCreateLogColorTable( surface->image_ps,
+ (ULONG) LCOL_PURECOLOR,
+ (LONG) LCOLF_CONSECRGB,
+ (LONG) 0L,
+ (LONG) count,
+ (PLONG) palette );
+
+ /* now, copy the color indexes to surface->shades */
+ for ( x = 0; x < count; x++ )
+ surface->shades[x] = GpiQueryColorIndex( surface->image_ps,
+ 0, palette[x] );
+ }
+
+ /* set up the blit points array */
+ surface->blit_points[1].x = surface->root.bitmap.width;
+ surface->blit_points[1].y = surface->root.bitmap.rows;
+ surface->blit_points[3] = surface->blit_points[1];
+
+ window_created = 0;
+
+ /* Finally, create the event handling thread for the surface's window */
+ DosCreateThread( &surface->message_thread,
+ (PFNTHREAD) RunPMWindow,
+ (ULONG) surface,
+ 0UL,
+ 32920 );
+
+ /* wait for the window creation */
+ for ( ; window_created == 0; )
+
+ surface->root.done = (grDoneSurfaceFunc) done_surface;
+ surface->root.refresh_rect = (grRefreshRectFunc) refresh_rectangle;
+ surface->root.set_title = (grSetTitleFunc) set_title;
+ surface->root.listen_event = (grListenEventFunc) listen_event;
+
+ /* convert_rectangle( surface, 0, 0, bitmap->width, bitmap->rows ); */
+ return surface;
+ }
+
+
+
+ MRESULT EXPENTRY Message_Process( HWND handle,
+ ULONG mess,
+ MPARAM parm1,
+ MPARAM parm2 );
+
+
+ static
+ void RunPMWindow( grPMSurface* surface )
+ {
+ unsigned char class_name[] = "DisplayClass";
+ ULONG class_flags;
+
+ static HMQ queue;
+ QMSG message;
+
+ /* store the current surface pointer in "the_surface". It is a static */
+ /* variable that is only used to retrieve the pointer in the client */
+ /* window procedure the first time is is called.. */
+ the_surface = surface;
+
+ LOG(( "Os2PM: RunPMWindow( %08lx )\n", (long)surface ));
+
+ /* create an anchor to allow this thread to use PM */
+ surface->anchor = WinInitialize(0);
+ if (!surface->anchor)
+ {
+ printf( "Error doing WinInitialize()\n" );
+ return;
+ }
+
+ /* create a message queue */
+ queue = WinCreateMsgQueue( surface->anchor, 0 );
+ if (!queue)
+ {
+ printf( "Error doing >inCreateMsgQueue()\n" );
+ return;
+ }
+
+ /* register the window class */
+ if ( !WinRegisterClass( surface->anchor,
+ (PSZ) class_name,
+ (PFNWP) Message_Process,
+ CS_SIZEREDRAW,
+ 0 ) )
+ {
+ printf( "Error doing WinRegisterClass()\n" );
+ return;
+ }
+
+ /* create the PM window */
+ class_flags = FCF_TITLEBAR | FCF_MINBUTTON | FCF_DLGBORDER |
+ FCF_TASKLIST | FCF_SYSMENU;
+
+ LOG(( "Os2PM: RunPMWindow: Creating window\n" ));
+ surface->frame_window = WinCreateStdWindow(
+ HWND_DESKTOP,
+ WS_VISIBLE,
+ &class_flags,
+ (PSZ) class_name,
+ (PSZ) "FreeType Viewer - press F1 for help",
+ WS_VISIBLE,
+ 0, 0,
+ &surface->client_window );
+ if (!surface->frame_window)
+ {
+ printf( "Error doing WinCreateStdWindow()\n" );
+ return;
+ }
+
+ /* find the title window handle */
+ surface->title_window = WinWindowFromID( surface->frame_window,
+ FID_TITLEBAR );
+ LOG (( "Os2PM: RunPMWIndow: Creation succeeded\n" ));
+ LOG (( " -- frame = %08lx\n", surface->frame_window ));
+ LOG (( " -- client = %08lx\n", surface->client_window ));
+
+ /* set Window size and position */
+ WinSetWindowPos( surface->frame_window,
+ 0L,
+ (SHORT) 60,
+
+ (SHORT) WinQuerySysValue( HWND_DESKTOP, SV_CYSCREEN ) -
+ (surface->root.bitmap.rows + 100),
+
+ (SHORT) WinQuerySysValue( HWND_DESKTOP, SV_CYDLGFRAME )*2 +
+ surface->root.bitmap.width,
+
+ (SHORT) WinQuerySysValue( HWND_DESKTOP, SV_CYTITLEBAR ) +
+ WinQuerySysValue( HWND_DESKTOP, SV_CYDLGFRAME )*2 +
+ surface->root.bitmap.rows,
+
+ SWP_SIZE | SWP_MOVE );
+
+#if 0
+ /* save the handle to the current surface within the window words */
+ WinSetWindowPtr( surface->client_window,QWL_USER, surface );
+#endif
+
+ window_created = 1;
+
+ /* run the message queue till the end */
+ while ( WinGetMsg( surface->anchor, &message, (HWND)NULL, 0, 0 ) )
+ {
+ WinDispatchMsg( surface->anchor, &message );
+ }
+
+ /* clean-up */
+ WinDestroyWindow( surface->frame_window );
+ surface->frame_window = 0;
+
+ WinDestroyMsgQueue( queue );
+ WinTerminate( surface->anchor );
+
+ /* await death... */
+ while ( 1 )
+ DosSleep( 100 );
+ }
+
+
+
+
+ /* Message processing for our PM Window class */
+ MRESULT EXPENTRY Message_Process( HWND handle,
+ ULONG mess,
+ MPARAM parm1,
+ MPARAM parm2 )
+ {
+ static HDC screen_dc;
+ static HPS screen_ps;
+ static BOOL minimized;
+
+ SIZEL sizl;
+ SWP swp;
+
+ grPMSurface* surface;
+
+ /* get the handle to the window's surface -- note that this */
+ /* value will be null when the window is created */
+ surface = (grPMSurface*)WinQueryWindowPtr( handle, QWL_USER );
+ if (!surface)
+ {
+ surface = the_surface;
+ WinSetWindowPtr( handle, QWL_USER, surface );
+ }
+
+ switch( mess )
+ {
+ case WM_DESTROY:
+ /* warn the main thread to quit if it didn't know */
+ surface->event.type = gr_event_key;
+ surface->event.key = grKeyEsc;
+ DosPostEventSem( surface->event_lock );
+ break;
+
+ case WM_CREATE:
+ /* set original magnification */
+ minimized = FALSE;
+
+ /* create Device Context and Presentation Space for screen. */
+ screen_dc = WinOpenWindowDC( handle );
+ screen_ps = GpiCreatePS( surface->anchor,
+ screen_dc,
+ &sizl,
+ PU_PELS | GPIT_MICRO |
+ GPIA_ASSOC | GPIF_DEFAULT );
+ /* take the input focus */
+ WinFocusChange( HWND_DESKTOP, handle, 0L );
+ LOG(( "screen_dc and screen_ps have been created\n" ));
+ break;
+
+ case WM_MINMAXFRAME:
+ /* to update minimized if changed */
+ swp = *((PSWP) parm1);
+ if ( swp.fl & SWP_MINIMIZE )
+ minimized = TRUE;
+ if ( swp.fl & SWP_RESTORE )
+ minimized = FALSE;
+ return WinDefWindowProc( handle, mess, parm1, parm2 );
+ break;
+
+ case WM_ERASEBACKGROUND:
+ case WM_PAINT:
+ /* copy the memory image of the screen out to the real screen */
+ DosRequestMutexSem( surface->image_lock, SEM_INDEFINITE_WAIT );
+ WinBeginPaint( handle, screen_ps, NULL );
+
+ /* main image and magnified picture */
+ GpiBitBlt( screen_ps,
+ surface->image_ps,
+ 4L,
+ surface->blit_points,
+ ROP_SRCCOPY, BBO_AND );
+
+ WinEndPaint( screen_ps );
+ DosReleaseMutexSem( surface->image_lock );
+ break;
+
+ case WM_HELP: /* this really is a F1 Keypress !! */
+ surface->event.key = grKeyF1;
+ goto Do_Key_Event;
+
+ case WM_CHAR:
+ if ( CHARMSG( &mess )->fs & KC_KEYUP )
+ break;
+
+ /* look for a specific vkey */
+ {
+ int count = sizeof( key_translators )/sizeof( key_translators[0] );
+ Translator* trans = key_translators;
+ Translator* limit = trans + count;
+
+ for ( ; trans < limit; trans++ )
+ if ( CHARMSG(&mess)->vkey == trans->os2key )
+ {
+ surface->event.key = trans->grkey;
+ goto Do_Key_Event;
+ }
+ }
+
+ /* otherwise, simply record the character code */
+ if ( (CHARMSG( &mess )->fs & KC_CHAR) == 0 )
+ break;
+
+ surface->event.key = CHARMSG(&mess)->chr;
+
+ Do_Key_Event:
+ surface->event.type = gr_event_key;
+ DosPostEventSem( surface->event_lock );
+ break;
+
+ default:
+ return WinDefWindowProc( handle, mess, parm1, parm2 );
+ }
+
+ return (MRESULT) FALSE;
+ }
+
+
+
+
+ grDevice gr_os2pm_device =
+ {
+ sizeof( grPMSurface ),
+ "os2pm",
+
+ init_device,
+ done_device,
+
+ (grDeviceInitSurfaceFunc) init_surface,
+
+ 0,
+ 0
+
+ };
+
+
--- /dev/null
+++ b/demos/graph/os2/gros2pm.def
@@ -1,0 +1,5 @@
+NAME WINDOWCOMPAT
+
+DESCRIPTION 'FreeType Graphics'
+HEAPSIZE 8192
+STACKSIZE 40888
--- /dev/null
+++ b/demos/graph/os2/gros2pm.h
@@ -1,0 +1,23 @@
+#ifndef GROS2PM_H
+#define GROS2PM_H
+
+#include "grobjs.h"
+
+ extern
+ grDevice gr_os2pm_device;
+
+#ifdef GR_INIT_BUILD
+ static
+ grDeviceChain gr_os2pm_device_chain =
+ {
+ "os2pm",
+ &gr_os2pm_device,
+ GR_INIT_DEVICE_CHAIN
+ };
+
+#undef GR_INIT_DEVICE_CHAIN
+#define GR_INIT_DEVICE_CHAIN &gr_os2pm_device_chain
+
+#endif /* GR_INIT_BUILD */
+
+#endif /* GROS2PM_H */
--- /dev/null
+++ b/demos/graph/os2/rules.mk
@@ -1,0 +1,32 @@
+#**************************************************************************
+#*
+#* OS/2 specific rules file, used to compile the OS/2 graphics driver
+#* to the graphics subsystem
+#*
+#**************************************************************************
+
+ifeq ($(PLATFORM),os2)
+
+GR_OS2 := $(GRAPH_)os2
+GR_OS2_ := $(GR_OS2)$(SEP)
+
+# the GRAPH_LINK is expanded each time an executable is linked with the
+# graphics library.
+#
+GRAPH_LINK += $(GR_OS2_)gros2pm.def
+
+# Add the OS/2 driver object file to the graphics library "graph.a"
+#
+GRAPH_OBJS += $(OBJ_)gros2pm.$O
+
+DEVICES += OS2_PM
+DEVICE_INCLUDES += $(GR_OS2)
+
+# the rule used to compile the graphics driver
+#
+$(OBJ_)gros2pm.$O: $(GR_OS2_)gros2pm.c $(GR_OS2_)gros2pm.h
+ $(CC) $(CFLAGS) $(GRAPH_INCLUDES:%=$I%) $I$(GR_OS2) $T$@ $<
+
+endif
+
+
--- a/demos/graph/rules.mk
+++ b/demos/graph/rules.mk
@@ -45,11 +45,11 @@
#
#
-GRAPH_INCLUDES := graph
-GRAPH_LIB := $(OBJ_)graph.a
+GRAPH_INCLUDES := $(TOP2_)graph
+GRAPH_LIB := $(OBJ_)graph.$A
GRAPH_LINK := $(GRAPH_LIB)
-GRAPH_ := graph$(SEP)
+GRAPH_ := $(TOP2_)graph$(SEP)
GRAPH_H := $(GRAPH_)graph.h \
$(GRAPH_)grtypes.h \
@@ -65,10 +65,15 @@
$(OBJ_)grinit.$O
+# Default value for COMPILE_GRAPH_LIB
+# this value can be modified by the system-specific graphics drivers..
+#
+COMPILE_GRAPH_LIB = ar -r $@ $(GRAPH_OBJS)
+
# Add the rules used to detect and compile graphics driver depending
# on the current platform..
#
-include $(wildcard config/*/rules.mk)
+include $(wildcard $(GRAPH_)/*/rules.mk)
#########################################################################
#
@@ -80,7 +85,7 @@
#
#
$(GRAPH_LIB): $(GRAPH_OBJS)
- ar -r $@ $(GRAPH_OBJS)
+ $(COMPILE_GRAPH_LIB)
# pattern rule for normal sources
--- /dev/null
+++ b/demos/graph/win32/grwin32.c
@@ -1,0 +1,504 @@
+/*******************************************************************
+ *
+ * grwin32.c graphics driver for Win32 platform. 0.1
+ *
+ * This is the driver for displaying inside a window under Win32,
+ * used by the graphics utility of the FreeType test suite.
+ *
+ * Written by Antoine Leca.
+ * Copyright 1999-2000 by Antoine Leca, David Turner
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * Borrowing liberally from the other FreeType drivers.
+ *
+ * This file is part of the FreeType project, and may only be used
+ * modified and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ ******************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+#include "grwin32.h"
+#include "grdevice.h"
+
+
+/* logging facility */
+#include <stdarg.h>
+
+#define DEBUGxxx
+
+#ifdef DEBUG
+#define LOG(x) LogMessage##x
+#else
+#define LOG(x) /* rien */
+#endif
+
+#ifdef DEBUG
+ static void LogMessage( const char* fmt, ... )
+ {
+ va_list ap;
+
+ va_start( ap, fmt );
+ vfprintf( stderr, fmt, ap );
+ va_end( ap );
+ }
+#endif
+/*-------------------*/
+
+/* Size of the window. */
+#define WIN_WIDTH 640u
+#define WIN_HEIGHT 450u
+
+/* These values can be changed, but WIN_WIDTH should remain for now a */
+/* multiple of 32 to avoid padding issues. */
+
+ typedef struct _Translator
+ {
+ ULONG winkey;
+ grKey grkey;
+
+ } Translator;
+
+ static
+ Translator key_translators[] =
+ {
+ { VK_BACK, grKeyBackSpace },
+ { VK_TAB, grKeyTab },
+ { VK_RETURN, grKeyReturn },
+ { VK_ESCAPE, grKeyEsc },
+ { VK_HOME, grKeyHome },
+ { VK_LEFT, grKeyLeft },
+ { VK_UP, grKeyUp },
+ { VK_RIGHT, grKeyRight },
+ { VK_DOWN, grKeyDown },
+ /*
+ { VK_PAGEUP, grKeyPageUp },
+ { VK_PAGEDOWN, grKeyPageDown },
+ */
+ { VK_END, grKeyEnd },
+ { VK_F1, grKeyF1 },
+ { VK_F2, grKeyF2 },
+ { VK_F3, grKeyF3 },
+ { VK_F4, grKeyF4 },
+ { VK_F5, grKeyF5 },
+ { VK_F6, grKeyF6 },
+ { VK_F7, grKeyF7 },
+ { VK_F8, grKeyF8 },
+ { VK_F9, grKeyF9 },
+ { VK_F10, grKeyF10 },
+ { VK_F11, grKeyF11 },
+ { VK_F12, grKeyF12 }
+ };
+
+ /* This is a minimalist driver, it is only able to display */
+ /* a _single_ window. Moreover, only monochrome and gray */
+ /* bitmaps are supported.. */
+
+ /* handle of the window. */
+ static HWND hwndGraphic;
+
+ static int window_width, window_height;
+
+ /* the following variables are used to set the window title lazily */
+ static int title_set = 1;
+ static const char* the_title;
+
+ /* bitmap information */
+ static LPBITMAPINFO pbmi;
+ static HBITMAP hbm;
+
+ /* local event to pass on */
+ static grEvent ourevent;
+ static int eventToProcess = 0;
+
+/* destroys the surface*/
+static
+void done_surface( grSurface* surface )
+{
+ /* The graphical window has perhaps already destroyed itself */
+ if ( hwndGraphic )
+ {
+ DestroyWindow ( hwndGraphic );
+ PostMessage( hwndGraphic, WM_QUIT, 0, 0 );
+ }
+ grDoneBitmap( &surface->bitmap );
+ if ( pbmi ) free ( pbmi );
+}
+
+ static
+ const int pixel_mode_bit_count[] =
+ {
+ 0,
+ 1, /* mono */
+ 4, /* pal4 */
+ 8, /* pal8 */
+ 8, /* grays */
+ 15, /* rgb15 */
+ 16, /* rgb16 */
+ 24, /* rgb24 */
+ 32 /* rgb32 */
+ };
+
+ static
+ void refresh_rectangle( grSurface* surface,
+ int x,
+ int y,
+ int w,
+ int h )
+ {
+ HDC hDC;
+ int row_bytes;
+
+ LOG(( "Win32: refresh_rectangle( %08lx, %d, %d, %d, %d )\n",
+ (long)surface, x, y, w, h ));
+ (void)x;
+ (void)y;
+ (void)w;
+ (void)h;
+
+ row_bytes = surface->bitmap.pitch;
+ if (row_bytes < 0) row_bytes = -row_bytes;
+
+ if ( row_bytes*8 != pbmi->bmiHeader.biWidth * pbmi->bmiHeader.biBitCount )
+ pbmi->bmiHeader.biWidth = row_bytes * 8 / pbmi->bmiHeader.biBitCount;
+
+ hDC = GetDC ( hwndGraphic );
+ SetDIBits ( hDC, hbm,
+ 0,
+ surface->bitmap.rows,
+ surface->bitmap.buffer,
+ pbmi,
+ DIB_RGB_COLORS );
+
+ ReleaseDC ( hwndGraphic, hDC );
+
+ ShowWindow( hwndGraphic, SW_SHOW );
+ InvalidateRect ( hwndGraphic, NULL, FALSE );
+ UpdateWindow ( hwndGraphic );
+ }
+
+ static
+ void set_title( grSurface* surface, const char* title )
+ {
+ (void)surface;
+
+ /* the title will be set on the next listen_event, just */
+ /* record it there.. */
+ the_title = title;
+ title_set = 0;
+ }
+
+ static
+ void listen_event( grSurface* surface,
+ int event_mask,
+ grEvent* grevent )
+ {
+ MSG msg;
+
+ (void)surface;
+ (void)event_mask;
+
+ if ( hwndGraphic && !title_set )
+ {
+ SetWindowText( hwndGraphic, the_title );
+ title_set = 1;
+ }
+
+ do
+ {
+ while ( PeekMessage( &msg, 0, 0, 0, PM_REMOVE ) )
+ {
+ TranslateMessage( &msg );
+ DispatchMessage( &msg );
+ }
+ if (!eventToProcess)
+ WaitMessage();
+ }
+ while (!eventToProcess);
+
+ *grevent = ourevent;
+ }
+
+/*
+ * set graphics mode
+ * and create the window class and the message handling.
+ */
+
+/* Declarations of the Windows-specific functions that are below. */
+static BOOL RegisterTheClass ( void );
+static BOOL CreateTheWindow ( int width, int height );
+
+static
+grSurface* init_surface( grSurface* surface,
+ grBitmap* bitmap )
+{
+ static RGBQUAD black = { 0, 0, 0, 0 };
+ static RGBQUAD white = { 0xFF, 0xFF, 0xFF, 0 };
+
+ if( ! RegisterTheClass() ) return 0; /* if already running, fails. */
+
+ /* find some memory for the bitmap header */
+ if ( (pbmi = malloc ( sizeof ( BITMAPINFO ) + sizeof ( RGBQUAD ) * 256 ) )
+ /* 256 should really be 2 if not grayscale */
+ == NULL )
+ /* lack of memory; fails the process */
+ return 0;
+
+ LOG(( "Win32: init_surface( %08lx, %08lx )\n",
+ (long)surface, (long)bitmap ));
+
+ LOG(( " -- input bitmap =\n" ));
+ LOG(( " -- mode = %d\n", bitmap->mode ));
+ LOG(( " -- grays = %d\n", bitmap->grays ));
+ LOG(( " -- width = %d\n", bitmap->width ));
+ LOG(( " -- height = %d\n", bitmap->rows ));
+
+ /* create the bitmap - under Win32, we support all modes as the GDI */
+ /* handles all conversions automatically.. */
+ if ( grNewBitmap( bitmap->mode,
+ bitmap->grays,
+ bitmap->width,
+ bitmap->rows,
+ bitmap ) )
+ return 0;
+
+ LOG(( " -- output bitmap =\n" ));
+ LOG(( " -- mode = %d\n", bitmap->mode ));
+ LOG(( " -- grays = %d\n", bitmap->grays ));
+ LOG(( " -- width = %d\n", bitmap->width ));
+ LOG(( " -- height = %d\n", bitmap->rows ));
+
+ bitmap->pitch = -bitmap->pitch;
+ surface->bitmap = *bitmap;
+
+ /* initialize the header to appropriate values */
+ memset( pbmi, 0, sizeof ( BITMAPINFO ) + sizeof ( RGBQUAD ) * 256 );
+
+ switch ( bitmap->mode )
+ {
+ case gr_pixel_mode_mono:
+ pbmi->bmiHeader.biBitCount = 1;
+ pbmi->bmiColors[0] = white;
+ pbmi->bmiColors[1] = black;
+ break;
+
+ case gr_pixel_mode_gray:
+ pbmi->bmiHeader.biBitCount = 8;
+ pbmi->bmiHeader.biClrUsed = bitmap->grays;
+ {
+ int count = bitmap->grays;
+ int x;
+ RGBQUAD* color = pbmi->bmiColors;
+
+ for ( x = 0; x < count; x++, color++ )
+ {
+ color->rgbRed =
+ color->rgbGreen =
+ color->rgbBlue = (((count-x)*255)/count);
+ color->rgbReserved = 0;
+ }
+ }
+ break;
+
+ default:
+ free ( pbmi );
+ return 0; /* Unknown mode */
+ }
+
+ pbmi->bmiHeader.biSize = sizeof ( BITMAPINFOHEADER );
+ pbmi->bmiHeader.biWidth = bitmap->width;
+ pbmi->bmiHeader.biHeight = bitmap->rows;
+ pbmi->bmiHeader.biPlanes = 1;
+
+ if( ! CreateTheWindow( bitmap->width, bitmap->rows ) )
+ {
+ free ( pbmi );
+ return 0;
+ }
+
+ surface->done = (grDoneSurfaceFunc) done_surface;
+ surface->refresh_rect = (grRefreshRectFunc) refresh_rectangle;
+ surface->set_title = (grSetTitleFunc) set_title;
+ surface->listen_event = (grListenEventFunc) listen_event;
+
+ return surface;
+}
+
+
+/* ---- Windows-specific stuff ------------------------------------------- */
+
+LRESULT CALLBACK Message_Process( HWND, UINT, WPARAM, LPARAM );
+
+static
+BOOL RegisterTheClass ( void )
+ {
+ WNDCLASS ourClass = {
+ /* UINT style */ 0,
+ /* WNDPROC lpfnWndProc */ Message_Process,
+ /* int cbClsExtra */ 0,
+ /* int cbWndExtra */ 0,
+ /* HANDLE hInstance */ 0,
+ /* HICON hIcon */ 0,
+ /* HCURSOR hCursor */ 0,
+ /* HBRUSH hbrBackground*/ 0,
+ /* LPCTSTR lpszMenuName */ NULL,
+ /* LPCTSTR lpszClassName*/ "FreeTypeTestGraphicDriver"
+ };
+
+ ourClass.hInstance = GetModuleHandle( NULL );
+ ourClass.hIcon = LoadIcon(0, IDI_APPLICATION);
+ ourClass.hCursor = LoadCursor(0, IDC_ARROW);
+ ourClass.hbrBackground= GetStockObject(BLACK_BRUSH);
+
+ return RegisterClass(&ourClass) != 0; /* return False if it fails. */
+ }
+
+static
+BOOL CreateTheWindow ( int width, int height )
+ {
+ window_width = width;
+ window_height = height;
+
+ if ( ! (hwndGraphic = CreateWindow(
+ /* LPCSTR lpszClassName; */ "FreeTypeTestGraphicDriver",
+ /* LPCSTR lpszWindowName; */ "FreeType Test Graphic Driver",
+ /* DWORD dwStyle; */ WS_OVERLAPPED | WS_SYSMENU,
+ /* int x; */ CW_USEDEFAULT,
+ /* int y; */ CW_USEDEFAULT,
+ /* int nWidth; */ width + 2*GetSystemMetrics(SM_CXBORDER),
+ /* int nHeight; */ height+ GetSystemMetrics(SM_CYBORDER)
+ + GetSystemMetrics(SM_CYCAPTION),
+ /* HWND hwndParent; */ HWND_DESKTOP,
+ /* HMENU hmenu; */ 0,
+ /* HINSTANCE hinst; */ GetModuleHandle( NULL ),
+ /* void FAR* lpvParam; */ NULL))
+ )
+ /* creation failed... */
+ return 0;
+
+ return 1;
+ }
+
+ /* Message processing for our Windows class */
+LRESULT CALLBACK Message_Process( HWND handle, UINT mess,
+ WPARAM wParam, LPARAM lParam )
+ {
+
+ switch( mess )
+ {
+ case WM_DESTROY:
+ /* warn the main thread to quit if it didn't know */
+ ourevent.type = gr_event_key;
+ ourevent.key = grKeyEsc;
+ eventToProcess = 1;
+ hwndGraphic = 0;
+ PostQuitMessage ( 0 );
+ DeleteObject ( hbm );
+ break;
+
+ case WM_CREATE:
+ {
+ HDC hDC;
+
+ hDC = GetDC ( handle );
+ hbm = CreateDIBitmap (
+ /* HDC hdc; handle of device context */ hDC,
+ /* BITMAPINFOHEADER FAR* lpbmih; addr.of header*/ &pbmi->bmiHeader,
+ /* DWORD dwInit; CBM_INIT to initialize bitmap */ 0,
+ /* const void FAR* lpvBits; address of values */ NULL,
+ /* BITMAPINFO FAR* lpbmi; addr.of bitmap data */ pbmi,
+ /* UINT fnColorUse; RGB or palette indices */ DIB_RGB_COLORS);
+ ReleaseDC ( handle, hDC );
+ break;
+ }
+
+ case WM_PAINT:
+ {
+ HDC hDC, memDC;
+ HANDLE oldbm;
+ PAINTSTRUCT ps;
+
+ hDC = BeginPaint ( handle, &ps );
+ memDC = CreateCompatibleDC(hDC);
+ oldbm = SelectObject(memDC, hbm);
+ BitBlt ( hDC, 0, 0, window_width, window_height, memDC, 0, 0, SRCCOPY);
+ ReleaseDC ( handle, hDC );
+ SelectObject ( memDC, oldbm );
+ DeleteObject ( memDC );
+ EndPaint ( handle, &ps );
+ }
+
+ case WM_KEYDOWN:
+ switch ( wParam )
+ {
+ case VK_ESCAPE:
+ ourevent.type = gr_event_key;
+ ourevent.key = grKeyEsc;
+ eventToProcess = 1;
+ break;
+
+ default:
+ /* lookup list of translated keys */
+ {
+ int count = sizeof( key_translators )/sizeof( key_translators[0] );
+ Translator* trans = key_translators;
+ Translator* limit = trans + count;
+ for ( ; trans < limit; trans++ )
+ if ( wParam == trans->winkey )
+ {
+ ourevent.key = trans->grkey;
+ goto Do_Key_Event;
+ }
+ }
+ }
+
+ case WM_CHAR:
+ {
+ ourevent.key = wParam;
+
+ Do_Key_Event:
+ ourevent.type = gr_event_key;
+ eventToProcess = 1;
+ }
+ break;
+
+ default:
+ return DefWindowProc( handle, mess, wParam, lParam );
+ }
+
+ return 0;
+ }
+
+ static int init_device( void )
+ {
+ return 0;
+ }
+
+ static void done_device( void )
+ {
+ }
+
+ grDevice gr_win32_device =
+ {
+ sizeof( grSurface ),
+ "win32",
+
+ init_device,
+ done_device,
+
+ (grDeviceInitSurfaceFunc) init_surface,
+
+ 0,
+ 0
+ };
+
+
+/* End */
--- /dev/null
+++ b/demos/graph/win32/grwin32.h
@@ -1,0 +1,23 @@
+#ifndef GRWIN32_H
+#define GRWIN32_H
+
+#include "grobjs.h"
+
+ extern
+ grDevice gr_win32_device;
+
+#ifdef GR_INIT_BUILD
+ static
+ grDeviceChain gr_win32_device_chain =
+ {
+ "win32",
+ &gr_win32_device,
+ GR_INIT_DEVICE_CHAIN
+ };
+
+#undef GR_INIT_DEVICE_CHAIN
+#define GR_INIT_DEVICE_CHAIN &gr_win32_device_chain
+
+#endif /* GR_INIT_BUILD */
+
+#endif /* GRWIN32_H */
--- /dev/null
+++ b/demos/graph/win32/rules.mk
@@ -1,0 +1,49 @@
+#**************************************************************************
+#*
+#* Win32 specific rules file, used to compile the Win32 graphics driver
+#* to the graphics subsystem
+#*
+#**************************************************************************
+
+ifeq ($(PLATFORM),win32)
+
+GR_WIN32 := $(GRAPH_)win32
+GR_WIN32_ := $(GR_WIN32)$(SEP)
+
+# Add the Win32 driver object file to the graphics library "graph.a"
+#
+GRAPH_OBJS += $(OBJ_)grwin32.$O
+
+DEVICES += WIN32
+DEVICE_INCLUDES += $(GR_WIN32)
+
+# the rule used to compile the graphics driver
+#
+$(OBJ_)grwin32.$O: $(GR_WIN32_)grwin32.c $(GR_WIN32_)grwin32.h
+ $(CC) $(CFLAGS) $(GRAPH_INCLUDES:%=$I%) $I$(GR_WIN32) $T$@ $<
+
+# Now update COMPILE_GRAPH_LIB according to the compiler used on Win32
+#
+ifeq ($(CC),gcc) # test for GCC
+LINK = $(CC) $T$@ $< $(FTLIB)
+COMMON_LINK = $(LINK) $(COMMON_OBJ)
+GRAPH_LINK = $(COMMON_LINK) $(GRAPH_LIB) -luser32 -lgdi32
+endif
+
+ifeq ($(CC),cl) # test for Visual C++
+COMPILE_GRAPH_LIB = lib /nologo /out:$(GRAPH_LIB) $(GRAPH_OBJS)
+LINK = cl /nologo /MD -o $@ $< $(FTLIB)
+COMMON_LINK = $(LINK) $(COMMON_OBJ)
+GRAPH_LINK = $(COMMON_LINK) $(GRAPH_LIB) user32.lib gdi32.lib
+endif
+
+ifeq ($(CC),lcc) # test for LCC-Win32
+COMPILE_GRAPH_LIB = lcclib /out:$(subst /,\\,$(GRAPH_LIB)) $(subst /,\\,$(GRAPH_OBJS))
+GRAPH_LINK = $(subst /,\\,$(GRAPH_LIB)) user32.lib gdi32.lib
+LINK_ROOT = lcclnk -o $(subst /,\\,$@) $(subst /,\\,$<)
+LINK = $(LINK_ROOT) $(subst /,\\,$(FTLIB))
+COMMON_LINK = $(LINK_ROOT) $(subst /,\\,$(COMMON_OBJ)) $(subst /,\\,$(FTLIB))
+GRAPH_LINK = $(LINK_ROOT) $(subst /,\\,$(COMMON_OBJ)) $(subst /,\\,$(GRAPH_LIB)) $(subst /,\\,$(FTLIB))
+endif
+endif
+
--- /dev/null
+++ b/demos/graph/x11/grx11.c
@@ -1,0 +1,936 @@
+#include "grx11.h"
+
+
+#ifdef TEST
+#include "grfont.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/cursorfont.h>
+#include <X11/keysym.h>
+
+ static void Panic( const char* message )
+ {
+ fprintf( stderr, "%s", message );
+ exit(1);
+ }
+
+ typedef struct Translator
+ {
+ KeySym xkey;
+ grKey grkey;
+
+ } Translator;
+
+ static
+ Translator key_translators[] =
+ {
+ { XK_BackSpace, grKeyBackSpace },
+ { XK_Tab, grKeyTab },
+ { XK_Return, grKeyReturn },
+ { XK_Escape, grKeyEsc },
+ { XK_Home, grKeyHome },
+ { XK_Left, grKeyLeft },
+ { XK_Up, grKeyUp },
+ { XK_Right, grKeyRight },
+ { XK_Down, grKeyDown },
+ { XK_Page_Up, grKeyPageUp },
+ { XK_Page_Down, grKeyPageDown },
+ { XK_End, grKeyEnd },
+ { XK_Begin, grKeyHome },
+ { XK_F1, grKeyF1 },
+ { XK_F2, grKeyF2 },
+ { XK_F3, grKeyF3 },
+ { XK_F4, grKeyF4 },
+ { XK_F5, grKeyF5 },
+ { XK_F6, grKeyF6 },
+ { XK_F7, grKeyF7 },
+ { XK_F8, grKeyF8 },
+ { XK_F9, grKeyF9 },
+ { XK_F10, grKeyF10 },
+ { XK_F11, grKeyF11 },
+ { XK_F12, grKeyF12 }
+ };
+
+
+#ifdef TEST
+
+#define grAlloc malloc
+
+#endif
+
+
+ static Display* display;
+ static char* displayname = "";
+
+ static Cursor idle;
+ static Cursor busy;
+
+#define MAX_PIXEL_MODES 32
+
+ typedef XPixmapFormatValues XDepth;
+
+ static int num_pixel_modes = 0;
+ static grPixelMode pixel_modes[ MAX_PIXEL_MODES ];
+ static XDepth pixel_depth[ MAX_PIXEL_MODES ];
+
+ typedef struct grXSurface_
+ {
+ grSurface root;
+ grBitmap image;
+
+ Window win;
+ Visual* visual;
+ Colormap colormap;
+ int depth;
+ Bool gray;
+
+ GC gc;
+
+ XColor color[256]; /* gray levels palette for 8-bit modes */
+ XImage* ximage;
+
+ int win_org_x;
+ int win_org_y;
+ int win_width;
+ int win_height;
+
+ int image_width;
+ int image_height;
+
+ } grXSurface;
+
+
+
+
+ /* close a given window */
+ static
+ void done_surface( grXSurface* surface )
+ {
+ XUnmapWindow( display, surface->win );
+ }
+
+
+
+ /* close the device, i.e. the display connection */
+ static
+ void done_device( void )
+ {
+ XCloseDisplay( display );
+ }
+
+
+
+ static
+ void add_pixel_mode( grPixelMode pixel_mode,
+ XDepth* depth )
+ {
+ if ( num_pixel_modes >= MAX_PIXEL_MODES )
+ Panic( "X11.Too many pixel modes\n" );
+
+ pixel_modes[ num_pixel_modes ] = pixel_mode;
+ pixel_depth[ num_pixel_modes ] = *depth;
+
+ num_pixel_modes++;
+ }
+
+
+
+ static
+ int init_device( void )
+ {
+ XDepth dummy;
+
+ XrmInitialize();
+
+ display = XOpenDisplay( displayname );
+ if (!display)
+ {
+ return -1;
+ /* Panic( "Gr:error: cannot open X11 display\n" ); */
+ }
+
+ idle = XCreateFontCursor( display, XC_left_ptr );
+ busy = XCreateFontCursor( display, XC_watch );
+
+ num_pixel_modes = 0;
+
+ /* always enable the 8-bit gray levels pixel mode */
+ /* even if its display is emulated through a constrained palette */
+ /* or another color mode */
+ dummy.depth = 8;
+ dummy.bits_per_pixel = 8;
+ dummy.scanline_pad = 8;
+ add_pixel_mode( gr_pixel_mode_gray, &dummy );
+
+ {
+ int count;
+ XDepth* format;
+ XDepth* formats;
+ XVisualInfo template;
+
+ formats = XListPixmapFormats( display, &count );
+ format = formats;
+
+#ifdef TEST
+ printf( "available pixmap formats\n" );
+ printf( "depth pixbits scanpad\n" );
+#endif
+
+ while ( count-- > 0 )
+ {
+#ifdef TEST
+ printf( " %3d %3d %3d\n",
+ format->depth,
+ format->bits_per_pixel,
+ format->scanline_pad );
+#endif
+
+ if ( format->depth == 1 )
+ /* usually, this should be the first format */
+ add_pixel_mode( gr_pixel_mode_mono, format );
+
+ else if ( format->depth == 8 )
+ add_pixel_mode( gr_pixel_mode_pal8, format );
+
+ /* note, the 32-bit modes return a depth of 24, and 32 bits per pixel */
+ else if ( format->depth == 24 )
+ {
+ if ( format->bits_per_pixel == 24 )
+ add_pixel_mode( gr_pixel_mode_rgb24, format );
+
+ else if ( format->bits_per_pixel == 32 )
+ add_pixel_mode( gr_pixel_mode_rgb32, format );
+ }
+
+ else if ( format->depth == 16 )
+ {
+ int count2;
+ XVisualInfo* visuals;
+ XVisualInfo* visual;
+
+ template.depth = format->depth;
+ visuals = XGetVisualInfo( display,
+ VisualDepthMask,
+ &template,
+ &count2 );
+ visual = visuals;
+
+ while ( count2-- > 0 )
+ {
+#ifdef TEST
+ const char* string = "unknown";
+
+ switch (visual->class)
+ {
+ case TrueColor: string = "TrueColor"; break;
+ case DirectColor: string = "DirectColor"; break;
+ case PseudoColor: string = "PseudoColor"; break;
+ case StaticGray : string = "StaticGray"; break;
+ case StaticColor: string = "StaticColor"; break;
+ case GrayScale: string = "GrayScale"; break;
+ }
+
+ printf( "> RGB %02x:%02x:%02x, colors %3d, bits %2d %s\n",
+ visual->red_mask,
+ visual->green_mask,
+ visual->blue_mask,
+ visual->colormap_size,
+ visual->bits_per_rgb,
+ string );
+#endif
+ if ( visual->red_mask == 0xf800 &&
+ visual->green_mask == 0x07e0 &&
+ visual->blue_mask == 0x001f )
+ add_pixel_mode( gr_pixel_mode_rgb565, format );
+
+ else if ( visual->red_mask == 0x7c00 &&
+ visual->green_mask == 0x03e0 &&
+ visual->blue_mask == 0x001f )
+ add_pixel_mode( gr_pixel_mode_rgb555, format );
+
+ /* other 16-bit modes are ignored */
+ visual++;
+ }
+
+ XFree( visuals );
+ }
+
+ format++;
+ }
+
+ XFree( formats );
+ }
+
+ gr_x11_device.num_pixel_modes = num_pixel_modes;
+ gr_x11_device.pixel_modes = pixel_modes;
+
+ return 0;
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+ static
+ void convert_gray_to_pal8( grXSurface* surface,
+ int x,
+ int y,
+ int w,
+ int h )
+ {
+ grBitmap* target = &surface->image;
+ grBitmap* source = &surface->root.bitmap;
+ byte* write = (byte*)target->buffer + y*target->pitch + x;
+ byte* read = (byte*)source->buffer + y*source->pitch + x;
+ XColor* palette = surface->color;
+
+ while (h > 0)
+ {
+ byte* _write = write;
+ byte* _read = read;
+ byte* limit = _write + w;
+
+ for ( ; _write < limit; _write++, _read++ )
+ *_write = (byte) palette[ *_read ].pixel;
+
+ write += target->pitch;
+ read += source->pitch;
+ h--;
+ }
+ }
+
+
+ static
+ void convert_gray_to_16( grXSurface* surface,
+ int x,
+ int y,
+ int w,
+ int h )
+ {
+ grBitmap* target = &surface->image;
+ grBitmap* source = &surface->root.bitmap;
+ byte* write = (byte*)target->buffer + y*target->pitch + 2*x;
+ byte* read = (byte*)source->buffer + y*source->pitch + x;
+ XColor* palette = surface->color;
+
+ while (h > 0)
+ {
+ byte* _write = write;
+ byte* _read = read;
+ byte* limit = _write + 2*w;
+
+ for ( ; _write < limit; _write += 2, _read++ )
+ *(short*)_write = (short)palette[ *_read ].pixel;
+
+ write += target->pitch;
+ read += source->pitch;
+ h--;
+ }
+ }
+
+
+ static
+ void convert_gray_to_24( grXSurface* surface,
+ int x,
+ int y,
+ int w,
+ int h )
+ {
+ grBitmap* target = &surface->image;
+ grBitmap* source = &surface->root.bitmap;
+ byte* write = (byte*)target->buffer + y*target->pitch + 3*x;
+ byte* read = (byte*)source->buffer + y*source->pitch + x;
+
+ while (h > 0)
+ {
+ byte* _write = write;
+ byte* _read = read;
+ byte* limit = _write + 3*w;
+
+ for ( ; _write < limit; _write += 3, _read++ )
+ {
+ byte color = *_read;
+
+ _write[0] =
+ _write[1] =
+ _write[2] = color;
+ }
+
+ write += target->pitch;
+ read += source->pitch;
+ h--;
+ }
+ }
+
+
+ static
+ void convert_gray_to_32( grXSurface* surface,
+ int x,
+ int y,
+ int w,
+ int h )
+ {
+ grBitmap* target = &surface->image;
+ grBitmap* source = &surface->root.bitmap;
+ byte* write = (byte*)target->buffer + y*target->pitch + 4*x;
+ byte* read = (byte*)source->buffer + y*source->pitch + x;
+
+ while (h > 0)
+ {
+ byte* _write = write;
+ byte* _read = read;
+ byte* limit = _write + 4*w;
+
+ for ( ; _write < limit; _write += 4, _read++ )
+ {
+ byte color = *_read;
+
+ _write[0] =
+ _write[1] =
+ _write[2] =
+ _write[3] = color;
+ }
+
+ write += target->pitch;
+ read += source->pitch;
+ h--;
+ }
+ }
+
+
+ static
+ void convert_rectangle( grXSurface* surface,
+ int x,
+ int y,
+ int w,
+ int h )
+ {
+ int z;
+
+ /* first of all, clip to the surface's area */
+ if ( x >= surface->image.width ||
+ x+w <= 0 ||
+ y >= surface->image.rows ||
+ y+h <= 0 )
+ return;
+
+ if ( x < 0 )
+ {
+ w += x;
+ x = 0;
+ }
+
+ z = (x + w) - surface->image.width;
+ if (z > 0)
+ w -= z;
+
+ z = (y + h) - surface->image.rows;
+ if (z > 0)
+ h -= z;
+
+ /* convert the rectangle to the target depth for gray surfaces */
+ if (surface->gray)
+ {
+ switch (surface->depth)
+ {
+ case 8 : convert_gray_to_pal8( surface, x, y, w, h ); break;
+ case 16: convert_gray_to_16 ( surface, x, y, w, h ); break;
+ case 24: convert_gray_to_24 ( surface, x, y, w, h ); break;
+ case 32: convert_gray_to_32 ( surface, x, y, w, h ); break;
+ }
+ }
+ }
+
+
+ static
+ void refresh_rectangle( grXSurface* surface,
+ int x,
+ int y,
+ int w,
+ int h )
+ {
+ if (surface->gray)
+ convert_rectangle( surface, x, y, w, h );
+
+ XPutImage( display,
+ surface->win,
+ surface->gc,
+ surface->ximage,
+ x, y, x, y, w, h );
+ }
+
+
+ static
+ void set_title( grXSurface* surface,
+ const char* title )
+ {
+ XStoreName( display, surface->win, title );
+ }
+
+
+
+ static
+ grKey KeySymTogrKey( KeySym key )
+ {
+ grKey k;
+ int count = sizeof(key_translators)/sizeof(key_translators[0]);
+ Translator* trans = key_translators;
+ Translator* limit = trans + count;
+
+ k = grKeyNone;
+
+ while ( trans < limit )
+ {
+ if ( trans->xkey == key )
+ {
+ k = trans->grkey;
+ break;
+ }
+ trans++;
+ }
+
+ return k;
+ }
+
+
+
+ static
+ void listen_event( grXSurface* surface,
+ int event_mask,
+ grEvent* grevent )
+ {
+ static char key_buffer[10];
+ static int key_cursor = 0;
+ static int key_number = 0;
+ static XEvent x_event;
+ KeySym key;
+
+ int bool_exit;
+ grKey grkey;
+
+ XComposeStatus compose;
+
+ /* XXXX : For now, ignore the event mask, and only exit when */
+ /* a key is pressed.. */
+ (void)event_mask;
+
+ bool_exit = key_cursor < key_number;
+
+ XDefineCursor( display, surface->win, idle );
+
+ while ( !bool_exit )
+ {
+ XNextEvent( display, &x_event );
+
+ switch ( x_event.type )
+ {
+ case KeyPress:
+ key_number = XLookupString( &x_event.xkey,
+ key_buffer,
+ sizeof ( key_buffer ),
+ &key,
+ &compose );
+ key_cursor = 0;
+
+ if ( key_number == 0 ||
+ key > 512 )
+ {
+ /* this may be a special key like F1, F2, etc.. */
+ grkey = KeySymTogrKey(key);
+ if (grkey != grKeyNone)
+ goto Set_Key;
+ }
+ else
+ bool_exit = 1;
+ break;
+
+ case MappingNotify:
+ XRefreshKeyboardMapping( &x_event.xmapping );
+ break;
+
+ case Expose:
+ refresh_rectangle( surface,
+ x_event.xexpose.x,
+ x_event.xexpose.y,
+ x_event.xexpose.width,
+ x_event.xexpose.height );
+ break;
+
+ /* You should add more cases to handle mouse events, etc. */
+ }
+ }
+
+ XDefineCursor( display, surface->win, busy );
+ XFlush ( display );
+
+ /* Now, translate the keypress to a grKey */
+ /* If this wasn't part of the simple translated keys, simply get the charcode */
+ /* from the character buffer */
+ grkey = grKEY(key_buffer[key_cursor++]);
+
+ Set_Key:
+ grevent->type = gr_key_down;
+ grevent->key = grkey;
+ }
+
+
+
+
+ grXSurface* init_surface( grXSurface* surface,
+ grBitmap* bitmap )
+ {
+ int screen;
+ grBitmap* image;
+ char grays;
+ XDepth* format;
+ int image_depth;
+
+ screen = DefaultScreen( display );
+
+ surface->colormap = DefaultColormap( display, screen );
+ surface->depth = DefaultDepth( display, screen );
+ surface->visual = DefaultVisual( display, screen );
+
+ image = &surface->image;
+
+ /* force the surface image depth to 1 if necessary */
+ /* as this should be supported by all windows */
+ image_depth = surface->depth;
+ if (bitmap->mode == gr_pixel_mode_mono)
+ image_depth = 1;
+
+ grays = ( bitmap->mode == gr_pixel_mode_gray &&
+ bitmap->grays >= 2 );
+
+ surface->gray = grays;
+
+ /* copy dimensions */
+ image->width = bitmap->width;
+ image->rows = bitmap->rows;
+ image->mode = bitmap->mode;
+ image->pitch = 0;
+ image->grays = 0;
+ image->buffer = 0;
+
+ /* find the supported format corresponding to the request */
+ format = 0;
+
+ if (grays)
+ {
+ /* choose the default depth in case of grays rendering */
+ int i;
+ for ( i = 0; i < num_pixel_modes; i++ )
+ if ( image_depth == pixel_depth[i].depth )
+ {
+ format = pixel_depth + i;
+ break;
+ }
+ }
+ else
+ {
+ /* otherwise, select the format depending on the pixel mode */
+ int i;
+
+ format = 0;
+ for ( i = 0; i < num_pixel_modes; i++ )
+ if ( pixel_modes[i] == bitmap->mode )
+ {
+ format = pixel_depth + i;
+ break;
+ }
+ }
+
+ if (!format)
+ {
+ grError = gr_err_bad_argument;
+ return 0;
+ }
+
+
+ /* correct surface.depth. This is required because in the case */
+ /* of 32-bits pixels, the value of "format.depth" is 24 under X11 */
+ if ( format->depth == 24 &&
+ format->bits_per_pixel == 32 )
+ image_depth = 32;
+
+ /* allocate surface image */
+ {
+ int bits, over;
+
+ bits = image->width * format->bits_per_pixel;
+ over = bits % format->scanline_pad;
+
+ if (over)
+ bits += format->scanline_pad - over;
+
+ if (!grays)
+ {
+ image->width = bits;
+ bitmap->width = bits;
+ }
+ image->pitch = bits >> 3;
+ }
+
+ image->buffer = grAlloc( image->pitch * image->rows );
+ if (!image->buffer) return 0;
+
+ /* now, allocate a gray pal8 pixmap, only when we asked */
+ /* for an 8-bit pixmap */
+ if ( grays )
+ {
+ /* pad pitch to 32 bits */
+ bitmap->pitch = (bitmap->width + 3) & -4;
+ bitmap->buffer = grAlloc( bitmap->pitch * bitmap->rows );
+ if (!bitmap->buffer)
+ Panic( "grX11: could not allocate surface bitmap!\n" );
+ }
+ else /* otherwise */
+ {
+ *bitmap = *image;
+ }
+
+ surface->root.bitmap = *bitmap;
+
+ /* Now create the surface X11 image */
+ surface->ximage = XCreateImage( display,
+ surface->visual,
+ format->depth,
+ format->depth == 1 ? XYBitmap : ZPixmap,
+ 0,
+ (char*)image->buffer,
+ image->width,
+ image->rows,
+ 8,
+ 0 );
+ if ( !surface->ximage )
+ Panic( "grX11: cannot create surface X11 image\n" );
+
+
+ /* allocate gray levels in the case of gray surface */
+ if ( grays )
+ {
+ XColor* color = surface->color;
+ int i;
+
+ for ( i = 0; i < bitmap->grays; i++, color++ )
+ {
+ color->red =
+ color->green =
+ color->blue = 65535 - ( i * 65535 ) / bitmap->grays;
+
+ if ( !XAllocColor( display, surface->colormap, color ) )
+ Panic( "ERROR: cannot allocate Color\n" );
+ }
+ }
+ else if ( image_depth == 1 )
+ {
+ surface->ximage->byte_order = MSBFirst;
+ surface->ximage->bitmap_bit_order = MSBFirst;
+ }
+
+ {
+ XTextProperty xtp;
+ XSizeHints xsh;
+ XSetWindowAttributes xswa;
+
+ xswa.border_pixel = BlackPixel( display, screen );
+ xswa.background_pixel = WhitePixel( display, screen );
+ xswa.cursor = busy;
+
+ xswa.event_mask = KeyPressMask | ExposureMask;
+
+ surface->win = XCreateWindow( display,
+ RootWindow( display, screen ),
+ 0,
+ 0,
+ image->width,
+ image->rows,
+ 10,
+ surface->depth,
+ InputOutput,
+ surface->visual,
+ CWBackPixel | CWBorderPixel |
+ CWEventMask | CWCursor,
+ &xswa );
+
+ XMapWindow( display, surface->win );
+
+ surface->gc = XCreateGC( display, RootWindow( display, screen ), 0L, NULL );
+ XSetForeground( display, surface->gc, xswa.border_pixel );
+ XSetBackground( display, surface->gc, xswa.background_pixel );
+
+
+ /* make window manager happy :-) */
+ xtp.value = (unsigned char*)"FreeType";
+ xtp.encoding = 31;
+ xtp.format = 8;
+ xtp.nitems = strlen( (char*)xtp.value );
+
+ xsh.x = 0;
+ xsh.y = 0;
+
+ xsh.width = image->width;
+ xsh.height = image->rows;
+ xsh.flags = (PPosition | PSize);
+ xsh.flags = 0;
+
+ XSetWMProperties( display, surface->win, &xtp, &xtp, NULL, 0, &xsh, NULL, NULL );
+ }
+
+ surface->root.done = (grDoneSurfaceFunc) done_surface;
+ surface->root.refresh_rect = (grRefreshRectFunc) refresh_rectangle;
+ surface->root.set_title = (grSetTitleFunc) set_title;
+ surface->root.listen_event = (grListenEventFunc) listen_event;
+
+ convert_rectangle( surface, 0, 0, bitmap->width, bitmap->rows );
+ return surface;
+ }
+
+
+
+
+ grDevice gr_x11_device =
+ {
+ sizeof( grXSurface ),
+ "x11",
+
+ init_device,
+ done_device,
+
+ (grDeviceInitSurfaceFunc) init_surface,
+
+ 0,
+ 0
+
+ };
+
+#ifdef TEST
+
+typedef struct grKeyName
+{
+ grKey key;
+ const char* name;
+
+} grKeyName;
+
+
+static
+const grKeyName key_names[] =
+{
+ { grKeyF1, "F1" },
+ { grKeyF2, "F2" },
+ { grKeyF3, "F3" },
+ { grKeyF4, "F4" },
+ { grKeyF5, "F5" },
+ { grKeyF6, "F6" },
+ { grKeyF7, "F7" },
+ { grKeyF8, "F8" },
+ { grKeyF9, "F9" },
+ { grKeyF10, "F10" },
+ { grKeyF11, "F11" },
+ { grKeyF12, "F12" },
+ { grKeyEsc, "Esc" },
+ { grKeyHome, "Home" },
+ { grKeyEnd, "End" },
+
+ { grKeyPageUp, "Page_Up" },
+ { grKeyPageDown, "Page_Down" },
+ { grKeyLeft, "Left" },
+ { grKeyRight, "Right" },
+ { grKeyUp, "Up" },
+ { grKeyDown, "Down" },
+ { grKeyBackSpace, "BackSpace" },
+ { grKeyReturn, "Return" }
+};
+
+int main( void )
+{
+ grSurface* surface;
+ int n;
+
+ grInit();
+ surface = grNewScreenSurface( 0, gr_pixel_mode_gray, 320, 400, 128 );
+ if (!surface)
+ Panic("Could not create window\n" );
+ else
+ {
+ grColor color;
+ grEvent event;
+ const char* string;
+ int x;
+
+ grSetSurfaceRefresh( surface, 1 );
+ grSetTitle(surface,"X11 driver demonstration" );
+
+ for ( x = -10; x < 10; x++ )
+ {
+ for ( n = 0; n < 128; n++ )
+ {
+ color.value = (n*3) & 127;
+ grWriteCellChar( surface,
+ x + ((n % 60) << 3),
+ 80 + (x+10)*8*3 + ((n/60) << 3), n, color );
+ }
+
+ }
+ color.value = 64;
+ grWriteCellString( surface, 0, 0, "just an example", color );
+
+ do
+ {
+ listen_event((grXSurface*)surface, 0, &event);
+
+ /* return if ESC was pressed */
+ if ( event.key == grKeyEsc )
+ return 0;
+
+ /* otherwise, display key string */
+ color.value = (color.value + 8) & 127;
+ {
+ int count = sizeof(key_names)/sizeof(key_names[0]);
+ grKeyName* name = key_names;
+ grKeyName* limit = name + count;
+ const char* kname = 0;
+ char kname_temp[16];
+
+ while (name < limit)
+ {
+ if ( name->key == event.key )
+ {
+ kname = name->name;
+ break;
+ }
+ name++;
+ }
+
+ if (!kname)
+ {
+ sprintf( kname_temp, "char '%c'", (char)event.key );
+ kname = kname_temp;
+ }
+
+ grWriteCellString( surface, 30, 30, kname, color );
+ grRefreshSurface(surface);
+ paint_rectangle( surface, 0, 0, surface->bitmap.width, surface->bitmap.rows );
+ }
+ } while (1);
+ }
+
+ return 0;
+
+
+}
+#endif /* TEST */
+
--- /dev/null
+++ b/demos/graph/x11/grx11.h
@@ -1,0 +1,24 @@
+#ifndef GRX11_H
+#define GRX11_H
+
+#include "grobjs.h"
+#include "grdevice.h"
+
+ extern
+ grDevice gr_x11_device;
+
+#ifdef GR_INIT_BUILD
+ static
+ grDeviceChain gr_x11_device_chain =
+ {
+ "x11",
+ &gr_x11_device,
+ GR_INIT_DEVICE_CHAIN
+ };
+
+#undef GR_INIT_DEVICE_CHAIN
+#define GR_INIT_DEVICE_CHAIN &gr_x11_device_chain
+
+#endif /* GR_INIT_BUILD */
+
+#endif /* GRX11_H */
--- /dev/null
+++ b/demos/graph/x11/rules.mk
@@ -1,0 +1,81 @@
+#**************************************************************************
+#*
+#* X11-specific rules files, used to compile the X11 graphics driver
+#* when supported by the current platform
+#*
+#**************************************************************************
+
+#########################################################################
+#
+# Try to detect an X11 setup.
+#
+# We simply try to detect a `X11R6/bin', `X11R5/bin' or `X11/bin' in
+# the current path.
+#
+ifneq ($(findstring X11R6$(SEP)bin,$(PATH)),)
+xversion := X11R6
+else
+
+ifneq ($(findstring X11R5$(SEP)bin,$(PATH)),)
+xversion := X11R5
+else
+
+ifneq ($(findstring X11$(SEP)bin,$(PATH)),)
+xversion := X11
+endif
+endif
+endif
+
+ifdef xversion
+X11_PATH := $(subst ;, ,$(PATH)) $(subst :, ,$(PATH))
+X11_PATH := $(filter %$(xversion)$(SEP)bin,$(X11_PATH))
+X11_PATH := $(X11_PATH:%$(SEP)bin=%)
+endif
+
+##########################################################################
+#
+# Update some variables to compile the X11 graphics module. Note that
+# X11 is available on Unix, or on OS/2. However, it only compiles with
+# gcc on the latter platform, which is why it is safe to use the flags
+# `-L' and `-l'
+#
+ifneq ($(X11_PATH),)
+
+X11_INCLUDE := $(X11_PATH:%=%$(SEP)include)
+X11_LIB := $(X11_PATH:%=%$(SEP)lib)
+
+# the GRAPH_LINK variable is expanded each time an executable is linked against
+# the graphics library..
+#
+GRAPH_LINK += $(X11_LIB:%=-L%) -lX11
+
+# Solaris needs a -lsocket in GRAPH_LINK ..
+#
+UNAME := $(shell uname)
+ifneq ($(findstring $(UNAME),SunOS Solaris),)
+GRAPH_LINK += -lsocket
+endif
+
+
+# add the X11 driver object file to the graphics library
+#
+GRAPH_OBJS += $(OBJ_)grx11.$O
+
+
+
+GR_X11 := $(GRAPH_)x11
+GR_X11_ := $(GR_X11)$(SEP)
+
+DEVICES += X11
+DEVICE_INCLUDES += $(GR_X11)
+
+# the rule used to compile the X11 driver
+#
+$(OBJ_)grx11.$O: $(GR_X11_)grx11.c $(GR_X11_)grx11.h
+ $(CC) $(CFLAGS) $(GRAPH_INCLUDES:%=$I%) $I$(GR_X11) \
+ $(X11_INCLUDE:%=$I%) $T$@ $<
+endif
+
+
+
+