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