DRAWSTR.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:46k
源码类别:

Windows编程

开发平台:

Visual C++

  1. /*****************************************************************************
  2. *
  3. *  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  4. *  ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
  5. *  TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR
  6. *  A PARTICULAR PURPOSE.
  7. *
  8. *  Copyright (C) 1993 - 1997 Microsoft Corporation. All Rights Reserved.
  9. *
  10. *****************************************************************************/
  11. /*+ DrawStr.c
  12.  *
  13.  *-=================================================================*/
  14. #include <windows.h>
  15. #include <windowsx.h>
  16. #include <string.h>
  17. #include <memory.h>
  18. #include <stdlib.h>
  19. #include "drawstr.h"
  20. #include "tridee.h"
  21. #include "res.h"
  22. #include "idfedit.h"
  23. CONST LOGFONT lfMain = {
  24.     12,                        //int   lfHeight;
  25.     0,                         //int   lfWidth;
  26.     0,                         //int   lfEscapement;
  27.     0,                         //int   lfOrientation;
  28.     FW_DONTCARE,               //int   lfWeight;
  29.     0,                         //BYTE  lfItalic;
  30.     0,                         //BYTE  lfUnderline;
  31.     0,                         //BYTE  lfStrikeOut;
  32.     ANSI_CHARSET,              //BYTE  lfCharSet;
  33.     OUT_DEFAULT_PRECIS,        //BYTE  lfOutPrecision;
  34.     CLIP_DEFAULT_PRECIS,       //BYTE  lfClipPrecision;
  35.     DEFAULT_QUALITY,           //BYTE  lfQuality;
  36.     DEFAULT_PITCH | FF_SWISS,  //BYTE  lfPitchAndFamily;
  37.     "MS Sans Serif",           //BYTE  lfFaceName[LF_FACESIZE];
  38.     };
  39. DSPREF dspref = {0};
  40. BOOL   bInEditingMode;
  41. #ifdef USE_MDI
  42.  #define DefProc DefMDIChildProc
  43. #else
  44.  #define DefProc DefWindowProc
  45. #endif
  46. /*+  AccessFilter
  47.  *
  48.  *   exception filter for access violations
  49.  *
  50.  *   this function is a filter for an except block. It must
  51.  *   return one of the following DWORD values:
  52.  *      EXCEPTION_EXECUTE_HANDLER
  53.  *      EXCEPTION_CONTINUE_SEARCH
  54.  *      EXCEPTION_CONTINUE_EXECUTION
  55.  *
  56.  *-=================================================================*/
  57. DWORD AccessFilter (
  58.    DWORD dwExceptCode)
  59. {
  60.    if (dwExceptCode == EXCEPTION_ACCESS_VIOLATION)
  61.       return EXCEPTION_EXECUTE_HANDLER;
  62.    return EXCEPTION_CONTINUE_SEARCH;
  63. }
  64. /*+ DrawDsLabels
  65.  *
  66.  *-=================================================================*/
  67. VOID WINAPI DrawDsLabels (
  68.    HDC          hDC,
  69.    PDSFIELDTBL  pTable,
  70.    PDSLINEINFO  pLineInfo,
  71.    LPRECT       lpRect,
  72.    POINT        ptOffset)
  73.    {
  74.    WORD        wOldAlign;  // temp, prev state of alignment
  75.    UINT        ii;         // general index variable
  76.    int         cx;         // current x position to draw at
  77.    int         cy;         // current y position to draw at
  78.    int         cyText;
  79.    PDSFIELD    pField;
  80.    struct _dsline * pLine;
  81.    char        sz[100];
  82.    // do some simple error checking, if not a valid DC
  83.    // dont go any further.
  84.    //
  85.    if (!hDC)
  86.       return;
  87.    // get the text metrics and initialize the max width variable
  88.    //
  89.    cyText = pLineInfo->cyLine;
  90.    // setup the current x & y locations for writing text
  91.    //
  92.    cx = lpRect->left - ptOffset.x;
  93.    cy = lpRect->top - ptOffset.y;
  94.    // draw each of the labels making a vertical
  95.    // column starting 'cx,cy'.  But be sure not to
  96.    // draw outside of the rectangle 'lpRect'
  97.    //
  98.    wOldAlign = SetTextAlign (hDC, TA_TOP | TA_LEFT);
  99.    // clear the background
  100.    //
  101.    ExtTextOut (hDC, cx, cy, ETO_CLIPPED | ETO_OPAQUE, lpRect, "", 0, NULL);
  102.    // draw the labels
  103.    //
  104.    for (pLine = &pLineInfo->aLine[ii = 0];
  105.         ii < pLineInfo->nCurLine;
  106.         ++ii, ++pLine, cy += cyText)
  107.       {
  108.       if (cy < lpRect->top - cyText)
  109.          continue;
  110.       if (cy > lpRect->bottom)
  111.          break;
  112.       pField = pTable[pLine->uStruct].pFields;
  113.       pField += pLine->uField;
  114.       wsprintf (sz, pField->psz, pLine->uMember);
  115.       if (sz[0] == ' ')
  116.          {
  117.          SetTextAlign (hDC, TA_TOP | TA_RIGHT);
  118.          cx = lpRect->right - 2;
  119.          }
  120.       else
  121.          {
  122.          SetTextAlign (hDC, TA_TOP | TA_LEFT);
  123.          cx = lpRect->left - ptOffset.x + (pLine->uDepth-1) * 16;
  124.          }
  125.       // draw the label pointed to by pFields[ii].psz
  126.       // then increment cy by the height of a label
  127.       //
  128.       ExtTextOut (hDC,
  129.                   cx,
  130.                   cy,
  131.                   ETO_CLIPPED,
  132.                   lpRect,
  133.                   sz,
  134.                   lstrlen(sz),
  135.                   NULL);
  136.       }
  137.    // restore text alignment and return
  138.    //
  139.    SetTextAlign (hDC, wOldAlign);
  140.    return;
  141.    }
  142. /*+ GetFieldText
  143.  *
  144.  *-=================================================================*/
  145. VOID WINAPI GetFieldText (
  146.    PDSFIELD  pField,
  147.    LPVOID    lpData,
  148.    UINT      uMember,
  149.    LPSTR     pszIn,
  150.    UINT      cchIn,
  151.    PDSBUFF   pds)
  152.    {
  153.    UINT    cb;
  154.    LPBYTE  lp;
  155.    pds->ptr = pszIn;
  156.    pds->cch = cchIn;
  157.    if (pds->cch > 10) // allow a bit of slop
  158.       pds->cch -= 10;
  159.    pds->ptr[0] = 0;
  160.    __try
  161.       {
  162.       if (pField->fmt & AS_REF)
  163.          {
  164.          lp = *(LPBYTE *)lpData;
  165.          lp += (uMember * pField->siz);
  166.          if (dspref.bShowAddresses)
  167.             {
  168.             wsprintf (pds->ptr, "@%08x: ", lpData);
  169.             cb = lstrlen(pds->ptr);
  170.             pds->ptr += cb;
  171.             pds->cch -= cb;
  172.             }
  173.          }
  174.       else
  175.          {
  176.          lp = (LPBYTE)lpData + (uMember * pField->siz);
  177.          if (dspref.bShowAddresses)
  178.             {
  179.             wsprintf (pds->ptr, "@%08x: ", lp);
  180.             cb = lstrlen(pds->ptr);
  181.             pds->ptr += cb;
  182.             pds->cch -= cb;
  183.             }
  184.          }
  185.       if (lp == NULL)
  186.          lstrcpy (pds->ptr, "<null>");
  187.       else
  188.       switch (pField->fmt & 0xFF)
  189.          {
  190.          case AS_NONE:
  191.             //wsprintf (pds->ptr, "%08X = ", lp);
  192.             break;
  193.          case AS_SZ:
  194.             strncpy (pds->ptr, (LPTSTR)lp, pds->cch);
  195.             break;
  196.          case AS_MODE:
  197.             {
  198.             UINT (*pfnMode)(LPSTR, UINT, DWORD) = (LPVOID)pField->aux;
  199.             if (pField->siz == sizeof(DWORD))
  200.                 pfnMode (pds->ptr, pds->cch, *(DWORD *)lp);
  201.             else
  202.                 pfnMode (pds->ptr, pds->cch, (DWORD)lp);
  203.             }
  204.             break;
  205.          case AS_XMODE:
  206.             {
  207.             UINT (*pfnMode)(LPSTR, UINT, UINT, UINT, UINT) = (LPVOID)pField->aux;
  208.             if (pField->siz == sizeof(DWORD))
  209.                 pfnMode (pds->ptr, pds->cch, *(UINT *)lp, pField->array, WM_GETTEXT);
  210.             else
  211.                 pfnMode (pds->ptr, pds->cch, (UINT)lp, pField->array, WM_GETTEXT);
  212.             }
  213.             break;
  214.          case AS_ERROR:
  215.             {
  216.             UINT cb;
  217.             DWORD dwError = *(LPDWORD)lp;
  218.             pds->ptr[0] = 0;
  219.             if (dwError)
  220.                 FormatMessage (FORMAT_MESSAGE_IGNORE_INSERTS
  221.                                | FORMAT_MESSAGE_FROM_SYSTEM,
  222.                                0,
  223.                                dwError,
  224.                                0,
  225.                                pds->ptr,
  226.                                pds->cch,
  227.                                NULL);
  228.             // get rid of terminating CR/LF if it exists
  229.             //
  230.             cb = lstrlen(pds->ptr);
  231.             if (cb > 2)
  232.                pds->ptr[cb-2] = 0;
  233.             }
  234.             break;
  235.          case AS_ACH:
  236.             {
  237.             UINT jj;
  238.             for (jj = 0; jj < pds->cch-1 && jj < pField->siz; ++jj)
  239.                 pds->ptr[jj] = lp[jj] > 31 ? lp[jj] : '.';
  240.             pds->ptr[jj] = 0;
  241.             }
  242.             break;
  243.          case AS_DUMP:
  244.             {
  245.             UINT   jj;
  246.             UINT   cb;
  247.             for (jj = 0; jj < pField->siz; jj += sizeof(WORD))
  248.                {
  249.                cb = wsprintf (pds->ptr, "%04X ", *(WORD *)(lp+jj));
  250.                if (cb >= pds->cch)
  251.                   {
  252.                   pds->ptr[pds->cch-1] = 0;
  253.                   break;
  254.                   }
  255.                pds->cch -= cb;
  256.                pds->ptr += cb;
  257.                }
  258.             for (jj = 0; jj < pds->cch-1 && jj < pField->siz; ++jj)
  259.                 pds->ptr[jj] = lp[jj] > 31 ? lp[jj] : '.';
  260.             pds->ptr[jj] = 0;
  261.             }
  262.             break;
  263.          case AS_HEX:
  264.             {
  265.             UINT   jj;
  266.             UINT   cb;
  267.             if (pField->siz == sizeof(DWORD))
  268.                 pds->ptr += wsprintf (pds->ptr, "%08X", *(DWORD *)lp);
  269.             else
  270.             for (jj = 0; jj < pField->siz; jj += sizeof(WORD))
  271.                {
  272.                cb = wsprintf (pds->ptr, "%04X ", *(WORD *)(lp+jj));
  273.                if (cb >= pds->cch)
  274.                   {
  275.                   pds->ptr[pds->cch-1] = 0;
  276.                   break;
  277.                   }
  278.                pds->cch -= cb;
  279.                pds->ptr += cb;
  280.                }
  281.             *pds->ptr = 0;
  282.             }
  283.             break;
  284.          case AS_INT:
  285.          case AS_UINT:
  286.             if (sizeof(WORD) == pField->siz)
  287.                wsprintf (pds->ptr, "%d", *(WORD *)lp);
  288.             else if (sizeof(DWORD) == pField->siz)
  289.                wsprintf (pds->ptr, "%d", *(DWORD *)lp);
  290.             else
  291.                {
  292.                int  jj;
  293.                UINT cb;
  294.                for (jj = pField->siz-2; jj >= 0; jj -= sizeof(WORD))
  295.                   {
  296.                   cb = wsprintf (pds->ptr, "%d ", *(WORD *)(lp+jj));
  297.                   if (cb >= pds->cch)
  298.                      {
  299.                      pds->ptr[pds->cch-1] = 0;
  300.                      break;
  301.                      }
  302.                   pds->ptr += cb;
  303.                   pds->ptr -= cb;
  304.                   }
  305.                *pds->ptr = 0;
  306.                }
  307.             break;
  308.          case AS_HANDLE:
  309.             wsprintf (pds->ptr, "%08X", *(UINT *)lp);
  310.             break;
  311.          case AS_BITFIELD:
  312.             lstrcpy (pds->ptr, ((*(UINT *)lp & (1 << pField->aux)) ? "TRUE" : "FALSE"));
  313.             break;
  314.          case AS_RECT:
  315.             wsprintf (pds->ptr, "%d,%d,%d,%d", *(LPRECT)lp);
  316.             break;
  317.          case AS_POINT:
  318.          case AS_SIZE:
  319.             wsprintf (pds->ptr, "%d,%d", *(LPPOINT)lp);
  320.             break;
  321.          case AS_POINTS:
  322.             wsprintf (pds->ptr, "%d,%d", ((SHORT *)lp)[0], ((SHORT *)lp)[1]);
  323.             break;
  324.          case AS_FLOAT:
  325.             lstrcpy (pds->ptr, "<float not supported>");
  326.             break;
  327.          case AS_BYTES:
  328.             {
  329.             UINT   jj;
  330.             LPTSTR psz = pds->ptr;
  331.             for (jj = 0; jj < pField->siz; ++jj)
  332.                {
  333.                wsprintf (psz, "%3d ", *(BYTE *)((LPSTR)lp+jj));
  334.                psz += lstrlen(psz);
  335.                *psz = 0;
  336.                if (psz > (pds->ptr + pds->cch - 10))
  337.                   {
  338.                   *psz++ = '.';
  339.                   *psz++ = '.';
  340.                   *psz++ = '.';
  341.                   *psz++ = 0;
  342.                   break;
  343.                   } 
  344.                }
  345.             }
  346.             break;
  347.          }
  348.       }
  349.    __except (AccessFilter(GetExceptionCode()))
  350.       {
  351.       lstrcpy (pds->ptr, "<no access>");
  352.       }
  353.    return;
  354.    }
  355. /*+ SetFieldText
  356.  *
  357.  *
  358.  *-=================================================================*/
  359. BOOL SetFieldText (
  360.    struct _dsline * pLine,
  361.    PDSFIELD         pField,
  362.    PDSBUFF          pds)
  363. {
  364.    LPBYTE lpv;
  365.    lpv = pLine->lpv;
  366.    if (pField->fmt & AS_REF)
  367.      lpv = *(LPBYTE *)lpv;
  368.    lpv += (pLine->uMember * pField->siz);
  369.    if (!pds->cch)
  370.       return FALSE;
  371.    pds->ptr[pds->cch-1] = 0;
  372.    switch (pField->fmt & 0xFF)
  373.       {
  374.       case AS_SZ:
  375.          strncpy (lpv, pds->ptr, min(pField->siz, pds->cch));
  376.          break;
  377.       case AS_BITFIELD:
  378.          {
  379.          LPTSTR psz = pds->ptr;
  380.          while (*psz == 't' && *psz == ' ')
  381.             ++psz;
  382.          if ((*psz & ~0x20) == 'T' || (*psz & ~0x20) == 'Y' || *psz == '1')
  383.             *(LPDWORD)lpv |= (1 << pField->aux);
  384.          else if ((*psz & ~0x20) == 'F' || (*psz & ~0x20) == 'N' || *psz == '0')
  385.             *(LPDWORD)lpv &= ~(1 << pField->aux);
  386.          }
  387.          break;
  388.       case AS_XMODE:
  389.          {
  390.          UINT (*pfnMode)(LPSTR, UINT, UINT, UINT, UINT) = (LPVOID)pField->aux;
  391.          if (pField->siz == sizeof(DWORD))
  392.              pfnMode (pds->ptr, pds->cch, *(UINT *)lpv, pField->array, WM_SETTEXT);
  393.          else
  394.              pfnMode (pds->ptr, pds->cch, (UINT)lpv, pField->array, WM_SETTEXT);
  395.          }
  396.          break;
  397.       case AS_UINT:
  398.          {
  399.          LPSTR pszStop = pds->ptr;
  400.          DWORD dw = (DWORD)strtoul (pds->ptr, &pszStop, 10);
  401.          if (pszStop != pds->ptr)
  402.             {
  403.             if (pField->siz == sizeof(DWORD))
  404.                *(LPDWORD)lpv = dw;
  405.             else if (pField->siz == sizeof(WORD))
  406.                *(LPWORD)lpv = LOWORD(dw);
  407.             }
  408.          }
  409.          break;
  410.       case AS_INT:
  411.          {
  412.          LPSTR pszStop = pds->ptr;
  413.          LONG  ii = strtol (pds->ptr, &pszStop, 10);
  414.          if (pszStop != pds->ptr)
  415.             {
  416.             if (pField->siz == sizeof(LONG))
  417.                *(LPLONG)lpv = ii;
  418.             else if (pField->siz == sizeof(short))
  419.                *(short int *)lpv = (short int)ii;
  420.             }
  421.          }
  422.          break;
  423.       case AS_BYTES:
  424.          {
  425.          UINT   jj;
  426.          LPTSTR psz;
  427.          psz = pds->ptr;
  428.          for (jj = 0; jj < pField->siz; ++jj)
  429.             {
  430.             ULONG uu;
  431.             LPTSTR pszStop;
  432.             while (*psz == 't' || *psz == ' ')
  433.                ++psz;
  434.             pszStop = psz;
  435.             uu = strtoul (psz, &pszStop, 10);
  436.             if (pszStop == psz)
  437.                break;
  438.             lpv[jj] = (BYTE)uu;
  439.             psz = pszStop;
  440.             }
  441.          }
  442.          break;
  443.       case AS_HEX:
  444.          {
  445.          DWORD  dw = 0;
  446.          LPTSTR psz;
  447.          psz = pds->ptr;
  448.          while (*psz == 't' || *psz == ' ')
  449.              ++psz;
  450.          if (psz[0] == '0' && (psz[1] == 'X' || psz[1] == 'x'))
  451.              psz += 2;
  452.          while (*psz)
  453.             {
  454.             if (*psz >= '0' && *psz <= '9')
  455.                dw = (dw << 4) + *psz - '0';
  456.             else if ((*psz >= 'A' && *psz <= 'F') ||
  457.                      (*psz >= 'a' && *psz <= 'f'))
  458.                dw = (dw << 4) + (*psz & ~0x20) - 'A' + 10;
  459.             else
  460.                break;
  461.             ++psz;
  462.             }
  463.          if (dw != 0 || (psz > pds->ptr && psz[-1] == '0'))
  464.             {
  465.             if (pField->siz == sizeof(DWORD))
  466.                *(LPDWORD)lpv = dw;
  467.             else if (pField->siz == sizeof(WORD))
  468.                *(LPWORD)lpv = LOWORD(dw);
  469.             }
  470.          }
  471.          break;
  472.       }
  473.    return TRUE;
  474. }
  475. /*+ DrawDsData
  476.  *
  477.  *-=================================================================*/
  478. VOID WINAPI DrawDsData (
  479.    HDC          hDC,
  480.    PDSFIELDTBL  pTable,
  481.    PDSLINEINFO  pLineInfo, //
  482.    LPRECT       lpRect,     // rectangle to clip drawing to
  483.    POINT        ptOffset)   // scrolling offset for upper left corner
  484.    {
  485.    WORD        wOldAlign;  // temp, prev state of alignment
  486.    UINT        ii;         // general index variable
  487.    int         cx;         // current x position to draw at
  488.    int         cy;         // current y position to draw at
  489.    int         cyText;
  490.    PDSFIELD    pField;
  491.    struct _dsline * pLine;
  492.    // do some simple error checking, if not a valid DC
  493.    // dont go any further.
  494.    //
  495.    if (!hDC)
  496.       return;
  497.    // get the text metrics and initialize the max width variable
  498.    //
  499.    cyText = pLineInfo->cyLine;
  500.    // setup the current x & y locations for writing text
  501.    //
  502.    cx = lpRect->left - ptOffset.x;
  503.    cy = lpRect->top - ptOffset.y;
  504.    // draw each of the labels making a vertical
  505.    // column starting 'cx,cy'.  But be sure not to
  506.    // draw outside of the rectangle 'lpRect'
  507.    //
  508.    wOldAlign = SetTextAlign (hDC, TA_TOP | TA_LEFT);
  509.    // clear the background
  510.    //
  511.    ExtTextOut (hDC, cx, cy, ETO_CLIPPED | ETO_OPAQUE, lpRect, "", 0, NULL);
  512.    // draw the data
  513.    //
  514.    for (pLine = &pLineInfo->aLine[ii = 0];
  515.         ii < pLineInfo->nCurLine;
  516.         ++ii, ++pLine, cy += cyText)
  517.       {
  518.       char   sz[1024]; // buffer for formatting text info
  519.       LPBYTE lpv;
  520.       DSBUFF ds;
  521.       UINT   cb;
  522.       if (cy < lpRect->top - cyText)
  523.          continue;
  524.       if (cy > lpRect->bottom)
  525.          break;
  526.       pField = pTable[pLine->uStruct].pFields;
  527.       pField += pLine->uField;
  528.       lpv = pLine->lpv;
  529.       sz[0] = 0;
  530.       GetFieldText (pField, lpv, pLine->uMember, sz, NUMELMS(sz), &ds);
  531.       if (cb = lstrlen (sz))
  532.          ExtTextOut (hDC,
  533.                      cx, cy,
  534.                      ETO_CLIPPED, lpRect, sz, cb, NULL);
  535.       }
  536.    // restore text alignment and return
  537.    //
  538.    SetTextAlign (hDC, wOldAlign);
  539.    return;
  540.    }
  541. /*+ GetDsLabelWidth
  542.  *
  543.  *-=================================================================*/
  544. int WINAPI GetDsLabelWidth (
  545.    HDC          hDC,
  546.    PDSFIELDTBL  pTable,
  547.    PDSLINEINFO  pLineInfo)
  548.    {
  549.    int  cxWidth = 0;
  550.    UINT ii;
  551.    struct _dsline * pLine = pLineInfo->aLine;
  552.    for (pLine = &pLineInfo->aLine[ii = 0];
  553.         ii < pLineInfo->nCurLine;
  554.         ++ii, ++pLine)
  555.       {
  556.       PDSFIELD pFields = pTable[pLine->uStruct].pFields;
  557.       SIZE     size = {0,0};
  558.       GetTextExtentPoint (hDC,
  559.                           pFields[pLine->uField].psz,
  560.                           lstrlen (pFields[pLine->uField].psz),
  561.                           &size);
  562.       size.cx += (pLine->uDepth * 16) - 16;
  563.       if (cxWidth < size.cx)
  564.          cxWidth = size.cx;
  565.       }
  566.    return cxWidth;
  567.    }
  568. /*+ AllocDsLineInfo
  569.  *
  570.  *-=================================================================*/
  571. PDSLINEINFO WINAPI AllocDsLineInfo (
  572.    UINT nMax)
  573.    {
  574.    PDSLINEINFO pLineInfo;
  575.    pLineInfo = GlobalAllocPtr (GHND, sizeof(DSLINEINFO)
  576.                                + sizeof(struct _dsline) * nMax);
  577.    pLineInfo->nMaxLine = nMax;
  578.    pLineInfo->nMaxDepth = 10;
  579.    pLineInfo->nCurLine = 0;
  580.    pLineInfo->nCurDepth = 0;
  581.    return pLineInfo;
  582.    }
  583. /*+ BuildDsLineInfo
  584.  *
  585.  *-=================================================================*/
  586. VOID WINAPI BuildDsLineInfo (
  587.    PDSFIELDTBL  pTable,
  588.    UINT         uStruct,    //
  589.    LPVOID       lpData,     // pointer to structure to show
  590.    WORD         nMember,
  591.    WORD         nLastMember,
  592.    PDSLINEINFO  pLineInfo)
  593.    {
  594.    UINT      uField;
  595.    PDSFIELD  pField;
  596.    UINT      cbStruct;
  597.    if (!pTable)
  598.      return;
  599.    pField = pTable[uStruct].pFields;
  600.    cbStruct = pTable[uStruct].cbSize;
  601.    if (pLineInfo->nCurDepth >= pLineInfo->nMaxDepth)
  602.       return;
  603.    ++pLineInfo->nCurDepth;
  604.    do
  605.    {
  606.       // now build the lines
  607.       //
  608.       for (uField = 0; pField->psz != NULL; ++pField, ++uField)
  609.          {
  610.          UINT   ix;
  611.          if (pLineInfo->nCurLine >= pLineInfo->nMaxLine)
  612.             break;
  613.          ix = 0;
  614.          do {
  615.             struct _dsline * pLine;
  616.             LPBYTE lpv;
  617.             if (pLineInfo->nCurLine >= pLineInfo->nMaxLine)
  618.                break;
  619.             pLine = &pLineInfo->aLine[pLineInfo->nCurLine];
  620.             ++pLineInfo->nCurLine;
  621.             pLine->uStruct = uStruct;
  622.             pLine->uField = uField;
  623.             pLine->uDepth = pLineInfo->nCurDepth;
  624.             pLine->uMember = ix;
  625.             pLine->lpv = (LPVOID)-2;
  626.             __try
  627.                {
  628.                lpv = (LPBYTE)lpData + (cbStruct * nMember) + pField->off;
  629.                pLine->lpv = lpv;
  630.                if (HIWORD(lpv)) // simple validity check...
  631.                   {
  632.                   lpv += (ix * pField->siz);
  633.                   if ((pField->fmt & 0x1FF) == AS_STRUCT)
  634.                       BuildDsLineInfo (pTable, pField->aux, lpv,
  635.                                        (WORD)ix, (WORD)ix, pLineInfo);
  636.                   }
  637.                }
  638.             __except (AccessFilter(GetExceptionCode()))
  639.                {
  640.                }
  641.             } while (++ix < pField->array);
  642.          }
  643.    } while (++nMember <= nLastMember);
  644.    --pLineInfo->nCurDepth;
  645.    return;
  646.    }
  647. /*+ GetViewExtent
  648.  *
  649.  *-=================================================================*/
  650. int WINAPI GetViewExtent (
  651.    HDC         hDC,
  652.    PVIEWINIT   pvim,
  653.    PDSLINEINFO pLineInfo,
  654.    LPSIZE      lpItemSize,
  655.    LPSIZE      lpTotalSize)
  656.    {
  657.    TEXTMETRIC tm;
  658.    pLineInfo->nCurLine = 0;
  659.    pLineInfo->nCurDepth = 0;
  660.    BuildDsLineInfo (pvim->pTable,
  661.                     pvim->uStruct,
  662.                     pvim->lpData,
  663.                     0, 0,
  664.                     pLineInfo);
  665.    GetTextMetrics (hDC, &tm);
  666.    pLineInfo->cyLine = tm.tmHeight + tm.tmExternalLeading;
  667.    lpItemSize->cx = GetDsLabelWidth (hDC, pvim->pTable, pLineInfo);
  668.    lpItemSize->cy = pLineInfo->cyLine;
  669.    lpTotalSize->cx = lpItemSize->cx * 2;
  670.    lpTotalSize->cy = pLineInfo->cyLine * pLineInfo->nCurLine;
  671.    return pLineInfo->nCurLine;
  672.    }
  673. /*+
  674.  *  ViewWndProc
  675.  *
  676.  *-=================================================================*/
  677. // misc manifest constants
  678. //
  679. #define HTLABEL 1
  680. #define HTEDGE  2
  681. #define HTDATA  3
  682. typedef struct _viewstate {
  683.    UINT        wLabelWidth;
  684.    SIZE        sTotal;
  685.    SIZE        sLabel;
  686.    SIZE        sScroll;
  687.    POINT       ptVisible;
  688.    //HBRUSH      hBrFace;
  689.    HFONT       hFontLabel;
  690.    HFONT       hFontData;
  691.    HMENU       hMenu;
  692.    WORD        wHit;
  693.    UINT        nHitLine;
  694.    HCURSOR     hCurEdge;
  695.    POINT       ptEdgeBegin;
  696.    int         cxEdgeSlop;
  697.    POINT       ptLastEdge;
  698.    int         nWindowCnt;
  699.    PDSLINEINFO pLineInfo;
  700.    int         cyLine;
  701.    int         cyWnd;
  702.    VIEWINIT    vi;
  703.    } VIEWSTATE, *PVIEWSTATE;
  704. /*+
  705.  *
  706.  *
  707.  *-=================================================================*/
  708. VOID WINAPI UpdateScrollRanges (
  709.    PVIEWSTATE pv,
  710.    HWND       hWnd)
  711.    {
  712.    RECT rc;
  713.    pv->sTotal.cy = pv->cyLine * pv->pLineInfo->nCurLine;
  714.    GetClientRect (hWnd, &rc);
  715.    pv->cyWnd = (rc.bottom - rc.top);
  716.    pv->cyWnd -= (pv->cyWnd % pv->cyLine);
  717.    pv->sScroll.cy = max (pv->sTotal.cy - pv->cyWnd, 0);
  718.    pv->ptVisible.y = min (pv->sScroll.cy, pv->ptVisible.y);
  719.    SetScrollRange (hWnd, SB_VERT, 0, pv->sScroll.cy, FALSE);
  720.    SetScrollPos (hWnd, SB_VERT, pv->ptVisible.y, TRUE);
  721.    }
  722. /*+
  723.  *  ViewPrivate
  724.  *
  725.  *-=================================================================*/
  726. UINT WINAPI EditInPlace (
  727.    HWND       hWnd,
  728.    PVIEWSTATE pv,
  729.    UINT       nLine);
  730. LONG WINAPI ViewPrivate (
  731.    HWND   hWnd,
  732.    UINT   wMsgID,
  733.    WPARAM wParam,
  734.    LPARAM lParam)
  735.    {
  736.    LONG       lRet = 0l;               // return value from this routine
  737.    PVIEWSTATE pv;
  738.    pv = (LPVOID) GetWindowLong (hWnd, GWL_USERDATA);
  739.    if (!pv)
  740.       return 0;
  741.    switch (wMsgID)
  742.       {
  743.       case VM_GETDATA:
  744.          lRet = (LRESULT)pv->vi.lpData;
  745.          break;
  746.       case VM_SETDATA:
  747.          lRet = (LRESULT)pv->vi.lpData;
  748.          pv->vi.lpData = (LPVOID)lParam;
  749.          if (lRet != (LRESULT)pv->vi.lpData)
  750.             {
  751.             RECT rc;
  752.             pv->pLineInfo->nCurLine = 0;
  753.             pv->pLineInfo->nCurDepth = 0;
  754.             BuildDsLineInfo (pv->vi.pTable,
  755.                              pv->vi.uStruct,
  756.                              pv->vi.lpData,
  757.                              0, 0,
  758.                              pv->pLineInfo);
  759.             GetClientRect (hWnd, &rc);
  760.             rc.left = pv->wLabelWidth + 5;
  761.             InvalidateRect (hWnd, &rc, FALSE);
  762.             }
  763.          break;
  764.       case VM_INVALIDATE:
  765.          {
  766.          RECT  rc;
  767.          int   yLine;
  768.          if (!wParam && !lParam)
  769.             InvalidateRect (hWnd, NULL, FALSE);
  770.          GetClientRect (hWnd, &rc);
  771.          yLine = ((int)lParam * pv->cyLine) - pv->ptVisible.y;
  772.          if (yLine >= rc.top && yLine <= rc.bottom)
  773.             {
  774.             rc.left += pv->wLabelWidth + 5;
  775.             rc.top += yLine;
  776.             rc.bottom = rc.top + (pv->cyLine * max(1, wParam));
  777.             InvalidateRect (hWnd, &rc, FALSE);
  778.             }
  779.          }
  780.          break;
  781.       case VM_SETSEL:
  782.          {
  783.          UINT nLine = (UINT)lParam;
  784.          BOOL bPrev = (BOOL)wParam;
  785.          while (nLine < pv->pLineInfo->nCurLine)
  786.             {
  787.             struct _dsline * pLine = &pv->pLineInfo->aLine[nLine];
  788.             PDSFIELD pField = pv->vi.pTable[pLine->uStruct].pFields + pLine->uField;
  789.             if (pField->fmt & IS_EDIT)
  790.                {
  791.                RECT rc;
  792.                int  yLine;
  793.                GetClientRect (hWnd, &rc);
  794.                yLine = (int)(nLine * pv->cyLine) - pv->ptVisible.y;
  795.                if (yLine >= rc.top && (yLine + pv->cyLine) <= rc.bottom)
  796.                   pv->nHitLine = nLine, lRet = 1;
  797.                break;
  798.                }
  799.             if (bPrev && nLine == 0)
  800.                 break;
  801.             nLine = bPrev ? nLine-1 : nLine+1;
  802.             }
  803.          }
  804.          break;
  805.       case VM_EDITNEXT:
  806.          {
  807.          UINT nLine = pv->nHitLine;
  808.          BOOL bPrev = (BOOL)wParam;
  809.          if (bPrev && nLine == 0)
  810.             break;
  811.          nLine = bPrev ? nLine-1 : nLine+1;
  812.          if (ViewPrivate (hWnd, VM_SETSEL, bPrev, nLine))
  813.             {
  814.             EditInPlace (hWnd, pv, pv->nHitLine);
  815.             }
  816.          }
  817.       }
  818.    return lRet;
  819.    }
  820. /*+
  821.  *  
  822.  *
  823.  *-=================================================================*/
  824. LRESULT Notify (
  825.    HWND hWnd,
  826.    UINT code)
  827. {
  828.    NMHDR nm;
  829.    nm.hwndFrom = hWnd;
  830.    nm.idFrom = GetDlgCtrlID(hWnd);
  831.    nm.code = code;
  832.    return SendMessage (GetParent(hWnd), WM_NOTIFY, nm.idFrom, (LPARAM)(LPVOID)&nm);
  833. }
  834. /*+
  835.  *  EditInPlace
  836.  *
  837.  *-=================================================================*/
  838. UINT WINAPI EditInPlace (
  839.    HWND       hWnd,
  840.    PVIEWSTATE pv,
  841.    UINT       nLine)
  842.    {
  843.    PDSFIELDTBL  pTable = pv->vi.pTable;
  844.    PDSLINEINFO  pLineInfo = pv->pLineInfo;
  845.    struct _dsline * pLine;
  846.    PDSFIELD         pField;
  847.    TCHAR        sz[1000];
  848.    HWND         hWndEdit;
  849.    RECT         rc;
  850.    MSG          msg;
  851.    UINT         uId;
  852.    DSBUFF       ds;
  853.    if (nLine >= pLineInfo->nCurLine)
  854.       return 0;
  855.    pLine = &pLineInfo->aLine[nLine];
  856.    pField = pTable[pLine->uStruct].pFields + pLine->uField;
  857.    GetFieldText (pField, pLine->lpv, pLine->uMember, sz, NUMELMS(sz), &ds);
  858.    GetClientRect (hWnd, &rc);
  859.    rc.left += pv->wLabelWidth + 5;
  860.    rc.top = (nLine * pv->cyLine) - pv->ptVisible.y -2;
  861.    rc.bottom = rc.top + pv->cyLine + 4;
  862.    hWndEdit = CreateWindowEx (fdwExStyle | WS_EX_NOPARENTNOTIFY,
  863.                               "Edit",
  864.                               sz,
  865.                               ES_AUTOHSCROLL |
  866.                               ES_LEFT |
  867.                               WS_CHILD | WS_BORDER,
  868.                               rc.left, rc.top,
  869.                               rc.right - rc.left, rc.bottom - rc.top,
  870.                               hWnd,
  871.                               (HMENU)IDE_VALUE,
  872.                               GetWindowInstance(hWnd),
  873.                               NULL);
  874.    if ( ! hWndEdit)
  875.       return 0;
  876.    SendMessage (hWndEdit, WM_SETFONT, (WPARAM)pv->hFontData, 0);
  877.    Edit_SetSel (hWndEdit, 0, NUMELMS(sz)+2);
  878.    ShowWindow (hWndEdit, SW_SHOWNORMAL);
  879.    SetFocus (hWndEdit);
  880.    uId = IDOK;
  881.    bInEditingMode = TRUE;
  882.    do {
  883.       if (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE))
  884.          {
  885.          if (msg.hwnd != hWndEdit &&
  886.              (msg.message == WM_LBUTTONDOWN ||
  887.               msg.message == WM_RBUTTONDOWN))
  888.             break;
  889.          if (msg.message == WM_QUIT)
  890.             break;
  891.          if (msg.message == WM_SYSKEYDOWN)
  892.             break;
  893.          GetMessage (&msg, NULL, 0, 0);
  894.          if ((msg.hwnd == hWndEdit) && (msg.message == WM_KEYDOWN))
  895.             {
  896.             if (LOWORD(msg.wParam) == VK_RETURN)
  897.                break;
  898.             else if (LOWORD(msg.wParam) == VK_TAB)
  899.                {
  900.                PostMessage (hWnd, VM_EDITNEXT, (WPARAM)GetKeyState(VK_SHIFT), 0);
  901.                break;
  902.                }
  903.             else if (LOWORD(msg.wParam) == VK_ESCAPE)
  904.                {
  905.                uId = IDCANCEL;
  906.                break;
  907.                }
  908.             }
  909.          TranslateMessage (&msg);
  910.          DispatchMessage (&msg);
  911.          }
  912.       else
  913.          {
  914.          //SendMessage (hWnd, WM_ENTERIDLE, 0, 0);
  915.          WaitMessage();
  916.          }
  917.       } while (bInEditingMode && GetFocus() == hWndEdit);
  918.    bInEditingMode = FALSE;
  919.    if (uId == IDOK)
  920.    {
  921.        GetWindowText (hWndEdit, sz, NUMELMS(sz));
  922.        ds.ptr = sz;
  923.        ds.cch = lstrlen(ds.ptr)+1;
  924.        SetFieldText (pLine, pField, &ds);
  925.        ViewPrivate (hWnd, VM_INVALIDATE, 0, nLine);
  926.        Notify (hWnd, VN_CHANGE);
  927.    }
  928.    DestroyWindow (hWndEdit);
  929.    return uId;
  930. }
  931. /*+
  932.  *  CopyLineToClip
  933.  *
  934.  *-=================================================================*/
  935. LONG WINAPI CopyLineToClip (
  936.    HWND       hWnd,
  937.    PVIEWSTATE pv,
  938.    UINT       nLine)
  939. {
  940.    PDSFIELDTBL  pTable = pv->vi.pTable;
  941.    PDSLINEINFO  pLineInfo = pv->pLineInfo;
  942.    HGLOBAL      hMem;
  943.    struct _dsline * pLine;
  944.    PDSFIELD         pField;
  945.    UINT         cfType;
  946.    pLine = &pLineInfo->aLine[nLine];
  947.    pField = pTable[pLine->uStruct].pFields + pLine->uField;
  948.    switch (pField->fmt & 0xFF)
  949.       {
  950.       case AS_BYTES:
  951.       case AS_DUMP:
  952.          {
  953.          LPRIFF pRiff;
  954.          LPBYTE lpv;
  955.          lpv = pLine->lpv;
  956.          if (pField->fmt & AS_REF)
  957.             lpv = *(LPBYTE *)lpv;
  958.          lpv += (pLine->uMember * pField->siz);
  959.          cfType = CF_RIFF;
  960.          hMem = GlobalAlloc (GHND, pField->siz + sizeof(RIFF));
  961.          if (!(pRiff = GlobalLock (hMem)))
  962.             return 0;
  963.          pRiff->fcc = MAKEFOURCC('B','y','t','e');
  964.          pRiff->cb = pField->siz;
  965.          CopyMemory (pRiff+1, lpv, pField->siz);
  966.          GlobalUnlock (hMem);
  967.          }
  968.          break;
  969.       case AS_XMODE:
  970.          {
  971.          UINT (*pfnMode)(LPSTR, UINT, UINT, UINT, UINT) = (LPVOID)pField->aux;
  972.          LPBYTE lpv;
  973.          lpv = pLine->lpv;
  974.          if (pField->fmt & AS_REF)
  975.             lpv = *(LPBYTE *)lpv;
  976.          lpv += (pLine->uMember * pField->siz);
  977.          if (pField->siz == sizeof(DWORD))
  978.              {
  979.              if (pfnMode (NULL, (UINT)hWnd, *(UINT *)lpv, pField->array, WM_COPY))
  980.                 return 0;
  981.              }
  982.          else
  983.              {
  984.              if (pfnMode (NULL, (UINT)hWnd, (UINT)lpv, pField->array, WM_COPY))
  985.                 return 0;
  986.              }
  987.          }
  988.          // fall through
  989.       default:
  990.          {
  991.          DSBUFF ds;
  992.          LPSTR  psz;
  993.          UINT   cch = 128 * 5 + 10;
  994.          cfType = CF_TEXT;
  995.          hMem = GlobalAlloc (GHND, cch);
  996.          if (!(psz = GlobalLock (hMem)))
  997.             return 0;
  998.          // get data for the current line into the global
  999.          // object.
  1000.          //
  1001.          GetFieldText (pField, pLine->lpv, pLine->uMember, psz, cch, &ds);
  1002.          // truncate the global object to fit the size of the data
  1003.          //
  1004.          GlobalUnlock (hMem);
  1005.          GlobalReAlloc (hMem, lstrlen(psz) + 2, 0);
  1006.          }
  1007.          break;
  1008.       }
  1009.    if (OpenClipboard (hWnd))
  1010.        {
  1011.        EmptyClipboard ();
  1012.        SetClipboardData (cfType, hMem);
  1013.        CloseClipboard ();
  1014.        }
  1015.    else
  1016.        GlobalFree (hMem);
  1017.    return 0;
  1018. }
  1019. /*+
  1020.  *  PasteLineFromClip
  1021.  *
  1022.  *-=================================================================*/
  1023. LONG WINAPI PasteLineFromClip (
  1024.    HWND       hWnd,
  1025.    PVIEWSTATE pv,
  1026.    UINT       nLine)
  1027. {
  1028.    HGLOBAL hMem;
  1029.    PDSFIELDTBL  pTable = pv->vi.pTable;
  1030.    PDSLINEINFO  pLineInfo = pv->pLineInfo;
  1031.    struct _dsline * pLine = &pLineInfo->aLine[nLine];
  1032.    PDSFIELD     pField = pTable[pLine->uStruct].pFields + pLine->uField;
  1033.    LONG lRet = 0;
  1034.    switch (pField->fmt & 0xFF)
  1035.       {
  1036.       case AS_BYTES:
  1037.       case AS_DUMP:
  1038.           if (OpenClipboard (hWnd))
  1039.              {
  1040.              if (hMem = GetClipboardData (CF_RIFF))
  1041.                {
  1042.                LPRIFF pRiff;
  1043.                LPBYTE lpv;
  1044.                lpv = pLine->lpv;
  1045.                if (pField->fmt & AS_REF)
  1046.                   lpv = *(LPBYTE *)lpv;
  1047.                lpv += (pLine->uMember * pField->siz);
  1048.                if (pRiff = GlobalLock (hMem))
  1049.                   {
  1050.                   if (pRiff->fcc == MAKEFOURCC('B','y','t','e') &&
  1051.                       pRiff->cb == pField->siz)
  1052.                      {
  1053.                      CopyMemory (lpv, pRiff+1, pField->siz);
  1054.                      lRet = 2;
  1055.                      }
  1056.                   GlobalUnlock (hMem);
  1057.                   }
  1058.                } 
  1059.             CloseClipboard ();
  1060.             }
  1061.          break;
  1062.       case AS_XMODE:
  1063.          {
  1064.          UINT (*pfnMode)(LPSTR, UINT, UINT, UINT, UINT) = (LPVOID)pField->aux;
  1065.          LPBYTE lpv;
  1066.          lpv = pLine->lpv;
  1067.          if (pField->fmt & AS_REF)
  1068.             lpv = *(LPBYTE *)lpv;
  1069.          lpv += (pLine->uMember * pField->siz);
  1070.          if (pField->siz == sizeof(DWORD))
  1071.              lRet = pfnMode (NULL, (UINT)hWnd, *(UINT *)lpv, pField->array, WM_PASTE);
  1072.          else
  1073.              lRet = pfnMode (NULL, (UINT)hWnd, (UINT)lpv, pField->array, WM_PASTE);
  1074.          // fall through if pfnMode handled the paste operation
  1075.          //
  1076.          if (lRet != 0)
  1077.             break;
  1078.          }
  1079.          // fall through
  1080.       default:
  1081.          if (OpenClipboard (hWnd))
  1082.             {
  1083.             if (hMem = GetClipboardData (CF_TEXT))
  1084.                {
  1085.                DSBUFF ds;
  1086.                ds.ptr = GlobalLock (hMem);
  1087.                if (ds.ptr)
  1088.                   {
  1089.                   ds.cch = lstrlen(ds.ptr)+1;
  1090.                   SetFieldText (pLine, pField, &ds);
  1091.                   lRet = 2;
  1092.                   }
  1093.                }
  1094.             CloseClipboard ();
  1095.             }
  1096.          break;
  1097.       }
  1098.    if (lRet > 0)
  1099.    {
  1100.       ViewPrivate (hWnd, VM_INVALIDATE, 0, nLine);
  1101.       Notify (hWnd, VN_CHANGE);
  1102.    }
  1103.    return lRet;
  1104. }
  1105. /*+
  1106.  *  ViewCommands
  1107.  *
  1108.  *-=================================================================*/
  1109. LONG WINAPI ViewCommands (
  1110.    HWND   hWnd,
  1111.    WPARAM wParam,
  1112.    LPARAM lParam)
  1113.    {
  1114.    LONG       lRet = 0l;               // return value from this routine
  1115.    PVIEWSTATE pv;
  1116.    pv = (LPVOID) GetWindowLong (hWnd, GWL_USERDATA);
  1117.    if (!pv)
  1118.       return 0;
  1119.    switch (GET_WM_COMMAND_ID(wParam,lParam))
  1120.       {
  1121.       case IDM_OBJEDIT:
  1122.           EditInPlace   (hWnd, pv, pv->nHitLine);
  1123.           //EditLineValue (hWnd, pv, pv->nHitLine);
  1124.           break;
  1125.       case IDM_EDITCOPY:
  1126.           CopyLineToClip (hWnd, pv, pv->nHitLine);
  1127.           break;
  1128.       case IDM_EDITPASTE:
  1129.           PasteLineFromClip (hWnd, pv, pv->nHitLine);
  1130.           break;
  1131.       }
  1132.    return lRet;
  1133.    }
  1134. /*+
  1135.  *  ViewWndProc
  1136.  *
  1137.  *-=================================================================*/
  1138. LONG CALLBACK ViewWndProc (
  1139.    HWND   hWnd,
  1140.    UINT   wMsgID,
  1141.    WPARAM wParam,
  1142.    LPARAM lParam)
  1143.    {
  1144.    LONG       lRet = 0l;               // return value from this routine
  1145.    PVIEWSTATE pv;
  1146.    pv = (LPVOID) GetWindowLong (hWnd, GWL_USERDATA);
  1147.    if (wMsgID >= WM_USER && wMsgID < 0x8000)
  1148.       lRet = ViewPrivate (hWnd, wMsgID, wParam, lParam);
  1149.    else
  1150.    switch (wMsgID)
  1151.       {
  1152.       case WM_NCHITTEST:
  1153.          lRet = DefProc (hWnd, wMsgID, wParam, lParam);
  1154.          if (lRet == HTCLIENT)
  1155.             {
  1156.             POINT pt = {MAKEPOINTS(lParam).x, MAKEPOINTS(lParam).y};
  1157.             ScreenToClient (hWnd, &pt);
  1158.             pv->wHit = HTEDGE;
  1159.             if (pt.x <= (int)pv->wLabelWidth -4)
  1160.                pv->wHit = HTLABEL;
  1161.             else if (pt.x >= (int)pv->wLabelWidth +4)
  1162.                pv->wHit = HTDATA;
  1163.             }
  1164.          break;
  1165.      #if 0
  1166.       case WM_SETCURSOR:
  1167.          if (LOWORD (lParam) == HTCLIENT &&
  1168.              pv->wHit == HTEDGE &&
  1169.              pv->hCurEdge != NULL)
  1170.             SetCursor (pv->hCurEdge);
  1171.          else
  1172.             lRet = DefProc (hWnd, wMsgID, wParam, lParam);
  1173.          break;
  1174.      #endif
  1175.       case WM_LBUTTONDBLCLK:
  1176.          {
  1177.          POINT pt = {MAKEPOINTS(lParam).x, MAKEPOINTS(lParam).y};
  1178.          PDSFIELDTBL  pTable = pv->vi.pTable;
  1179.          PDSLINEINFO  pLineInfo = pv->pLineInfo;
  1180.          UINT         nLine = (pt.y + pv->ptVisible.y) / pv->cyLine;
  1181.          lRet = DefProc (hWnd, wMsgID, wParam, lParam);
  1182.          if (nLine < pLineInfo->nCurLine)
  1183.              {
  1184.              struct _dsline * pLine = &pLineInfo->aLine[nLine];
  1185.              PDSFIELD pField = pTable[pLine->uStruct].pFields + pLine->uField;
  1186.              if ((pField->fmt & IS_EDIT) && pv->hMenu)
  1187.                 {
  1188.                 pv->nHitLine = nLine;
  1189.                 SetCapture (hWnd);
  1190.                 }
  1191.             }
  1192.          break;
  1193.          }
  1194.       case WM_LBUTTONUP:
  1195.          {
  1196.          if (GetCapture() == hWnd)
  1197.             {
  1198.             POINT pt = {MAKEPOINTS(lParam).x, MAKEPOINTS(lParam).y};
  1199.             PDSFIELDTBL  pTable = pv->vi.pTable;
  1200.             PDSLINEINFO  pLineInfo = pv->pLineInfo;
  1201.             UINT         nLine = (pt.y + pv->ptVisible.y) / pv->cyLine;
  1202.             ReleaseCapture ();
  1203.             if (nLine == pv->nHitLine)
  1204.                PostMessage (hWnd, WM_COMMAND, IDM_OBJEDIT, 0);
  1205.             }
  1206.          lRet = DefProc (hWnd, wMsgID, wParam, lParam);
  1207.          break;
  1208.          }
  1209.       case WM_LBUTTONDOWN:
  1210.       case WM_RBUTTONDOWN:
  1211.          SetFocus (hWnd);
  1212.          lRet = DefProc (hWnd, wMsgID, wParam, lParam);
  1213.          break;
  1214.       case WM_RBUTTONUP:
  1215.          {
  1216.          POINT pt = {MAKEPOINTS(lParam).x, MAKEPOINTS(lParam).y};
  1217.          PDSFIELDTBL  pTable = pv->vi.pTable;
  1218.          PDSLINEINFO  pLineInfo = pv->pLineInfo;
  1219.          UINT         nLine = (pt.y + pv->ptVisible.y) / pv->cyLine;
  1220.          lRet = DefProc (hWnd, wMsgID, wParam, lParam);
  1221.          if (nLine < pLineInfo->nCurLine)
  1222.              {
  1223.              struct _dsline * pLine = &pLineInfo->aLine[nLine];
  1224.              PDSFIELD pField = pTable[pLine->uStruct].pFields + pLine->uField;
  1225.              //if (pv->wHit == HTLABEL)
  1226.              //   {
  1227.              //   }
  1228.              if ((pField->fmt & IS_EDIT) && pv->hMenu)
  1229.                 {
  1230.                 pv->nHitLine = nLine;
  1231.                 ClientToScreen (hWnd, &pt);
  1232.                 TrackPopupMenu (pv->hMenu,
  1233.                                #if (WINVER >= 0x400)
  1234.                                 TPM_TOPALIGN |
  1235.                                #endif
  1236.                                 TPM_LEFTALIGN | TPM_RIGHTBUTTON,
  1237.                                 pt.x, pt.y,
  1238.                                 0,
  1239.                                 hWnd,
  1240.                                 NULL);
  1241.                 }
  1242.             }
  1243.          break;
  1244.          }
  1245.       case WM_COMMAND:
  1246.          lRet = ViewCommands (hWnd, wParam, lParam);
  1247.          break;
  1248.       case WM_SIZE:
  1249.          lRet = DefProc (hWnd, wMsgID, wParam, lParam);
  1250.          UpdateScrollRanges (pv, hWnd);
  1251.          break;
  1252.       case WM_KEYDOWN:
  1253.          {
  1254.          int  nNewPos = -1;
  1255.          switch (LOWORD(wParam))
  1256.             {
  1257.             case VK_UP:
  1258.                nNewPos = pv->ptVisible.y - pv->cyLine;
  1259.                break;
  1260.             case VK_DOWN:
  1261.                nNewPos = pv->ptVisible.y + pv->cyLine;
  1262.                break;
  1263.             case VK_PRIOR:
  1264.                nNewPos = pv->ptVisible.y - (pv->cyWnd - pv->cyLine);
  1265.                break;
  1266.             case VK_NEXT:
  1267.                nNewPos = pv->ptVisible.y + (pv->cyWnd - pv->cyLine);
  1268.                break;
  1269.             }
  1270.          if (nNewPos != -1)
  1271.             {
  1272.             nNewPos = min (nNewPos, pv->sScroll.cy);
  1273.             nNewPos = max (nNewPos, 0);
  1274.             ScrollWindow (hWnd, 0, pv->ptVisible.y - nNewPos, NULL, NULL);
  1275.             pv->ptVisible.y = nNewPos;
  1276.             SetScrollPos (hWnd, SB_VERT, pv->ptVisible.y, TRUE);
  1277.             }
  1278.          break;
  1279.          }
  1280.      case WM_VSCROLL:
  1281.          {
  1282.          int  nPos;
  1283.          int  nNewPos = -1;
  1284.          WORD wScrollCode;
  1285.          wScrollCode = LOWORD (wParam);
  1286.          nPos        = (int)HIWORD (wParam);
  1287.       
  1288.          switch (wScrollCode)
  1289.             {
  1290.             case SB_LINEUP:
  1291.                nNewPos = pv->ptVisible.y - pv->cyLine;
  1292.                break;
  1293.             case SB_LINEDOWN:
  1294.                nNewPos = pv->ptVisible.y + pv->cyLine;
  1295.                break;
  1296.             case SB_PAGEUP:
  1297.                nNewPos = pv->ptVisible.y - (pv->cyWnd - pv->cyLine);
  1298.                break;
  1299.             case SB_PAGEDOWN:
  1300.                nNewPos = pv->ptVisible.y + (pv->cyWnd - pv->cyLine);
  1301.                break;
  1302.             case SB_THUMBPOSITION:
  1303.                nNewPos = nPos - (nPos % pv->cyLine);
  1304.                break;
  1305.             }
  1306.          if (nNewPos != -1)
  1307.             {
  1308.             nNewPos = min (nNewPos, pv->sScroll.cy);
  1309.             nNewPos = max (nNewPos, 0);
  1310.             ScrollWindow (hWnd, 0, pv->ptVisible.y - nNewPos, NULL, NULL);
  1311.             pv->ptVisible.y = nNewPos;
  1312.             SetScrollPos (hWnd, SB_VERT, pv->ptVisible.y, TRUE);
  1313.             }
  1314.          break;
  1315.          }
  1316.       case WM_ERASEBKGND:
  1317.          {
  1318.          RECT rc;
  1319.          lRet = DefWindowProc (hWnd, wMsgID, wParam, lParam);
  1320.          GetClientRect (hWnd, &rc);
  1321.          //rc.left = pv->wLabelWidth + 3;
  1322.          //TrideeWellShadow ( (HDC)wParam, &rc);
  1323.          SetTextColor ( (HDC)wParam, RGB (0,0,128));
  1324.          //SetBkColor ( (HDC)wParam, GetSysColor (COLOR_BTNFACE));
  1325.          //rc.left = 0;
  1326.          rc.right = pv->wLabelWidth;
  1327.          //TrideeWellShadow ( (HDC)wParam, &rc);
  1328.          if (pv->hFontLabel)
  1329.             SelectObject ((HDC)wParam, pv->hFontLabel);
  1330.          DrawDsLabels ((HDC)wParam,
  1331.                        pv->vi.pTable,
  1332.                        pv->pLineInfo,
  1333.                        &rc,
  1334.                        pv->ptVisible);
  1335.          break;
  1336.          }
  1337.       case WM_PAINT:
  1338.          {
  1339.          PAINTSTRUCT ps;           // structure for BeginPaint
  1340.          HDC         hDC;          // DC to draw info into
  1341.          RECT        rcClip;       // clip rect for drawing
  1342.          // and draw the info into our client area
  1343.          //
  1344.          hDC = BeginPaint (hWnd, &ps);
  1345.          GetClientRect (hWnd, &rcClip);
  1346.          rcClip.left += pv->wLabelWidth + 5;
  1347.          if (pv->hFontData)
  1348.             SelectObject (hDC, pv->hFontData);
  1349.          SetTextColor (hDC, GetSysColor (COLOR_WINDOWTEXT));
  1350.          SetBkColor (hDC, GetSysColor (COLOR_WINDOW));
  1351.          DrawDsData (hDC,
  1352.                      pv->vi.pTable,
  1353.                      pv->pLineInfo,
  1354.                      &rcClip,
  1355.                      pv->ptVisible);
  1356.          EndPaint (hWnd, &ps);
  1357.          break;
  1358.          }
  1359.       case WM_CREATE:
  1360.          {
  1361.          HDC               hDC;
  1362.          char              sz[120];
  1363.          LPCREATESTRUCT    lpCreate = (LPCREATESTRUCT)lParam;
  1364.          POINT             pt = {0,0};
  1365.          pv = LocalAlloc (LPTR, sizeof(VIEWSTATE));
  1366.          if (!pv)
  1367.             return -1;
  1368.          SetWindowLong (hWnd, GWL_USERDATA, (LONG)pv);
  1369.          // init local state information
  1370.          //
  1371.          pv->pLineInfo = AllocDsLineInfo (1000);
  1372.          //pv->hBrFace = TrideeCreate (hWnd);
  1373.           //CreateFontIndirect (&lfMain);
  1374.          pv->hFontLabel = GetStockObject (DEFAULT_GUI_FONT);
  1375.          pv->hFontData  = GetStockObject (ANSI_FIXED_FONT);
  1376.          pv->hMenu = CreatePopupMenu ();
  1377.          //AppendMenuItem (pv->hMenu, &mii);
  1378.          AppendMenu (pv->hMenu, MF_STRING, IDM_OBJEDIT, "&Edit...");
  1379.          AppendMenu (pv->hMenu, MF_STRING, IDM_EDITCOPY, "&Copy");
  1380.          AppendMenu (pv->hMenu, MF_STRING, IDM_EDITPASTE, "&Paste");
  1381.          // get init stuff from last parameter (if possible)
  1382.          //
  1383.         #ifdef USE_MDI
  1384.          {
  1385.          LPMDICREATESTRUCT lpMcs;
  1386.          lpMcs = (LPMDICREATESTRUCT) (lpCreate->lpCreateParams);
  1387.          lpMcs->x = lpMcs->y = CW_USEDEFAULT;
  1388.          lpMcs->cx = lpMcs->cy = CW_USEDEFAULT;
  1389.          if (lpMcs->lParam)
  1390.             pv->vi = *(PVIEWINIT)lpMcs->lParam;
  1391.          }
  1392.         #else
  1393.          if (lpCreate->lpCreateParams)
  1394.             pv->vi = *(PVIEWINIT)(lpCreate->lpCreateParams);
  1395.         #endif
  1396.          hDC = GetDC (hWnd);
  1397.          if (pv->hFontLabel)
  1398.             SelectObject (hDC, pv->hFontLabel);
  1399.          GetViewExtent (hDC,
  1400.                         &pv->vi,
  1401.                         pv->pLineInfo,
  1402.                         &pv->sLabel,
  1403.                         &pv->sTotal);
  1404.          pv->cyLine = pv->pLineInfo->cyLine;
  1405.          pv->wLabelWidth = pv->sLabel.cx + 16;
  1406.          ReleaseDC (hWnd, hDC);
  1407.          pv->hCurEdge = LoadCursor (lpCreate->hInstance,
  1408.                                     MAKEINTRESOURCE (IDC_EDGE));
  1409.          wsprintf (sz, "%s:%08lxx",
  1410.                    pv->vi.pTable[pv->vi.uStruct].pszName,
  1411.                    pv->vi.lpData);
  1412.          SetWindowText (hWnd, sz);
  1413.          
  1414.          break;
  1415.          }
  1416.       case WM_DESTROY:
  1417.          {
  1418.          //TrideeDestroy (hWnd);
  1419.          // delete font if not using stock object
  1420.          //DeleteObject (pv->hFontLabel);
  1421.          break;            // return FALSE;
  1422.          }
  1423.       default:
  1424.          lRet = DefProc (hWnd, wMsgID, wParam, lParam);
  1425.       }
  1426.    return lRet;
  1427.    }
  1428. /*+ DrawDragEdge
  1429.  *
  1430.  *
  1431.  *-=================================================================*/
  1432. VOID WINAPI DrawDragEdge (HWND hWnd, LPPOINT lppt, LPPOINT lpptLastEdge)
  1433.    {
  1434.    HDC  hDC;
  1435.    RECT rc;
  1436.    hDC = GetDC (hWnd);
  1437.    GetClientRect (hWnd, &rc);
  1438.    if (lpptLastEdge)
  1439.       PatBlt (hDC, lpptLastEdge->x, rc.top, 3, rc.bottom - rc.top, PATINVERT);
  1440.    if (lppt)
  1441.       {
  1442.       PatBlt (hDC, lppt->x, rc.top, 3, rc.bottom - rc.top, PATINVERT);
  1443.       if (lpptLastEdge)
  1444.          *lpptLastEdge = *lppt;
  1445.       }
  1446.    ReleaseDC (hWnd, hDC);
  1447.    }