Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/* Copyright (C) 1994 Aladdin Enterprises.  All rights reserved.
2
 
3
  This software is provided AS-IS with no warranty, either express or
4
  implied.
5
 
6
  This software is distributed under license and may not be copied,
7
  modified or distributed except as expressly authorized under the terms
8
  of the license contained in the file LICENSE in this distribution.
9
 
10
  For more information about licensing, please refer to
11
  http://www.ghostscript.com/licensing/. For information on
12
  commercial licensing, go to http://www.artifex.com/licensing/ or
13
  contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14
  San Rafael, CA  94903, U.S.A., +1(415)492-9861.
15
*/
16
 
17
/* $Id: gspmdrv.c,v 1.4 2002/02/21 22:24:52 giles Exp $ */
18
/* Presentation Manager driver for Ghostscript */
19
/* Written by Russell Lang */
20
 
21
/* To display output from os2pm driver: */
22
/*   gspmdrv -d id_string */
23
/* To display BMP file (used for testing display code) */
24
/*   gspmdrv -b filename.bmp */
25
 
26
#define INCL_DOS
27
#define INCL_WIN
28
#define INCL_GPI
29
#include <os2.h>
30
#include <stdio.h>
31
#include <stdlib.h>
32
#include <string.h>
33
#include <sys/emxload.h>
34
#include "gspmdrv.h"
35
#include "gdevpm.h"
36
 
37
#ifndef min
38
#define min(x,y)  ( (x) < (y) ? (x) : (y) )
39
#endif
40
#ifndef max
41
#define max(x,y)  ( (x) > (y) ? (x) : (y) )
42
#endif
43
 
44
HEV update_event_sem;
45
HMTX bmp_mutex_sem;
46
 
47
/* bitmap details */
48
typedef struct tagBM {
49
    BOOL valid;
50
    BOOL old_bmp;		/* bitmap type */
51
    PBITMAPINFO2 pbmi;		/* pointer to bitmap info */
52
    PBYTE bits;			/* pointer to bitmap bits */
53
    int width;
54
    int height;
55
    int planes;
56
    int depth;
57
    int palsize;
58
    int palimportant;
59
    int old_width;
60
    int old_height;
61
    int old_planes;
62
    int old_depth;
63
    int old_palsize;
64
    int old_palimportant;
65
} BMAP;
66
 
67
typedef struct tagDISPLAY {
68
    LONG planes;
69
    LONG bitcount;
70
    LONG hasPalMan;		/* Palette Manager */
71
    BOOL hpal_exists;
72
    HPAL hpal;
73
} DISPLAY;
74
 
75
/* options that are saved in INI file */
76
typedef struct tagOPTIONS {
77
    POINTL img_origin;
78
    POINTL img_size;
79
    BOOL img_max;
80
} OPTIONS;
81
 
82
#define CW_USEDEFAULT 32768
83
 
84
 
85
BMAP bitmap;
86
DISPLAY display;
87
OPTIONS option;
88
PBYTE bbuffer;			/* for BMP file display */
89
POINTL scroll_pos;		/* not used *//* not used */
90
ULONG os_version;
91
char *section = "Ghostscript Image";
92
 
93
HAB hab;			/* Anchor Block */
94
HWND hwnd_frame;
95
HWND hwnd_bmp;
96
HWND hwnd_gs;			/* window handle for CMD.EXE that started gs */
97
TID update_tid;
98
 
99
#define WM_GSUPDATE WM_USER+1
100
#define SB_TOP 20
101
#define SB_BOTTOM 21
102
 
103
 
104
MRESULT EXPENTRY ClientWndProc(HWND, ULONG, MPARAM, MPARAM);
105
MRESULT EXPENTRY AboutDlgProc(HWND, ULONG, MPARAM, MPARAM);
106
APIRET init_window(void);
107
void fix_sysmenu(HWND);
108
APIRET restore_window_position(SWP * pswp);
109
BOOL scan_bitmap(BMAP * pbm);
110
void read_profile(void);
111
void write_profile(void);
112
APIRET init_display(int argc, char *argv[]);
113
APIRET init_bitmap(int argc, char *argv[]);
114
void copy_clipboard(void);
115
HBITMAP make_bitmap(BMAP * pbm, ULONG left, ULONG bottom, ULONG right, ULONG top, ULONG depth);
116
 
117
void
118
debugbeep(int type)
119
{
120
#ifdef DEBUG
121
    int i;
122
 
123
/* current debug beeps are: */
124
/* 1. Null handle PS */
125
/* 2. make_bitmap() failed */
126
/* 3. GpiDrawBits() or WinDrawBitmap() failed */
127
/* 4. Null handle PS from WinBeginPaint() */
128
    for (i = 0; i < type; i++) {
129
	DosBeep(400 + 100 * type, 50);
130
	DosSleep(50);
131
    }
132
#endif
133
}
134
 
135
 
136
/* display message */
137
int
138
message_box(char *str, int icon)
139
{
140
    return WinMessageBox(HWND_DESKTOP, hwnd_frame ? hwnd_frame : HWND_DESKTOP,
141
			 str, "gspmdrv.exe", 0, icon | MB_MOVEABLE | MB_OK);
142
}
143
 
144
void 
145
error_message(char *str)
146
{
147
    WinMessageBox(HWND_DESKTOP, HWND_DESKTOP, str, "gspmdrv.exe", 0, MB_MOVEABLE | MB_ICONHAND | MB_OK);
148
    WinPostMsg(hwnd_frame, WM_QUIT, MPFROMLONG(0), MPFROMLONG(0));
149
}
150
 
151
/* Update thread */
152
/* This thread waits for the update event semaphore from gs.exe */
153
/* then generates a WM_PAINT message for the bitmap */
154
/* This thread must NOT call C library functions */
155
VOID APIENTRY 
156
update_func(ULONG unused)
157
{
158
    APIRET rc;
159
    BOOL flag;
160
    ULONG count;
161
 
162
    unused = unused;		/* to shut up warning */
163
    while (!DosQueryEventSem(update_event_sem, &count)) {
164
	/* loop while semaphore exists */
165
	DosWaitEventSem(update_event_sem, SEM_INDEFINITE_WAIT);
166
	DosResetEventSem(update_event_sem, &count);
167
	WinPostMsg(hwnd_bmp, WM_GSUPDATE, MPFROMLONG(0), MPFROMLONG(0));
168
    }
169
}
170
 
171
VOID APIENTRY 
172
exit_func(ULONG code)
173
{
174
    write_profile();
175
    DosCloseEventSem(update_event_sem);
176
    DosCloseMutexSem(bmp_mutex_sem);
177
    DosFreeMem((PVOID) bitmap.pbmi);
178
    DosExitList(EXLST_EXIT, 0);
179
    code = code;		/* to shut up warning */
180
}
181
 
182
void
183
find_hwnd_gs(char *gsid)
184
{
185
    ULONG ulCount;
186
    ULONG ulLength;
187
    ULONG pBase;
188
    ULONG cbBuf;
189
    PSWBLOCK pswblk;
190
    PSWENTRY pswentry;
191
    SWCNTRL *pswc;
192
    int i;
193
    ULONG pid;
194
    char buf[256];
195
    char *p, *s;
196
    PTIB pptib;
197
    PPIB pppib;
198
 
199
    /* extract gs pid from command line id */
200
    strcpy(buf, gsid);
201
    for (p = buf; *p && *p != '_'; p++);
202
    *p++ = '\0';
203
    s = p;
204
    for (p = buf; *p && *p != '_'; p++);
205
    *p = '\0';
206
    pid = atoi(s);		/* pid is Process ID of CMD.EXE that started gsos2.exe */
207
 
208
    ulCount = WinQuerySwitchList(hab, NULL, 0);		/* get num of items */
209
    cbBuf = (ulCount * sizeof(SWENTRY)) + sizeof(HSWITCH);
210
    pswblk = (PSWBLOCK) malloc(cbBuf + 32768);
211
    ulCount = WinQuerySwitchList(hab, pswblk, cbBuf);	/* get num of items */
212
    for (i = 0; i < ulCount; i++) {
213
	pswentry = &pswblk->aswentry[i];
214
	pswc = &pswentry->swctl;
215
	if (pid == pswc->idProcess)
216
	    hwnd_gs = pswc->hwnd;	/* save window handle */
217
    }
218
}
219
 
220
 
221
int
222
main(int argc, char *argv[])
223
{
224
    HMQ hand_mq;		/* message queue */
225
    QMSG q_mess;		/* message queue */
226
    APIRET rc = 0;
227
 
228
 
229
    hab = WinInitialize(0);	/* Get the Anchor Block */
230
 
231
    hand_mq = WinCreateMsgQueue(hab, 0);	/* start a queue */
232
 
233
    if (argc < 2) {
234
	rc = 1;
235
	error_message("Usage: gspmdrv -d id_string");
236
    }
237
    if (!rc) {
238
	if (strcmp(argv[1], "-d") == 0) {
239
	    rc = init_display(argc, argv);
240
	} else if (strcmp(argv[1], "-b") == 0) {
241
	    rc = init_bitmap(argc, argv);
242
	} else {
243
	    rc = 1;
244
	    error_message("Usage: gspmdrv -d id_string");
245
	}
246
    }
247
    if (!rc) {
248
	rc = DosCreateThread(&update_tid, update_func, 0, 0, 8192);
249
	if (rc)
250
	    error_message("Failed to create update thread");
251
    }
252
    if (!rc)
253
	rc = init_window();
254
 
255
    if (!rc)
256
	WinShowWindow(hwnd_frame, TRUE);
257
 
258
    if (!rc) {
259
	/* keep gspmdrv.exe in memory for number of minutes specified in */
260
	/* environment variable GS_LOAD */
261
	_emxload_env("GS_LOAD");
262
    }
263
    DosExitList(EXLST_ADD, exit_func);
264
 
265
    /* message loop */
266
    while (!rc && WinGetMsg(hab, &q_mess, 0L, 0, 0))
267
	WinDispatchMsg(hab, &q_mess);
268
 
269
    /* Shut down the application window and queue */
270
    DosKillThread(update_tid);
271
    WinDestroyWindow(hwnd_frame);
272
    WinDestroyMsgQueue(hand_mq);
273
    WinTerminate(hab);
274
    return rc;
275
}
276
 
277
APIRET
278
init_window()
279
{
280
    ULONG version[3];
281
    SWP swp;
282
    APIRET rc = 0;
283
    ULONG flFlags;		/* Window frame definition */
284
    unsigned char class[] = "gspmdrvClass";	/* class name */
285
 
286
    if (DosQuerySysInfo(QSV_VERSION_MAJOR, QSV_VERSION_REVISION, &version, sizeof(version)))
287
	os_version = 201000;	/* a guess */
288
    else {
289
	os_version = version[0] * 10000 + version[1] * 100 + version[2];
290
    }
291
 
292
    /* define the frame constants */
293
    flFlags = FCF_TITLEBAR |	/* have a title bar */
294
	FCF_SIZEBORDER |	/* have a sizeable window */
295
	FCF_MINMAX |		/* have a min and max button */
296
	FCF_SYSMENU |		/* include a system menu */
297
	FCF_VERTSCROLL |	/* vertical scroll bar */
298
	FCF_HORZSCROLL |	/* horizontal scroll bar */
299
	FCF_TASKLIST |		/* show it in window list */
300
	FCF_ICON;		/* Load icon from resources */
301
 
302
    /* save SHELL default size and location */
303
    rc = WinQueryTaskSizePos(hab, 0, &swp);
304
    if (rc)
305
	return rc;
306
 
307
    read_profile();
308
    if ((option.img_size.x == 0) || (option.img_size.y == 0))
309
	option.img_size.x = option.img_size.y = CW_USEDEFAULT;
310
 
311
    if (!rc) {
312
	HPS ps = WinGetPS(HWND_DESKTOP);
313
	HDC hdc = GpiQueryDevice(ps);
314
 
315
	DevQueryCaps(hdc, CAPS_COLOR_PLANES, 1, &display.planes);
316
	DevQueryCaps(hdc, CAPS_COLOR_BITCOUNT, 1, &display.bitcount);
317
	DevQueryCaps(hdc, CAPS_ADDITIONAL_GRAPHICS, 1, &display.hasPalMan);
318
	display.hasPalMan &= CAPS_PALETTE_MANAGER;
319
	WinReleasePS(ps);
320
    }
321
    if (!rc) {
322
	if (!WinRegisterClass(	/* register this window class */
323
				 hab,	/* anchor block */
324
				 (PSZ) class,	/* class name */
325
				 (PFNWP) ClientWndProc,		/* window function */
326
				 CS_SIZEREDRAW |	/* window style */
327
				 CS_MOVENOTIFY,
328
				 0))	/* no storage */
329
	    exit(1);
330
 
331
	hwnd_frame = WinCreateStdWindow(
332
					   HWND_DESKTOP,	/* window type */
333
					   0,	/* frame style is not WS_VISIBLE */
334
					   &flFlags,	/* definitions */
335
					   (PSZ) class,		/* client class */
336
					   (PSZ) "Ghostscript Image",	/* title */
337
					   WS_VISIBLE,	/* client style */
338
					   0,	/* resource module */
339
					   ID_GSPMDRV,	/* resource identifier */
340
					   &hwnd_bmp);	/* pointer to client */
341
 
342
	fix_sysmenu(hwnd_frame);
343
    }
344
    rc = restore_window_position(&swp);
345
 
346
    return rc;
347
}
348
 
349
 
350
void
351
write_profile(void)
352
{
353
    char profile[64];
354
 
355
    sprintf(profile, "%d %d", option.img_origin.x, option.img_origin.y);
356
    PrfWriteProfileString(HINI_USERPROFILE, section, "Origin", profile);
357
    sprintf(profile, "%d %d", option.img_size.x, option.img_size.y);
358
    PrfWriteProfileString(HINI_USERPROFILE, section, "Size", profile);
359
    sprintf(profile, "%d", option.img_max);
360
    PrfWriteProfileString(HINI_USERPROFILE, section, "Maximized", profile);
361
}
362
 
363
void
364
read_profile(void)
365
{
366
    char profile[64];
367
 
368
    PrfQueryProfileString(HINI_USERPROFILE, section, "Origin", "", profile, sizeof(profile));
369
    if (sscanf(profile, "%d %d", &option.img_origin.x, &option.img_origin.y) != 2) {
370
	option.img_origin.x = CW_USEDEFAULT;
371
	option.img_origin.y = CW_USEDEFAULT;
372
    }
373
    PrfQueryProfileString(HINI_USERPROFILE, section, "Size", "", profile, sizeof(profile));
374
    if (sscanf(profile, "%d %d", &option.img_size.x, &option.img_size.y) != 2) {
375
	option.img_size.x = CW_USEDEFAULT;
376
	option.img_size.y = CW_USEDEFAULT;
377
    }
378
    PrfQueryProfileString(HINI_USERPROFILE, section, "Maximized", "", profile, sizeof(profile));
379
    if (sscanf(profile, "%d", &option.img_max) != 1)
380
	option.img_max = 0;
381
}
382
 
383
void
384
fix_sysmenu(HWND hwnd)
385
{
386
    MENUITEM mi;
387
    HWND hwndSysMenu;
388
 
389
    if (!WinSendMsg(WinWindowFromID(hwnd, FID_SYSMENU), MM_QUERYITEM,
390
		    MPFROM2SHORT(SC_SYSMENU, TRUE), MPFROMP(&mi))) {
391
	message_box("failed getting system menu handle", 0);
392
	return;
393
    }
394
    hwndSysMenu = mi.hwndSubMenu;
395
    mi.iPosition = MIT_END;
396
    mi.afStyle = MIS_SEPARATOR;
397
    mi.afAttribute = 0;
398
    mi.id = 0;
399
    mi.hwndSubMenu = 0;
400
    mi.hItem = 0;
401
    WinSendMsg(hwndSysMenu, MM_INSERTITEM, MPFROMP(&mi), NULL);
402
    mi.afStyle = MIS_TEXT;
403
    mi.id = IDM_ABOUT;
404
    WinSendMsg(hwndSysMenu, MM_INSERTITEM, MPFROMP(&mi), "About...");
405
    mi.id = IDM_COPY;
406
    WinSendMsg(hwndSysMenu, MM_INSERTITEM, MPFROMP(&mi), "Copy");
407
}
408
 
409
APIRET
410
restore_window_position(SWP * pswp)
411
{
412
    SWP swp;
413
 
414
    swp.fl = SWP_MOVE | SWP_SIZE | SWP_SHOW;
415
 
416
    if (option.img_max) {
417
	/* Get maximized frame window position and size. */
418
	if (!WinGetMaxPosition(hwnd_frame, &swp))
419
	    return 1;
420
	swp.fl |= SWP_MAXIMIZE;
421
    } else if ((option.img_size.x != CW_USEDEFAULT) &&
422
	       (option.img_size.y != CW_USEDEFAULT) &&
423
	       (option.img_origin.y != CW_USEDEFAULT) &&
424
	       (option.img_origin.y != CW_USEDEFAULT)) {
425
	LONG cxClientMax;
426
	LONG cyClientMax;
427
	LONG cyTitleBar;
428
	LONG cxSizeBorder;
429
	LONG cySizeBorder;
430
 
431
	/* get maximum client window size */
432
	cxClientMax = WinQuerySysValue(HWND_DESKTOP, SV_CXFULLSCREEN);
433
	cyClientMax = WinQuerySysValue(HWND_DESKTOP, SV_CYFULLSCREEN);
434
	cyTitleBar = WinQuerySysValue(HWND_DESKTOP, SV_CYTITLEBAR);
435
	cxSizeBorder = WinQuerySysValue(HWND_DESKTOP, SV_CXSIZEBORDER);
436
	cySizeBorder = WinQuerySysValue(HWND_DESKTOP, SV_CYSIZEBORDER);
437
	cyClientMax += cyTitleBar;
438
 
439
	/* Make sure x origin is within display boundaries */
440
	swp.x = option.img_origin.x;
441
	if (swp.x < -cxSizeBorder)
442
	    swp.x = 0;
443
 
444
	/* Make sure window isn't too wide, or negative value */
445
	swp.cx = option.img_size.x;
446
	if (swp.cx >= cxClientMax || swp.cx < 0) {
447
	    swp.cx = cxClientMax;
448
	    swp.x = 0;
449
	}
450
	if ((swp.x + swp.cx) > (cxClientMax + cxSizeBorder))
451
	    swp.x = cxClientMax + cxSizeBorder - swp.cx;
452
 
453
	/* Make sure y origin is within display boundaries */
454
	swp.y = option.img_origin.y;
455
	if (swp.y < -cySizeBorder)
456
	    swp.y = 0;
457
 
458
	/* Make sure window isn't too high, or negative value */
459
	swp.cy = option.img_size.y;
460
	if (swp.cy > cyClientMax || swp.cy < 0) {
461
	    swp.cy = cyClientMax;
462
	    swp.y = 0;
463
	}
464
	if ((swp.y + swp.cy) > (cyClientMax + cySizeBorder))
465
	    swp.y = cyClientMax + cySizeBorder - swp.cy;
466
    } else {			/* No saved position -- use supplied position */
467
	swp = *pswp;
468
	option.img_origin.x = swp.x;
469
	option.img_origin.y = swp.y;
470
	option.img_size.x = swp.cx;
471
	option.img_size.y = swp.cy;
472
	option.img_max = FALSE;
473
	swp.fl = SWP_MOVE | SWP_SIZE | SWP_SHOW;
474
    }
475
 
476
    if (hwnd_gs)
477
	swp.fl |= SWP_ZORDER;
478
    /* Position and size this frame window */
479
    if (!WinSetWindowPos(hwnd_frame, hwnd_gs,
480
			 swp.x, swp.y, swp.cx, swp.cy, swp.fl))
481
	return 1;
482
    return 0;
483
}
484
 
485
APIRET 
486
init_display(int argc, char *argv[])
487
{
488
    char buf[256];
489
    char name[256];
490
    APIRET rc = 0;
491
 
492
    if (argc != 3) {
493
	rc = 1;
494
	error_message("Usage: gspmdrv -d id_string");
495
    }
496
    find_hwnd_gs(argv[2]);
497
 
498
    if (!rc) {
499
	sprintf(name, SHARED_NAME, argv[2]);
500
	rc = DosGetNamedSharedMem((PVOID *) & bitmap.pbmi, name, PAG_READ | PAG_WRITE);
501
	if (rc) {
502
	    sprintf(buf, "Failed to open: bmp shared memory \"%s\" rc = %d", argv[0], rc);
503
	    error_message(buf);
504
	}
505
    }
506
    if (!rc) {
507
	sprintf(name, SYNC_NAME, argv[2]);
508
	rc = DosOpenEventSem(name, &update_event_sem);
509
	if (rc) {
510
	    sprintf(buf, "Failed to open: update event semaphore \"%s\" rc = %d", argv[1], rc);
511
	    error_message(buf);
512
	}
513
    }
514
    if (!rc) {
515
	sprintf(name, MUTEX_NAME, argv[2]);
516
	rc = DosOpenMutexSem(name, &bmp_mutex_sem);
517
	if (rc) {
518
	    sprintf(buf, "Failed to open: bmp mutex semaphore \"%s\" rc = %d", argv[1], rc);
519
	    error_message(buf);
520
	}
521
    }
522
    if (!rc) {
523
	scan_bitmap(&bitmap);
524
	bitmap.valid = TRUE;
525
    }
526
    return rc;
527
}
528
 
529
 
530
APIRET 
531
init_bitmap(int argc, char *argv[])
532
{
533
    char buf[256];
534
    APIRET rc = 0;
535
    HFILE hf;
536
    ULONG action, count, length;
537
    PBITMAPFILEHEADER2 pbmfh;
538
 
539
    if (argc != 3)
540
	return 1;		/* error - no filename */
541
 
542
    /* open bitmap */
543
    if ((rc = DosOpen(argv[2], &hf, &action, 0, FILE_NORMAL, FILE_OPEN,
544
		      OPEN_ACCESS_READONLY | OPEN_SHARE_DENYREADWRITE, 0))
545
	!= (APIRET) 0) {
546
	sprintf(buf, "Error opening: %s", argv[2]);
547
	error_message(buf);
548
	return rc;
549
    }
550
    rc = DosSetFilePtr(hf, 0, FILE_END, &length);
551
    if (rc) {
552
	sprintf(buf, "failed seeking to EOF: error = %d", rc);
553
	error_message(buf);
554
	return rc;
555
    }
556
    rc = DosSetFilePtr(hf, 0, FILE_BEGIN, &count);
557
    if (rc) {
558
	sprintf(buf, "failed seeking to BOF: error = %d", rc);
559
	error_message(buf);
560
	return rc;
561
    };
562
 
563
    /* allocate memory for bitmap */
564
    if ((rc = DosAllocMem((PPVOID) & bbuffer, length, PAG_READ | PAG_WRITE | PAG_COMMIT))
565
	!= (APIRET) 0) {
566
	sprintf(buf, "failed allocating memory");
567
	error_message(buf);
568
	return rc;
569
    }
570
    rc = DosRead(hf, bbuffer, length, &count);
571
    DosClose(hf);
572
    if (rc) {
573
	sprintf(buf, "failed reading bitmap, error = %u, count = %u", rc, count);
574
	error_message(buf);
575
	return rc;
576
    }
577
    /* extract some info about bitmap */
578
    pbmfh = (PBITMAPFILEHEADER2) bbuffer;
579
    bitmap.pbmi = (PBITMAPINFO2) (&pbmfh->bmp2);
580
 
581
    scan_bitmap(&bitmap);
582
    bitmap.valid = TRUE;
583
 
584
    sprintf(buf, "bitmap width = %d, height = %d", bitmap.width, bitmap.height);
585
    message_box(buf, 0);
586
    return rc;
587
}
588
 
589
#define MAX_PAL_SIZE 256
590
void
591
make_palette(BMAP * pbm)
592
{
593
    ULONG tbl[MAX_PAL_SIZE];
594
    PRGB2 palptr = (PRGB2) ((PBYTE) (pbm->pbmi) + pbm->pbmi->cbFix);
595
    RGB *old_palptr = (RGB *) palptr;
596
    int palcount = pbm->palimportant;
597
    int i;
598
    BOOL old_bmp = (pbm->pbmi->cbFix == sizeof(BITMAPINFOHEADER));
599
 
600
    if (old_bmp) {
601
	for (i = 0; i < palcount; i++) {
602
	    tbl[i] = (old_palptr->bRed << 16) + (old_palptr->bGreen << 8) + (old_palptr->bBlue);
603
	    palptr++;
604
	}
605
    } else {
606
	for (i = 0; i < palcount; i++) {
607
	    tbl[i] = (palptr->bRed << 16) + (palptr->bGreen << 8) + (palptr->bBlue);
608
	    palptr++;
609
	}
610
    }
611
    if (display.hpal_exists)
612
	GpiDeletePalette(display.hpal);
613
    display.hpal = GpiCreatePalette(hab, 0L, LCOLF_CONSECRGB, palcount, tbl);
614
    display.hpal_exists = TRUE;
615
}
616
 
617
 
618
 
619
/* scan bitmap */
620
/* update bitmap structure */
621
/* return value is TRUE if bitmap dimension has changed */
622
BOOL
623
scan_bitmap(BMAP * pbm)
624
{
625
    PBITMAPINFO2 pbmi = pbm->pbmi;
626
    PBITMAPINFO old_pbmi = (PBITMAPINFO) pbmi;
627
    BOOL old_bmp = (pbmi->cbFix == sizeof(BITMAPINFOHEADER));
628
 
629
    if (old_bmp) {
630
	/* it is a BITMAPINFO */
631
	switch (old_pbmi->cBitCount) {
632
	    case 24:
633
		pbm->palsize = 0;
634
		break;
635
	    case 8:
636
		pbm->palsize = 256;
637
		break;
638
	    case 4:
639
		pbm->palsize = 16;
640
		break;
641
	    case 1:
642
		pbm->palsize = 2;
643
		break;
644
	    default:
645
		pbm->valid = FALSE;
646
		error_message("scan_bitmap: wrong number of bits");	/* panic */
647
		return FALSE;
648
	}
649
	pbm->palimportant = pbm->palsize;
650
	pbm->palsize = pbm->palsize * sizeof(RGB);
651
	pbm->bits = (PBYTE) old_pbmi + old_pbmi->cbFix + pbm->palsize;
652
	pbm->width = old_pbmi->cx;
653
	pbm->height = old_pbmi->cy;
654
	pbm->planes = old_pbmi->cPlanes;
655
	pbm->depth = old_pbmi->cBitCount;
656
    } else {
657
	/* it is a BITMAPINFO2 */
658
	switch (pbmi->cBitCount) {
659
	    case 24:
660
		pbm->palsize = 0;
661
		break;
662
	    case 8:
663
		pbm->palsize = 256;
664
		break;
665
	    case 4:
666
		pbm->palsize = 16;
667
		break;
668
	    case 1:
669
		pbm->palsize = 2;
670
		break;
671
	    default:
672
		pbm->valid = FALSE;
673
		error_message("scan_bitmap: wrong number of bits");	/* panic */
674
		return FALSE;
675
	}
676
	if ((pbmi->cbFix > (&(pbmi->cclrUsed) - &(pbmi->cbFix)))
677
	    && (pbmi->cclrUsed != 0) && (pbmi->cBitCount != 24))
678
	    pbm->palsize = pbmi->cclrUsed;
679
	pbm->palimportant = pbm->palsize;
680
	if ((pbmi->cbFix > (&(pbmi->cclrImportant) - &(pbmi->cbFix)))
681
	    && (pbmi->cclrImportant != 0) && (pbmi->cBitCount != 24))
682
	    pbm->palimportant = pbmi->cclrImportant;
683
	pbm->palsize = pbm->palsize * sizeof(RGB2);
684
	pbm->bits = (PBYTE) pbmi + pbmi->cbFix + pbm->palsize;
685
	pbm->width = pbmi->cx;
686
	pbm->height = pbmi->cy;
687
	pbm->planes = pbmi->cPlanes;
688
	pbm->depth = pbmi->cBitCount;
689
    }
690
 
691
    if ((pbm->palsize != pbm->old_palsize) || (pbm->palimportant != pbm->old_palimportant)) {
692
	if ((pbm->depth == 8) && display.hasPalMan)
693
	    make_palette(pbm);
694
	pbm->old_palimportant = pbm->palimportant;
695
    }
696
    if ((pbm->width == pbm->old_width) &&
697
	(pbm->height == pbm->old_height) &&
698
	(pbm->planes == pbm->old_planes) &&
699
	(pbm->depth == pbm->old_depth) &&
700
	(pbm->palsize == pbm->old_palsize) &&
701
	(pbm->old_bmp == old_bmp))
702
	return FALSE;
703
 
704
    /* bitmap has changed */
705
    pbm->old_width = pbm->width;
706
    pbm->old_height = pbm->height;
707
    pbm->old_planes = pbm->planes;
708
    pbm->old_depth = pbm->depth;
709
    pbm->old_palsize = pbm->palsize;
710
    pbm->old_bmp = old_bmp;
711
    return TRUE;
712
}
713
 
714
 
715
void
716
update_scroll_bars(void)
717
{
718
    /* Cause update of scroll bars etc. */
719
    SWP swp;
720
 
721
    WinQueryWindowPos(hwnd_bmp, &swp);
722
    WinSendMsg(hwnd_bmp, WM_SIZE, MPFROM2SHORT(swp.cx, swp.cy), MPFROM2SHORT(swp.cx, swp.cy));
723
}
724
 
725
 
726
/* copy bitmap to the clipboard */
727
void
728
copy_clipboard(void)
729
{
730
    HBITMAP hbmp;
731
 
732
    if (!bitmap.valid) {
733
	message_box("Cannot copy to clipboard:\nNo Bitmap displayed", 0);
734
	return;
735
    }
736
    if (WinOpenClipbrd(hab)) {
737
	/* get bmp mutex to stop gs.exe changing bitmap while we copy it */
738
	DosRequestMutexSem(bmp_mutex_sem, 10000);
739
	if (scan_bitmap(&bitmap)) {
740
	    /* bitmap has changed */
741
	    update_scroll_bars();
742
	}
743
	hbmp = make_bitmap(&bitmap, 0, 0, bitmap.width, bitmap.height, bitmap.depth);
744
	if (hbmp) {
745
	    WinEmptyClipbrd(hab);
746
	    WinSetClipbrdData(hab, (ULONG) hbmp, CF_BITMAP, CFI_HANDLE);
747
	}
748
	DosReleaseMutexSem(bmp_mutex_sem);
749
	WinCloseClipbrd(hab);
750
    }
751
}
752
 
753
 
754
HBITMAP
755
make_bitmap(BMAP * pbm, ULONG left, ULONG bottom, ULONG right, ULONG top, ULONG depth)
756
{
757
    HDC hdc = DEV_ERROR, hdcMem = DEV_ERROR;
758
    HPS hps = GPI_ERROR;
759
    HBITMAP hbmp = GPI_ERROR, hbmr = HBM_ERROR;
760
    SIZEL sizePS;
761
    BITMAPINFOHEADER2 bmih;
762
 
763
    if ((left == right) || (bottom == top))
764
	return (HBITMAP) NULL;
765
 
766
    if (right > pbm->width)
767
	right = pbm->width;
768
    if (left > pbm->width)
769
	left = 0;
770
    if (top > pbm->height)
771
	top = pbm->height;
772
    if (bottom > pbm->height)
773
	bottom = 0;
774
 
775
    memset(&bmih, 0, sizeof(bmih));
776
    bmih.cbFix = sizeof(BITMAPINFOHEADER2);
777
    bmih.cx = right - left;
778
    bmih.cy = top - bottom;
779
    bmih.cPlanes = 1;
780
    bmih.cBitCount = depth;
781
 
782
    /* create memory DC compatible with screen */
783
    hdcMem = DevOpenDC(hab, OD_MEMORY, "*", 0L, NULL, NULLHANDLE);
784
 
785
    sizePS.cx = right - left;
786
    sizePS.cy = top - bottom;
787
    if (hdcMem != DEV_ERROR)
788
	hps = GpiCreatePS(hab, hdcMem, &sizePS,
789
			  PU_PELS | GPIF_DEFAULT | GPIT_MICRO | GPIA_ASSOC);
790
 
791
    if (hps != GPI_ERROR)
792
	hbmp = GpiCreateBitmap(hps, &bmih, 0L, NULL, NULL);
793
 
794
    if (hbmp != GPI_ERROR)
795
	hbmr = GpiSetBitmap(hps, hbmp);
796
 
797
 
798
    if (hbmr != HBM_ERROR) {
799
	LONG rc;
800
	ERRORID eid;
801
	POINTL apts[4];
802
 
803
	/* target is inclusive */
804
	apts[0].x = 0;
805
	apts[0].y = 0;
806
	apts[1].x = right - left - 1;
807
	apts[1].y = top - bottom - 1;
808
	/* source is not inclusive of top & right borders */
809
	apts[2].x = left;
810
	apts[2].y = bottom;
811
	apts[3].x = right;
812
	apts[3].y = top;
813
 
814
	rc = 0;
815
	eid = WinGetLastError(hab);
816
	rc = GpiDrawBits(hps, pbm->bits, pbm->pbmi, 4, apts,
817
		     (bitmap.depth != 1) ? ROP_SRCCOPY : ROP_NOTSRCCOPY, 0);
818
	if (rc == 0) {
819
	    char buf[256];
820
 
821
	    eid = WinGetLastError(hab);
822
	    sprintf(buf, "make_bitmap: GpiDrawBits rc = %08x, eid = %08x", rc, eid);
823
	    message_box(buf, 0);
824
	}
825
    }
826
    if (hbmr != HBM_ERROR)
827
	GpiSetBitmap(hps, (ULONG) 0);
828
    if (hps != GPI_ERROR)
829
	GpiDestroyPS(hps);
830
    if (hdcMem != DEV_ERROR)
831
	DevCloseDC(hdcMem);
832
 
833
    if ((hbmr == HBM_ERROR) || (hdcMem == DEV_ERROR) ||
834
	(hbmp == GPI_ERROR) || (hps == GPI_ERROR)) {
835
	if (hbmp != GPI_ERROR)
836
	    GpiDeleteBitmap(hbmp);
837
	debugbeep(2);
838
	return 0;
839
    }
840
    return hbmp;
841
}
842
 
843
MRESULT
844
paint_bitmap(HPS ps, PRECTL prect, int scrollx, int scrolly)
845
{
846
    POINTL apts[4];
847
    int wx, wy;
848
 
849
    if (WinIsRectEmpty(hab, prect))
850
	return 0;
851
    if (ps == NULLHANDLE) {
852
	debugbeep(1);
853
    }
854
    /* source is not inclusive of top & right borders */
855
    wx = prect->xRight - prect->xLeft;	/* update width */
856
    wy = prect->yTop - prect->yBottom;	/* update height */
857
    apts[2].x = prect->xLeft + scrollx;
858
    apts[2].y = prect->yBottom + scrolly;
859
    if (apts[2].x > bitmap.width)
860
	apts[2].x = bitmap.width;
861
    if (apts[2].x + wx > bitmap.width)
862
	wx = bitmap.width - apts[2].x;
863
    apts[3].x = apts[2].x + wx;
864
    if (apts[2].y > bitmap.height)
865
	apts[2].y = bitmap.height;
866
    if (apts[2].y + wy > bitmap.height)
867
	wy = bitmap.height - apts[2].y;
868
    apts[3].y = apts[2].y + wy;
869
    /* target is inclusive */
870
    apts[0].x = prect->xLeft;
871
    apts[0].y = prect->yBottom;
872
    apts[1].x = prect->xLeft + wx - 1;
873
    apts[1].y = prect->yBottom + wy - 1;
874
 
875
    if ((display.bitcount == 4)	/* standard VGA is buggy */
876
	||((os_version == 201100) && (display.bitcount == 8) && (bitmap.depth == 1))	/* S3 and ATI GU are buggy */
877
	) {
878
	/* slow code to dodge OS/2 bugs */
879
	/* this code double buffers the bitmap and works on a standard VGA
880
	 * but didn't work on an ATI Ultra Graphics Pro in 8514 emulation
881
	 */
882
	/* This won't work for version 2.11, S3 or ATI GU, 8bit/pixel display, 8bit/pixel bitmap */
883
	HBITMAP hbmp;
884
 
885
	/* create a bitmap */
886
	hbmp = make_bitmap(&bitmap, apts[2].x, apts[2].y, apts[3].x, apts[3].y, bitmap.depth);
887
	/* Draw it to the display */
888
	if (hbmp) {
889
	    WinDrawBitmap(ps, hbmp, NULL, &apts[0], CLR_BLACK, CLR_WHITE, DBM_NORMAL);
890
	    GpiDeleteBitmap(hbmp);
891
	}
892
    } else {
893
	/* fast code which doesn't always work */
894
	/* This code works on the Trident SVGA and 8514 in 256 color mode,
895
	 * but GpiDrawBits fails with a SYS3175 on the standard VGA.
896
	 */
897
	/* This won't work for version 2.11, S3 or ATI GU, 8bit/pixel display, 1bit/pixel bitmap */
898
	GpiDrawBits(ps, bitmap.bits, bitmap.pbmi, 4, apts,
899
		    (bitmap.depth != 1) ? ROP_SRCCOPY : ROP_NOTSRCCOPY, 0);
900
    }
901
 
902
    return 0;
903
}
904
 
905
 
906
/* This is the window function */
907
MRESULT EXPENTRY 
908
ClientWndProc(HWND hwnd, ULONG mess,
909
	      MPARAM mp1, MPARAM mp2)
910
{
911
    char buf[256];
912
    static int cxClient, cyClient;
913
    static int cxAdjust, cyAdjust;
914
    static int nHscrollMax, nHscrollPos;
915
    static int nVscrollMax, nVscrollPos;
916
    int nHscrollInc;
917
    int nVscrollInc;
918
    HWND hwndScroll;
919
    HPS hps;
920
    RECTL rect;
921
    ULONG ulclr;
922
 
923
    switch (mess) {
924
	case WM_CREATE:
925
	    break;
926
	case WM_ERASEBACKGROUND:
927
	    /* by returning TRUE, the Presentation Manager automatically clears
928
	     * the window each time the window is resized or moved.
929
	     */
930
	    return (MRESULT) TRUE;
931
	case WM_GSUPDATE:
932
	    if (!WinInvalidateRect(hwnd_bmp, (PRECTL) NULL, TRUE))
933
		error_message("error invalidating rect");
934
	    if (!WinUpdateWindow(hwnd_bmp))
935
		error_message("error updating window");
936
	    return 0;
937
	case WM_COMMAND:
938
	    switch (LONGFROMMP(mp1)) {
939
		case IDM_ABOUT:
940
		    WinDlgBox(HWND_DESKTOP, hwnd, AboutDlgProc, 0, IDD_ABOUT, 0);
941
		    break;
942
		case IDM_COPY:
943
		    copy_clipboard();
944
		    break;
945
	    }
946
	    break;
947
	case WM_REALIZEPALETTE:
948
	    if ((bitmap.depth == 8) && display.hasPalMan && display.hpal_exists) {
949
		hps = WinGetPS(hwnd);
950
		if (hps == NULLHANDLE)
951
		    debugbeep(1);
952
		GpiSelectPalette(hps, display.hpal);
953
		if (WinRealizePalette(hwnd, hps, &ulclr) > 0)
954
		    WinInvalidateRect(hwnd, NULL, FALSE);
955
		GpiSelectPalette(hps, (HPAL) NULL);
956
		WinReleasePS(hps);
957
		return 0;
958
	    }
959
	    break;		/* use default processing */
960
	case WM_PAINT:
961
	    /* Refresh the window each time the WM_PAINT message is received */
962
 
963
	    /* get bmp mutex to stop gs.exe changing bitmap while we paint */
964
	    DosRequestMutexSem(bmp_mutex_sem, 10000);
965
	    if (scan_bitmap(&bitmap))
966
		update_scroll_bars();	/* bitmap has changed */
967
 
968
	    if (!bitmap.valid) {
969
		DosReleaseMutexSem(bmp_mutex_sem);
970
		hps = WinBeginPaint(hwnd, (ULONG) 0, &rect);
971
		if (hps == NULLHANDLE)
972
		    debugbeep(4);
973
		WinFillRect(hps, &rect, CLR_BACKGROUND);
974
		WinEndPaint(hwnd);
975
		return 0;
976
	    }
977
	    hps = WinBeginPaint(hwnd, (HPS) NULL, &rect);
978
	    if (hps == NULLHANDLE)
979
		debugbeep(4);
980
	    if ((bitmap.depth == 8) && display.hasPalMan && display.hpal_exists) {
981
		GpiSelectPalette(hps, display.hpal);
982
		WinRealizePalette(hwnd, hps, &ulclr);
983
		paint_bitmap(hps, &rect, nHscrollPos, nVscrollMax - nVscrollPos);
984
		GpiSelectPalette(hps, (HPAL) NULL);
985
	    } else
986
		paint_bitmap(hps, &rect, nHscrollPos, nVscrollMax - nVscrollPos);
987
	    WinEndPaint(hwnd);
988
 
989
	    DosReleaseMutexSem(bmp_mutex_sem);
990
	    return 0;
991
	case WM_MOVE:
992
	    /* don't interrogate the window location immediately since */
993
	    /* it causes the Diamond Stealth VL24 with IBM S3 drivers */
994
	    /* to corrupt the display */
995
	    DosSleep(50);
996
	    if (hwnd_frame) {	/* save window position for INI file */
997
		SWP swp;
998
 
999
		WinQueryWindowPos(WinQueryWindow(hwnd, QW_PARENT), &swp);
1000
		if (!(swp.fl & SWP_MINIMIZE)) {
1001
		    option.img_origin.x = swp.x;
1002
		    option.img_origin.y = swp.y;
1003
		    option.img_max = ((swp.fl & SWP_MAXIMIZE) != 0);
1004
		}
1005
	    }
1006
	    return 0;
1007
	case WM_SIZE:
1008
	    cyClient = SHORT2FROMMP(mp2);
1009
	    cxClient = SHORT1FROMMP(mp2);
1010
 
1011
	    cyAdjust = min(bitmap.height, cyClient) - cyClient;
1012
	    cyClient += cyAdjust;
1013
 
1014
	    nVscrollMax = max(0, bitmap.height - cyClient);
1015
	    nVscrollPos = min(nVscrollPos, nVscrollMax);
1016
	    scroll_pos.y = nVscrollMax - nVscrollPos;
1017
 
1018
	    if (!bitmap.valid)
1019
		cyClient = cyAdjust = nVscrollMax = nVscrollPos;
1020
 
1021
	    hwndScroll = WinWindowFromID(WinQueryWindow(hwnd, QW_PARENT), FID_VERTSCROLL);
1022
	    WinSendMsg(hwndScroll, SBM_SETSCROLLBAR, MPFROMLONG(nVscrollPos),
1023
		       MPFROM2SHORT(0, nVscrollMax));
1024
	    if (bitmap.valid)
1025
		WinSendMsg(hwndScroll, SBM_SETTHUMBSIZE, MPFROM2SHORT(cyClient, bitmap.height),
1026
			   MPFROMLONG(0));
1027
	    else
1028
		WinSendMsg(hwndScroll, SBM_SETTHUMBSIZE, MPFROM2SHORT(1, 1),
1029
			   MPFROMLONG(0));
1030
 
1031
	    cxAdjust = min(bitmap.width, cxClient) - cxClient;
1032
	    cxClient += cxAdjust;
1033
 
1034
	    nHscrollMax = max(0, bitmap.width - cxClient);
1035
	    nHscrollPos = min(nHscrollPos, nHscrollMax);
1036
	    scroll_pos.x = nHscrollPos;
1037
 
1038
	    if (!bitmap.valid)
1039
		cxClient = cxAdjust = nHscrollMax = nHscrollPos;
1040
 
1041
	    hwndScroll = WinWindowFromID(WinQueryWindow(hwnd, QW_PARENT), FID_HORZSCROLL);
1042
	    WinSendMsg(hwndScroll, SBM_SETSCROLLBAR, MPFROMLONG(nHscrollPos),
1043
		       MPFROM2SHORT(0, nHscrollMax));
1044
	    if (bitmap.valid)
1045
		WinSendMsg(hwndScroll, SBM_SETTHUMBSIZE, MPFROM2SHORT(cxClient, bitmap.width),
1046
			   MPFROMLONG(0));
1047
	    else
1048
		WinSendMsg(hwndScroll, SBM_SETTHUMBSIZE, MPFROM2SHORT(1, 1),
1049
			   MPFROMLONG(0));
1050
 
1051
	    if ((cxAdjust != 0 || cyAdjust != 0)) {
1052
		SWP swp;
1053
 
1054
		WinQueryWindowPos(WinQueryWindow(hwnd, QW_PARENT), &swp);
1055
		WinSetWindowPos(WinQueryWindow(hwnd, QW_PARENT), 0,
1056
				swp.x, swp.y - cyAdjust,
1057
		 swp.cx + cxAdjust, swp.cy + cyAdjust, SWP_SIZE | SWP_MOVE);
1058
		cxAdjust = cyAdjust = 0;
1059
	    }
1060
	    if (hwnd_frame) {	/* save window size for INI file */
1061
		SWP swp;
1062
 
1063
		WinQueryWindowPos(WinQueryWindow(hwnd, QW_PARENT), &swp);
1064
		if (!(swp.fl & SWP_MINIMIZE)) {
1065
		    option.img_size.x = swp.cx;
1066
		    option.img_size.y = swp.cy;
1067
		    option.img_max = ((swp.fl & SWP_MAXIMIZE) != 0);
1068
		}
1069
	    }
1070
	    break;
1071
	case WM_VSCROLL:
1072
	    switch (SHORT2FROMMP(mp2)) {
1073
		case SB_LINEUP:
1074
		    nVscrollInc = -cyClient / 16;
1075
		    break;
1076
		case SB_LINEDOWN:
1077
		    nVscrollInc = cyClient / 16;
1078
		    break;
1079
		case SB_PAGEUP:
1080
		    nVscrollInc = min(-1, -cyClient);
1081
		    break;
1082
		case SB_PAGEDOWN:
1083
		    nVscrollInc = max(1, cyClient);
1084
		    break;
1085
		case SB_SLIDERPOSITION:
1086
		    nVscrollInc = SHORT1FROMMP(mp2) - nVscrollPos;
1087
		    break;
1088
		case SB_TOP:
1089
		    nVscrollInc = -nVscrollPos;
1090
		    break;
1091
		case SB_BOTTOM:
1092
		    nVscrollInc = nVscrollMax - nVscrollPos;
1093
		    break;
1094
		default:
1095
		    nVscrollInc = 0;
1096
	    }
1097
	    if ((nVscrollInc = max(-nVscrollPos,
1098
		       min(nVscrollInc, nVscrollMax - nVscrollPos))) != 0) {
1099
		LONG lComplexity;
1100
 
1101
		hwndScroll = WinWindowFromID(WinQueryWindow(hwnd, QW_PARENT), FID_VERTSCROLL);
1102
		nVscrollPos += nVscrollInc;
1103
		scroll_pos.y = nVscrollMax - nVscrollPos;
1104
		lComplexity = WinScrollWindow(hwnd, 0, nVscrollInc, (PRECTL) NULL, (PRECTL) NULL,
1105
				     (HRGN) NULLHANDLE, (PRECTL) & rect, 0);
1106
		WinSendMsg(hwndScroll, SBM_SETPOS, MPFROMLONG(nVscrollPos), 0);
1107
		if (lComplexity != RGN_RECT) {
1108
		    WinInvalidateRect(hwnd, (PRECTL) NULL, FALSE);
1109
		    WinUpdateWindow(hwnd);
1110
		} else {
1111
		    /* redraw exposed area */
1112
		    hps = WinGetPS(hwnd);
1113
		    if (hps == NULLHANDLE)
1114
			debugbeep(1);
1115
		    if ((bitmap.depth == 8) && display.hasPalMan && display.hpal_exists) {
1116
			GpiSelectPalette(hps, display.hpal);
1117
			WinRealizePalette(hwnd, hps, &ulclr);
1118
			paint_bitmap(hps, &rect, nHscrollPos, nVscrollMax - nVscrollPos);
1119
			GpiSelectPalette(hps, (HPAL) NULL);
1120
		    } else
1121
			paint_bitmap(hps, &rect, nHscrollPos, nVscrollMax - nVscrollPos);
1122
		    WinReleasePS(hps);
1123
		}
1124
	    }
1125
	    break;
1126
	case WM_HSCROLL:
1127
	    switch (SHORT2FROMMP(mp2)) {
1128
		case SB_LINELEFT:
1129
		    nHscrollInc = -cxClient / 16;
1130
		    break;
1131
		case SB_LINERIGHT:
1132
		    nHscrollInc = cyClient / 16;
1133
		    break;
1134
		case SB_PAGELEFT:
1135
		    nHscrollInc = min(-1, -cxClient);
1136
		    break;
1137
		case SB_PAGERIGHT:
1138
		    nHscrollInc = max(1, cxClient);
1139
		    break;
1140
		case SB_SLIDERPOSITION:
1141
		    nHscrollInc = SHORT1FROMMP(mp2) - nHscrollPos;
1142
		    break;
1143
		default:
1144
		    nHscrollInc = 0;
1145
	    }
1146
	    if ((nHscrollInc = max(-nHscrollPos,
1147
		       min(nHscrollInc, nHscrollMax - nHscrollPos))) != 0) {
1148
		LONG lComplexity;
1149
 
1150
		hwndScroll = WinWindowFromID(WinQueryWindow(hwnd, QW_PARENT), FID_HORZSCROLL);
1151
		nHscrollPos += nHscrollInc;
1152
		scroll_pos.x = nHscrollPos;
1153
		lComplexity = WinScrollWindow(hwnd, -nHscrollInc, 0, (PRECTL) NULL, (PRECTL) NULL,
1154
				     (HRGN) NULLHANDLE, (PRECTL) & rect, 0);
1155
		/* need to send next message BEFORE redrawing, otherwise S3 driver screws up */
1156
		WinSendMsg(hwndScroll, SBM_SETPOS, MPFROMLONG(nHscrollPos), 0);
1157
		if (lComplexity != RGN_RECT) {
1158
		    WinInvalidateRect(hwnd, (PRECTL) NULL, FALSE);
1159
		    WinUpdateWindow(hwnd);
1160
		} else {
1161
		    /* redraw exposed area */
1162
		    hps = WinGetPS(hwnd);
1163
		    if (hps == NULLHANDLE)
1164
			debugbeep(1);
1165
		    if ((bitmap.depth == 8) && display.hasPalMan && display.hpal_exists) {
1166
			GpiSelectPalette(hps, display.hpal);
1167
			WinRealizePalette(hwnd, hps, &ulclr);
1168
			paint_bitmap(hps, &rect, nHscrollPos, nVscrollMax - nVscrollPos);
1169
			GpiSelectPalette(hps, (HPAL) NULL);
1170
		    } else
1171
			paint_bitmap(hps, &rect, nHscrollPos, nVscrollMax - nVscrollPos);
1172
		    WinReleasePS(hps);
1173
		}
1174
	    }
1175
	    break;
1176
	case WM_CHAR:		/* process keystrokes here */
1177
	    if (SHORT1FROMMP(mp1) & KC_CHAR) {
1178
		/* pass control to gs if ENTER pressed */
1179
		if (hwnd_gs && (SHORT1FROMMP(mp2) == '\r'))
1180
		    WinSetActiveWindow(HWND_DESKTOP, hwnd_gs);
1181
	    }
1182
	    /* Process only key presses, not key releases */
1183
	    if (SHORT1FROMMP(mp1) & KC_KEYUP)
1184
		break;
1185
	    if (SHORT1FROMMP(mp1) & KC_VIRTUALKEY) {
1186
		USHORT vkey = SHORT2FROMMP(mp2);
1187
 
1188
		switch (vkey) {
1189
		    case VK_HOME:
1190
			WinSendMsg(hwnd, WM_VSCROLL, MPFROMLONG(0), MPFROM2SHORT(0, SB_TOP));
1191
			break;
1192
		    case VK_END:
1193
			WinSendMsg(hwnd, WM_VSCROLL, MPFROMLONG(0), MPFROM2SHORT(0, SB_BOTTOM));
1194
			break;
1195
		    case VK_UP:
1196
			WinSendMsg(hwnd, WM_VSCROLL, MPFROMLONG(0), MPFROM2SHORT(0, SB_LINEUP));
1197
			break;
1198
		    case VK_DOWN:
1199
			WinSendMsg(hwnd, WM_VSCROLL, MPFROMLONG(0), MPFROM2SHORT(0, SB_LINEDOWN));
1200
			break;
1201
		    case VK_PAGEUP:
1202
			WinSendMsg(hwnd, WM_VSCROLL, MPFROMLONG(0), MPFROM2SHORT(0, SB_PAGEUP));
1203
			break;
1204
		    case VK_PAGEDOWN:
1205
			WinSendMsg(hwnd, WM_VSCROLL, MPFROMLONG(0), MPFROM2SHORT(0, SB_PAGEDOWN));
1206
			break;
1207
		    case VK_LEFT:
1208
			if (SHORT1FROMMP(mp1) & KC_CTRL)
1209
			    WinSendMsg(hwnd, WM_HSCROLL, MPFROMLONG(0), MPFROM2SHORT(0, SB_PAGELEFT));
1210
			else
1211
			    WinSendMsg(hwnd, WM_HSCROLL, MPFROMLONG(0), MPFROM2SHORT(0, SB_LINELEFT));
1212
			break;
1213
		    case VK_RIGHT:
1214
			if (SHORT1FROMMP(mp1) & KC_CTRL)
1215
			    WinSendMsg(hwnd, WM_HSCROLL, MPFROMLONG(0), MPFROM2SHORT(0, SB_PAGERIGHT));
1216
			else
1217
			    WinSendMsg(hwnd, WM_HSCROLL, MPFROMLONG(0), MPFROM2SHORT(0, SB_LINERIGHT));
1218
			break;
1219
		}
1220
	    }
1221
	    break;
1222
	default:
1223
	    /* All messages not handled by the ClientWndProc must be passed
1224
	     * along to the Presentation Manager for default processing
1225
	     */
1226
	    return WinDefWindowProc(hwnd, mess, mp1, mp2);
1227
    }
1228
    return (MRESULT) FALSE;
1229
}
1230
 
1231
 
1232
 
1233
/* About Dialog Box */
1234
MRESULT EXPENTRY 
1235
AboutDlgProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
1236
{
1237
    switch (msg) {
1238
	case WM_COMMAND:
1239
	    switch (COMMANDMSG(&msg)->cmd) {
1240
		case DID_OK:
1241
		    WinDismissDlg(hwnd, TRUE);
1242
		    return (MRESULT) TRUE;
1243
	    }
1244
	    break;
1245
    }
1246
    return WinDefDlgProc(hwnd, msg, mp1, mp2);
1247
}