home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mltcol.zip / LISTBX.C < prev    next >
C/C++ Source or Header  |  1993-05-27  |  18KB  |  396 lines

  1. /*----------------------------------------------------------------------*/
  2. /*  Defines and Include Files                                           */
  3. /*----------------------------------------------------------------------*/
  4. #define INCL_PM
  5. #include <os2.h>
  6.  
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include <stdarg.h>
  10. #include <malloc.h>
  11.  
  12.  
  13. #define COLUMN_SEPARATOR        20
  14.  
  15. #define HEADING_MAXCOLS      0
  16. #define HEADING_COLWIDTH     2
  17. #define HEADING_TOP          6
  18. #define HEADING_BOTTOM        10
  19. #define HEADING_CURCOL        14
  20.  
  21.  
  22. void  DrawLine ( HPS     hps,        HWND   hwnd,       RECTL  *prcl,
  23.                  USHORT  fsCmd,      LONG   lForeColor, LONG   lBackColor,
  24.                  char   *pszHeading, BOOL   fGrid );
  25.  
  26. void  MeasureLine ( unsigned char *pszColumn, LONG  alColWidth[],
  27.                            USHORT  usMaxCols, LONG  alWidthTable[] );
  28.  
  29. /*======================================================================*/
  30. /* Measure the text size for a owner drawn list box.            */
  31. /*======================================================================*/
  32. LONG EXPENTRY LBMeasure(HWND hwnd, USHORT idListBox, USHORT idItem,
  33.                 LONG alColWidth[], USHORT usMaxCols, USHORT idHdg,
  34.                 PSZ pszHdgTop, PSZ pszHdgBottom) {
  35.  
  36.     USHORT          usTextLen;
  37.     HPS             hps;
  38.     FONTMETRICS     fm;
  39.     LONG            alWidthTable[256];
  40.     HWND            hwndHdg;
  41.     BYTE           *pszBuf;
  42.     USHORT          ilColumn;
  43.     LONG            lWidth;
  44.  
  45.     /*------------------------------------------------------------------*/
  46.     /* Save info in the heading window's reserved memory.               */
  47.     /*------------------------------------------------------------------*/
  48.     if ( idHdg )  {
  49.         if ( ( hwndHdg = WinWindowFromID ( hwnd, idHdg ) ) != NULL )  {
  50.             WinSetWindowUShort ( hwndHdg, HEADING_MAXCOLS,  usMaxCols    );
  51.             WinSetWindowPtr    ( hwndHdg, HEADING_COLWIDTH, alColWidth   );
  52.             WinSetWindowPtr    ( hwndHdg, HEADING_TOP,      pszHdgTop    );
  53.             WinSetWindowPtr    ( hwndHdg, HEADING_BOTTOM,   pszHdgBottom );
  54.             WinSetWindowULong  ( hwndHdg, HEADING_CURCOL,   0 );
  55.         }
  56.     }
  57.  
  58.     /*------------------------------------------------------------------*/
  59.     /* Get the font metrics and char width table for the current font   */
  60.     /*------------------------------------------------------------------*/
  61.     hps = WinGetPS ( hwnd );
  62.     GpiQueryFontMetrics ( hps, (LONG) sizeof(FONTMETRICS), &fm );
  63.     GpiQueryWidthTable  ( hps, 1L, 255L, alWidthTable );
  64.     WinReleasePS        ( hps );
  65.  
  66.     /*------------------------------------------------------------------*/
  67.     /* Measure the top heading line.                                    */
  68.     /*------------------------------------------------------------------*/
  69.     if ( pszHdgTop )  {
  70.         MeasureLine ( pszHdgTop, alColWidth, usMaxCols, alWidthTable );
  71.     }
  72.  
  73.     /*------------------------------------------------------------------*/
  74.     /* Measure the bottom heading line.                                 */
  75.     /*------------------------------------------------------------------*/
  76.     if ( pszHdgBottom )  {
  77.         MeasureLine ( pszHdgBottom, alColWidth, usMaxCols, alWidthTable );
  78.     }
  79.  
  80.     /*------------------------------------------------------------------*/
  81.     /* Measure the text from the list box.                              */
  82.     /*------------------------------------------------------------------*/
  83.     usTextLen =  SHORT1FROMMR ( WinSendDlgItemMsg ( hwnd, idListBox, LM_QUERYITEMTEXTLENGTH,
  84.         MPFROMSHORT ( idItem ), 0 ) );
  85.     pszBuf = malloc ( usTextLen + 1 );
  86.  
  87.     WinSendDlgItemMsg ( hwnd, idListBox, LM_QUERYITEMTEXT,
  88.         MPFROM2SHORT ( idItem, usTextLen + 1 ), MPFROMP(pszBuf) );
  89.  
  90.     MeasureLine ( pszBuf, alColWidth, usMaxCols, alWidthTable );
  91.  
  92.     /*------------------------------------------------------------------*/
  93.     /* Calculate the width of the line.                                 */
  94.     /*------------------------------------------------------------------*/
  95.     for (ilColumn = 0, lWidth = 0; ilColumn < usMaxCols; ilColumn++)
  96.             lWidth += alColWidth[ilColumn];
  97.  
  98.     lWidth -= COLUMN_SEPARATOR;
  99.  
  100.     free ( pszBuf );
  101.     /*------------------------------------------------------------------*/
  102.     /* Return the height and width.                                     */
  103.     /*------------------------------------------------------------------*/
  104.     return ( MAKELONG(fm.lMaxBaselineExt, lWidth) );
  105. }
  106.  
  107. /*======================================================================*/
  108. /* Draw the text for a owner drawn list box.                */
  109. /*======================================================================*/
  110. VOID EXPENTRY LBDraw(HWND hwnd, USHORT idListBox, POWNERITEM poi,
  111.                 LONG alColWidth[], USHORT usMaxCols, USHORT idHdg,
  112.         BOOL fGrid) {
  113.  
  114.     USHORT          usTextLen;
  115.     LONG            lForeColor, lBackColor, lHdgColumn;
  116.     HWND            hwndHdg;
  117.     CHAR           *pszBuf;
  118.     LONG            alWidthTable[256];
  119.     FONTMETRICS     fm;
  120.     HPS             hps;
  121.  
  122.     /*------------------------------------------------------------------*/
  123.     /* Get info from the heading window's reserved memory.              */
  124.     /*------------------------------------------------------------------*/
  125.     if ( idHdg )  {
  126.         hwndHdg    = WinWindowFromID     ( hwnd, idHdg );
  127.         lHdgColumn = WinQueryWindowULong ( hwndHdg, HEADING_CURCOL );
  128.  
  129.         /*--------------------------------------------------------------*/
  130.         /* If we've scrolled horizontally, re-paint the heading.        */
  131.         /*--------------------------------------------------------------*/
  132.         if ( lHdgColumn != poi->rclItem.xLeft )  {
  133.             WinSetWindowULong ( hwndHdg, HEADING_CURCOL, poi->rclItem.xLeft );
  134.  
  135.             WinInvalidateRect ( hwndHdg, NULL, FALSE );
  136.             WinUpdateWindow   ( hwndHdg );
  137.         }
  138.     }
  139.  
  140.     /*------------------------------------------------------------------*/
  141.     /* Get the text to be drawn.                                        */
  142.     /*------------------------------------------------------------------*/
  143.     usTextLen =  SHORT1FROMMR ( WinSendDlgItemMsg ( hwnd, idListBox, LM_QUERYITEMTEXTLENGTH,
  144.         MPFROMSHORT ( poi->idItem ), 0 ) );
  145.     pszBuf = malloc ( usTextLen + 1 );
  146.  
  147.     WinSendDlgItemMsg ( hwnd, idListBox, LM_QUERYITEMTEXT,
  148.         MPFROM2SHORT(poi->idItem, usTextLen + 1), MPFROMP(pszBuf) );
  149.  
  150.     /*------------------------------------------------------------------*/
  151.     /* If fsState is TRUE, text is to be hilited.  Otherwise, use       */
  152.     /* default colors.                                                  */
  153.     /*------------------------------------------------------------------*/
  154.     if (poi->fsState) {
  155.             lForeColor = SYSCLR_HILITEFOREGROUND;
  156.             lBackColor = SYSCLR_HILITEBACKGROUND;
  157.     }
  158.     else {
  159.             lForeColor = SYSCLR_WINDOWTEXT;
  160.             lBackColor = SYSCLR_WINDOW;
  161.     }
  162.  
  163.     /*------------------------------------------------------------------*/
  164.     /* Clear the rectangle.                                             */
  165.     /*------------------------------------------------------------------*/
  166.     WinFillRect ( poi->hps, &poi->rclItem, lBackColor);
  167.  
  168.     /*------------------------------------------------------------------*/
  169.     /* Get the font metrics and character width table for the           */
  170.     /* current font.                                                    */
  171.     /*------------------------------------------------------------------*/
  172.     hps = WinGetPS ( hwnd );
  173.     GpiQueryFontMetrics ( hps, (LONG) sizeof(FONTMETRICS), &fm );
  174.     GpiQueryWidthTable  ( hps, 1L, 255L, alWidthTable );
  175.     WinReleasePS ( hps );
  176.  
  177.     MeasureLine ( pszBuf, alColWidth, usMaxCols, alWidthTable );
  178.     /*------------------------------------------------------------------*/
  179.     /* Get the first column.                                            */
  180.     /*------------------------------------------------------------------*/
  181.  
  182.     DrawLine ( poi->hps, hwndHdg, &poi->rclItem, DT_TOP, lForeColor,
  183.                lBackColor, pszBuf, fGrid );
  184.  
  185.     free ( pszBuf );
  186.  
  187.     /*------------------------------------------------------------------*/
  188.     /* Tell PM what we've done.                                         */
  189.     /*------------------------------------------------------------------*/
  190.     poi->fsState = poi->fsStateOld = FALSE;
  191.     return;
  192. }
  193.  
  194. /*======================================================================*/
  195. /* Window procedure for ADSLBHeading class.                */
  196. /*======================================================================*/
  197. MRESULT EXPENTRY HeadingWndProc(HWND hwnd, USHORT msg, MPARAM mp1,
  198.         MPARAM mp2) {
  199.  
  200.     HPS             hps;
  201.     RECTL           rclWindow;
  202.  
  203.     switch ( msg )  {
  204.     case WM_PAINT:
  205.         /*--------------------------------------------------------------*/
  206.         /* Get the size of the rectangle.                               */
  207.         /*--------------------------------------------------------------*/
  208.         hps = WinBeginPaint ( hwnd, NULL, NULL );
  209.         WinQueryWindowRect  ( hwnd, &rclWindow );
  210.  
  211.         /*--------------------------------------------------------------*/
  212.         /* Clear the rectangle.                                         */
  213.         /*--------------------------------------------------------------*/
  214.         WinFillRect ( hps, &rclWindow, SYSCLR_DIALOGBACKGROUND );
  215.  
  216.         /*--------------------------------------------------------------*/
  217.         /* Draw the top heading line.                                   */
  218.         /*--------------------------------------------------------------*/
  219.         DrawLine ( hps, hwnd, &rclWindow, DT_TOP, SYSCLR_WINDOWSTATICTEXT, SYSCLR_DIALOGBACKGROUND,
  220.                    WinQueryWindowPtr ( hwnd, HEADING_TOP ), FALSE );
  221.  
  222.         /*--------------------------------------------------------------*/
  223.         /* Draw the bottom heading line.                                */
  224.         /*--------------------------------------------------------------*/
  225.         DrawLine ( hps, hwnd, &rclWindow, DT_BOTTOM, SYSCLR_WINDOWSTATICTEXT, SYSCLR_DIALOGBACKGROUND,
  226.                    WinQueryWindowPtr ( hwnd, HEADING_BOTTOM ), FALSE );
  227.  
  228.         WinEndPaint ( hps );
  229.         break;
  230.     }
  231.  
  232.     return WinDefWindowProc(hwnd, msg, mp1, mp2);
  233. }
  234.  
  235. void  MeasureLine ( unsigned char *pszCol, LONG alColWidth[], USHORT usMaxCols, LONG  alWidthTable[] )
  236. {
  237.     PSZ             pszNextCol;
  238.     USHORT          usCol;
  239.     LONG            lWidth;
  240.  
  241.     /*------------------------------------------------------------------*/
  242.     /* Loop processing each column.                                     */
  243.     /*------------------------------------------------------------------*/
  244.     for ( usCol = 0; pszCol  &&  usCol < usMaxCols; usCol++ )  {
  245.         /*--------------------------------------------------------------*/
  246.         /* NULL terminate the column.                                   */
  247.         /*--------------------------------------------------------------*/
  248.         if ( ( pszNextCol = strchr ( pszCol, '\t' ) ) != NULL )
  249.             *pszNextCol++ = 0;
  250.  
  251.         /*--------------------------------------------------------------*/
  252.         /* Calculate the width of the column.                           */
  253.         /*--------------------------------------------------------------*/
  254.         for ( lWidth = 0; *pszCol; pszCol++ )  {
  255.             if ( *pszCol == '\r' ||  *pszCol == '\n' )
  256.                 continue;
  257.  
  258.             lWidth += alWidthTable[*pszCol - 1];
  259.         }
  260.  
  261.         lWidth += COLUMN_SEPARATOR;
  262.  
  263.         /*--------------------------------------------------------------*/
  264.         /* Save width of data in column table.                          */
  265.         /*--------------------------------------------------------------*/
  266.         if ( lWidth > alColWidth[usCol] )
  267.             alColWidth[usCol] = lWidth;
  268.  
  269.         /*--------------------------------------------------------------*/
  270.         /* Get the next column.                                         */
  271.         /*--------------------------------------------------------------*/
  272.         pszCol = pszNextCol;
  273.         if ( pszNextCol != NULL )
  274.             pszNextCol[-1] = '\t';
  275.     }
  276. }
  277.  
  278. void  DrawLine ( HPS     hps,   HWND   hwnd,       RECTL  *prcl,
  279.                  USHORT  fsCmd, LONG   lForeColor, LONG   lBackColor,
  280.                  char  *pszHdg, BOOL fGrid )  {
  281.  
  282.     CHAR           *pszCol, *pszNextCol;
  283.     USHORT          usCol, usMaxCols;
  284.     LONG           *plColWidth, lHeadingColumn;
  285.  
  286.     /*------------------------------------------------------------------*/
  287.     /* Get info from the heading window's reserved memory.              */
  288.     /*------------------------------------------------------------------*/
  289.     usMaxCols        = WinQueryWindowUShort ( hwnd, HEADING_MAXCOLS  );
  290.     plColWidth       = WinQueryWindowPtr    ( hwnd, HEADING_COLWIDTH );
  291.     lHeadingColumn   = WinQueryWindowULong  ( hwnd, HEADING_CURCOL   );
  292.  
  293.     /*------------------------------------------------------------------*/
  294.     /* Draw heading line.                                               */
  295.     /*------------------------------------------------------------------*/
  296.     if ( pszHdg )
  297.         pszCol = pszHdg;
  298.     else
  299.         pszCol = NULL;
  300.  
  301.     /*------------------------------------------------------------------*/
  302.     /* Use xLeft from list box for heading.                             */
  303.     /*------------------------------------------------------------------*/
  304.     prcl->xLeft = lHeadingColumn;
  305.  
  306.     /*------------------------------------------------------------------*/
  307.     /* Loop processing each column.                                     */
  308.     /*------------------------------------------------------------------*/
  309.     for ( usCol = 0; pszCol && usCol < usMaxCols; usCol++ )  {
  310.         /*--------------------------------------------------------------*/
  311.         /* NULL terminate the column.                                   */
  312.         /*--------------------------------------------------------------*/
  313.         if ( ( pszNextCol = strchr ( pszCol, '\t' ) ) != NULL )
  314.             *pszNextCol++ = 0;
  315.  
  316.         /*--------------------------------------------------------------*/
  317.         /* Calculate the right side of the  rectangle for this column.  */
  318.         /*--------------------------------------------------------------*/
  319.         prcl->xRight = prcl->xLeft + plColWidth[usCol] - COLUMN_SEPARATOR;
  320.  
  321.         /*--------------------------------------------------------------*/
  322.         /* Draw the text either center, left or right justified.        */
  323.         /*--------------------------------------------------------------*/
  324.         if ( *pszCol == '\n' )
  325.             WinDrawText ( hps, strlen ( pszCol + 1 ), pszCol + 1, prcl,
  326.                 lForeColor, lBackColor, fsCmd | DT_CENTER );
  327.         else if ( *pszCol == '\r' )
  328.             WinDrawText ( hps, strlen ( pszCol + 1 ), pszCol + 1, prcl,
  329.                 lForeColor, lBackColor, fsCmd | DT_RIGHT );
  330.         else
  331.             WinDrawText ( hps, strlen ( pszCol ), pszCol, prcl,
  332.                 lForeColor, lBackColor, fsCmd | DT_LEFT );
  333.  
  334.         /*--------------------------------------------------------------*/
  335.         /* If specified, draw a grid.                                   */
  336.         /*--------------------------------------------------------------*/
  337.         if ( fGrid )  {
  338.             prcl->xLeft  -= COLUMN_SEPARATOR / 2;
  339.             prcl->xRight += COLUMN_SEPARATOR / 2;
  340.  
  341.             WinDrawBorder ( hps, prcl, 1, 1, lForeColor, lBackColor,
  342.                             DB_STANDARD );
  343.  
  344.             prcl->xLeft += COLUMN_SEPARATOR / 2;
  345.         }
  346.  
  347.         /*--------------------------------------------------------------*/
  348.         /* Update the left side of the rectangle for the next column.   */
  349.         /*--------------------------------------------------------------*/
  350.         prcl->xLeft += plColWidth[usCol];
  351.  
  352.         /*--------------------------------------------------------------*/
  353.         /* Get the next column.                                         */
  354.         /*--------------------------------------------------------------*/
  355.         pszCol = pszNextCol;
  356.         if ( pszNextCol != NULL )
  357.             pszNextCol[-1] = '\t';
  358.     }
  359. }
  360.  
  361.  
  362.  
  363. void ExtractCols ( char *pszText, ... )  {
  364.  
  365.     int      i = 0, j;
  366.     char    *pCol;
  367.     va_list  marker;
  368.  
  369.     va_start( marker, pszText );        /* Initialize variable args     */
  370.  
  371.     while ( TRUE )  {
  372.  
  373.         if ( pszText[i] == '\r'|| pszText[i] == '\b' || pszText[i] == '\n' )
  374.             i++;
  375.  
  376.         pCol = va_arg( marker, char * );
  377.  
  378.         if ( pCol == NULL )  {
  379.             for ( ; pszText[i] != '\t' && pszText[i]; i++ );
  380.         }
  381.         else  {
  382.             for ( j = 0; pszText[i] != '\t' && pszText[i]; j++, i++ )  {
  383.                 pCol[ j ] = pszText[ i ];
  384.             }
  385.             pCol[j] = 0;
  386.         }
  387.  
  388.         if ( ! pszText[i] )
  389.             break;
  390.  
  391.         if ( pszText[i] == '\t' )
  392.             i++;
  393.     }
  394.     va_end( marker );                   /* Reset variable arguments     */
  395. }
  396.