home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1995 November / PCWK1195.iso / inne / podstawy / os2 / nakladki / pc2v190.exe / SOURCE.ZIP / Source / Thread.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-01  |  66.1 KB  |  1,095 lines

  1. /***********************************************************************\
  2.  *                              Thread.c                               *
  3.  *              Copyright (C) by Stangl Roman, 1994, 1995              *
  4.  * This Code may be freely distributed, provided the Copyright isn't   *
  5.  * removed, under the conditions indicated in the documentation.       *
  6.  *                                                                     *
  7.  * Thread.c     PC/2's object window working thread.                   *
  8.  *                                                                     *
  9. \***********************************************************************/
  10.  
  11. static char RCSID[]="@(#) $Header: Thread.c Version 1.90 05,1995 $ (LBL)";
  12.  
  13. #define         _FILE_  "PC/2 - Thread.c V1.90"
  14.  
  15. #include        "PC2.h"                 /* User include files */
  16. #include        "Error.h"
  17.  
  18. typedef struct  _ColorWindow    COLORWINDOW;
  19.  
  20. struct  _ColorWindow
  21. {
  22. ULONG   ulBackgroundRGB;                /* RGB background color of window drawn on overview window */
  23. ULONG   ulForegroundRGB;                /* RGB foreground color of window text */
  24. };
  25.  
  26. HPS     hpsClient;                      /* PC/2's client area presentation space */
  27. SWP     swpApplications[128];           /* Window position of all enumerated applications
  28.                                            except Window List, PC/2 and optionally Desktop */
  29. ULONG   ulApplicationsCount;            /* Counter of last filled entry within array
  30.                                            swpApplications */
  31.  
  32.                                         /* PC/2's working thread */
  33. void _Optlink   PC2_Thread(void *ThreadArg)
  34. {
  35. HAB     habThread;
  36. HMQ     hmqThread;
  37. QMSG    qmsgThread;
  38. HDC     hdcClient;                      /* Client area DC */
  39. SIZEL   sizelClient;
  40.  
  41. while(TRUE)
  42. {
  43.                                         /* Initialize anchor block and message queue */
  44.     if(WinStartUp(&habThread, &hmqThread)==FALSE)
  45.         {
  46.         USR_ERR(pHP->hwndFrame, HELP_CREATEWINDOW, MB_ERROR|MB_OK|MB_MOVEABLE|MB_DEFBUTTON1,
  47.             "Initializing thread's PM environment failed, PC/2 can't continue. You may have run out "\
  48.             "of resources, close some windows or applications and retry. Exiting...");
  49.                                         /* On error shut down PC/2 */
  50.         pHP->ulStatusFlag|=PC2EMERGENCYEXIT;
  51.         WinPostMsg(pHP->hwndClient, WM_QUIT, NULL, NULL);
  52.         break;
  53.         }
  54.     if(!WinRegisterClass(               /* Register window class */
  55.         habThread,                      /* Handle of anchor block */
  56.         (PSZ)PC2_CLASSNAME_THREAD,      /* Window class name */
  57.         (PFNWP)PC2_ThreadWindowProc,    /* Address of window procedure */
  58.         CS_SIZEREDRAW | CS_SAVEBITS,
  59.         0))                             /* Extra window words */
  60.         {
  61.         PM_ERR(habThread, pHP->hwndFrame, HELP_CREATEWINDOW, MB_ERROR|MB_OK|MB_MOVEABLE|MB_DEFBUTTON1,
  62.             "Initializing thread's PM environment failed, PC/2 can't continue. You may have run out "\
  63.             "of resources, close some windows or applications and retry. Exiting...");
  64.                                         /* On error shut down PC/2 */
  65.         pHP->ulStatusFlag|=PC2EMERGENCYEXIT;
  66.         WinPostMsg(pHP->hwndClient, WM_QUIT, NULL, NULL);
  67.         break;
  68.         }
  69.     pHP->hwndThread=WinCreateWindow(
  70.         HWND_OBJECT,                    /* Parent window */
  71.         PC2_CLASSNAME_THREAD,           /* Window class */
  72.         NULL,                           /* Window text */
  73.         0,                              /* Window style */
  74.                                         /* Windos position & size */
  75.         0, 0, 0, 0,
  76.         HWND_OBJECT,                    /* Owner window */
  77.         HWND_BOTTOM,                    /* Sibling window */
  78.         ID_PC2MAINWINDOW,               /* Window ID */
  79.         NULL,                           /* Control data */
  80.         NULL);                          /* Presentation parameters */
  81.                                         /* Create a standard window */
  82. /*                                                                                      *\
  83.  * Now setup working thread's required data.                                            *
  84. \*                                                                                      */
  85.                                         /* Get presentation space for PC/2's client window */
  86.     sizelClient.cx=pHP->DesktopSize.x;
  87.     sizelClient.cy=pHP->DesktopSize.y;
  88.                                         /* Get device context and a presentation space associated
  89.                                            for client window */
  90.     hdcClient=WinOpenWindowDC(pHP->hwndClient);
  91.     hpsClient=GpiCreatePS(pHP->habPc2, hdcClient, &sizelClient, PU_PELS|GPIA_ASSOC);
  92.     GpiCreateLogColorTable(hpsClient,   /* Change color table into RGB mode */
  93.         0L,                             /* Options */
  94.         LCOLF_RGB,                      /* Set color table into RGB mode */
  95.         0L, 0L, NULL);                  /* Starting, ending item, table */
  96.                                         /* Post message to query Desktop's/PM window handle */
  97.     WinPostMsg(pHP->hwndThread, WM_SETDESKTOPHANDLE, NULL, NULL);
  98.                                         /* If required expand WPS */
  99.     if(pHP->ulStatusFlag & EXPANDWPS)
  100.         WinPostMsg(pHP->hwndThread, WM_EXPANDWPS, (MPARAM)TRUE, NULL);
  101.                                         /* Load PM background bitmap */
  102.     WinPostMsg(pHP->hwndThread, WM_BACKGROUNDBITMAP, NULL, NULL);
  103.                                         /* Enumerate all windows */
  104.     WinPostMsg(pHP->hwndThread, WM_SETUPSIZEPOSITION, NULL, NULL);
  105.                                         /* Change to all local drives root directory */
  106.     WinPostMsg(pHP->hwndThread, WM_SETDRIVEROOT, NULL, NULL);
  107.                                         /* Post this message as the last one into the message queue,
  108.                                            to inform client window that working thread is ready then */
  109.     WinPostMsg(pHP->hwndThread, WM_THREADSTARTUPREADY, NULL, NULL);
  110. /*                                                                                      *\
  111.  * Here we loop dispatching the messages...                                             *
  112. \*                                                                                      */
  113.     while(WinGetMsg(habThread, &qmsgThread, 0, 0, 0))
  114.                                             /* Dispatch messages to window procedure */
  115.         WinDispatchMsg(habThread, &qmsgThread);
  116.     break;
  117. }
  118.                                         /* Release presentation space */
  119. GpiDestroyPS(hpsClient);
  120.                                         /* Release device context */
  121. DevCloseDC(hdcClient);
  122.                                         /* Close window */
  123. WinDestroyWindow(pHP->hwndThread);
  124. WinDestroyMsgQueue(hmqThread);
  125. WinTerminate(habThread);
  126. _endthread();                           /* Terminate C thread code */
  127. DosExit(EXIT_THREAD, 0UL);              /* Terminate thread */
  128. }
  129.  
  130. /*--------------------------------------------------------------------------------------*\
  131.  * This procedure is the PC/2 working thread window procedure (is an object window).    *
  132. \*--------------------------------------------------------------------------------------*/
  133. MRESULT EXPENTRY PC2_ThreadWindowProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
  134. {
  135. switch(msg)
  136. {
  137. case WM_PRESPARAMCHANGED:
  138.     if((ULONG)mp1==PP_FONTNAMESIZE)
  139.         {
  140.         FATTRS  *pfatPC2Font;
  141.         USHORT  usMaxBaselineExt;
  142.         SIZEF   sizefFont;
  143.  
  144.         if(pHP->ulDebug>=DEBUG_FULL)
  145.             printf("Thread: WM_PRESPARAMCHANGEDTHREADSTARTUPREADY\n");
  146.                                         /* Get overview window font */
  147.         pfatPC2Font=(FATTRS *)PVOIDFROMMP(mp2);
  148.                                         /* For outline fonts the baseline is expected 0 */
  149.         usMaxBaselineExt=(USHORT)pfatPC2Font->lMaxBaselineExt;
  150.         if(pfatPC2Font->fsFontUse&FATTR_FONTUSE_OUTLINE)
  151.             pfatPC2Font->lMaxBaselineExt=0;
  152.                                         /* Delete previous logical font */
  153.         GpiDeleteSetId(HPSDRAW, LCID_FONT);
  154.                                         /* Create the logical font and select it */
  155.         GpiCreateLogFont(HPSDRAW, NULL, LCID_FONT, pfatPC2Font);
  156.         GpiSetCharSet(HPSDRAW, LCID_FONT);
  157.         sizefFont.cx=MAKEFIXED(usMaxBaselineExt, 0);
  158.         sizefFont.cy=MAKEFIXED(usMaxBaselineExt, 0);
  159.         GpiSetCharBox(HPSDRAW, &sizefFont);
  160.         free(pfatPC2Font);              /* Free structure allocated by main thread */
  161.                                         /* Repaint overview window */
  162.         WinPostMsg(hwnd, WM_PAINT, NULL, NULL);
  163.         }
  164.     break;
  165.  
  166. /*                                                                                      *\
  167.  * Syntax: WM_AUTOSTART, NULL, NULL                                                     *
  168. \*                                                                                      */
  169. case WM_AUTOSTART:
  170. /*                                                                                      *\
  171.  * This message is posted during initialization of the working thread to autostart all  *
  172.  * menu items that have the autostart flag.                                             *
  173.  * Ref.:                                                                                *
  174.  *      pPopupMenu                                                                      *
  175. \*                                                                                      */
  176.                                         /* Scan recursively through Popup-Menu and start
  177.                                            all applications that have the autostart flag
  178.                                            by simulating a selection of the application from
  179.                                            the Popup-Menu. */
  180.     if(pHP->ulDebug>=DEBUG_FULL)
  181.         printf("Thread: Received WM_AUTOSTART\n");
  182.     SearchAutoStartItem(pHP->pPopupMenu);
  183.     break;
  184.  
  185. /*                                                                                      *\
  186.  * Syntax: WM_THREADSTARTUPREADY, NULL, NULL                                            *
  187. \*                                                                                      */
  188. case WM_THREADSTARTUPREADY:
  189. /*                                                                                      *\
  190.  * Working thread is now ready, make overview window visible when requested.            *
  191. \*                                                                                      */
  192.                                         /* Inform client window that working thread is now ready */
  193.     WinPostMsg(pHP->hwndClient, WM_THREADSTARTUPREADY, NULL, NULL);
  194.     break;
  195. /*                                                                                      *\
  196.  * Syntax: WM_PAINT, NULL, NULL                                                         *
  197. \*                                                                                      */
  198. case WM_PAINT:
  199. /*                                                                                      *\
  200.  * This message is send by PC/2's client window when a repaint is needed.               *
  201.  * Ref.:                                                                                *
  202.  *          none                                                                        *
  203. \*                                                                                      */
  204.     {
  205.     RECTL       rcClient;               /* Rectangle to redraw */
  206.     LONG        lX, lY;                 /* Position (x|y) on client area */
  207.     LONG        lXSize, lYSize;         /* Length on client area */
  208.     SWP         swpWindow;              /* Any window to be drawn on overview window */
  209.     ULONG       ulWindowIndex;          /* Index in Windows.wdWindow[] */
  210.                                         /* RGB colors available to draw winwdows */
  211.     COLORWINDOW ColorWindow[]={ {RGB_BLACK,  RGB_WHITE}, {RGB_BLUE,  RGB_WHITE}, {RGB_GREEN, RGB_BLACK},
  212.                                 {RGB_CYAN,   RGB_BLACK}, {RGB_RED,   RGB_WHITE}, {RGB_PINK,  RGB_WHITE},
  213.                                 {RGB_YELLOW, RGB_BLACK} };
  214. #ifndef SLOWVIDEO
  215.     POINTL      ptl;
  216. #endif /* SLOWVIDEO */
  217.  
  218.                                         /* Set background to dialog background */
  219.     WinQueryWindowRect(pHP->hwndClient, &rcClient);
  220.     WinFillRect(HPSDRAW, &rcClient, WinQuerySysColor(HWND_DESKTOP, SYSCLR_DIALOGBACKGROUND, 0L));
  221.                                         /* Now get scale factor to scale virtual Desktop
  222.                                            to client area */
  223.     pHP->fScaleX=(float)(pHP->swpPC2Client.cx-1)/
  224.         (pHP->ulHorizontalDesktops*pHP->DesktopSize.x);
  225.     pHP->fScaleY=(float)(pHP->swpPC2Client.cy)/
  226.         (pHP->ulVerticalDesktops*pHP->DesktopSize.y);
  227.                                         /* Get coordinates (0|0) origin, relativ to (0|0) of
  228.                                            the Virtual Desktop */
  229.     pHP->ptlOrigin.x=(pHP->VirtualDesktopPos.x-pHP->VirtualDesktopMin.x)*
  230.         pHP->fScaleX;
  231.     pHP->ptlOrigin.y=(pHP->VirtualDesktopPos.y-pHP->VirtualDesktopMin.y)*
  232.         pHP->fScaleY;
  233.                                         /* Get size of one of the number of Desktops that must fit into
  234.                                            the client area */
  235.     lXSize=pHP->swpPC2Client.cx/pHP->ulHorizontalDesktops;
  236.     lYSize=pHP->swpPC2Client.cy/pHP->ulVerticalDesktops;
  237.                                         /* If WPS is expanded to whole Virtual Desktop draw Desktop
  238.                                            first before drawing the borders of the Virtual Desktop */
  239.     if(pHP->ulStatusFlag & EXPANDWPS)
  240.         {
  241.                                         /* Calculate and draw window */
  242.         swpWindow.x=pHP->ptlOrigin.x+
  243.             (float)pHP->Windows.wdWindow[pHP->Windows.ulDesktop].swpWindow.x*pHP->fScaleX;
  244.         swpWindow.y=pHP->ptlOrigin.y+
  245.             (float)pHP->Windows.wdWindow[pHP->Windows.ulDesktop].swpWindow.y*pHP->fScaleY;
  246.         swpWindow.cx=(float)pHP->Windows.wdWindow[pHP->Windows.ulDesktop].swpWindow.cx*pHP->fScaleX;
  247.         swpWindow.cy=(float)pHP->Windows.wdWindow[pHP->Windows.ulDesktop].swpWindow.cy*pHP->fScaleY;
  248.                                         /* Display Window List title or titlebar */
  249.         if(strlen(pHP->Windows.wdWindow[pHP->Windows.ulDesktop].ucWindowTitle))
  250.             DrawWindow(HPSDRAW, &swpWindow,
  251.                 ColorWindow[pHP->Windows.ulDesktop % (sizeof(ColorWindow)/sizeof(COLORWINDOW))].ulBackgroundRGB,
  252.                 ColorWindow[pHP->Windows.ulDesktop % (sizeof(ColorWindow)/sizeof(COLORWINDOW))].ulForegroundRGB,
  253.                 FOREGROUND_WND, pHP->Windows.wdWindow[pHP->Windows.ulDesktop].ucWindowTitle);
  254.         else
  255.             DrawWindow(HPSDRAW, &swpWindow,
  256.                 ColorWindow[pHP->Windows.ulDesktop % (sizeof(ColorWindow)/sizeof(COLORWINDOW))].ulBackgroundRGB,
  257.                 ColorWindow[pHP->Windows.ulDesktop % (sizeof(ColorWindow)/sizeof(COLORWINDOW))].ulForegroundRGB,
  258.                 FOREGROUND_WND, pHP->Windows.wdWindow[pHP->Windows.ulDesktop].ucPgmTitle);
  259.         }
  260.     swpWindow.cx=lXSize-1;
  261.     swpWindow.cy=lYSize-1;
  262.                                         /* Draw all Virtual Desktops */
  263.     for(lX=0; lX<pHP->ulHorizontalDesktops; lX++)
  264.         for(lY=0; lY<pHP->ulVerticalDesktops; lY++)
  265.             {
  266.             swpWindow.x=lX*lXSize;
  267.             swpWindow.y=lY*lYSize;
  268.             DrawWindow(HPSDRAW, &swpWindow,
  269.                 WinQuerySysColor(HWND_DESKTOP, SYSCLR_DIALOGBACKGROUND, 0L), 0L,
  270.                 (pHP->ulStatusFlag & EXPANDWPS) ? BACKGROUND_WND | BORDERONLY_WND : BACKGROUND_WND,
  271.                 NULL);
  272.             }
  273.                                         /* Draw physical Desktop window */
  274.     swpWindow.x=pHP->ptlOrigin.x;
  275.     swpWindow.y=pHP->ptlOrigin.y;
  276.     DrawWindow(HPSDRAW, &swpWindow, RGB_WHITE, RGB_BLACK, FOREGROUND_WND, "Display");
  277.                                         /* Now display the windows from topmost to bottommost */
  278.     for(ulWindowIndex=pHP->Windows.ulWindowLast;
  279.         ulWindowIndex!=(ULONG)-1 && pHP->Windows.ulWindowLast!=(ULONG)-1;
  280.         ulWindowIndex--)
  281.         {
  282.                                         /* Ignore invisible windows or when WPS is expanded to
  283.                                            Virtual Desktop */
  284.         if((!(pHP->Windows.wdWindow[ulWindowIndex].ulStatus & VISIBLE)) ||
  285.             ((pHP->ulStatusFlag & EXPANDWPS) && (ulWindowIndex==pHP->Windows.ulDesktop)))
  286.             continue;
  287.  
  288.                                         /* Calculate and draw window */
  289.         swpWindow.x=pHP->ptlOrigin.x+
  290.             (float)pHP->Windows.wdWindow[ulWindowIndex].swpWindow.x*pHP->fScaleX;
  291.         swpWindow.y=pHP->ptlOrigin.y+
  292.             (float)pHP->Windows.wdWindow[ulWindowIndex].swpWindow.y*pHP->fScaleY;
  293.         swpWindow.cx=(float)pHP->Windows.wdWindow[ulWindowIndex].swpWindow.cx*pHP->fScaleX;
  294.         swpWindow.cy=(float)pHP->Windows.wdWindow[ulWindowIndex].swpWindow.cy*pHP->fScaleY;
  295.                                         /* Display Window List title or titlebar */
  296.         if(strlen(pHP->Windows.wdWindow[ulWindowIndex].ucWindowTitle))
  297.             DrawWindow(HPSDRAW, &swpWindow,
  298.                 ColorWindow[ulWindowIndex % (sizeof(ColorWindow)/sizeof(COLORWINDOW))].ulBackgroundRGB,
  299.                 ColorWindow[ulWindowIndex % (sizeof(ColorWindow)/sizeof(COLORWINDOW))].ulForegroundRGB,
  300.                 FOREGROUND_WND, pHP->Windows.wdWindow[ulWindowIndex].ucWindowTitle);
  301.         else
  302.             DrawWindow(HPSDRAW, &swpWindow,
  303.                 ColorWindow[ulWindowIndex % (sizeof(ColorWindow)/sizeof(COLORWINDOW))].ulBackgroundRGB,
  304.                 ColorWindow[ulWindowIndex % (sizeof(ColorWindow)/sizeof(COLORWINDOW))].ulForegroundRGB,
  305.                 FOREGROUND_WND, pHP->Windows.wdWindow[ulWindowIndex].ucPgmTitle);
  306.         }
  307. #ifndef SLOWVIDEO
  308.                                     /* Draw the whole memory bitmap into the client area,
  309.                                        without any background or foreground color because
  310.                                        we have no monochrome bitmap */
  311.     ptl.x=ptl.y=0;
  312.     WinDrawBitmap(hpsClient, pHP->hbmMemory, NULL, &ptl, 0L, 0L, DBM_NORMAL);
  313. #endif /* SLOWVIDEO */
  314.     }
  315.     break;
  316.  
  317. /*                                                                                      *\
  318.  * Syntax: WM_DESKTOPMOVE, LONG SlidingXFactor, LONG SlidingYFactor                     *
  319. \*                                                                                      */
  320. case WM_DESKTOPMOVE:
  321. /*                                                                                      *\
  322.  * The hook found that the pointer was over one of the border rows and/or columns of    *
  323.  * the physical Desktop or the user doubleclicked on a virtual Desktop on the overview  *
  324.  * window. The passed parameter mp1 contains the number of pixels to slide all windows  *
  325.  * on the virtual Desktop horizontally. We calculate if and where the physical Desktop  *
  326.  * must be moved, or ignore it, if we're allready at a border position of the virtual   *
  327.  * Desktop. If move request is finished successfully, WM_THREADREADY is posted.         *
  328. \*                                                                                      */
  329.     {
  330.                                         /* Slide in x direction in pixels */
  331.     LONG        lSlidingXFactor=LONGFROMMP(mp1);
  332.                                         /* Slide in y direction in pixels */
  333.     LONG        lSlidingYFactor=LONGFROMMP(mp2);
  334.     ULONG       ulWindowIndex=0;        /* Index in WINDOWS structure */
  335.     BOOL        bChanged=FALSE;         /* TRUE is at least one window has been changed
  336.                                            (added, removed, moved, sized,...) */
  337.  
  338.     if(pHP->ulDebug>=DEBUG_ENTRY)
  339.         {
  340.         DosBeep(1000,250);
  341.         }
  342.     if(pHP->ulDebug>=DEBUG_FULL)
  343.         printf("Thread: WM_DESKTOPMOVE\n");
  344.     ulApplicationsCount=0;              /* Begin with first window */
  345.                                         /* From all windows select the ones we are
  346.                                            interested to move */
  347.     for( ; ulWindowIndex<=pHP->Windows.ulWindowLast; ulWindowIndex++)
  348.         {
  349.                                         /* Ignore known windows not being a movable frame window. */
  350.         if(!(pHP->Windows.wdWindow[ulWindowIndex].ulStatus & FRAMECLASS))
  351.             continue;
  352.                                         /* Preserve Window list */
  353.         if(!strcmp(pHP->Windows.wdWindow[ulWindowIndex].ucPgmTitle, pHP->ucWindowListName))
  354.             continue;
  355.                                         /* Preserve PC/2's window, locating by titlebar or frame
  356.                                            window handle */
  357.         if((strstr(pHP->Windows.wdWindow[ulWindowIndex].ucWindowTitle, "PC/2")) ||
  358.             (strstr(pHP->Windows.wdWindow[ulWindowIndex].ucPgmTitle, "PC/2"))) continue;
  359.         if(pHP->Windows.wdWindow[ulWindowIndex].swpWindow.hwnd==pHP->hwndFrame) continue;
  360.                                         /* Only move certain window */
  361.         pHP->Windows.wdWindow[ulWindowIndex].swpWindow.x+=lSlidingXFactor;
  362.         pHP->Windows.wdWindow[ulWindowIndex].swpWindow.y+=lSlidingYFactor;
  363.                                         /* Now compare current one if it changed */
  364.         if(memcmp(&swpApplications[ulApplicationsCount], &pHP->Windows.wdWindow[ulWindowIndex].swpWindow, sizeof(SWP)))
  365.             {
  366.             bChanged=TRUE;
  367.             memcpy(&swpApplications[ulApplicationsCount], &pHP->Windows.wdWindow[ulWindowIndex].swpWindow, sizeof(SWP));
  368.                                         /* Move window only if not marked non-movable. Such a window
  369.                                            appears on every Virtual Desktop but may change its position
  370.                                            relative to the lower left corner so we have to compare its
  371.                                            old and new position to update overview window correctly */
  372.             if(pHP->Windows.wdWindow[ulWindowIndex].SwpFlag & SWP_NOMOVE)
  373.                 swpApplications[ulApplicationsCount].fl=SWP_NOADJUST;
  374.             else
  375.                 swpApplications[ulApplicationsCount].fl=SWP_MOVE | SWP_NOADJUST;
  376.             }
  377.         ulApplicationsCount++;
  378.         }
  379.                                         /* Now move all windows */
  380.     if(lSlidingXFactor || lSlidingYFactor)
  381.         {
  382.         if(WinSetMultWindowPos(pHP->habPc2, swpApplications, ulApplicationsCount))
  383.             {
  384.             bChanged=TRUE;              /* If windows were successfully moved update overview window */
  385.                                         /* Adjust physical Desktop within virtual Desktop */
  386.             pHP->VirtualDesktopPos.x-=lSlidingXFactor;
  387.             pHP->VirtualDesktopPos.y-=lSlidingYFactor;
  388.                                         /* Windows have changed, request repaint client area */
  389.             WinSendMsg(hwnd, WM_PAINT, NULL, NULL);
  390.                                         /* Indicate that working thread is ready after moving windows
  391.                                            from one Virtual Desktop to another */
  392.             WinPostMsg(pHP->hwndClient, WM_THREADREADY, MPFROMLONG(THREADMOVEBUSY), NULL);
  393.             }
  394.         else
  395.                                         /* If windows weren't successfully moved retry */
  396.             WinPostMsg(hwnd, WM_DESKTOPMOVE, MPFROMLONG(lSlidingXFactor), MPFROMLONG(lSlidingYFactor));
  397.         }
  398.     else
  399.         {
  400.                                         /* If windows changed, request repaint client area */
  401.         if(bChanged) WinSendMsg(hwnd, WM_PAINT, NULL, NULL);
  402.                                         /* Indicate that working thread is ready after enumerating
  403.                                            windows */
  404.         WinPostMsg(pHP->hwndClient, WM_THREADREADY, MPFROMLONG(THREADWINDOWBUSY), NULL);
  405.         }
  406.     }
  407.     break;
  408.  
  409. /*                                                                                      *\
  410.  * Syntax: WM_SETDESKTOPHANDLE, NULL, NULL                                              *
  411. \*                                                                                      */
  412. case WM_SETDESKTOPHANDLE:
  413. /*                                                                                      *\
  414.  * Query the window handle of the Desktop windows and load them into PC2HOOK.DLL        *
  415.  * library. If the WPS is installed, we can obtain its handle by searching for a window *
  416.  * class of #37. Even if the WPS is installed, we can also obtain the the window handle *
  417.  * of the PM, which is also present, if the WPS isn't installed.                        *
  418.  * Ref.:                                                                                *
  419.  *          Windows ........... WINDOWS structure containing all windows control data   *
  420. \*                                                                                      */
  421.     {
  422.     UCHAR       ucClass[8];             /* Save class name here */
  423.     HWND        hwndWPS;                /* Save WPS window handle */
  424.     HWND        hwndDesktop;            /* Save PM window handle */
  425.     HENUM       henumWindows;           /* Enumerate windows */
  426.  
  427.                                         /* Get to bottommost window handle of the "Desktop" */
  428.     hwndDesktop=WinQueryWindow(HWND_DESKTOP, QW_BOTTOM);
  429.                                         /* Enumerate all windows at "Desktop" bottom z-order,
  430.                                            that is all windows the WPS consists of. The window
  431.                                            we are interested in is the client area which is a
  432.                                            WC_CONTAINER class windo */
  433.     henumWindows=WinBeginEnumWindows(hwndDesktop);
  434.     while((hwndWPS=WinGetNextWindow(henumWindows))!=NULLHANDLE)
  435.         {
  436.                                         /* Now get the class name of that window handle */
  437.         WinQueryClassName(hwndWPS, sizeof(ucClass), (PCH)ucClass);
  438.                                         /* If we find the required "Desktop" window (it
  439.                                            has a class name of #37, which is reserved in the
  440.                                            Toolkit) set this value into the Hook DLL.
  441.                                            The "Desktop" is just a WC_CONTAINER class.
  442.                                            This class is owned by the WPS, so we found the
  443.                                            WPS' window handle */
  444.         if(!strcmp(ucClass, DESKTOP_CLASS)) break;
  445.         }
  446.     WinEndEnumWindows(henumWindows);    /* End enumeration */
  447. /*                                                                                      *\
  448.  * Now get the PM window handle for the case, that the WPS is not installed, or moved   *
  449.  * outwards of the display (by setting the move Desktop checkbox).                      *
  450. \*                                                                                      */
  451.                                         /* Without WPS installed we can only get the
  452.                                            "Desktop" window handle */
  453.     hwndDesktop=WinQueryDesktopWindow(pHP->habPc2, NULLHANDLE);
  454.                                         /* Inform DLL if Desktop windows handles have
  455.                                            changed */
  456.     if((hwndWPS!=pHP->hwndWPS) || (hwndDesktop!=pHP->hwndDesktop))
  457.         {
  458.         pHP->hwndWPS=hwndWPS;
  459.         pHP->hwndDesktop=hwndDesktop;
  460.         }
  461.     }
  462.     break;
  463.  
  464. /*                                                                                      *\
  465.  * Syntax: WM_SETUPSIZEPOSITION, ULONG ulMsg, NULL                                      *
  466. \*                                                                                      */
  467. case WM_SETUPSIZEPOSITION:
  468. /*                                                                                      *\
  469.  * This message is posted as a result of a user event in the hook. All windows running  *
  470.  * in the system are queried and registered in the Windows control structure.           *                                                                           *
  471.  * The Window List is queried to find the Window List entries of the PM windows.        *
  472.  * Ref.:                                                                                *
  473.  *          Windows ........... WINDOWS structure containing all windows control data   *
  474. \*                                                                                      */
  475.     {
  476.     ULONG       ulWindowIndex;          /* Index in Windows.wdWindow[] */
  477.     HENUM       henumDesktop;           /* Window handle of WC_FRAME class Desktop */
  478.     HWND        hwndApplication;        /* Window handles of enumerated application */
  479.     ULONG       ulWindowListCount, ulWindowListIndex;
  480.     MENUDATA    *pMD;                   /* Pointer to MENUDATA structure of corresponding window */
  481.     PSWBLOCK    pSwBlock;               /* Pointer to window list */
  482.     BOOL        bFoundItem;             /* TRUE if current window was found within PC/2 Popup-Menu */
  483.  
  484.     if(pHP->ulDebug>=DEBUG_FULL)
  485.         printf("Thread: WM_SETUPSIZEPOSITION\n");
  486.                                         /* Query the number of entries in window list */
  487.     ulWindowListCount=WinQuerySwitchList(pHP->habPc2, NULL, 0);
  488.                                         /* Allocate space for window list */
  489.     pSwBlock=(PSWBLOCK)malloc(ulWindowListCount=(ulWindowListCount*sizeof(SWENTRY)+sizeof(HSWITCH)));
  490.                                         /* Enumerate window list to query how the Session title of a
  491.                                            frame window (using it's window handle) is spelled in the
  492.                                            Window list */
  493.     ulWindowListCount=WinQuerySwitchList(pHP->habPc2, pSwBlock, ulWindowListCount);
  494.     pHP->Windows.ulDesktop=(ULONG)-1;   /* Set to -1 if we don't find the Desktop's name */
  495.                                         /* Set to -1 if we don't find the Window List's name */
  496.     pHP->Windows.ulWindowList=(ULONG)-1;
  497.     ulWindowIndex=(ULONG)-1;            /* Begin with offset 0 in first iteration */
  498.                                         /* Enumerate all descendants of HWND_DESKTOP,
  499.                                            which are the frame windows seen on Desktop,
  500.                                            but not having necessarily the class WC_FRAME */
  501.     henumDesktop=WinBeginEnumWindows(HWND_DESKTOP);
  502.     while((hwndApplication=WinGetNextWindow(henumDesktop))!=NULLHANDLE)
  503.         {
  504.         ulWindowIndex++;
  505.                                         /* Asume window visible */
  506.         pHP->Windows.wdWindow[ulWindowIndex].ulStatus|=VISIBLE;
  507.         pHP->Windows.wdWindow[ulWindowIndex].ulStatus|=FRAMECLASS;
  508.                                         /* Get window's size and position */
  509.         WinQueryWindowPos(hwndApplication, &pHP->Windows.wdWindow[ulWindowIndex].swpWindow);
  510.         if(pHP->Windows.wdWindow[ulWindowIndex].swpWindow.fl & SWP_HIDE)
  511.                                         /* Get window's titlebar */
  512.             pHP->Windows.wdWindow[ulWindowIndex].ulStatus &= (~VISIBLE);
  513.                                         /* Get window's class name */
  514.         WinQueryClassName(hwndApplication, CLASSNAMESIZE,
  515.             pHP->Windows.wdWindow[ulWindowIndex].ucClassName);
  516.                                         /* If it is an minimized icon text class window
  517.                                            treat it as an invisible one */
  518.         if(!strcmp(pHP->Windows.wdWindow[ulWindowIndex].ucClassName, "#32765"))
  519.             pHP->Windows.wdWindow[ulWindowIndex].ulStatus &= (~VISIBLE);
  520.                                         /* If it is a menu treat it as an invisible one and
  521.                                            not being a frame window */
  522.         if(!strcmp(pHP->Windows.wdWindow[ulWindowIndex].ucClassName, "#4"))
  523.             {
  524.             pHP->Windows.wdWindow[ulWindowIndex].ulStatus &= (~VISIBLE);
  525.             pHP->Windows.wdWindow[ulWindowIndex].ulStatus &= (~FRAMECLASS);
  526.             }
  527.                                         /* If it is a combobox treat it as an invisible one and
  528.                                            not being a frame window */
  529.         if(!strcmp(pHP->Windows.wdWindow[ulWindowIndex].ucClassName, "#7"))
  530.             {
  531.             pHP->Windows.wdWindow[ulWindowIndex].ulStatus &= (~VISIBLE);
  532.             pHP->Windows.wdWindow[ulWindowIndex].ulStatus &= (~FRAMECLASS);
  533.             }
  534.                                         /* Get window's titlebar */
  535.         WinQueryWindowText(hwndApplication, MAXNAMEL+1,
  536.             pHP->Windows.wdWindow[ulWindowIndex].ucPgmTitle);
  537.                                         /* If we found the index of the Window List save it */
  538.         if(strstr(pHP->Windows.wdWindow[ulWindowIndex].ucPgmTitle, pHP->ucWindowListName))
  539.             {
  540.             pHP->hwndWindowList=hwndApplication;
  541.             pHP->Windows.ulWindowList=ulWindowIndex;
  542.             pHP->Windows.wdWindow[ulWindowIndex].ulStatus &= (~FRAMECLASS);
  543.             }
  544.                                         /* If we found the index of the Desktop save it */
  545.         if(strstr(pHP->Windows.wdWindow[ulWindowIndex].ucPgmTitle, pHP->ucDesktopName))
  546.             {
  547.             pHP->Windows.ulDesktop=ulWindowIndex;
  548.             if(!(pHP->ulStatusFlag & (MOVEDESKTOP | EXPANDWPS)))
  549.                 pHP->Windows.wdWindow[ulWindowIndex].ulStatus &= (~FRAMECLASS);
  550.             }
  551.                                         /* If we found a "shadow" window created by seamless
  552.                                            WIN-OS2 ignore it. E.g. a dropdown menu is painted
  553.                                            into a PM window named "Seamless" to allow the menu
  554.                                            to be displayed outside any area coverd by the WIN-OS2
  555.                                            application too */
  556.         if(strstr(pHP->Windows.wdWindow[ulWindowIndex].ucPgmTitle, "Seamless"))
  557.             {
  558.             pHP->Windows.wdWindow[ulWindowIndex].ulStatus &= (~VISIBLE);
  559.             pHP->Windows.wdWindow[ulWindowIndex].ulStatus &= (~FRAMECLASS);
  560.             }
  561.                                         /* If we found PC/2, or any of PC/2's dialogs save it */
  562.         if(hwndApplication==pHP->hwndFrame)
  563.             pHP->Windows.wdWindow[ulWindowIndex].ulStatus &= (~VISIBLE);
  564.         if(strstr(pHP->Windows.wdWindow[ulWindowIndex].ucPgmTitle, "PC/2"))
  565.             pHP->Windows.wdWindow[ulWindowIndex].ulStatus &= (~VISIBLE);
  566.                                         /* If we don't find an entry in the Window List set
  567.                                            it to default empty string */
  568.         strcpy(pHP->Windows.wdWindow[ulWindowIndex].ucWindowTitle, "");
  569.                                         /* If we don't find an entry set to 0 */
  570.         pHP->Windows.wdWindow[ulWindowIndex].hswitchWindow=0;
  571.         for(ulWindowListIndex=0; ulWindowListIndex<=ulWindowListCount; ulWindowListIndex++)
  572.             {                           /* If window handle of frame window and window handle in
  573.                                            window list equal, copy the name of the entry from the
  574.                                            window list */
  575.             if(pSwBlock->aswentry[ulWindowListIndex].swctl.hwnd==pHP->Windows.wdWindow[ulWindowIndex].swpWindow.hwnd)
  576.                 {
  577.                 strcpy(pHP->Windows.wdWindow[ulWindowIndex].ucWindowTitle,
  578.                     pSwBlock->aswentry[ulWindowListIndex].swctl.szSwtitle);
  579.                                         /* Get the switch handle */
  580.                 pHP->Windows.wdWindow[ulWindowIndex].hswitchWindow=pSwBlock->aswentry[ulWindowListIndex].hswitch;
  581.                 break;                  /* If found we need no further seek */
  582.                 }
  583.             }
  584.                                         /* Search if current window is contained in PC/2's
  585.                                            Popup-Menu */
  586.         bFoundItem=FALSE;
  587.         pMD=SearchTitle(pHP->pPopupMenu, &pHP->Windows.wdWindow[ulWindowIndex], &bFoundItem);
  588.         if(pMD!=NULL)
  589.                                         /* If found copy flag because we need to determine
  590.                                            if window should be moved on virtual Desktops
  591.                                            and how it should be restored when hotkeying to it */
  592.             {
  593.             pHP->Windows.wdWindow[ulWindowIndex].SwpFlag=pMD->SwpFlag;
  594.             memcpy(&pHP->Windows.wdWindow[ulWindowIndex].KeyData, &(pMD->KeyData), sizeof(KEYDATA));
  595.             if(pMD->SwpFlag & SWP_MOVEWINDOW)
  596.                 {
  597.                 SWP     swp;
  598.                 USHORT  usSwp;
  599.                                         /* If window was only invisible because of the movement
  600.                                            make it visible again */
  601.                 if(pMD->SwpFlag & SWP_MOVEWINDOWVISIBLE)
  602.                     usSwp=SWP_MOVE | SWP_SHOW | SWP_NOADJUST;
  603.                 else
  604.                     usSwp=SWP_MOVE | SWP_NOADJUST;
  605.                                         /* If this flag is set we found an application's window
  606.                                            the first time after invokation and we have to reposition
  607.                                            it and reset the flag */
  608.                 pMD->SwpFlag&=(~(SWP_MOVEWINDOW | SWP_MOVEWINDOWVISIBLE));
  609.                                         /* Now calculate window's position on Virtual Desktops and
  610.                                            move it to its absolute (relative to logical 0|0) position */
  611.                 swp.fl=usSwp;
  612.                 swp.x=pMD->InitXPos-pHP->VirtualDesktopPos.x,
  613.                 swp.y=pMD->InitYPos-pHP->VirtualDesktopPos.y,
  614.                 swp.hwndInsertBehind=HWND_TOP;
  615.                 swp.hwnd=pHP->Windows.wdWindow[ulWindowIndex].swpWindow.hwnd;
  616.                 WinSetMultWindowPos(pHP->habPc2, &swp, 1);
  617.                 }
  618.             }
  619.         else
  620.             {
  621.             pHP->Windows.wdWindow[ulWindowIndex].SwpFlag=0;
  622.             memset(&pHP->Windows.wdWindow[ulWindowIndex].KeyData, 0, sizeof(KEYDATA));
  623.             }
  624.         }
  625.     WinEndEnumWindows(henumDesktop);    /* End enumeration */
  626.     pHP->Windows.ulWindowLast=ulWindowIndex;
  627.     free(pSwBlock);
  628.     WinPostMsg(hwnd, WM_DESKTOPMOVE, MPFROMLONG(0), MPFROMLONG(0));
  629.     }
  630.     break;
  631.  
  632. /*                                                                                      *\
  633.  * Syntax: WM_BUTTON1DBLCLK, (LONG mp1), (LONG mp2)                                     *
  634. \*                                                                                      */
  635. case WM_BUTTON1DBLCLK:
  636. /*                                                                                      *\
  637.  * This message detected and passed from the PC/2 window procedure is used to switch    *
  638.  * between Virtual Desktops.                                                            *
  639.  * Ref.:                                                                                *
  640.  *          Windows ........... WINDOWS structure containing all windows control data   *
  641. \*                                                                                      */
  642.     {
  643.     LONG        lClickX, lClickY;       /* Pointer position during click */
  644.     LONG        lSlidingXFactor;        /* Slide in x direction in pixels */
  645.     LONG        lSlidingYFactor;        /* Slide in y direction in pixels */
  646.  
  647.     if(pHP->ulDebug>=DEBUG_ENTRY)
  648.         {
  649.         DosBeep(1000,250);
  650.         }
  651.     if(pHP->ulDebug>=DEBUG_FULL)
  652.         printf("Thread: WM_BUTTON1DBLCLK\n");
  653.                                         /* Get the virtual Desktop the user doubleclicked on */
  654.     lClickX=pHP->VirtualDesktopMin.x;
  655.     lClickY=pHP->VirtualDesktopMin.y;
  656.     lClickX+=((LONG)(SHORT1FROMMP(mp1)))/
  657.         (pHP->swpPC2Client.cx/pHP->ulHorizontalDesktops)*pHP->DesktopSize.x;
  658.     lClickY+=((LONG)(SHORT2FROMMP(mp1)))/
  659.         (pHP->swpPC2Client.cy/pHP->ulVerticalDesktops)*pHP->DesktopSize.y;
  660.                                         /* The right and top borders are the limit (necessary because
  661.                                            the frame rectangle is sized pointwise and the virtual Desktops
  662.                                            drawn are sized every n points leaving 0 to n-1 points outside.
  663.                                            Can be fixed by allowing the frame also sized only every n
  664.                                            points, but this requires subclassing of the frame. */
  665.     if(lClickX>(pHP->VirtualDesktopMax.x-pHP->DesktopSize.x))
  666.         lClickX=(pHP->VirtualDesktopMax.x-pHP->DesktopSize.x);
  667.     if(lClickY>(pHP->VirtualDesktopMax.y-pHP->DesktopSize.y))
  668.         lClickY=(pHP->VirtualDesktopMax.y-pHP->DesktopSize.y);
  669.                                         /* Calculate Desktop move in pixel */
  670.     lSlidingXFactor=pHP->VirtualDesktopPos.x-lClickX;
  671.     lSlidingYFactor=pHP->VirtualDesktopPos.y-lClickY;
  672.     if(lSlidingXFactor || lSlidingYFactor)
  673.                                         /* Now move the windows */
  674.         WinPostMsg(pHP->hwndThread, WM_DESKTOPMOVE, MPFROMLONG(lSlidingXFactor), MPFROMLONG(lSlidingYFactor));
  675.     else
  676.                                         /* Indicate that working thread is ready because it doesn't need
  677.                                            to move windows from one Virtual Desktop to another */
  678.         WinPostMsg(pHP->hwndClient, WM_THREADREADY, MPFROMLONG(THREADMOVEBUSY), NULL);
  679.     }
  680.     break;
  681.  
  682. /*                                                                                      *\
  683.  * Syntax: WM_HOTKEY, (USHORT usFlags, USHORT usCh), ULONG ulKeyDataIndex               *
  684.  *                                                                                      *
  685. \*                                                                                      */
  686. case WM_HOTKEY:
  687. /*                                                                                      *\
  688.  * WM_HOTKEY is a WM_CHAR message, passed when a hotkey was detected in PC2Hook.DLL.    *
  689.  * The key passed from the input hook is flaged as used. Either the running program     *
  690.  * corresponding to the hotkey is switched into the foreground, or if it is not already *
  691.  * running it is started.                                                               *
  692.  * Ref.:                                                                                *
  693.  *          Windows ........... WINDOWS structure containing all windows control data   *
  694. \*                                                                                      */
  695.     {
  696.                                         /* Get key code */
  697.     USHORT      usFlags=SHORT1FROMMP(mp1);
  698.                                         /* Get ASCII key value */
  699.     USHORT      usCh=SHORT2FROMMP(mp1);
  700.                                         /* Index in KeyData of HotKey found */
  701.     ULONG       ulKeyDataIndex=LONGFROMMP(mp2);
  702.     POINTL      VirtualDesktopPos;      /* Copy structure from HookParameters */
  703.     ULONG       ulWindowIndex;          /* Index in Windows.wdWindow[] */
  704.     POINTL      HotKeyWindow;           /* Position of the window the Hotkey is defined for
  705.                                            in coordinates relative to logical (0|0) point */
  706.     LONG        lSlidingXFactor=0;      /* Slide in x direction in pixels */
  707.     LONG        lSlidingYFactor=0;      /* Slide in y direction in pixels */
  708.     LONG        lDiff;
  709.     USHORT      usfl;                   /* Flags for WinSetMultWindowPos() */
  710.  
  711.     if(pHP->ulDebug>=DEBUG_FULL)
  712.         printf("Thread: WM_HOTKEY\n");
  713.     VirtualDesktopPos=pHP->VirtualDesktopPos;
  714.                                         /* Find match between actual hotkey pressed and
  715.                                            any (available) window this hotkey is defined for */
  716.     for(ulWindowIndex=0; ulWindowIndex<=pHP->Windows.ulWindowLast; ulWindowIndex++)
  717.         {
  718.         if((pHP->Windows.wdWindow[ulWindowIndex].KeyData.usFlags==usFlags) &&
  719.             (pHP->Windows.wdWindow[ulWindowIndex].KeyData.usCh==usCh))
  720.             break;
  721.         }
  722.                                         /* Only do something when a window for a hotkey
  723.                                            is available */
  724.     if(ulWindowIndex<=pHP->Windows.ulWindowLast)
  725.         {                               /* The coordinates in the WINDOWS structure are relative to
  726.                                            PM, which is, if the Virtual Desktop is enabled, relative
  727.                                            to the logical (0|0) point (which is the lower left position
  728.                                            of the Display in the overview window.
  729.                                            To get the position relative to logical (0|0) get the winow's
  730.                                            position on PM and add the logical position of PM relative to
  731.                                            logical (0|0). Compare with the middle of the hotkeyed window. */
  732.         HotKeyWindow.x=pHP->VirtualDesktopPos.x+
  733.             pHP->Windows.wdWindow[ulWindowIndex].swpWindow.x+(pHP->Windows.wdWindow[ulWindowIndex].swpWindow.cx>>1);
  734.         HotKeyWindow.y=pHP->VirtualDesktopPos.y+
  735.             pHP->Windows.wdWindow[ulWindowIndex].swpWindow.y+(pHP->Windows.wdWindow[ulWindowIndex].swpWindow.cy>>1);
  736.                                         /* Move physical Desktop right, but not over the
  737.                                            right border of the virtual Desktop until
  738.                                            the hotkeyed window's horizontal position comes
  739.                                            onto the Desktop */
  740.         while(HotKeyWindow.x>(VirtualDesktopPos.x+pHP->SlidingXFactor))
  741.             {                           /* Move physical Desktop right one additional unit,
  742.                                            can also be seen to move all windows in virtual
  743.                                            Desktop left one additional unit */
  744.             lSlidingXFactor-=pHP->SlidingXFactor;
  745.             VirtualDesktopPos.x+=pHP->SlidingXFactor;
  746.             lDiff=VirtualDesktopPos.x-(pHP->VirtualDesktopMax.x-pHP->DesktopSize.x);
  747.             if(lDiff>0)                 /* Correct if we moved out of the physical Desktop */
  748.                 {
  749.                 lSlidingXFactor+=lDiff;
  750.                 break;                  /* We can't move further */
  751.                 }
  752.             }
  753.                                         /* Do the same left */
  754.         while(HotKeyWindow.x<VirtualDesktopPos.x)
  755.             {                           /* Move physical Desktop left one additional unit */
  756.             lSlidingXFactor+=pHP->SlidingXFactor;
  757.             VirtualDesktopPos.x-=pHP->SlidingXFactor;
  758.             lDiff=VirtualDesktopPos.x-pHP->VirtualDesktopMin.x;
  759.             if(lDiff<0)                 /* Correct if we moved out of the physical Desktop */
  760.                 {
  761.                 lSlidingXFactor+=lDiff;
  762.                 break;                  /* We can't move further */
  763.                 }
  764.             }
  765.                                         /* Move physical Desktop up, but not over the
  766.                                            top border of the virtual Desktop until
  767.                                            the hotkeyed window's vertiacal position comes
  768.                                            onto the Desktop */
  769.         while(HotKeyWindow.y>(VirtualDesktopPos.y+pHP->SlidingYFactor))
  770.             {                           /* Move physical Desktop up one additional unit,
  771.                                            can also be seen to move all windows in virtual
  772.                                            Desktop down one additional unit */
  773.             lSlidingYFactor-=pHP->SlidingYFactor;
  774.             VirtualDesktopPos.y+=pHP->SlidingYFactor;
  775.             lDiff=VirtualDesktopPos.y-(pHP->VirtualDesktopMax.y-pHP->DesktopSize.y);
  776.             if(lDiff>0)                 /* Correct if we moved out of the physical Desktop */
  777.                 {
  778.                 lSlidingYFactor+=lDiff;
  779.                 break;                  /* We can't move further */
  780.                 }
  781.             }
  782.                                         /* Do the same downwards */
  783.         while(HotKeyWindow.y<VirtualDesktopPos.y)
  784.             {                           /* Move physical Desktop down one additional unit */
  785.             lSlidingYFactor+=pHP->SlidingYFactor;
  786.             VirtualDesktopPos.y-=pHP->SlidingYFactor;
  787.             lDiff=VirtualDesktopPos.y-pHP->VirtualDesktopMin.y;
  788.             if(lDiff<0)                 /* Correct if we moved out of the physical Desktop */
  789.                 {
  790.                 lSlidingYFactor+=lDiff;
  791.                 break;                  /* We can't move further */
  792.                 }
  793.             }
  794.         if(lSlidingXFactor || lSlidingYFactor)
  795.                                         /* Now move the windows and activate window after move. Prior
  796.                                            version 1.80 WinPostMsg() was used to switch to a Virtual
  797.                                            Desktop. This worked unless the window we switched to with
  798.                                            the Hotkey was minmized. In this case the window got
  799.                                            activated first by the WinSetMultWindowPos() call, before
  800.                                            the Virtual Desktop got switch by WM_DESKTOPMOVE, causing
  801.                                            the minimized window expanding to the current Desktop, with
  802.                                            a switch to the Virtual Desktop the minimized window was
  803.                                            afterwards.
  804.                                            Version 1.90+ uses WinSendMsg() to switch to the Virtual
  805.                                            Desktop first, before restoring the minimized window. */
  806.             WinSendMsg(pHP->hwndThread, WM_DESKTOPMOVE, MPFROMLONG(lSlidingXFactor), MPFROMLONG(lSlidingYFactor));
  807.                                         /* Get flags WinSetMultWindowPos() */
  808.         usfl=(pHP->Windows.wdWindow[ulWindowIndex].SwpFlag & ~SWP_NOMOVE) | SWP_SHOW;
  809.                                         /* If not switch handle found activate window through
  810.                                            WinSetMultWindowPos() else via WinSwitchToProgram which
  811.                                            also switches to different screen groups */
  812.         if(!pHP->Windows.wdWindow[ulWindowIndex].hswitchWindow)
  813.             usfl|=(SWP_ACTIVATE | SWP_ZORDER);
  814.         pHP->Windows.wdWindow[ulWindowIndex].swpWindow.fl=usfl;
  815.         pHP->Windows.wdWindow[ulWindowIndex].swpWindow.hwndInsertBehind=HWND_TOP;
  816.         WinSetMultWindowPos(pHP->habPc2, &pHP->Windows.wdWindow[ulWindowIndex].swpWindow, 1);
  817.         if(pHP->Windows.wdWindow[ulWindowIndex].hswitchWindow)
  818.             WinSwitchToProgram(pHP->Windows.wdWindow[ulWindowIndex].hswitchWindow);
  819.         }
  820.     else
  821.         {                               /* If no session found for the pressed hotkey, start
  822.                                            the corresponding session */
  823.         WinPostMsg(pHP->hwndClient, WM_COMMAND,
  824.                                         /* Get ID and set it as posted by a menu control */
  825.             MPFROM2SHORT((USHORT)((pHP->pKeyData+ulKeyDataIndex)->pMenuData->id),
  826.                 CMDSRC_MENU),
  827.                                         /* Simulate Message a result of a keyboard operation */
  828.             MPFROMCHAR(FALSE));
  829.         }
  830.     }
  831.     break;
  832.  
  833. /*                                                                                      *\
  834.  * Syntax: WM_WINDOWLIST, (USHORT x, USHORT y), NULL                                    *
  835. \*                                                                                      */
  836. case WM_WINDOWLIST:
  837. /*                                                                                      *\
  838.  * WM_WINDIWLIST is sent by PC2Hook.dll and passed from PC/2's window procedure, if     *
  839.  * mouse clicks are detected on PM that would display the Window List on the WPS. Be-   *
  840.  * cause the WPS displayed the Window List but not PM, we simulate this on PM.          *
  841.  * Ref.:                                                                                *
  842.  *          Windows ........... WINDOWS structure containing all windows control data   *
  843. \*                                                                                      */
  844.     {                                   /* Mouse position when Window List was requested */
  845.     USHORT      usX=SHORT1FROMMP(mp1), usY=SHORT2FROMMP(mp1);
  846.  
  847.     if(pHP->Windows.ulWindowList!=(ULONG)-1) /* Display Window List */
  848.         {
  849.                                         /* Place Window List centered under mouse pointer
  850.                                            whenever possible */
  851.         if((pHP->Windows.wdWindow[pHP->Windows.ulWindowList].swpWindow.cx>>1)>usX)
  852.             usX=0;
  853.         else if(pHP->DesktopSize.x-(pHP->Windows.wdWindow[pHP->Windows.ulWindowList].swpWindow.cx>>1)<usX)
  854.             usX=pHP->DesktopSize.x-pHP->Windows.wdWindow[pHP->Windows.ulWindowList].swpWindow.cx;
  855.         else usX=usX-(pHP->Windows.wdWindow[pHP->Windows.ulWindowList].swpWindow.cx>>1);
  856.         if((pHP->Windows.wdWindow[pHP->Windows.ulWindowList].swpWindow.cy>>1)>usY)
  857.             usY=0;
  858.         else if(pHP->DesktopSize.y-(pHP->Windows.wdWindow[pHP->Windows.ulWindowList].swpWindow.cy>>1)<usY)
  859.             usY=pHP->DesktopSize.y-pHP->Windows.wdWindow[pHP->Windows.ulWindowList].swpWindow.cy;
  860.         else usY=usY-(pHP->Windows.wdWindow[pHP->Windows.ulWindowList].swpWindow.cy>>1);
  861.         pHP->Windows.wdWindow[pHP->Windows.ulWindowList].swpWindow.fl=
  862.             SWP_MOVE|SWP_SHOW|SWP_ZORDER|SWP_NOADJUST;
  863.         pHP->Windows.wdWindow[pHP->Windows.ulWindowList].swpWindow.x=usX;
  864.         pHP->Windows.wdWindow[pHP->Windows.ulWindowList].swpWindow.y=usY;
  865.         pHP->Windows.wdWindow[pHP->Windows.ulWindowList].swpWindow.hwndInsertBehind=HWND_TOP;
  866.         WinSetMultWindowPos(pHP->habPc2, &pHP->Windows.wdWindow[pHP->Windows.ulWindowList].swpWindow, 1);
  867.         if(pHP->Windows.wdWindow[pHP->Windows.ulWindowList].hswitchWindow)
  868.             WinSwitchToProgram(pHP->Windows.wdWindow[pHP->Windows.ulWindowList].hswitchWindow);
  869.         }
  870.     }
  871.     break;
  872.  
  873. /*                                                                                      *\
  874.  * Syntax: WM_MOVEREQUEST, (USHORT usMouseXPos, USHORT usMouseYPos), (ULONG ulMoveFlag) *
  875. \*                                                                                      */
  876. case WM_MOVEREQUEST:
  877. /*                                                                                      *\
  878.  * This local procedure is called from the PC2DLL_Hook procedure to move the windows    *
  879.  * within the virtual Desktop on its behalf.                                            *
  880.  * Req.:                                                                                *
  881.  *      usMouseXPos.... X Position of mouse pointer during creation of move message     *
  882.  *      usMouseYPos.... Y Position of mouse pointer during creation of move message     *
  883.  *      ulMoveFlag..... Bitmapped flag to control move                                  *
  884.  * Returns:                                                                             *
  885.  *      none                                                                            *
  886.  * Ref.:                                                                                *
  887.  *      Windows ....... WINDOWS structure containing all windows control data           *
  888. \*                                                                                      */
  889.     {
  890.                                         /* Get pointer position */
  891.     LONG        lMouseXPos=(LONG)SHORT1FROMMP(mp1);
  892.     LONG        lMouseYPos=(LONG)SHORT2FROMMP(mp1);
  893.     POINTL      VirtualDesktopPos;      /* Copy structure from HookParameters */
  894.                                         /* Get bitmapped move control flag */
  895.     ULONG       ulMoveFlag=LONGFROMMP(mp2);
  896.     LONG        lSlidingXFactor;        /* Horizontal offset to move */
  897.     LONG        lSlidingYFactor;        /* Vertical offset to move */
  898.     LONG        lDiff;                  /* Difference between movement and Desktop size */
  899.  
  900.     if(pHP->ulDebug>=DEBUG_ENTRY)
  901.         {
  902.         DosBeep(1000,250);
  903.         }
  904.     if(pHP->ulDebug>=DEBUG_FULL)
  905.         printf("Thread: WM_MOVEREQUEST\n");
  906.     lSlidingXFactor=0;
  907.     lSlidingYFactor=0;
  908.     VirtualDesktopPos=pHP->VirtualDesktopPos;
  909.     if((ulMoveFlag&MOVEXR))
  910.         {                               /* Move physical Desktop left, but not over the
  911.                                            left border of the virtual Desktop */
  912.         lSlidingXFactor=pHP->SlidingXFactor;
  913.         VirtualDesktopPos.x-=pHP->SlidingXFactor;
  914.         lDiff=VirtualDesktopPos.x-pHP->VirtualDesktopMin.x;
  915.         if(lDiff<0)
  916.             {
  917.             lSlidingXFactor+=lDiff;
  918.             }
  919.         }
  920.     if((ulMoveFlag&MOVEXL))
  921.         {                               /* Move physical Desktop right, but not over the
  922.                                            right border of the virtual Desktop */
  923.         lSlidingXFactor=-pHP->SlidingXFactor;
  924.         VirtualDesktopPos.x+=pHP->SlidingXFactor;
  925.         lDiff=VirtualDesktopPos.x-(pHP->VirtualDesktopMax.x-pHP->DesktopSize.x);
  926.         if(lDiff>0)
  927.             {
  928.             lSlidingXFactor+=lDiff;
  929.             }
  930.         }
  931.     if((ulMoveFlag&MOVEYU))
  932.         {                               /* Move physical Desktop down, but not under the
  933.                                            bottom border of the virtual Desktop */
  934.         lSlidingYFactor=pHP->SlidingYFactor;
  935.         VirtualDesktopPos.y-=pHP->SlidingYFactor;
  936.         lDiff=VirtualDesktopPos.y-pHP->VirtualDesktopMin.y;
  937.         if(lDiff<0)
  938.             {
  939.             lSlidingYFactor+=lDiff;
  940.             }
  941.         }
  942.     if((ulMoveFlag&MOVEYD))
  943.         {                               /* Move physical Desktop up, but not over the
  944.                                            top border of the virtual Desktop */
  945.         lSlidingYFactor=-pHP->SlidingYFactor;
  946.         VirtualDesktopPos.y+=pHP->SlidingYFactor;
  947.         lDiff=VirtualDesktopPos.y-(pHP->VirtualDesktopMax.y-pHP->DesktopSize.y);
  948.         if(lDiff>0)
  949.             {
  950.             lSlidingYFactor+=lDiff;
  951.             }
  952.         }
  953.                                         /* If there is nothing to move, because we are
  954.                                            on a border position, don't do further processing
  955.                                            but return */
  956.     if(lSlidingXFactor || lSlidingYFactor)
  957.         {                               /* Move pointer so that it is on that pixel it
  958.                                            would be, if we hadn't moved the windows. Also
  959.                                            change the pixel which gets the message. */
  960.         if(pHP->ulScrollPercentage==100)
  961.             WinSetPointerPos(HWND_DESKTOP, (lMouseXPos+=lSlidingXFactor*0.5),
  962.                 (lMouseYPos+=lSlidingYFactor*0.5));
  963.         else
  964.             WinSetPointerPos(HWND_DESKTOP, (lMouseXPos+=lSlidingXFactor),
  965.                 (lMouseYPos+=lSlidingYFactor));
  966.                                         /* Inform working thread to move windows */
  967.         WinPostMsg(pHP->hwndThread, WM_DESKTOPMOVE,
  968.             MPFROMLONG(lSlidingXFactor), MPFROMLONG(lSlidingYFactor));
  969.         }
  970.     else
  971.                                         /* If clicked on absolute border row or column we
  972.                                            don't have to do anything but to reset move busy flag */
  973.         WinPostMsg(pHP->hwndClient, WM_THREADREADY, MPFROMLONG(THREADMOVEBUSY), NULL);
  974.     }
  975.     break;
  976.  
  977. /*                                                                                      *\
  978.  * Syntax: WM_EXPANDWPS, (BOOL bExpand)                                                 *
  979. \*                                                                                      */
  980. case WM_EXPANDWPS:
  981. /*                                                                                      *\
  982.  * This local procedure is called to resize the WPS either to the whole Virtual         *
  983.  * Desktop or to the size of the physical screen.                                       *
  984.  * Req:                                                                                 *
  985.  *      bExpand ....... TRUE if WPS should expand to whole Virtual Desktop              *
  986.  *                      FALSE otherwise                                                 *
  987.  * Returns:                                                                             *
  988.  *      none                                                                            *
  989.  * Ref.:                                                                                *
  990. \*                                                                                      */
  991.     {
  992.     SWP     swp;
  993.  
  994.                                         /* If no WPS is running it can't be sized */
  995.     if(!pHP->hwndWPS) break;
  996.     if((BOOL)SHORT1FROMMP(mp1)==TRUE)
  997.         {
  998.                                         /* If WPS should be expanded to whole Virtual Desktop
  999.                                            resize and move WPS */
  1000.         if(pHP->ulStatusFlag & EXPANDWPS)
  1001.                                         /* Resize WPS which is the parent window of the WC_CONTAINER
  1002.                                            class client area we catch mouse clicks on to display
  1003.                                            the Popup-Menu */
  1004.             swp.fl=SWP_SIZE|SWP_MOVE|SWP_NOADJUST;
  1005.             swp.x=pHP->VirtualDesktopMin.x-pHP->VirtualDesktopPos.x-1;
  1006.             swp.y=pHP->VirtualDesktopMin.y-pHP->VirtualDesktopPos.y-1;
  1007.             swp.cx=pHP->DesktopSize.x*pHP->ulHorizontalDesktops+2;
  1008.             swp.cy=pHP->DesktopSize.y*pHP->ulVerticalDesktops+
  1009.                 WinQuerySysValue(HWND_DESKTOP, SV_CYTITLEBAR)+2;
  1010.             swp.hwndInsertBehind=NULLHANDLE;
  1011.             swp.hwnd=WinQueryWindow(pHP->hwndWPS, QW_PARENT);
  1012.             WinSetMultWindowPos(pHP->habPc2, &swp, 1);
  1013.         }
  1014.     else
  1015.         {                               /* If WPS was expanded to whole Virtual Desktop
  1016.                                            resize and move WPS to default */
  1017.         swp.fl=SWP_SIZE|SWP_MOVE|SWP_NOADJUST;
  1018.         swp.x=-1;
  1019.         swp.y=-1;
  1020.         swp.cx=pHP->DesktopSize.x+2;
  1021.         swp.cy=pHP->DesktopSize.y+WinQuerySysValue(HWND_DESKTOP, SV_CYTITLEBAR)+2;
  1022.         swp.hwndInsertBehind=NULLHANDLE;
  1023.         swp.hwnd=WinQueryWindow(pHP->hwndWPS, QW_PARENT);
  1024.         WinSetMultWindowPos(pHP->habPc2, &swp, 1);
  1025.         }
  1026.     }
  1027.     break;
  1028.  
  1029. /*                                                                                      *\
  1030.  * Syntax: WM_BACKGROUNDBITMAP, NULL, NULL                                              *
  1031. \*                                                                                      */
  1032. case WM_BACKGROUNDBITMAP:
  1033. /*                                                                                      *\
  1034.  * This local procedure is called to change the PM background bitmap.                   *
  1035.  * Req:                                                                                 *
  1036.  *      HookParameters. Extract bitmap info                                             *
  1037.  * Returns:                                                                             *
  1038.  *      none                                                                            *
  1039.  * Ref.:                                                                                *
  1040. \*                                                                                      */
  1041.     {
  1042.     DESKTOP Desktop;                    /* Desktop state structure */
  1043.  
  1044.     Desktop.cbSize=sizeof(DESKTOP);     /* Length */
  1045.     Desktop.hbm=0;                      /* Bitmap handle */
  1046.     Desktop.x=Desktop.y=0;              /* Bitmap origin coordinates */
  1047.                                         /* Desktop background state settings */
  1048.     if(pHP->ulStatusFlag & BACKGROUNDBITMAP)
  1049.         {
  1050.                                         /* Load it from file and destroy existing one */
  1051.         Desktop.fl=SDT_LOADFILE;
  1052.         if(pHP->ulBackgroundBitmapFlag & BITMAPNORMAL)
  1053.             Desktop.fl|=SDT_CENTER;
  1054.         if(pHP->ulBackgroundBitmapFlag & BITMAPSCALED)
  1055.             Desktop.fl|=SDT_SCALE;
  1056.         if(pHP->ulBackgroundBitmapFlag & BITMAPTILED)
  1057.             {
  1058.             Desktop.fl|=SDT_TILE;
  1059.                                         /* Use tile count if set otherwise 0 */
  1060.             Desktop.lTileCount=pHP->ulBackgroundBitmapFlag & 0xFFFF;
  1061.             }
  1062.         else
  1063.             Desktop.lTileCount=0;
  1064.                                         /* Full qualified path to bitmap file */
  1065.         strcpy(Desktop.szFile, pHP->ucBackgroundBitmap);
  1066.         }
  1067.     else
  1068.         {                               /* If no bitmap should be selected unset and destroy it */
  1069.         Desktop.fl=SDT_DESTROY | SDT_NOBKGND;
  1070.         Desktop.lTileCount=0;           /* No tile count */
  1071.         Desktop.szFile[0]='\0';         /* No bitmap file */
  1072.         }
  1073.                                         /* Set new PM desktop background bitmap */
  1074.     WinSetDesktopBkgnd(HWND_DESKTOP, &Desktop);
  1075.     }
  1076.     break;
  1077.  
  1078. /*                                                                                      *\
  1079.  * Syntax: WM_SETDRIVEROOT, NULL, NULL                                                  *
  1080. \*                                                                                      */
  1081. case WM_SETDRIVEROOT:
  1082. /*                                                                                      *\
  1083.  * This message is posted to change to the root directory of all local drives, so that  *
  1084.  * before another application is startet via the Popup-Menu all local drives are        *
  1085. \*                                                                                      */
  1086.     SetDriveRoot();                     /* Change to root */
  1087.     break;
  1088.  
  1089. default:                                /* Default window procedure must be called */
  1090.     return((MRESULT)WinDefWindowProc(hwnd, msg, mp1, mp2));
  1091. }
  1092. return((MRESULT)FALSE);                 /* We have handled the message */
  1093. }
  1094.  
  1095.