home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / smart21b.zip / SAMPLES / SLINK / LINKXR.C < prev    next >
C/C++ Source or Header  |  1992-10-20  |  35KB  |  1,039 lines

  1. /*************************************************************
  2.  LINKXR.c
  3.  
  4. **************************************************************/
  5.  
  6. #include "link.h"
  7.  
  8. /************ External GLOBALS *******************************/
  9.  
  10. extern CHAR szFileName[CCHMAXPATH];
  11. extern CHAR szXRName[MAXXRNAME+1];
  12. extern USHORT usRetXRType;
  13. extern BOOL FILE_ISOPEN;
  14. extern BOOL FILE_CHANGED;
  15. extern BOOL COMMAND_LINE_FILE;
  16. extern HHXRP hhp;
  17. extern CHAR *pAlloc,*szEditBuf,*szAscii,*szScratch;
  18. extern HOLDFXR *pHoldFXR;
  19. extern DELETELIST *pDelList;
  20. extern XRDATA ConvTable[XRTABLESIZE];
  21.  
  22. /*************************************************************/
  23.  
  24.  
  25. /*
  26.  * Function name: AddXR()
  27.  *
  28.  * Parameters:  hwnd which is the current window handle.
  29.  *
  30.  * Returns: TRUE iff the XR is successfully added.
  31.  *
  32.  * Purpose: This routine handles the addition of a new XR to the linked list.
  33.  *
  34.  * Usage/Warnings:  Routine does NOT do full memory error trapping and the
  35.  *                  insert message to the l-box is not error checked.
  36.  *
  37.  * Calls: EditXRValue()
  38.  */
  39.  
  40. BOOL AddXR(HWND hwnd)
  41. {
  42.    HOLDFXR  *pFXR=pHoldFXR;  /* Points to the beginning of the XR list */
  43.    HOLDFXR  *pNewFXR;        /* Used to temporarily hold the new XR    */
  44.    PASSDATA PData;
  45.  
  46.    if(!FILE_ISOPEN)
  47.       return(FALSE);
  48.  
  49.    if(!WinDlgBox(HWND_DESKTOP,         /* get new XR name and type */
  50.                  hwnd,
  51.                  AddXRProc,
  52.                  NULL,
  53.                  IDD_ADDXR,
  54.                  NULL))
  55.       return(FALSE);                   /* they said cancel */
  56.  
  57.      if (WinDlgBox(HWND_DESKTOP,
  58.              hwndFrame,    /* handle of the owner         */
  59.              OpenDlg,      /* dialog procedure address    */
  60.              NULLHANDLE,   /* location of dialog resource */
  61.              IDD_OPEN,     /* resource identifier         */
  62.              NULL)) {      /* application-specific data   */
  63.  
  64.    GetMem(pNewFXR, sizeof(HOLDFXR));   /* Allocate space for new XR struct */
  65.  
  66.    pNewFXR->cbName = (CHAR) strlen(szXRName);  /* Fill in new structure */
  67.    pNewFXR->cbValue= 0;
  68.    pNewFXR->fXR    = 0; /* Need bit NOT set */
  69.  
  70.    GetMem(pNewFXR->szName,pNewFXR->cbName+1);  /* Name returned in szXRName */
  71.    strcpy(pNewFXR->szName,strupr(szXRName));
  72.    pNewFXR->aValue = NULL;
  73.    pNewFXR->next   = NULL;
  74.  
  75.    if(pHoldFXR == NULL)           /* It's the first XR for the file */
  76.    {
  77.       pHoldFXR = pNewFXR;
  78.    }
  79.    else                           /* Add XR to the end of the linked list */
  80.    {
  81.       while(pFXR->next)
  82.          pFXR = pFXR->next;
  83.       pFXR->next = pNewFXR;
  84.    }
  85.    PData.Point         = (CHAR *) pNewFXR;  /* Setup user data for call */
  86.    PData.cbMulti       = 0;                 /* to edit of the name and  */
  87.    PData.usMultiOffset = 0;                 /* XR Value                 */
  88.  
  89.    if(!EditXRValue(hwnd,&PData)) /* They canceled the edit */
  90.    {
  91.       if(pFXR)               /* It's not the only XR          */
  92.          pFXR->next = NULL;  /* Disconnect the partial new XR */
  93.       else
  94.          pHoldFXR = NULL;    /* The new XR was the first one  */
  95.  
  96.       FreeMem(pNewFXR->szName,pNewFXR->cbName+1);
  97.       FreeMem(pNewFXR,sizeof(HOLDFXR));
  98.  
  99.       return(FALSE);
  100.    }
  101.  
  102.    WinSendDlgItemMsg(hwnd, IDD_LBOX, LM_INSERTITEM, /* Insert name in L-Box */
  103.                      MPFROM2SHORT(LIT_END,0),
  104.                      MPFROMP(pNewFXR->szName));
  105.  
  106.    return(TRUE);
  107. }
  108.  
  109.  
  110. /*
  111.  * Calls: Free_FXRList(), CheckXRIntegrity()
  112.  */
  113.  
  114. BOOL QueryXRs(HWND hwnd,CHAR *pszPath)
  115. {
  116.    CHAR *pAlloc;       /* Holds the FXR struct returned by DosEnumAttribute */
  117.                        /* also used to create the GXRLIST for DosQPathInfo  */
  118.    CHAR *pBigAlloc;    /* Temp buffer to hold each XR as it is read in      */
  119.    USHORT cbBigAlloc;  /* Size of buffer                                    */
  120.  
  121.    ULONG ulEntryNum = 1; /* count of current XR to read (1-relative)        */
  122.    ULONG ulEnumCnt;      /* Number of XRs for Enum to return, always 1      */
  123.  
  124.    HOLDFXR *pLastIn;     /* Points to last XR added, so new XR can link     */
  125.    HOLDFXR *pNewFXR;     /* Struct to build the new XR in                   */
  126.  
  127.    FXR *pFXR;            /* Used to read from Enum's return buffer          */
  128.    GXRLIST *pGXRList;    /* Ptr used to set up buffer for DosQPathInfo call */
  129.    XROP eaopGet;         /* Used to call DosQPathInfo                       */
  130.  
  131.    GetMem(pAlloc,MAX_GXR);     /* Allocate enough room for any GXR List     */
  132.    pFXR = (FXR *) pAlloc;      /* pFXR always uses pAlloc buffer            */
  133.  
  134.    pHoldFXR = NULL;            /* Reset the pointer for the XR linked list  */
  135.  
  136.    while(TRUE) /* Loop continues until there are no more XRs */
  137.    {
  138.       ulEnumCnt = 1;                 /* Only want to get one XR at a time */
  139.       if(DosEnumAttribute(Ref_ASCIIZ,          /* Read into pAlloc Buffer */
  140.                           pszPath,             /* Note that this does not */
  141.                           ulEntryNum,          /* get the aValue field,   */
  142.                           pAlloc,              /* so DosQPathInfo must be */
  143.                           MAX_GXR,             /* called to get it.       */
  144.                           &ulEnumCnt,
  145.                           (LONG) GetInfoLevel1,
  146.                           0L))
  147.         break;                         /* There was some sort of error    */
  148.  
  149.       if(ulEnumCnt != 1)               /* All the XRs have been read      */
  150.          break;
  151.  
  152.       ulEntryNum++;
  153.  
  154.       GetMem(pNewFXR,sizeof(HOLDFXR));
  155.  
  156.       if (pNewFXR == NULL)             /* Out of memory */
  157.       {
  158.          FreeMem(pAlloc,MAX_GXR);
  159.          Free_FXRList(pHoldFXR,pDelList);
  160.          return (FALSE);
  161.       }
  162.  
  163.       pNewFXR->cbName = pFXR->cbName;  /* Fill in the HoldFXR structure   */
  164.       pNewFXR->cbValue= pFXR->cbValue;
  165.       pNewFXR->fXR    = pFXR->fXR;
  166.       pNewFXR->next = NULL;
  167.  
  168.       GetMem(pNewFXR->szName,pFXR->cbName +1); /* Allocate for 2 arrays   */
  169.       GetMem(pNewFXR->aValue,pFXR->cbValue);
  170.  
  171.       if (!pNewFXR->szName || !pNewFXR->aValue) /* Out of memory */
  172.       {
  173.          if(pNewFXR->szName)
  174.             FreeMem(pNewFXR->szName,pFXR->cbName+1);
  175.          if(pNewFXR->aValue)
  176.             FreeMem(pNewFXR->aValue,pFXR->cbValue);
  177.  
  178.          FreeMem(pAlloc, MAX_GXR);
  179.          FreeMem(pNewFXR,sizeof(HOLDFXR));
  180.  
  181.          Free_FXRList(pHoldFXR,pDelList);
  182.          return (FALSE);
  183.       }
  184.       strcpy(pNewFXR->szName,pAlloc+sizeof(FXR));      /* Copy in XR Name */
  185.  
  186.       cbBigAlloc = sizeof(FXRLIST) + pNewFXR->cbName+1 + pNewFXR->cbValue;
  187.       GetMem(pBigAlloc,cbBigAlloc);
  188.       if (pBigAlloc == NULL)
  189.       {
  190.          FreeMem(pNewFXR->szName,pFXR->cbName+1);
  191.          FreeMem(pNewFXR->aValue,pFXR->cbValue);
  192.          FreeMem(pAlloc, MAX_GXR);
  193.          FreeMem(pNewFXR,sizeof(HOLDFXR));
  194.          Free_FXRList(pHoldFXR,pDelList);
  195.          return (FALSE);
  196.       }
  197.  
  198.       pGXRList = (GXRLIST *) pAlloc;   /* Set up GXRList structure */
  199.  
  200.       pGXRList->cbList = sizeof(GXRLIST) + pNewFXR->cbName; /* +1 for NULL */
  201.       pGXRList->list[0].cbName = pNewFXR->cbName;
  202.       strcpy(pGXRList->list[0].szName,pNewFXR->szName);
  203.  
  204.       eaopGet.fpGXRList = (GXRLIST far *) pAlloc;
  205.       eaopGet.fpFXRList = (FXRLIST far *) pBigAlloc;
  206.  
  207.       eaopGet.fpFXRList->cbList = cbBigAlloc;
  208.  
  209.       DosQPathInfo(pszPath,            /* Get the complete XR info        */
  210.                    GetInfoLevel3,
  211.                    (PVOID) &eaopGet,
  212.                    sizeof(XROP),
  213.                    0L);
  214.       memcpy(pNewFXR->aValue,          /* Copy the value to HoldFXR       */
  215.              pBigAlloc+sizeof(FXRLIST)+pNewFXR->cbName+1,
  216.              pNewFXR->cbValue);
  217.  
  218.       FreeMem(pBigAlloc,cbBigAlloc);   /* Release the temp Enum buffer    */
  219.  
  220.       if(!CheckXRIntegrity(pNewFXR->aValue,pNewFXR->cbValue)) /* Bad XR   */
  221.       {
  222.          FreeMem(pNewFXR->szName,pFXR->cbName+1);
  223.          FreeMem(pNewFXR->aValue,pFXR->cbValue);
  224.          FreeMem(pNewFXR,sizeof(HOLDFXR));
  225.          continue;                    /* Don't add this XR to linked list */
  226.       }
  227.  
  228.       if(pHoldFXR == NULL)             /* If first XR, set pHoldFXR       */
  229.          pHoldFXR = pNewFXR;
  230.       else                             /* Otherwise, add to end of list   */
  231.          pLastIn->next = pNewFXR;
  232.  
  233.       pLastIn = pNewFXR;               /* Update the end of the list      */
  234.    }
  235.    FreeMem(pAlloc, MAX_GXR);  /* Free up the GXR buf for DosEnum */
  236.    return (TRUE);
  237. }
  238.  
  239.  
  240. /*
  241.  * Function name: CheckXRIntegrity()
  242.  *
  243.  * Calls: MultiTypeIndex()
  244.  */
  245.  
  246. BOOL CheckXRIntegrity(CHAR *aBuf,USHORT cbBuf)
  247. {
  248.    USHORT *pusPtr = (USHORT *) aBuf;
  249.    USHORT usOffset;
  250.    CHAR   *aEndPtr;
  251.  
  252.    usOffset = LookupXRType(*pusPtr);  /* Get the XR type */
  253.  
  254.    switch(ConvTable[usOffset].usFldType)
  255.    {
  256.       case IDD_LPDATA:
  257.          pusPtr++;
  258.          if(*pusPtr + 2*sizeof(USHORT) == cbBuf)
  259.             return TRUE;
  260.          else
  261.             return FALSE;
  262.  
  263.       case IDD_MULTILIST:
  264.          if(*pusPtr == XR_MVMT)
  265.          {
  266.             pusPtr += 2;
  267.  
  268.             /* This checks where the end of the m-m list ends to determine
  269.                the size of the XR.  This is probably not good if the XR is
  270.                badly corrupted and it points to protected memory */
  271.  
  272.             aEndPtr = MultiTypeIndex(aBuf,*pusPtr);
  273.             if(aEndPtr - aBuf == cbBuf)
  274.                return TRUE;
  275.             else
  276.                return FALSE;
  277.          }
  278.          else /* Single type, multi-value is not yet implemented */
  279.          {
  280.             return TRUE;
  281.          }
  282.       default:
  283.          return FALSE;
  284.    }
  285.    return TRUE;
  286. }
  287.  
  288.  
  289. /*
  290.  * Function name: Free_FXRList()
  291.  *
  292.  */
  293.  
  294. VOID Free_FXRList(HOLDFXR *pFXR,DELETELIST *pDList)
  295. {
  296.    HOLDFXR *next;  /* Holds the next field since we free the structure */
  297.                    /* before reading the current next field            */
  298.    DELETELIST *Dnext; /* Same purpose as *next */
  299.  
  300.    while(pFXR)
  301.    {
  302.       next = pFXR->next;
  303.       if(pFXR->szName)                         /* Free if non-NULL name  */
  304.          FreeMem(pFXR->szName,pFXR->cbName+1);
  305.       if(pFXR->aValue)                         /* Free if non-NULL value */
  306.          FreeMem(pFXR->aValue,pFXR->cbValue);
  307.  
  308.       FreeMem(pFXR,sizeof(HOLDFXR));           /* Free HoldFXR struct    */
  309.       pFXR = next;
  310.    }
  311.  
  312.    while(pDList)
  313.    {
  314.       Dnext = pDList->next;
  315.       if(pDList->XRName)
  316.          FreeMem(pDList->XRName,strlen(pDList->XRName)+1);
  317.       FreeMem(pDList,sizeof(DELETELIST));
  318.       pDList = Dnext;
  319.    }
  320. }
  321.  
  322.  
  323. /*
  324.  * Function name: LookupXRType()
  325.  *
  326.  * Calls:
  327.  */
  328.  
  329. USHORT LookupXRType(USHORT usType)
  330. {
  331.    USHORT cnt;
  332.  
  333.    for(cnt=0;cnt<XRTABLESIZE-1;cnt++)
  334.       if(ConvTable[cnt].usPrefix == usType)
  335.          return(cnt);
  336.    return(cnt);
  337. }
  338.  
  339.  
  340. /*
  341.  * Function name: DeleteCurXR()
  342.  *
  343.  * Calls: GetCurFXR()
  344.  */
  345.  
  346. VOID DeleteCurXR(HWND hwnd)
  347. {
  348.    HOLDFXR *pFXR,*pFXRPrev;
  349.    DELETELIST *pDL,*pDLcnt;  /* Utility ptrs for manipulating the Del list */
  350.    LONG lOffset;
  351.  
  352.    pFXR = GetCurFXR(hwnd,pHoldFXR);    /* Gets a pointer to item to delete */
  353.    if (pFXR == NULL)
  354.       return;
  355.  
  356.    /* These two allocations should be checked for out of memory */
  357.    GetMem(pDL,sizeof(DELETELIST));     /* Add Name to Delete List */
  358.    GetMem(pDL->XRName,pFXR->cbName+1);
  359.    strcpy(pDL->XRName,pFXR->szName);
  360.    pDL->next = NULL;
  361.  
  362.    if(pDelList == NULL)        /* The del list was previously empty  */
  363.       pDelList = pDL;
  364.    else                        /* tack name onto the end of the list */
  365.    {
  366.       pDLcnt = pDelList;
  367.       while(pDLcnt->next)
  368.          pDLcnt = pDLcnt->next;
  369.       pDLcnt->next = pDL;
  370.    }
  371.  
  372.    lOffset = (LONG) WinSendDlgItemMsg(hwnd, IDD_LBOX,
  373.                                      LM_QUERYSELECTION,0,0);
  374.    WinSendDlgItemMsg(hwnd, IDD_LBOX,
  375.                      LM_DELETEITEM,MPFROMSHORT((SHORT) lOffset),0L);
  376.  
  377.    if(lOffset<1)               /* Remove pFXR from the linked list */
  378.    {
  379.       pHoldFXR = pFXR->next;
  380.    }
  381.    else
  382.    {
  383.       pFXRPrev = pHoldFXR;
  384.  
  385.       while(--lOffset)              /* Find previous XR */
  386.          pFXRPrev = pFXRPrev->next;
  387.  
  388.       pFXRPrev->next = pFXR->next;
  389.    }
  390.  
  391.    FreeMem(pFXR->szName,pFXR->cbName+1);  /* Release the memory */
  392.    FreeMem(pFXR->aValue,pFXR->cbValue);
  393.    FreeMem(pFXR,sizeof(HOLDFXR));
  394.  
  395.    FILE_CHANGED = TRUE;
  396. }
  397.  
  398.  
  399. /*
  400.  * Function name: CurXRType()
  401.  *
  402.  */
  403.  
  404. USHORT CurXRType(HOLDFXR *pFXR)   /* Same as GetUSHORT(,0); */
  405. {
  406.    USHORT *pusType;    /* XR Type is stored in first USHORT of aValue field */
  407.  
  408.    pusType = (USHORT *) pFXR->aValue;
  409.    return(*pusType);
  410. }
  411.  
  412.  
  413. /*
  414.  * Function name: GetUSHORT()
  415.  */
  416.  
  417. USHORT GetUSHORT(HOLDFXR *pFXR,USHORT index)
  418. {
  419.    USHORT *pusType;
  420.  
  421.    pusType = (USHORT *) pFXR->aValue;
  422.    while(index-- > 0)
  423.       pusType++;
  424.    return(*pusType);
  425. }
  426.  
  427.  
  428. /*
  429.  * Function name: WriteXRs()
  430.  */
  431.  
  432. VOID WriteXRs(HWND hwnd)
  433. {
  434.    DELETELIST *pDL = pDelList,*pDLnext;
  435.    HOLDFXR    *pHFXR= pHoldFXR;
  436.    XROP       eaopWrite;
  437.    CHAR       aBuf[MAX_GXR],*aPtr;
  438.    FXR        *pFXR = (FXR *) &aBuf[sizeof(ULONG)];
  439.    USHORT     usRet,usMemNeeded;
  440.    ULONG      *pulPtr=(ULONG *) aBuf; /* Initally points to top of FXRLIST */
  441.  
  442.    if(!FILE_ISOPEN || !FILE_CHANGED) /* Don't write unless it's necessary */
  443.       return;
  444.  
  445.    eaopWrite.fpFXRList = (FXRLIST far *) aBuf; /* Setup fields that won't */
  446.    pFXR->fXR     = 0;                          /* change for the delete   */
  447.    pFXR->cbValue = 0;                          /* calls to DosSetPathInfo */
  448.  
  449.    while(pDL)                       /* Clean out all the deleted XR names */
  450.    {
  451.       pFXR->cbName = (UCHAR) strlen(pDL->XRName);
  452.       *pulPtr      = sizeof(FXRLIST) + pFXR->cbName+1; /* +1 for NULL */
  453.       strcpy(aBuf+sizeof(FXRLIST),pDL->XRName);
  454.  
  455.       usRet=DosSetPathInfo(szFileName,    /* Delete XR's by saying cbValue=0 */
  456.                            SetInfoLevel2,
  457.                            (PVOID) &eaopWrite,
  458.                            (USHORT) sizeof(XROP),
  459.                            DSPI_WRTTHRU,
  460.                            0L);
  461.  
  462.       pDLnext = pDL->next;                   /* Temp hold next pDL         */
  463.       FreeMem(pDL->XRName, pFXR->cbName+1);  /* Free up current Del struct */
  464.       FreeMem(pDL, sizeof(DELETELIST));
  465.       pDL = pDLnext;                         /* Set pDL to saved value     */
  466.    }
  467.    pDelList = NULL;                          /* DelList is now empty       */
  468.  
  469.    while(pHFXR)   /* Go through each HoldFXR */
  470.    {
  471.       usMemNeeded = sizeof(FXRLIST) + pHFXR->cbName+1 + pHFXR->cbValue;
  472.       GetMem(aPtr,usMemNeeded);
  473.  
  474.       eaopWrite.fpFXRList = (FXRLIST far *) aPtr; /* Fill in eaop struct */
  475.       eaopWrite.fpFXRList->cbList = usMemNeeded;
  476.  
  477.       eaopWrite.fpFXRList->list[0].fXR     = pHFXR->fXR;
  478.       eaopWrite.fpFXRList->list[0].cbName  = pHFXR->cbName;
  479.       eaopWrite.fpFXRList->list[0].cbValue = pHFXR->cbValue;
  480.  
  481.       strcpy(aPtr + sizeof(FXRLIST),  pHFXR->szName);
  482.       memcpy(aPtr + sizeof(FXRLIST) + pHFXR->cbName+1,
  483.              pHFXR->aValue, pHFXR->cbValue);
  484.  
  485.       usRet=DosSetPathInfo(szFileName,             /* Write out the XR */
  486.                            SetInfoLevel2,
  487.                            (PVOID) &eaopWrite,
  488.                            (USHORT) sizeof(XROP),
  489.                            DSPI_WRTTHRU,0L);
  490.  
  491.       FreeMem(aPtr,usMemNeeded);       /* Free up the FXRLIST struct */
  492.  
  493.       pHFXR = pHFXR->next;
  494.    }
  495.  
  496.    FILE_CHANGED = FALSE;
  497. }
  498.  
  499.  
  500. /*
  501.  * Function name: EditXRValue()
  502.  *
  503.  */
  504.  
  505. BOOL EditXRValue(HWND hwnd, PASSDATA *pPDat)
  506. {
  507.    USHORT usXRType; /* Holds the field type to be edited */
  508.    USHORT *pusPtr;
  509.    USHORT usSize;   /* Holds the delta difference of the old and new buffers */
  510.    CHAR   *szNew,*szTrash;     /* Temporary pointers */
  511.    PASSDATA PDat;
  512.    HOLDFXR *pFXR = (HOLDFXR *) pPDat->Point;   /* The XR to be edited */
  513.  
  514.    /* Determine the type of XR that will be edited */
  515.    if(pPDat->cbMulti)                  /* It's a multi-type job  */
  516.    {
  517.       pusPtr = (USHORT *) MultiTypeIndex(pFXR->aValue+pPDat->usMultiOffset,
  518.                                          pPDat->usIndex);
  519.       usXRType = *pusPtr;
  520.    }
  521.    else if(pFXR->cbValue) /* It isn't a new XR name */
  522.    {
  523.       pusPtr   = (USHORT *) pFXR->aValue;
  524.       usXRType = *pusPtr;
  525.    }
  526.    else    /* It's a new XR */
  527.    {
  528.       usXRType = ConvTable[usRetXRType].usPrefix;
  529.    }
  530.  
  531.    PDat.Point   = pFXR->szName;        /* General setup for AsciiEditProc */
  532.    PDat.usIndex = pPDat->cbMulti ? 1 : 0;   /* =1 if there is a multi  */
  533.    PDat.fFlag   = (BYTE) ((pFXR->fXR & 0x80) ? TRUE : FALSE);
  534.  
  535.    switch(usXRType)
  536.    {
  537.       case XR_ASCIIZ:
  538.       case XR_ASCIIZFN:
  539.       case XR_ASCIIZXR:
  540.       case XR_ASN1:
  541.          if(pPDat->cbMulti)            /* It is a multi-type field */
  542.             szAscii=MultiTypeIndex(pFXR->aValue + pPDat->usMultiOffset,
  543.                                    pPDat->usIndex)
  544.                     +sizeof(USHORT);
  545.          else if(pFXR->cbValue)        /* There is a current value */
  546.             szAscii=pFXR->aValue+sizeof(USHORT);
  547.          else                                     /* It's a new XR */
  548.             szAscii=NULL;
  549.  
  550.  
  551.          if(!WinDlgBox(HWND_DESKTOP,        /* Do an ascii text edit */
  552.                        hwnd,
  553.                        AsciiEditProc,
  554.                        NULL,
  555.                        IDD_ASCIIEDIT,
  556.                        &PDat))
  557.             return(FALSE);                  /* They said cancel */
  558.  
  559.          if(PDat.fFlag)            /* Handle the need/nice bit */
  560.             PDat.fFlag = 0x80;
  561.          if(PDat.fFlag != (PDat.fFlag & 0x80))
  562.             FILE_CHANGED = TRUE;
  563.          pFXR->fXR = (pFXR->fXR & 0x7f) | PDat.fFlag;
  564.  
  565.          if(stricmp(strupr(szXRName),pFXR->szName)) /* The name changed */
  566.             ChangeName(hwnd,pFXR,szXRName);
  567.  
  568.          if(pFXR->cbValue) /* There is a current value */
  569.          {
  570.             if(!strcmp(szAscii,szScratch))  /* It hasn't changed */
  571.                return(TRUE);
  572.  
  573.             if(pPDat->cbMulti) /* Do the whole thing here if m-m */
  574.             {
  575.                usSize = strlen(szScratch)-strlen(szAscii); /* Change in size */
  576.  
  577.                if(usSize > 0) /* The new string is longer */
  578.                {
  579.                   ResizeMem(pFXR->aValue,          /* Enlarge the XR size */
  580.                             pFXR->cbValue,
  581.                             pFXR->cbValue+usSize);
  582.                   szTrash=MultiTypeIndex(pFXR->aValue + pPDat->usMultiOffset,
  583.                                          pPDat->usIndex+1);
  584.                   memmove(szTrash+usSize,  /* Move end of XR to make room */
  585.                           szTrash,
  586.                           pFXR->cbValue-(szTrash-pFXR->aValue));
  587.                }
  588.                else if(usSize < 0) /* The new string is shorter */
  589.                {
  590.                   szTrash=MultiTypeIndex(pFXR->aValue + pPDat->usMultiOffset,
  591.                                          pPDat->usIndex+1);
  592.                   memmove(szTrash+usSize, /* Move back the end of the XR */
  593.                           szTrash,
  594.                           pFXR->cbValue-(szTrash-pFXR->aValue));
  595.                   ResizeMem(pFXR->aValue,  /* Shrink the XR buffer */
  596.                             pFXR->cbValue,
  597.                             pFXR->cbValue+usSize);
  598.                }
  599.                szTrash=MultiTypeIndex(pFXR->aValue + pPDat->usMultiOffset,
  600.                                       pPDat->usIndex);
  601.                strcpy(szTrash+sizeof(USHORT),szScratch); /* Copy in new val */
  602.                pFXR->cbValue+=usSize;              /* Change buffer count   */
  603.  
  604.                return(FILE_CHANGED = TRUE);  /* Done with m-m edit */
  605.             }
  606.             else
  607.             {
  608.                FreeMem(pFXR->aValue,pFXR->cbValue); /* Release old Value mem */
  609.             }
  610.          }
  611.          GetMem(szNew,strlen(szScratch)+3);  /* +3 for Type & NULL */
  612.          pusPtr = (USHORT *) szNew;
  613.          *pusPtr= usXRType;                  /* Set type in new buffer       */
  614.          strcpy(szNew+2,szScratch);          /* Copy in the new value        */
  615.          pFXR->aValue = szNew;               /* Fix up the structure         */
  616.          pFXR->cbValue= strlen(szScratch)+3;
  617.  
  618.          return(FILE_CHANGED = TRUE);
  619.  
  620.       case XR_LPBINARY:
  621.       case XR_LPASCII:
  622.       case XR_LPMETAFILE:
  623.          if(pPDat->cbMulti)            /* It is a multi-type field */
  624.          {  /* szTrash points to field to edit, pusPtr to the field length */
  625.             szTrash=MultiTypeIndex(pFXR->aValue + pPDat->usMultiOffset,
  626.                                    pPDat->usIndex);
  627.             pusPtr = (USHORT *) ((CHAR *) szTrash + sizeof(USHORT));
  628.             usSize = *pusPtr;
  629.             if(usSize)  /* It isn't a new XR */
  630.             {
  631.                GetMem(szAscii,usSize+1); /* Set up inital value for edit */
  632.                memcpy(szAscii,szTrash+2*sizeof(USHORT),usSize);
  633.                szAscii[usSize]=NULL;
  634.             }
  635.             else                       /* No inital value */
  636.                szAscii = NULL;
  637.          }
  638.          else if(pFXR->cbValue)
  639.          {
  640.             usSize=GetUSHORT(pFXR,1);  /* Get size and set inital value */
  641.             if(usSize)
  642.             {
  643.                GetMem(szTrash,usSize+1); /* +1 for null */
  644.                memcpy(szTrash,pFXR->aValue+4,usSize);
  645.                szTrash[usSize]=NULL;
  646.                szAscii=szTrash;
  647.             }
  648.             else
  649.                szAscii = NULL;
  650.          }
  651.          else
  652.             szAscii = NULL;
  653.  
  654.          if(!WinDlgBox(HWND_DESKTOP,        /* Do an ascii text edit */
  655.                        hwnd,
  656.                        AsciiEditProc,
  657.                        NULL,
  658.                        IDD_ASCIIEDIT,
  659.                        &PDat))
  660.          {  /* Cancel, but check if memory needs to be freed before exit */
  661.             if(pPDat->cbMulti || pFXR->cbValue)
  662.                if(szAscii) /* It's not NULL */
  663.                   FreeMem(szAscii,strlen(szAscii)+1); /* +1 for NULL */
  664.  
  665.             return(FALSE);
  666.          }
  667.  
  668.          if(PDat.fFlag)              /* Handle the need/nice bit */
  669.             PDat.fFlag = 0x80;
  670.          if(PDat.fFlag != (PDat.fFlag & 0x80))
  671.             FILE_CHANGED = TRUE;
  672.          pFXR->fXR = (pFXR->fXR & 0x7f) | PDat.fFlag;
  673.  
  674.          if(stricmp(strupr(szXRName),pFXR->szName)) /* The name changed */
  675.             ChangeName(hwnd,pFXR,szXRName);
  676.  
  677.          if(pFXR->cbValue) /* There is a current value */
  678.          {
  679.             if(!strcmp(szAscii,szScratch))  /* It hasn't changed */
  680.             {
  681.                if(szAscii)
  682.                   FreeMem(szAscii,usSize+1);
  683.                return(TRUE);
  684.             }
  685.             if(szAscii)                  /* Free default value buffer */
  686.                FreeMem(szAscii,usSize+1);
  687.  
  688.             if(pPDat->cbMulti)   /* Do the whole thing here is multi-type */
  689.             {
  690.                USHORT usDelta = strlen(szScratch) - usSize; /* Change in len */
  691.                if(usDelta > 0) /* The new string is longer, resize first */
  692.                {
  693.                   ResizeMem(pFXR->aValue,pFXR->cbValue,pFXR->cbValue+usDelta);
  694.                   szTrash=MultiTypeIndex(pFXR->aValue + pPDat->usMultiOffset,
  695.                                          pPDat->usIndex+1);
  696.                   memmove(szTrash+usDelta,szTrash,
  697.                           pFXR->cbValue-(szTrash-pFXR->aValue));
  698.                }
  699.                else if(usDelta < 0) /* move first, resize afterwards */
  700.                {
  701.                   szTrash=MultiTypeIndex(pFXR->aValue + pPDat->usMultiOffset,
  702.                                          pPDat->usIndex+1);
  703.                   memmove(szTrash+usDelta,szTrash,
  704.                           pFXR->cbValue-(szTrash-pFXR->aValue));
  705.                   ResizeMem(pFXR->aValue,pFXR->cbValue,pFXR->cbValue+usDelta);
  706.                }
  707.                szTrash=MultiTypeIndex(pFXR->aValue + pPDat->usMultiOffset,
  708.                                       pPDat->usIndex);
  709.                memmove(szTrash+2*sizeof(USHORT),szScratch,strlen(szScratch));
  710.                pusPtr = (USHORT *) ((CHAR *) szTrash + sizeof(USHORT));
  711.                *pusPtr= strlen(szScratch);   /* Set the length field */
  712.  
  713.  
  714.                pFXR->cbValue += usDelta;     /* Adjust struct len field */
  715.  
  716.               return(FILE_CHANGED = TRUE);
  717.             }
  718.  
  719.             FreeMem(pFXR->aValue,pFXR->cbValue); /* Free up old value */
  720.          }
  721.          GetMem(szNew,strlen(szScratch)+4);    /* Get space for new value */
  722.          pusPtr = (USHORT *) szNew;
  723.          *pusPtr= usXRType;                    /* Set type field */
  724.          pusPtr++;
  725.          *pusPtr= strlen(szScratch);           /* Set length field */
  726.          memcpy(szNew+4,szScratch,*pusPtr);    /* Copy in new value */
  727.          pFXR->aValue = szNew;                 /* Adjust pointers */
  728.          pFXR->cbValue= strlen(szScratch)+4;   /* +4 for type and LP cnt */
  729.  
  730.          return(FILE_CHANGED = TRUE);
  731.  
  732.       case XR_MVMT:                    /* It's multi-value multi-type */
  733.          if(pFXR->cbValue == 0) /* It's a new XR */
  734.          {
  735.             GetMem(pFXR->aValue,3*sizeof(USHORT)); /* Allocate empty m-m XR */
  736.             pFXR->cbValue = 3*sizeof(USHORT);
  737.             pusPtr      = (USHORT *) pFXR->aValue;
  738.             *pusPtr = 0xffdf;                 /* Multi-value, multi-type */
  739.             pusPtr+=2;                        /* Skip type, codepage */
  740.             *pusPtr = 0;                      /* No fields initially     */
  741.             FILE_CHANGED = TRUE;
  742.          }
  743.  
  744.          /* Set up passed in data */
  745.          if(pPDat->cbMulti) /* It's a multi-type job  */
  746.          {
  747.             szNew   = MultiTypeIndex(pFXR->aValue + pPDat->usMultiOffset,
  748.                                      pPDat->usIndex);
  749.             szTrash = MultiTypeIndex(pFXR->aValue + pPDat->usMultiOffset,
  750.                                      pPDat->usIndex+1);
  751.             PDat.usMultiOffset = szNew - pFXR->aValue;
  752.             PDat.cbMulti       = szTrash - szNew;
  753.          }
  754.          else
  755.          {
  756.             PDat.usMultiOffset = 0;
  757.             PDat.cbMulti       = pFXR->cbValue;
  758.          }
  759.          PDat.Point         = (CHAR *) pFXR;
  760.  
  761.          WinDlgBox(HWND_DESKTOP,           /* Do the Multi-type edit */
  762.                    hwnd,
  763.                    MultiTypeProc,
  764.                    NULL,
  765.                    IDD_MULTIBOX,
  766.                    &PDat);
  767.          return(TRUE);
  768.  
  769.    }
  770. }
  771.  
  772.  
  773. /*
  774.  * Function name: XRExists()
  775.  *
  776.  */
  777.  
  778. BOOL XRExists(CHAR *szXRName)
  779. {
  780.    HOLDFXR *phFXR=pHoldFXR;
  781.  
  782.    while(phFXR)
  783.    {
  784.       if(!stricmp(szXRName,phFXR->szName))
  785.          return(TRUE);
  786.       phFXR=phFXR->next;
  787.    }
  788.    return(FALSE);
  789. }
  790.  
  791.  
  792. /*
  793.  * Function name: ChangeName()
  794.  *
  795.  */
  796.  
  797. VOID ChangeName(HWND hwnd,HOLDFXR *pFXR,CHAR *szName)
  798. {
  799.    CHAR *szTemp;
  800.    DELETELIST *pDL;
  801.  
  802.    GetMem(szTemp,strlen(szName+1));  /* Allocate space for new name */
  803.    if(!szTemp)
  804.       return;
  805.  
  806.    GetMem(pDL,(USHORT) sizeof(DELETELIST)); /* Allocate a new delete struct  */
  807.    pDL->XRName = pFXR->szName;              /* Fill in DeleteList struct     */
  808.    pDL->next   = pDelList;
  809.    pDelList    = pDL;
  810.  
  811.    strcpy(szTemp,szName);                   /* Copy name to permanent buffer */
  812.    pFXR->szName = szTemp;                   /* Fix up struct                 */
  813.    pFXR->cbName = (CHAR) strlen(szName);
  814.  
  815.    FILE_CHANGED = TRUE;
  816. }
  817.  
  818.  
  819. /*
  820.  * Function name: MultiTypeIndex()
  821.  */
  822.  
  823. CHAR *MultiTypeIndex(CHAR *pMulti, USHORT usIndex)
  824. {
  825.    USHORT *pusPtr;
  826.    USHORT usOffset;
  827.  
  828.    pMulti += 3*sizeof(USHORT);  /* skip over 0xffdf, codepage, and field cnt */
  829.  
  830.    while(usIndex--)             /* loop to skip over correct # of flds  */
  831.    {
  832.       pusPtr   = (USHORT *) pMulti;
  833.       usOffset = LookupXRType(*pusPtr);    /* Get offset of field type */
  834.  
  835.       pMulti += sizeof(USHORT);            /* Skip over the type field */
  836.  
  837.       switch(ConvTable[usOffset].usFldType)
  838.       {
  839.          case IDD_ASCIIZ:
  840.             while(*pMulti++);              /* Increment to point after NULL */
  841.             break;
  842.  
  843.          case IDD_LPDATA:
  844.             pusPtr = (USHORT *) pMulti;                /* Get the length */
  845.             pMulti += *pusPtr + sizeof(USHORT);        /* skip to end */
  846.             break;
  847.  
  848.          case IDD_MULTILIST:
  849.             if(*pusPtr == XR_MVMT) /* m-m, do a recursive call to skip fld */
  850.             {
  851.                pusPtr = (USHORT *) pMulti; /* points to field cnt */
  852.                pMulti = MultiTypeIndex(pMulti-sizeof(USHORT),*pusPtr);
  853.                break;
  854.             }
  855.             /* Not yet implemented for Multi-valued single-type stuff... */
  856.             break;
  857.       }
  858.    }
  859.    return(pMulti);
  860. }
  861.  
  862.  
  863. /*
  864.  * Function name: XRValueString()
  865.  */
  866.  
  867. CHAR *XRValueString(HWND hwnd,CHAR *aXRVal)
  868. {
  869.    USHORT *pusPtr= (USHORT *) aXRVal;  /* Points to XR Type     */
  870.    CHAR *szRet,*szTemp;        /* szRet points to return string */
  871.  
  872.    switch(*pusPtr)
  873.    {
  874.       case XR_ASCIIZ:    /* For asciiz strings, return MAXSHOWSIZE-1 chars */
  875.       case XR_ASCIIZFN:
  876.       case XR_ASCIIZXR:
  877.       case XR_ASN1:
  878.          aXRVal += sizeof(USHORT);
  879.          if(strlen(aXRVal)<MAXSHOWSIZE)
  880.          {
  881.             GetMem(szRet,strlen(aXRVal)+1);
  882.             strcpy(szRet,aXRVal);
  883.          }
  884.          else
  885.          {
  886.             GetMem(szRet,MAXSHOWSIZE);
  887.             strncpy(szRet,aXRVal,MAXSHOWSIZE-4);
  888.             strcpy (szRet+MAXSHOWSIZE-4,"...");
  889.             szRet[MAXSHOWSIZE-1]=NULL;
  890.          }
  891.          return(szRet);
  892.  
  893.       case XR_LPASCII:   /* Display up to first MAXSHOWSIZE-1 chars */
  894.       case XR_LPMETAFILE:
  895.          pusPtr++;
  896.          aXRVal += 2*sizeof(USHORT);
  897.          if(*pusPtr < MAXSHOWSIZE)
  898.          {
  899.             GetMem(szRet,*pusPtr +1);
  900.             strncpy(szRet,aXRVal,*pusPtr);
  901.             szRet[*pusPtr]=NULL;
  902.          }
  903.          else
  904.          {
  905.             GetMem(szRet,MAXSHOWSIZE);
  906.             strncpy(szRet,aXRVal,MAXSHOWSIZE-4);
  907.             strcpy (szRet+MAXSHOWSIZE-4,"...");
  908.             szRet[MAXSHOWSIZE-1]=NULL;
  909.          }
  910.          return(szRet);
  911.  
  912.       /* For the rest of the types, just display the field type */
  913.  
  914.       case XR_LPBINARY:
  915.          szTemp = "*** LP Binary ***";
  916.          break;
  917.  
  918.       case XR_LPBITMAP:
  919.          szTemp = "*** LP Bitmap ***";
  920.          break;
  921.  
  922.       case XR_LPICON:
  923.          szTemp = "*** LP Icon ***";
  924.          break;
  925.  
  926.       case XR_MVMT:
  927.          szTemp = "*** Multi-value Multi-type ***";
  928.          break;
  929.  
  930.       case XR_MVST:
  931.          szTemp = "*** Multi-value Single-type ***";
  932.          break;
  933.  
  934.       default:
  935.          szTemp = "*** Unknown XR type ***";
  936.          break;
  937.  
  938.    }
  939.    GetMem(szRet,strlen(szTemp)+1); /* Copy string from static to dynamic */
  940.    strcpy(szRet,szTemp);
  941.    return(szRet);
  942. }
  943.  
  944.  
  945. /*
  946.  * Function name: MultiAdd()
  947.  */
  948.  
  949. VOID MultiAdd(HWND hwnd, HOLDFXR *pFXR,PASSDATA FAR *pPDat)
  950. {
  951.    USHORT   usSize;
  952.    USHORT   *pusPtr;
  953.    CHAR     aUtility[6];      /* Used to hold the header for all XR types */
  954.    CHAR     *pInsert,*pValue;
  955.    PASSDATA PDat;
  956.  
  957.    PDat.Point = pFXR->szName;
  958.  
  959.    if(!WinDlgBox(HWND_DESKTOP,        /* Get the name and type */
  960.                  hwnd,
  961.                  AddXRProc,
  962.                  NULL,
  963.                  IDD_ADDXR,
  964.                  &PDat))
  965.       return;                         /* They said cancel */
  966.  
  967.    pusPtr = (USHORT *) aUtility;
  968.    *pusPtr= ConvTable[usRetXRType].usPrefix;   /* Set the type in header buf */
  969.  
  970.    switch(ConvTable[usRetXRType].usFldType)
  971.    {
  972.       case IDD_ASCIIZ:     /* make buffer look like: xx FF 00, size 3 */
  973.          usSize = 3;
  974.          aUtility[2]=0;
  975.          break;
  976.  
  977.       case IDD_LPDATA:     /* make the buffer look like: xx FF 00 00, size 4 */
  978.          usSize = 4;
  979.          pusPtr = (USHORT *) &aUtility[2];
  980.          *pusPtr= 0;
  981.          break;
  982.  
  983.       case IDD_MULTILIST:
  984.          usSize = 6;
  985.          pusPtr = (USHORT *) &aUtility[2];
  986.          *pusPtr= 0; /* Zero out codepage */
  987.          pusPtr++;
  988.          *pusPtr= 0; /* Zero out fld cnt */
  989.          break;
  990.    }
  991.    /* Increase XR size to accomodate the header */
  992.    ResizeMem(pFXR->aValue,pFXR->cbValue,pFXR->cbValue+usSize);
  993.  
  994.    pusPtr  = (USHORT *) ((CHAR *) pFXR->aValue + pPDat->usMultiOffset);
  995.    pusPtr+=2;    /* Point to the current number of m-m fields */
  996.  
  997.    /* Get ptr to beginning of current XR, scoot the rest down and insert
  998.       the 3-4 byte header at the end of the list.                        */
  999.    pInsert = MultiTypeIndex(pFXR->aValue+pPDat->usMultiOffset, *pusPtr);
  1000.    memmove(pInsert+usSize,pInsert, pFXR->cbValue-(pInsert-pFXR->aValue));
  1001.    memcpy(pInsert,aUtility,usSize);
  1002.  
  1003.    pFXR->cbValue += usSize;   /* Fix up the counts */
  1004.    pPDat->cbMulti+= usSize;
  1005.                                                   /* Set the PDat for call */
  1006.    PDat.Point         = (CHAR *) pFXR;
  1007.    PDat.cbMulti       = pPDat->cbMulti;
  1008.    PDat.usMultiOffset = pPDat->usMultiOffset;
  1009.    PDat.usIndex       = *pusPtr;
  1010.  
  1011.    if(!EditXRValue(hwnd,&PDat)) /* They canceled the edit */
  1012.    {  /* Move the XR's back to effectively kill the inserted header */
  1013.       memmove(pInsert,pInsert+usSize,pFXR->cbValue-(pInsert-pFXR->aValue));
  1014.       ResizeMem(pFXR->aValue,pFXR->cbValue,pFXR->cbValue-usSize);
  1015.       pFXR->cbValue -= usSize;   /* Adjust counters */
  1016.       pPDat->cbMulti-= usSize;
  1017.  
  1018.       return;
  1019.    }
  1020.  
  1021.    /* Reset pusPtr since EditXRValue could have moved the base address */
  1022.    pusPtr  = (USHORT *) ((CHAR *) pFXR->aValue + pPDat->usMultiOffset);
  1023.    pusPtr+=2;
  1024.  
  1025.    pInsert = MultiTypeIndex(pFXR->aValue+pPDat->usMultiOffset, *pusPtr);
  1026.  
  1027.    *pusPtr += 1; /* Field cnt incremented AFTER call to Edit */
  1028.  
  1029.    pValue = XRValueString(hwnd,pInsert);   /* Add new field to the list box */
  1030.  
  1031.    WinSendDlgItemMsg(hwnd, IDD_LBOX, LM_INSERTITEM,
  1032.                      MPFROM2SHORT(LIT_END,0),
  1033.                      MPFROMP(pValue));
  1034.    FreeMem(pValue,strlen(pValue)+1);
  1035.  
  1036.    FILE_CHANGED = TRUE;
  1037. }
  1038. /***************************************/
  1039. /***************************************/