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