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 } 1248