home *** CD-ROM | disk | FTP | other *** search
/ ftp.wwiv.com / ftp.wwiv.com.zip / ftp.wwiv.com / pub / MISC / LSW270SR.ZIP / lswitch.c < prev    next >
C/C++ Source or Header  |  2004-04-11  |  37KB  |  964 lines

  1. /*
  2.  *      Copyright (C) 1997-2004 Andrei Los.
  3.  *      This file is part of the lSwitcher source package.
  4.  *      lSwitcher is free software; you can redistribute it and/or modify
  5.  *      it under the terms of the GNU General Public License as published
  6.  *      by the Free Software Foundation, in version 2 as it comes in the
  7.  *      "COPYING" file of the lSwitcher main distribution.
  8.  *      This program is distributed in the hope that it will be useful,
  9.  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11.  *      GNU General Public License for more details.
  12.  */
  13.  
  14. #include "lswitch.h"
  15. #include "settings.h"
  16. #include "taskbar.h"
  17. #include "common.h"
  18. #include "fsutil.h"
  19. #include "prmdlg.h"
  20.  
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include <process.h>
  25. #include <ctype.h>
  26. #include <unikbd.h>
  27.  
  28. /* we subclass the window procedure of the popup window frame */
  29. static MRESULT EXPENTRY FrameWndProc(HWND hwnd,ULONG msg,MPARAM mp1,MPARAM mp2)
  30. {
  31.  
  32.   switch (msg) {
  33.   case WM_ADJUSTWINDOWPOS: {
  34.     SWP *pswp;
  35.     LSWDATA *plswData;
  36.  
  37. #ifndef XWORKPLACE
  38.     plswData = WinQueryWindowPtr(WinWindowFromID(hwnd,FID_CLIENT),0);
  39. #else
  40.     plswData = ((PXCENTERWIDGET)WinQueryWindowPtr(WinWindowFromID(hwnd,FID_CLIENT),0))->pUser;
  41. #endif
  42.  
  43.     pswp = PVOIDFROMMP(mp1);
  44.  
  45.     if (!plswData->bNowActive) {
  46.       /* make sure we are not brought to top or activated as a result of other
  47.        windows repositioning */
  48.       if (pswp->fl & SWP_ZORDER) pswp->fl &= ~SWP_ZORDER;
  49.       if (pswp->fl & SWP_ACTIVATE) pswp->fl &= ~SWP_ACTIVATE;
  50.  
  51.       if (pswp->fl & SWP_SHOW)
  52.         WinPostMsg(plswData->hwndPopup,WM_COMMAND,MPFROMSHORT(CMD_SHOWSETTINGS),MPFROM2SHORT(CMDSRC_OTHER,FALSE));
  53.     }
  54.   }
  55.   default:
  56.     return ((PFNWP)WinQueryWindowPtr(hwnd,0))(hwnd,msg,mp1,mp2);
  57.   }
  58. }
  59.  
  60.  
  61. /* This function returns the bottom left corner coords of the usNum number
  62.   icon counting from the top left corner in the popup window */
  63. VOID IconPosFromNumber(LSWDATA *plswData,USHORT usNum,USHORT *usPosX, USHORT *usPosY)
  64. { USHORT usLine,usLines,usGapX,usGapY,usIconsPerLine;
  65.   RECTL rcl;
  66.   ULONG cxIcon,cyIcon;
  67.  
  68.   usIconsPerLine = min(plswData->usItems,MAXICONSINLINE);
  69.   usLine = usNum/MAXICONSINLINE+1;
  70.   usLines = min(ICONLINES,(plswData->usItems-1)/MAXICONSINLINE+1);
  71.   cxIcon = WinQuerySysValue(HWND_DESKTOP, SV_CXICON);
  72.   cyIcon = WinQuerySysValue(HWND_DESKTOP, SV_CYICON);
  73.   usGapX = cxIcon*ICONSPACINGX;
  74.   usGapY = cyIcon*ICONSPACINGY;
  75.  
  76.   WinQueryWindowRect(plswData->hwndPopClient,&rcl);
  77.  
  78.   *usPosX = rcl.xRight/2-
  79.     cxIcon*(usIconsPerLine-(usIconsPerLine%2==0?1:0))/2-
  80.     (usIconsPerLine-1)/2*usGapX+(usNum-(usLine-1)*MAXICONSINLINE)*(cxIcon+usGapX);
  81.  
  82.   *usPosY = rcl.yTop-2*cyIcon*SELBOXOFFSET-SELBOXLINEWIDTH-
  83.     usLine*cyIcon-(usLine-1)*usGapY-WinQuerySysValue(HWND_DESKTOP,SV_CYSCREEN)/200;//popup window border size
  84. }
  85.  
  86.  
  87. /* This function returns the number of the item in the TaskArr from the number
  88.  of its icon counting from the top left corner in the popup window */
  89. SHORT ItemNumFromIconNum(LSWDATA *plswData,SHORT iNum)
  90. { SHORT iItemNum;
  91.   USHORT usLines;
  92.  
  93.   usLines = min(ICONLINES,(plswData->usItems-1)/MAXICONSINLINE+1);
  94.  
  95.   iItemNum = plswData->iShift+iNum-
  96.     (min(MAXICONSINLINE,plswData->usItems)-1)/2-(usLines-1)/2*MAXICONSINLINE+
  97.     (plswData->Settings.bScrollItems ? plswData->usCurrItem : 0);
  98.  
  99.   AdjustItem(iItemNum,plswData->usItems);
  100.  
  101.   return iItemNum;
  102. }
  103.  
  104.  
  105. /* This function returns the number of the icon in the popup window
  106.  counting from the top left corner from the corresponding item number in the
  107.  TaskArr. */
  108. SHORT IconNumFromItemNum(LSWDATA *plswData, USHORT usNum)
  109. { USHORT usLines, usLastIconNum;
  110.   SHORT iIconNum;
  111.  
  112.   usLastIconNum = min(plswData->usItems,MAXICONSINLINE*ICONLINES)-1;
  113.  
  114.   usLines = min(ICONLINES,(plswData->usItems-1)/MAXICONSINLINE+1);
  115.  
  116.   iIconNum = usNum-plswData->iShift+
  117.     (min(MAXICONSINLINE,plswData->usItems)-1)/2+(usLines-1)/2*MAXICONSINLINE-
  118.     (plswData->Settings.bScrollItems ? plswData->usCurrItem : 0);
  119.  
  120.   while (iIconNum > usLastIconNum || iIconNum < 0)
  121.     if (iIconNum > usLastIconNum)
  122.       iIconNum -= plswData->usItems;
  123.     else if (iIconNum < 0)
  124.       iIconNum += plswData->usItems;
  125.  
  126.   return iIconNum;
  127. }
  128.  
  129.  
  130. /* This function returns the number of the item in the TaskArr
  131.  whose icon in the popup window is currently under the mouse pointer.
  132.  -1 is returned if mouse pointer does not point on any icon*/
  133. SHORT ItemNumFromPos(LSWDATA *plswData, USHORT usX, USHORT usY)
  134. { USHORT usItemNum;
  135.   USHORT usPosX,usPosY,usGapX,usGapY,usCol,usRow;
  136.   ULONG cxIcon,cyIcon;
  137.  
  138.   cxIcon = WinQuerySysValue(HWND_DESKTOP, SV_CXICON);
  139.   cyIcon = WinQuerySysValue(HWND_DESKTOP, SV_CYICON);
  140.   usGapX = cxIcon*ICONSPACINGX;
  141.   usGapY = cyIcon*ICONSPACINGY;
  142.  
  143.   IconPosFromNumber(plswData,0,&usPosX,&usPosY);
  144.   usPosY+=cyIcon; //top left corner instead of the bottom left
  145.  
  146.   usCol = (usX-usPosX)/(cxIcon+usGapX)+1;
  147.   usRow = (usPosY-usY)/(cyIcon+usGapY)+1;
  148.  
  149.   usItemNum = ItemNumFromIconNum(plswData,(usRow-1)*MAXICONSINLINE+usCol-1);
  150.   /* check if mouse points on an icon */
  151.   if ((usRow-1)*MAXICONSINLINE+usCol<=plswData->usItems &&
  152.       usX>=usPosX+(usCol-1)*(cxIcon+usGapX) && usX<=usPosX+usCol*(cxIcon+usGapX)-usGapX &&
  153.       usY<=usPosY-(usRow-1)*(cyIcon+usGapY) && usY>=usPosY-usRow*(cyIcon+usGapY)+usGapY)
  154.     return usItemNum;
  155.   else
  156.     return -1;
  157. }
  158.  
  159.  
  160.  
  161. VOID MakeHintStr(LSWDATA *plswData,USHORT usItem,UCHAR *ucStr,USHORT usStrLen)
  162. { UCHAR ucBuf[32],ucCmd[32],*pucTilde,ucHot;
  163.   USHORT k,l;
  164.  
  165.   WinLoadString(plswData->hab,plswData->hmodRes,STRID_HINTS,usStrLen,ucStr);
  166.  
  167.   for (k = CMD_HIDE; k <= CMD_CLOSE; k++)
  168.     if (MenuNeedsItem(plswData,usItem,k,ucBuf,sizeof(ucBuf),FALSE) && k!=CMD_MOVE) {
  169.       if ((pucTilde = strchr(ucBuf,'~'))!=NULL) {
  170.         memmove(pucTilde,pucTilde+1,strlen(pucTilde));
  171.         if (plswData->Settings.ucLanguage == RUSSIAN) {
  172.           if (*pucTilde >= 160 && *pucTilde <= 175)
  173.             ucHot = *pucTilde - 32;
  174.           else if (*pucTilde >= 224 && *pucTilde <= 239)
  175.             ucHot = *pucTilde - 80;
  176.           else
  177.             ucHot = *pucTilde;
  178.         } else
  179.           ucHot = toupper(*pucTilde);
  180.       }
  181.  
  182.       if (plswData->Settings.ucLanguage == RUSSIAN) {
  183.         for (l=0; l < strlen(ucBuf); l++)
  184.           if (ucBuf[l] >= 128 && ucBuf[l]<= 143)
  185.             ucBuf[l] += 32;
  186.           else if (ucBuf[l] >= 144 && ucBuf[l] <= 159)
  187.             ucBuf[l] += 80;
  188.       } else if (plswData->Settings.ucLanguage != GERMAN)
  189.         strlwr(ucBuf);
  190.  
  191.       sprintf(ucCmd,"  %c:%s",ucHot,ucBuf);
  192.       strncat(ucStr,ucCmd,usStrLen-strlen(ucStr)-1);
  193.     }
  194. }
  195.  
  196.  
  197. VOID AdjustPopupWin(LSWDATA *plswData,BOOL bInit)
  198. { USHORT cxPopup,cyPopup,cxIcon,cyIcon,usLines,usPosX,usPosY,
  199.     usTxtHgtTitle,usTxtHgtHints, usPopupBorderSize;
  200.   RECTL rcl;
  201.   HWND hwndTitle,hwndHints;
  202.   HPS hps;
  203.   POINTL aptl[TXTBOX_COUNT],ptl;
  204.   UCHAR ucBuf[2*NAMELEN];
  205.   SWP swp;
  206.  
  207.   cxIcon = WinQuerySysValue(HWND_DESKTOP, SV_CXICON);
  208.   cyIcon = WinQuerySysValue(HWND_DESKTOP, SV_CYICON);
  209.   usPopupBorderSize=WinQuerySysValue(HWND_DESKTOP,SV_CYSCREEN)/200;
  210.  
  211.   hwndTitle = WinWindowFromID(plswData->hwndPopClient,ID_TITLESTR);
  212.   hwndHints = WinWindowFromID(plswData->hwndPopClient,ID_HINTSTR);
  213.  
  214.   if (bInit) {
  215.     WinSetPresParam(plswData->hwndPopClient,PP_BACKGROUNDCOLORINDEX,
  216.                     sizeof(plswData->Settings.lBackColor),
  217.                     &plswData->Settings.lBackColor);
  218.  
  219.     WinSetPresParam(hwndTitle,PP_FONTNAMESIZE,
  220.                     strlen(plswData->Settings.ucTitleFont)+1,
  221.                     plswData->Settings.ucTitleFont);
  222.     WinSetPresParam(hwndTitle,PP_BACKGROUNDCOLOR,
  223.                     sizeof(plswData->Settings.lBackColor),
  224.                     &plswData->Settings.lBackColor);
  225.     WinSetPresParam(hwndTitle,PP_FOREGROUNDCOLOR,
  226.                     sizeof(plswData->Settings.lTitleRGBCol),
  227.                     &plswData->Settings.lTitleRGBCol);
  228.  
  229.     WinSetPresParam(hwndHints,PP_BACKGROUNDCOLOR,
  230.                     sizeof(plswData->Settings.lBackColor),
  231.                     &plswData->Settings.lBackColor);
  232.     WinSetPresParam(hwndHints,PP_FOREGROUNDCOLOR,
  233.                     sizeof(plswData->Settings.lHintsRGBCol),
  234.                     &plswData->Settings.lHintsRGBCol);
  235.  
  236.     WinSetAccelTable(plswData->hab,plswData->Settings.bStickyPopup?plswData->haccNoAlt:
  237.                      plswData->Settings.ucPopupHotKey==0?plswData->haccAlt:
  238.                      plswData->Settings.ucPopupHotKey==1?plswData->haccCtrl:plswData->haccNoAlt,
  239.                      plswData->hwndPopup);
  240.   }
  241.  
  242.   hps = WinGetPS(hwndTitle);
  243.   GpiQueryTextBox(hps,1L,"M",TXTBOX_COUNT,aptl);
  244.   WinReleasePS(hps);
  245.   usTxtHgtTitle = aptl[TXTBOX_TOPLEFT].y-aptl[TXTBOX_BOTTOMLEFT].y;
  246.  
  247.   hps = WinGetPS(hwndHints);
  248.   GpiQueryTextBox(hps,1L,"M",TXTBOX_COUNT,aptl);
  249.   WinReleasePS(hps);
  250.   usTxtHgtHints = aptl[TXTBOX_TOPLEFT].y-aptl[TXTBOX_BOTTOMLEFT].y;
  251.  
  252.   GetItemTitle(plswData->TaskArr[plswData->usCurrItem].hsw,ucBuf,sizeof(ucBuf),FALSE);
  253.   WinSetWindowText(hwndTitle,ucBuf);
  254.  
  255.   MakeHintStr(plswData,plswData->usCurrItem,ucBuf,sizeof(ucBuf));
  256.   WinSetWindowText(hwndHints,ucBuf);
  257.  
  258.   WinSendMsg(plswData->hwndPopup,WM_QUERYBORDERSIZE,MPFROMP(&ptl),0);
  259.   cxPopup = cxIcon*MAXICONSINLINE+cxIcon*(MAXICONSINLINE+2)*ICONSPACINGX+2*ptl.x+2*usPopupBorderSize;
  260.   usLines = plswData->Settings.bOldPopup ? 1 :
  261.     min(ICONLINES,(plswData->usItems-1)/MAXICONSINLINE+1);
  262.   cyPopup = usLines*cyIcon+(usLines-1)*cyIcon*ICONSPACINGY+
  263.     usTxtHgtTitle*
  264.       ((plswData->Settings.bShowHints || plswData->Settings.bOldPopup) ? 2: 3)/2+
  265.     ((plswData->Settings.bShowHints && !plswData->Settings.bOldPopup) ? usTxtHgtHints : 0)+
  266.     4*cyIcon*SELBOXOFFSET+2*SELBOXLINEWIDTH+
  267.     2*ptl.y+2*usPopupBorderSize;
  268.  
  269.   WinQueryWindowPos(plswData->hwndPopup,&swp);
  270.   plswData->usPopupWinHideX=swp.x;   plswData->usPopupWinHideY=swp.y;
  271.   WinSetWindowPos(plswData->hwndPopup, HWND_TOP,
  272.                   (WinQuerySysValue(HWND_DESKTOP, SV_CXSCREEN)-cxPopup)/2,
  273.                   (WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN)-cyPopup)/2,
  274.                   cxPopup, cyPopup,
  275.                   SWP_MOVE | SWP_SIZE |
  276.                   (bInit? (SWP_ACTIVATE | SWP_ZORDER | SWP_SHOW) : 0));
  277.  
  278.   // not sure if this is needed but sometimes the popup window hides immediately
  279.   // after showing. Maybe it doesn't get focus and WM_TIMER hides it, let's
  280.   // observe if this happens ever is we set the focus explicitly
  281.   if (bInit) WinSetFocus(HWND_DESKTOP,plswData->hwndPopClient);
  282.  
  283.   WinQueryWindowRect(plswData->hwndPopClient,&rcl);
  284.  
  285.   if (plswData->Settings.bOldPopup) {
  286.     WinSetWindowPos(hwndTitle, 0, cxIcon+cxIcon*ICONSPACINGX, 1,
  287.                     rcl.xRight-cxIcon-cxIcon*ICONSPACINGX-2, rcl.yTop-2,
  288.                     SWP_SIZE | SWP_MOVE);
  289.     WinSetWindowPos(hwndHints,0,0,0,0,0,SWP_SIZE | SWP_MOVE);
  290.   } else {
  291.     IconPosFromNumber(plswData, (usLines-1)*MAXICONSINLINE, &usPosX,&usPosY);
  292.     WinSetWindowPos(hwndTitle, 0,
  293.                     1+usPopupBorderSize,
  294.                     1+usPopupBorderSize+(plswData->Settings.bShowHints ? usTxtHgtHints : 0),
  295.                     rcl.xRight-2-2*usPopupBorderSize,
  296.                     usTxtHgtTitle*(plswData->Settings.bShowHints ? 2 : 3)/2,
  297.                     SWP_SIZE | SWP_MOVE);
  298.     WinSetWindowPos(hwndHints,0,
  299.                     plswData->Settings.bShowHints ? 1+usPopupBorderSize : 0,
  300.                     plswData->Settings.bShowHints ? 1+usPopupBorderSize : 0,
  301.                     plswData->Settings.bShowHints ? rcl.xRight-2-2*usPopupBorderSize : 0,
  302.                     plswData->Settings.bShowHints ? usTxtHgtHints : 0,
  303.                     SWP_SIZE | SWP_MOVE);
  304.   }
  305.  
  306.   WinInvalidateRect(plswData->hwndPopClient,NULL,TRUE);
  307. }
  308.  
  309.  
  310. /* popup client window procedure */
  311. static MRESULT EXPENTRY PopupWndProc(HWND hwnd,ULONG msg,MPARAM mp1,MPARAM mp2)
  312. { static ULONG cxIcon,cyIcon,cyPointer;
  313.   static HWND hwndTitle,hwndHints;
  314.   static BOOL bNowSticky=FALSE;
  315.   static USHORT usScrollCnt=0;
  316.   LSWDATA *plswData;
  317.   MRESULT mrc=0;
  318.  
  319.   if (msg!=WM_CREATE)
  320. #ifndef XWORKPLACE
  321.     plswData = WinQueryWindowPtr(hwnd,0);
  322. #else
  323.     plswData = ((PXCENTERWIDGET)WinQueryWindowPtr(hwnd,0))->pUser;
  324. #endif
  325.  
  326.   switch (msg) {
  327.   case WM_HSCROLL:
  328.   case WM_VSCROLL:
  329.     usScrollCnt=++usScrollCnt%plswData->Settings.usScrollDiv;
  330.  
  331.     if (usScrollCnt==0 && (SHORT2FROMMP(mp2)==SB_LINELEFT || SHORT2FROMMP(mp2)==SB_LINERIGHT))
  332.       WinPostMsg(hwnd,WM_COMMAND,MPFROMSHORT(SHORT2FROMMP(mp2)==SB_LINELEFT?CMD_SCROLLLEFT:CMD_SCROLLRIGHT),MPFROM2SHORT(CMDSRC_OTHER,FALSE));
  333.     break;
  334.  
  335.   case WM_BUTTON1CLICK: {
  336.     SHORT iItemNum;
  337.  
  338.     if (!plswData->Settings.bOldPopup &&
  339.         (iItemNum=ItemNumFromPos(plswData,SHORT1FROMMP(mp1),SHORT2FROMMP(mp1)))>=0) {
  340.       plswData->usCurrItem=iItemNum;
  341.       WinInvalidateRect(hwnd,NULL,FALSE);
  342.       DosSleep(50);
  343.       ProcessCommand(CMD_SWITCHFROMPM,CMDSRC_OTHER,plswData, FALSE,FALSE);
  344.       mrc=(MRESULT)TRUE;
  345.     }
  346.     break;
  347.   }
  348.  
  349.   case WM_BUTTON2CLICK:
  350.     if (!plswData->Settings.bOldPopup &&
  351.         (plswData->iMenuAtItem=
  352.          ItemNumFromPos(plswData,SHORT1FROMMP(mp1),SHORT2FROMMP(mp1)))>=0) {
  353.       ShowMenu(plswData, plswData->iMenuAtItem,FALSE,FALSE);
  354.       ShowBubble(plswData,0,0,0,-1,NULL);
  355.  
  356.       mrc=(MRESULT)TRUE;
  357.     }
  358.     break;
  359.  
  360.   case WM_CHAR: {
  361.     USHORT usFlags;
  362.     UCHAR ucScan;
  363.  
  364.     usFlags = SHORT1FROMMP(mp1); ucScan = CHAR4FROMMP(mp1);
  365.     if (plswData->bNowActive && (usFlags & KC_SCANCODE) && (usFlags & KC_KEYUP)) {
  366.  
  367.       if ((plswData->Settings.ucPopupHotKey==0 && (ucScan==SCAN_CTRL || ucScan==SCAN_RIGHTCTRL)) ||
  368.           (plswData->Settings.ucPopupHotKey==1 && (ucScan==SCAN_ALT || ucScan==SCAN_RIGHTALT)) ||
  369.           (plswData->Settings.ucPopupHotKey==2 && (ucScan==SCAN_CTRL || ucScan==SCAN_RIGHTCTRL ||
  370.                                                    ucScan==SCAN_ALT || ucScan==SCAN_RIGHTALT))) {
  371.         bNowSticky=TRUE;
  372.         WinSetAccelTable(plswData->hab,plswData->haccNoAlt, plswData->hwndPopup);
  373.         break;
  374.       }
  375.  
  376.       // left alt, ctrl or winkey release, switch to the selected window
  377.       if (ucScan==((plswData->Settings.bStickyPopup||bNowSticky)?SCAN_ENTER:
  378.                    plswData->Settings.ucPopupHotKey==0?SCAN_ALT:
  379.                    plswData->Settings.ucPopupHotKey==1?SCAN_CTRL:SCAN_WINLEFT))
  380.         ProcessCommand(CMD_SWITCHFROMPM,CMDSRC_OTHER,plswData, FALSE,FALSE);
  381.     }
  382.     break;
  383.   }
  384.  
  385.   case WM_COMMAND:
  386.     switch (SHORT1FROMMP(mp1)) {
  387.     case CMD_SCROLLLEFT:
  388.     case CMD_SCROLLRIGHT:
  389.     case CMD_SCROLLUP:
  390.     case CMD_SCROLLDOWN:
  391.     case CMD_SCROLLLEFTFROMFS:
  392.     case CMD_SCROLLRIGHTFROMFS: {
  393.       USHORT usPrevSel, usMaxIcons, usPosX, usPosY;
  394.       RECTL rcl,rcl1,rcl2;
  395.       BOOL bUpdateAll,bFullScreenInit,bForward,bNeedScroll;
  396.       UCHAR ucBuf[2*NAMELEN];
  397.       SHORT iCurrItem;
  398.  
  399.       bFullScreenInit = SHORT1FROMMP(mp1)==CMD_SCROLLLEFTFROMFS ||
  400.                         SHORT1FROMMP(mp1)==CMD_SCROLLRIGHTFROMFS;
  401.  
  402.       if (!plswData->bNowActive) {
  403.         InitTaskArr(plswData,bFullScreenInit,FALSE,TRUE);
  404.         if (plswData->usItems == 0) break;
  405.       }
  406.  
  407.       usMaxIcons = MAXICONSINLINE*ICONLINES;
  408.  
  409.       usPrevSel = plswData->usCurrItem;
  410.       bForward = SHORT1FROMMP(mp1)==CMD_SCROLLRIGHT ||
  411.                  SHORT1FROMMP(mp1)==CMD_SCROLLRIGHTFROMFS ||
  412.                  SHORT1FROMMP(mp1)==CMD_SCROLLDOWN;
  413.       bNeedScroll = FALSE;
  414.  
  415.       switch SHORT1FROMMP(mp1) {
  416.       case CMD_SCROLLLEFT:
  417.       case CMD_SCROLLLEFTFROMFS:  iCurrItem = usPrevSel - 1; break;
  418.       case CMD_SCROLLRIGHT:
  419.       case CMD_SCROLLRIGHTFROMFS: iCurrItem = usPrevSel + 1; break;
  420.       case CMD_SCROLLUP:
  421.       case CMD_SCROLLDOWN: {
  422.         SHORT iRow;
  423.         USHORT usRows,usCol,usIconNum;
  424.  
  425.         usIconNum = IconNumFromItemNum(plswData,usPrevSel);
  426.         usRows = min(ICONLINES,(plswData->usItems-1)/MAXICONSINLINE+1);
  427.         if (usRows == 1) { iCurrItem = usPrevSel; break; }
  428.         iRow = usIconNum/MAXICONSINLINE;
  429.         usCol = usIconNum-iRow*MAXICONSINLINE;
  430.  
  431.         if (plswData->usItems <= usMaxIcons) {
  432.           if (SHORT1FROMMP(mp1) == CMD_SCROLLUP)
  433.             if (iRow == 0) iRow = usRows-1; else iRow--;
  434.           else
  435.             if (iRow == usRows-1) iRow = 0; else iRow++;
  436.           iCurrItem = usPrevSel+min(iRow*MAXICONSINLINE+usCol,plswData->usItems-1)-
  437.                       usIconNum;
  438.         } else {
  439.           iCurrItem = usPrevSel +
  440.             (SHORT1FROMMP(mp1) == CMD_SCROLLUP ? -MAXICONSINLINE : MAXICONSINLINE);
  441.           bNeedScroll = (iRow==ICONLINES-1 && bForward) || (iRow==0 && !bForward);
  442.         }
  443.         break;
  444.       }
  445.       }
  446.  
  447.       AdjustItem(iCurrItem,plswData->usItems);
  448.       plswData->usCurrItem = iCurrItem;
  449.  
  450.       /* check if the number of items is larger than fits in the window and we are
  451.          at a window end so we need to scroll */
  452.       if (!plswData->Settings.bScrollItems && plswData->usItems>usMaxIcons &&
  453.           (plswData->usCurrItem ==
  454.            ItemNumFromIconNum(plswData,bForward ? usMaxIcons : -1) ||
  455.            bNeedScroll)) {
  456.         plswData->iShift += (SHORT)(bForward ? MAXICONSINLINE : -MAXICONSINLINE);
  457.         plswData->iShift -= plswData->iShift/(SHORT)plswData->usItems*plswData->usItems;
  458.         bUpdateAll = TRUE;
  459.       } else
  460.         bUpdateAll = FALSE;
  461.  
  462.       if (!plswData->bNowActive) {
  463.         // this must be just before adjusting the window, otherwise if it's after,
  464.         // the subclassed frame window proc won't let us do repositioning;
  465.         // if it's much before, the WM_TIMER might have time to hide the window
  466.         plswData->bNowActive = TRUE; bNowSticky = FALSE;
  467.  
  468.         if (bFullScreenInit)  WinSwitchToProgram(plswData->hswitch);
  469.  
  470.         AdjustPopupWin(plswData,TRUE);
  471.  
  472.       } else {
  473.         if (plswData->Settings.bScrollItems || plswData->Settings.bOldPopup ||
  474.             bUpdateAll) {
  475.           WinQueryWindowRect(hwnd,&rcl);
  476.           if (plswData->Settings.bOldPopup) {
  477.             WinSetRect(plswData->hab,&rcl,1,1,rcl.xRight-2,rcl.yTop-2);
  478.           } else {
  479.             WinQueryWindowRect(hwndHints,&rcl1);
  480.             WinSetRect(plswData->hab,&rcl,1,1+rcl1.yTop,rcl.xRight-2,rcl.yTop-2);
  481.           }
  482.         } else {
  483.           IconPosFromNumber(plswData, IconNumFromItemNum(plswData,usPrevSel),
  484.                             &usPosX,&usPosY);
  485.           WinSetRect(plswData->hab,&rcl1, usPosX-cxIcon*SELBOXOFFSET-SELBOXLINEWIDTH,
  486.                      usPosY-cyIcon*SELBOXOFFSET-SELBOXLINEWIDTH,
  487.                      usPosX+cxIcon+cxIcon*SELBOXOFFSET+SELBOXLINEWIDTH,
  488.                      usPosY+cyIcon+cyIcon*SELBOXOFFSET+SELBOXLINEWIDTH);
  489.           IconPosFromNumber(plswData, IconNumFromItemNum(plswData,plswData->usCurrItem),
  490.                             &usPosX,&usPosY);
  491.           WinSetRect(plswData->hab,&rcl2, usPosX-cxIcon*SELBOXOFFSET-SELBOXLINEWIDTH,
  492.                      usPosY-cyIcon*SELBOXOFFSET-SELBOXLINEWIDTH,
  493.                      usPosX+cxIcon+cxIcon*SELBOXOFFSET+SELBOXLINEWIDTH,
  494.                      usPosY+cyIcon+cyIcon*SELBOXOFFSET+SELBOXLINEWIDTH);
  495.           WinUnionRect(plswData->hab,&rcl,&rcl1,&rcl2);
  496.         }
  497.  
  498.         WinInvalidateRect(hwnd,&rcl,FALSE);
  499.  
  500.         GetItemTitle(plswData->TaskArr[plswData->usCurrItem].hsw,ucBuf,sizeof(ucBuf),FALSE);
  501.         WinSetWindowText(hwndTitle,ucBuf);
  502.  
  503.         MakeHintStr(plswData,plswData->usCurrItem,ucBuf,sizeof(ucBuf));
  504.         WinSetWindowText(hwndHints,ucBuf);
  505.       }
  506.       break;
  507.     }
  508.  
  509.     default:
  510.       if (plswData->bNowActive &&
  511.           (SHORT1FROMMP(mp1)==CMD_SWITCHFROMPM || SHORT1FROMMP(mp1)==CMD_CANCELPOPUP || SHORT1FROMMP(mp1)==CMD_CANCELPOPUP1)) {
  512.         UCHAR ucBuf[128];
  513.  
  514.         usScrollCnt=0;
  515.         WinQueryPresParam(hwndTitle,PP_FONTNAMESIZE,0,NULL,sizeof(ucBuf),ucBuf,QPF_NOINHERIT);
  516.         strncpy(plswData->Settings.ucTitleFont,ucBuf,sizeof(plswData->Settings.ucTitleFont));
  517.         WinQueryPresParam(hwndHints,PP_FONTNAMESIZE,0,NULL,sizeof(ucBuf),ucBuf,QPF_NOINHERIT);
  518.         strncpy(plswData->Settings.ucHintsFont,ucBuf,sizeof(plswData->Settings.ucHintsFont));
  519.         WinQueryPresParam(hwndTitle,PP_FOREGROUNDCOLOR,0,NULL,sizeof(ucBuf),ucBuf,QPF_NOINHERIT);
  520.         plswData->Settings.lTitleRGBCol = ucBuf[0]+ucBuf[1]*256+ucBuf[2]*65536;
  521.         WinQueryPresParam(hwndHints,PP_FOREGROUNDCOLOR,0,NULL,sizeof(ucBuf),ucBuf,QPF_NOINHERIT);
  522.         plswData->Settings.lHintsRGBCol = ucBuf[0]+ucBuf[1]*256+ucBuf[2]*65536;
  523.       }
  524.       ProcessCommand(SHORT1FROMMP(mp1),SHORT1FROMMP(mp2),plswData, FALSE,FALSE);
  525.     }
  526.  
  527.     break;
  528.  
  529.   case WM_CREATE: {
  530.     DosGetNamedSharedMem((PVOID*)&plswData,SHAREMEM_NAME,PAG_READ | PAG_WRITE);
  531.  
  532.     WinStartTimer(plswData->hab, hwnd, 0, BUBBLETIMERINTERVAL);
  533.  
  534.     plswData->hwndMenu = WinCreateMenu(HWND_DESKTOP, NULL);
  535.  
  536.     WinSetPresParam(plswData->hwndMenu,PP_FONTNAMESIZE,7,"8.Helv");
  537.  
  538.     hwndTitle = WinCreateWindow(hwnd,WC_STATIC,"",
  539.                                 WS_VISIBLE | SS_TEXT | DT_CENTER | DT_VCENTER,
  540.                                 0,0,0,0,hwnd,HWND_TOP,ID_TITLESTR,NULL,NULL);
  541.  
  542.     hwndHints = WinCreateWindow(hwnd,WC_STATIC,"",
  543.                                 WS_VISIBLE | SS_TEXT | DT_CENTER | DT_VCENTER,
  544.                                 0,0,0,0,hwnd,HWND_TOP,ID_HINTSTR,NULL,NULL);
  545.     WinSetPresParam(hwndHints,PP_FONTNAMESIZE,strlen(plswData->Settings.ucHintsFont)+1,plswData->Settings.ucHintsFont);
  546.  
  547. #ifndef XWORKPLACE
  548.     WinSetWindowPtr(hwnd, 0, plswData);
  549. #else
  550.     WinSetWindowPtr(hwnd, 0, plswData->pWidget);
  551. #endif
  552.     DosFreeMem(plswData);
  553.  
  554.   }
  555.   case WM_SYSVALUECHANGED:
  556.     cxIcon = WinQuerySysValue(HWND_DESKTOP, SV_CXICON);
  557.     cyIcon = WinQuerySysValue(HWND_DESKTOP, SV_CYICON);
  558.     cyPointer=WinQuerySysValue(HWND_DESKTOP, SV_CYPOINTER);
  559.     break;
  560.  
  561.   case WM_MENUEND:
  562.     WinSetWindowPos(plswData->hwndMenu,HWND_BOTTOM,0,0,0,0,SWP_ZORDER);
  563.     if (plswData->bNowActive) WinSetFocus(HWND_DESKTOP,hwnd);
  564.     break;
  565.  
  566.   case WM_ERASEBACKGROUND:
  567.     mrc = (MRESULT)FALSE;
  568.     break;
  569.  
  570.   case WM_PAINT: {
  571.     HPS hps;
  572.     RECTL rclUpdate, rclWnd, rclSelBox;
  573.     USHORT k,usPosX,usPosY,usItemNum,usBorderSize,usR,usB,usG;
  574.     POINTL ptl;
  575.  
  576.     hps = WinBeginPaint(hwnd,NULLHANDLE,&rclUpdate);
  577.     WinQueryWindowRect(hwnd, &rclWnd);
  578.  
  579.     GpiCreateLogColorTable(hps, 0, LCOLF_RGB, 0, 0, NULL);
  580.     WinFillRect(hps,&rclUpdate,plswData->Settings.lBackColor);
  581.  
  582.     usBorderSize=WinQuerySysValue(HWND_DESKTOP,SV_CYSCREEN)/200;
  583.     usR=(plswData->Settings.lBackColor&0xFF0000)>>16,
  584.     usG=(plswData->Settings.lBackColor&0xFF00)>>8,
  585.     usB=(plswData->Settings.lBackColor&0xFF);
  586.  
  587.     for (k=1;k<=usBorderSize;k++) {
  588.       ULONG ulColor;
  589.  
  590.       ulColor=(230-usB)/usBorderSize*(/*usBorderSize-*/k)+usB+
  591.         ((230-usG)/usBorderSize*(/*usBorderSize-*/k)+usG)*256+
  592.         ((230-usR)/usBorderSize*(/*usBorderSize-*/k)+usR)*65536;
  593.       WinDrawBorder(hps,&rclWnd,1,1,ulColor,ulColor,0);
  594.       rclWnd.xLeft+=1; rclWnd.xRight-=1; rclWnd.yBottom+=1; rclWnd.yTop-=1;
  595.     }
  596.  
  597.     if (plswData->Settings.bOldPopup) {
  598.       WinDrawPointer(hps,rclWnd.xLeft+cxIcon*ICONSPACINGX,
  599.                      (rclWnd.yTop+rclWnd.yBottom-cyIcon)/2,
  600.                      plswData->TaskArr[plswData->usCurrItem].hIcon,DP_NORMAL);
  601.     } else {
  602.       /* Draw icons */
  603.       for (k = 0; k < min(MAXICONSINLINE*ICONLINES,plswData->usItems); k++) {
  604.  
  605.         IconPosFromNumber(plswData,k,&usPosX,&usPosY);
  606.         usItemNum = ItemNumFromIconNum(plswData,k);
  607.  
  608.         WinDrawPointer(hps, usPosX, usPosY, plswData->TaskArr[usItemNum].hIcon,DP_NORMAL|
  609.                        (plswData->TaskArr[usItemNum].fl&(SWP_HIDE|SWP_MINIMIZE))?DP_HALFTONED:0);
  610.  
  611. /* Draw selection box */
  612.         if (usItemNum == plswData->usCurrItem) {
  613.           WinSetRect(plswData->hab,&rclSelBox,
  614.             usPosX-cxIcon*SELBOXOFFSET-1, usPosY-cyIcon*SELBOXOFFSET-1,
  615.             usPosX+cxIcon*SELBOXOFFSET+cxIcon+1,usPosY+cyIcon*SELBOXOFFSET+cyIcon+1);
  616.           WinDrawBorder(hps,&rclSelBox,SELBOXLINEWIDTH,SELBOXLINEWIDTH,
  617.                         plswData->Settings.lSunkenFrameColor,
  618.                         plswData->Settings.lRaisedFrameColor,DB_DEPRESSED);
  619.         }
  620.       }
  621.  
  622.     }
  623.     WinEndPaint(hps);
  624.     break;
  625.   }
  626.  
  627.   case LSWM_WNDSTATECHANGED:
  628.     if (SHORT2FROMMP(mp1) & (SWP_RESTORE|SWP_MAXIMIZE|SWP_SHOW))
  629.       MinimizeHideAll(plswData, TRUE, HWNDFROMMP(mp2));
  630.  
  631.   case LSWM_WNDICONCHANGED: {
  632.     USHORT k,usPosX,usPosY;
  633.     RECTL rcl;
  634.     UCHAR ucBuf[150];
  635.     BOOL bNeedUpdate;
  636.  
  637.     if (!plswData->bNowActive) break;
  638.  
  639.     for (k=0;k<plswData->usItems;k++)
  640.       if (plswData->TaskArr[k].hwnd==HWNDFROMMP(mp2)) {
  641.         if (msg==LSWM_WNDICONCHANGED) {
  642.           plswData->TaskArr[k].hIcon=LONGFROMMP(mp1);
  643.           WinSendMsg(HWNDFROMMP(mp2),WM_NULL,0,0); // to make sure the icon handle has become valid
  644.           bNeedUpdate = TRUE;
  645.         } else {
  646.           bNeedUpdate = UpdateWinFlags(&plswData->TaskArr[k].fl, SHORT2FROMMP(mp1));
  647.  
  648.           if (plswData->TaskArr[MAXITEMS-1].hwnd == plswData->TaskArr[k].hwnd)
  649.             plswData->TaskArr[MAXITEMS-1].fl = plswData->TaskArr[k].fl;
  650.  
  651.           if (k==plswData->usCurrItem && bNeedUpdate) {
  652.             MakeHintStr(plswData,k,ucBuf,sizeof(ucBuf)); //change hints to reflect the changed task state
  653.             WinSetWindowText(hwndHints,ucBuf);
  654.           }
  655.         }
  656.  
  657.         if (bNeedUpdate) {
  658.           IconPosFromNumber(plswData, IconNumFromItemNum(plswData,k), &usPosX,&usPosY);
  659.           WinSetRect(plswData->hab,&rcl,usPosX,usPosY,usPosX+cxIcon,usPosY+cyIcon);
  660.           WinInvalidateRect(hwnd,&rcl,FALSE);
  661.         }
  662.  
  663.         break;
  664.       }
  665.     break;
  666.   }
  667.   case LSWM_SWITCHLISTCHANGED: {
  668.     USHORT k;
  669.     UCHAR ucBuf[NAMELEN];
  670.  
  671.     if (!plswData->bNowActive) break;
  672.  
  673.     for (k=0;k<plswData->usItems;k++) {
  674.       if (plswData->TaskArr[k].hsw!=LONGFROMMP(mp2)) continue;
  675.  
  676.       if (LONGFROMMP(mp1)==2) ShowBubble(plswData,k,0,0,11,NULL); //update bubble
  677.  
  678.       if (LONGFROMMP(mp1)==2 && k==plswData->usCurrItem) {
  679.         GetItemTitle(plswData->TaskArr[k].hsw,ucBuf,sizeof(ucBuf),FALSE);
  680.         WinSetWindowText(hwndTitle,ucBuf);
  681.       }
  682.       if ((LONGFROMMP(mp1)==2 &&
  683.            (GetItemTitle(plswData->TaskArr[k].hsw,ucBuf,sizeof(ucBuf),FALSE),
  684.             IsInSkipList(&plswData->Settings,ucBuf,FALSE))) ||
  685.           LONGFROMMP(mp1)==3) {
  686.         memmove(&plswData->TaskArr[k],&plswData->TaskArr[k+1],sizeof(SWITEM)*(plswData->usItems-k-1));
  687.         plswData->usItems--;
  688.         if (plswData->usItems==0)
  689.           ProcessCommand(CMD_CANCELPOPUP1,CMDSRC_OTHER,plswData, FALSE,FALSE);//cancel popup and don't return to original session
  690.         else if (WinQueryFocus(HWND_DESKTOP)==plswData->hwndPopClient && !plswData->Settings.bOldPopup)
  691.           AdjustPopupWin(plswData,FALSE);
  692.  
  693.         break;
  694.       }
  695.     }
  696.     break;
  697.  
  698.   }
  699.  
  700.   case WM_PRESPARAMCHANGED: {
  701.     LONG lParam, lValue;
  702.     UCHAR ucBuf[64];
  703.     lParam = LONGFROMMP(mp1);
  704.  
  705.     if (!(lParam==PP_FOREGROUNDCOLOR || lParam==PP_BACKGROUNDCOLOR) ||
  706.         (LONG)WinQueryPresParam(hwnd,lParam,0,NULL,sizeof(ucBuf),ucBuf,QPF_NOINHERIT)==0)
  707.       break;
  708.  
  709.     lValue = ucBuf[0]+ucBuf[1]*256+ucBuf[2]*65536;
  710.  
  711.     switch(lParam) {
  712.     case PP_BACKGROUNDCOLOR:
  713.       plswData->Settings.lBackColor = plswData->Settings.lTitleRGBCol =
  714.         plswData->Settings.lHintsRGBCol = lValue;
  715.       WinSetPresParam(hwndTitle,PP_BACKGROUNDCOLOR,4,&lValue);
  716.       WinSetPresParam(hwndHints,PP_BACKGROUNDCOLOR,4,&lValue);
  717.       WinInvalidateRect(hwnd,NULL,TRUE);
  718.       break;
  719.     }
  720.     break;
  721.   }
  722.  
  723.   case WM_TIMER: {
  724.     static SHORT iMouseIsAtItem;
  725.     POINTL ptl;
  726.     SWP swp1,swp2;
  727.     HWND hwndFocus;
  728.  
  729.     if (plswData->bNowActive) {
  730.       if (WinQueryFocus(HWND_DESKTOP) == plswData->hwndPopClient &&
  731.           WinQueryWindow(HWND_DESKTOP,QW_TOP) != plswData->hwndPopup)
  732.         WinSetWindowPos(plswData->hwndPopup,WinIsWindowVisible(plswData->hwndBubble)?
  733.                         plswData->hwndBubble:HWND_TOP,0,0,0,0,SWP_ZORDER);
  734.  
  735.       hwndFocus = WinQueryFocus(HWND_DESKTOP);
  736.       if (hwndFocus != plswData->hwndPopClient && hwndFocus != plswData->hwndMenu &&
  737.           WinQueryWindow(hwndFocus,QW_OWNER) != plswData->hwndMenu)
  738.         ProcessCommand(CMD_CANCELPOPUP1,CMDSRC_OTHER,plswData, FALSE,FALSE);//cancel popup and don't return to original session
  739.       else if (!(plswData->Settings.bStickyPopup||bNowSticky) &&
  740.                (WinGetPhysKeyState(HWND_DESKTOP,(plswData->Settings.ucPopupHotKey==0?SCAN_ALT:
  741.                                              plswData->Settings.ucPopupHotKey==1?SCAN_CTRL:
  742.                                              SCAN_WINLEFT)) & 0x8000)==0)
  743.         ProcessCommand(CMD_SWITCHFROMPM,CMDSRC_OTHER,plswData, FALSE,FALSE);
  744.     }
  745.  
  746. /* check if mouse pointer is inside the popup window and above an icon */
  747.     if (plswData->bNowActive && (WinQueryPointerPos(HWND_DESKTOP,&ptl),
  748.         WinQueryWindowPos(plswData->hwndPopup,&swp1),WinQueryWindowPos(hwnd,&swp2),
  749.         (ptl.x>=swp1.x+swp2.x && ptl.y>=swp1.y+swp2.y &&
  750.         ptl.x<=swp1.x+swp2.x+swp2.cx && ptl.y<=swp1.y+swp2.y+swp2.cy)) &&
  751.         (iMouseIsAtItem=
  752.         ItemNumFromPos(plswData,ptl.x-swp1.x-swp2.x,ptl.y-swp1.y-swp2.y))>=0 &&
  753.         !WinIsWindowVisible(plswData->hwndMenu))
  754.  
  755.       ShowBubble(plswData,iMouseIsAtItem,ptl.x,ptl.y-cyPointer-1,1,NULL);
  756.     else
  757.       ShowBubble(plswData,0,0,0,-1,NULL);
  758.  
  759.     break;
  760.   }
  761.   default:
  762.     mrc = WinDefWindowProc(hwnd, msg, mp1, mp2);
  763.   }
  764.   return mrc;
  765. }
  766.  
  767. LONG SwitcherInit(HAB hab, HMQ hmq, UCHAR *ucErrMsg, USHORT usMsgLen, PVOID *ppData, USHORT usFunc)
  768. { ULONG flFrameFlags,ulHookVer;
  769.   LONG rc,rc1 = 0;
  770.   LSWDATA *plswData;
  771.   UCHAR ucFName[CCHMAXPATH], ucResLang,ucFound=0,ucLangStr[32];
  772.   SWCNTRL swctl;
  773.  
  774. // usFunc is 0 for app initialization, 1 and for widget phases 1 and 2 initialization
  775.  
  776.   if (usFunc != 1)
  777.     DosSetPriority(PRTYS_THREAD,PRTYC_TIMECRITICAL,+31,0);
  778.  
  779.   if (usFunc != 2) {
  780. //need to loop so that search handle is closed
  781.     while (FindResDll(ucFName, sizeof(ucFName), &ucResLang, ucLangStr, sizeof(ucLangStr)))
  782.       if (ucResLang!=0) ucFound=1;
  783.  
  784.     if (!ucFound) {
  785.       strncpy(ucErrMsg,"Could not find resource DLL or resource DLL invalid error",usMsgLen);
  786.       return 1;
  787.     }
  788.  
  789.     ulHookVer = lswHookGetVersion();
  790.     if (LOUCHAR(LOUSHORT(ulHookVer)) < LASTHOOKVERMAJOROK ||
  791.                 HIUCHAR(LOUSHORT(ulHookVer)) < LASTHOOKVERMINOROK ||
  792.                 LOUCHAR(HIUSHORT(ulHookVer)) < LASTHOOKREVISIONOK) {
  793.       strncpy(ucErrMsg,"Wrong hook DLL version error",usMsgLen);
  794.       return 1;
  795.     }
  796.  
  797.     if (!WinRegisterClass(hab,LSWPOPUPCLASS,PopupWndProc,CS_SAVEBITS|CS_SYNCPAINT,sizeof(PLSWDATA))) {
  798.       strncpy(ucErrMsg,"WinRegisterClass(lswPopupClass) error",usMsgLen);
  799.       return WinGetLastError(hab);
  800.     }
  801.  
  802.     if ((rc = DosAllocSharedMem((VOID*)&plswData,SHAREMEM_NAME,sizeof(LSWDATA),PAG_COMMIT | PAG_READ | PAG_WRITE))!=0) {
  803.       strncpy(ucErrMsg,"DosAllocSharedMem error",usMsgLen);
  804.       return rc;
  805.     }
  806.  
  807.     memset(plswData,0,sizeof(LSWDATA));
  808.     *ppData = (PVOID)plswData;
  809.  
  810. #ifdef XWORKPLACE
  811.     plswData->bWidget = TRUE;
  812. #endif
  813.  
  814.     plswData->hab = hab;
  815.     plswData->hmq = hmq;
  816.  
  817.     GetIniFileName(ucFName,sizeof(ucFName));
  818.     if (LoadSettings(hab,ucFName,&plswData->Settings)!=0) rc1=LSWERRCANTLOADSETTINGS;
  819.     if (rc1==0 && !CheckSettings(&plswData->Settings)) rc1=LSWERROLDSETTINGS;
  820.  
  821.     if (rc1 < 0)
  822.       InitSettings(&plswData->Settings);
  823.     else if (plswData->Settings.sTskBarCX>WinQuerySysValue(HWND_DESKTOP,SV_CXSCREEN)+2) {
  824.       plswData->Settings.sTskBarX = -TSKBARFRAMEWIDTH;
  825.       if (plswData->Settings.bTaskBarTopScr)
  826.         plswData->Settings.sTskBarY = WinQuerySysValue(HWND_DESKTOP,SV_CYSCREEN)-plswData->Settings.sTskBarCY+TSKBARFRAMEWIDTH;
  827.       else
  828.         plswData->Settings.sTskBarY = -TSKBARFRAMEWIDTH;
  829.       plswData->Settings.sTskBarCX = WinQuerySysValue(HWND_DESKTOP,SV_CXSCREEN)+2*TSKBARFRAMEWIDTH;
  830.       plswData->Settings.sTskBarCY = WinQuerySysValue(HWND_DESKTOP,SV_CYICON)/2+4+2*BUTTONBORDERWIDTH+2+2*TSKBARFRAMEWIDTH;
  831.     }
  832.   }
  833.  
  834.   if (usFunc != 1) {
  835. #ifdef XWORKPLACE
  836.     if (usFunc==2) plswData=(PLSWDATA)(*ppData);
  837. #endif
  838.  
  839.     if ((plswData->hmodRes=LoadResource(plswData->Settings.ucLanguage, plswData, TRUE))==0) {
  840.       strncpy(ucErrMsg,"Could not load resources ",usMsgLen);
  841.       return 1;
  842.     }
  843.  
  844.     if ((rc = DosCreateEventSem(SEMRUNNINGNAME,&plswData->hevRunning,0,0)) ||
  845.         (rc = DosCreateEventSem(SEMCTRLTABNAME,&plswData->hevCtrlTab,0,
  846.                                 (plswData->Settings.ucPopupHotKey==1))) ||
  847.         (rc = DosCreateEventSem(SEMWINTABNAME,&plswData->hevWinTab,0,
  848.                                 (plswData->Settings.ucPopupHotKey==2)))) {
  849.       strncpy(ucErrMsg,"DosCreateEventSem",usMsgLen);
  850.       return rc;
  851.     }
  852.  
  853.     flFrameFlags = FCF_BORDER;
  854. #ifndef XWORKPLACE
  855.     flFrameFlags |= FCF_TASKLIST | FCF_ICON;
  856. #endif
  857.     plswData->hwndPopup = WinCreateStdWindow(HWND_DESKTOP,0,&flFrameFlags,
  858.                           LSWPOPUPCLASS,"",
  859.                           0,0,ID_POPUPWIN,&plswData->hwndPopClient);
  860.  
  861.     if (plswData->hwndPopup==NULLHANDLE) {
  862.       strncpy(ucErrMsg,"WinCreateStdWin(lswPopupWin)",usMsgLen);
  863.       return WinGetLastError(hab);
  864.     }
  865.  
  866.     plswData->usPopupWinHideX=POPUPWINHIDEPOSX;
  867.     plswData->usPopupWinHideY=POPUPWINHIDEPOSY;
  868.     WinSetWindowPos(plswData->hwndPopup,HWND_BOTTOM, plswData->usPopupWinHideX, plswData->usPopupWinHideY,
  869.                     0, 0, SWP_MOVE | SWP_SIZE | SWP_SHOW | SWP_DEACTIVATE | SWP_ZORDER);
  870.  
  871.     WinSetWindowPtr(plswData->hwndPopup, 0, (VOID *)WinSubclassWindow(plswData->hwndPopup, FrameWndProc));
  872.  
  873.     plswData->hwndBubble = WinCreateWindow(HWND_DESKTOP,WC_STATIC,"",
  874.                                            SS_TEXT | DT_CENTER | DT_VCENTER,
  875.                                            0,0,0,0,0,HWND_BOTTOM,ID_BUBBLE,NULL,NULL);
  876.     WinSetPresParam(plswData->hwndBubble,PP_FONTNAMESIZE,7,"8.Helv");
  877.     WinSetPresParam(plswData->hwndBubble,PP_BACKGROUNDCOLOR,
  878.                     sizeof(plswData->Settings.lBubbleRGBCol),
  879.                     &plswData->Settings.lBubbleRGBCol);
  880.     WinSetPresParam(plswData->hwndBubble,PP_FOREGROUNDCOLOR,
  881.                     sizeof(plswData->Settings.lBubbleTextRGBCol),
  882.                     &plswData->Settings.lBubbleTextRGBCol);
  883.     WinCreateWindow(plswData->hwndBubble,WC_STATIC,"",SS_HALFTONEFRAME,
  884.                     0,0,0,0,0,HWND_TOP,ID_BUBBLEFRAME,NULL,NULL);
  885.  
  886.  
  887.     if ((plswData->itidFSDispat = _beginthread(FSMonDispat,NULL,0x4000,plswData))<0) {
  888.       strncpy(ucErrMsg,"_beginthread",usMsgLen);
  889.       return plswData->itidFSDispat;
  890.     }
  891.  
  892.     if ((rc = lswHookInit(plswData)) < 0) {
  893.       strncpy(ucErrMsg,"lswHookInit",usMsgLen);
  894.       return (-rc);
  895.     }
  896.  
  897. #ifndef XWORKPLACE
  898.     plswData->hswitch = WinQuerySwitchHandle(plswData->hwndPopup, 0);
  899.     WinQuerySwitchEntry(plswData->hswitch, &swctl);
  900.     swctl.uchVisibility = plswData->Settings.bShowInWinList ? SWL_VISIBLE : SWL_INVISIBLE;
  901.     WinChangeSwitchEntry(plswData->hswitch, &swctl);
  902.  
  903.     if (plswData->Settings.bTaskBarOn)
  904.       if ((rc = InitTaskBar(plswData,ucErrMsg,usMsgLen)) != 0)
  905.         return rc;
  906.  
  907.     if ((rc = DosExitList(EXLST_ADD, (PFNEXITLIST)lswExitProc)) !=0 ) {
  908.       strncpy(ucErrMsg,"DosExitList",usMsgLen);
  909.       return rc;
  910.     }
  911. #else
  912.     if (plswData->pWidget->pGlobals!=NULL) plswData->hswitch = WinQuerySwitchHandle(plswData->pWidget->pGlobals->hwndFrame, 0);
  913. #endif
  914.   }
  915.  
  916.   return rc1;
  917. }
  918.  
  919. VOID SwitcherTerm(LSWDATA *plswData,USHORT usFunc)
  920. {
  921. // usFunc is 0 for app termination, 1 and 2 for widget phases 1 and 2 termination
  922.   if (usFunc!=2) {
  923.     lswHookTerm(plswData);
  924.  
  925.     DosPostEventSem(plswData->hevRunning);
  926.     DosSleep(500);
  927.  
  928. #ifndef XWORKPLACE
  929.     DoneTaskBar(plswData);
  930. #endif
  931.  
  932.     DosCloseEventSem(plswData->hevShift);
  933.     DosCloseEventSem(plswData->hevPopup);
  934.     DosCloseEventSem(plswData->hevRunning);
  935.     DosCloseEventSem(plswData->hevCtrlTab);
  936.     DosCloseEventSem(plswData->hevWinTab);
  937.  
  938.     WinDestroyWindow(plswData->hwndPopup);
  939.     if (plswData->bSettingsDlgOn) WinDestroyWindow(plswData->hwndParamDlg);
  940.  
  941.     DosFreeModule(plswData->hmodRes);
  942.   }
  943.  
  944. #ifndef XWORKPLACE
  945.   WinDestroyMsgQueue(plswData->hmq);
  946.   WinTerminate(plswData->hab);
  947. #endif
  948.  
  949.   if (usFunc!=1)
  950.     DosFreeMem(plswData);
  951. }
  952.  
  953.  
  954. VOID APIENTRY lswExitProc()
  955. { LSWDATA *plswData;
  956.  
  957.   DosGetNamedSharedMem((PVOID*)&plswData,SHAREMEM_NAME,PAG_READ | PAG_WRITE);
  958.  
  959.   if (plswData!=NULL) SwitcherTerm(plswData,0);
  960.  
  961.   DosExitList(EXLST_EXIT, (PFNEXITLIST)lswExitProc);
  962. }
  963.  
  964.