parent
cb58dbb4fb
commit
1631d04827
7 changed files with 0 additions and 1855 deletions
@ -1,754 +0,0 @@ |
||||
#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 |
||||
|
||||
}; |
||||
|
||||
|
@ -1,5 +0,0 @@ |
||||
NAME WINDOWCOMPAT |
||||
|
||||
DESCRIPTION 'FreeType Graphics' |
||||
HEAPSIZE 8192 |
||||
STACKSIZE 40888 |
@ -1,23 +0,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 */ |
@ -1,32 +0,0 @@ |
||||
#**************************************************************************
|
||||
#*
|
||||
#* OS/2 specific rules file, used to compile the OS/2 graphics driver
|
||||
#* to the graphics subsystem
|
||||
#*
|
||||
#**************************************************************************
|
||||
|
||||
ifeq ($(PLATFORM),os2) |
||||
|
||||
GR_OS2 := config$(SEP)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 |
||||
|
||||
|
@ -1,936 +0,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 */ |
||||
|
@ -1,24 +0,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 */ |
@ -1,81 +0,0 @@ |
||||
#**************************************************************************
|
||||
#*
|
||||
#* 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 := config$(SEP)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 |
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in new issue