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
debugbeep(int type)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
message_box(char * str,int icon)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
error_message(char * str)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
update_func(ULONG unused)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
exit_func(ULONG code)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
find_hwnd_gs(char * gsid)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
main(int argc,char * argv[])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
init_window()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
write_profile(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
read_profile(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
fix_sysmenu(HWND hwnd)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
restore_window_position(SWP * pswp)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
init_display(int argc,char * argv[])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
init_bitmap(int argc,char * argv[])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
make_palette(BMAP * pbm)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
scan_bitmap(BMAP * pbm)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
update_scroll_bars(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
copy_clipboard(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
make_bitmap(BMAP * pbm,ULONG left,ULONG bottom,ULONG right,ULONG top,ULONG depth)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
paint_bitmap(HPS ps,PRECTL prect,int scrollx,int scrolly)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
ClientWndProc(HWND hwnd,ULONG mess,MPARAM mp1,MPARAM mp2)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
AboutDlgProc(HWND hwnd,ULONG msg,MPARAM mp1,MPARAM mp2)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 }
1248