home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / tcltk805.zip / tcl805s.zip / tk8.0.5 / os2 / tkOS2X.c < prev    next >
C/C++ Source or Header  |  2001-09-08  |  45KB  |  1,381 lines

  1. /* 
  2.  * tkOS2X.c --
  3.  *
  4.  *    This file contains OS/2 PM emulation procedures for X routines. 
  5.  *
  6.  * Copyright (c) 1996-2000 Illya Vaes
  7.  * Copyright (c) 1995 Sun Microsystems, Inc.
  8.  * Copyright (c) 1994 Software Research Associates, Inc.
  9.  *
  10.  * See the file "license.terms" for information on usage and redistribution
  11.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  12.  */
  13.  
  14.  
  15. #include "tkInt.h"
  16. #include "tkOS2Int.h"
  17.  
  18. /*
  19.  * Declarations of static variables used in this file.
  20.  */
  21.  
  22. static TkDisplay *os2Display = NULL;    /* Display representing PM screen. */
  23. static char os2ScreenName[] = "PM:0";    /* Default name of OS2 display. */
  24. static int childClassInitialized = 0;    /* Registered child class? */
  25.  
  26. /*
  27.  * Forward declarations of procedures used in this file.
  28.  */
  29.  
  30. static void             GenerateXEvent _ANSI_ARGS_((HWND hwnd, ULONG message,
  31.                             MPARAM param1, MPARAM param2));
  32. static unsigned int     GetState _ANSI_ARGS_((ULONG message, MPARAM param1,
  33.                             MPARAM param2));
  34.  
  35. /*
  36.  *----------------------------------------------------------------------
  37.  *
  38.  * TkGetServerInfo --
  39.  *
  40.  *    Given a window, this procedure returns information about
  41.  *    the window server for that window.  This procedure provides
  42.  *    the guts of the "winfo server" command.
  43.  *
  44.  * Results:
  45.  *    None.
  46.  *
  47.  * Side effects:
  48.  *    None.
  49.  *
  50.  *----------------------------------------------------------------------
  51.  */
  52.  
  53. void
  54. TkGetServerInfo(interp, tkwin)
  55.     Tcl_Interp *interp;        /* The server information is returned in
  56.                  * this interpreter's result. */
  57.     Tk_Window tkwin;        /* Token for window;  this selects a
  58.                  * particular display and server. */
  59. {
  60.     char buffer[50];
  61.     ULONG info[QSV_MAX]= {0};    /* System Information Data Buffer */
  62.     APIRET rc;
  63.  
  64.     /* Request all available system information */
  65.     rc= DosQuerySysInfo (1L, QSV_MAX, (PVOID)info, sizeof(info));
  66.     /*
  67.      * Hack for LX-versions above 2.11
  68.      *  OS/2 version    MAJOR MINOR
  69.      *  2.0             20    0
  70.      *  2.1             20    10
  71.      *  2.11            20    11
  72.      *  3.0             20    30
  73.      *  4.0             20    40
  74.      */
  75.     if (info[QSV_VERSION_MAJOR - 1] == 20 && info[QSV_VERSION_MINOR - 1] > 11) {
  76.         int major = (int) (info[QSV_VERSION_MINOR - 1] / 10);
  77.         if (info[QSV_VERSION_REVISION - 1] != 0) {
  78.             sprintf(buffer, "OS/2 PM %d.%d revision %d", major,
  79.                     (int) (info[QSV_VERSION_MINOR - 1] - major * 10),
  80.                     (int) info[QSV_VERSION_REVISION - 1]);
  81.         } else {
  82.             sprintf(buffer, "OS/2 PM %d.%d", major,
  83.                     (int) (info[QSV_VERSION_MINOR - 1] - major * 10));
  84.         }
  85.     } else {
  86.         if (info[QSV_VERSION_REVISION - 1] != 0) {
  87.             sprintf(buffer, "OS/2 PM %d.%d revision %d",
  88.                     (int) (info[QSV_VERSION_MAJOR - 1] / 10),
  89.                     (int) info[QSV_VERSION_MINOR - 1],
  90.                     (int) info[QSV_VERSION_REVISION - 1]);
  91.         } else {
  92.             sprintf(buffer, "OS/2 PM %d.%d",
  93.                     (int) (info[QSV_VERSION_MAJOR - 1] / 10),
  94.                     (int) info[QSV_VERSION_MINOR - 1]);
  95.         }
  96.     }
  97.     Tcl_AppendResult(interp, buffer, (char *) NULL);
  98. #ifdef VERBOSE
  99.     printf("TkGetServerInfo [%s]\n", buffer);
  100. #endif
  101. }
  102.  
  103. /*
  104.  *----------------------------------------------------------------------
  105.  *
  106.  * Tk_GetHMODULE --
  107.  *
  108.  *      Retrieves the global instance handle used by the Tk library.
  109.  *
  110.  * Results:
  111.  *      Returns the library module handle.
  112.  *
  113.  * Side effects:
  114.  *      None.
  115.  *
  116.  *----------------------------------------------------------------------
  117.  */
  118.  
  119. HMODULE
  120. Tk_GetHMODULE()
  121. {
  122. #ifdef VERBOSE
  123.     printf("Tk_GetHMODULE\n");
  124. #endif
  125.     return dllHandle;
  126. }
  127.  
  128. /*
  129.  *----------------------------------------------------------------------
  130.  *
  131.  * TkOS2XInit --
  132.  *
  133.  *    Initialize Xlib emulation layer.
  134.  *
  135.  * Results:
  136.  *    None.
  137.  *
  138.  * Side effects:
  139.  *    Sets up various data structures.
  140.  *
  141.  *----------------------------------------------------------------------
  142.  */
  143.  
  144. void
  145. TkOS2XInit( hModule )
  146.     HMODULE hModule;
  147. {
  148.     BOOL success;
  149.  
  150. #ifdef VERBOSE
  151.     printf("TkOS2XInit\n");
  152. #endif
  153.     if (childClassInitialized != 0) {
  154.         return;
  155.     }
  156.     childClassInitialized = 1;
  157.  
  158.     /*
  159.      * Register the Child window class.
  160.      */
  161.  
  162.     /*
  163.      * Don't use CS_SIZEREDRAW for the child, this will make vertical resizing
  164.      * work incorrectly (keeping the same distance from the bottom instead of
  165.      * from the top when using Tk's "pack ... -side top").
  166.      */
  167.     success = WinRegisterClass(TclOS2GetHAB(), TOC_CHILD, TkOS2ChildProc, 0,
  168.                                sizeof(ULONG));
  169.     if (!success) {
  170.         panic("Unable to register TkChild class");
  171.     }
  172. }
  173.  
  174. /*
  175.  *----------------------------------------------------------------------
  176.  *
  177.  * TkOS2XCleanup --
  178.  *
  179.  *      Removes the registered classes for Tk.
  180.  *
  181.  * Results:
  182.  *      None.
  183.  *
  184.  * Side effects:
  185.  *      Removes window classes from the system.
  186.  *
  187.  *----------------------------------------------------------------------
  188.  */
  189.  
  190. void
  191. TkOS2XCleanup(hModule)
  192.     HMODULE hModule;
  193. {
  194.     /*
  195.      * Clean up our own class.
  196.      */
  197.  
  198. #ifdef VERBOSE
  199.     printf("TkOS2XCleanup\n");
  200. #endif
  201.     if (childClassInitialized) {
  202.         childClassInitialized = 0;
  203.     }
  204.  
  205.     /*
  206.      * And let the window manager clean up its own class(es).
  207.      */
  208.  
  209.     TkOS2WmCleanup(hModule);
  210. }
  211.  
  212. /*
  213.  *----------------------------------------------------------------------
  214.  *
  215.  * TkGetDefaultScreenName --
  216.  *
  217.  *      Returns the name of the screen that Tk should use during
  218.  *      initialization.
  219.  *
  220.  * Results:
  221.  *      Returns a statically allocated string.
  222.  *
  223.  * Side effects:
  224.  *      None.
  225.  *
  226.  *----------------------------------------------------------------------
  227.  */
  228.  
  229. char *
  230. TkGetDefaultScreenName(interp, screenName)
  231.     Tcl_Interp *interp;         /* Not used. */
  232.     char *screenName;           /* If NULL, use default string. */
  233. {
  234.     char *DISPLAY = NULL;
  235.  
  236. #ifdef VERBOSE
  237.     printf("TkGetDefaultScreenName [%s] ", screenName);
  238. #endif
  239.     if ((screenName == NULL) || (screenName[0] == '\0')) {
  240.         DISPLAY = getenv("DISPLAY");
  241.         if (DISPLAY != NULL) {
  242.             screenName = DISPLAY;
  243.         } else {
  244.             screenName = os2ScreenName;
  245.         }
  246.     }
  247. #ifdef VERBOSE
  248.     printf("returns [%s]\n", screenName);
  249. #endif
  250.     return screenName;
  251. }
  252.  
  253. /*
  254.  *----------------------------------------------------------------------
  255.  *
  256.  * TkpOpenDisplay --
  257.  *
  258.  *    Create the Display structure and fill it with device
  259.  *    specific information.
  260.  *
  261.  * Results:
  262.  *    Returns a Display structure on success or NULL on failure.
  263.  *
  264.  * Side effects:
  265.  *    Allocates a new Display structure.
  266.  *
  267.  *----------------------------------------------------------------------
  268.  */
  269.  
  270. TkDisplay *
  271. TkpOpenDisplay(display_name)
  272.     char *display_name;
  273. {
  274.     Screen *screen;
  275.     TkOS2Drawable *todPtr;
  276.     Display *display;
  277. #ifdef VERBOSE
  278.     printf("TkpOpenDisplay(\"%s\"), os2Display %x\n", display_name, os2Display);
  279. #endif
  280.  
  281.     if (os2Display != NULL) {
  282.     if (strcmp(os2Display->display->display_name, display_name) == 0) {
  283.         return os2Display;
  284.     } else {
  285.         return NULL;
  286.     }
  287.     }
  288.  
  289.     display = (Display *) ckalloc(sizeof(Display));
  290.     if (!display) {
  291.         return NULL;
  292.     }
  293. #ifdef VERBOSE
  294.     printf("ckalloc Display returned %x\n", display);
  295. #endif
  296.     display->display_name = (char *) ckalloc(strlen(display_name)+1);
  297.     if (!display->display_name) {
  298.     ckfree((char *)display);
  299.         return NULL;
  300.     }
  301.     strcpy(display->display_name, display_name);
  302.  
  303.     display->cursor_font = 1;
  304.     display->nscreens = 1;
  305.     display->request = 1;
  306.     display->qlen = 0;
  307.  
  308.     screen = (Screen *) ckalloc(sizeof(Screen));
  309.     if (!screen) {
  310.     ckfree((char *)display->display_name);
  311.     ckfree((char *)display);
  312.     return NULL;
  313.     }
  314. #ifdef VERBOSE
  315.     printf("ckalloc Screen returned %x\n", screen);
  316. #endif
  317.     screen->display = display;
  318.  
  319.     screen->width = aDevCaps[CAPS_WIDTH];
  320.     screen->height = yScreen;
  321.     screen->mwidth = (screen->width*1000)/ aDevCaps[CAPS_HORIZONTAL_RESOLUTION];
  322.     screen->mheight = (screen->height*1000)/ aDevCaps[CAPS_VERTICAL_RESOLUTION];
  323.  
  324.     /*
  325.      * Set up the root window.
  326.      */
  327.  
  328.     todPtr = (TkOS2Drawable*) ckalloc(sizeof(TkOS2Drawable));
  329.     if (!todPtr) {
  330.     ckfree((char *)display->display_name);
  331.     ckfree((char *)display);
  332.     ckfree((char *)screen);
  333.     return NULL;
  334.     }
  335. #ifdef VERBOSE
  336.     printf("    new todPtr (drawable) %x\n", todPtr);
  337. #endif
  338.     todPtr->type = TOD_WINDOW;
  339.     todPtr->window.winPtr = NULL;
  340.     todPtr->window.handle = HWND_DESKTOP;
  341.     screen->root = (Window)todPtr;
  342.  
  343.     /*
  344.      * On OS/2, when creating a color bitmap, need two pieces of
  345.      * information: the number of color planes and the number of
  346.      * pixels per plane.  Need to remember both quantities so that
  347.      * when constructing an HBITMAP for offscreen rendering, we can
  348.      * specify the correct value for the number of planes.  Otherwise
  349.      * the HBITMAP won't be compatible with the HWND and we'll just
  350.      * get blank spots copied onto the screen.
  351.      */
  352.  
  353.     screen->ext_data = (XExtData *) aDevCaps[CAPS_COLOR_PLANES];
  354.     screen->root_depth = aDevCaps[CAPS_COLOR_BITCOUNT] * (int) screen->ext_data;
  355.  
  356.     screen->root_visual = (Visual *) ckalloc(sizeof(Visual));
  357.     if (!screen->root_visual) {
  358.     ckfree((char *)display->display_name);
  359.     ckfree((char *)display);
  360.     ckfree((char *)screen);
  361.     ckfree((char *)todPtr);
  362.     return NULL;
  363.     }
  364.     screen->root_visual->visualid = 0;
  365.     if ( aDevCaps[CAPS_ADDITIONAL_GRAPHICS] & CAPS_PALETTE_MANAGER ) {
  366.     screen->root_visual->map_entries = aDevCaps[CAPS_COLORS];
  367.     screen->root_visual->class = PseudoColor;
  368.         screen->root_visual->red_mask = 0x0;
  369.         screen->root_visual->green_mask = 0x0;
  370.         screen->root_visual->blue_mask = 0x0;
  371.     } else {
  372.     if (screen->root_depth == 4) {
  373.         screen->root_visual->class = StaticColor;
  374.         screen->root_visual->map_entries = 16;
  375. screen->root_visual->map_entries = aDevCaps[CAPS_COLOR_INDEX]+1;
  376.         } else if (screen->root_depth == 8) {
  377.             screen->root_visual->class = StaticColor;
  378.             screen->root_visual->map_entries = 256;
  379.         } else if (screen->root_depth == 12) {
  380.             screen->root_visual->class = TrueColor;
  381.             screen->root_visual->map_entries = 32;
  382. screen->root_visual->map_entries = aDevCaps[CAPS_COLOR_INDEX]+1;
  383.             screen->root_visual->red_mask = 0xf0;
  384.             screen->root_visual->green_mask = 0xf000;
  385.             screen->root_visual->blue_mask = 0xf00000;
  386.     } else if (screen->root_depth == 16) {
  387.         screen->root_visual->class = TrueColor;
  388.         screen->root_visual->map_entries = 64;
  389. screen->root_visual->map_entries = aDevCaps[CAPS_COLOR_INDEX]+1;
  390.             screen->root_visual->red_mask = 0xf8;
  391.             screen->root_visual->green_mask = 0xfc00;
  392.             screen->root_visual->blue_mask = 0xf80000;
  393.         /*
  394.         screen->root_visual->map_entries = aDevCaps[CAPS_COLOR_INDEX]+1;
  395.         screen->root_visual->red_mask = 0xff;
  396.         screen->root_visual->green_mask = 0xff00;
  397.         screen->root_visual->blue_mask = 0xff0000;
  398.         */
  399.     } else if (screen->root_depth >= 24) {
  400.         screen->root_visual->class = TrueColor;
  401.         screen->root_visual->map_entries = 256;
  402.         screen->root_visual->red_mask = 0xff;
  403.         screen->root_visual->green_mask = 0xff00;
  404.         screen->root_visual->blue_mask = 0xff0000;
  405.     }
  406.     }
  407.     screen->root_visual->bits_per_rgb = screen->root_depth;
  408.  
  409.     /*
  410.      * Note that these pixel values are not palette relative.
  411.      */
  412.  
  413.     screen->white_pixel = RGB(255, 255, 255);
  414.     screen->black_pixel = RGB(0, 0, 0);
  415.  
  416.     display->screens = screen;
  417.     display->nscreens = 1;
  418.     display->default_screen = 0;
  419.     screen->cmap = XCreateColormap(display, None, screen->root_visual,
  420.         AllocNone);
  421.     os2Display = (TkDisplay *) ckalloc(sizeof(TkDisplay));
  422.     if (!os2Display) {
  423.         ckfree((char *)screen->root_visual);
  424.     ckfree((char *)display->display_name);
  425.     ckfree((char *)display);
  426.     ckfree((char *)screen);
  427.     ckfree((char *)todPtr);
  428.         return NULL;
  429.     }
  430.     os2Display->display = display;
  431. #ifdef VERBOSE
  432.     printf("    os2Display %x, display %x, screens %x\n", os2Display,
  433.            os2Display->display, os2Display->display->screens);
  434. #endif
  435.     return os2Display;
  436. }
  437.  
  438. /*
  439.  *----------------------------------------------------------------------
  440.  *
  441.  * TkpCloseDisplay --
  442.  *
  443.  *      Closes and deallocates a Display structure created with the
  444.  *      TkpOpenDisplay function.
  445.  *
  446.  * Results:
  447.  *      None.
  448.  *
  449.  * Side effects:
  450.  *      Frees up memory.
  451.  *
  452.  *----------------------------------------------------------------------
  453.  */
  454.  
  455. void
  456. TkpCloseDisplay(dispPtr)
  457.     TkDisplay *dispPtr;
  458. {
  459.     Display *display = dispPtr->display;
  460.     HWND hwnd;
  461.  
  462. #ifdef VERBOSE
  463.     printf("TkpCloseDisplay TkDisplay %x, Display %x\n", dispPtr, display);
  464. #endif
  465.     if (dispPtr != os2Display) {
  466.         panic("TkpCloseDisplay: tried to call TkpCloseDisplay on another display
  467. ");
  468.         return;
  469.     }
  470.  
  471.     /*
  472.      * Force the clipboard to be rendered if we are the clipboard owner.
  473.      */
  474.  
  475.     if (dispPtr->clipWindow) {
  476.         hwnd = Tk_GetHWND(Tk_WindowId(dispPtr->clipWindow));
  477.         if (WinQueryClipbrdOwner(TclOS2GetHAB()) == hwnd) {
  478.             WinOpenClipbrd(TclOS2GetHAB());
  479.             WinEmptyClipbrd(TclOS2GetHAB());
  480.             TkOS2ClipboardRender(dispPtr, CF_TEXT);
  481.             WinCloseClipbrd(TclOS2GetHAB());
  482.         }
  483.     }
  484.  
  485.     /* Memory gets freed via dispPtr */
  486.     os2Display = NULL;
  487.  
  488.     if (display->display_name != (char *) NULL) {
  489.         ckfree(display->display_name);
  490.     }
  491.     if (display->screens != (Screen *) NULL) {
  492.         if (display->screens->root_visual != NULL) {
  493.             ckfree((char *) display->screens->root_visual);
  494.         }
  495.         if (display->screens->root != None) {
  496.             ckfree((char *) display->screens->root);
  497.         }
  498.         if (display->screens->cmap != None) {
  499.             XFreeColormap(display, display->screens->cmap);
  500.         }
  501.         ckfree((char *) display->screens);
  502.     }
  503.     ckfree((char *) display);
  504.     ckfree((char *) dispPtr);
  505. }
  506.  
  507. /*
  508.  *----------------------------------------------------------------------
  509.  *
  510.  * XBell --
  511.  *
  512.  *    Generate a beep.
  513.  *
  514.  * Results:
  515.  *    None.
  516.  *
  517.  * Side effects:
  518.  *    Plays a sound.
  519.  *
  520.  *----------------------------------------------------------------------
  521.  */
  522.  
  523. void
  524. XBell(display, percent)
  525.     Display* display;
  526.     int percent;
  527. {
  528.     if (!WinAlarm(HWND_DESKTOP, WA_NOTE)) {
  529.         DosBeep (770L, 300L);
  530.     }
  531. }
  532.  
  533. /*
  534.  *----------------------------------------------------------------------
  535.  *
  536.  * TkOS2ChildProc --
  537.  *
  538.  *    Callback from Presentation Manager whenever an event occurs on
  539.  *    a child window.
  540.  *
  541.  * Results:
  542.  *    Standard OS/2 PM return value.
  543.  *
  544.  * Side effects:
  545.  *    Default window behavior.
  546.  *
  547.  *----------------------------------------------------------------------
  548.  */
  549.  
  550. MRESULT EXPENTRY
  551. TkOS2ChildProc(hwnd, message, param1, param2)
  552.     HWND hwnd;
  553.     ULONG message;
  554.     MPARAM param1;
  555.     MPARAM param2;
  556. {
  557.     MRESULT result;
  558. #ifdef VERBOSE
  559.     printf("TkOS2ChildProc hwnd %x, msg %x, p1 %x, p2 %x\n", hwnd, message,
  560.            param1, param2);
  561.     switch (message) {
  562.         case WM_ACTIVATE: printf("   WM_ACTIVATE Child %x\n", hwnd); break;
  563.         case WM_ADJUSTFRAMEPOS: printf("   WM_ADJUSTFRAMEPOS Child %x\n", hwnd); break;
  564.         case WM_ADJUSTWINDOWPOS:
  565.             printf("  WM_ADJUSTWINDOWPOS Child %x (%d,%d) %dx%d fl %x\n", hwnd,
  566.                    ((PSWP)param1)->x, ((PSWP)param1)->y, ((PSWP)param1)->cx,
  567.                    ((PSWP)param1)->cy, ((PSWP)param1)->fl);
  568.             break;
  569.         case WM_BUTTON1DOWN: printf("   WM_BUTTON1DOWN Child %x\n", hwnd); break;
  570.         case WM_BUTTON1UP: printf("   WM_BUTTON1UP Child %x\n", hwnd); break;
  571.         case WM_BUTTON1DBLCLK: printf("   WM_BUTTON1DBLCLK Child %x\n", hwnd); break;
  572.         case WM_BUTTON2DOWN: printf("   WM_BUTTON2DOWN Child %x\n", hwnd); break;
  573.         case WM_BUTTON2UP: printf("   WM_BUTTON2UP Child %x\n", hwnd); break;
  574.         case WM_BUTTON2DBLCLK: printf("   WM_BUTTON2DBLCLK Child %x\n", hwnd); break;
  575.         case WM_BUTTON3DOWN: printf("   WM_BUTTON3DOWN Child %x\n", hwnd); break;
  576.         case WM_BUTTON3UP: printf("   WM_BUTTON3UP Child %x\n", hwnd); break;
  577.         case WM_BUTTON3DBLCLK: printf("   WM_BUTTON3DBLCLK Child %x\n", hwnd); break;
  578.         case WM_CALCFRAMERECT: printf("   WM_CALCFRAMERECT Child %x\n", hwnd); break;
  579.         case WM_CALCVALIDRECTS: printf("   WM_CALCVALIDRECTS Child %x\n", hwnd); break;
  580.         case WM_CLOSE: printf("   WM_CLOSE Child %x\n", hwnd); break;
  581.         case WM_COMMAND: printf("   WM_COMMAND Child %x cmd %d s %d p %d\n",
  582.                                 hwnd, SHORT1FROMMP(param1),
  583.                                 SHORT1FROMMP(param2), SHORT2FROMMP(param2));
  584.              break;
  585.         case WM_CREATE: printf("   WM_CREATE Child %x\n", hwnd); break;
  586.         case WM_DESTROY: printf("   WM_DESTROY Child %x\n", hwnd); break;
  587.         case WM_ERASEBACKGROUND: printf("   WM_ERASEBACKGROUND Child %x\n", hwnd); break;
  588.         case WM_FOCUSCHANGE: printf("   WM_FOCUSCHANGE Child %x\n", hwnd); break;
  589.         case WM_FORMATFRAME: printf("   WM_FORMATFRAME Child %x\n", hwnd); break;
  590.         case WM_HSCROLL: printf("   WM_HSCROLL Child %x\n", hwnd); break;
  591.         case WM_MINMAXFRAME: printf("   WM_MINMAXFRAME Child %x\n", hwnd); break;
  592.         case WM_MOUSEMOVE: printf("   WM_MOUSEMOVE Child %x p1 %x p2 %x\n",
  593.                                   hwnd, param1, param2); break;
  594.         case WM_MOVE: printf("   WM_MOVE Child %x\n", hwnd); break;
  595.         case WM_OWNERPOSCHANGE: printf("   WM_OWNERPOSCHANGE Child %x\n", hwnd); break;
  596.         case WM_PAINT: printf("   WM_PAINT Child %x\n", hwnd); break;
  597.         case WM_QUERYBORDERSIZE: printf("   WM_QUERYBORDERSIZE Child %x\n", hwnd); break;
  598.         case WM_QUERYDLGCODE: printf("   WM_QUERYDLGCODE Child %x\n", hwnd); break;
  599.         case WM_QUERYFRAMECTLCOUNT: printf("   WM_QUERYFRAMECTLCOUNT Child %x\n", hwnd); break;
  600.         case WM_QUERYFOCUSCHAIN: printf("   WM_QUERYFOCUSCHAIN Child %x\n", hwnd); break;
  601.         case WM_QUERYICON: printf("   WM_QUERYICON Child %x\n", hwnd); break;
  602.         case WM_QUERYTRACKINFO: printf("   WM_QUERYTRACKINFO Child %x\n", hwnd); break;
  603.         case WM_REALIZEPALETTE: printf("   WM_REALIZEPALETTE Child %x\n", hwnd); break;
  604.         case WM_SETFOCUS: printf("   WM_SETFOCUS Child %x\n", hwnd); break;
  605.         case WM_SETSELECTION: printf("   WM_SETSELECTION Child %x\n", hwnd); break;
  606.         case WM_TRANSLATEACCEL: printf("   WM_TRANSLATEACCEL Child %x\n", hwnd); break;
  607.         case WM_UPDATEFRAME: printf("   WM_UPDATEFRAME Child %x\n", hwnd); break;
  608.         case WM_VSCROLL: printf("   WM_VSCROLL Child %x\n", hwnd); break;
  609.         case WM_WINDOWPOSCHANGED:
  610.             printf("  WM_WINDOWPOSCHANGED Child %x (%d,%d) %dx%d fl %x\n", hwnd,
  611.                    ((PSWP)param1)->x, ((PSWP)param1)->y, ((PSWP)param1)->cx,
  612.                    ((PSWP)param1)->cy, ((PSWP)param1)->fl);
  613.             break;
  614.     }
  615. #endif
  616.  
  617.     switch (message) {
  618.         case WM_CONTROLPOINTER:
  619.             /*
  620.              * Short circuit the WM_CONTROLPOINTER message since we set
  621.              * the cursor elsewhere.
  622.              */
  623.  
  624.             result = param2;
  625.             break;
  626.  
  627.         case WM_CREATE:
  628.         case WM_WINDOWPOSCHANGED:
  629.         case WM_UPDATEFRAME:
  630.         case WM_ERASEBACKGROUND:
  631.             result = 0;
  632.             break;
  633.  
  634.         case WM_PAINT:
  635.             GenerateXEvent(hwnd, message, param1, param2);
  636.             result = WinDefWindowProc(hwnd, message, param1, param2);
  637.             break;
  638.  
  639.         case TK_CLAIMFOCUS:
  640.         case TK_GEOMETRYREQ:
  641.         case TK_ATTACHWINDOW:
  642.         case TK_DETACHWINDOW:
  643. #ifdef VERBOSE
  644.             printf("TK_CLAIMFOCUS/GEOMETRYREQ/ATTACHWIN/DETACHWIN");
  645.         printf(" h %x, p1 %x\n", hwnd, param1);
  646.         fflush(stdout);
  647. #endif
  648.             result = TkOS2EmbeddedEventProc(hwnd, message, param1, param2);
  649.             break;
  650.  
  651.         default:
  652. #ifdef VERBOSE
  653.             printf("default, trying Tk_TranslateOS2Event\n");
  654.         fflush(stdout);
  655. #endif
  656.             if (!Tk_TranslateOS2Event(hwnd, message, param1, param2,
  657.                     &result)) {
  658. #ifdef VERBOSE
  659.                 printf("Tk_TranslateOS2Event FALSE => WinDefWindowProc\n");
  660.             fflush(stdout);
  661. #endif
  662.                 result = WinDefWindowProc(hwnd, message, param1, param2);
  663. #ifdef VERBOSE
  664.             } else {
  665.                 printf("Tk_TranslateOS2Event TRUE\n");
  666.             fflush(stdout);
  667. #endif
  668.             }
  669.             break;
  670.     }
  671. #ifdef VERBOSE
  672.     switch (message) {
  673.         case WM_WINDOWPOSCHANGED:
  674.             printf("   WM_WINDOWPOSCHANGED Child %x now (%d,%d) %dx%d\n", hwnd,
  675.                    ((PSWP)param1)->x, ((PSWP)param1)->y, ((PSWP)param1)->cx,
  676.                    ((PSWP)param1)->cy);
  677.             break;
  678.     }
  679. #endif
  680.  
  681.     /*
  682.      * Handle any newly queued events before returning control to PM.
  683.      */
  684.  
  685.     Tcl_ServiceAll();
  686.     return result;
  687. }
  688.  
  689. /*
  690.  *----------------------------------------------------------------------
  691.  *
  692.  * Tk_TranslateOS2Event --
  693.  *
  694.  *    This function is called by the window procedures to handle
  695.  *    the translation from OS/2 PM events to Tk events.
  696.  *
  697.  * Results:
  698.  *    Returns 1 if the event was handled, else 0.
  699.  *
  700.  * Side effects:
  701.  *    Depends on the event.
  702.  *
  703.  *----------------------------------------------------------------------
  704.  */
  705.  
  706. int
  707. Tk_TranslateOS2Event(hwnd, message, param1, param2, resultPtr)
  708.     HWND hwnd;
  709.     ULONG message;
  710.     MPARAM param1;
  711.     MPARAM param2;
  712.     MRESULT *resultPtr;
  713. {
  714. #ifdef VERBOSE
  715.     printf("Tk_TranslateOS2Event hwnd %x msg %x p1 %x p2 %x resultPtr %x\n",
  716.            hwnd, message, param1, param2, resultPtr);
  717.     fflush(stdout);
  718. #endif
  719.     *resultPtr = (MPARAM)0;
  720.     switch (message) {
  721.         case WM_RENDERFMT: {
  722.             TkWindow *winPtr = (TkWindow *) Tk_HWNDToWindow(hwnd);
  723. #ifdef VERBOSE
  724.             printf("Tk_HWNDToWindow(%x) winPtr %x\n", hwnd, winPtr);
  725. #endif
  726.             if (winPtr) {
  727.                 TkOS2ClipboardRender(winPtr->dispPtr,
  728.                                      (ULONG)(SHORT1FROMMP(param1)));
  729.             }
  730.             return 1;
  731.         }
  732.  
  733.             /*
  734.         case WM_CONTROL:
  735.         case WM_VSCROLL:
  736.         case WM_HSCROLL: {
  737.              * Reflect these messages back to the sender so that they
  738.              * can be handled by the window proc for the control.  Note
  739.              * that we need to be careful not to reflect a message that
  740.              * is targeted to this window, or we will loop.
  741.  
  742.             HWND target = WinWindowFromID(hwnd, (ULONG)(SHORT1FROMMP(param1)));
  743.             if (target && target != hwnd) {
  744.                 *resultPtr = WinSendMsg(target, message, param1, param2);
  745.                 return 1;
  746.             }
  747.             break;
  748.             return 0;
  749.         }
  750.              */
  751.  
  752.         case WM_BUTTON1DOWN:
  753.         case WM_BUTTON1UP:
  754.         case WM_BUTTON2DOWN:
  755.         case WM_BUTTON2UP:
  756.         case WM_BUTTON3DOWN:
  757.         case WM_BUTTON3UP:
  758. #ifdef VERBOSE
  759.              printf("calling Tk_PointerEvent(%hd,%hd) for WM_BUTTON%s\n",
  760.                     SHORT1FROMMP(param1), SHORT2FROMMP(param1),
  761.                     message == WM_BUTTON1DOWN ? "1DOWN" :
  762.                     (message == WM_BUTTON2DOWN ? "2DOWN" :
  763.                     (message == WM_BUTTON3DOWN ? "3DOWN" :
  764.                     (message == WM_BUTTON1UP ? "1UP" :
  765.                     (message == WM_BUTTON2UP ? "2UP" :
  766.                     (message == WM_BUTTON3UP ? "3UP" : "???"))))));
  767. #endif
  768.             Tk_PointerEvent(hwnd, SHORT1FROMMP(param1), SHORT2FROMMP(param1));
  769.             *resultPtr = (MPARAM)1;
  770.             return 1;
  771.  
  772.         case WM_BUTTON1DBLCLK:
  773.         message = WM_BUTTON1DOWN;
  774.             Tk_PointerEvent(hwnd, SHORT1FROMMP(param1), SHORT2FROMMP(param1));
  775.         message = WM_BUTTON1UP;
  776.             Tk_PointerEvent(hwnd, SHORT1FROMMP(param1), SHORT2FROMMP(param1));
  777.         message = WM_BUTTON1DOWN;
  778.             Tk_PointerEvent(hwnd, SHORT1FROMMP(param1), SHORT2FROMMP(param1));
  779.         message = WM_BUTTON1UP;
  780.             Tk_PointerEvent(hwnd, SHORT1FROMMP(param1), SHORT2FROMMP(param1));
  781.             *resultPtr = (MPARAM)1;
  782.             return 1;
  783.  
  784.         case WM_BUTTON2DBLCLK:
  785.         message = WM_BUTTON2DOWN;
  786.             Tk_PointerEvent(hwnd, SHORT1FROMMP(param1), SHORT2FROMMP(param1));
  787.         message = WM_BUTTON2UP;
  788.             Tk_PointerEvent(hwnd, SHORT1FROMMP(param1), SHORT2FROMMP(param1));
  789.         message = WM_BUTTON2DOWN;
  790.             Tk_PointerEvent(hwnd, SHORT1FROMMP(param1), SHORT2FROMMP(param1));
  791.         message = WM_BUTTON2UP;
  792.             Tk_PointerEvent(hwnd, SHORT1FROMMP(param1), SHORT2FROMMP(param1));
  793.             *resultPtr = (MPARAM)1;
  794.             return 1;
  795.  
  796.         case WM_BUTTON3DBLCLK:
  797.         message = WM_BUTTON3DOWN;
  798.             Tk_PointerEvent(hwnd, SHORT1FROMMP(param1), SHORT2FROMMP(param1));
  799.         message = WM_BUTTON3UP;
  800.             Tk_PointerEvent(hwnd, SHORT1FROMMP(param1), SHORT2FROMMP(param1));
  801.         message = WM_BUTTON3DOWN;
  802.             Tk_PointerEvent(hwnd, SHORT1FROMMP(param1), SHORT2FROMMP(param1));
  803.         message = WM_BUTTON3UP;
  804.             Tk_PointerEvent(hwnd, SHORT1FROMMP(param1), SHORT2FROMMP(param1));
  805.             *resultPtr = (MPARAM)1;
  806.             return 1;
  807.  
  808.         case WM_MOUSEMOVE:
  809. #ifdef VERBOSE
  810.             printf("Child %x: WM_MOUSEMOVE (%hd,%hd) HIT %x, fl %x\n", hwnd,
  811.                    SHORT1FROMMP(param1), SHORT2FROMMP(param1),
  812.                    SHORT1FROMMP(param2), SHORT2FROMMP(param2));
  813. #endif
  814.             Tk_PointerEvent(hwnd, SHORT1FROMMP(param1), SHORT2FROMMP(param1));
  815.             *resultPtr = (MPARAM)1;
  816.             return 1;
  817.  
  818.         case WM_CLOSE:
  819. #ifdef VERBOSE
  820.             printf("Child: WM_CLOSE\n");
  821. #endif
  822.         case WM_SETFOCUS:
  823. #ifdef VERBOSE
  824.             printf("Child: WM_SETFOCUS\n");
  825. #endif
  826.         case WM_DESTROYCLIPBOARD:
  827. #ifdef VERBOSE
  828.             printf("Child: WM_DESTROYCLIPBOARD\n");
  829. #endif
  830.         case WM_CHAR:
  831. #ifdef VERBOSE
  832.             printf("Child: WM_CHAR\n");
  833.             fflush(stdout);
  834. #endif
  835.             GenerateXEvent(hwnd, message, param1, param2);
  836.             return 1;
  837.  
  838.         /* Added by/for Ilya Zakharevich: */
  839.         case WM_TRANSLATEACCEL: {
  840.             PQMSG pqmsg = PVOIDFROMMP(param1);
  841.             USHORT flags = (USHORT) SHORT1FROMMP(pqmsg->mp1);
  842.             USHORT charcode = (USHORT) SHORT1FROMMP(pqmsg->mp2);
  843.             USHORT vkeycode = (USHORT) SHORT2FROMMP(pqmsg->mp2);
  844. #ifdef VERBOSE
  845.             printf("Child: WM_TRANSLATEACCEL vk %x char %x fl %x\n", vkeycode,
  846.                    charcode, flags);
  847. #endif
  848.  
  849.             if (flags & KC_VIRTUALKEY) {
  850.                 switch (vkeycode) {
  851.                     case VK_F1:
  852.                     case VK_F10:
  853.                     case VK_SPACE:
  854.                         /* Do not consider as a shortcut */
  855.  
  856.                         return 1;
  857.                 }
  858.             } else if ( charcode == ' ') { /* Alt-Space */
  859.                 /* Do not consider as a shortcut */
  860.                 return 1;
  861.             }
  862.             break;
  863.         }
  864.     }
  865.     return 0;
  866. }
  867.  
  868. /*
  869.  *----------------------------------------------------------------------
  870.  *
  871.  * GenerateXEvent --
  872.  *
  873.  *      This routine generates an X event from the corresponding
  874.  *      OS/2 PM event.
  875.  *
  876.  * Results:
  877.  *      None.
  878.  *
  879.  * Side effects:
  880.  *      Queues one or more X events.
  881.  *
  882.  *----------------------------------------------------------------------
  883.  */
  884.  
  885. static void
  886. GenerateXEvent(hwnd, message, param1, param2)
  887.     HWND hwnd;
  888.     ULONG message;
  889.     MPARAM param1;
  890.     MPARAM param2;
  891. {
  892.     XEvent event;
  893.     TkWindow *winPtr = (TkWindow *)Tk_HWNDToWindow(hwnd);
  894. #ifdef VERBOSE
  895.     LONG windowHeight = TkOS2HwndHeight(WinQueryWindow(hwnd, QW_PARENT));
  896.     printf("GenerateXEvent hwnd %x (winPtr %x) msg %x p1 %x p2 %x, height %d\n",
  897.            hwnd, winPtr, message, param1, param2, windowHeight);
  898. #endif
  899.  
  900.     if (!winPtr || winPtr->window == None) {
  901. #ifdef VERBOSE
  902.         printf("null winPtr or no winPtr->window, returning\n");
  903. #endif
  904.         return;
  905.     }
  906.  
  907.     event.xany.serial = winPtr->display->request++;
  908.     event.xany.send_event = False;
  909.     event.xany.display = winPtr->display;
  910.     event.xany.window = winPtr->window;
  911.  
  912.     switch (message) {
  913.         case WM_PAINT: {
  914.             HPS hps;
  915.             RECTL rectl;
  916.  
  917.             event.type = Expose;
  918.             hps= WinBeginPaint(hwnd, NULLHANDLE, &rectl);
  919. #ifdef VERBOSE
  920.             WinFillRect(hps, &rectl, CLR_RED);
  921.             if (hps==NULLHANDLE) {
  922.                 printf("WinBeginPaint hwnd %x ERROR %x\n", hwnd,
  923.                        WinGetLastError(TclOS2GetHAB()));
  924.             } else {
  925.                 printf("WinBeginPaint hwnd %x is %x\n", hwnd, hps);
  926.             }
  927. #endif
  928.             event.xexpose.x = rectl.xLeft;
  929.             /* PM coordinates reversed */
  930.             event.xexpose.y = TkOS2TranslateY(hwnd, rectl.yTop, 0);
  931.             event.xexpose.width = rectl.xRight - rectl.xLeft;
  932.             event.xexpose.height = rectl.yTop - rectl.yBottom;
  933.             WinEndPaint(hps);
  934. #ifdef VERBOSE
  935.             printf("EVENT hwnd %x Expose (%d,%d) %dx%d WM_PAINT %d,%d->%d,%d\n",
  936.                hwnd, event.xexpose.x, event.xexpose.y, event.xexpose.width,
  937.            event.xexpose.height, rectl.xLeft, rectl.yBottom,
  938.            rectl.xRight, rectl.yTop);
  939. #endif
  940.             event.xexpose.count = 0;
  941.             break;
  942.         }
  943.  
  944.         case WM_CLOSE:
  945.             event.type = ClientMessage;
  946.             event.xclient.message_type =
  947.                 Tk_InternAtom((Tk_Window) winPtr, "WM_PROTOCOLS");
  948.             event.xclient.format = 32;
  949.             event.xclient.data.l[0] =
  950.                 Tk_InternAtom((Tk_Window) winPtr, "WM_DELETE_WINDOW");
  951.             break;
  952.  
  953.         case WM_SETFOCUS: {
  954.             TkWindow *otherWinPtr = (TkWindow *)Tk_HWNDToWindow((HWND) param1);
  955. #ifdef VERBOSE
  956.             printf("Tk_HWNDToWindow(%x) otherWinPtr %x\n", param1, otherWinPtr);
  957. #endif
  958.  
  959.             /*
  960.              * Compare toplevel windows to avoid reporting focus
  961.              * changes within the same toplevel.
  962.              */
  963.  
  964.             while (!(winPtr->flags & TK_TOP_LEVEL)) {
  965.                 winPtr = winPtr->parentPtr;
  966.                 if (winPtr == NULL) {
  967. #ifdef VERBOSE
  968.                     printf("WM_SETFOCUS, NULL winPtr\n");
  969. #endif
  970.                     return;
  971.                 }
  972.             }
  973.             while (otherWinPtr && !(otherWinPtr->flags & TK_TOP_LEVEL)) {
  974.                 otherWinPtr = otherWinPtr->parentPtr;
  975.             }
  976.             if (otherWinPtr == winPtr) {
  977. #ifdef VERBOSE
  978.                 printf("WM_SETFOCUS, otherWinptr == winPtr (%x)\n", winPtr);
  979. #endif
  980.                 return;
  981.             }
  982.  
  983.             event.xany.window = winPtr->window;
  984.             event.type = SHORT1FROMMP(param2) == TRUE ? FocusIn : FocusOut;
  985.             event.xfocus.mode = NotifyNormal;
  986.             event.xfocus.detail = NotifyNonlinear;
  987. #ifdef VERBOSE
  988.             printf("EVENT hwnd %x %s\n", hwnd,
  989.                SHORT1FROMMP(param2) == TRUE ? "FocusIn" : "FocusOut");
  990. #endif
  991.             break;
  992.         }
  993.  
  994.         case WM_DESTROYCLIPBOARD:
  995.             event.type = SelectionClear;
  996.             event.xselectionclear.selection =
  997.                 Tk_InternAtom((Tk_Window)winPtr, "CLIPBOARD");
  998.             event.xselectionclear.time = TkpGetMS();
  999.             break;
  1000.  
  1001.         case WM_CHAR: {
  1002.             /*
  1003.              * Careful: for each keypress, two of these messages are
  1004.              * generated, one when pressed and one when released.
  1005.              * When the keyboard-repeat is triggered, multiple key-
  1006.              * down messages can be generated. If this goes faster
  1007.              * than they are retrieved from the queue, they can be
  1008.              * combined in one message.
  1009.              */
  1010.             USHORT flags= CHARMSG(&message)->fs;
  1011.             UCHAR krepeat= CHARMSG(&message)->cRepeat;
  1012.             USHORT charcode= CHARMSG(&message)->chr;
  1013.             USHORT vkeycode= CHARMSG(&message)->vkey;
  1014.             unsigned int state = GetState(message, param1, param2);
  1015.             Time time = TkpGetMS();
  1016.             POINTL point;
  1017. #ifdef VERBOSE
  1018.             printf("WM_CHAR flags %x krepeat %d charcode %d vkeycode %x\n",
  1019.                    flags, krepeat, charcode, vkeycode);
  1020. #endif
  1021.  
  1022.             /*
  1023.              * Compute the screen and window coordinates of the event.
  1024.              * Set up the common event fields.
  1025.              */
  1026.  
  1027.             WinQueryMsgPos(TclOS2GetHAB(), &point);
  1028.             /* point now in screen coordinates */
  1029.             event.xbutton.x_root = point.x;
  1030.             event.xbutton.y_root = yScreen - point.y;    /* PM y reversed */
  1031.             event.xbutton.root = RootWindow(winPtr->display,
  1032.                     winPtr->screenNum);
  1033.  
  1034.             WinMapWindowPoints(HWND_DESKTOP, hwnd, &point, 1);
  1035.             /* point now in window coordinates */
  1036.             event.xbutton.subwindow = None;
  1037.             event.xbutton.x = point.x;
  1038.             event.xbutton.y = TkOS2TranslateY(hwnd, point.y, 0);
  1039. #ifdef VERBOSE
  1040.             printf("EVENT hwnd %x Key: (%d,%d) PM: (%d,%d) state %x flags %x\n",
  1041.                    hwnd, event.xbutton.x, event.xbutton.y, point.x, point.y,
  1042.                    state, flags);
  1043. #endif
  1044.             event.xbutton.state = state;
  1045.             event.xbutton.time = time;
  1046.             event.xbutton.same_screen = True;
  1047.  
  1048.             /*
  1049.              * Now set up event specific fields.
  1050.              */
  1051.  
  1052. #ifdef VERBOSE
  1053.             if ( (flags & KC_ALT) && !(flags & KC_KEYUP) && !(flags & KC_CTRL)
  1054.                  && (vkeycode != VK_CTRL) && (vkeycode != VK_F10) ) {
  1055.                 /* Equivalent to Windows' WM_SYSKEYDOWN */
  1056.                 printf("Equivalent of WM_SYSKEYDOWN...\n");
  1057.         }
  1058.             if ( (flags & KC_ALT) && (flags & KC_KEYUP) && !(flags & KC_CTRL)
  1059.                  && (vkeycode != VK_CTRL) && (vkeycode != VK_F10) ) {
  1060.                 /* Equivalent to Windows' WM_SYSKEYUP */
  1061.                 printf("Equivalent of WM_SYSKEYUP...\n");
  1062.             }
  1063. #endif
  1064.             if ( flags & KC_KEYUP ) {
  1065.                 /* Key Up */
  1066. #ifdef VERBOSE
  1067.                 printf("KeyUp\n");
  1068. #endif
  1069.                 event.type = KeyRelease;
  1070.                 /* Added by/for Ilya Zakharevich */
  1071.                 /* KeyRelease for alphanums gets ORed with 0x*00 */
  1072.                 if ( !(flags & KC_VIRTUALKEY) ) {
  1073.                     charcode = charcode & 0xFF;
  1074.                     if (charcode && charcode <= 0x1F &&
  1075.                         (flags & KC_CTRL)) {
  1076. #ifdef VERBOSE
  1077.                         printf("KeyUp ADDING\n");
  1078. #endif
  1079.                         charcode += ((flags & KC_SHIFT) ? 'A'-1
  1080.                                                         : 'a'-1);
  1081.                     }
  1082.                 }
  1083.             } else {
  1084.                 /* Key Down */
  1085. #ifdef VERBOSE
  1086.                 printf("KeyDown\n");
  1087. #endif
  1088.                 event.type = KeyPress;
  1089.             }
  1090.             if ( flags & KC_VIRTUALKEY ) {
  1091.                /* Next if() added by/for Ilya Zakharevich */
  1092.                 if ( (flags & KC_SHIFT) && vkeycode == VK_BACKTAB ) {
  1093.                     vkeycode = VK_TAB;
  1094.                 }
  1095.                 /* vkeycode is valid, should be given precedence */
  1096.                 event.xkey.keycode = vkeycode;
  1097. #ifdef VERBOSE
  1098.                 printf("virtual keycode %x (%s)\n", vkeycode,
  1099.                        vkeycode == VK_ENTER ? "VK_ENTER" :
  1100.                        (vkeycode == VK_NEWLINE ? "VK_NEWLINE" :
  1101.                        (vkeycode == VK_ESC ? "VK_ESC" :
  1102.                        (vkeycode == VK_UP ? "VK_UP" :
  1103.                        (vkeycode == VK_DOWN ? "VK_DOWN" :
  1104.                        (vkeycode == VK_LEFT ? "VK_LEFT" :
  1105.                        (vkeycode == VK_RIGHT ? "VK_RIGHT" :
  1106.                        (vkeycode == VK_ALT ? "VK_ALT" :
  1107.                        (vkeycode == VK_TAB ? "VK_TAB" :
  1108.                        (vkeycode == VK_F1 ? "VK_F1" :
  1109.                        (vkeycode == VK_F10 ? "VK_F10" : "OTHER"
  1110.                        )))))))))));
  1111. #endif
  1112.             } else {
  1113.                 /* Move to VK_USER range */
  1114.                 event.xkey.keycode = (charcode & 0xFF) + 0x100;
  1115.             }
  1116.             if ( flags & KC_CHAR ) {
  1117.                 int loop;
  1118.                 /* charcode is valid */
  1119.                 event.xkey.nchars = krepeat;
  1120.                 for ( loop=0; loop < krepeat; loop++ ) {
  1121.                         event.xkey.trans_chars[loop] = charcode;
  1122. #ifdef VERBOSE
  1123.                 printf("charcode 0x%x=%d (%c)\n", charcode, charcode, charcode);
  1124. #endif
  1125.                 }
  1126.             } else {
  1127.                 /*
  1128.                  * No KC_CHAR, but char can be valid with KC_ALT,
  1129.                  * KC_CTRL when it is not 0.
  1130.                  */
  1131. #ifdef VERBOSE
  1132.                 printf("no KC_CHAR, charcode %d (0x%x)\n", charcode, charcode);
  1133.                 fflush(stdout);
  1134. #endif
  1135.                 /* KC_VIRTUALKEY criterion added by Ilya Zakharevich */
  1136.                 if ( (flags & KC_ALT || flags & KC_CTRL)
  1137.                      && charcode != 0 && !(flags & KC_VIRTUALKEY)) {
  1138.                     int loop;
  1139. #ifdef VERBOSE
  1140.                     printf("KC_ALT/KC_CTRL and non-0 char %c (%x)\n",
  1141.                            charcode, charcode);
  1142.                     fflush(stdout);
  1143. #endif
  1144.                     event.xkey.keycode = charcode;
  1145.                     event.xkey.nchars = krepeat;
  1146.                     for ( loop=0; loop < krepeat; loop++ ) {
  1147.                         event.xkey.trans_chars[loop] = charcode;
  1148. #ifdef VERBOSE
  1149.                         printf("charcode 0x%x=%d (%c)\n", charcode, charcode, charcode);
  1150. #endif
  1151.                     }
  1152.                 } else {
  1153. #ifdef VERBOSE
  1154.                     printf("KC_ALT %x KC_CTRL %x charc. %x KC_VIRTUALKEY %x\n",
  1155.                            flags & KC_ALT, flags & KC_CTRL, charcode,
  1156.                            flags & KC_VIRTUALKEY);
  1157.                     fflush(stdout);
  1158. #endif
  1159.                     event.xkey.nchars = 0;
  1160.                 }
  1161.                 event.xkey.trans_chars[0] = 0;
  1162.             }
  1163.  
  1164.             /*
  1165.              * Setting xany.send_event to -1 indicates to the
  1166.              * OS/2 implementation of XLookupString that this
  1167.              * event was generated by OS/2 and that the OS/2
  1168.              * extension xkey.trans_chars is filled.
  1169.              * If it is not -1, xkey.keycode is the virtual
  1170.              * key being sent programmatically by generic code.
  1171.              */
  1172.  
  1173.             event.xany.send_event = -1;
  1174.             break;
  1175.         }
  1176.  
  1177.         default:
  1178.             return;
  1179.     }
  1180.     Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
  1181. }
  1182.  
  1183. /*
  1184.  *----------------------------------------------------------------------
  1185.  *
  1186.  * GetState --
  1187.  *
  1188.  *    This function constructs a state mask for the mouse buttons 
  1189.  *    and modifier keys as they were before the event occured.
  1190.  *
  1191.  * Results:
  1192.  *    Returns a composite value of all the modifier and button state
  1193.  *    flags that were set at the time the event occurred.
  1194.  *
  1195.  * Side effects:
  1196.  *    None.
  1197.  *
  1198.  *----------------------------------------------------------------------
  1199.  */
  1200.  
  1201. unsigned int
  1202. GetState(message, param1, param2)
  1203.     ULONG message;        /* OS/2 PM message type */
  1204.     MPARAM param1;        /* param1 of message, used if key message */
  1205.     MPARAM param2;        /* param2 of message, used if key message */
  1206. {
  1207.     int mask;
  1208.     int prevState = 0;        /* 1 if key was previously down */
  1209.     unsigned int state = TkOS2GetModifierState();
  1210. #ifdef VERBOSE
  1211.     printf("GetState mp1 %x mp2 %x\n", param1, param2);
  1212. #endif
  1213.  
  1214.     /*
  1215.      * If the event is a key press or release, we check for modifier
  1216.      * keys so we can report the state of the world before the event.
  1217.      */
  1218.  
  1219.     if (message == WM_CHAR) {
  1220.         USHORT flags = SHORT1FROMMP(param1);
  1221.         USHORT vkeycode = SHORT2FROMMP(param2); /* function key */
  1222.         mask = 0;
  1223.         prevState = flags & KC_PREVDOWN;
  1224.         switch (vkeycode) {
  1225.             case VK_SHIFT:
  1226.                 mask = ShiftMask;
  1227.                 break;
  1228.             case VK_CTRL:
  1229.                 mask = ControlMask;
  1230.                 break;
  1231.             case VK_MENU:
  1232.                 mask = Mod2Mask;
  1233.                 break;
  1234.             case VK_CAPSLOCK:
  1235.                 if (!(flags & KC_KEYUP)) {
  1236.                     mask = LockMask;
  1237.                     prevState = ((state & mask) ^ prevState) ? 0 : 1;
  1238.                 }
  1239.             case VK_NUMLOCK:
  1240.                 if (!(flags & KC_KEYUP)) {
  1241.                     mask = Mod1Mask;
  1242.                     prevState = ((state & mask) ^ prevState) ? 0 : 1;
  1243.                 }
  1244.                 break;
  1245.             case VK_SCRLLOCK:
  1246.                 if (!(flags & KC_KEYUP)) {
  1247.                     mask = Mod3Mask;
  1248.                     prevState = ((state & mask) ^ prevState) ? 0 : 1;
  1249.                 }
  1250.                 break;
  1251.         }
  1252.         if (prevState) {
  1253.             state |= mask;
  1254.         } else {
  1255.             state &= ~mask;
  1256.         }
  1257.     }
  1258.     return state;
  1259. }
  1260.  
  1261. /*
  1262.  *----------------------------------------------------------------------
  1263.  *
  1264.  * Tk_FreeXId --
  1265.  *
  1266.  *      This inteface is not needed under OS/2.
  1267.  *
  1268.  * Results:
  1269.  *      None.
  1270.  *
  1271.  * Side effects:
  1272.  *      None.
  1273.  *
  1274.  *----------------------------------------------------------------------
  1275.  */
  1276.  
  1277. void
  1278. Tk_FreeXId(display, xid)
  1279.     Display *display;
  1280.     XID xid;
  1281. {
  1282. }
  1283.  
  1284. /*
  1285.  *----------------------------------------------------------------------
  1286.  *
  1287.  * TkOS2ResendEvent --
  1288.  *
  1289.  *      This function converts an X event into a PM event and
  1290.  *      invokes the specified window procedure.
  1291.  *
  1292.  * Results:
  1293.  *      A standard OS/2 PM result.
  1294.  *
  1295.  * Side effects:
  1296.  *      Invokes the window procedure
  1297.  *
  1298.  *----------------------------------------------------------------------
  1299.  */
  1300.  
  1301. MRESULT
  1302. TkOS2ResendEvent(wndproc, hwnd, eventPtr)
  1303.     PFNWP wndproc;
  1304.     HWND hwnd;
  1305.     XEvent *eventPtr;
  1306. {
  1307.     ULONG msg;
  1308.     MPARAM param1;
  1309.     MPARAM param2;
  1310. #ifdef VERBOSE
  1311.     printf("TkOS2ResendEvent (%d,%d)\n", eventPtr->xbutton.x,
  1312.            eventPtr->xbutton.y);
  1313. #endif
  1314.  
  1315.     if (eventPtr->type == ButtonPress) {
  1316.         switch (eventPtr->xbutton.button) {
  1317.             case Button1:
  1318.                 msg = WM_BUTTON1DOWN;
  1319.                 param2 = (MPARAM) VK_BUTTON1;
  1320.                 break;
  1321.             case Button2:
  1322.                 msg = WM_BUTTON3DOWN;
  1323.                 param2 = (MPARAM) VK_BUTTON3;
  1324.                 break;
  1325.             case Button3:
  1326.                 msg = WM_BUTTON2DOWN;
  1327.                 param2 = (MPARAM) VK_BUTTON2;
  1328.                 break;
  1329.             default:
  1330.                 return 0;
  1331.         }
  1332.         if (eventPtr->xbutton.state & Button1Mask) {
  1333.             param2 = (MPARAM) (((LONG) param2) | VK_BUTTON1);
  1334.         }
  1335.         if (eventPtr->xbutton.state & Button2Mask) {
  1336.             param2 = (MPARAM) (((LONG) param2) | VK_BUTTON3);
  1337.         }
  1338.         if (eventPtr->xbutton.state & Button3Mask) {
  1339.             param2 = (MPARAM) (((LONG) param2) | VK_BUTTON2);
  1340.         }
  1341.         if (eventPtr->xbutton.state & ShiftMask) {
  1342.             param2 = (MPARAM) (((LONG) param2) | VK_SHIFT);
  1343.         }
  1344.         if (eventPtr->xbutton.state & ControlMask) {
  1345.             param2 = (MPARAM) (((LONG) param2) | VK_CTRL);
  1346.         }
  1347.         param1 = MPFROM2SHORT((SHORT) eventPtr->xbutton.x,
  1348.                               (SHORT) TkOS2TranslateY(hwnd,
  1349.                                                       eventPtr->xbutton.y, 0));
  1350.     } else {
  1351.         return 0;
  1352.     }
  1353.     return (*wndproc)(hwnd, msg, param1, param2);
  1354. }
  1355.  
  1356. /*
  1357.  *----------------------------------------------------------------------
  1358.  *
  1359.  * TkpGetMS --
  1360.  *
  1361.  *      Return a relative time in milliseconds.  It doesn't matter
  1362.  *      when the epoch was.
  1363.  *
  1364.  * Results:
  1365.  *      Number of milliseconds.
  1366.  *
  1367.  * Side effects:
  1368.  *      None.
  1369.  *
  1370.  *----------------------------------------------------------------------
  1371.  */
  1372.  
  1373. unsigned long
  1374. TkpGetMS()
  1375. {
  1376. #ifdef VERBOSE
  1377.     printf("TkpGetMS\n");
  1378. #endif
  1379.     return WinGetCurrentTime(TclOS2GetHAB());
  1380. }
  1381.