home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / VISUAL_B / CODIGO_1 / FILELIST / FILELIST.C < prev    next >
Encoding:
C/C++ Source or Header  |  1991-11-13  |  42.1 KB  |  1,376 lines

  1. //---------------------------------------------------------------------------
  2. // List.c
  3. //---------------------------------------------------------------------------
  4. // List Button Control
  5. //---------------------------------------------------------------------------
  6.  
  7. #define NOCOMM
  8.  
  9. #include <windows.h>
  10.  
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include <ctype.h>
  14. #include "vbapi.h"
  15. #include "filelist.h"
  16.  
  17. #define RESET_MASK  0x0000
  18. #define SELECT_MASK 0x0001
  19. #define GRAY_MASK   0x0002
  20. #define INVALID_GRAY -1
  21.  
  22. static     BOOL NEAR                 InitiateListBuffer         (PFILELIST);
  23. static     BOOL NEAR                 TeminateListBuffer         (PFILELIST);
  24. static     LPSTR NEAR                 GetListLine             (int, PFILELIST);
  25. static     LPSTR NEAR                 DisplayLine             (LPSTR, LPSTR, PFILELIST, int);
  26. static     LPSTR NEAR                 OutputLine                 (LPSTR, LPSTR, PFILELIST, int);
  27. static     LPSTR NEAR                 InputLine                 (LPSTR, LPSTR, PFILELIST, int);
  28. static     BOOL NEAR                 GoToLine                 (int, HWND, PFILELIST);
  29. static     BOOL NEAR                 FindString                 (LPSTR, HWND, PFILELIST);
  30. static     LPSTR NEAR                 VerifyString             (LPSTR, HWND, PFILELIST);
  31. static     LPSTR NEAR                 LocateString             (LPSTR, HWND, PFILELIST);
  32. BOOL    ItemStatus              (HCTL, HWND, int);
  33. BOOL    SpillItem               (HCTL, HWND, LONG, PFILELIST);
  34. BOOL    CheckItem               (HCTL, HWND, LPDRAWITEMSTRUCT, PFILELIST);
  35. BOOL    DrawItem                (HCTL, HWND, LPDRAWITEMSTRUCT, PFILELIST);
  36.  
  37. //---------------------------------------------------------------------------
  38. // InitiateListBuffer
  39. //---------------------------------------------------------------------------
  40. static BOOL NEAR InitiateListBuffer (PFILELIST    lpListStruct) {
  41.  
  42.     LONG lBufferLen;
  43.  
  44.     // BUFFER ALLOCATION
  45.     lBufferLen = (lpListStruct->nLineSize + 1) * NUMBER_LINES;
  46.     if (lpListStruct->hListBuffer = GlobalAlloc (GHND, lBufferLen)) {
  47.  
  48.         lpListStruct->lpListBuffer = (LPSTR)
  49.                                       GlobalLock (lpListStruct->hListBuffer);
  50.          return (TRUE);
  51.     }
  52.     return (FALSE);
  53. }
  54.  
  55. //---------------------------------------------------------------------------
  56. // TeminateListBuffer
  57. //---------------------------------------------------------------------------
  58. static BOOL NEAR TeminateListBuffer (PFILELIST    lpListStruct) {
  59.  
  60.     // BUFFER DEALLOCATION
  61.     if (lpListStruct->hListBuffer) {
  62.         GlobalUnlock (lpListStruct->hListBuffer);
  63.         GlobalFree   (lpListStruct->hListBuffer);
  64.         lpListStruct->hListBuffer  = (HANDLE)NULL;
  65.         lpListStruct->lpListBuffer = (LPSTR)NULL;
  66.         return (TRUE);
  67.     }
  68.     return (FALSE);
  69. }
  70.  
  71. //---------------------------------------------------------------------------
  72. // GetFileLength
  73. //---------------------------------------------------------------------------
  74. static WORD NEAR GetFileLength (PFILELIST lpListStruct) {
  75.  
  76.     int     fH,
  77.             nLastLine;
  78.     LPSTR     lpFileName;
  79.  
  80.     lpFileName = VBDerefHsz (lpListStruct->hFileName);
  81.     if ((fH = _lopen (lpFileName, OF_READ )) != -1) {
  82.         int  nLastLine;
  83.  
  84.         nLastLine = _llseek (fH, 0L, 2) / lpListStruct->nLineSize;
  85.         _llseek (fH, 0l, 0);
  86.         _lclose (fH);
  87.         return (nLastLine);
  88.     }
  89.     return (FALSE);
  90. }
  91.  
  92. //---------------------------------------------------------------------------
  93. // FillBuffer
  94. //---------------------------------------------------------------------------
  95. static BOOL NEAR FillBuffer (int         nStartLine,
  96.                              PFILELIST    lpListStruct) {
  97.  
  98.     int     fH,
  99.             nLastLine;
  100.     LPSTR     lpFileName;
  101.  
  102.     // IS THE BUFFER READY ?
  103.     if (!lpListStruct->lpListBuffer) {
  104.         if (!InitiateListBuffer (lpListStruct)) {
  105.             return (FALSE);
  106.         }
  107.     }
  108.  
  109.     lpFileName = VBDerefHsz (lpListStruct->hFileName);
  110.     if ((fH = _lopen (lpFileName, OF_READ )) != -1) {
  111.         LONG lOffSet;
  112.         int  nLastLine,
  113.              n;
  114.  
  115.         nLastLine = _llseek (fH, 0L, 2) / lpListStruct->nLineSize;
  116.  
  117.         lpListStruct->nStartLine = nStartLine;
  118.         lpListStruct->nEndLine = min (nLastLine,
  119.                                       lpListStruct->nStartLine +
  120.                                       NUMBER_LINES - 1);
  121.         lOffSet = lpListStruct->nLineSize * lpListStruct->nStartLine;
  122.         if (_llseek (fH, lOffSet, 0) != -1) {
  123.             for (n = lpListStruct->nStartLine;
  124.                  n <= lpListStruct->nEndLine;
  125.                  ++n)
  126.                 _lread (fH,
  127.                         lpListStruct->lpListBuffer +
  128.                         (n  - lpListStruct->nStartLine) *
  129.                         (lpListStruct->nLineSize + 1),
  130.                         lpListStruct->nLineSize);
  131.             _lclose (fH);
  132.             return (TRUE);
  133.         }
  134.     }
  135.     return (FALSE);
  136. }
  137.  
  138. //---------------------------------------------------------------------------
  139. // GoToLine
  140. //---------------------------------------------------------------------------
  141. static BOOL NEAR GoToLine (    int         nLine,
  142.                             HWND        hWnd,
  143.                             PFILELIST    lpListStruct) {
  144.  
  145.         RECT rTemp;
  146.  
  147.         // INHIBIT REPAINT
  148.         SendMessage (hWnd,
  149.                     WM_SETREDRAW,
  150.                     (WORD)NULL,
  151.                     (LONG)NULL);
  152.  
  153.         // SCROLL TO TOP
  154.         SendMessage (hWnd,
  155.                     LB_SETTOPINDEX,
  156.                     nLine,
  157.                     (LONG)NULL);
  158.  
  159.         // GET TOP RECTANGLE
  160.         SendMessage (hWnd,
  161.                     LB_GETITEMRECT,
  162.                     nLine,
  163.                     (LONG)(LPRECT)&rTemp);
  164.  
  165.         // CLICK TWICE ON TOP RECTANGLE
  166.         SendMessage (hWnd,
  167.                     WM_LBUTTONDOWN,
  168.                     (WORD)NULL,
  169.                     MAKELONG (rTemp.left, rTemp.top));
  170.         SendMessage (hWnd,
  171.                     WM_LBUTTONUP,
  172.                     (WORD)NULL,
  173.                     MAKELONG (rTemp.left, rTemp.top));
  174.         SendMessage (hWnd,
  175.                     WM_LBUTTONDOWN,
  176.                     (WORD)NULL,
  177.                     MAKELONG (rTemp.left, rTemp.top));
  178.         SendMessage (hWnd,
  179.                     WM_LBUTTONUP,
  180.                     (WORD)NULL,
  181.                     MAKELONG (rTemp.left, rTemp.top));
  182.  
  183.         // REPAINT LISTBOX
  184.         SendMessage (hWnd,
  185.                     WM_SETREDRAW,
  186.                     (WORD)TRUE,
  187.                     (LONG)NULL);
  188.         InvalidateRect (hWnd, (LPRECT)NULL, TRUE);
  189.  
  190.         // SAVE NEW POSITIONS
  191.         lpListStruct->nCurrPos = nLine;
  192.  
  193.         return (TRUE);
  194. }
  195.  
  196. //---------------------------------------------------------------------------
  197. // FindString
  198. //---------------------------------------------------------------------------
  199. static BOOL NEAR FindString (LPSTR        lpString,
  200.                              HWND        hWnd,
  201.                              PFILELIST    lpListStruct) {
  202.  
  203.     static char szInString    [LINE_SIZE + 1];
  204.     static char szOutString [LINE_SIZE + 1];
  205.     LPSTR        lpFileName;
  206.     int            fH;
  207.  
  208.     // GET FILE NAME
  209.     lpFileName = VBDerefHsz (lpListStruct->hFileName);
  210.  
  211.     // OPEN FILE
  212.     if ((fH = _lopen (lpFileName, OF_READ )) != -1) {
  213.         int  n, nLastLine;
  214.  
  215.         // GET NUMBER OF LINES
  216.         nLastLine = _llseek (fH, 0L, 2) / lpListStruct->nLineSize;
  217.         for (n = 0; n <= nLastLine; ++n) {
  218.  
  219.             // GO TO NEXT LINE
  220.             _llseek (fH, (LONG)(n * lpListStruct->nLineSize), 0);
  221.             _lread (fH,
  222.                     (LPSTR)szInString,
  223.                     lpListStruct->nLineSize);
  224.             lstrcpy (szOutString,
  225.                      DisplayLine ((LPSTR)szInString,
  226.                                   (LPSTR)szOutString,
  227.                                    lpListStruct,
  228.                                    LINE_SIZE));
  229.  
  230.             if (_fstrnicmp (szOutString, lpString, lstrlen (lpString)) == 0) {
  231.                 _lclose (fH);
  232.                 return (GoToLine (n, hWnd, lpListStruct));
  233.             }
  234.         }
  235.         _lclose (fH);
  236.     }
  237.     return (FALSE);
  238.  
  239.  
  240. }
  241.  
  242. //---------------------------------------------------------------------------
  243. // VerifyString
  244. //---------------------------------------------------------------------------
  245. static LPSTR NEAR VerifyString (LPSTR        lpString,
  246.                                 HWND        hWnd,
  247.                                  PFILELIST    lpListStruct) {
  248.  
  249.     static char szInString    [LINE_SIZE + 1];
  250.     static char szOutString [LINE_SIZE + 1];
  251.     LPSTR        lpFileName;
  252.     int            fH;
  253.  
  254.     // GET FILE NAME
  255.     lpFileName = VBDerefHsz (lpListStruct->hFileName);
  256.  
  257.     // OPEN FILE
  258.     if ((fH = _lopen (lpFileName, OF_READ )) != -1) {
  259.         int  n, nLastLine;
  260.  
  261.         // GET NUMBER OF LINES
  262.         nLastLine = _llseek (fH, 0L, 2) / lpListStruct->nLineSize;
  263.         for (n = 0; n <= nLastLine; ++n) {
  264.  
  265.             // GO TO NEXT LINE
  266.             _llseek (fH, (LONG)(n * lpListStruct->nLineSize), 0);
  267.  
  268.             // LOOP OVER ALL LINES OF TEXT
  269.             _lread (fH,
  270.                     (LPSTR)szInString,
  271.                     lpListStruct->nLineSize);
  272.             lstrcpy (szOutString,
  273.                     InputLine ((LPSTR)szInString,
  274.                                (LPSTR)szOutString,
  275.                                lpListStruct,
  276.                                LINE_SIZE));
  277.  
  278.             if (_fstrnicmp (szOutString, lpString, lstrlen (szOutString)) == 0) {
  279.                 LONG lCurr;
  280.                 // OBTAIN OUTPUT STRING
  281.                 lCurr = _llseek (fH, 0l, 1);
  282.                 _llseek (fH, lCurr - lpListStruct->nLineSize, 0);
  283.                 _lread (fH,
  284.                          (LPSTR)szInString,
  285.                          lpListStruct->nLineSize);
  286.                 lstrcpy (szOutString,
  287.                         OutputLine ((LPSTR)szInString,
  288.                                        (LPSTR)szOutString,
  289.                                      lpListStruct,
  290.                                      LINE_SIZE));
  291.                 _lclose (fH);
  292.                 return ((LPSTR)szOutString);
  293.             }
  294.         }
  295.         _lclose (fH);
  296.     }
  297.     return ((LPSTR)NULL);
  298.  
  299. }
  300.  
  301. //---------------------------------------------------------------------------
  302. // LocateString
  303. //---------------------------------------------------------------------------
  304. static LPSTR NEAR LocateString (LPSTR        lpString,
  305.                                 HWND        hWnd,
  306.                                  PFILELIST    lpListStruct) {
  307.  
  308.     static char szInString    [LINE_SIZE + 1];
  309.     static char szOutString [LINE_SIZE + 1];
  310.     LPSTR        lpFileName;
  311.     int            fH;
  312.  
  313.     // GET FILE NAME
  314.     lpFileName = VBDerefHsz (lpListStruct->hFileName);
  315.  
  316.     // OPEN FILE
  317.     if ((fH = _lopen (lpFileName, OF_READ )) != -1) {
  318.         int  n, nLastLine;
  319.  
  320.         // GET NUMBER OF LINES
  321.         nLastLine = _llseek (fH, 0L, 2) / lpListStruct->nLineSize;
  322.         for (n = 0; n <= nLastLine; ++n) {
  323.  
  324.             // GO TO NEXT LINE
  325.             _llseek (fH, (LONG)(n * lpListStruct->nLineSize), 0);
  326.  
  327.             // LOOP OVER ALL LINES OF TEXT
  328.             _lread (fH,
  329.                     (LPSTR)szInString,
  330.                     lpListStruct->nLineSize);
  331.             lstrcpy (szOutString,
  332.                     InputLine ((LPSTR)szInString,
  333.                                (LPSTR)szOutString,
  334.                                lpListStruct,
  335.                                LINE_SIZE));
  336.  
  337.             if (_fstrnicmp (szOutString, lpString, lstrlen (szOutString)) == 0) {
  338.                 LONG lCurr;
  339.                 // OBTAIN OUTPUT STRING
  340.                 lCurr = _llseek (fH, 0l, 1);
  341.                 _llseek (fH, lCurr - lpListStruct->nLineSize, 0);
  342.                 _lread (fH,
  343.                          (LPSTR)szInString,
  344.                          lpListStruct->nLineSize);
  345.                 lstrcpy (szOutString,
  346.                         OutputLine ((LPSTR)szInString,
  347.                                        (LPSTR)szOutString,
  348.                                      lpListStruct,
  349.                                      LINE_SIZE));
  350.                 _lclose (fH);
  351.                 GoToLine (n, hWnd, lpListStruct);
  352.                 return ((LPSTR)szOutString);
  353.             }
  354.         }
  355.         _lclose (fH);
  356.     }
  357.     return ((LPSTR)NULL);
  358.  
  359. }
  360.  
  361. //---------------------------------------------------------------------------
  362. // GetListLine
  363. //---------------------------------------------------------------------------
  364. static LPSTR NEAR GetListLine (    int         nLine,
  365.                                 PFILELIST     lpListStruct) {
  366.  
  367.     if (
  368.         (nLine < lpListStruct->nStartLine) ||
  369.         (nLine > lpListStruct->nEndLine)
  370.        ) {
  371.  
  372.         int nStartLine,
  373.             nPage;
  374.  
  375.         // NEED TO GET NEW STAFF INTO THE BUFFER
  376.         nPage      = (nLine - 1) / lpListStruct->nLineSize;
  377.         nStartLine = nPage * lpListStruct->nLineSize;
  378.         if (FillBuffer (nStartLine, lpListStruct)) {
  379.  
  380.             return (lpListStruct->lpListBuffer +
  381.                     (nLine - lpListStruct->nStartLine) *
  382.                     (lpListStruct->nLineSize + 1));
  383.         } else
  384.             return (FALSE);
  385.     }
  386.  
  387.     return (lpListStruct->lpListBuffer +
  388.             (nLine - lpListStruct->nStartLine) *
  389.             (lpListStruct->nLineSize + 1));
  390. }
  391.  
  392. //---------------------------------------------------------------------------
  393. // ItemStatus
  394. //---------------------------------------------------------------------------
  395. BOOL ItemStatus (HCTL hctl,
  396.                  HWND hWnd,
  397.                  int  nItemId) {
  398.  
  399.     DATASTRUCT  ds;
  400.     BOOL        bRet = RESET_MASK;
  401.     int         n, nGrayIndex, nSelectIndex;
  402.  
  403.     ds.cindex               = 1;
  404.     ds.index[0].datatype    = DT_SHORT;
  405.  
  406.     // LOOP OVER ALL GRAY INDEXES (NON-SELECTABLE ITEMS)
  407.     n = 0;
  408.     while (n < ARRMAX) {
  409.  
  410.         // GET nth GRAY FILELIST ITEM
  411.         ds.index[0].data        = n++;
  412.         VBGetControlProperty (hctl, IPROP_FILELIST_LISTGRAY, &ds);
  413.  
  414.         if ((nGrayIndex = LOWORD (ds.data)) == nItemId) {
  415.  
  416.             bRet = GRAY_MASK;
  417.  
  418.             // FIND OUT IF ITEMID IN GRAY FILELIST IS ALSO SELECTED
  419.             n = 0;
  420.             while (n < ARRMAX) {
  421.  
  422.                 // GET nth SELECT FILELIST ITEM
  423.                 ds.index[0].data        = n++;
  424.                 VBGetControlProperty (hctl, IPROP_FILELIST_LISTSELECT, &ds);
  425.                 if ((nSelectIndex = LOWORD (ds.data)) == nItemId) {
  426.                     bRet |= SELECT_MASK;
  427.                     return (bRet);
  428.                 } else if (nSelectIndex == -1)
  429.                     return (bRet);
  430.  
  431.             }
  432.             return (bRet);
  433.  
  434.         } else if (nGrayIndex == -1) {
  435.  
  436.             // IF GRAY LIST IS EXHAUSTED RETURN
  437.             bRet = RESET_MASK;
  438.  
  439.             // FIND OUT IF ITEMID NOT IN GRAY LIST IS SELECTED
  440.             n = 0;
  441.             while (n < ARRMAX) {
  442.  
  443.                 // GET nth SELECT FILELIST ITEM
  444.                 ds.index[0].data        = n++;
  445.                 VBGetControlProperty (hctl, IPROP_FILELIST_LISTSELECT, &ds);
  446.                 if ((nSelectIndex = LOWORD (ds.data)) == nItemId) {
  447.                     bRet |= SELECT_MASK;
  448.                     return (bRet);
  449.                 } else if (nSelectIndex == -1)
  450.                     return (bRet);
  451.  
  452.             }
  453.             return (bRet);
  454.  
  455.         }
  456.     }
  457.     return (bRet);
  458. }
  459.  
  460. //---------------------------------------------------------------------------
  461. // SpillItem
  462. //---------------------------------------------------------------------------
  463. BOOL SpillItem (HCTL          hctl,
  464.                 HWND          hWnd,
  465.                 LONG          lParam,
  466.                 PFILELIST     lpListStruct) {
  467.  
  468.     LONG         n;
  469.     LPDATASTRUCT lpDs = (LPDATASTRUCT) lParam;
  470.     LPSTR        lpString;
  471.     static char  szString [LINE_SIZE + 1];
  472.  
  473.     // GET CURRENT INDEX
  474.     n = lpDs->index [0].data;
  475.     if (
  476.         (n < 0)                             ||
  477.         (n > GetFileLength (lpListStruct))
  478.        ) {
  479.  
  480.         lpDs->data = (LONG)(HSZ)NULL;
  481.         return (381);
  482.  
  483.     } else {
  484.         lpString   = GetListLine (LOWORD(n), lpListStruct);
  485.  
  486.         // PERFORM OUTPUT CONVERSION
  487.         lstrcpy ((LPSTR)szString, lpString);
  488.         lpString = OutputLine (lpString,
  489.                                (LPSTR)szString,
  490.                                lpListStruct,
  491.                                LINE_SIZE);
  492.  
  493.         if (lstrlen (lpString))
  494.             lpDs->data = (LONG) VBCreateHsz ((_segment) hctl, lpString);
  495.         else
  496.             lpDs->data = (LONG) VBCreateHsz ((_segment) hctl, (LPSTR)" ");
  497.         return (FALSE);
  498.     }
  499. }
  500.  
  501.  
  502. //---------------------------------------------------------------------------
  503. // CheckItem
  504. //---------------------------------------------------------------------------
  505. BOOL CheckItem (HCTL             hctl,
  506.                 HWND             hWnd,
  507.                 LPDRAWITEMSTRUCT lpDis,
  508.                 PFILELIST        lpListStruct) {
  509.     BOOL bStat;
  510.  
  511.     if (
  512.         (lpDis->itemID != -1)             &&
  513.         (lpDis->itemAction == ODA_SELECT)
  514.        ) {
  515.           if ((bStat = ItemStatus (hctl, hWnd, lpDis->itemID)) & GRAY_MASK) {
  516.  
  517.             if (lpDis->itemState == ODS_SELECTED) {
  518.                 PostMessage (hWnd,
  519.                              LB_SETSEL,
  520.                              0,
  521.                              (LONG)lpDis->itemID);
  522.                 MessageBeep (0);
  523.                 return (FALSE);
  524.             } else if (
  525.                      (lpDis->itemState == ODS_DISABLED) ||
  526.                      (lpDis->itemState == 0)
  527.                     ) {
  528.                 PostMessage (hWnd,
  529.                              LB_SETSEL,
  530.                              1,
  531.                              (LONG)lpDis->itemID);
  532.                 MessageBeep (0);
  533.                 return (FALSE);
  534.             }
  535.  
  536.         } else if (lpDis->itemState == ODS_SELECTED) {
  537.             int nSel;
  538.  
  539.             nSel = SendMessage (hWnd,
  540.                                 LB_GETSELCOUNT,
  541.                                 NULL,
  542.                                 (LONG)NULL);
  543.             if (nSel > lpListStruct->nMaxSelect) {
  544.                 PostMessage (hWnd,
  545.                              LB_SETSEL,
  546.                              0,
  547.                              (LONG)lpDis->itemID);
  548.                 MessageBeep (0);
  549.                 return (FALSE);
  550.             }
  551.         }
  552.     }
  553.        return (TRUE);
  554. }
  555.  
  556. //---------------------------------------------------------------------------
  557. // DisplayLine
  558. //---------------------------------------------------------------------------
  559. static LPSTR NEAR DisplayLine (    LPSTR        lpInputLine,
  560.                                 LPSTR        lpOutputLine,
  561.                                 PFILELIST   lpListStruct,
  562.                                 int            nMaxLineLength) {
  563.  
  564.     static char szString [LINE_SIZE + 1];
  565.     LPSTR        lpString;
  566.     int            n, m;
  567.  
  568.     // INITIALIZE STRING TO ORIGINAL
  569.     *lpOutputLine = *lpInputLine;
  570.  
  571.     for (n = 0; n < COLMAX; ++n) {
  572.  
  573.         // COPY ON TEMPORARY STRING
  574.         lstrcpy ((LPSTR)szString, lpInputLine);
  575.  
  576.         // EXIT WHEN -1 FOUND
  577.         if (lpListStruct->nDisplayCol [n] == -1)
  578.             break;
  579.         else {
  580.  
  581.             // INITIALLY RESET EVERYTHING
  582.             if (!n)
  583.                 lstrcpy (lpOutputLine, (LPSTR)"");
  584.  
  585.             lpString = _fstrtok ((LPSTR)szString, (LPSTR)" ,\r\t\n");
  586.             for (m = 1; m < lpListStruct->nDisplayCol [n]; ++m) {
  587.                 if (!(lpString = _fstrtok (NULL, (LPSTR)" ,\r\t\n")))
  588.                     break;
  589.             }
  590.  
  591.             if (lpString) {
  592.                 if (n) {
  593.                     if ((lstrlen (lpOutputLine) + 1) <= nMaxLineLength)
  594.                         lstrcat (lpOutputLine, " ");
  595.                     if ((lstrlen (lpOutputLine) + lstrlen (lpString)) <= nMaxLineLength)
  596.                         lstrcat (lpOutputLine, lpString);
  597.                 } else {
  598.                     if (lstrlen (lpString) <= nMaxLineLength)
  599.                         lstrcpy (lpOutputLine, lpString);
  600.                 }
  601.             }
  602.         }
  603.  
  604.     }
  605.     return (lpOutputLine);
  606.  
  607. }
  608.  
  609. //---------------------------------------------------------------------------
  610. // OutputLine
  611. //---------------------------------------------------------------------------
  612. static LPSTR NEAR OutputLine (    LPSTR        lpInputLine,
  613.                                 LPSTR        lpOutputLine,
  614.                                 PFILELIST   lpListStruct,
  615.                                 int            nMaxLineLength) {
  616.  
  617.     static char szString [LINE_SIZE + 1];
  618.     LPSTR        lpString;
  619.     int            n, m;
  620.  
  621.     // INITIALIZE STRING TO ORIGINAL
  622.     *lpOutputLine = *lpInputLine;
  623.  
  624.     for (n = 0; n < COLMAX; ++n) {
  625.  
  626.         // COPY ON TEMPORARY STRING
  627.         lstrcpy ((LPSTR)szString, lpInputLine);
  628.  
  629.         // EXIT WHEN -1 FOUND
  630.         if (lpListStruct->nOutputCol [n] == -1)
  631.             break;
  632.         else {
  633.  
  634.             // INITIALLY RESET EVERYTHING
  635.             if (!n)
  636.                 lstrcpy (lpOutputLine, (LPSTR)"");
  637.  
  638.             lpString = _fstrtok ((LPSTR)szString, (LPSTR)" ,\r\t\n");
  639.             for (m = 1; m < lpListStruct->nOutputCol [n]; ++m) {
  640.                 if (!(lpString = _fstrtok (NULL, (LPSTR)" ,\r\t\n")))
  641.                     break;
  642.             }
  643.  
  644.             if (lpString) {
  645.                 if (n) {
  646.                     if ((lstrlen (lpOutputLine) + 1) <= nMaxLineLength)
  647.                         lstrcat (lpOutputLine, " ");
  648.                     if ((lstrlen (lpOutputLine) + lstrlen (lpString)) <= nMaxLineLength)
  649.                         lstrcat (lpOutputLine, lpString);
  650.                 } else {
  651.                     if (lstrlen (lpString) <= nMaxLineLength)
  652.                         lstrcpy (lpOutputLine, lpString);
  653.                 }
  654.             }
  655.         }
  656.  
  657.     }
  658.     return (lpOutputLine);
  659.  
  660. }
  661.  
  662.  
  663. //---------------------------------------------------------------------------
  664. // InputLine
  665. //---------------------------------------------------------------------------
  666. static LPSTR NEAR InputLine (    LPSTR        lpInputLine,
  667.                                 LPSTR        lpOutputLine,
  668.                                 PFILELIST   lpListStruct,
  669.                                 int            nMaxLineLength) {
  670.  
  671.     static char szString [LINE_SIZE + 1];
  672.     LPSTR        lpString;
  673.     int            n, m;
  674.  
  675.     // INITIALIZE STRING TO ORIGINAL
  676.     *lpOutputLine = *lpInputLine;
  677.  
  678.     for (n = 0; n < COLMAX; ++n) {
  679.  
  680.         // COPY ON TEMPORARY STRING
  681.         lstrcpy ((LPSTR)szString, lpInputLine);
  682.  
  683.         // EXIT WHEN -1 FOUND
  684.         if (lpListStruct->nInputCol [n] == -1)
  685.             break;
  686.         else {
  687.  
  688.             // INITIALLY RESET EVERYTHING
  689.             if (!n)
  690.                 lstrcpy (lpOutputLine, (LPSTR)"");
  691.  
  692.             lpString = _fstrtok ((LPSTR)szString, (LPSTR)" ,\r\t\n");
  693.             for (m = 1; m < lpListStruct->nInputCol [n]; ++m) {
  694.                 if (!(lpString = _fstrtok (NULL, (LPSTR)" ,\r\t\n")))
  695.                     break;
  696.             }
  697.  
  698.             if (lpString) {
  699.                 if (n) {
  700.                     if ((lstrlen (lpOutputLine) + 1) <= nMaxLineLength)
  701.                         lstrcat (lpOutputLine, " ");
  702.                     if ((lstrlen (lpOutputLine) + lstrlen (lpString)) <= nMaxLineLength)
  703.                         lstrcat (lpOutputLine, lpString);
  704.                 } else {
  705.                     if (lstrlen (lpString) <= nMaxLineLength)
  706.                         lstrcpy (lpOutputLine, lpString);
  707.                 }
  708.             }
  709.         }
  710.  
  711.     }
  712.     return (lpOutputLine);
  713.  
  714. }
  715.  
  716. //---------------------------------------------------------------------------
  717. // DrawItem
  718. //---------------------------------------------------------------------------
  719. BOOL DrawItem (HCTL             hctl,
  720.                HWND             hWnd,
  721.                LPDRAWITEMSTRUCT lpDis,
  722.                PFILELIST        lpListStruct) {
  723.  
  724.     HBRUSH      hbr;
  725.     LPSTR       lpString;
  726.     static char    szString [LINE_SIZE + 1];
  727.  
  728.     if (lpDis->itemID == -1)
  729.         return (FALSE);
  730.  
  731.     if (lpString = GetListLine (lpDis->itemID, lpListStruct)) {
  732.  
  733.         LONG        lBackColor, lForeColor;
  734.         int         nOldBkMode;
  735.         COLORREF    lOldBkColor, lOldTxColor;
  736.         HDC         hDC;
  737.         HPEN        hPen;
  738.         HBRUSH      hBrush;
  739.         HFONT       hOldFont;
  740.         BOOL        bStat;
  741.  
  742.         #define SYS_COLOR_MASK     0x80000000
  743.         #define NOT_SYS_COLOR_MASK 0x7fffffff
  744.  
  745.         if ((bStat = ItemStatus (hctl, hWnd, lpDis->itemID)) & GRAY_MASK) {
  746.  
  747.             // GET BACKGROUND COLOR FOR GRAYED ITEM
  748.             VBGetControlProperty (hctl, IPROP_FILELIST_BACKCOLORGRAY, &lBackColor);
  749.             if (lBackColor & SYS_COLOR_MASK)
  750.                 lBackColor = GetSysColor (LOWORD (lBackColor & NOT_SYS_COLOR_MASK));
  751.  
  752.             // GET FOREGROUND COLOR FOR GRAYED ITEM
  753.             VBGetControlProperty (hctl, IPROP_FILELIST_FORECOLORGRAY, &lForeColor);
  754.             if (lForeColor & SYS_COLOR_MASK)
  755.                 lForeColor = GetSysColor (LOWORD (lForeColor & NOT_SYS_COLOR_MASK));
  756.  
  757.  
  758.         } else {
  759.  
  760.             // GET BACKGROUND COLOR
  761.             VBGetControlProperty (hctl, IPROP_FILELIST_BACKCOLOR, &lBackColor);
  762.             if (lBackColor & SYS_COLOR_MASK)
  763.                 lBackColor = GetSysColor (LOWORD (lBackColor & NOT_SYS_COLOR_MASK));
  764.  
  765.             // GET FOREGROUND COLOR
  766.             VBGetControlProperty (hctl, IPROP_FILELIST_FORECOLOR, &lForeColor);
  767.             if (lForeColor & SYS_COLOR_MASK)
  768.                 lForeColor = GetSysColor (LOWORD (lForeColor & NOT_SYS_COLOR_MASK));
  769.  
  770.         }
  771.  
  772.         // SET COLOR IN CHILD WINDOW
  773.         if (!(lpDis->itemState & ODS_SELECTED)) {
  774.  
  775.             // UNSELECTED LINES
  776.             nOldBkMode  = SetBkMode  (lpDis->hDC, TRANSPARENT);
  777.             lOldBkColor = SetBkColor (lpDis->hDC, lBackColor);
  778.             lOldTxColor = SetTextColor (lpDis->hDC, lForeColor);
  779.  
  780.             if (
  781.                 (lpDis->itemAction == ODA_DRAWENTIRE) ||
  782.                 (lpDis->itemAction == ODA_SELECT)
  783.                ) {
  784.  
  785.                 if (hBrush = CreateSolidBrush (lBackColor)) {
  786.                     FillRect (lpDis->hDC, (LPRECT)&lpDis->rcItem, hBrush);
  787.                     DeleteObject (hBrush);
  788.                 }
  789.  
  790.                 // CONVERT STRING TO SELECTED COLUMNS
  791.                 lstrcpy ((LPSTR)szString, lpString);
  792.                 lpString = DisplayLine (lpString,
  793.                                         (LPSTR)szString,
  794.                                         lpListStruct,
  795.                                         LINE_SIZE);
  796.  
  797.                  if (lstrlen (lpString)) {
  798.  
  799.                     if (lpListStruct->hFont) {
  800.                         hOldFont = SelectObject (lpDis->hDC, lpListStruct->hFont);
  801.                         TextOut (lpDis->hDC,
  802.                                 lpDis->rcItem.left,
  803.                                 lpDis->rcItem.top,
  804.                                 lpString,
  805.                                 min (lpListStruct->nLineSize, lstrlen (lpString)));
  806.                         SelectObject (lpDis->hDC, hOldFont);
  807.                     } else
  808.                         TextOut (lpDis->hDC,
  809.                                 lpDis->rcItem.left,
  810.                                 lpDis->rcItem.top,
  811.                                 lpString,
  812.                                 min (lpListStruct->nLineSize, lstrlen (lpString)));
  813.  
  814.                 }
  815.  
  816.             } else {
  817.                 if (hPen = CreatePen (PS_DOT, 1, lForeColor)) {
  818.                     HPEN hOldPen;
  819.  
  820.                     hOldPen = SelectObject (lpDis->hDC, hPen);
  821.                     DrawFocusRect (lpDis->hDC, (LPRECT)&lpDis->rcItem);
  822.  
  823.                     SelectObject (lpDis->hDC, hOldPen);
  824.                     DeleteObject (hPen);
  825.                 }
  826.             }
  827.  
  828.             SetBkMode  (lpDis->hDC,   nOldBkMode);
  829.             SetBkColor (lpDis->hDC,   lOldBkColor);
  830.             SetTextColor (lpDis->hDC, lOldTxColor);
  831.  
  832.         } else {
  833.  
  834.             // SELECTED LINES
  835.             nOldBkMode  = SetBkMode  (lpDis->hDC, TRANSPARENT);
  836.             lOldBkColor = SetBkColor (lpDis->hDC, lForeColor);
  837.             lOldTxColor = SetTextColor (lpDis->hDC, lBackColor);
  838.  
  839.             if (
  840.                 (lpDis->itemAction == ODA_DRAWENTIRE) ||
  841.                 (lpDis->itemAction == ODA_SELECT)
  842.                ) {
  843.                 if (hBrush = CreateSolidBrush (lForeColor)) {
  844.                     FillRect (lpDis->hDC, (LPRECT)&lpDis->rcItem, hBrush);
  845.                     DeleteObject (hBrush);
  846.                 }
  847.  
  848.                 // CONVERT STRING TO SELECTED COLUMNS
  849.                 lstrcpy (szString, lpString);
  850.                 lpString = DisplayLine (lpString,
  851.                                         szString,
  852.                                         lpListStruct,
  853.                                         LINE_SIZE);
  854.  
  855.                 if (lstrlen (lpString)) {
  856.  
  857.                     if (lpListStruct->hFont) {
  858.                         hOldFont = SelectObject (lpDis->hDC, lpListStruct->hFont);
  859.                         TextOut (lpDis->hDC,
  860.                                  lpDis->rcItem.left,
  861.                                  lpDis->rcItem.top,
  862.                                  lpString,
  863.                                  min (lpListStruct->nLineSize, lstrlen (lpString)));
  864.                          SelectObject (lpDis->hDC, hOldFont);
  865.                     } else
  866.                         TextOut (lpDis->hDC,
  867.                                  lpDis->rcItem.left,
  868.                                  lpDis->rcItem.top,
  869.                                  lpString,
  870.                                  min (lpListStruct->nLineSize, lstrlen (lpString)));
  871.  
  872.                 }
  873.  
  874.              } else {
  875.                 if (hPen = CreatePen (PS_DOT, 1, lBackColor)) {
  876.                     HPEN hOldPen;
  877.  
  878.                     hOldPen = SelectObject (lpDis->hDC, hPen);
  879.                     DrawFocusRect (lpDis->hDC, (LPRECT)&lpDis->rcItem);
  880.  
  881.                     // SAVE CURRENT POSITION
  882.                     lpListStruct->nCurrPos = lpDis->itemID;
  883.  
  884.                     SelectObject (lpDis->hDC, hOldPen);
  885.                     DeleteObject (hPen);
  886.                 }
  887.             }
  888.  
  889.             SetBkMode  (lpDis->hDC, nOldBkMode);
  890.             SetBkColor (lpDis->hDC, lOldBkColor);
  891.             SetTextColor (lpDis->hDC, lOldTxColor);
  892.  
  893.         }
  894.         return(TRUE);
  895.     }
  896.  
  897.     return(FALSE);
  898. }
  899.  
  900. //---------------------------------------------------------------------------
  901. // List control function
  902. //---------------------------------------------------------------------------
  903. LONG _export FileListCtlProc (    HCTL        hctl,
  904.                                   HWND        hWnd,
  905.                                  USHORT      msg,
  906.                                   USHORT      wp,
  907.                                   LONG        lp) {
  908.  
  909.     LONG        lResult;
  910.     PFILELIST   lpListStruct = FILELISTDEREF(hctl);
  911.  
  912.     // Message pre-processing
  913.     switch( msg ) {
  914.  
  915.         case WM_CREATE: {
  916.             int n;
  917.  
  918.             // INITIALIZE PROPERTIES
  919.             lpListStruct->lBackColorGray = RGB ((BYTE)0xff, (BYTE)0xff, (BYTE)0xff);
  920.             lpListStruct->lForeColorGray = RGB ((BYTE)0, (BYTE)0, (BYTE)0);
  921.             lpListStruct->nMaxSelect     = (LONG)ARRMAX;
  922.             lpListStruct->hWnd           = 0;
  923.             lpListStruct->hFileName      = (HSZ)NULL;
  924.             lpListStruct->hVerifyText    = (HSZ)NULL;
  925.             lpListStruct->nLineSize      = LINE_SIZE;
  926.  
  927.             lpListStruct->hListArray[0]  = (HSZ)NULL;
  928.             for (n = 0; n < ARRMAX; ++n) {
  929.                 lpListStruct->nListGray[n]   = -1;
  930.                 lpListStruct->nListSelect[n] = -1;
  931.             }
  932.  
  933.             for (n = 0; n < COLMAX; ++n) {
  934.                 lpListStruct->nDisplayCol[n] = -1;
  935.                 lpListStruct->nOutputCol[n] = -1;
  936.                 lpListStruct->nInputCol[n] = -1;
  937.             }
  938.  
  939.             // INITIALIZE NON-PROPERTIES
  940.             lpListStruct->hFont                    = 0;
  941.             lpListStruct->nStartLine            = -1;
  942.             lpListStruct->nEndLine                = -1;
  943.             lpListStruct->hListBuffer            = (HANDLE)NULL;
  944.             lpListStruct->lpListBuffer            = (LPSTR)NULL;
  945.             lpListStruct->nCurrPos                = -1;
  946.             lpListStruct->nSearchStringLen         = 0;
  947.             lpListStruct->szSearchString [0]    = 0;
  948.  
  949.         }
  950.         break;
  951.  
  952.         case VBM_GETPROPERTY:
  953.             switch (wp) {
  954.                 case IPROP_FILELIST_LISTARRAY:
  955.                     return (SpillItem (hctl, hWnd, lp, lpListStruct));
  956.  
  957.                 case IPROP_FILELIST_LISTGRAY: {
  958.                     SHORT n;
  959.                     LPDATASTRUCT lpDs = (LPDATASTRUCT) lp;
  960.  
  961.                     n = lpDs->index [0].data;
  962.                     if (
  963.                         (n >= 0)     &&
  964.                         (n < ARRMAX)
  965.                        )
  966.                         lpDs->data = (LONG)lpListStruct->nListGray [n];
  967.                     else
  968.                         return 381L;
  969.                 }
  970.                 break;
  971.  
  972.                 case IPROP_FILELIST_DISPLAYCOL: {
  973.                     SHORT n;
  974.                     LPDATASTRUCT lpDs = (LPDATASTRUCT) lp;
  975.  
  976.                     n = lpDs->index [0].data;
  977.                     if (
  978.                         (n >= 0)     &&
  979.                         (n < COLMAX)
  980.                        )
  981.                         lpDs->data = (LONG)lpListStruct->nDisplayCol [n];
  982.                     else
  983.                         return 381L;
  984.                 }
  985.                 break;
  986.  
  987.                 case IPROP_FILELIST_OUTPUTCOL: {
  988.                     SHORT n;
  989.                     LPDATASTRUCT lpDs = (LPDATASTRUCT) lp;
  990.  
  991.                     n = lpDs->index [0].data;
  992.                     if (
  993.                         (n >= 0)     &&
  994.                         (n < COLMAX)
  995.                        )
  996.                         lpDs->data = (LONG)lpListStruct->nOutputCol [n];
  997.                     else
  998.                         return 381L;
  999.                 }
  1000.                 break;
  1001.  
  1002.                 case IPROP_FILELIST_INPUTCOL: {
  1003.                     SHORT n;
  1004.                     LPDATASTRUCT lpDs = (LPDATASTRUCT) lp;
  1005.  
  1006.                     n = lpDs->index [0].data;
  1007.                     if (
  1008.                         (n >= 0)     &&
  1009.                         (n < COLMAX)
  1010.                        )
  1011.                         lpDs->data = (LONG)lpListStruct->nInputCol [n];
  1012.                     else
  1013.                         return 381L;
  1014.                 }
  1015.                 break;
  1016.  
  1017.                 case IPROP_FILELIST_LISTSELECT: {
  1018.                     SHORT n;
  1019.                     LPDATASTRUCT lpDs = (LPDATASTRUCT) lp;
  1020.  
  1021.                     n = lpDs->index [0].data;
  1022.                     if (
  1023.                         (n >= 0)     &&
  1024.                         (n < ARRMAX)
  1025.                        )
  1026.                         lpDs->data = (LONG)lpListStruct->nListSelect [n];
  1027.                     else
  1028.                         return 381L;
  1029.                 }
  1030.                 break;
  1031.             }
  1032.             break;
  1033.  
  1034.         case VBM_SETPROPERTY:
  1035.             switch (wp) {
  1036.                 case IPROP_FILELIST_FONTNAME:
  1037.                 case IPROP_FILELIST_FONTSIZE:
  1038.                 case IPROP_FILELIST_FONTBOLD:
  1039.                 case IPROP_FILELIST_FONTITALIC:
  1040.                 case IPROP_FILELIST_FONTSTRIKE:
  1041.                 case IPROP_FILELIST_FONTUNDER:
  1042.                 case IPROP_FILELIST_BACKCOLOR:
  1043.                 case IPROP_FILELIST_FORECOLOR:
  1044.                 case IPROP_FILELIST_BACKCOLORGRAY:
  1045.                 case IPROP_FILELIST_FORECOLORGRAY:
  1046.                     InvalidateRect (hWnd, NULL, TRUE);
  1047.                     break;
  1048.  
  1049.                 case IPROP_FILELIST_MAXSELECT:
  1050.                     lpListStruct->nMaxSelect = LOWORD (lp);
  1051.                     break;
  1052.  
  1053.                 case IPROP_FILELIST_HWND:
  1054.                     lpListStruct->hWnd = LOWORD (lp);
  1055.                     break;
  1056.  
  1057.                 case IPROP_FILELIST_LINESIZE:
  1058.                     if (LOWORD (lp) > LINE_SIZE) {
  1059.                         return (380);
  1060.                     }
  1061.                     lpListStruct->nLineSize = LOWORD (lp);
  1062.                     break;
  1063.  
  1064.                 case IPROP_FILELIST_VERIFYTEXT:
  1065.                     if (lstrlen ((LPSTR)lp)) {
  1066.                         LPSTR lpStr;
  1067.  
  1068.                         if (lpStr = VerifyString ((LPSTR)lp, hWnd, lpListStruct))
  1069.                             lpListStruct->hVerifyText = VBCreateHsz (
  1070.                                                         (_segment)hctl,
  1071.                                                         lpStr);
  1072.                         else
  1073.                             return (380);
  1074.                     }
  1075.  
  1076.                     break;
  1077.  
  1078.  
  1079.                 case IPROP_FILELIST_LOCATETEXT:
  1080.                     if (lstrlen ((LPSTR)lp)) {
  1081.                         LPSTR lpStr;
  1082.  
  1083.                         if (lpStr = LocateString ((LPSTR)lp, hWnd, lpListStruct))
  1084.                             lpListStruct->hLocateText = VBCreateHsz (
  1085.                                                         (_segment)hctl,
  1086.                                                         lpStr);
  1087.                         else
  1088.                             return (380);
  1089.                     }
  1090.  
  1091.                     break;
  1092.  
  1093.                 case IPROP_FILELIST_FILENAME: {
  1094.                     if (lstrlen ((LPSTR)lp)) {
  1095.                         int     n,
  1096.                                 nLastLine,
  1097.                                 nOffSet;
  1098.                         LPSTR     lpListBuffer;
  1099.  
  1100.  
  1101.                         lpListStruct->hFileName = VBCreateHsz ((_segment)hctl,
  1102.                                                                    (LPSTR)lp);
  1103.  
  1104.                         // NOW FILL LIST BOX WITH EMPTY STRINGS
  1105.                         SendMessage (    hWnd,
  1106.                                         LB_RESETCONTENT,
  1107.                                          (WORD)NULL,
  1108.                                          (LONG)NULL);
  1109.  
  1110.                         nLastLine = GetFileLength (lpListStruct);
  1111.                         for (n = 0; n < nLastLine; ++n)
  1112.                             SendMessage (hWnd,
  1113.                                          LB_ADDSTRING,
  1114.                                           (WORD)NULL,
  1115.                                           (LONG)(LPSTR)" ");
  1116.  
  1117.                     }
  1118.                 }
  1119.                 break;
  1120.  
  1121.                 case IPROP_FILELIST_LISTGRAY: {
  1122.                     SHORT n;
  1123.                     LPDATASTRUCT lpDs = (LPDATASTRUCT) lp;
  1124.  
  1125.                     n = lpDs->index [0].data;
  1126.                     if (
  1127.                         (n >= 0)     &&
  1128.                         (n < ARRMAX)
  1129.                        )
  1130.                         lpListStruct->nListGray [n] = (SHORT)lpDs->data;
  1131.                     else
  1132.                         return 381L;
  1133.                 }
  1134.                 break;
  1135.  
  1136.                 case IPROP_FILELIST_DISPLAYCOL: {
  1137.                     SHORT n;
  1138.                     LPDATASTRUCT lpDs = (LPDATASTRUCT) lp;
  1139.  
  1140.                     n = lpDs->index [0].data;
  1141.                     if (
  1142.                         (n >= 0)     &&
  1143.                         (n < COLMAX)
  1144.                        )
  1145.                         lpListStruct->nDisplayCol [n] = (SHORT)lpDs->data;
  1146.                     else
  1147.                         return 381L;
  1148.                 }
  1149.                 break;
  1150.  
  1151.                 case IPROP_FILELIST_OUTPUTCOL: {
  1152.                     SHORT n;
  1153.                     LPDATASTRUCT lpDs = (LPDATASTRUCT) lp;
  1154.  
  1155.                     n = lpDs->index [0].data;
  1156.                     if (
  1157.                         (n >= 0)     &&
  1158.                         (n < COLMAX)
  1159.                        )
  1160.                         lpListStruct->nOutputCol [n] = (SHORT)lpDs->data;
  1161.                     else
  1162.                         return 381L;
  1163.                 }
  1164.                 break;
  1165.  
  1166.                 case IPROP_FILELIST_INPUTCOL: {
  1167.                     SHORT n;
  1168.                     LPDATASTRUCT lpDs = (LPDATASTRUCT) lp;
  1169.  
  1170.                     n = lpDs->index [0].data;
  1171.                     if (
  1172.                         (n >= 0)     &&
  1173.                         (n < COLMAX)
  1174.                        )
  1175.                         lpListStruct->nInputCol [n] = (SHORT)lpDs->data;
  1176.                     else
  1177.                         return 381L;
  1178.                 }
  1179.                 break;
  1180.  
  1181.                 case IPROP_FILELIST_LISTSELECT: {
  1182.                     SHORT n, nCount, nSel;
  1183.                     LPDATASTRUCT lpDs = (LPDATASTRUCT) lp;
  1184.  
  1185.                     n = lpDs->index [0].data;
  1186.                     if (
  1187.                         (n >= 0)     &&
  1188.                         (n < ARRMAX)
  1189.                        ) {
  1190.  
  1191.                         // SELECT ITEM IN FILELIST
  1192.                         nCount = SendMessage (hWnd,
  1193.                                               LB_GETCOUNT,
  1194.                                               NULL,
  1195.                                               (LONG)NULL);
  1196.                         nSel = SendMessage (hWnd,
  1197.                                             LB_GETSELCOUNT,
  1198.                                             NULL,
  1199.                                             (LONG)NULL);
  1200.                         if ((SHORT)lpDs->data == -1) {
  1201.  
  1202.                             // REMOVE SELECTION
  1203.                             if (lpListStruct->nListSelect [n] >= 0) {
  1204.                                 int nSel;
  1205.  
  1206.                                 SendMessage (hWnd,
  1207.                                             LB_SETSEL,
  1208.                                             0,
  1209.                                             (LONG)lpListStruct->nListSelect [n]);
  1210.  
  1211.                                 SendMessage (hWnd,
  1212.                                              LB_GETSELITEMS,
  1213.                                               ARRMAX,
  1214.                                               (LONG)(LPSTR)lpListStruct->nListSelect);
  1215.                                 nSel = SendMessage (hWnd,
  1216.                                              LB_GETSELCOUNT,
  1217.                                              NULL,
  1218.                                              (LONG)NULL);
  1219.                                 lpListStruct->nListSelect [nSel] = -1;
  1220.                             }
  1221.  
  1222.                         } else if (
  1223.                             ((SHORT)lpDs->data < nCount) &&
  1224.                             (nSel < lpListStruct->nMaxSelect)
  1225.                            ) {
  1226.  
  1227.                                // ADD SELECTION
  1228.                             lpListStruct->nListSelect [n] = (SHORT)lpDs->data;
  1229.                             if (lpListStruct->nListSelect [n] >= 0)
  1230.                                 SendMessage (hWnd,
  1231.                                             LB_SETSEL,
  1232.                                             1,
  1233.                                             (LONG)lpListStruct->nListSelect [n]);
  1234.                         }
  1235.                     } else
  1236.                         return 381L;
  1237.                 }
  1238.                 break;
  1239.             }
  1240.             break;
  1241.  
  1242.         case VBN_COMMAND:
  1243.             switch (HIWORD (lp)) {
  1244.                 case LBN_SELCHANGE: {
  1245.                     int nSel;
  1246.  
  1247.                     SendMessage (hWnd,
  1248.                                  LB_GETSELITEMS,
  1249.                                  ARRMAX,
  1250.                                  (
  1251.                                  LONG)(LPSTR)lpListStruct->nListSelect);
  1252.                     nSel = SendMessage (hWnd,
  1253.                                         LB_GETSELCOUNT,
  1254.                                         NULL,
  1255.                                         (LONG)NULL);
  1256.                     lpListStruct->nListSelect [nSel] = -1;
  1257.                 }
  1258.                 break;
  1259.  
  1260.             }
  1261.             break;
  1262.  
  1263.         case VBN_DRAWITEM:
  1264.              if (CheckItem (hctl,
  1265.                             hWnd,
  1266.                             (LPDRAWITEMSTRUCT) lp,
  1267.                             lpListStruct))
  1268.                 DrawItem (hctl,
  1269.                           hWnd,
  1270.                           (LPDRAWITEMSTRUCT) lp,
  1271.                           lpListStruct);
  1272.             break;
  1273.  
  1274.         case VBN_MEASUREITEM: {
  1275.  
  1276.             LPMEASUREITEMSTRUCT lpMis;
  1277.             HDC                 hDC;
  1278.             TEXTMETRIC          tTextMetric;
  1279.             HFONT               hOldFont;
  1280.  
  1281.             lpMis    = (LPMEASUREITEMSTRUCT) lp;
  1282.             hDC      = GetDC (hWnd);
  1283.  
  1284.             hOldFont = SelectObject (hDC, lpListStruct->hFont);
  1285.             GetTextMetrics(hDC, &tTextMetric);
  1286.             SelectObject (hDC, hOldFont);
  1287.  
  1288.             ReleaseDC(hWnd, hDC);
  1289.  
  1290.             lpMis->itemHeight = tTextMetric.tmHeight;
  1291.         }
  1292.         break;
  1293.  
  1294.         case WM_SETFONT:
  1295.             lpListStruct->hFont = (HFONT)wp;
  1296.             break;
  1297.  
  1298.         case WM_GETFONT:
  1299.             return (lpListStruct->hFont);
  1300.  
  1301.         case WM_NCDESTROY: {
  1302.             int n = 0;
  1303.  
  1304.             while (lpListStruct->hListArray [n]) {
  1305.                 VBDestroyHsz (lpListStruct->hListArray [n]);
  1306.                 lpListStruct->hListArray [n] = (HSZ)NULL;
  1307.                 ++n;
  1308.             }
  1309.             TeminateListBuffer (lpListStruct);
  1310.         }
  1311.         break;
  1312.  
  1313.         case WM_KEYUP:
  1314.             switch (wp) {
  1315.                 case VK_UP:
  1316.                 case VK_DOWN:
  1317.                 case VK_PRIOR:
  1318.                 case VK_NEXT:
  1319.                 case VK_END:
  1320.                 case VK_HOME:
  1321.                     lpListStruct->nSearchStringLen         = 0;
  1322.                     lpListStruct->szSearchString [0]     = 0;
  1323.                     break;
  1324.             }
  1325.             break;
  1326.  
  1327.        case WM_CHAR: {
  1328.  
  1329.             switch (wp) {
  1330.  
  1331.                 case VK_ESCAPE:
  1332.                     lpListStruct->nSearchStringLen    = 0;
  1333.                     lpListStruct->szSearchString [0] = 0;
  1334.                     GoToLine (0, hWnd, lpListStruct);
  1335.                     break;
  1336.  
  1337.                 case VK_BACK:
  1338.                     if (lpListStruct->nSearchStringLen > 1) {
  1339.                         --lpListStruct->nSearchStringLen;
  1340.                         lpListStruct->szSearchString
  1341.                             [lpListStruct->nSearchStringLen] = 0;
  1342.                         FindString (lpListStruct->szSearchString,
  1343.                                     hWnd,
  1344.                                     lpListStruct);
  1345.                     } else {
  1346.                         lpListStruct->nSearchStringLen   = 0;
  1347.                         lpListStruct->szSearchString [0] = 0;
  1348.                         GoToLine (0, hWnd, lpListStruct);
  1349.                     }
  1350.                     break;
  1351.  
  1352.                 default:
  1353.                     if (isalnum (wp)) {
  1354.                         lpListStruct->szSearchString
  1355.                             [lpListStruct->nSearchStringLen] = wp;
  1356.                         ++lpListStruct->nSearchStringLen;
  1357.                         lpListStruct->szSearchString
  1358.                             [lpListStruct->nSearchStringLen] = 0;
  1359.                         if (!FindString (lpListStruct->szSearchString,
  1360.                                          hWnd, lpListStruct)) {
  1361.                             --lpListStruct->nSearchStringLen;
  1362.                             lpListStruct->szSearchString
  1363.                                 [lpListStruct->nSearchStringLen] = 0;
  1364.                         }
  1365.                     }
  1366.             }
  1367.  
  1368.         }
  1369.         break;
  1370.  
  1371.     }
  1372.     // Default processing:
  1373.     lResult = VBDefControlProc (hctl, hWnd, msg, wp, lp);
  1374.     return lResult;
  1375. }
  1376.