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