#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define INCL_DOS
#define INCL_WIN
#define INCL_GPI
#define INCL_SUB
#include <os2.h>
#include "gdriver.h"
#include "gevents.h"
#include "gmain.h"
#define VIO_WIDTH 640u
#define VIO_HEIGHT 360u
#define MAG_WIDTH VIO_WIDTH
#define MAG_HEIGHT 120u
#define MAX_MAG 16
typedef struct _Translator
{
char key;
GEvent event_class;
int event_info;
} Translator;
#define NUM_Translators 20
static const Translator trans[NUM_Translators] =
{
{ (char)27, event_Quit, 0 },
{ 'q', event_Quit, 0 },
{ 'x', event_Rotate_Glyph, -1 },
{ 'c', event_Rotate_Glyph, 1 },
{ 'v', event_Rotate_Glyph, -16 },
{ 'b', event_Rotate_Glyph, 16 },
{ '{', event_Change_Glyph, -10000 },
{ '}', event_Change_Glyph, 10000 },
{ '(', event_Change_Glyph, -1000 },
{ ')', event_Change_Glyph, 1000 },
{ '9', event_Change_Glyph, -100 },
{ '0', event_Change_Glyph, 100 },
{ 'i', event_Change_Glyph, -10 },
{ 'o', event_Change_Glyph, 10 },
{ 'k', event_Change_Glyph, -1 },
{ 'l', event_Change_Glyph, 1 },
{ '+', event_Scale_Glyph, 10 },
{ '-', event_Scale_Glyph, -10 },
{ 'u', event_Scale_Glyph, 1 },
{ 'j', event_Scale_Glyph, -1 }
};
static HAB habt;
static HAB hab;
static HWND hwndFrame, hwndClient;
static HWND hwndTitle;
static HDC hdcMemory;
static HPS hpsMemory = (HPS) NULL;
TID MessageThread;
HMTX hmtxPSMemoryLock;
HEV hevKeyLock;
static PBITMAPINFO2 pbmi;
static HBITMAP hbm;
BYTE Bitmap[VIO_WIDTH * VIO_HEIGHT];
BOOL ready = FALSE;
POINTL aptlFull[4] = {{ 0u, MAG_HEIGHT },
{ VIO_WIDTH, VIO_HEIGHT + MAG_HEIGHT },
{ 0u, 0u },
{ VIO_WIDTH, VIO_HEIGHT }};
POINTL aptlMagd[4] = {{ 0u, 0u },
{ MAG_WIDTH, MAG_HEIGHT },
{ 0u, 0u },
{ VIO_WIDTH, VIO_HEIGHT }};
static int magnification=1;
static POINTL view_target = {0, 0};
static SIZEL mag_win_size;
TEvent ourevent = { event_Rotate_Glyph, 0 };
int Colourmode;
extern char Header[];
void RunPMWindow( ULONG );
MRESULT EXPENTRY Message_Process( HWND, ULONG, MPARAM, MPARAM );
int Driver_Restore_Mode()
{
if ( hwndFrame )
WinDestroyWindow( hwndFrame );
WinReleasePS( hpsMemory );
WinTerminate( habt );
return 1;
}
int Driver_Set_Graphics( int mode )
{
LONG palette[5];
int x;
POINTL coords;
SIZEL sizl = { 0, 0 };
PTIB thread_block;
PPIB process_block;
DosGetInfoBlocks( &thread_block, &process_block );
process_block->pib_ultype = 3;
Colourmode = mode;
DosCreateEventSem( NULL, &hevKeyLock, 0, TRUE );
DosCreateMutexSem( NULL, &hmtxPSMemoryLock, 0, FALSE );
DosCreateThread( &MessageThread, (PFNTHREAD)RunPMWindow, 0UL, 0UL, 32920 );
habt = WinInitialize( 0 );
hdcMemory = DevOpenDC( hab, OD_MEMORY, (PSZ)"*", 0L, 0L, 0L );
DosRequestMutexSem( hmtxPSMemoryLock, SEM_INDEFINITE_WAIT );
hpsMemory = GpiCreatePS(
habt, hdcMemory, &sizl,
PU_PELS | GPIT_MICRO | GPIA_ASSOC | GPIF_DEFAULT );
GpiSetBackMix( hpsMemory, BM_OVERPAINT );
DosAllocMem( (PPVOID)&pbmi,
sizeof ( BITMAPINFO2 ) + sizeof ( RGB2 ) * 256,
PAG_COMMIT | PAG_READ | PAG_WRITE);
memset( pbmi, 0, sizeof ( BITMAPINFO2 ) + sizeof ( RGB2 ) * 256 );
pbmi->cbFix = sizeof ( BITMAPINFOHEADER2 );
pbmi->cx = VIO_WIDTH;
pbmi->cy = VIO_HEIGHT;
pbmi->cPlanes = 1;
switch ( mode )
{
case Graphics_Mode_Mono:
pbmi->cBitCount = 1;
break;
case Graphics_Mode_Gray:
pbmi->cBitCount = 8;
break;
}
hbm = GpiCreateBitmap( hpsMemory, (PBITMAPINFOHEADER2)pbmi,
0L, NULL, NULL );
GpiSetBitmap( hpsMemory, hbm );
pbmi->cbFix = sizeof ( BITMAPINFOHEADER2 );
GpiQueryBitmapInfoHeader( hbm, (PBITMAPINFOHEADER2) pbmi );
switch ( mode )
{
case Graphics_Mode_Mono:
DosReleaseMutexSem( hmtxPSMemoryLock );
vio_ScanLineWidth = VIO_WIDTH / 8;
vio_Width = VIO_WIDTH;
vio_Height = VIO_HEIGHT;
gray_palette[0] = 0;
break;
case Graphics_Mode_Gray:
vio_ScanLineWidth = VIO_WIDTH;
vio_Width = VIO_WIDTH;
vio_Height = VIO_HEIGHT;
palette[0] = 0xffffffL;
palette[1] = 0xbbbbbbL;
palette[2] = 0x777777L;
palette[3] = 0x333333L;
palette[4] = 0L;
GpiCreateLogColorTable( hpsMemory, (ULONG)LCOL_PURECOLOR,
(LONG)LCOLF_CONSECRGB, (LONG)0L,
(LONG)5L, (PLONG)palette );
for (x = 0 ; x < 5 ; x++)
{
GpiSetColor( hpsMemory, (LONG)x );
coords.x = x;
coords.y = 0;
GpiSetPel( hpsMemory, &coords );
}
GpiQueryBitmapInfoHeader( hbm, (PBITMAPINFOHEADER2) pbmi );
GpiQueryBitmapBits( hpsMemory, 0L, (LONG)VIO_HEIGHT - 2,
&Bitmap[0], pbmi );
for ( x = 0; x < 5; x++ )
{
gray_palette[x] = Bitmap[x];
}
memset( &Bitmap[0], gray_palette[0], vio_Height * vio_ScanLineWidth );
DosReleaseMutexSem( hmtxPSMemoryLock );
break;
default:
return 0;
}
return 1;
}
int Driver_Display_Bitmap( char* buffer, int lines, int cols )
{
int y, target;
if ( (lines == vio_Height) & (cols == vio_ScanLineWidth) )
memcpy( &Bitmap[0], buffer, lines * cols );
else
{
memset( &Bitmap[0], gray_palette[0], vio_Height * vio_ScanLineWidth );
target = ( vio_Height - lines ) / 2 * vio_ScanLineWidth +
( vio_ScanLineWidth - cols ) / 2;
for ( y = 0 ; y < lines ; y++ )
{
memcpy( &Bitmap[target], buffer, cols );
target += vio_ScanLineWidth;
buffer += cols;
}
}
DosRequestMutexSem( hmtxPSMemoryLock, SEM_INDEFINITE_WAIT );
GpiSetBitmapBits( hpsMemory, 0L, (LONG)VIO_HEIGHT - 2, &Bitmap[0], pbmi );
DosReleaseMutexSem( hmtxPSMemoryLock );
ready = TRUE;
WinInvalidateRect( hwndClient, NULL, FALSE );
WinUpdateWindow( hwndFrame );
return 1;
}
void Get_Event( TEvent* event )
{
ULONG ulRequestCount;
DosWaitEventSem( hevKeyLock, SEM_INDEFINITE_WAIT );
DosQueryEventSem( hevKeyLock, &ulRequestCount );
DosResetEventSem( hevKeyLock, &ulRequestCount );
event->what = ourevent.what;
event->info = ourevent.info;
return;
}
void RunPMWindow( ULONG dummy )
{
unsigned char classname[] = "DisplayClass";
ULONG flClassFlags;
static HMQ hmq;
QMSG qmsg;
if ( (hab = WinInitialize( 0 )) == 0 )
{
printf( "Error doing WinInitialize()\n" );
return;
}
if ( (hmq = WinCreateMsgQueue( hab, 0 )) == (HMQ)NULL )
{
printf( "Error doing WinCreateMsgQueue()\n" );
return;
}
if ( !WinRegisterClass( hab, (PSZ)classname, (PFNWP)Message_Process,
CS_SIZEREDRAW, 0 ) )
{
printf( "Error doing WinRegisterClass()\n" );
return;
}
flClassFlags = FCF_TITLEBAR | FCF_MINBUTTON | FCF_DLGBORDER |
FCF_TASKLIST | FCF_SYSMENU;
if ( (hwndFrame = WinCreateStdWindow( HWND_DESKTOP,
WS_VISIBLE,
&flClassFlags,
(PSZ)classname,
(PSZ)"FreeType PM Graphics",
WS_VISIBLE,
0, 0, &hwndClient )) == 0 )
{
printf( "Error doing WinCreateStdWindow()\n" );
return;
}
hwndTitle = WinWindowFromID( hwndFrame, FID_TITLEBAR );
WinSetWindowPos(
hwndFrame, 0L,
(SHORT)60,
(SHORT)WinQuerySysValue( HWND_DESKTOP, SV_CYSCREEN ) -
( VIO_HEIGHT + MAG_HEIGHT + 100 ),
(SHORT)WinQuerySysValue( HWND_DESKTOP, SV_CYDLGFRAME ) * 2 +
VIO_WIDTH,
(SHORT)WinQuerySysValue( HWND_DESKTOP, SV_CYTITLEBAR ) +
WinQuerySysValue( HWND_DESKTOP, SV_CYDLGFRAME ) * 2 +
VIO_HEIGHT + MAG_HEIGHT,
SWP_SIZE | SWP_MOVE ) ;
while ( WinGetMsg( hab, &qmsg, (HWND)NULL, 0, 0 ) )
WinDispatchMsg( hab, &qmsg );
WinDestroyWindow( hwndFrame );
hwndFrame = (HWND)NULL;
WinDestroyMsgQueue( hmq );
WinTerminate( hab );
while ( 1 )
DosSleep( 100 );
}
void Adjust_Mag_Rectangle( void )
{
SIZEL source,
target;
source.cx = mag_win_size.cx / magnification;
if (source.cx > vio_Width) source.cx = vio_Width;
source.cy = mag_win_size.cy / magnification;
if (source.cy > vio_Height) source.cy = vio_Height;
target.cx = source.cx * magnification;
target.cy = source.cy * magnification;
aptlMagd[0].x = (mag_win_size.cx - target.cx) / 2;
aptlMagd[0].y = (mag_win_size.cy - target.cy) / 2;
aptlMagd[1].x = aptlMagd[0].x + target.cx - 1;
aptlMagd[1].y = aptlMagd[0].x + target.cy - 1;
aptlMagd[2].x = view_target.x - source.cx / 2;
aptlMagd[2].y = view_target.y - source.cy / 2;
if (aptlMagd[2].x < 0 ) aptlMagd[2].x = 0;
if (aptlMagd[2].y < 0 ) aptlMagd[2].y = 0;
if (aptlMagd[2].x > vio_Width - source.cx)
aptlMagd[2].x = vio_Width - source.cx;
if (aptlMagd[2].y > vio_Height - source.cy)
aptlMagd[2].y = vio_Height - source.cy;
aptlMagd[3].x = aptlMagd[2].x + source.cx - 1;
aptlMagd[3].y = aptlMagd[2].y + source.cy - 1;
}
MRESULT EXPENTRY Message_Process( HWND handle, ULONG mess,
MPARAM parm1, MPARAM parm2 )
{
static HDC hdc;
static HPS hps;
static BOOL minimized;
POINTL top_corner, bottom_corner;
SWP swp;
int i;
switch( mess )
{
case WM_DESTROY:
ourevent.what = event_Quit;
ourevent.info = 0;
DosPostEventSem( hevKeyLock );
break;
case WM_CREATE:
magnification = 4;
minimized = FALSE;
hdc = WinOpenWindowDC( handle );
mag_win_size.cx = 0;
mag_win_size.cy = 0;
hps = GpiCreatePS( hab, hdc, &mag_win_size,
PU_PELS | GPIT_MICRO | GPIA_ASSOC | GPIF_DEFAULT );
mag_win_size.cx = MAG_WIDTH;
mag_win_size.cy = MAG_HEIGHT;
Adjust_Mag_Rectangle();
WinFocusChange( HWND_DESKTOP, handle, 0L );
break;
case WM_BUTTON1DOWN:
if ( MOUSEMSG( &mess )->y >= MAG_HEIGHT )
{
view_target.x = MOUSEMSG( &mess )->x;
view_target.y = MOUSEMSG( &mess )->y - MAG_HEIGHT;
Adjust_Mag_Rectangle();
WinInvalidateRect( hwndClient, NULL, FALSE );
}
return WinDefWindowProc( handle, mess, parm1, parm2 );
break;
case WM_MINMAXFRAME:
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:
if ( !minimized )
WinSetWindowText( hwndTitle, Header );
DosRequestMutexSem( hmtxPSMemoryLock, SEM_INDEFINITE_WAIT );
WinBeginPaint( handle, hps, NULL );
GpiBitBlt( hps, hpsMemory, 4L, aptlFull, ROP_SRCCOPY, BBO_AND );
GpiBitBlt( hps, hpsMemory, 4L, aptlMagd, ROP_SRCCOPY, BBO_AND );
if ( magnification != 1 )
{
GpiSetLineType( hps, LINETYPE_LONGDASH );
bottom_corner.x = aptlMagd[2].x - 1;
bottom_corner.y = aptlMagd[2].y + MAG_HEIGHT - 1;
top_corner.x = aptlMagd[3].x ;
top_corner.y = aptlMagd[3].y + MAG_HEIGHT;
GpiMove( hps, &bottom_corner );
GpiBox( hps, DRO_OUTLINE, &top_corner, 0L, 0L );
#if 0
GpiSetClipRegion();
GpiErase();
#endif
}
WinEndPaint( hps );
DosReleaseMutexSem( hmtxPSMemoryLock );
break;
case WM_CHAR:
if ( CHARMSG( &mess )->fs & KC_KEYUP )
break;
switch ( CHARMSG( &mess )->vkey )
{
case VK_ESC:
ourevent.what = event_Quit;
ourevent.info = 0;
DosPostEventSem( hevKeyLock );
break;
case VK_PAGEDOWN:
if ( magnification < MAX_MAG )
{
magnification += 1;
Adjust_Mag_Rectangle();
WinInvalidateRect( handle, NULL, FALSE );
}
break;
case VK_PAGEUP:
if ( magnification > 1 )
{
magnification -= 1;
Adjust_Mag_Rectangle();
WinInvalidateRect( handle, NULL, FALSE );
}
break;
case VK_LEFT:
if ( view_target.x > 0 )
{
view_target.x -= 1;
Adjust_Mag_Rectangle();
WinInvalidateRect( handle, NULL, FALSE );
}
break;
case VK_RIGHT:
if ( view_target.x < VIO_WIDTH - 1 )
{
view_target.x += 1;
Adjust_Mag_Rectangle();
WinInvalidateRect( handle, NULL, FALSE );
}
break;
case VK_DOWN:
if ( view_target.y > 0 )
{
view_target.y -= 1;
Adjust_Mag_Rectangle();
WinInvalidateRect( handle, NULL, FALSE );
}
break;
case VK_UP:
if ( view_target.y < VIO_HEIGHT - 1 )
{
view_target.y += 1;
Adjust_Mag_Rectangle();
WinInvalidateRect( handle, NULL, FALSE );
}
break;
case VK_F1:
break;
}
if ( CHARMSG( &mess )->fs & KC_CHAR )
{
char c = (CHAR)CHARMSG( &mess )->chr ;
for ( i = 0; i < NUM_Translators; i++ )
{
if ( c == trans[i].key )
{
ourevent.what = trans[i].event_class;
ourevent.info = trans[i].event_info;
DosPostEventSem( hevKeyLock );
return (MRESULT)TRUE;
}
}
ourevent.what = event_Keyboard;
ourevent.info = (int)c;
DosPostEventSem( hevKeyLock );
}
break;
default:
return WinDefWindowProc( handle, mess, parm1, parm2 );
}
return (MRESULT) FALSE;
}