{
***************************************************************************
*                       joinres.pas
*
*  (c) Copyright 2003, Professor Abimbola A Olowofoyeku (The African Chief)
*
*  This utility combines any number of win32 binary resource (.RES)
*  files into one binary resource file that can be converted into COFF
*  format by "windres" for linking into Win32 applications.
*
*  Such a utility is needed because, under Borland's Delphi, free
*  Win32 compilers (e.g., gcc, gpc, fpc) cannot link more than one
*  resource file into an executable.
*
*  With this utility, the combined file can be linked.
*
*  This program compiles under GNU Pascal, FreePascal, 32-bit
*  Delphi, and Virtual Pascal.
*
*  Author: Professor Abimbola A Olowofoyeku (The African Chief)
*          WWW:     http://www.bigfoot.com/~african_chief/
*          E-mail:  african_chief [at] bigfoot.com
*
*  Last modified: 01 January  2003
*  Version: 1.00
*  Licence: Freeware
*
***************************************************************************
}
PROGRAM joinres;

{$I-}

USES
{$ifdef __GPC__}
cClasses,
{$else}
Classes,
{$endif}
Sysutils;


CONST
CopyBufSize = ( 1024 * 4 );   // 4k buffer
ResourceOffset = 32;          // offset for resources

{
******************************************************************
Function JoinResourceFiles:
  purpose: to concantenate a series of resource files into an
           output file in a form that can be converted by windres
  parameters:
      Source = a list of binary resource files to concantenate
      Target = the destination (combined) file
  returns:
     if successful, the number of bytes written to the destination file
     if unsuccessful, a negative error value
********************************************************************
}
FUNCTION JoinResourceFiles
( {$ifdef __GPC__}VAR{$endif} Source : TStrings; CONST Target : String ) : Longint;
VAR
SrcFile, DestFile : FILE;
i,
Total,
Size,
BRead, BWrite,
LocalOffset : Longint;
Buf : ARRAY [1 .. CopyBufSize] OF Byte;
BEGIN

   // we must have a target
   Result := - 1;
   IF ( Target = '' ) THEN Exit;

   // we must have more than 1 source file
   Result := - 2;
   IF ( Source.Count < 2 ) THEN Exit;

   // all source files must exist
   Result := - 3;
   FOR i := 0 TO Pred ( Source.Count ) DO
     IF NOT FileExists ( Source.Strings {$ifdef __GPC__} ( i ) {$else} [i]{$endif} )
       THEN Exit;

   // we must be able TO create the target file
   Result := - 4;
   Assign ( DestFile, Target );
   ReWrite ( DestFile, 1 );
   IF IOResult <> 0 THEN Exit;

   Result := - 4;

   Total := 0;
   FOR i := 0 TO Pred ( Source.Count )
   DO BEGIN
      Assign ( SrcFile, Source.Strings {$ifdef __GPC__} ( i ) {$else} [i]{$endif} );
      Reset ( SrcFile, 1 );
      IF IOResult <> 0
      THEN BEGIN
         Close ( DestFile );
         Exit;
      END;

      // copy the first file in full, but start copying the others
      // from offset 32
      IF i = 0 THEN LocalOffset := 0 ELSE LocalOffset := ResourceOffset;

      // bytes to read
      Size := FileSize ( SrcFile ) - LocalOffset;

      // jump to the required offset
      Seek ( SrcFile, LocalOffset );

      // copy the file
      WHILE NOT Eof ( SrcFile )
      DO BEGIN
         BlockRead ( SrcFile, Buf, SizeOf ( Buf ), BRead );
         BlockWrite ( DestFile, Buf, BRead, BWrite );
         Inc ( Total, BWrite );
         Dec ( Size, BWrite );
         IF Size <= 0 THEN Break;
      END;  // WHILE
      Close ( SrcFile );
   END; // FOR
   Result := Total; // return total bytes copied
END;

{****************************************}
VAR
Count : Longint;
List : TStrings;
BEGIN
   Writeln ('Joinres v1.00 (c)Copyright 2003, Prof. A Olowofoyeku (The African Chief).');
   IF paramcount < 3
   THEN BEGIN
      Writeln ( 'Syntax = joinres <targetfile.res> <file1.res> <file2.res> [files...]' );
      Halt;
   END;

   List {$ifndef __GPC__} := TStringList{$endif}.Create;

   FOR Count := 2 TO ParamCount DO List.Add ( ParamStr ( Count ) );

   Count := JoinResourceFiles ( List, ParamStr ( 1 ) );

   List.{$ifdef __GPC__}Done{$else}Free{$endif};

   Writeln ( Count, ' byte(s) copied.' );
END.

