home *** CD-ROM | disk | FTP | other *** search
/ Chip 2004 June / CHIP_CD_2004-06.iso / software / miranda_hit / files / mirinstsetup.exe / Miranda Installer 0.0.1.2 / PackageSelector.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2004-04-20  |  33.0 KB  |  966 lines

  1. /*
  2.     Miranda Installer - Installs nightlies and Miranda addons.
  3.     Copyright (C) 2002-2003 Goblineye Entertainment
  4.  
  5.     Authors: Saar (Tornado) and Kai (kai_b)
  6.  
  7.     This program is free software; you can redistribute it and/or modify
  8.     it under the terms of the GNU General Public License as published by
  9.     the Free Software Foundation; either version 2 of the License, or
  10.     (at your option) any later version.
  11.  
  12.     This program is distributed in the hope that it will be useful,
  13.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.     GNU General Public License for more details.
  16.  
  17.     You should have received a copy of the GNU General Public License
  18.     along with this program; if not, write to the Free Software
  19.     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  20. */
  21.  
  22. #include "PackageSelector.h"
  23. #pragma hdrstop
  24.  
  25.  
  26.  
  27. // fills with the current RECT of the package
  28. static void PS_GetPackageRect(HWND hWnd,const PS_CONTROLINFO *pCtrlInfo,int iPosY,const PS_PACKAGELIST *pPackage,RECT *pRect)
  29. {
  30.     RECT rcWnd;
  31.     GetClientRect(hWnd,&rcWnd);
  32.  
  33.     pRect->left = 1;
  34.     pRect->top = iPosY + (pPackage->TitleSize.cy >> 1) - ((pCtrlInfo->wRowHeight-(PS_PACKAGESPACE>>1)) >> 1);
  35.     pRect->right = rcWnd.right - 1;
  36.     pRect->bottom = pRect->top + pCtrlInfo->wRowHeight + ((pPackage->dwFlags & 1) ? (pCtrlInfo->wFileHeight*pPackage->wTotalFiles) : (0));
  37. }
  38.  
  39.  
  40.  
  41. void PS_DrawControl(HWND hWnd,HDC hDC,RECT *pUpdateRect)
  42. {
  43.     // pUpdateRect must not be NULL
  44.     // it points to the invalidation RECT
  45.     // should be whole client area of control if you want to draw all of it
  46.     PS_CONTROLINFO *pCtrlInfo = (PS_CONTROLINFO*)GetWindowLong(hWnd,0);
  47.  
  48.     HRGN hClippingRgn = CreateRectRgnIndirect(pUpdateRect);
  49.     // there's no flickering when drawing even when using a small invalidation rect
  50.     // because windows clips everything to the paint rect!! GDI is nice :)
  51.  
  52.     // drawing is done package-by-package
  53.     // the painting RECT is checked against the RECT of the package
  54.     // it is, of course, to avoid flickering and un-necessary drawing
  55.     HFONT hOldFont = (HFONT)SelectObject(hDC,pCtrlInfo->hTitleFont); // select our favourite font
  56. //    BOOL bIsEnabled = IsWindowEnabled(hWnd); // used for colors (hate BOOL, but conversion could be dangerous)
  57.     RECT rcWnd;
  58.     GetClientRect(hWnd,&rcWnd);
  59.  
  60.     // the background region is created from the update RECT, that way
  61.     // less drawing will be needed
  62.     // if at all :)
  63.     // this is drawn right at the end
  64.     // it only fills the missing "holes"
  65.     // for now, the "hole" can only be at the bottom of the control
  66.     // the background is erased for each and every package individually later on
  67.     HRGN hBKRgn = CreateRectRgnIndirect(pUpdateRect); // region will be used to fill background when we're done
  68.  
  69.     // hmm
  70.     // we have to remove the border from the background region
  71.     // but instead of removing it (too much code), we'll AND hBKRgn with the drawing area of the control
  72.     InflateRect(&rcWnd,-1,-1); // remove border (just for a sec)
  73.     HRGN hTempRgn = CreateRectRgnIndirect(&rcWnd);
  74.     InflateRect(&rcWnd,1,1); // back
  75.     CombineRgn(hBKRgn,hBKRgn,hTempRgn,RGN_AND); // only touch drawing area (btw - params are fine according to docs)
  76.     DeleteObject(hTempRgn);
  77.     
  78.  
  79.     PS_PACKAGELIST *pCurPackage = pCtrlInfo->pPackageList;
  80.  
  81.     int iPosY = PS_PACKAGEPOS_Y - pCtrlInfo->wScrollPos;
  82.     SetBkMode(hDC,TRANSPARENT);
  83.     while (pCurPackage != NULL)
  84.     {
  85.         RECT rcItem;
  86.         PS_GetPackageRect(hWnd,pCtrlInfo,iPosY,pCurPackage,&rcItem);
  87.  
  88.         // check if the package rect (that include files) is in the update region
  89.         if (!RectInRegion(hClippingRgn,&rcItem))
  90.         {
  91.             // nope, continue
  92.             iPosY += pCtrlInfo->wRowHeight + ((pCurPackage->dwFlags & 1) ? (pCtrlInfo->wFileHeight*pCurPackage->wTotalFiles) : (0));
  93.             pCurPackage = pCurPackage->next;
  94.             continue;
  95.         }
  96.  
  97.         // draw background
  98.         // if selected - selection background
  99.         // if not - just the "white" background
  100.         FillRect(hDC,&rcItem,((pCurPackage->packageInfo.fSelected) ? (pCtrlInfo->hBKBrush) : (GetSysColorBrush(COLOR_WINDOW))));
  101.  
  102.         // take off
  103.         HRGN hItemRgn = CreateRectRgnIndirect(&rcItem);
  104.         // XOR will work because hItemRgn is ALWAYS part of hBKRgn
  105.         // otherwise we wouldn't be here (if (!RectInRegion() would have kicked us to the next package)
  106.         CombineRgn(hBKRgn,hItemRgn,hBKRgn,RGN_XOR); // take out hItemRgn (according to docs, this is OK)
  107.         DeleteObject(hItemRgn);
  108.  
  109.         SetTextColor(hDC,/*((bIsEnabled) ? (*/GetSysColor(COLOR_WINDOWTEXT)/*) : (RGB(120,120,120)))*/); // window text
  110.  
  111.         // check if hot tracked
  112.         if (pCurPackage->dwFlags & 2)
  113.         {
  114.             HPEN hVOPen = (HPEN)SelectObject(hDC,pCtrlInfo->hTitleUL);
  115.             MoveToEx(hDC,PS_PACKAGEPOS_X,iPosY + pCurPackage->TitleSize.cy,NULL);
  116.             LineTo(hDC,PS_PACKAGEPOS_X + pCurPackage->TitleSize.cx,iPosY + pCurPackage->TitleSize.cy);
  117.             SelectObject(hDC,hVOPen);
  118.         }
  119.  
  120.         // the actual text
  121.         TextOut(hDC,PS_PACKAGEPOS_X,iPosY,pCurPackage->lpDisplayText,lstrlen(pCurPackage->lpDisplayText));
  122.         
  123.         // remember the old pen
  124.         HPEN hOldPen = (HPEN)SelectObject(hDC,pCtrlInfo->hTitleLine);
  125.  
  126.         // package line
  127.         MoveToEx(hDC,PS_PACKAGEPOS_X + pCurPackage->TitleSize.cx + 5,iPosY + (pCurPackage->TitleSize.cy >> 1),NULL);
  128.         LineTo(hDC,rcWnd.right - 5,iPosY + (pCurPackage->TitleSize.cy >> 1));
  129.  
  130.         SetTextColor(hDC,RGB(90,90,90)); // I like it... bah :)
  131.  
  132.         char szPackageDesc[128], szPackageSize[32];
  133.         // format size first
  134.         Format_DisplaySize(szPackageSize,pCurPackage->dwTotalSize);
  135.         wsprintf(szPackageDesc,Translate("%d file/s (%s)"),pCurPackage->wTotalFiles,szPackageSize);
  136.  
  137.         SIZE tempSize; // used temp for drawing of description and possibly PACKAGESELECTOR_OPTIONALTEXT
  138.  
  139.         GetTextExtentPoint32(hDC,szPackageDesc,lstrlen(szPackageDesc),&tempSize);
  140.  
  141.         HFONT hPrevFont = (HFONT)SelectObject(hDC,pCtrlInfo->hPackageInfoFont);
  142.         if (rcWnd.right-tempSize.cx-5 > (rcWnd.right * 0.4)) // small enough to be drawn
  143.         {
  144.             // draw description
  145.             TextOut(hDC,rcWnd.right-tempSize.cx-5,iPosY+(pCurPackage->TitleSize.cy >> 1)+1,szPackageDesc,lstrlen(szPackageDesc));
  146.         }
  147.         // now draw optional (maybe)
  148.         if (pCurPackage->packageInfo.fOptional)
  149.         {
  150.             GetTextExtentPoint32(hDC,PS_OPTIONALTEXT,lstrlen(PS_OPTIONALTEXT),&tempSize);
  151.             if (rcWnd.right-tempSize.cx-5 > (rcWnd.right * 0.4)) // small enough to be drawn
  152.             {
  153.                 TextOut(hDC,rcWnd.right-tempSize.cx-5,iPosY-tempSize.cy+(pCurPackage->TitleSize.cy >> 1),PS_OPTIONALTEXT,lstrlen(PS_OPTIONALTEXT));
  154.             }
  155.         }
  156.  
  157.         SelectObject(hDC,hPrevFont);
  158.         SelectObject(hDC,hOldPen);
  159.  
  160.  
  161.         // ok now let's draw icon for package and such
  162.         hOldPen = (HPEN)SelectObject(hDC,pCtrlInfo->hCBPen);
  163.         HBRUSH hOldBrush = (HBRUSH)SelectObject(hDC,(HBRUSH)GetStockObject(NULL_BRUSH));
  164.  
  165.         RECT rcIcon;
  166.         rcIcon.top = iPosY + 1;
  167.         rcIcon.bottom = rcIcon.top + pCurPackage->TitleSize.cy - 1;
  168.         rcIcon.left = (PS_PACKAGEPOS_X - (rcIcon.bottom-rcIcon.top)) >> 1;
  169.         rcIcon.right = (rcIcon.bottom - rcIcon.top) + rcIcon.left;
  170.  
  171.         RoundRect(hDC,rcIcon.left,rcIcon.top,rcIcon.right,rcIcon.bottom,2,2);
  172.  
  173.         if (pCurPackage->packageInfo.fSelected)
  174.         {
  175.             InflateRect(&rcIcon,-1,-1); // make it smaller
  176.             Ellipse(hDC,rcIcon.left+1,rcIcon.top+1,rcIcon.right-1,rcIcon.bottom-1);
  177.         }
  178.         SelectObject(hDC,hOldPen);
  179.         SelectObject(hDC,hOldBrush);
  180.         // done icon
  181.  
  182.         // clean up...
  183.         if (pCurPackage->dwFlags & 1) // expanded
  184.         {
  185.             // before we start, draw the entire line we're going to need for the files
  186.             // usign rcIcon for this
  187.             int iMidIcon = (int)(((rcIcon.right-rcIcon.left)>>1) + rcIcon.left);
  188.  
  189.             // remember there's at least one file in each package!
  190.             // this is the line from the icon to the middle of the last file
  191.             InflateRect(&rcIcon,1,1); // inflate it again
  192.             hOldPen = (HPEN)SelectObject(hDC,pCtrlInfo->hTitleLine);
  193.             MoveToEx(hDC,iMidIcon,rcIcon.bottom,NULL);
  194.             LineTo(hDC,iMidIcon,iPosY+(pCtrlInfo->wFileHeight * pCurPackage->wTotalFiles)+(pCtrlInfo->wFileHeight>>1));
  195.  
  196.             // ok now for the actual files
  197.             PS_FILELIST *pCurFile = pCurPackage->pFileList;
  198.             int iFilePos = iPosY + (int)((float)pCtrlInfo->wFileHeight*1.5f); // position at which we draw (first fileheight, then another half to get at position)
  199.             while (pCurFile != NULL)
  200.             {
  201.                 iPosY += pCtrlInfo->wFileHeight; // the actual size of the font
  202.  
  203.                 // draw the filename
  204.                 TextOut(hDC,PS_FILEPOS_X,iPosY,pCurFile->lpDisplayText,lstrlen(pCurFile->lpDisplayText));
  205.  
  206.                 // now let's also do the other thingy, with the pen... :)
  207.                 MoveToEx(hDC,iMidIcon,iFilePos,NULL);
  208.                 LineTo(hDC,PS_FILEPOS_X,iFilePos);
  209.  
  210.                 iFilePos += pCtrlInfo->wFileHeight;
  211.                 pCurFile = pCurFile->next;
  212.             }
  213.             SelectObject(hDC,hOldPen);
  214.         }
  215.  
  216.         // row height includes space
  217.         iPosY += pCtrlInfo->wRowHeight;
  218.         pCurPackage = pCurPackage->next;
  219.     }
  220.  
  221.     // fill the rest of the background rgn
  222.     FillRgn(hDC,hBKRgn,/*((bIsEnabled) ? (*/GetSysColorBrush(COLOR_WINDOW)/*) : ((HBRUSH)GetStockObject(LTGRAY_BRUSH)))*/);
  223.  
  224.     // delete clipping region
  225.     DeleteObject(hClippingRgn);
  226.     DeleteObject(hBKRgn);
  227.  
  228.     // should be at end
  229.     FrameRect(hDC,&rcWnd,(HBRUSH)GetStockObject(GRAY_BRUSH));
  230.     SelectObject(hDC,hOldFont);
  231. }
  232.  
  233.  
  234.  
  235. static LRESULT CALLBACK PackSelWndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
  236. {
  237.     switch(msg)
  238.     {
  239.         case WM_CREATE:
  240.         {
  241.             // we keep a pointer to the PS_CONTROLINFO structure, which points to the first package
  242.             // which points to the next one
  243.             // which points to the next one, etc.
  244.             // each package points to its first file and its attributes
  245.             // each file points to the next, etc. :)
  246.             PS_CONTROLINFO *pCtrlInfo = new PS_CONTROLINFO;
  247.             ZeroMemory(pCtrlInfo,sizeof(PS_CONTROLINFO));
  248.  
  249.             HFONT hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
  250.             LOGFONT logFont; // font information
  251.             GetObject(hFont,sizeof(logFont),&logFont); // get font information
  252.             logFont.lfQuality = PROOF_QUALITY;
  253.             logFont.lfWeight = FW_NORMAL;
  254.             logFont.lfHeight -= 1;
  255.             pCtrlInfo->hTitleFont = CreateFontIndirect(&logFont); // recreate the font, underlined
  256.  
  257.             GetObject(hFont,sizeof(logFont),&logFont); // get font information
  258.             logFont.lfQuality = PROOF_QUALITY;
  259.             logFont.lfWeight = FW_NORMAL;
  260.             logFont.lfHeight += 2;
  261.             pCtrlInfo->hPackageInfoFont = CreateFontIndirect(&logFont); // recreate the font, underlined
  262.  
  263.             pCtrlInfo->hTitleLine = CreatePen(PS_SOLID,1,RGB(210,210,210));
  264.  
  265.             SIZE fontSize;
  266.             HDC hDC = GetDC(hWnd);
  267.             GetTextExtentPoint32(hDC,PS_OPTIONALTEXT,lstrlen(PS_OPTIONALTEXT),&fontSize); // hmm I think this will work ok :)
  268.             pCtrlInfo->wRowHeight = (fontSize.cy << 1) + 1 + PS_PACKAGESPACE; // 1 (pen) + 4 (space)
  269.             pCtrlInfo->wFileHeight = fontSize.cy + 1; // not too high
  270.             ReleaseDC(hWnd,hDC);
  271.  
  272.             pCtrlInfo->hTitleUL = CreatePen(PS_SOLID,1,GetSysColor(COLOR_WINDOWTEXT));
  273.             pCtrlInfo->hCBPen = CreatePen(PS_SOLID,1,RGB(111,178,235));
  274.             pCtrlInfo->hBKBrush = CreateSolidBrush(RGB(224,237,252));
  275. //            pCtrlInfo->hDBKBrush = CreateSolidBrush(RGB(200,200,200));
  276.  
  277.             OSVERSIONINFO osVers;
  278.             osVers.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  279.             GetVersionEx(&osVers);
  280.             if ((osVers.dwMajorVersion == 5) || ((osVers.dwMajorVersion == 4) && ((osVers.dwMinorVersion == 10) || (osVers.dwMinorVersion == 90))))
  281.             {
  282.                 pCtrlInfo->hHandCursor = LoadCursor(NULL,IDC_HAND);
  283.             }
  284.             else
  285.             {
  286.                 pCtrlInfo->hHandCursor = LoadCursor(g_hInstance,MAKEINTRESOURCE(IDC_MYHAND));
  287.             }
  288.  
  289.             SetWindowLong(hWnd,0,(LONG)pCtrlInfo);
  290.  
  291.             // init scrollbar
  292.             SendMessage(hWnd,PSM_SCROLLBARUPDATE,0,0);
  293. //            SendMessage(hWnd,WM_ENABLE,IsWindowEnabled(hWnd),0); // change state of scrollbar (if necessary)
  294.         } break;
  295.         case WM_GETFONT: // not very important, but should be implemented
  296.         {
  297.             PS_CONTROLINFO *pCtrlInfo = (PS_CONTROLINFO*)GetWindowLong(hWnd,0);
  298.             return(((pCtrlInfo) ? ((LPARAM)pCtrlInfo->hTitleFont) : (NULL))); // return title font
  299.         } break;
  300.         case PSM_SCROLLBARUPDATE: // if wParam is 1, we were called by the PSM_SCROLLBAR msg
  301.         {
  302.             PS_CONTROLINFO *pCtrlInfo = (PS_CONTROLINFO*)GetWindowLong(hWnd,0);
  303.             RECT rcWnd;
  304.             GetClientRect(hWnd,&rcWnd);
  305.  
  306.             // scrollbar info
  307.             SCROLLINFO scrollInfo;
  308.             scrollInfo.cbSize = sizeof(SCROLLINFO);
  309.             scrollInfo.fMask = SIF_PAGE | SIF_POS | SIF_RANGE;
  310.             scrollInfo.nMin = 0;
  311.             scrollInfo.nPos = pCtrlInfo->wScrollPos;
  312.             scrollInfo.nPage = rcWnd.bottom; // height of client area
  313.             // scrollInfo.nMax is tricky to compute
  314.             // let's do it... :)
  315.             scrollInfo.nMax = pCtrlInfo->wPackagesNum * pCtrlInfo->wRowHeight;
  316.  
  317.             PS_PACKAGELIST *pCurPackage = pCtrlInfo->pPackageList;
  318.             while (pCurPackage != NULL)
  319.             {
  320.                 if (pCurPackage->dwFlags & 1) // expanded
  321.                 {
  322.                     scrollInfo.nMax += pCurPackage->wTotalFiles * pCtrlInfo->wFileHeight;
  323.                 }
  324.                 pCurPackage = pCurPackage->next;
  325.             }
  326.  
  327.             // I hate scrollbars
  328.             if ((unsigned int)scrollInfo.nMax > scrollInfo.nPage) // scrollbar is shown
  329.             {
  330.                 int iDelta = scrollInfo.nMax - scrollInfo.nPage;
  331.                 if (pCtrlInfo->wScrollPos > iDelta) // too much! (i.e. we're drawing over the edge)
  332.                 {
  333.                     pCtrlInfo->wScrollPos = iDelta; // go back
  334.                     scrollInfo.nPos = pCtrlInfo->wScrollPos;
  335.                     if (!wParam) // no call from routine, let's redraw ourselves
  336.                     {
  337.                         RECT rcWnd;
  338.                         GetClientRect(hWnd,&rcWnd);
  339.                         InflateRect(&rcWnd,-1,-1); // do not redraw border!
  340.                         InvalidateRect(hWnd,&rcWnd,false);
  341.                         UpdateWindow(hWnd);
  342.                     }
  343.                 }
  344.             }
  345.             else // no scrolling at all
  346.             {
  347.                 // make sure we're at 0
  348.                 pCtrlInfo->wScrollPos = 0;
  349.                 scrollInfo.nPos = 0;
  350.                 if (!wParam) // no call from routine, let's redraw ourselves
  351.                 {
  352.                     RECT rcWnd;
  353.                     GetClientRect(hWnd,&rcWnd);
  354.                     InflateRect(&rcWnd,-1,-1); // do not redraw border!
  355.                     InvalidateRect(hWnd,&rcWnd,false);
  356.                     UpdateWindow(hWnd);
  357.                 }
  358.             }
  359.  
  360.             SetScrollInfo(hWnd,SB_VERT,&scrollInfo,true);
  361.             return(0);
  362.         } break;
  363.         case PSM_SCROLLBAR: // wParam is new pos
  364.         {
  365.             PS_CONTROLINFO *pCtrlInfo = (PS_CONTROLINFO*)GetWindowLong(hWnd,0);
  366.             WORD wOldPos = pCtrlInfo->wScrollPos;
  367.             pCtrlInfo->wScrollPos = wParam; // new position
  368.  
  369.             SendMessage(hWnd,PSM_SCROLLBARUPDATE,1,0);
  370.  
  371.             RECT rcClient, rcWnd; // rcWnd will be used later to include the border in the invalidation region
  372.             GetClientRect(hWnd,&rcClient); // this will be the clipping rect
  373.             CopyMemory(&rcWnd,&rcClient,sizeof(RECT)); // make a copy
  374.  
  375.             InflateRect(&rcClient,-1,-1); // exclude border (otherwise it'll be scrolled to and smear around)
  376.             ScrollWindowEx(hWnd,0,wOldPos - pCtrlInfo->wScrollPos,&rcClient,NULL,NULL,NULL,SW_INVALIDATE);
  377.  
  378.             // before we call an update, we need to include the border in the invalidation region
  379.             HRGN hWndRgn = CreateRectRgnIndirect(&rcWnd); // entire window
  380.             HRGN hClientRgn = CreateRectRgnIndirect(&rcClient); // client area
  381.             HRGN hBorderRgn = CreateRectRgn(1,1,2,2); // the border
  382.  
  383.             CombineRgn(hBorderRgn,hWndRgn,hClientRgn,RGN_XOR); // XOR (we will be left with the border)
  384.             InvalidateRgn(hWnd,hBorderRgn,false);
  385.  
  386.             UpdateWindow(hWnd);
  387.  
  388.             // clean up
  389.             DeleteObject(hBorderRgn);
  390.             DeleteObject(hClientRgn);
  391.             DeleteObject(hWndRgn);
  392.             return(0);
  393.         } break;
  394.         case WM_MOUSEWHEEL:
  395.         {
  396.             UINT uiScrollLines;
  397.             PS_CONTROLINFO *pCtrlInfo = (PS_CONTROLINFO*)GetWindowLong(hWnd,0);
  398.             int iScrollPos = (int)(pCtrlInfo->wScrollPos); // signed (boundaries check come later)
  399.  
  400.             SCROLLINFO scrollInfo;
  401.             scrollInfo.cbSize = sizeof(SCROLLINFO);
  402.             scrollInfo.fMask = SIF_RANGE | SIF_PAGE; // get nMax
  403.             GetScrollInfo(hWnd,SB_VERT,&scrollInfo);
  404.             scrollInfo.nMax -= scrollInfo.nPage; // no problems here (we have a scroll bar, meaning the max is bigger than the page) - this is how much we can actually scroll
  405.  
  406.             if (SystemParametersInfo(SPI_GETWHEELSCROLLLINES,0,&uiScrollLines,0) == 0) // got nothing
  407.             {
  408.                 uiScrollLines = 3;
  409.             }
  410.             // scrolling is actually:
  411.             iScrollPos -= ((short)HIWORD(wParam) * pCtrlInfo->wFileHeight * (int)uiScrollLines) / WHEEL_DELTA;
  412.  
  413.             // boundaries check
  414.             if (iScrollPos < 0)
  415.             {
  416.                 iScrollPos = 0;
  417.             }
  418.             else if (iScrollPos > scrollInfo.nMax)
  419.             {
  420.                 iScrollPos = scrollInfo.nMax;
  421.             }
  422.  
  423.             if ((int)(pCtrlInfo->wScrollPos) != iScrollPos) // change
  424.             {
  425.                 SendMessage(hWnd,PSM_SCROLLBAR,iScrollPos,0);
  426.             }
  427.             return(0);
  428.         } break;
  429.         case WM_VSCROLL:
  430.         {/* // TOOD is this needed? - nope, coz we're not supporting disable/enable mode
  431.             if (!IsWindowEnabled(hWnd)) // disabled
  432.             {
  433.                 return(0);
  434.             }*/
  435.  
  436.             PS_CONTROLINFO *pCtrlInfo = (PS_CONTROLINFO*)GetWindowLong(hWnd,0);
  437.             int iScrollPos = (int)(pCtrlInfo->wScrollPos); // signed (boundaries check come later)
  438.             RECT rcWnd;
  439.             GetClientRect(hWnd,&rcWnd);
  440.  
  441.             SCROLLINFO scrollInfo;
  442.             scrollInfo.cbSize = sizeof(SCROLLINFO);
  443.             scrollInfo.fMask = SIF_RANGE | SIF_PAGE; // get nMax
  444.             GetScrollInfo(hWnd,SB_VERT,&scrollInfo);
  445.             scrollInfo.nMax -= scrollInfo.nPage; // no problems here (we have a scroll bar, meaning the max is bigger than the page) - this is how much we can actually scroll
  446.  
  447.             // scrolling is a mess
  448.             // SB_BOTTOM/SB_TOP/SB_LINEDOWN/SB_LINEUP are rather easy
  449.             // SB_PAGEDOWN and SB_PAGEUP were a mess, but it works rather well now :)
  450.             switch(LOWORD(wParam))
  451.             {
  452.                 case SB_BOTTOM: iScrollPos = scrollInfo.nMax; break;
  453.                 case SB_LINEDOWN: iScrollPos += pCtrlInfo->wFileHeight; break;
  454.                 case SB_LINEUP: iScrollPos -= pCtrlInfo->wFileHeight; break;
  455.                 // boundary check here
  456.                 case SB_PAGEDOWN: if (iScrollPos+rcWnd.bottom <= scrollInfo.nMax) iScrollPos += (WORD)rcWnd.bottom; else iScrollPos = scrollInfo.nMax; break;
  457.                 case SB_PAGEUP: if (iScrollPos >= (WORD)rcWnd.bottom) iScrollPos -= (WORD)rcWnd.bottom; else iScrollPos = 0; break;
  458.                 case SB_THUMBTRACK: iScrollPos = HIWORD(wParam); break;
  459.                 case SB_TOP: iScrollPos = scrollInfo.nMin; break;
  460.             }
  461.  
  462.             if (iScrollPos < 0)
  463.             {
  464.                 iScrollPos = 0;
  465.             }
  466.             else if (iScrollPos > scrollInfo.nMax)
  467.             {
  468.                 iScrollPos = scrollInfo.nMax;
  469.             }
  470.  
  471.             if ((int)(pCtrlInfo->wScrollPos) != iScrollPos) // change
  472.             {
  473.                 SendMessage(hWnd,PSM_SCROLLBAR,iScrollPos,0);
  474.             }
  475.             return(0);
  476.         } break;
  477.         case WM_GETDLGCODE: // need to get direction keys msgs
  478.         {
  479.             return(DLGC_WANTARROWS);
  480.         } break;
  481.         case WM_KEYDOWN: // handle some more user input
  482.         {
  483.             if (wParam == VK_DOWN)
  484.             {
  485.                 SendMessage(hWnd,WM_VSCROLL,MAKEWPARAM(SB_LINEDOWN,0),NULL); // use WM_VSCROLL
  486.             }
  487.             else if (wParam == VK_UP)
  488.             {
  489.                 SendMessage(hWnd,WM_VSCROLL,MAKEWPARAM(SB_LINEUP,0),NULL); // use WM_VSCROLL
  490.             }
  491.             return(0);
  492.         } break;
  493.         case WM_SETCURSOR:
  494.         {
  495.             RECT rcTemp;
  496.  
  497.             UINT mouseMsg = HIWORD(lParam);
  498.             if (/*(!IsWindowEnabled(hWnd)) || */((mouseMsg != WM_MOUSEMOVE) && (mouseMsg != WM_LBUTTONDOWN))) // only these msgs are involved
  499.             {
  500.                 return(false);
  501.             }
  502.  
  503.             // check "collision" for each package
  504.             PS_CONTROLINFO *pCtrlInfo = (PS_CONTROLINFO*)GetWindowLong(hWnd,0);
  505.  
  506.             RECT rcWnd;
  507.             GetClientRect(hWnd,&rcWnd);
  508.  
  509.             PS_PACKAGELIST *pCurPackage = pCtrlInfo->pPackageList;
  510.             POINT ptMouse;
  511.             GetCursorPos(&ptMouse);
  512.             ScreenToClient(hWnd,&ptMouse);
  513.  
  514.             bool fSetCursor = false;
  515.             int iPosY = PS_PACKAGEPOS_Y - pCtrlInfo->wScrollPos;
  516.             while (pCurPackage != NULL)
  517.             {
  518.                 rcTemp.left = PS_PACKAGEPOS_X;
  519.                 rcTemp.right = rcTemp.left + pCurPackage->TitleSize.cx;
  520.                 rcTemp.top = iPosY;
  521.                 rcTemp.bottom = rcTemp.top + pCurPackage->TitleSize.cy;
  522.  
  523.                 bool fLastState = ((pCurPackage->dwFlags & 2) >> 1) & 1;
  524.                 if (PtInRect(&rcTemp,ptMouse))
  525.                 {
  526.                     pCurPackage->dwFlags |= 2; // hot-track
  527.                     SetCursor(pCtrlInfo->hHandCursor);
  528.                     fSetCursor = true;
  529.  
  530.                     if (mouseMsg == WM_LBUTTONDOWN)
  531.                     {
  532.                         bool fOldState = !(pCurPackage->dwFlags & 1); // reverse
  533.                         pCurPackage->dwFlags &= ~1; // clear
  534.                         pCurPackage->dwFlags |= fOldState & 1;
  535.  
  536.                         // invalidate entire item (background)
  537.                         rcTemp.left = 1;
  538.                         rcTemp.top = iPosY + (pCurPackage->TitleSize.cy >> 1) - ((pCtrlInfo->wRowHeight-(PS_PACKAGESPACE>>1)) >> 1);
  539.                         rcTemp.right = rcWnd.right - 1;
  540.                         rcTemp.bottom = rcWnd.bottom - 1; // we redraw to the bottom of the control (necessary) - no need for last pixel, it's the frame
  541.  
  542.                         SendMessage(hWnd,PSM_SCROLLBARUPDATE,0,0);
  543.                         InvalidateRect(hWnd,&rcTemp,false);
  544.                         UpdateWindow(hWnd);
  545.                     }
  546.                 }
  547.                 else
  548.                 {
  549.                     pCurPackage->dwFlags &= ~2; // bye (no hot-track)
  550.                 }
  551.  
  552.                 // only redraw if we must
  553.                 if ((unsigned long)fLastState != (((pCurPackage->dwFlags & 2) >> 1) & 1))
  554.                 {
  555.                     rcTemp.bottom++; // will force a refresh
  556.                     InvalidateRect(hWnd,&rcTemp,false);
  557.                     UpdateWindow(hWnd);
  558.                 }
  559.  
  560.                 if (fSetCursor)
  561.                 {
  562.                     iPosY += pCtrlInfo->wRowHeight;
  563.                     pCurPackage = pCurPackage->next;
  564.                     continue; // we don't break, read below
  565.                 }
  566.  
  567.                 // now check for icon
  568.                 rcTemp.top = iPosY + 1;
  569.                 rcTemp.bottom = rcTemp.top + pCurPackage->TitleSize.cy - 1;
  570.                 rcTemp.left = (PS_PACKAGEPOS_X - (rcTemp.bottom-rcTemp.top)) >> 1;
  571.                 rcTemp.right = (rcTemp.bottom - rcTemp.top) + rcTemp.left;
  572.  
  573.                 // latest change: package is only changeable if it is optional (Kai)
  574.                 if ((pCurPackage->packageInfo.fOptional) && (PtInRect(&rcTemp,ptMouse)))
  575.                 {
  576.                     SetCursor(pCtrlInfo->hHandCursor);
  577.                     fSetCursor = true;
  578.                     if (mouseMsg == WM_LBUTTONDOWN)
  579.                     {
  580.                         pCurPackage->packageInfo.fSelected = !pCurPackage->packageInfo.fSelected;
  581.  
  582.                         SendMessage(GetParent(hWnd),PSN_PACKAGESELCHANGE,0,0); // notify parent
  583.  
  584.                         // invalidate entire item (background)
  585.                         PS_GetPackageRect(hWnd,pCtrlInfo,iPosY,pCurPackage,&rcTemp);
  586.  
  587.                         SendMessage(hWnd,PSM_SCROLLBARUPDATE,0,0);
  588.                         InvalidateRect(hWnd,&rcTemp,false);
  589.                         UpdateWindow(hWnd);
  590.                     }
  591.                 }
  592.  
  593.                 // we could stop here if the cursor was set for one item
  594.                 // coz it's enough
  595.                 // but we might need to unset the hot-tracking for other items, sux
  596.  
  597.                 iPosY += pCtrlInfo->wRowHeight + ((pCurPackage->dwFlags & 1) ? (pCtrlInfo->wFileHeight*pCurPackage->wTotalFiles) : (0));
  598.                 pCurPackage = pCurPackage->next;
  599.             }
  600.  
  601.             if (!fSetCursor) // set arrow
  602.             {
  603.                 SetCursor(LoadCursor(NULL,IDC_ARROW));
  604.             }
  605.  
  606.             if ((GetFocus() != hWnd) && (((mouseMsg == WM_LBUTTONDOWN) || (mouseMsg == WM_RBUTTONDOWN)))) // keyboard focus needs to be set
  607.             {
  608.                 SetFocus(hWnd);
  609.             }
  610.             return(false);
  611.         } break;
  612.         // painting
  613.         case WM_ERASEBKGND: // this should'nt be sent. ever. but just in case.
  614.         {
  615.             return(1);
  616.         } break;
  617.         case WM_PRINTCLIENT: // not REALLY needed, but it's rather easy, and might be useful later
  618.         {
  619.             RECT rcWnd;
  620.             GetWindowRect(hWnd,&rcWnd);
  621.             PS_DrawControl(hWnd,(HDC)wParam,&rcWnd);
  622.         } break;
  623.         case WM_PAINT:
  624.         {
  625.             PAINTSTRUCT ps;
  626.             PS_DrawControl(hWnd,BeginPaint(hWnd,&ps),&(ps.rcPaint));
  627.             EndPaint(hWnd,&ps);
  628.             return(0);
  629.         } break;
  630.         case PSM_ADDPACKAGE: // add a new package. will be inserted at positon given by wParam, lParam is a pointer to a PS_PACKAGEINFO structure that contains info about the new package. returns unique ID of package
  631.         {
  632.             PS_CONTROLINFO *pCtrlInfo = (PS_CONTROLINFO*)GetWindowLong(hWnd,0);
  633.             PS_PACKAGELIST *node = new PS_PACKAGELIST; // allocate
  634.             // not a big fan of these stuff. but might as well get used to it :)
  635.             ZeroMemory(node,sizeof(PS_PACKAGELIST));
  636.             CopyMemory(&(node->packageInfo),(PS_PACKAGEINFO*)lParam,sizeof(PS_PACKAGEINFO));
  637.  
  638.             // find insertion position
  639.             WORD wPos = 0; // we're not always entering the loop
  640.             PS_PACKAGELIST *pCurPos = pCtrlInfo->pPackageList;
  641.             PS_PACKAGELIST *pLastPos = NULL;
  642.             while (pCurPos != NULL)
  643.             {
  644.                 if (wPos++ == wParam)
  645.                 {
  646.                     wPos--; // right pos
  647.                     break;
  648.                 }
  649.                 pLastPos = pCurPos;
  650.                 pCurPos = pCurPos->next;
  651.             }
  652.  
  653.             // insertion point is pLastFile
  654.             if (pLastPos == NULL) // new head
  655.             {
  656.                 node->next = pCtrlInfo->pPackageList;
  657.                 pCtrlInfo->pPackageList = node; // new head
  658.             }
  659.             else // somewhere in the middle/end
  660.             {
  661.                 node->next = pLastPos->next; // if another item is after pCurPos, we stick it to the end of node
  662.                 pLastPos->next = node; // new item after pCurPos is node
  663.             }
  664.  
  665.             HDC hDC = GetDC(hWnd);
  666.  
  667.             HFONT hOldFont = (HFONT)SelectObject(hDC,pCtrlInfo->hTitleFont); // select our favourite font
  668.             // we now do lpDisplayText and wTitleWidth
  669.             char *lpTemp = new char[lstrlen(node->packageInfo.lpTitle) + 1];
  670.             lstrcpy(lpTemp,node->packageInfo.lpTitle);
  671.  
  672.             SIZE titleSize;
  673.             GetTextExtentPoint32(hDC,lpTemp,lstrlen(lpTemp),&titleSize);
  674.             if (lstrlen(lpTemp) > 3) // only if more than 3!
  675.             {
  676.                 RECT rcWnd;
  677.                 GetClientRect(hWnd,&rcWnd);
  678.  
  679.                 char *lpDotIndex = lpTemp + lstrlen(lpTemp) - 3; // 3 is length of dots. fixed, for now
  680.                 while (titleSize.cx+PS_PACKAGEPOS_X >= (rcWnd.right*0.5)) // no more than 50% of client width
  681.                 {
  682.                     lstrcpy(lpDotIndex,"...");
  683.                     lpDotIndex--;
  684.                     GetTextExtentPoint32(hDC,lpTemp,lstrlen(lpTemp),&titleSize);
  685.                 }
  686.             }
  687.  
  688.             // now copy it back
  689.             node->lpDisplayText = new char[lstrlen(lpTemp) + 1];
  690.             lstrcpy(node->lpDisplayText,lpTemp);
  691.             CopyMemory(&(node->TitleSize),&titleSize,sizeof(SIZE));
  692. //            node->wTitleWidth = (WORD)titleSize.cx;
  693.  
  694.             delete [] lpTemp;
  695.             SelectObject(hDC,hOldFont);
  696.             ReleaseDC(hWnd,hDC);
  697.  
  698.             pCtrlInfo->wPackagesNum++;
  699.             SendMessage(hWnd,PSM_SCROLLBARUPDATE,0,0);
  700.             return(wPos);
  701.         } break;
  702.         case PSM_ADDFILE: // adds a new file (files are added alphabetically). the package it should be put in is identified by wParam, lParam is a pointer to a PS_FILEINFO structure. return value is unique ID of file.
  703.         {
  704.             PS_CONTROLINFO *pCtrlInfo = (PS_CONTROLINFO*)GetWindowLong(hWnd,0);
  705.  
  706.             WORD wPos = 0;
  707.             PS_PACKAGELIST *pCurPos = pCtrlInfo->pPackageList;
  708.             while (pCurPos != NULL)
  709.             {
  710.                 if (wPos++ == wParam)
  711.                 {
  712.             //        wPos--; // we don't use this again later
  713.                     break;
  714.                 }
  715.                 pCurPos = pCurPos->next;
  716.             }
  717.  
  718.             if (pCurPos != NULL) // yay, we got the package
  719.             {
  720.                 PS_FILELIST *node = new PS_FILELIST;
  721.                 ZeroMemory(node,sizeof(PS_FILELIST));
  722.                 CopyMemory(&(node->fileInfo),(PS_FILEINFO*)lParam,sizeof(PS_FILEINFO));
  723.                 CharLower(node->fileInfo.lpFilename); // convert to lower case
  724.  
  725.                 // now add the display text!
  726.                 char szTemp[128], szFileSize[32];; // will hold size
  727.                 SIZE extraSize, textSize; // extra text (szTemp) size
  728.                 RECT rcWnd;
  729.  
  730.                 GetClientRect(hWnd,&rcWnd);
  731.  
  732.                 Format_DisplaySize(szFileSize,node->fileInfo.dwFileSize);
  733.                 wsprintf(szTemp," (%s)",szFileSize);
  734.  
  735.                 HDC hDC = GetDC(hWnd);
  736.                 HFONT hOldFont = (HFONT)SelectObject(hDC,pCtrlInfo->hTitleFont);
  737.  
  738.                 char *lpTempText = new char[lstrlen(node->fileInfo.lpFilename) + 1]; // used to shorten the name. temporary.
  739.                 lstrcpy(lpTempText,node->fileInfo.lpFilename);
  740.  
  741.                 if (lstrlen(lpTempText) > 3)
  742.                 {
  743.                     GetTextExtentPoint32(hDC,szTemp,lstrlen(szTemp),&extraSize);
  744.                     GetTextExtentPoint32(hDC,lpTempText,lstrlen(lpTempText),&textSize);
  745.  
  746.                     char *lpDotIndex = lpTempText + lstrlen(lpTempText) - 3; // 3 is length of dots. fixed, for now
  747.                     while (PS_FILEPOS_X+textSize.cx+extraSize.cx > (rcWnd.right >> 1)) // too big
  748.                     {
  749.                         lstrcpy(lpDotIndex,"...");
  750.                         lpDotIndex--;
  751.                         GetTextExtentPoint32(hDC,lpTempText,lstrlen(lpTempText),&textSize);
  752.                     }
  753.                 }
  754.  
  755.                 node->lpDisplayText = new char[lstrlen(lpTempText) + lstrlen(szTemp) + 1]; // final copy
  756.                 lstrcpy(node->lpDisplayText,lpTempText);
  757.                 lstrcat(node->lpDisplayText,szTemp);
  758.  
  759.                 delete [] lpTempText;
  760.  
  761.                 SelectObject(hDC,hOldFont);
  762.                 ReleaseDC(hWnd,hDC);
  763.  
  764.                 WORD wFilePos = 0;
  765.                 PS_FILELIST *pCurFile = pCurPos->pFileList;
  766.                 PS_FILELIST *pLastFile = NULL;
  767.                 while (pCurFile != NULL)
  768.                 {
  769.                     // lstrcmpi isn't needed, it's always lower case (we make sure)
  770.                     if (lstrcmp(pCurFile->fileInfo.lpFilename,node->fileInfo.lpFilename) >= 0) // insert here
  771.                     {
  772.                         if (wFilePos > 0) wFilePos--;
  773.                         break;
  774.                     }
  775.  
  776.                     pLastFile = pCurFile;
  777.                     pCurFile = pCurFile->next;
  778.                     wFilePos++;
  779.                 }
  780.  
  781.                 // insertion point is pLastFile
  782.                 if (pLastFile == NULL) // new head
  783.                 {
  784.                     node->next = pCurPos->pFileList;
  785.                     pCurPos->pFileList = node; // new head
  786.                 }
  787.                 else // somewhere in the middle/end
  788.                 {
  789.                     node->next = pLastFile->next; // if another item is after pCurFile, we stick it to the end of node
  790.                     pLastFile->next = node; // new item after pCurFile is node
  791.                 }
  792.  
  793.                 // another file added
  794.                 pCurPos->wTotalFiles++; // per-package
  795.                 pCurPos->dwTotalSize += node->fileInfo.dwFileSize;
  796.                 SendMessage(hWnd,PSM_SCROLLBARUPDATE,0,0);
  797.                 return(wFilePos);
  798.             }
  799.             return(0);
  800.         } break;
  801.         case PSM_SELECTPACKAGE: // wParam identifies the package, if lParam is TRUE, the package will be selected, if lParam is FALSE, the package will be un-selected :)
  802.         {
  803.             PS_CONTROLINFO *pCtrlInfo = (PS_CONTROLINFO*)GetWindowLong(hWnd,0);
  804.  
  805.             WORD wPos = 0;
  806.             int iPosY = PS_PACKAGEPOS_Y - pCtrlInfo->wScrollPos;
  807.             PS_PACKAGELIST *pCurPos = pCtrlInfo->pPackageList;
  808.             while (pCurPos != NULL)
  809.             {
  810.                 // we need to find our position
  811.                 PS_FILELIST *pCurFile = pCurPos->pFileList;
  812.  
  813.                 if (wPos++ == wParam)
  814.                 {
  815.                     if (pCurPos->packageInfo.fSelected != (lParam & 1)) // only if different
  816.                     {
  817.                         pCurPos->packageInfo.fSelected = lParam & 1; // compiler warnings suck
  818.  
  819.                         RECT rcPackage;
  820.                         PS_GetPackageRect(hWnd,pCtrlInfo,iPosY,pCurPos,&rcPackage);
  821.  
  822.                         InvalidateRect(hWnd,&rcPackage,false);
  823.                         UpdateWindow(hWnd);
  824.                     }
  825.                     return(1);
  826.                 }
  827.                 iPosY += pCtrlInfo->wRowHeight + ((pCurPos->dwFlags & 1) ? (pCtrlInfo->wFileHeight*pCurPos->wTotalFiles) : (0));
  828.                 pCurPos = pCurPos->next;
  829.             }
  830.  
  831.             return(0);
  832.         } break;
  833.         case PSM_GETPACKAGECOUNT: // ... :)
  834.         {
  835.             return(((PS_CONTROLINFO*)GetWindowLong(hWnd,0))->wPackagesNum);
  836.         } break;
  837.         case PSM_GETPACKAGEINFO: // wParam is ID of package, return value is a pointer to the package info (PS_PACKAGEINFO) - look but don't touch.
  838.         {
  839.             WORD wPos = 0;
  840.             PS_PACKAGELIST *pCurPos = ((PS_CONTROLINFO*)GetWindowLong(hWnd,0))->pPackageList;
  841.             while (pCurPos != NULL)
  842.             {
  843.                 if (wPos++ == wParam)
  844.                 {
  845.                     break;
  846.                 }
  847.                 pCurPos = pCurPos->next;
  848.             }
  849.  
  850.             if (pCurPos != NULL) // yay, we got the package
  851.             {
  852.                 return((LRESULT)&(pCurPos->packageInfo));
  853.             }
  854.             return(0);
  855.         } break;
  856.         case PSM_GETFILECOUNT: // wParam is ID of package
  857.         {
  858.             WORD wPos = 0;
  859.             PS_PACKAGELIST *pCurPos = ((PS_CONTROLINFO*)GetWindowLong(hWnd,0))->pPackageList;
  860.             while (pCurPos != NULL)
  861.             {
  862.                 if (wPos++ == wParam)
  863.                 {
  864.                     return(pCurPos->wTotalFiles);
  865.                 }
  866.                 pCurPos = pCurPos->next;
  867.             }
  868.             return(0);
  869.         } break;
  870.         case PSM_GETFILEINFO: // wParam is ID of file in package (wait a sec), lParam is a pointer to a PS_PACKAGEINFO structure returned by PSM_GETPACKAGEINFO (now u got it :)). return value is a pointer to a PS_FILEINFO structure
  871.         {
  872.             // :)
  873.             // so easy this is almost devilish
  874.             // well, it could be easier, actually :)
  875.             // first we need to find the package
  876.             PS_PACKAGEINFO *pPackageInfo = (PS_PACKAGEINFO*)lParam;
  877.  
  878.             PS_PACKAGELIST *pCurPos = ((PS_CONTROLINFO*)GetWindowLong(hWnd,0))->pPackageList;
  879.             while (pCurPos != NULL)
  880.             {
  881.                 if (&(pCurPos->packageInfo) == pPackageInfo) // compare address. comparison can also be made according to pCurPos, since package info is right at the beginning
  882.                 {
  883.                     WORD wPos = 0;
  884.                     PS_FILELIST *pCurFile = pCurPos->pFileList;
  885.                     while (pCurFile != NULL)
  886.                     {
  887.                         if (wPos++ == wParam)
  888.                         {
  889.                             return((LPARAM)&(pCurFile->fileInfo));
  890.                         }
  891.                         pCurFile = pCurFile->next;
  892.                     }
  893.                 }
  894.                 pCurPos = pCurPos->next;
  895.             }
  896.             return(NULL);
  897.         } break;/*
  898.         case WM_ENABLE: // mode is changing...
  899.         {
  900.             InvalidateRect(hWnd,NULL,false);
  901.             UpdateWindow(hWnd);
  902.             return(0);
  903.         } break;*/
  904.         case WM_DESTROY:
  905.         {
  906.             PS_CONTROLINFO *pCtrlInfo = (PS_CONTROLINFO*)GetWindowLong(hWnd,0);
  907.             PS_PACKAGELIST *pCurPackage = pCtrlInfo->pPackageList;
  908.  
  909.             while (pCurPackage != NULL)
  910.             {
  911.                 PS_PACKAGELIST *pNextPackage = pCurPackage->next;
  912.                 delete [] pCurPackage->packageInfo.lpTitle; // delete it
  913.                 delete [] pCurPackage->lpDisplayText;
  914.  
  915.                 // now delete all files
  916.                 PS_FILELIST *pCurFile = pCurPackage->pFileList;
  917.  
  918.                 while (pCurFile != NULL)
  919.                 {
  920.                     PS_FILELIST *pNextFile = pCurFile->next;
  921.                     delete [] pCurFile->fileInfo.lpFilename;
  922.                     delete [] pCurFile->lpDisplayText;
  923.  
  924.                     delete pCurFile;
  925.                     pCurFile = pNextFile;
  926.                 }
  927.  
  928.                 delete pCurPackage;
  929.                 pCurPackage = pNextPackage;
  930.             }
  931.  
  932.             DeleteObject(pCtrlInfo->hTitleFont);
  933.             DeleteObject(pCtrlInfo->hTitleLine);
  934.             DeleteObject(pCtrlInfo->hPackageInfoFont);
  935.             DeleteObject(pCtrlInfo->hTitleUL);
  936.             DeleteObject(pCtrlInfo->hCBPen);
  937.             DeleteObject(pCtrlInfo->hBKBrush);
  938.         //    DeleteObject(pCtrlInfo->hDBKBrush);
  939.             delete pCtrlInfo;
  940.             return(0);
  941.         } break;
  942.     }
  943.     return(DefWindowProc(hWnd,msg,wParam,lParam));
  944. }
  945.  
  946.  
  947.  
  948. void PackageSelector_Init(void)
  949. {
  950.     WNDCLASS wcl;
  951.  
  952.     wcl.style = CS_HREDRAW | CS_VREDRAW | CS_CLASSDC;
  953.     wcl.lpfnWndProc = PackSelWndProc;
  954.     wcl.cbClsExtra = 0;
  955.     wcl.cbWndExtra = sizeof(PS_CONTROLINFO*);
  956.     wcl.hInstance = g_hInstance;
  957.     wcl.hCursor = NULL;//LoadCursor(NULL,IDC_ARROW);;
  958.     wcl.lpszClassName = PACKAGESELECTOR_CLASSNAME;
  959. //    wcl.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
  960.     wcl.hbrBackground = NULL;
  961.     wcl.hIcon = NULL;
  962.     wcl.lpszMenuName = NULL;
  963.  
  964.     RegisterClass(&wcl);
  965. }
  966.