|
|
1.1 ! root 1: /***************************************************************************\ ! 2: * wmchar.c -- Displays WM_CHAR messages ! 3: * ! 4: * Created by Microsoft Corporation, 1989 ! 5: \***************************************************************************/ ! 6: ! 7: ! 8: #define INCL_WIN ! 9: #define INCL_GPILCIDS ! 10: #include <os2.h> ! 11: #include <string.h> ! 12: #include <stdio.h> ! 13: #include "wmchar.h" ! 14: ! 15: ! 16: #define max2(a, b) ((a) > (b) ? (a) : (b)) ! 17: #define min2(a, b) ((a) < (b) ? (a) : (b)) ! 18: ! 19: ! 20: /* display dependent values */ ! 21: SHORT gcyChar; ! 22: SHORT gcxAveChar; ! 23: SHORT gcxMaxChar; ! 24: SHORT gcxMargin; ! 25: ! 26: /* program globals */ ! 27: USHORT gcMessages = 0; /* also the "number" of the most recent message */ ! 28: CHAR gszNull[] = " --"; /* denotes an empty field */ ! 29: BOOL gfKeyUps = FALSE; ! 30: ! 31: ! 32: /* char messages are stored in a circular buffer */ ! 33: typedef struct _CHMSG { /* cm */ ! 34: USHORT usKC; ! 35: UCHAR uchRep; ! 36: UCHAR uchScan; ! 37: USHORT ch; ! 38: USHORT usVK; ! 39: } CHMSG; ! 40: ! 41: #define CBUFFERELTS 20 ! 42: ! 43: CHMSG gacm[CBUFFERELTS]; ! 44: SHORT gicmStart = 0; ! 45: ! 46: ! 47: /* display field attributes are stored in an array */ ! 48: typedef struct _MSGFIELD { /* mf */ ! 49: BOOL fDisplay; /* TRUE if field is currently being displayed */ ! 50: SHORT cxWidth; /* field width, initially chars, then pixels */ ! 51: CHAR *szHeading; /* field heading */ ! 52: } MSGFIELD; ! 53: ! 54: #define INUMBER 0 ! 55: #define IVIRTUALKEY 1 ! 56: #define ICHAR 2 ! 57: #define ISCANCODE 3 ! 58: #define IREPEAT 4 ! 59: #define IFLAGS 5 ! 60: ! 61: MSGFIELD gamf[CDISPLAYFIELDS] = { ! 62: TRUE, 7, " #", ! 63: TRUE, 15, "VK_ Value", ! 64: TRUE, 14, "Char", ! 65: FALSE, 10, "Scan", ! 66: FALSE, 8, "Rep", ! 67: TRUE, 0, "KC_ Flags" /* variable width, so it's last */ ! 68: }; ! 69: ! 70: SHORT gcxMargin = 3; ! 71: ! 72: ! 73: /* char flag strings */ ! 74: CHAR *gachFlags[] = { ! 75: "char", ! 76: "virtualkey", ! 77: "scancode", ! 78: "shift", ! 79: "ctrl", ! 80: "alt", ! 81: "keyup", ! 82: "prevdown", ! 83: "lonekey", ! 84: "deadkey", ! 85: "composite", ! 86: "invalidcomp", ! 87: "toggle", ! 88: "invalidchar", ! 89: "dbcsrsrvd1", ! 90: "dbcsrsrvd2" ! 91: }; ! 92: ! 93: /* virtual key strings */ ! 94: CHAR *gachVK[] = { ! 95: gszNull, ! 96: "button1", ! 97: "button2", ! 98: "button3", ! 99: "break", ! 100: "backspace", ! 101: "tab", ! 102: "backtab", ! 103: "newline", ! 104: "shift", ! 105: "ctrl", ! 106: "alt", ! 107: "altgraf", ! 108: "pause", ! 109: "capslock", ! 110: "esc", ! 111: "space", ! 112: "pageup", ! 113: "pagedown", ! 114: "end", ! 115: "home", ! 116: "left", ! 117: "up", ! 118: "right", ! 119: "down", ! 120: "printscrn", ! 121: "insert", ! 122: "delete", ! 123: "scrllock", ! 124: "numlock", ! 125: "enter", ! 126: "sysrq", ! 127: "f1", ! 128: "f2", ! 129: "f3", ! 130: "f4", ! 131: "f5", ! 132: "f6", ! 133: "f7", ! 134: "f8", ! 135: "f9", ! 136: "f10", ! 137: "f11", ! 138: "f12", ! 139: "f13", ! 140: "f14", ! 141: "f15", ! 142: "f16", ! 143: "f17", ! 144: "f18", ! 145: "f19", ! 146: "f20", ! 147: "f21", ! 148: "f22", ! 149: "f23", ! 150: "f24" ! 151: }; ! 152: ! 153: ! 154: ! 155: /***************************************************************************\ ! 156: * DrawText ! 157: * ! 158: * This function displays a text string. ! 159: * ! 160: * Parameters: ! 161: * hps: presentation space ! 162: * cx, cy: point to begin drawing ! 163: * sz: string to draw ! 164: * iColor: text color ! 165: * fExtent: whether to calc extent or not ! 166: * ! 167: * Returns: ! 168: * x position of end of painted string if fExtent == TRUE ! 169: \***************************************************************************/ ! 170: ! 171: SHORT DrawText( ! 172: HPS hps, ! 173: SHORT cx, ! 174: SHORT cy, ! 175: CHAR *sz, ! 176: LONG iColor, ! 177: BOOL fExtent) ! 178: { ! 179: RECTL rcl; ! 180: SHORT cch; ! 181: ! 182: cch = strlen(sz); ! 183: ! 184: rcl.xLeft = cx; ! 185: rcl.xRight = cx + cch * gcxMaxChar; /* hack */ ! 186: rcl.yBottom = cy; ! 187: rcl.yTop = cy + gcyChar; ! 188: ! 189: WinDrawText(hps, cch, (PCH)sz, (PRECTL)&rcl, iColor, SYSCLR_WINDOW, 0); ! 190: ! 191: if (fExtent) { ! 192: WinDrawText(hps, cch, (PCH)sz, (PRECTL)&rcl, iColor, ! 193: SYSCLR_WINDOW, DT_QUERYEXTENT); ! 194: return (SHORT)rcl.xRight; ! 195: } ! 196: ! 197: return 0; ! 198: } ! 199: ! 200: ! 201: ! 202: /***************************************************************************\ ! 203: * FormatHexChar ! 204: * ! 205: * This function formats an unsigned hex number into a string. It is needed ! 206: * to get around shortcomings of sprintf(). ! 207: * ! 208: * Parameters: ! 209: * uch: number to format ! 210: * sz: string to get number ! 211: \***************************************************************************/ ! 212: ! 213: VOID FormatHexChar( ! 214: USHORT uch, ! 215: CHAR *sz) ! 216: { ! 217: sprintf(sz, "0x%2x", uch); ! 218: ! 219: /* patch up hex byte display */ ! 220: if (strlen(sz) > 4) { ! 221: /* remove sign extension of byte */ ! 222: sz[2] = sz[4]; ! 223: sz[3] = sz[5]; ! 224: sz[4] = 0; ! 225: } else if (sz[2] == ' ') { ! 226: /* fill in blank with 0 */ ! 227: sz[2] = '0'; ! 228: } ! 229: } ! 230: ! 231: ! 232: ! 233: /***************************************************************************\ ! 234: * DrawMessage ! 235: * ! 236: * This function draws a single message line. ! 237: * ! 238: * Parameters: ! 239: * hps: presentation space ! 240: * iMessage: message number to display ! 241: * pcm: pointer to message structure ! 242: * cy: y position of message ! 243: \***************************************************************************/ ! 244: ! 245: VOID DrawMessage( ! 246: HPS hps, ! 247: SHORT iMessage, ! 248: CHMSG *pcm, ! 249: SHORT cy) ! 250: { ! 251: CHAR sz[16]; ! 252: USHORT fsFlags; ! 253: SHORT i; ! 254: SHORT cx; ! 255: ! 256: cx = gcxMargin; ! 257: ! 258: if (gamf[INUMBER].fDisplay) { ! 259: /* draw message number */ ! 260: sprintf(sz, "%u.", iMessage); ! 261: DrawText(hps, cx, cy, sz, SYSCLR_WINDOWTEXT, FALSE); ! 262: cx += gamf[INUMBER].cxWidth; ! 263: } ! 264: ! 265: if (gamf[IVIRTUALKEY].fDisplay) { ! 266: /* draw virtual key code */ ! 267: DrawText(hps, cx, cy, gachVK[pcm->usVK], SYSCLR_WINDOWTEXT, ! 268: FALSE); ! 269: cx += gamf[IVIRTUALKEY].cxWidth; ! 270: } ! 271: ! 272: if (gamf[ICHAR].fDisplay) { ! 273: /* draw character */ ! 274: if ((CHAR)pcm->ch) { ! 275: FormatHexChar(pcm->ch, sz); ! 276: DrawText(hps, cx, cy, sz, SYSCLR_WINDOWTEXT, FALSE); ! 277: sprintf(sz, "'%c'", (CHAR)pcm->ch); ! 278: DrawText(hps, cx + 7 * gcxAveChar, cy, sz, SYSCLR_WINDOWTEXT, ! 279: FALSE); ! 280: } else { ! 281: DrawText(hps, cx, cy, gszNull, SYSCLR_WINDOWTEXT, FALSE); ! 282: } ! 283: cx += gamf[ICHAR].cxWidth; ! 284: } ! 285: ! 286: if (gamf[ISCANCODE].fDisplay) { ! 287: if (pcm->uchScan) { ! 288: FormatHexChar(pcm->uchScan, sz); ! 289: DrawText(hps, cx, cy, sz, SYSCLR_WINDOWTEXT, FALSE); ! 290: } else { ! 291: DrawText(hps, cx, cy, gszNull, SYSCLR_WINDOWTEXT, FALSE); ! 292: } ! 293: cx += gamf[ISCANCODE].cxWidth; ! 294: } ! 295: ! 296: if (gamf[IREPEAT].fDisplay) { ! 297: sprintf(sz, "%u", pcm->uchRep); ! 298: DrawText(hps, cx, cy, sz, SYSCLR_WINDOWTEXT, FALSE); ! 299: cx += gamf[IREPEAT].cxWidth; ! 300: } ! 301: ! 302: if (gamf[IFLAGS].fDisplay) { ! 303: /* draw KC_ flags */ ! 304: fsFlags = pcm->usKC; ! 305: for (i = 0; i < 16; i++) { ! 306: if (fsFlags & 1) { ! 307: switch (i) { ! 308: case 0: ! 309: if (gamf[ICHAR].fDisplay) ! 310: goto DF_PRINTIT; ! 311: break; ! 312: case 1: ! 313: if (gamf[IVIRTUALKEY].fDisplay) ! 314: goto DF_PRINTIT; ! 315: break; ! 316: case 2: ! 317: if (gamf[ISCANCODE].fDisplay) ! 318: goto DF_PRINTIT; ! 319: break; ! 320: default: ! 321: DF_PRINTIT: ! 322: cx = DrawText(hps, cx, cy, gachFlags[i], SYSCLR_WINDOWTEXT, TRUE); ! 323: cx += gcxAveChar; ! 324: } ! 325: } ! 326: fsFlags >>= 1; ! 327: } ! 328: cx += gamf[IFLAGS].cxWidth; ! 329: } ! 330: } ! 331: ! 332: ! 333: ! 334: /***************************************************************************\ ! 335: * PaintClient ! 336: * ! 337: * This function paints a client window. ! 338: * ! 339: * Parameters: ! 340: * hwnd: window handle ! 341: \***************************************************************************/ ! 342: ! 343: VOID PaintClient( ! 344: HWND hwnd) ! 345: { ! 346: HPS hps; ! 347: RECTL rcl; ! 348: SHORT iMessage; ! 349: SHORT yBottom; ! 350: SHORT cx; ! 351: SHORT i; ! 352: ! 353: hps = WinBeginPaint(hwnd, (HPS)NULL, (PRECTL)&rcl); ! 354: ! 355: /* clear invalidated region */ ! 356: WinFillRect(hps, (PRECTL)&rcl, SYSCLR_WINDOW); ! 357: ! 358: /* get y position to start drawing */ ! 359: WinQueryWindowRect(hwnd, (PRECTL)&rcl); ! 360: yBottom = (SHORT)(rcl.yTop - gcyChar - gcyChar / 2); ! 361: ! 362: /* draw headings */ ! 363: cx = gcxMargin; ! 364: for (i = 0; i < CDISPLAYFIELDS; i++) { ! 365: if (gamf[i].fDisplay) { ! 366: DrawText(hps, cx, yBottom, gamf[i].szHeading, ! 367: SYSCLR_WINDOWSTATICTEXT, FALSE); ! 368: cx += gamf[i].cxWidth; ! 369: } ! 370: } ! 371: ! 372: /* draw each entry */ ! 373: i = gicmStart; ! 374: iMessage = gcMessages; ! 375: yBottom -= (gcyChar + gcyChar / 2); ! 376: do { ! 377: if (!iMessage || yBottom < -gcyChar) ! 378: break; ! 379: ! 380: DrawMessage(hps, iMessage, &gacm[i], yBottom); ! 381: ! 382: i = (i + 1) % CBUFFERELTS; ! 383: iMessage--; ! 384: yBottom -= gcyChar; ! 385: ! 386: } while (i != gicmStart); ! 387: ! 388: WinEndPaint(hps); ! 389: } ! 390: ! 391: ! 392: ! 393: /***************************************************************************\ ! 394: * NewMessage ! 395: * ! 396: * This function adds a new WM_CHAR message to the list. ! 397: * ! 398: * Parameters: ! 399: * hwnd: window handle ! 400: * mp1, mp2: ! 401: * usKC: key flags ! 402: * usVK: virtual key code ! 403: * ch: char; ! 404: \***************************************************************************/ ! 405: ! 406: VOID NewMessage( ! 407: HWND hwnd, ! 408: MPARAM mp1, ! 409: MPARAM mp2) ! 410: { ! 411: RECTL rclScroll, rclUpdate; ! 412: HPS hps; ! 413: ! 414: /* overwrite oldest entry */ ! 415: if (gicmStart) ! 416: gicmStart--; ! 417: else ! 418: gicmStart = CBUFFERELTS - 1; ! 419: ! 420: gacm[gicmStart].usKC = SHORT1FROMMP(mp1); ! 421: gacm[gicmStart].uchRep = CHAR3FROMMP(mp1); ! 422: gacm[gicmStart].uchScan = CHAR4FROMMP(mp1); ! 423: gacm[gicmStart].ch = SHORT1FROMMP(mp2); ! 424: gacm[gicmStart].usVK = SHORT2FROMMP(mp2); ! 425: ! 426: gcMessages++; ! 427: ! 428: /* scroll and update intelligently */ ! 429: WinQueryWindowRect(hwnd, (PRECTL)&rclScroll); ! 430: rclScroll.yTop -= 2 * gcyChar; ! 431: rclScroll.yBottom = max2(0L, rclScroll.yTop - (LONG)(CBUFFERELTS * gcyChar)); ! 432: ! 433: WinScrollWindow(hwnd, 0, -gcyChar, (PRECTL)&rclScroll, (PRECTL)&rclScroll, ! 434: NULL, &rclUpdate, 0); ! 435: ! 436: hps = WinGetPS(hwnd); ! 437: WinFillRect(hps, (PRECTL)&rclUpdate, SYSCLR_WINDOW); ! 438: DrawMessage( hps ! 439: , gcMessages ! 440: , &gacm[gicmStart] ! 441: , (SHORT)rclScroll.yTop - gcyChar ); ! 442: WinReleasePS(hps); ! 443: } ! 444: ! 445: ! 446: ! 447: /***************************************************************************\ ! 448: * CheckMenuItem ! 449: * ! 450: * This function sets the check state of a menu item. ! 451: * ! 452: * Parameters: ! 453: * hwnd: frame window ! 454: * id: menu id ! 455: * fCheck: check state ! 456: \***************************************************************************/ ! 457: ! 458: VOID CheckMenuItem( ! 459: HWND hwndFrame, ! 460: SHORT id, ! 461: BOOL fCheck) ! 462: { ! 463: HWND hwndMenu; ! 464: ! 465: /* toggle menu checkmark */ ! 466: hwndMenu = WinWindowFromID(hwndFrame, FID_MENU); ! 467: WinSendMsg(hwndMenu, MM_SETITEMATTR, MPFROM2SHORT(id, TRUE), ! 468: MPFROM2SHORT(MIA_CHECKED, fCheck ? MIA_CHECKED : 0)); ! 469: } ! 470: ! 471: ! 472: ! 473: /***************************************************************************\ ! 474: * MenuCommand ! 475: * ! 476: * This function processes WM_COMMAND messages. ! 477: * ! 478: * Parameters: ! 479: * hwnd: client window handle ! 480: * id: command identifier ! 481: \***************************************************************************/ ! 482: ! 483: VOID MenuCommand( ! 484: HWND hwnd, ! 485: SHORT id) ! 486: { ! 487: BOOL *pfDisplay; ! 488: HWND hwndFrame; ! 489: ! 490: if (id == IDM_CLEAR) { ! 491: ! 492: /* clear current messages */ ! 493: gcMessages = 0; ! 494: WinInvalidateRect(hwnd, NULL, FALSE); ! 495: ! 496: } else if (id == IDM_KEYUPS) { ! 497: ! 498: /* toggle logging keyups */ ! 499: gfKeyUps = !gfKeyUps; ! 500: hwndFrame = WinQueryWindow(hwnd, QW_PARENT, FALSE); ! 501: CheckMenuItem(hwndFrame, IDM_KEYUPS, gfKeyUps); ! 502: ! 503: } else if (id >= IDM_DISPLAYFIRST && id <= IDM_DISPLAYLAST) { ! 504: ! 505: /* toggle display field */ ! 506: pfDisplay = &(gamf[id - IDM_DISPLAYFIRST].fDisplay); ! 507: *pfDisplay = !*pfDisplay; ! 508: hwndFrame = WinQueryWindow(hwnd, QW_PARENT, FALSE); ! 509: CheckMenuItem(hwndFrame, id, *pfDisplay); ! 510: ! 511: /* repaint in new format */ ! 512: WinInvalidateRect(hwnd, NULL, FALSE); ! 513: } ! 514: } ! 515: ! 516: ! 517: ! 518: /***************************************************************************\ ! 519: * MainWndProc ! 520: * ! 521: * This is the window procedure for the main client window. ! 522: \***************************************************************************/ ! 523: ! 524: MRESULT CALLBACK MainWndProc( ! 525: HWND hwnd, ! 526: USHORT msg, ! 527: MPARAM mp1, ! 528: MPARAM mp2) ! 529: { ! 530: switch (msg) { ! 531: ! 532: case WM_PAINT: ! 533: PaintClient(hwnd); ! 534: break; ! 535: ! 536: case WM_COMMAND: ! 537: MenuCommand(hwnd, SHORT1FROMMP(mp1)); ! 538: break; ! 539: ! 540: case WM_CHAR: ! 541: if (gfKeyUps || !(KC_KEYUP & SHORT1FROMMP(mp1))) { ! 542: ! 543: /* add new message to list */ ! 544: NewMessage(hwnd, mp1, mp2); ! 545: } ! 546: break; ! 547: ! 548: default: ! 549: return WinDefWindowProc(hwnd, msg, mp1, mp2); ! 550: } ! 551: ! 552: return (MRESULT)0; ! 553: } ! 554: ! 555: ! 556: ! 557: /***************************************************************************\ ! 558: * CheckMenus ! 559: * ! 560: * This function sets menu check marks according to their current internal ! 561: * state. ! 562: * ! 563: * Parameters: ! 564: * hwndFrame: main app window handle ! 565: \***************************************************************************/ ! 566: ! 567: VOID CheckMenus( ! 568: HWND hwndFrame) ! 569: { ! 570: SHORT id; ! 571: ! 572: CheckMenuItem(hwndFrame, IDM_KEYUPS, gfKeyUps); ! 573: ! 574: for (id = IDM_DISPLAYFIRST; id <= IDM_DISPLAYLAST; id++) { ! 575: CheckMenuItem(hwndFrame, id, gamf[id - IDM_DISPLAYFIRST].fDisplay); ! 576: } ! 577: } ! 578: ! 579: ! 580: ! 581: /***************************************************************************\ ! 582: * RegisterSwitchEntry ! 583: * ! 584: * This function registers the app with the switch list. ! 585: * ! 586: * Parameters: ! 587: * hwndFrame: main app window handle ! 588: \***************************************************************************/ ! 589: ! 590: VOID RegisterSwitchEntry( ! 591: HWND hwndFrame) ! 592: { ! 593: PID pid; ! 594: TID tid; ! 595: SWCNTRL swc; ! 596: ! 597: WinQueryWindowProcess(hwndFrame, (PPID)&pid, (PTID)&tid); ! 598: WinQueryWindowText(hwndFrame, MAXNAMEL, (PSZ)swc.szSwtitle); ! 599: swc.hwnd = hwndFrame; ! 600: swc.hwndIcon = (ULONG)NULL; ! 601: swc.hprog = (HPROGRAM)NULL; ! 602: swc.idProcess = pid; ! 603: swc.idSession = NULL; ! 604: swc.uchVisibility = SWL_VISIBLE; ! 605: swc.fbJump = SWL_JUMPABLE; ! 606: WinAddSwitchEntry((PSWCNTRL)&swc); ! 607: } ! 608: ! 609: ! 610: ! 611: /***************************************************************************\ ! 612: * GetDisplayValues ! 613: * ! 614: * This function sets display dependent global variables. ! 615: \***************************************************************************/ ! 616: ! 617: VOID GetDisplayValues(VOID) ! 618: { ! 619: HPS hps; ! 620: FONTMETRICS fm; ! 621: SHORT i; ! 622: ! 623: hps = WinGetPS(HWND_DESKTOP); ! 624: GpiQueryFontMetrics(hps, (ULONG)sizeof(FONTMETRICS), (PFONTMETRICS)&fm); ! 625: WinReleasePS(hps); ! 626: ! 627: gcyChar = (SHORT)(fm.lMaxBaselineExt + fm.lExternalLeading); ! 628: gcxAveChar = (SHORT)fm.lAveCharWidth; ! 629: gcxMaxChar = (SHORT)fm.lMaxCharInc; ! 630: ! 631: /* adjust display widths for this font */ ! 632: gcxMargin *= gcxAveChar; ! 633: for (i = 0; i < CDISPLAYFIELDS; i++) { ! 634: gamf[i].cxWidth *= gcxAveChar; ! 635: } ! 636: } ! 637: ! 638: ! 639: ! 640: /***************************************************************************\ ! 641: * main ! 642: * ! 643: * This is the main procedure for the app. ! 644: \***************************************************************************/ ! 645: ! 646: VOID cdecl main(VOID) ! 647: { ! 648: HAB hab; ! 649: HMQ hmq; ! 650: QMSG qmsg; ! 651: ULONG ulCreate; ! 652: HWND hwndFrame; ! 653: HWND hwndClient; ! 654: static CHAR szApp[] = "Char Messages"; ! 655: ! 656: /* init app */ ! 657: hab = WinInitialize(NULL); ! 658: hmq = WinCreateMsgQueue(hab, 0); ! 659: GetDisplayValues(); ! 660: ! 661: /* create main window */ ! 662: WinRegisterClass(hab, szApp, MainWndProc, 0L, 0); ! 663: ulCreate = FCF_TITLEBAR | FCF_SYSMENU | FCF_MINMAX | FCF_SIZEBORDER | ! 664: FCF_MENU | FCF_SHELLPOSITION; ! 665: hwndFrame = WinCreateStdWindow(HWND_DESKTOP, WS_VISIBLE, &ulCreate, ! 666: szApp, szApp, 0L, NULL, ID_RESOURCES, ! 667: &hwndClient); ! 668: ! 669: /* register with switch list */ ! 670: RegisterSwitchEntry(hwndFrame); ! 671: ! 672: /* initialize menu */ ! 673: CheckMenus(hwndFrame); ! 674: ! 675: /* message loop */ ! 676: while (WinGetMsg(hab, &qmsg, NULL, 0, 0)) ! 677: WinDispatchMsg(hab, &qmsg); ! 678: ! 679: /* clean up */ ! 680: WinDestroyWindow(hwndFrame); ! 681: WinDestroyMsgQueue(hmq); ! 682: WinTerminate(hab); ! 683: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.