home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / lstbx4.zip / TraffMgr.C < prev    next >
C/C++ Source or Header  |  1994-07-08  |  42KB  |  1,203 lines

  1. #pragma    title("List Box Replacement  --  Version 1.1 -- (TraffMgr.C)")
  2. #pragma    subtitle("   Traffic Manager - Interface Definitions")
  3.  
  4. /* Program name: Listbox.Dll    Title: A List Box Replacement        */
  5. /*                                    */
  6. /* OS/2    Developer Magazine, Issue:  May    '94, page 12                    */
  7. /* Author:  Mark Benge       IBM Corp.                    */
  8. /*        Matt Smith       Prominare Inc.                */
  9. /* Description:     Replacement for OS/2 List Box,    first of a series.    */
  10. /*                                    */
  11. /* Program Requirements:  OS/2 2.x                    */
  12. /*              IBM C    Set++                    */
  13. /*              WATCOM C 386/9.0                */
  14. /*              Borland C++ for OS/2                */
  15. /*              OS/2 Toolkit                    */
  16.  
  17. /* Copyright ╕ International Business Machines Corp. 1991-1994        */
  18. /* Copyright ╕ 1989-1994  Prominare Inc.  All Rights Reserved.        */
  19.  
  20. /************************************************************************/
  21. /************************************************************************/
  22. /*               DISCLAIMER OF WARRANTIES.            */
  23. /************************************************************************/
  24. /************************************************************************/
  25. /*     The following [enclosed]    code is    source code created by the    */
  26. /*     authors.     This source code is  provided to you solely        */
  27. /*     for the purpose of assisting you    in the development of your    */
  28. /*     applications.  The code is provided "AS IS", without        */
  29. /*     warranty    of any kind.  The authors shall    not be liable        */
  30. /*     for any damages arising out of your use of the source code,    */
  31. /*     even if they have been advised of the possibility of such    */
  32. /*     damages.     It is provided    purely for instructional and        */
  33. /*     illustrative purposes.                        */
  34. /************************************************************************/
  35. /************************************************************************/
  36.  
  37. #pragma    info(noext)
  38. #pragma    strings(readonly)
  39.  
  40. #define    INCL_GPI           /* Include OS/2 PM GPI Interface    */
  41. #define    INCL_WIN           /* Include OS/2 PM Windows Interface    */
  42.  
  43. #include <os2.h>
  44. #include <stdlib.h>
  45.  
  46. #include "entryfld.h"
  47. #include "listbox.h"
  48.  
  49. /* This    module contains    the routines that handle the traffic management    */
  50. /* for the list    box.                            */
  51. /*                                    */
  52. /* Equivalent command line invocation of each module using the        */
  53. /* IBM C Set++ Compiler    Version    2.0 is:                    */
  54. /*                                    */
  55. /*     Icc -G3e- -O+ -Rn -C -W3    -FoTraffMgr TraffMgr.C            */
  56.  
  57. /* Filename:   TraffMgr.C                        */
  58.  
  59. /*  Version:   1.1                            */
  60. /*  Created:   1993-10-14                        */
  61. /*  Revised:   1994-04-02                        */
  62.  
  63. /* Routines:   LONG lGetPresParam(HWND hWnd, ULONG ulID1, ULONG    ulID2,    */
  64. /*                  LONG lDefault);            */
  65. /*           VOID SizeListBox(PLISTBOXWIN plbw);            */
  66. /*           VOID FocusChange(PLISTBOXWIN plbw, LONG iFocus,        */
  67. /*                BOOL fSet);                */
  68. /*           VOID SetFocus(PLISTBOXWIN plbw, LONG iFocus);        */
  69. /*           VOID RemoveFocus(PLISTBOXWIN plbw);            */
  70. /*           BOOL fDecodeChkSelect(PLISTBOXWIN plbw, MPARAM mp1);    */
  71. /*           BOOL fDecodeMouse(PLISTBOXWIN plbw, MPARAM mp1);        */
  72. /*           BOOL fDecodeExtendedMouse(PLISTBOXWIN plbw, MPARAM mp1,    */
  73. /*                     BOOL fBlock);            */
  74. /*           VOID MeasureItem(PLISTBOXWIN plbw, LONG lMaxBaselineExt);*/
  75. /*           BOOL fAddHorzScroll(HWND    hWnd, PLISTBOXWIN plbw);    */
  76. /*           VOID LineUp(PLISTBOXWIN plbw);                */
  77. /*           VOID LineDown(PLISTBOXWIN plbw);                */
  78. /*           VOID DragUp(PLISTBOXWIN plbw);                */
  79. /*           VOID DragDown(PLISTBOXWIN plbw);                */
  80.  
  81.  
  82. /* --------------------------------------------------------------------    */
  83.  
  84. #pragma    subtitle("   Traffic Manager - Presentation Parameter Retrieve Procedure")
  85. #pragma    page( )
  86.  
  87. /* --- lGetPresParam ----------------------------------    [ Private } ---    */
  88. /*                                    */
  89. /*     This function is    used to    retrieve a presentation    parameter    */
  90. /*     that may    be present.  If    the presentation parameter is not,    */
  91. /*     the default colour passed to the    function will be used.    All    */
  92. /*     colours queried for are RGB or their RGB    equivalents.        */
  93. /*                                    */
  94. /*     Upon Entry:                            */
  95. /*                                    */
  96. /*     HWND  hWnd;     = Window    Handle                    */
  97. /*     ULONG ulID1;    = Presentation Parameter    1 ID (RGB)        */
  98. /*     ULONG ulID2;    = Presentation Parameter    2 ID (Index)        */
  99. /*     LONG  lDefault; = Default Colour                    */
  100. /*                                    */
  101. /*     Upon Exit:                            */
  102. /*                                    */
  103. /*     lGetPresParam = Colour to Use (RGB)                */
  104. /*                                    */
  105. /* --------------------------------------------------------------------    */
  106.  
  107. LONG lGetPresParam(HWND    hWnd, ULONG ulID1, ULONG ulID2,    LONG lDefault)
  108.  
  109. {
  110. HPS   hPS;               /* Presentation Space Handle        */
  111. LONG  lClr;               /* Presentation Parameter Colour    */
  112. ULONG ulID;               /* Presentation Parameter ID        */
  113.  
  114.                /* First    try to determine if any    presentation    */
  115.                /* parameters are set for the area requested.    */
  116.                /* The first ID is RGB index and    the second ID    */
  117.                /* is colour index.                */
  118.  
  119. if ( WinQueryPresParam(hWnd, ulID1, ulID2, &ulID, sizeof(LONG),    (PVOID)&lClr,
  120.                QPF_NOINHERIT | QPF_ID2COLORINDEX | QPF_PURERGBCOLOR) )
  121.  
  122.                /* Presentation parameter set for the area,    */
  123.                /* return the RGB colour                */
  124.    return(lClr);
  125. else
  126.                /* No presentation parameters set, check    to see    */
  127.                /* if the default is a system colour in which    */
  128.                /* only need to query the index for the RGB    */
  129.                /* value                        */
  130.  
  131.    if (    (lDefault >= SYSCLR_SHADOWHILITEBGND) &&
  132.     (lDefault <= SYSCLR_HELPHILITE)    )
  133.        return(WinQuerySysColor(HWND_DESKTOP, lDefault, 0L));
  134.    else
  135.                /* Standard colour index, get the RGB equivalent    */
  136.                /* for the index                    */
  137.  
  138.        if ( (hPS = WinGetPS(hWnd)) != (HPS)NULL    )
  139.        if (    (lClr =    GpiQueryRGBColor(hPS, LCOLOPT_REALIZED,    lDefault)) == GPI_ALTERROR )
  140.            {
  141.                /* Colour was not found,    return white as    colour    */
  142.  
  143.            WinReleasePS(hPS);
  144.            return(RGB_WHITE);
  145.            }
  146.        else
  147.            {
  148.                /* Colour found,    return the RGB value        */
  149.  
  150.            WinReleasePS(hPS);
  151.            return(lClr);
  152.            }
  153.        else
  154.        return(RGB_WHITE);
  155. }
  156. #pragma    subtitle("   Traffic Manager - List Box Sizing Procedure")
  157. #pragma    page( )
  158.  
  159. /* --- SizeListBox ------------------------------------    [ Private ] ---    */
  160. /*                                    */
  161. /*     This function is    used to    calculate the positions    of the        */
  162. /*     scroll bars that    are part of the    list box as well as the        */
  163. /*     border points that are to be drawn when the control is        */
  164. /*     painted.                                */
  165. /*                                    */
  166. /*     Upon Entry:                            */
  167. /*                                    */
  168. /*     PLISTBOXWIN plbw; = List    Box Control Information    Pointer        */
  169. /*                                    */
  170. /*     Upon Exit:                            */
  171. /*                                    */
  172. /*     Nothing                                */
  173. /*                                    */
  174. /* --------------------------------------------------------------------    */
  175.  
  176. VOID SizeListBox(PLISTBOXWIN plbw)
  177.  
  178. {
  179. LONG  lMargin;               /* Margin Size            */
  180. ULONG cswp;               /* SWP Array    Count            */
  181.  
  182.                /* Initialize the values    for the    list box    */
  183.                /* pertaining to    the number of items in the list    */
  184.                /* box, display line count, etc.            */
  185.  
  186. plbw->cLinesPage = (plbw->rcl.yTop - plbw->rcl.yBottom)    / plbw->cyItem;
  187. if ( (plbw->rcl.yTop - plbw->rcl.yBottom) % plbw->cyItem )
  188.    ++plbw->cLinesPage;
  189.  
  190. if ( plbw->flStyle & LS_NOADJUSTPOS )
  191.    plbw->cy = plbw->cyWindow;
  192. else
  193.    {
  194.    lMargin = 2L    + (plbw->flStyle & LS_HORZSCROLL ? plbw->cyScroll : 2L);
  195.    plbw->cy = ((plbw->cyWindow - lMargin) / plbw->cyItem) * plbw->cyItem + lMargin;
  196.    plbw->rclAdjusted.yTop    = plbw->cyWindow;
  197.    plbw->rclAdjusted.yBottom = plbw->cy;
  198.    plbw->rclAdjusted.xLeft   = 0L;
  199.    plbw->rclAdjusted.xRight  = plbw->cxWindow;
  200.    }
  201.                /* Calculate the    width of the group such    that it    */
  202.                /* is almost the    width of the window and    also    */
  203.                /* calculate the    width of the list box such that    */
  204.                /* it is    almost the width of the    group box    */
  205.  
  206. plbw->aswp[SWP_VERT].x    = (plbw->cx = plbw->cxWindow) -    plbw->cxScroll;
  207. plbw->aswp[SWP_VERT].cy    = plbw->cy;
  208.  
  209. if ( plbw->flStyle & LS_HORZSCROLL )
  210.    {
  211.                /*                   2        */
  212.                /* 1┌────────────────────────────────┬─┐        */
  213.                /*  │                    │^│        */
  214.                /*  │                    ├─┤        */
  215.                /*  │                    │ │        */
  216.                /*  │                    │ │        */
  217.                /*  │                    ├─┤        */
  218.                /*  │                    │v│        */
  219.                /* 0├─┬────────────────────────────┬─┼─┘        */
  220.                /*  │<│                  │>│        */
  221.                /*  └─┴────────────────────────────┴─┘        */
  222.    plbw->cptl =    2L;
  223.    plbw->aptlOutside[0].x = 0L;
  224.    plbw->aptlOutside[0].y = 1L;
  225.    plbw->aptlOutside[1].x = 0L;
  226.    plbw->aptlOutside[1].y = plbw->cy - 1L;
  227.    plbw->aptlOutside[2].x = plbw->aswp[SWP_VERT].x;
  228.    plbw->aptlOutside[2].y = plbw->cy - 1L;
  229.  
  230.    plbw->aptlInside[0].x = 1L;
  231.    plbw->aptlInside[0].y = 0L;
  232.    plbw->aptlInside[1].x = 1L;
  233.    plbw->aptlInside[1].y = plbw->cy - 2L;
  234.    plbw->aptlInside[2].x = plbw->aswp[SWP_VERT].x;
  235.    plbw->aptlInside[2].y = plbw->cy - 2L;
  236.  
  237.    plbw->rcl.yTop    = plbw->cy    - 2L;
  238.    plbw->rcl.yBottom = plbw->aswp[SWP_HORZ].cy;
  239.    plbw->rcl.xRight  = plbw->aswp[SWP_VERT].x;
  240.    plbw->rcl.xLeft   = 2L;
  241.  
  242.    plbw->aswp[SWP_HORZ].cx = plbw->aswp[SWP_VERT].x;;
  243.    plbw->aswp[SWP_VERT].y  = plbw->cyScroll;
  244.    plbw->aswp[SWP_VERT].cy = plbw->cy -    plbw->cyScroll;
  245.    cswp    = 2UL;
  246.    plbw->rclCorner.xLeft   = plbw->aswp[SWP_VERT].x;
  247.    plbw->rclCorner.xRight  = plbw->cx;
  248.    plbw->rclCorner.yBottom = 0L;
  249.    plbw->rclCorner.yTop       = plbw->aswp[SWP_VERT].y;
  250.    }
  251. else
  252.    {
  253.                /*  2                    3        */
  254.                /* 1┌────────────────────────────────┬─┐        */
  255.                /*  │                    │^│        */
  256.                /*  │                    ├─┤        */
  257.                /*  │                    │ │        */
  258.                /*  │                    │ │        */
  259.                /*  │                    ├─┤        */
  260.                /*  │                    │v│        */
  261.                /*  └────────────────────────────────┴─┘        */
  262.                /*  1                    0        */
  263.    plbw->cptl =    3L;
  264.    plbw->aptlOutside[0].x = plbw->aswp[SWP_VERT].x;
  265.    plbw->aptlOutside[0].y = 1L;
  266.    plbw->aptlOutside[1].x = 0L;
  267.    plbw->aptlOutside[1].y = 1L;
  268.    plbw->aptlOutside[2].x = 0L;
  269.    plbw->aptlOutside[2].y = plbw->cy - 1L;
  270.    plbw->aptlOutside[3].x = plbw->aswp[SWP_VERT].x;
  271.    plbw->aptlOutside[3].y = plbw->cy - 1L;
  272.  
  273.    plbw->aptlInside[0].x = plbw->aswp[SWP_VERT].x;
  274.    plbw->aptlInside[0].y = 0L;
  275.    plbw->aptlInside[1].x = 1L;
  276.    plbw->aptlInside[1].y = 0L;
  277.    plbw->aptlInside[2].x = 1L;
  278.    plbw->aptlInside[2].y = plbw->cy - 2L;
  279.    plbw->aptlInside[3].x = plbw->aswp[SWP_VERT].x;
  280.    plbw->aptlInside[3].y = plbw->cy - 2L;
  281.  
  282.    plbw->rcl.yTop    = plbw->cy    - 2L;
  283.    plbw->rcl.yBottom = 2L;
  284.    plbw->rcl.xRight  = plbw->aswp[SWP_VERT].x;
  285.    plbw->rcl.xLeft   = 2L;
  286.    cswp    = 1UL;
  287.    }
  288.                /* Window has been resized, calculate the new    */
  289.                /* values for the number    of lines displayed and    */
  290.                /* the relative number of characters displayed    */
  291.  
  292. plbw->cLinesPage = (plbw->rcl.yTop - plbw->rcl.yBottom)    / plbw->cyItem;
  293. if ( (plbw->rcl.yTop - plbw->rcl.yBottom) % plbw->cyItem )
  294.     ++plbw->cLinesPage;
  295. plbw->cCharsPage = (plbw->rcl.xRight - plbw->rcl.xLeft)    / plbw->xChar;
  296. if ( (plbw->rcl.xRight - plbw->rcl.xLeft) % plbw->xChar    )
  297.     ++plbw->cCharsPage;
  298.                /* Reposition and resize    the controls        */
  299.  
  300. WinSetMultWindowPos(plbw->hAB, plbw->aswp, cswp);
  301.  
  302. }
  303. #pragma    subtitle("   Traffic Manager - Focus Change Routine")
  304. #pragma    page( )
  305.  
  306. /* --- FocusChange ------------------------------------- [ Public ] ---    */
  307. /*                                    */
  308. /*     This function is    used to    draw the focus indicator around    a    */
  309. /*     list box    item.                            */
  310. /*                                    */
  311. /*     Upon Entry:                            */
  312. /*                                    */
  313. /*     PLISTBOXWIN plbw;   = List Box Data Pointer            */
  314. /*     LONG       iFocus; = Focus Item    Index                */
  315. /*                                    */
  316. /*     Upon Exit:                            */
  317. /*                                    */
  318. /*     Nothing                                */
  319. /*                                    */
  320. /* --------------------------------------------------------------------    */
  321.  
  322. VOID FocusChange(PLISTBOXWIN plbw, LONG    iFocus,    BOOL fSet)
  323.  
  324. {
  325. if ( (iFocus < plbw->cItems) &&    plbw->fFocus )
  326.    if (    fSet )
  327.        {
  328.                /* Check    to see if the item receiving the focus    */
  329.                /* is visible in    which case the focus indicator    */
  330.                /* needs    to be drawn for    it            */
  331.  
  332.        if ( fItemVisible(plbw, iFocus) )
  333.        {
  334.        WinCreateCursor(plbw->hWnd, plbw->rcl.xLeft,
  335.                (plbw->rcl.yTop - (iFocus - plbw->iVertScroll) *
  336.                           plbw->cyItem) - plbw->cyItem,
  337.                0L, 0L, CURSOR_SETPOS, NULL);
  338.        if (    !plbw->fFocusShown )
  339.            WinShowCursor(plbw->hWnd, plbw->fFocusShown = TRUE);
  340.        }
  341.        }
  342.    else
  343.                /* Check    to see if the item losing the focus    */
  344.                /* is visible in    which case the focus indicator    */
  345.                /* needs    to be drawn for    it            */
  346.  
  347.        if ( plbw->fFocusShown )
  348.        WinShowCursor(plbw->hWnd, plbw->fFocusShown = FALSE);
  349. }
  350. #pragma    subtitle("   Traffic Manager - Focus Draw Routine")
  351. #pragma    page( )
  352.  
  353. /* --- SetFocus    ---------------------------------------- [ Public ] ---    */
  354. /*                                    */
  355. /*     This function is    used to    draw the focus indicator around    a    */
  356. /*     list box    item.                            */
  357. /*                                    */
  358. /*     Upon Entry:                            */
  359. /*                                    */
  360. /*     PLISTBOXWIN plbw;   = List Box Data Pointer            */
  361. /*     LONG       iFocus; = Focus Item    Index                */
  362. /*                                    */
  363. /*     Upon Exit:                            */
  364. /*                                    */
  365. /*     Nothing                                */
  366. /*                                    */
  367. /* --------------------------------------------------------------------    */
  368.  
  369. VOID SetFocus(PLISTBOXWIN plbw,    LONG iFocus)
  370.  
  371. {
  372. if ( iFocus < plbw->cItems )
  373.    {
  374.                /* Check    to see if the item receiving the focus    */
  375.                /* is visible in    which case the focus indicator    */
  376.                /* needs    to be drawn for    it            */
  377.  
  378.    if (    WinIsWindowShowing(plbw->hWnd) )
  379.        FocusChange(plbw, iFocus, TRUE);
  380.  
  381.    if (    !(plbw->plc[0].apli[iFocus]->fl    & LI_FOCUS) )
  382.        {
  383.                /* Check    to see if a previous item had focus it    */
  384.                /* which    if the case, the item should have its    */
  385.                /* focus    flag cleared                */
  386.  
  387.        if ( plbw->iFocus != LIT_NONE )
  388.        plbw->plc[0].apli[plbw->iFocus]->fl &= ~LI_FOCUS;
  389.  
  390.                /* Set the focus    flag for the item now receiving    */
  391.                /* the focus                    */
  392.  
  393.        plbw->plc[0].apli[plbw->iFocus =    iFocus]->fl |= LI_FOCUS;
  394.        }
  395.    }
  396. }
  397. #pragma    subtitle("   Traffic Manager - Focus Remove Routine")
  398. #pragma    page( )
  399.  
  400. /* --- RemoveFocus ------------------------------------- [ Public ] ---    */
  401. /*                                    */
  402. /*     This function is    used to    draw the focus indicator around    a    */
  403. /*     list box    item.                            */
  404. /*                                    */
  405. /*     Upon Entry:                            */
  406. /*                                    */
  407. /*     PLISTBOXWIN plbw; = List    Box Data Pointer            */
  408. /*                                    */
  409. /*     Upon Exit:                            */
  410. /*                                    */
  411. /*     Nothing                                */
  412. /*                                    */
  413. /* --------------------------------------------------------------------    */
  414.  
  415. VOID RemoveFocus(PLISTBOXWIN plbw)
  416.  
  417. {
  418.  
  419. if ( plbw->iFocus != LIT_NONE )
  420.    {
  421.    plbw->plc[0].apli[plbw->iFocus]->fl &= ~LI_FOCUS;
  422.    FocusChange(plbw, plbw->iFocus, FALSE);
  423.    }
  424. }
  425. #pragma    subtitle("   Traffic Manager - Mouse Position Decode Routine")
  426. #pragma    page( )
  427.  
  428. /* --- fCreateEditArea --------------------------------    [ Private ] ---    */
  429. /*                                    */
  430. /*     This function is    used to    determine if the current location of    */
  431. /*     the mouse within    the list box is    over a valid entry and to    */
  432. /*     create the direct editing entry field window.            */
  433. /*                                    */
  434. /*     Upon Entry:                            */
  435. /*                                    */
  436. /*     PLISTBOXWIN plbw; = List    Box Data Pointer            */
  437. /*     MPARAM       mp1;     = Message Parameter 1                */
  438. /*                                    */
  439. /*     Upon Exit:                            */
  440. /*                                    */
  441. /*     fCreateEditArea =  TRUE : Edit Area Created            */
  442. /*               = FALSE : Mouse Pointer outside Edit Area    */
  443. /*                                    */
  444. /* --------------------------------------------------------------------    */
  445.  
  446. BOOL fCreateEditArea(PLISTBOXWIN plbw, MPARAM mp1)
  447.  
  448. {
  449. POINTL ptl;               /* Display Point            */
  450.  
  451. ptl.x =    (LONG)SHORT1FROMMP(mp1);
  452. ptl.y =    (LONG)SHORT2FROMMP(mp1);
  453. if ( WinPtInRect(plbw->hAB, &plbw->rcl,    &ptl) )
  454.    {
  455.    if (    (plbw->iEditing    = lItemFromPoint(plbw, (LONG)SHORT2FROMMP(mp1))) != plbw->iFocus )
  456.        RemoveFocus(plbw);
  457.  
  458.    if (    (plbw->hwndEdit    = WinCreateWindow(plbw->hWnd, CLASS_ENTRYFIELD,    plbw->plc[0].apli[plbw->iEditing]->pszText,
  459.                       WS_VISIBLE | ES_LEFT | ES_AUTOSCROLL,
  460.                       plbw->xTextOffset, plbw->rcl.yTop - ((plbw->iEditing - plbw->iVertScroll + 1)    * plbw->cyItem),
  461.                       plbw->rcl.xRight - plbw->rcl.xLeft - plbw->xTextOffset, plbw->cyItem,
  462.                       plbw->hWnd, HWND_TOP,    512UL,
  463.                       (PVOID)NULL, (PVOID)NULL)) !=    (HWND)NULL )
  464.        {
  465.        WinSetFocus(HWND_DESKTOP, plbw->hwndEdit);
  466.        return(TRUE);
  467.        }
  468.    else
  469.        return(FALSE);
  470.    }
  471. return(FALSE);
  472. }
  473. #pragma    subtitle("   Traffic Manager - Mouse Position Decode Routine")
  474. #pragma    page( )
  475.  
  476. /* --- fDecodeChkSelect    -------------------------------    [ Private ] ---    */
  477. /*                                    */
  478. /*     This function is    used to    determine if the current location of    */
  479. /*     the mouse within    the list box is    over a valid entry and to    */
  480. /*     either select or    deselect the item.                */
  481. /*                                    */
  482. /*     Upon Entry:                            */
  483. /*                                    */
  484. /*     PLISTBOXWIN plbw; = List    Box Data Pointer            */
  485. /*     MPARAM       mp1;     = Message Parameter 1                */
  486. /*                                    */
  487. /*     Upon Exit:                            */
  488. /*                                    */
  489. /*     fDecodeChkSelect    =  TRUE    : Mouse    Pointer    within List Area    */
  490. /*            = FALSE    : Mouse    Pointer    outside    List Area    */
  491. /*                                    */
  492. /* --------------------------------------------------------------------    */
  493.  
  494. BOOL fDecodeChkSelect(PLISTBOXWIN plbw,    MPARAM mp1)
  495.  
  496. {
  497. LONG   iSelected;           /* Selected Item Index        */
  498. POINTL ptl;               /* Display Point            */
  499.  
  500. ptl.x =    (LONG)SHORT1FROMMP(mp1);
  501. ptl.y =    (LONG)SHORT2FROMMP(mp1);
  502. if ( WinPtInRect(plbw->hAB, &plbw->rcl,    &ptl) )
  503.    {
  504.    if (    (iSelected = lItemFromPoint(plbw, (LONG)SHORT2FROMMP(mp1))) != plbw->iFocus )
  505.        RemoveFocus(plbw);
  506.  
  507.    if (    plbw->plc[0].apli[iSelected]->fl & LI_CHECKED )
  508.        plbw->plc[0].apli[iSelected]->fl    &= ~LI_CHECKED;
  509.    else
  510.        plbw->plc[0].apli[iSelected]->fl    |= LI_CHECKED;
  511.  
  512.                /* Draw the updated item                */
  513.  
  514.    DrawSelection(plbw, iSelected);
  515.  
  516.    if (    !(plbw->plc[0].apli[iSelected]->fl & LI_FOCUS) )
  517.        SetFocus(plbw, iSelected);
  518.  
  519.    mrNotifyOwner(plbw, LNX_CHECKED);
  520.  
  521.    return(TRUE);
  522.    }
  523. return(FALSE);
  524. }
  525. #pragma    subtitle("   Traffic Manager - Mouse Position Decode Routine")
  526. #pragma    page( )
  527.  
  528. /* --- fDecodeMouse -----------------------------------    [ Private ] ---    */
  529. /*                                    */
  530. /*     This function is    used to    determine if the current location of    */
  531. /*     the mouse within    the list box is    over a valid entry and to    */
  532. /*     either select or    deselect the item.                */
  533. /*                                    */
  534. /*     Upon Entry:                            */
  535. /*                                    */
  536. /*     PLISTBOXWIN plbw; = List    Box Data Pointer            */
  537. /*     MPARAM       mp1;     = Message Parameter 1                */
  538. /*                                    */
  539. /*     Upon Exit:                            */
  540. /*                                    */
  541. /*     fDecodeMouse =  TRUE : Mouse Pointer within List    Area        */
  542. /*            = FALSE : Mouse Pointer outside List Area        */
  543. /*                                    */
  544. /* --------------------------------------------------------------------    */
  545.  
  546. BOOL fDecodeMouse(PLISTBOXWIN plbw, MPARAM mp1)
  547.  
  548. {
  549. LONG   iSelected;           /* Selected Item Index        */
  550. POINTL ptl;               /* Display Point            */
  551.  
  552. ptl.x =    (LONG)SHORT1FROMMP(mp1);
  553. ptl.y =    (LONG)SHORT2FROMMP(mp1);
  554. if ( WinPtInRect(plbw->hAB, &plbw->rcl,    &ptl) )
  555.    {
  556.    if (    (iSelected = lItemFromPoint(plbw, (LONG)SHORT2FROMMP(mp1))) != plbw->iFocus )
  557.        RemoveFocus(plbw);
  558.  
  559.    if (    iSelected < plbw->cItems )
  560.        if ( plbw->flStyle & LS_EXTENDEDSEL )
  561.        {
  562.        if (    plbw->fCapture && (iSelected ==    plbw->iFocus) )
  563.            return(TRUE);
  564.        else
  565.            if ( plbw->fCapture )
  566.            {
  567.            SelectExtendedItems(plbw, 0L, iSelected);
  568.            SetFocus(plbw, iSelected);
  569.            }
  570.            else
  571.            if (    !(plbw->plc[0].apli[iSelected]->fl & LI_SELECTED) &&
  572.             fSelectItem(plbw, 0L, iSelected, TRUE) )
  573.                {
  574.                SetFocus(plbw, iSelected);
  575.                mrNotifyOwner(plbw, LN_SELECT);
  576.                }
  577.  
  578.        if (    !(plbw->plc[0].apli[iSelected]->fl & LI_FOCUS) )
  579.            SetFocus(plbw, iSelected);
  580.  
  581.        return(TRUE);
  582.        }
  583.        else
  584.        if (    plbw->flStyle &    LS_MULTIPLESEL )
  585.            {
  586.            if ( plbw->fCapture && (iSelected == plbw->iFocus) )
  587.            return(TRUE);
  588.            else
  589.            if (    plbw->fCapture )
  590.                SetFocus(plbw, iSelected);
  591.            else
  592.                {
  593.                if ( fSelectItem(plbw, 0L, iSelected,
  594.                     (BOOL)(plbw->plc[0].apli[iSelected]->fl    & LI_SELECTED ?    FALSE :    TRUE)) )
  595.                {
  596.                SetFocus(plbw, iSelected);
  597.                mrNotifyOwner(plbw, LN_SELECT);
  598.                return(TRUE);
  599.                }
  600.                }
  601.            }
  602.        else
  603.            if ( (iSelected != plbw->iSelected) &&
  604.             fSelectItem(plbw, 0L, iSelected, TRUE) )
  605.            {
  606.            SetFocus(plbw, iSelected);
  607.            mrNotifyOwner(plbw, LN_SELECT);
  608.            return(TRUE);
  609.            }
  610.    }
  611. return(FALSE);
  612. }
  613. #pragma    subtitle("   Traffic Manager - Mouse Position Decode Routine")
  614. #pragma    page( )
  615.  
  616. /* --- fDecodeExtendedMouse ---------------------------    [ Private ] ---    */
  617. /*                                    */
  618. /*     This function is    used to    determine if the current location of    */
  619. /*     the mouse within    the list box is    over a valid entry and to    */
  620. /*     either select or    deselect the item.                */
  621. /*                                    */
  622. /*     Upon Entry:                            */
  623. /*                                    */
  624. /*     PLISTBOXWIN plbw;   = List Box Data Pointer            */
  625. /*     MPARAM       mp1;       = Message Parameter 1            */
  626. /*     BOOL       fBlock; = Block Selected Flag            */
  627. /*                                    */
  628. /*     Upon Exit:                            */
  629. /*                                    */
  630. /*     fDecodeExtendedMouse =  TRUE : Mouse Pointer within List    Area    */
  631. /*                = FALSE : Mouse Pointer outside List Area    */
  632. /*                                    */
  633. /* --------------------------------------------------------------------    */
  634.  
  635. BOOL fDecodeExtendedMouse(PLISTBOXWIN plbw, MPARAM mp1,    BOOL fBlock)
  636.  
  637. {
  638. LONG   iSelected;           /* Selected Item Index        */
  639. POINTL ptl;               /* Display Point            */
  640.  
  641. ptl.x =    (LONG)SHORT1FROMMP(mp1);
  642. ptl.y =    (LONG)SHORT2FROMMP(mp1);
  643. if ( WinPtInRect(plbw->hAB, &plbw->rcl,    &ptl) )
  644.    {
  645.    if (    (iSelected = lItemFromPoint(plbw, (LONG)SHORT2FROMMP(mp1))) != plbw->iFocus )
  646.        RemoveFocus(plbw);
  647.  
  648.    if (    iSelected < plbw->cItems )
  649.        if ( fBlock )
  650.        {
  651.        SelectExtendedItems(plbw, 0L, iSelected);
  652.        SetFocus(plbw, iSelected);
  653.        mrNotifyOwner(plbw, LN_SELECT);
  654.        return(TRUE);
  655.        }
  656.        else
  657.        if (    fSelectMultipleItem(plbw, 0L, iSelected,
  658.                     (BOOL)(plbw->plc[0].apli[iSelected]->fl & LI_SELECTED ? FALSE : TRUE)) )
  659.            {
  660.            if ( (plbw->iFocus == iSelected)    && !(plbw->flStyle & LS_OWNERDRAW) )
  661.            plbw->iSelected = iSelected;
  662.            else
  663.            SetFocus(plbw, plbw->iSelected = iSelected);
  664.            mrNotifyOwner(plbw, LN_SELECT);
  665.            return(TRUE);
  666.            }
  667.    }
  668.  
  669. return(FALSE);
  670. }
  671. #pragma    subtitle("   Traffic Manager - Item Measure Routine")
  672. #pragma    page( )
  673.  
  674. /* --- MeasureItem ----------------------------------- [ Private ] --- */
  675. /*                                    */
  676. /*     This function is    used to    determine if the item is within    the    */
  677. /*     visible portion of the list box.                    */
  678. /*                                    */
  679. /*     Upon Entry:                            */
  680. /*                                    */
  681. /*     PLISTBOXWIN plbw;        = List Box Data Pointer        */
  682. /*     LONG       lMaxBaselineExt; = Maximum Font Height        */
  683. /*                                    */
  684. /*     Upon Exit:                            */
  685. /*                                    */
  686. /*     Nothing                                */
  687. /*                                    */
  688. /* --------------------------------------------------------------------    */
  689.  
  690. VOID MeasureItem(PLISTBOXWIN plbw, LONG    lMaxBaselineExt)
  691.  
  692. {
  693. ULONG ul;               /* Return Value            */
  694.  
  695. if ( plbw->flStyle & LS_OWNERDRAW )
  696.    {
  697.    if (    (plbw->cyItem =    (LONG)SHORT1FROMMR((ul = (ULONG)WinSendMsg(plbw->hwndOwner,
  698.                                    WM_MEASUREITEM,
  699.                                    MPFROMLONG(plbw->id),
  700.                                    MPFROMLONG(0UL))))) < lMaxBaselineExt )
  701.        plbw->cyItem  = lMaxBaselineExt;
  702.  
  703.    if (    plbw->flStyle &    LS_HORZSCROLL )
  704.        plbw->cxItem = (LONG)SHORT2FROMMR(ul);
  705.    }
  706. else
  707.    plbw->cyItem     = lMaxBaselineExt;
  708. }
  709. #pragma    subtitle("   Traffic Manager - Horizontal Scroll Creation Routine")
  710. #pragma    page( )
  711.  
  712. /* --- fAddHorzScroll ---------------------------------    [ Private ] ---    */
  713. /*                                    */
  714. /*     This function is    used to    create the horizontal scroll bar for    */
  715. /*     the list    box.                            */
  716. /*                                    */
  717. /*     Upon Entry:                            */
  718. /*                                    */
  719. /*     HWND       hWnd; = List    Box Window Handle            */
  720. /*     PLISTBOXWIN plbw; = List    Box Data Pointer            */
  721. /*                                    */
  722. /*     Upon Exit:                            */
  723. /*                                    */
  724. /*     fAddHorzScroll =     TRUE :    Scroll Bar Created            */
  725. /*              =    FALSE :    Scroll Bar Creation Error        */
  726. /*                                    */
  727. /* --------------------------------------------------------------------    */
  728.  
  729. BOOL fAddHorzScroll(HWND hWnd, PLISTBOXWIN plbw)
  730.  
  731. {
  732. LONG cxScroll;               /* Scroll Bar Width            */
  733.  
  734.                /* Calculate the    width of the scroll bar    and    */
  735.                /* make sure that it is a valid size otherwise    */
  736.                /* make its initial width zero            */
  737.  
  738. if ( (cxScroll = plbw->cx - plbw->cxScroll) < 0L )
  739.    cxScroll = 0L;
  740.  
  741. if ( (plbw->hwndScrollBottom = WinCreateWindow(hWnd, WC_SCROLLBAR, (PSZ)NULL,
  742.                            SBS_HORZ    | WS_VISIBLE,
  743.                            0L, 0L, cxScroll, plbw->cyScroll,
  744.                            hWnd, HWND_TOP, 0x0000c002UL,
  745.                            (PVOID)NULL, (PVOID)NULL)) != (HWND)NULL    )
  746.     {
  747.                /* Sub-class the    scroll bar to allow the        */
  748.                /* monitoring of    the button up events which will    */
  749.                /* allow    the proper refocusing to the list box    */
  750.  
  751.     WinSetWindowULong(plbw->hwndScrollBottom, QWL_USER,
  752.               (ULONG)WinSubclassWindow(plbw->hwndScrollBottom,
  753.                            (PFNWP)ScrollBarWndProc));
  754.  
  755.     WinQueryWindowPos(plbw->hwndScrollBottom, &plbw->aswp[SWP_HORZ]);
  756.     WinEnableWindow(plbw->hwndScrollBottom, FALSE);
  757.     return(TRUE);
  758.     }
  759. else
  760.     return(FALSE);
  761. }
  762. #pragma    subtitle("   Traffic Manager - Line Up Routine")
  763. #pragma    page( )
  764.  
  765. /* --- LineUp -----------------------------------------    [ Private ] ---    */
  766. /*                                    */
  767. /*     This function is    used to    move the focus one line    up within    */
  768. /*     the list    box.                            */
  769. /*                                    */
  770. /*     Upon Entry:                            */
  771. /*                                    */
  772. /*     PLISTBOXWIN plbw; = List    Box Data Pointer            */
  773. /*                                    */
  774. /*     Upon Exit:                            */
  775. /*                                    */
  776. /*     Nothing                                */
  777. /*                                    */
  778. /* --------------------------------------------------------------------    */
  779.  
  780. VOID LineUp(PLISTBOXWIN    plbw)
  781.  
  782. {
  783.                /* Check    to see if the focus has    been placed on    */
  784.                /* the list box and if it is visible remove the    */
  785.                /* focus    indicator                */
  786. if ( plbw->iFocus > 0L )
  787.    {
  788.                /* Check    to see if the list box is in single    */
  789.                /* select mode which means that the item    which    */
  790.                /* contains the focus also is the current item    */
  791.                /* selected                    */
  792.  
  793.    if (    (plbw->flStyle & (LS_MULTIPLESEL | LS_EXTENDEDSEL)) == 0UL )
  794.        {
  795.        SaveSelectState(0L, plbw->iFocus);
  796.        plbw->plc[0].apli[plbw->iFocus]->fl &= ~(LI_FOCUS | LI_SELECTED);
  797.        if ( fItemVisible(plbw, plbw->iFocus) )
  798.        {
  799.        FocusChange(plbw, plbw->iFocus, FALSE);
  800.        DrawItemSelection(plbw, plbw->iFocus);
  801.        }
  802.                /* Update the selected item index        */
  803.  
  804.        --plbw->iSelected;
  805.  
  806.                /* Check    to see if the new position calculated    */
  807.                /* will be before the current list top display    */
  808.                /* item,    in which case, the list    will need to be    */
  809.                /* shifted upwards and the list redisplayed    */
  810.  
  811.        if ( --plbw->iFocus < plbw->iVertScroll )
  812.        {
  813.                /* Set the new scroll bar position and force the    */
  814.                /* repainting of    the output window        */
  815.  
  816.        mrNotifyOwner(plbw, LN_SCROLL);
  817.        --plbw->iVertScroll;
  818.        WinSendMsg(plbw->hwndScrollRight, SBM_SETPOS,
  819.               MPFROMSHORT(plbw->iVertScroll = max(0, min(plbw->iVertScroll, plbw->cVertScroll))), 0L);
  820.        WinScrollWindow(plbw->hWnd, 0L, -plbw->cyItem,
  821.                (PRECTL)&plbw->rcl, (PRECTL)&plbw->rcl,
  822.                (HRGN)NULL, (PRECTL)NULL, SW_INVALIDATERGN);
  823.        WinUpdateWindow(plbw->hWnd);
  824.        }
  825.  
  826.        SaveSelectState(0L, plbw->iFocus);
  827.        plbw->plc[0].apli[plbw->iFocus]->fl |= (LI_FOCUS    | LI_SELECTED);
  828.        DrawItemSelection(plbw, plbw->iFocus);
  829.        FocusChange(plbw, plbw->iFocus, TRUE);
  830.        mrNotifyOwner(plbw, LN_SELECT);
  831.        }
  832.    else
  833.        {
  834.        RemoveFocus(plbw);
  835.  
  836.                /* Check    to see if the new position calculated    */
  837.                /* will be before the current list top display    */
  838.                /* item,    in which case, the list    will need to be    */
  839.                /* shifted upwards and the list redisplayed    */
  840.  
  841.        if ( --plbw->iFocus < plbw->iVertScroll )
  842.        {
  843.                /* Set the new scroll bar position and force the    */
  844.                /* repainting of    the output window        */
  845.  
  846.        mrNotifyOwner(plbw, LN_SCROLL);
  847.        --plbw->iVertScroll;
  848.        WinSendMsg(plbw->hwndScrollRight, SBM_SETPOS,
  849.               MPFROMSHORT(plbw->iVertScroll = max(0, min(plbw->iVertScroll, plbw->cVertScroll))), 0L);
  850.        WinScrollWindow(plbw->hWnd, 0L, -plbw->cyItem,
  851.                (PRECTL)&plbw->rcl, (PRECTL)&plbw->rcl,
  852.                (HRGN)NULL, (PRECTL)NULL, SW_INVALIDATERGN);
  853.        WinUpdateWindow(plbw->hWnd);
  854.        }
  855.        SetFocus(plbw, plbw->iFocus);
  856.        mrNotifyOwner(plbw, LN_SELECT);
  857.        }
  858.    }
  859. }
  860. #pragma    subtitle("   Traffic Manager - Line Down Routine")
  861. #pragma    page( )
  862.  
  863. /* --- LineDown    ---------------------------------------    [ Private ] ---    */
  864. /*                                    */
  865. /*     This function is    used to    move the focus one line    down within    */
  866. /*     the list    box.                            */
  867. /*                                    */
  868. /*     Upon Entry:                            */
  869. /*                                    */
  870. /*     PLISTBOXWIN plbw; = List    Box Data Pointer            */
  871. /*                                    */
  872. /*     Upon Exit:                            */
  873. /*                                    */
  874. /*     Nothing                                */
  875. /*                                    */
  876. /* --------------------------------------------------------------------    */
  877.  
  878. VOID LineDown(PLISTBOXWIN plbw)
  879.  
  880. {
  881.                /* Check    to see if the focus has    been placed on    */
  882.                /* the list box and if it is visible remove the    */
  883.                /* focus    indicator                */
  884.  
  885. if ( (plbw->iFocus != LIT_NONE)    && (plbw->iFocus < (plbw->cItems - 1L))    )
  886.    if (    (plbw->flStyle & (LS_MULTIPLESEL | LS_EXTENDEDSEL)) == 0UL )
  887.        {
  888.                /* Remove the focus from    the selected item    */
  889.  
  890.        SaveSelectState(0L, plbw->iFocus);
  891.        FocusChange(plbw, plbw->iFocus, FALSE);
  892.        plbw->plc[0].apli[plbw->iFocus]->fl &= ~(LI_FOCUS | LI_SELECTED);
  893.        if ( fItemVisible(plbw, plbw->iFocus) &&    (plbw->iSelected != LIT_NONE) )
  894.        DrawItemSelection(plbw, plbw->iSelected);
  895.  
  896.                /* Check    to see if the new position calculated    */
  897.                /* will be after    the list bottom    display    item,    */
  898.                /* in which case, the list will need to be    */
  899.                /* shifted downwards and    the list redisplayed    */
  900.  
  901.        if ( (plbw->iSelected = ++plbw->iFocus) >= (plbw->iVertScroll + plbw->cLinesPage) )
  902.        {
  903.                /* Set the new scroll bar position and force the    */
  904.                /* repainting of    the output window        */
  905.  
  906.        mrNotifyOwner(plbw, LN_SCROLL);
  907.        ++plbw->iVertScroll;
  908.        WinSendMsg(plbw->hwndScrollRight, SBM_SETPOS,
  909.               MPFROMSHORT(plbw->iVertScroll = max(0, min(plbw->iVertScroll, plbw->cVertScroll))), 0L);
  910.        WinScrollWindow(plbw->hWnd, 0L, plbw->cyItem,
  911.                (PRECTL)&plbw->rcl, (PRECTL)&plbw->rcl,
  912.                (HRGN)NULL, (PRECTL)NULL, SW_INVALIDATERGN);
  913.        WinUpdateWindow(plbw->hWnd);
  914.        }
  915.  
  916.        SaveSelectState(0L, plbw->iFocus);
  917.        plbw->plc[0].apli[plbw->iFocus]->fl |= (LI_FOCUS    | LI_SELECTED);
  918.        FocusChange(plbw, plbw->iFocus, TRUE);
  919.        DrawItemSelection(plbw, plbw->iFocus);
  920.        mrNotifyOwner(plbw, LN_SELECT);
  921.        }
  922.    else
  923.        {
  924.        RemoveFocus(plbw);
  925.                /* Check    to see if the list box is in single    */
  926.                /* select mode which means that the item    which    */
  927.                /* contains the focus also is the current item    */
  928.                /* selected                    */
  929.  
  930.        if ( (plbw->flStyle & LS_MULTIPLESEL) ==    0UL )
  931.        plbw->iSelected = ++plbw->iFocus;
  932.        else
  933.        ++plbw->iFocus;
  934.  
  935.                /* Check    to see if the new position calculated    */
  936.                /* will be after    the list bottom    display    item,    */
  937.                /* in which case, the list will need to be    */
  938.                /* shifted downwards and    the list redisplayed    */
  939.  
  940.        if ( plbw->iFocus >= (plbw->iVertScroll + plbw->cLinesPage) )
  941.        {
  942.                /* Set the new scroll bar position and force the    */
  943.                /* repainting of    the output window        */
  944.  
  945.        mrNotifyOwner(plbw, LN_SCROLL);
  946.        ++plbw->iVertScroll;
  947.        WinSendMsg(plbw->hwndScrollRight, SBM_SETPOS,
  948.               MPFROMSHORT(plbw->iVertScroll = max(0, min(plbw->iVertScroll, plbw->cVertScroll))), 0L);
  949.        WinScrollWindow(plbw->hWnd, 0L, plbw->cyItem,
  950.                (PRECTL)&plbw->rcl, (PRECTL)&plbw->rcl,
  951.                (HRGN)NULL, (PRECTL)NULL, SW_INVALIDATERGN);
  952.        WinUpdateWindow(plbw->hWnd);
  953.        }
  954.        mrNotifyOwner(plbw, LN_SELECT);
  955.        SetFocus(plbw, plbw->iFocus);
  956.        }
  957. }
  958. #pragma    subtitle("   Traffic Manager - Drag Up Routine")
  959. #pragma    page( )
  960.  
  961. /* --- LineUp -----------------------------------------    [ Private ] ---    */
  962. /*                                    */
  963. /*     This function is    used to    move the focus one line    up within    */
  964. /*     the list    box.                            */
  965. /*                                    */
  966. /*     Upon Entry:                            */
  967. /*                                    */
  968. /*     PLISTBOXWIN plbw; = List    Box Data Pointer            */
  969. /*                                    */
  970. /*     Upon Exit:                            */
  971. /*                                    */
  972. /*     Nothing                                */
  973. /*                                    */
  974. /* --------------------------------------------------------------------    */
  975.  
  976. VOID DragUp(PLISTBOXWIN    plbw)
  977.  
  978. {
  979.                /* Check    to see if the focus has    been placed on    */
  980.                /* the list box and if it is visible remove the    */
  981.                /* focus    indicator                */
  982. if ( plbw->iFocus > 0L )
  983.    {
  984.                /* Check    to see if the list box is in single    */
  985.                /* select mode which means that the item    which    */
  986.                /* contains the focus also is the current item    */
  987.                /* selected                    */
  988.  
  989.    if (    (plbw->flStyle & (LS_MULTIPLESEL | LS_EXTENDEDSEL)) == 0UL )
  990.        {
  991.        SaveSelectState(0L, plbw->iFocus);
  992.        FocusChange(plbw, plbw->iFocus, FALSE);
  993.        plbw->plc[0].apli[plbw->iFocus]->fl &= ~(LI_FOCUS | LI_SELECTED);
  994.        if ( fItemVisible(plbw, plbw->iFocus) )
  995.        DrawItemSelection(plbw, plbw->iFocus);
  996.  
  997.                /* Check    to see if the new position calculated    */
  998.                /* will be before the current list top display    */
  999.                /* item,    in which case, the list    will need to be    */
  1000.                /* shifted upwards and the list redisplayed    */
  1001.  
  1002.        if ( (plbw->iSelected = --plbw->iFocus) < plbw->iVertScroll )
  1003.        {
  1004.        SaveSelectState(0L, plbw->iFocus);
  1005.        plbw->plc[0].apli[plbw->iFocus]->fl |= (LI_FOCUS | LI_SELECTED);
  1006.  
  1007.                /* Set the new scroll bar position and force the    */
  1008.                /* repainting of    the output window        */
  1009.  
  1010.        mrNotifyOwner(plbw, LN_SCROLL);
  1011.        --plbw->iVertScroll;
  1012.        FocusChange(plbw, plbw->iFocus, TRUE);
  1013.        WinSendMsg(plbw->hwndScrollRight, SBM_SETPOS,
  1014.               MPFROMSHORT(plbw->iVertScroll = max(0, min(plbw->iVertScroll, plbw->cVertScroll))), 0L);
  1015.        WinScrollWindow(plbw->hWnd, 0L, -plbw->cyItem,
  1016.                (PRECTL)&plbw->rcl, (PRECTL)&plbw->rcl,
  1017.                (HRGN)NULL, (PRECTL)NULL, SW_INVALIDATERGN);
  1018.        WinUpdateWindow(plbw->hWnd);
  1019.        }
  1020.        else
  1021.        {
  1022.        SaveSelectState(0L, plbw->iFocus);
  1023.        plbw->plc[0].apli[plbw->iFocus]->fl |= (LI_FOCUS | LI_SELECTED);
  1024.        FocusChange(plbw, plbw->iFocus, TRUE);
  1025.        DrawItemSelection(plbw, plbw->iFocus);
  1026.        }
  1027.        mrNotifyOwner(plbw, LN_SELECT);
  1028.        }
  1029.    else
  1030.        {
  1031.        RemoveFocus(plbw);
  1032.  
  1033.                /* Check    to see if the drag is in an area where    */
  1034.                /* the current focus item will be deselected    */
  1035.  
  1036.        if ( plbw->iFocus > plbw->iAnchor )
  1037.        {
  1038.                /* In an    area where the drag direction is    */
  1039.                /* deselecting items, deselect the current item    */
  1040.                /* and redraw it                    */
  1041.  
  1042.        SaveSelectState(0L, plbw->iFocus);
  1043.        plbw->plc[0].apli[plbw->iFocus]->fl &= ~LI_SELECTED;
  1044.        DrawItemSelection(plbw, plbw->iFocus);
  1045.        }
  1046.                /* Check    to see if the new position calculated    */
  1047.                /* will be before the current list top display    */
  1048.                /* item,    in which case, the list    will need to be    */
  1049.                /* shifted upwards and the list redisplayed    */
  1050.  
  1051.        if ( --plbw->iFocus < plbw->iVertScroll )
  1052.        {
  1053.        SaveSelectState(0L, plbw->iFocus);
  1054.        plbw->plc[0].apli[plbw->iFocus]->fl |= LI_SELECTED;
  1055.  
  1056.                /* Set the new scroll bar position and force the    */
  1057.                /* repainting of    the output window        */
  1058.  
  1059.        mrNotifyOwner(plbw, LN_SCROLL);
  1060.        --plbw->iVertScroll;
  1061.        WinSendMsg(plbw->hwndScrollRight, SBM_SETPOS,
  1062.               MPFROMSHORT(plbw->iVertScroll = max(0, min(plbw->iVertScroll, plbw->cVertScroll))), 0L);
  1063.        WinScrollWindow(plbw->hWnd, 0L, -plbw->cyItem,
  1064.                (PRECTL)&plbw->rcl, (PRECTL)&plbw->rcl,
  1065.                (HRGN)NULL, (PRECTL)NULL, SW_INVALIDATERGN);
  1066.        WinUpdateWindow(plbw->hWnd);
  1067.        }
  1068.        else
  1069.        {
  1070.        SaveSelectState(0L, plbw->iFocus);
  1071.        plbw->plc[0].apli[plbw->iFocus]->fl |= LI_SELECTED;
  1072.        }
  1073.  
  1074.        mrNotifyOwner(plbw, LN_SELECT);
  1075.        SetFocus(plbw, plbw->iFocus);
  1076.        }
  1077.    }
  1078. }
  1079. #pragma    subtitle("   Traffic Manager - Drag Down Routine")
  1080. #pragma    page( )
  1081.  
  1082. /* --- DragDown    ---------------------------------------    [ Private ] ---    */
  1083. /*                                    */
  1084. /*     This function is    used to    move the focus one line    down within    */
  1085. /*     the list    box.                            */
  1086. /*                                    */
  1087. /*     Upon Entry:                            */
  1088. /*                                    */
  1089. /*     PLISTBOXWIN plbw; = List    Box Data Pointer            */
  1090. /*                                    */
  1091. /*     Upon Exit:                            */
  1092. /*                                    */
  1093. /*     Nothing                                */
  1094. /*                                    */
  1095. /* --------------------------------------------------------------------    */
  1096.  
  1097. VOID DragDown(PLISTBOXWIN plbw)
  1098.  
  1099. {
  1100.                /* Check    to see if the focus has    been placed on    */
  1101.                /* the list box and if it is visible remove the    */
  1102.                /* focus    indicator                */
  1103.  
  1104. if ( (plbw->iFocus != LIT_NONE)    && (plbw->iFocus < (plbw->cItems - 1L))    )
  1105.    if (    (plbw->flStyle & (LS_MULTIPLESEL | LS_EXTENDEDSEL)) == 0UL )
  1106.        {
  1107.        SaveSelectState(0L, plbw->iFocus);
  1108.        plbw->plc[0].apli[plbw->iFocus]->fl &= ~(LI_FOCUS | LI_SELECTED);
  1109.        if ( fItemVisible(plbw, plbw->iFocus) )
  1110.        DrawItemSelection(plbw, plbw->iFocus);
  1111.  
  1112.                /* Check    to see if the new position calculated    */
  1113.                /* will be after    the list bottom    display    item,    */
  1114.                /* in which case, the list will need to be    */
  1115.                /* shifted downwards and    the list redisplayed    */
  1116.  
  1117.        if ( (plbw->iSelected = ++plbw->iFocus) >= (plbw->iVertScroll + plbw->cLinesPage) )
  1118.        {
  1119.        SaveSelectState(0L, plbw->iFocus);
  1120.        plbw->plc[0].apli[plbw->iFocus]->fl |= (LI_FOCUS | LI_SELECTED);
  1121.        FocusChange(plbw, plbw->iFocus, TRUE);
  1122.  
  1123.                /* Set the new scroll bar position and force the    */
  1124.                /* repainting of    the output window        */
  1125.  
  1126.        mrNotifyOwner(plbw, LN_SCROLL);
  1127.        ++plbw->iVertScroll;
  1128.        WinSendMsg(plbw->hwndScrollRight, SBM_SETPOS,
  1129.               MPFROMSHORT(plbw->iVertScroll = max(0, min(plbw->iVertScroll, plbw->cVertScroll))), 0L);
  1130.        WinScrollWindow(plbw->hWnd, 0L, plbw->cyItem,
  1131.                (PRECTL)&plbw->rcl, (PRECTL)&plbw->rcl,
  1132.                (HRGN)NULL, (PRECTL)NULL, SW_INVALIDATERGN);
  1133.        WinUpdateWindow(plbw->hWnd);
  1134.        }
  1135.        else
  1136.        {
  1137.        SaveSelectState(0L, plbw->iFocus);
  1138.        plbw->plc[0].apli[plbw->iFocus]->fl |= (LI_FOCUS | LI_SELECTED);
  1139.        FocusChange(plbw, plbw->iFocus, TRUE);
  1140.        DrawItemSelection(plbw, plbw->iFocus);
  1141.        }
  1142.        mrNotifyOwner(plbw, LN_SELECT);
  1143.        }
  1144.    else
  1145.        {
  1146.        RemoveFocus(plbw);
  1147.  
  1148.                /* Check    to see if the drag is in an area where    */
  1149.                /* the current focus item will be deselected    */
  1150.  
  1151.        if ( plbw->iFocus < plbw->iAnchor )
  1152.        {
  1153.                /* In an    area where the drag direction is    */
  1154.                /* deselecting items, deselect the current item    */
  1155.                /* and redraw it                    */
  1156.  
  1157.        SaveSelectState(0L, plbw->iFocus);
  1158.        plbw->plc[0].apli[plbw->iFocus]->fl &= ~LI_SELECTED;
  1159.        DrawItemSelection(plbw, plbw->iFocus);
  1160.        }
  1161.                /* Check    to see if the list box is in single    */
  1162.                /* select mode which means that the item    which    */
  1163.                /* contains the focus also is the current item    */
  1164.                /* selected                    */
  1165.  
  1166.        if ( (plbw->flStyle & LS_MULTIPLESEL) ==    0UL )
  1167.        plbw->iSelected = ++plbw->iFocus;
  1168.        else
  1169.        ++plbw->iFocus;
  1170.  
  1171.                /* Check    to see if the new position calculated    */
  1172.                /* will be after    the list bottom    display    item,    */
  1173.                /* in which case, the list will need to be    */
  1174.                /* shifted downwards and    the list redisplayed    */
  1175.  
  1176.        if ( plbw->iFocus >= (plbw->iVertScroll + plbw->cLinesPage) )
  1177.        {
  1178.        SaveSelectState(0L, plbw->iFocus);
  1179.        plbw->plc[0].apli[plbw->iFocus]->fl |= LI_SELECTED;
  1180.  
  1181.                /* Set the new scroll bar position and force the    */
  1182.                /* repainting of    the output window        */
  1183.  
  1184.        mrNotifyOwner(plbw, LN_SCROLL);
  1185.        ++plbw->iVertScroll;
  1186.        WinSendMsg(plbw->hwndScrollRight, SBM_SETPOS,
  1187.               MPFROMSHORT(plbw->iVertScroll = max(0, min(plbw->iVertScroll, plbw->cVertScroll))), 0L);
  1188.        WinScrollWindow(plbw->hWnd, 0L, plbw->cyItem,
  1189.                (PRECTL)&plbw->rcl, (PRECTL)&plbw->rcl,
  1190.                (HRGN)NULL, (PRECTL)NULL, SW_INVALIDATERGN);
  1191.        WinUpdateWindow(plbw->hWnd);
  1192.        }
  1193.        else
  1194.        {
  1195.        SaveSelectState(0L, plbw->iFocus);
  1196.        plbw->plc[0].apli[plbw->iFocus]->fl |= LI_SELECTED;
  1197.        }
  1198.  
  1199.        mrNotifyOwner(plbw, LN_SELECT);
  1200.        SetFocus(plbw, plbw->iFocus);
  1201.        }
  1202. }
  1203.