MMRiff.pas
上传用户:hylc_2004
上传日期:2014-01-23
资源大小:46800k
文件大小:33k
源码类别:

Delphi控件源码

开发平台:

Delphi

  1. {========================================================================}
  2. {=                (c) 1995-98 SwiftSoft Ronald Dittrich                 =}
  3. {========================================================================}
  4. {=                          All Rights Reserved                         =}
  5. {========================================================================}
  6. {=  D 01099 Dresden             = Tel.: +0351-8012255                   =}
  7. {=  Loewenstr.7a                = info@swiftsoft.de                     =}
  8. {========================================================================}
  9. {=  Actual versions on http://www.swiftsoft.de/mmtools.html             =}
  10. {========================================================================}
  11. {=  This code is for reference purposes only and may not be copied or   =}
  12. {=  distributed in any format electronic or otherwise except one copy   =}
  13. {=  for backup purposes.                                                =}
  14. {=                                                                      =}
  15. {=  No Delphi Component Kit or Component individually or in a collection=}
  16. {=  subclassed or otherwise from the code in this unit, or associated   =}
  17. {=  .pas, .dfm, .dcu, .asm or .obj files may be sold or distributed     =}
  18. {=  without express permission from SwiftSoft.                          =}
  19. {=                                                                      =}
  20. {=  For more licence informations please refer to the associated        =}
  21. {=  HelpFile.                                                           =}
  22. {========================================================================}
  23. {=  $Date: 20.01.1998 - 18:00:00 $                                      =}
  24. {========================================================================}
  25. Unit MMRIFF;
  26. {$I COMPILER.INC}
  27. interface
  28. uses
  29. {$IFDEF WIN32}
  30.     Windows,
  31. {$ELSE}
  32.     WinTypes,
  33.     WinProcs,
  34. {$ENDIF}
  35.     SysUtils,
  36.     MMSystem,
  37.     MMUtils,
  38.     MMDIB,
  39.     MMAbout;
  40. const
  41.      CHUNK_MODIFIED = 1;    { chunk was modified                      }
  42.      CHUNK_REVERT   = 2;    { command to revert to original text      }
  43. {$IFDEF WIN32}
  44. type
  45.     THMMIO = HMMIO;             { whats that BORLAND !? }
  46. {$ENDIF}
  47. type
  48.     PChunk = ^TChunk;
  49.     TChunk = packed record
  50.        fcc: FOURCC;
  51.        cksize: Longint;
  52.        data: array[0..0] of Byte;
  53.     end;
  54.     PInfoData = ^TInfoData;
  55.     TInfoData = packed record
  56.        index       : Word;      { index into aINFO                        }
  57.        wFlags      : Word;      { flags for chunk                         }
  58.        dwINFOOffset: Longint;   { offset in file to INFO chunk            }
  59.        lpText      : PChar;     { text of modified chunk. None if NULL.   }
  60.        pNext       : PInfoData; { next read sub-chunk                     }
  61.     end;
  62.     PInfoChunk = ^TInfoChunk;
  63.     TInfoChunk = packed record
  64.        lpChunk     : PChar;     { complete chunk in memory (GlobalPtr)    }
  65.        cksize      : Longint;   { size of chunk data                      }
  66.        pHead       : PInfoData; { first sub-chunk data                    }
  67.     end;
  68.     TInfo = packed record
  69.       pFOURCC: PChar;
  70.       pShort : PChar;
  71.       pLong  : PChar;
  72.     end;
  73.     PDisp = ^TDisp;
  74.     TDisp = packed record
  75.        cfid   : Longint;        { Clipboard id of data                    }
  76.        wFlags : Word;           { flags for chunk                         }
  77.        lpChunk: PChar;          { ptr to original file data               }
  78.        lpData : PChar;          { ptr to modified data                    }
  79.        pNext  : PDISP;          { next in list                            }
  80.     end;
  81.     PDispList = ^TDispList;
  82.     TDispList = packed record
  83.        pHead : PDisp;           { first 'DISP' chunk                      }
  84.     end;
  85. const
  86.      aINFO: array[0..23] of TInfo = (
  87. (pFOURCC: 'IARL';
  88.  pShort: 'Archival Location';
  89.  pLong: 'Indicates where the subject of the file is archived.'),
  90. (pFOURCC: 'IART';
  91.  pShort: 'Artist'; 
  92.  pLong: 'Lists the artist of the original subject of the file. For example,'
  93.         +' "Michaelangelo."'),
  94. (pFOURCC: 'ICMS'; 
  95.  pShort: 'Commissioned'; 
  96.  pLong: 'Lists the name of the person or organization that commissioned '
  97.          +'the subject of the file. For example, "Pope Julian II."'),
  98. (pFOURCC: 'ICMT';
  99.  pShort: 'Comments';
  100.  pLong: 'Provides general comments about the file or the subject of the '
  101.         +'file. If the comment is several sentences long, end each sentence '
  102.         +'with a period. Do not include newline characters.'),
  103. (pFOURCC: 'ICOP';
  104.  pShort: 'Copyright';
  105.  pLong: 'Records the copyright information for the file. For example, '
  106.        +'"Copyright Encyclopedia International 1991." If there are multiple '
  107.        +'copyrights, separate them by a semicolon followed by a space.'),
  108. (pFOURCC: 'ICRD'; 
  109.  pShort: 'Creation date';
  110.  pLong: 'Specifies the date the subject of the file was created. List dates '
  111.        +'in year-month-day format, padding one-digit months and days with a'
  112.        +' zero on the left. For example, "1553-05-03" for May 3), 1553.'),
  113. (pFOURCC: 'ICRP'; 
  114.  pShort: 'Cropped'; 
  115.  pLong: 'Describes whether an image has been cropped and, if so, how it was '
  116.        +'cropped. For example, "lower right corner."'),
  117. (pFOURCC: 'IDIM';
  118.  pShort: 'Dimensions';
  119.  pLong: 'Specifies the size of the original subject of the file. For example, '
  120.        +'"8.5 in h, 11 in w."'),
  121. (pFOURCC: 'IDPI'; 
  122.  pShort: 'Dots Per Inch';
  123.  pLong: 'Stores dots per inch setting of the digitizer used to produce the '
  124.        +'file, such as "300."'),
  125. (pFOURCC: 'IENG'; 
  126.  pShort: 'Engineer';
  127.  pLong: 'Stores the name of the engineer who worked on the file. If there '
  128.        +'are multiple engineers, separate the names by a semicolon and a '
  129.        +'blank. For example, "Smith, John; Adams, Joe."'),
  130. (pFOURCC: 'IGNR'; 
  131.  pShort: 'Genre'; 
  132.  pLong: 'Describes the original work, such as, "landscape," "portrait," '
  133.        +'"still life," etc.'),
  134. (pFOURCC: 'IKEY'; 
  135.  pShort: 'Keywords';
  136.  pLong: 'Provides a list of keywords that refer to the file or subject of '
  137.        +'the file. Separate multiple keywords with a semicolon and a blank. For example, "Seattle; aerial view; scenery."'),
  138. (pFOURCC: 'ILGT';
  139.  pShort: 'Lightness'; 
  140.  pLong: 'Describes the changes in lightness settings on the digitizer required '
  141.        +'to produce the file. Note that the format of this information depends on hardware used.'),
  142. (pFOURCC: 'IMED'; 
  143.  pShort: 'Medium'; 
  144.  pLong: 'Describes the original subject of the file, such as, "computer image," '
  145.        +'"drawing," "lithograph," and so forth.'),
  146. (pFOURCC: 'INAM'; 
  147.  pShort: 'Name';
  148.  pLong: 'Stores the title of the subject of the file, such as, "Seattle From '
  149.        +'Above."'),
  150. (pFOURCC: 'IPLT'; 
  151.  pShort: 'Palette Setting';
  152.  pLong: 'Specifies the number of colors requested when digitizing an image, '
  153.        +'such as "256."'),
  154. (pFOURCC: 'IPRD';
  155.  pShort: 'Product';
  156.  pLong: 'Specifies the name of the title the file was originally intended '
  157.        +'for, such as "Encyclopedia of Pacific Northwest Geography."'),
  158. (pFOURCC: 'ISBJ'; 
  159.  pShort: 'Subject';
  160.  pLong: 'Describes the contents of the file, such as "Aerial view of Seattle."'),
  161. (pFOURCC: 'ISFT'; 
  162.  pShort: 'Software';
  163.  pLong: 'Identifies the name of the software package used to create the file, '
  164.        +'such as "Microsoft WaveEdit."'),
  165. (pFOURCC: 'ISHP'; 
  166.  pShort: 'Sharpness';
  167.  pLong: 'Identifies the changes in sharpness for the digitizer required to '
  168.        +'produce the file (the format depends on the hardware used).'),
  169. (pFOURCC: 'ISRC'; 
  170.  pShort: 'Source';
  171.  pLong: 'Identifies the name of the person or organization who supplied the '
  172.        +'original subject of the file. For example, "Trey Research."'),
  173. (pFOURCC: 'ISRF';
  174.  pShort: 'Source Form';
  175.  pLong: 'Identifies the original form of the material that was digitized, '
  176.        +'such as "slide," "paper," "map," and so forth. This is not necessarily '
  177.        +'the same as IMED.'),
  178. (pFOURCC: 'ITCH'; 
  179.  pShort: 'Technician'; 
  180.  pLong: 'Identifies the technician who digitized the subject file. For '
  181.        +'example, "Smith, John."'),
  182. (pFOURCC: NIL;
  183.  pShort: NIL;
  184.  pLong: NIL));
  185. {*************************************************************************}
  186. { error returns from RIFF functions                                       }
  187. {*************************************************************************}
  188. const
  189.      RIFFERR_BASE      = 0;
  190.      RIFFERR_NOERROR   = 0;
  191.      RIFFERR_ERROR     = RIFFERR_BASE+1;
  192.      RIFFERR_BADPARAM  = RIFFERR_BASE+2;
  193.      RIFFERR_FILEERROR = RIFFERR_BASE+3;
  194.      RIFFERR_NOMEM     = RIFFERR_BASE+4;
  195.      RIFFERR_BADFILE   = RIFFERR_BASE+5;
  196. (************************************************************************)
  197. function  mmioFourCC(ch0,ch1,ch2,ch3: Char): FourCC;
  198. function  RiffCopyChunk(hmmioSrc,hmmioDst: THMMIO; lpck: PMMCKINFO): Boolean;
  199. function  RiffCopyList(hmmioSrc,hmmioDst: THMMIO; lpck: PMMCKINFO): Boolean;
  200. (************************************************************************)
  201. function  RiffInitINFO(Var lpInfo: PInfoChunk): integer;
  202. function  RiffCopyInfo(Var lpInfoDst: PInfoChunk; lpInfoSrc: PInfoChunk): integer;
  203. function  RiffFreeINFO(Var lpInfo: PInfoChunk): integer;
  204. function  RiffReadINFO(hmmio: THMMIO; lpck: PMMCKINFO; lpInfo: PInfoChunk): integer;
  205. function  RiffWriteINFO(hmmio: THMMIO; lpInfo: PInfoChunk): integer;
  206. function  RiffCreateINFO(wFlags, id: Word; dwInfoOffset: Longint; lpText: PChar): PInfoData;
  207. procedure RiffInsertINFO(lpInfo: PInfoChunk; pInfo: PInfoData);
  208. function  RiffFindPIINFO(lpInfo: PInfoChunk; fcc: FOURCC): PInfoData;
  209. procedure RiffModifyINFO(lpInfo: PInfoChunk; pi: PInfoData;
  210.                          wFlags: Word; dw: Longint; lpText: PChar);
  211. function  RiffFindaINFO(fcc: FOURCC): integer;
  212. function  RiffParseINFO(lpInfo: PInfoChunk): integer;
  213. (************************************************************************)
  214. function  RiffInitDISP(Var lpDisp: PDispList): integer;
  215. function  RiffCopyDISP(lpDispDst, lpDispSrc: PDISPList): integer;
  216. function  RiffFreeDISP(Var lpDisp: PDispList; FreeList: Boolean): integer;
  217. function  RiffReadDISP(hmmio: THMMIO; lpck: PMMCKINFO; Var lpDisp: PDispList): integer;
  218. function  RiffWriteDISP(hmmio: THMMIO; lpDisp: PDispList): integer;
  219. function  RiffCreateDISP(wFlags: Word; id: Longint; lpChunk, lpData: PChar): PDisp;
  220. procedure RiffInsertDISP(lpDisp: PDispList; pd: PDisp);
  221. procedure RiffModifyDISP(lpDisp: PDispList; pd: PDisp;
  222.                          wFlags: Word; lpData: PChar);
  223. implementation
  224. {**************************************************************************}
  225. function mmioFourCC(ch0,ch1,ch2,ch3: Char): FourCC;
  226. begin
  227.      Result := Longint(ch0) OR
  228.                (Longint(ch1) shl 8) OR
  229.                (Longint(ch2) shl 16) OR
  230.                (Longint(ch3) shl 24);
  231. end;
  232. {**************************************************************************}
  233. function RiffCopyChunk(hmmioSrc, hmmioDst: THMMIO; lpck: PMMCKINFO): Boolean;
  234. Label rscc_Error;
  235. var
  236.    ck: TMMCKINFO;
  237.    pBuf: PChar;
  238. begin
  239.      Result := False;
  240.      pBuf := GlobalAllocPtr(GHND, lpck^.cksize);
  241.      if (pBuf = NIL) then
  242.         goto rscc_Error;
  243.      ck.ckid   := lpck^.ckid;
  244.      ck.cksize := lpck^.cksize;
  245.      if mmioCreateChunk(hmmioDst, @ck, 0) <> 0 then
  246.         goto rscc_Error;
  247.      if mmioRead(hmmioSrc, pBuf, lpck^.cksize) <> Longint(lpck^.cksize) then
  248.         goto rscc_Error;
  249.      if mmioWrite(hmmioDst, pBuf, lpck^.cksize) <> Longint(lpck^.cksize) then
  250.         goto rscc_Error;
  251.      if mmioAscend(hmmioDst, @ck, 0) <> 0 then
  252.         goto rscc_Error;
  253.      Result := True;
  254. rscc_Error:
  255.      if (pBuf <> NIL) then GlobalFreePtr(pBuf);
  256. end;
  257. {**************************************************************************}
  258. function RiffCopyList(hmmioSrc,hmmioDst: THMMIO; lpck: PMMCKINFO): Boolean;
  259. Label
  260.    rscl_Error;
  261. Var
  262.    ck: TMMCKINFO;
  263.    pBuf: PChar;
  264.    dwCopySize: Longint;
  265. begin
  266.      Result := False;
  267.      pBuf := GlobalAllocPtr(GHND,lpck^.cksize);
  268.      if (pBuf = NIL ) then
  269.         goto rscl_Error;
  270.      dwCopySize := lpck^.cksize;
  271.      { mmio leaves us after LIST ID }
  272.      ck.ckid    := lpck^.ckid;
  273.      ck.cksize  := dwCopySize;
  274.      ck.fccType := lpck^.fccType;
  275.      if mmioCreateChunk(hmmioDst, @ck, MMIO_CREATELIST) <> 0 then
  276. goto rscl_Error;
  277.      { we already wrote 'LIST' ID, so reduce byte count }
  278.      dec(dwCopySize, sizeof(FOURCC));
  279.      if mmioRead(hmmioSrc, pBuf, dwCopySize) <> dwCopySize then
  280.         goto rscl_Error;
  281.      if mmioWrite(hmmioDst, pBuf, dwCopySize) <> dwCopySize then
  282.         goto rscl_Error;
  283.      if mmioAscend(hmmioDst, @ck, 0) <> 0 then
  284.         goto rscl_Error;
  285.      Result := True;
  286. rscl_Error:
  287.     if (pBuf <> NIL) then GlobalFreePtr(pBuf);
  288. End;
  289. {**************************************************************************}
  290. function RiffInitINFO(Var lpInfo: PInfoChunk): integer;
  291. Var
  292.    id: Word;
  293.    pi: PInfoData;
  294. begin
  295.     lpInfo := GlobalAllocPtr(GHND,sizeof(TInfoChunk));
  296.     if (lpInfo <> Nil) then
  297.     begin
  298.          id := 0;
  299.          while (aINFO[id].pFOURCC <> NIL) do
  300.          begin
  301.       pI := RiffCreateINFO(0, id, 0, NIL);   { create empty INFO }
  302.       RiffInsertINFO(lpInfo, pI);
  303.               inc(id);
  304.          end;
  305.          Result := RIFFERR_NOERROR;
  306.     end
  307.     else Result := RIFFERR_NOMEM;
  308. end;
  309. {**************************************************************************}
  310. function RiffReadINFO(hmmio: THMMIO; lpck: PMMCKINFO; lpInfo: PInfoChunk): integer;
  311. Var
  312.    dwInfoSize: Longint;
  313. begin
  314.      Result := RIFFERR_NOERROR;
  315.      
  316.      dwInfoSize := lpck^.cksize - sizeof(FOURCC); { take out 'INFO' }
  317.      if dwInfoSize > 0 then
  318.      begin
  319.         lpInfo^.cksize := dwInfoSize;
  320.         lpInfo^.lpChunk := GlobalAllocPtr(GHND,dwInfoSize);
  321.         if (lpInfo^.lpChunk <> NIL) then
  322.         begin
  323.            if mmioRead(hmmio, PChar(lpInfo^.lpChunk), dwInfoSize) <> dwInfoSize then
  324.               Result := RIFFERR_FILEERROR
  325.            else
  326.               Result := RiffParseINFO(lpInfo);
  327.         end
  328.         else Result := RIFFERR_NOMEM;
  329.      end;
  330. end;
  331. {**************************************************************************}
  332. function RiffWriteINFO(hmmio: THMMIO; lpInfo: PInfoChunk): integer;
  333. Var
  334.    ck: TMMCKINFO;
  335.    ckInfo: TMMCKINFO;
  336.    pi: PInfoData;
  337.    lpstr: PChar;
  338.    fList: Boolean;
  339. begin
  340.      fList := False;
  341.      Result := RIFFERR_BADPARAM;
  342.      if (hmmio = 0) OR (lpInfo = Nil) then exit;
  343.      Result := RIFFERR_FILEERROR;
  344.      ckINFO.ckid   := mmioFOURCC('L', 'I', 'S', 'T');
  345.      ckINFO.cksize := 0;  { mmio fill it in later }
  346.      ckINFO.fccType:= mmioFOURCC('I', 'N', 'F', 'O');
  347.      pI := lpInfo^.pHead;
  348.      while (pI <> Nil) do
  349.      begin
  350.   if (pI^.lpText <> Nil) then
  351.              { Modified text }
  352.      lpstr := pi^.lpText
  353.           else if (pi^.dwINFOOffset <> 0) then
  354.      { default text }
  355.      lpstr := (lpInfo^.lpChunk+pI^.dwINFOOffset)
  356.           else
  357.      { no text }
  358.      lpstr := Nil;
  359.           if (lpstr <> Nil) and (lpstr^ <> #0) then
  360.           begin
  361.      if (Not fList) then
  362.              begin
  363.         { only create if needed... }
  364.         if mmioCreateChunk(hmmio, @ckINFO, MMIO_CREATELIST) <> 0 then
  365.                    exit;
  366. fList := True;
  367.              end;
  368.      ck.ckid := mmioStringToFOURCC(aINFO[pI^.index].pFOURCC,0);
  369.      ck.cksize := StrLen(lpstr)+1;
  370.      ck.fccType := 0;
  371.      if mmioCreateChunk(hmmio, @ck, 0) <> 0 then
  372. exit;
  373.      if mmioWrite(hmmio, lpstr, ck.cksize) <> Longint(ck.cksize) then
  374. exit;
  375.              if mmioAscend(hmmio, @ck, 0) <> 0 then
  376. exit;
  377.           end;
  378.   pi := pi^.pnext;
  379.      end;
  380.      if fList then
  381.      begin
  382.   if mmioAscend(hmmio, @ckINFO, 0) <> 0 then
  383.      exit;
  384.      end;
  385.      Result := RIFFERR_NOERROR;
  386. end;
  387. {**************************************************************************}
  388. function RiffCopyINFO(Var lpInfoDst: PInfoChunk; lpInfoSrc: PInfoChunk): integer;
  389. Var
  390.    pISrc,pIDst: PInfoData;
  391.    lpStr,pBuf: PChar;
  392. begin
  393.      Result := RIFFERR_BADPARAM;
  394.      if (lpInfoSrc = Nil) or (lpInfoDst = Nil) then exit;
  395.      pISrc := lpInfoSrc^.pHead;
  396.      while (pISrc <> Nil) do
  397.      begin              
  398.   if (pISrc^.lpText <> Nil) then
  399.              { Modified text }
  400.      lpStr := piSrc^.lpText
  401.           else if (pISrc^.wFlags <> CHUNK_MODIFIED) and (pISrc^.dwINFOOffset <> 0) then
  402.      { default text }
  403.      lpStr := (lpInfoSrc^.lpChunk+pISrc^.dwINFOOffset)
  404.           else
  405.      { no text }
  406.      lpStr := nil;
  407.           if (lpStr <> Nil) and (lpStr^ <> #0) then
  408.           begin
  409.              { the new text MUST allocated with GlobalAlloc }
  410.              pBuf := GlobalAllocPtr(GHND,StrLen(lpStr)+1);
  411.              piDst := RiffFindPIINFO(lpInfoDst, mmioStringToFOURCC(aINFO[pISrc^.index].pFOURCC,0));
  412.      RiffModifyINFO(lpInfoDst, piDst, CHUNK_MODIFIED, 0, StrCopy(pBuf,lpStr));
  413.          end;
  414.  piSrc := piSrc^.pNext;
  415.      end;
  416.      Result := RIFFERR_NOERROR;
  417. end;
  418. {**************************************************************************}
  419. procedure RiffInsertINFO(lpInfo: PInfoChunk; pInfo: PInfoData);
  420. Var
  421.    pi: PInfoData;
  422. begin
  423.      if (lpInfo = NIL) then exit;
  424.      if (lpInfo^.pHead = NIL) then
  425.      begin
  426.           lpInfo^.pHead := pInfo;
  427.   exit;
  428.      end;
  429.      pi := lpInfo^.pHead;
  430.      while (pi^.pnext <> NIL) do pi := pi^.pnext;
  431.      { insert at end }
  432.      pI^.pnext := pInfo;
  433. end;
  434. {**************************************************************************}
  435. function RiffCreateINFO(wFlags, id: Word; dwInfoOffset: Longint; lpText: PChar): PInfoData;
  436. Var
  437.    pi: PInfoData;
  438. begin
  439.      pI := GlobalAllocPtr(GHND,sizeof(TInfoData));
  440.      if (pI <> Nil) then
  441.      begin
  442.           pI^.index := id;
  443.           pI^.wFlags := wFlags;
  444.           pI^.dwINFOOffset := dwInfoOffset;
  445.           pI^.lpText := lpText;
  446.           Result := pi;
  447.      end
  448.      else Result := Nil;
  449. end;
  450. {**************************************************************************}
  451. function RiffFindPIINFO(lpInfo: PInfoChunk; fcc: FOURCC): PInfoData;
  452. Var
  453.    pi: PInfoData;
  454. begin
  455.      pi := lpInfo^.pHead;
  456.      while (pI <> Nil) do
  457.      begin
  458.   if mmioStringToFOURCC(aINFO[pI^.index].pFOURCC,0) = fcc then
  459.           begin
  460.        Result := pi;
  461.                exit;
  462.           end;
  463.           pi := pi^.pnext;
  464.      end;
  465.      Result := Nil;
  466. end;
  467. {**************************************************************************}
  468. procedure RiffModifyINFO(lpInfo: PInfoChunk;
  469.                          pi: PInfoData;
  470.                          wFlags: Word; dw: Longint; lpText: PChar);
  471. begin
  472.      if (pI = Nil) then exit;
  473.      if (wFlags and CHUNK_MODIFIED = 0) and
  474.         (wFlags and CHUNK_REVERT = 0) then pi^.dwINFOOffset := dw;
  475.      if (pi^.lpText <> Nil) then
  476.      begin
  477.         if (lpText <> Nil) then
  478.   begin
  479.        if StrComp(lpText,pi^.lpText) = 0 then
  480.                begin
  481.            { they are the same, don't bother changing... }
  482.            GlobalFreePtr(lpText);
  483.                end
  484.        else
  485.        begin
  486.    GlobalFreePtr(pi^.lpText);
  487.                    if (lpText^ <> #0) then
  488.                    begin
  489.                       { new text... }
  490.                       pi^.lpText := lpText;
  491.                       pi^.wFlags := wFlags;
  492.                    end
  493.                    else
  494.                    begin
  495.                       { new is blank, do nothing... }
  496.                       GlobalFreePtr(lpText);
  497.                       pi^.lpText := nil;
  498.                       pi^.wFlags := CHUNK_REVERT;
  499.                    end;
  500.                end;
  501.           end
  502.   else if (wFlags AND CHUNK_REVERT <> 0) then
  503.   begin
  504.        GlobalFreePtr(pi^.lpText);
  505.        pi^.lpText := Nil;
  506.                pi^.wFlags := wFlags;
  507.           end;
  508.      end
  509.      else if (lpText <> Nil) then
  510.      begin
  511.   { if no read data, don't bother to check.... }
  512.   if (lpInfo^.lpChunk = Nil) or (pi^.dwINFOOffset = 0) then
  513.   begin
  514.                if (lpText^ <> #0) then
  515.                begin
  516.                   { new text... }
  517.                   pi^.lpText := lpText;
  518.                   pi^.wFlags := wFlags;
  519.                end
  520.                else
  521.                begin
  522.                   { new is blank, do nothing... }
  523.                   GlobalFreePtr(lpText);
  524.                end;
  525.           end
  526.   else if StrComp(lpText, PChar(lpInfo^.lpChunk+pI^.dwINFOOffset)) <> 0 then
  527.   begin
  528.              if (lpText^ <> #0) then
  529.              begin
  530.                 { new text... }
  531.               pi^.lpText := lpText;
  532.                 pi^.wFlags := wFlags;
  533.              end
  534.              else
  535.              begin
  536.                 { new is blank }
  537.                 if PChar(lpInfo^.lpChunk+pI^.dwINFOOffset)^ <> #0 then
  538.                 begin
  539.                    { original was not blank }
  540.                    pi^.lpText := lpText;
  541.                    pi^.wFlags := wFlags;
  542.                 end
  543.                 else
  544.                 begin
  545.                    { do nothing }
  546.                    GlobalFreePtr(lpText);
  547.                 end;
  548.              end;
  549.           end
  550.   else
  551.           begin
  552.      { the same, don't bother... }
  553.      GlobalFreePtr(lpText);
  554.           end;
  555.      end;
  556. end;
  557. {**************************************************************************}
  558. function RiffFindaINFO(fcc: FOURCC): integer;
  559. Var
  560.    id: Word;
  561. begin
  562.      id := 0;
  563.      while aINFO[id].pFOURCC <> nil do
  564.      begin
  565.   if mmioStringToFOURCC(aINFO[id].pFOURCC, 0) = fcc then
  566.           begin
  567.                Result := id;
  568.                exit;
  569.           end;
  570.           inc(id);
  571.      end;
  572.      Result := -1;
  573. end;
  574. {**************************************************************************}
  575. function RiffParseINFO(lpInfo: PInfoChunk): integer;
  576. Var
  577.    pBuf: PChar;
  578.    dwCurInfoOffset: Longint;
  579.    pi: PInfoData;
  580.    lpck: PChunk;
  581. begin
  582.      pBuf := lpInfo^.lpChunk;
  583.      dwCurInfoOffset := 0;
  584.      while dwCurInfoOffset < lpInfo^.cksize do
  585.      begin
  586.   lpck := PChunk(PChar(pBuf+dwCurInfoOffset));
  587.           { dwCurInfoOffset is offset of data }
  588.   inc(dwCurInfoOffset, sizeof(TChunk)-1);
  589.   pi := RiffFindPIINFO(lpInfo, lpck^.fcc);
  590.   if (pi <> Nil) then
  591.           begin
  592.        { modify entry to show text (data) from file... }
  593.        RiffModifyINFO(lpInfo, pi, 0, dwCurInfoOffset, NIL);
  594.           end;
  595.           { skip past data }
  596.   inc(dwCurInfoOffset, lpck^.cksize+(lpck^.cksize AND 1));
  597.      end;
  598.      Result := RIFFERR_NOERROR;
  599. end;
  600. {**************************************************************************}
  601. function RiffFreeINFO(Var lpInfo: PInfoChunk): integer;
  602. Var
  603.     pi, pit:  PInfoData;
  604. begin
  605.      Result := RIFFERR_BADPARAM;
  606.      if (lpInfo = Nil) then exit;
  607.      if (lpInfo^.lpChunk <> Nil) then
  608.       GlobalFreePtr(lpInfo^.lpChunk);
  609.      pi := lpInfo^.pHead;
  610.      while (pi <> Nil) do
  611.      begin
  612.   pit := pi;
  613.   pi := pi^.pnext;
  614.           if (pit^.lpText <> nil) then GlobalFreePtr(pit^.lpText);
  615.   GlobalFreePtr(pit);
  616.      end;
  617.      GlobalFreePtr(lpInfo);
  618.      lpInfo := NIL;
  619.      Result := RIFFERR_NOERROR;
  620. end;
  621. {**************************************************************************}
  622. function RiffInitDISP(Var lpDisp: PDispList): integer;
  623. begin
  624.     lpDisp := GlobalAllocPtr(GHND,sizeof(TDispList));
  625.     if (lpDisp <> Nil) then
  626.         Result := RIFFERR_NOERROR
  627.     else
  628.         Result := RIFFERR_NOMEM;
  629. end;
  630. {**************************************************************************}
  631. function RiffCopyDISP(lpDispDst, lpDispSrc: PDISPList): integer;
  632. Label
  633.    riff_DI_Error;
  634. var
  635.    pdSrc,pdDst: PDisp;
  636.    lpData: PChar;
  637.    dwSize: Longint;
  638. begin
  639.    Result := RIFFERR_BADPARAM;
  640.    if (lpDispDst = nil) or (lpDispSrc = nil) then exit;
  641.    Result := RIFFERR_ERROR;
  642.    pdDst := nil;
  643.    { first remove all old 'DISP' chunks }
  644.    if RiffFreeDISP(lpDispDst,False) <> 0 then
  645.       goto riff_DI_Error;
  646.    Result := RIFFERR_NOMEM;
  647.    pdSrc := lpDispSrc^.pHead;
  648.    while pdSrc <> nil do
  649.    begin
  650.       if (pdSrc^.cfid <> 0) then
  651.       begin
  652.          if (pdSrc^.lpChunk <> nil) or (pdSrc^.lpData <> nil) then
  653.          begin
  654.             if (pdSrc^.lpData <> nil) then
  655.                 { modified Data }
  656.                 lpData := pdSrc^.lpData
  657.             else if (pdSrc^.wFlags <> CHUNK_MODIFIED) then
  658.                 { original file Data }
  659.                 lpData := pdSrc^.lpChunk
  660.             else
  661.                 lpData := nil;
  662.             if (lpData <> nil) and (lpData^ <> #0) then
  663.             begin
  664.                pdDst := RiffCreateDISP(0, pdSrc^.cfid, nil, nil);
  665.                if (pdDst = nil) then
  666.                    goto riff_DI_Error;
  667.                dwSize := GlobalMemSize(lpData);
  668.                pdDst^.lpData := GlobalAllocPtr(GHND,dwSize);
  669.                if (pdDst^.lpData = nil) then
  670.                   goto riff_DI_Error;
  671.                GlobalMoveMem(lpData^,pdDst^.lpData^,dwSize);
  672.                RiffInsertDISP(lpDispDst, pdDst);
  673.             end;
  674.          end;
  675.       end;
  676.       pdSrc := pdSrc^.pNext;
  677.    end;
  678.    Result := RIFFERR_NOERROR;
  679.    exit;
  680. riff_DI_Error:
  681.    if (pdDst <> nil) then
  682.    begin
  683.       if (pdDst^.lpData <> nil) then GlobalFreePtr(pdDst^.lpData);
  684.       GlobalFreePtr(pdDst);
  685.    end;
  686. end;
  687. {**************************************************************************}
  688. function RiffReadDISP(hmmio: THMMIO; lpck: PMMCKINFO; Var lpDisp: PDispList): integer;
  689. Label
  690.    riff_DI_Error;
  691. Var
  692.    pd: PDisp;
  693.    dwDispSize: Longint;
  694. begin
  695.      Result := RIFFERR_BADPARAM;
  696.      if (lpDisp = nil) then exit;
  697.      Result := RIFFERR_NOMEM;
  698.      { create empty 'DISP' }
  699.      pd := RiffCreateDISP(0, 0, nil, nil);
  700.      if (pd = nil) then
  701.         goto riff_DI_Error;
  702.      dwDispSize := lpck^.cksize - sizeof(pd^.cfid);{ take out id of Data }
  703.      if (dwDispSize > 0) then
  704.      begin
  705.         pd^.lpChunk := GlobalAllocPtr(GHND,dwDispSize);
  706.         if (pd^.lpChunk = nil) then
  707.            goto riff_DI_Error;
  708.         Result := RIFFERR_FILEERROR;
  709.         if mmioRead(hmmio, PChar(@pd^.cfid), sizeof(pd^.cfid)) <> sizeof(pd^.cfid) then
  710.            goto riff_DI_Error;
  711.         if mmioRead(hmmio, pd^.lpChunk, dwDispSize) <> dwDispSize then
  712.            goto riff_DI_Error;
  713.         RiffInsertDISP(lpDisp, pd);
  714.         Result := RIFFERR_NOERROR;
  715.         exit;
  716.      end;
  717.      Result := RIFFERR_NOERROR;
  718. riff_DI_Error:
  719.      if (pd <> nil) then
  720.      begin
  721.         if (pd^.lpChunk <> nil) then GlobalFreePtr(pd^.lpChunk);
  722.         GlobalFreePtr(pd);
  723.      end;
  724. end;
  725. {**************************************************************************}
  726. function RiffWriteDISP(hmmio: THMMIO; lpDisp: PDispList): integer;
  727. Var
  728.    ckDISP: TMMCKINFO;
  729.    pData : PChar;
  730.    pd    : PDisp;
  731.    dwSize: Longint;
  732. begin
  733.      Result := RIFFERR_BADPARAM;
  734.      if (hmmio = 0) or (lpDisp = nil) then exit;
  735.      Result := RIFFERR_FILEERROR;
  736.      pd := lpDisp^.pHead;
  737.      while (pd <> nil) do
  738.      with pd^ do
  739.      begin
  740. if ((cfid = CF_DIB) or (cfid = CF_TEXT)) then
  741.         begin
  742.            if (lpChunk <> nil) or (lpData <> nil) then
  743.            begin
  744.               if (lpData <> nil) then
  745.                   { modified Data }
  746.                   pData := lpData
  747.               else if (wFlags <> CHUNK_MODIFIED) then
  748.                   { original file Data }
  749.                   pData := lpChunk
  750.               else
  751.                   pData := nil;
  752.               if (pData <> nil) and (pData^ <> #0) then
  753.               begin
  754.                  ckDISP.ckid   := mmioFOURCC('D', 'I', 'S', 'P');
  755.                  ckDISP.cksize := 0;  { mmio fill it in later }
  756.          { create new 'DISP' chunk }
  757.          if mmioCreateChunk(hmmio, @ckDISP, 0) <> 0 then
  758.                     exit;
  759.                  dwSize := sizeOf(cfid);
  760.                  if mmioWrite(hmmio, @cfid, dwSize) <> dwSize then
  761.                     exit;
  762.                  case cfid of
  763.                    CF_TEXT: dwSize := StrLen(pData)+1;
  764.                    CF_DIB : dwSize := DIB_SIZE(PDIB(pData));
  765.                  end;
  766.                  if mmioWrite(hmmio, pData, dwSize) <> dwSize then
  767.                     exit;
  768.                  if mmioAscend(hmmio, @ckDISP, 0) <> 0 then
  769.     exit;
  770.               end;
  771.            end;
  772.         end;
  773.         pd := pd^.pNext;
  774.      end;
  775.      Result := RIFFERR_NOERROR;
  776. end;
  777. {**************************************************************************}
  778. function RiffCreateDISP(wFlags: Word; id: Longint; lpChunk, lpData: PChar): PDisp;
  779. Var
  780.    pd: PDisp;
  781. begin
  782.      pd := GlobalAllocPtr(GHND,sizeof(TDisp));
  783.      if (pd <> Nil) then
  784.      begin
  785.           pd^.cfid := id;
  786.           pd^.wFlags := wFlags;
  787.           pd^.lpChunk := lpChunk;
  788.           pd^.lpData := lpData;
  789.           Result := pd;
  790.      end
  791.      else Result := nil;
  792. end;
  793. {**************************************************************************}
  794. procedure RiffInsertDISP(lpDisp: PDispList; pd: PDisp);
  795. Var
  796.    pdi: PDisp;
  797. begin
  798.      if (lpDisp = nil) then exit;
  799.      if (lpDisp^.pHead = nil) then
  800.      begin
  801.           lpDisp^.pHead := pd;
  802.   exit;
  803.      end;
  804.      pdi := lpDisp^.pHead;
  805.      while (pdi^.pNext <> NIL) do pdi := pdi^.pNext;
  806.      { insert at end }
  807.      pdi^.pNext := pd;
  808. end;
  809. {**************************************************************************}
  810. procedure RiffModifyDISP(lpDisp: PDispList; pd: PDisp;
  811.                          wFlags: Word; lpData: PChar);
  812. var
  813.    Size: Longint;
  814. begin
  815.      if (pd = Nil) then exit;
  816.      if (pd^.lpData <> Nil) then
  817.      begin
  818.         if (lpData <> Nil) then
  819.   begin
  820.                Size := GlobalMemSize(lpData);
  821.                if (Size = GlobalMemSize(pd^.lpData)) and
  822.                    (GlobalCmpMem(lpData^,pd^.lpData^,Size) = True) then
  823.                begin
  824.            { they are the same, don't bother changing... }
  825.            GlobalFreePtr(lpData);
  826.                end
  827.        else
  828.        begin
  829.    GlobalFreePtr(pd^.lpData);
  830.                    if (lpData^ <> #0) then
  831.                    begin
  832.                       { new data... }
  833.                       pd^.lpData := lpData;
  834.                       pd^.wFlags := wFlags;
  835.                    end
  836.                    else
  837.                    begin
  838.                       { new is blank, do nothing... }
  839.                       GlobalFreePtr(lpData);
  840.                       pd^.lpData := nil;
  841.                       pd^.wFlags := CHUNK_REVERT;
  842.                    end;
  843.                end;
  844.           end
  845.   else
  846.           begin
  847.        GlobalFreePtr(pd^.lpData);
  848.        pd^.lpData := Nil;
  849.                pd^.wFlags := CHUNK_REVERT;
  850.         end;
  851.      end
  852.      else if (lpData <> Nil) then
  853.      begin
  854.   { if no read data, don't bother to check.... }
  855.   if (pd^.lpChunk = Nil) then
  856.   begin
  857.                if (lpData^ <> #0) then
  858.                begin
  859.                   { new text... }
  860.                   pd^.lpData := lpData;
  861.                   pd^.wFlags := wFlags;
  862.                end
  863.                else
  864.                begin
  865.                   { new is blank, do nothing... }
  866.                   GlobalFreePtr(lpData);
  867.                end;
  868.           end
  869.   else
  870.           begin
  871.              Size := GlobalMemSize(lpData);
  872.              if IsBadReadPtr(pd^.lpChunk,Size) or
  873.                 (GlobalCmpMem(lpData^, pd^.lpChunk^, Size) = False) then
  874.      begin
  875.                 if (lpData^ <> #0) then
  876.                 begin
  877.                    { new data... }
  878.                    pd^.lpData := lpData;
  879.                    pd^.wFlags := wFlags;
  880.                 end
  881.                 else
  882.                 begin
  883.                    { new is blank }
  884.                    if pd^.lpChunk^ <> #0 then
  885.                    begin
  886.                       { original was not blank }
  887.                       pd^.lpData := lpData;
  888.                       pd^.wFlags := wFlags;
  889.                    end
  890.                    else
  891.                    begin
  892.                       { do nothing }
  893.                       GlobalFreePtr(lpData);
  894.                    end;
  895.                 end;
  896.              end
  897.      else
  898.              begin
  899.           { the same, don't bother... }
  900.           GlobalFreePtr(lpData);
  901.              end;
  902.           end;
  903.      end
  904.      else pd^.wFlags := wFlags;
  905. end;
  906. {**************************************************************************}
  907. function RiffFreeDISP(Var lpDisp: PDispList; FreeList: Boolean): integer;
  908. Var
  909.    p,pd:  PDisp;
  910. begin
  911.    Result := RIFFERR_BADPARAM;
  912.    if (lpDisp = nil) then exit;
  913.    pd := lpDisp^.pHead;
  914.    while (pd <> nil) do
  915.    begin
  916.       p := pd;
  917.       pd := pd^.pNext;
  918.       if (p^.lpChunk <> nil) then
  919.       begin
  920.          GlobalFreePtr(p^.lpChunk);
  921.          p^.lpChunk := nil;
  922.       end;
  923.       if (p^.lpData <> nil) then
  924.       begin
  925.          GlobalFreePtr(p^.lpData);
  926.          p^.lpData := nil;
  927.       end;
  928.       GlobalFreePtr(p);
  929.    end;
  930.    lpDisp^.pHead := nil;
  931.    if FreeList then
  932.    begin
  933.       GlobalFreePtr(lpDisp);
  934.       lpDisp := nil;
  935.    end;
  936.    Result := RIFFERR_NOERROR;
  937. end;
  938. end.