/* An example of FUNCDEF'ing various functions in the Info-Zip * ZIP compression library (ZIP32.DLL). You need to obtain the * DLL from the web page. */ OPTIONS "C_CALL LABELCHECK WINFUNC NOSOURCE" NUMERIC DIGITS 10 LIBRARY rexxgui /* ============== FUNCDEF some needed ZIP functions ============ */ DO /* Register the ZIP32.DLL function ZipInit(). This initializes the ZIP32.DLL */ ZIPPRINT = '32u, void, 32u' ZIPCOMMENT = 'void, void' ZIPPASSWORD = '32, void, 32, void, void' ZIPFUNCS = "func ZIPPRINT, func ZIPCOMMENT, func ZIPPASSWORD, void" FUNCDEF("ZpInit", "32, struct ZIPFUNCS", "zip32") /* Register the ZIP32.DLL function ZpSetOptions(). This sets some options. */ ZIPOPTS = "void, str *, void, 32u, 32u, 32u, 32u, 32u, 32u, 32u, 32u, 32u, 32u, 32u, 32u, 32u, 32u, 32u, 32u, 32u, 32u, 32u, 32u, 32u, 32u, 32u, 32u, 32u, 32u, 32u, 32u, 8u" FUNCDEF("ZpSetOptions", "32u, struct ZIPOPTS", "zip32") /* ZIPNAMES struct must have a "str *" field for each filename you wish to add to the ZIP file. * Here we declare it as having 16 fields, which means we're limited to 16 files in the * zip. You can expand this if you need to. */ ZIPNAMES = "str *, str *, str *, str *, str *, str *, str *, str *, str *, str *, str *, str *, str *, str *, str *, str *" /* Register the ZIP32.DLL function ZpArchive(). This zips the files */ FUNCDEF("ZpArchive", "32, 32u, str, struct ZIPNAMES", "zip32") CATCH FAILURE CONDITION("M") RETURN END /* ====================== Zip up Files ====================== */ /* Present REXX GUI's File dialog to pick out the files. Allow * MULTIPLE selection. */ /* Store the filenames in the variable ZipNames.1.1 to ZipNames.1.xxx * where xxx is however many total filenames the user selects. * ZipNames is the variable we're going to use as our ZIPNAMES struct. */ ZipNames = '' /* Present the dialog */ err = GuiFile('ZipNames', 'EXISTING|MULTIPLE', 'Pick out files to zip') IF err = '' THEN DO /* Initialize a ZIPFUNCS struct */ ZipFuncs.1 = 'ZipPrint' ZipFuncs.2 = 'ZipComment' ZipFuncs.3 = 'ZipPassword' ZipFuncs.4 = 0 /* Initialize the ZIP32.DLL */ IF ZpInit(ZipFuncs) == 0 THEN DO GuiSay("ZpInit failure!") RETURN END /* Zero out all the numeric fields of the ZIPOPTS struct */ DO i = 1 TO 32 ZipOpts.i = 0 END /* Set the directory to the same one that RXFILE set */ ZipOpts.2 = DIRECTORY() /* Some of the above fields may be set to 1 (instead of 0) * for certain options, as so: * * ZipOpts.6 (Encrypt files) * ZipOpts.7 (Include system and hidden files) * ZipOpts.8 (Include the drive label) * ZipOpts.9 (Exclude extra attributes) * ZipOpts.10 (Do not add directory entries) * ZipOpts.13 (Report oddities in the file) * ZipOpts.14 (Quiet operation) * ZipOpts.15 (Translate '0D0A'X to '0A'X, ie, CR/LF to LF) * ZipOpts.16 (Translate '0A'X to '0D0A'X, ie, LF to CR/LF) * ZipOpts.17 (Junk directory names) * ZipOpts.18 (Allow appending to a zip file) * ZipOpts.19 (Make entries using DOS names, ie k for Katz) * ZipOpts.20 (Delete files added or updated in zip file) * ZipOpts.21 (Delete files from zip file) * ZipOpts.22 (Update zip file--overwrite only if newer) * ZipOpts.23 (Freshen zip file--overwrite only) * ZipOpts.24 (Junk SFX prefix) * ZipOpts.25 (Set zip file time to time of latest file in it) * ZipOpts.26 (Put comment in zip file. Our ZipComment subroutine would need to return the comment text) * ZipOpts.27 (Update archive offsets for SFX files) * ZipOpts.28 (Use privileges) * * ============================== * * ZipOpts.30 can be set to 1 if you want to recurse into subdirectories (-r option, * or 2 if the -R option). * * ZipOpts.31 can be set to 1 if you want to repair the zip file (-F option, * or 2 if the -FF option). * * ZipOpts.32 is the compression level 0 to 9 (where 0 is the default level, and 9 is maximum). */ /* Set the options */ ZpSetOptions(ZipOpts) /* We have a limit of 16 names due to our ZIPNAMES struct definition */ IF ZipNames.0 > 16 THEN ZipNames.0 = 16 /* The file names were already set into ZipNames.1 to ZipNames.16 */ /* Zip them into a ZIP file named "test.zip" in the TEMP dir, but first * delete any such file. Otherwise we would be adding these to that * existing zip archive. */ ZipName = SEARCHPATH('%TEMP%') || "test.zip" DELETEFILE(ZipName) IF ZpArchive(ZipNames.0, ZipName, ZipNames) \== 0 THEN GuiSay("ZpArchive error!") END RETURN /* ================================================================== * ZIP Password callback - We don't bother with passwords. */ ZipPassword: RETURN 1 /* ================================================================== * ZIP Print callback. Prints any text that the ZIP32.DLL functions * want displayed. We print to a console window. * * ARG(1) = The text to print. * ARG(2) = The number of characters of text. */ ZipPrint: IF ARG(2) > 0 THEN DO /* ARG(1) needs to be in a format suitable for REXX to handle. * We didn't know ahead of time how many chars it would be, so * we had to declare it as void type. Now that we know how many * chars, we can construct a Definition string and use CONVERTDATA() * to get it into the format we really want -- a char[] array. */ def = 'char[' || ARG(2) || ']' IF CONVERTDATA(ARG(1), 'text', def) \== "" THEN SAY text END /* Return the number of chars printed */ RETURN ARG(2) /* ================================================================== * ZIP Comment callback - We don't bother with comments. */ ZipComment: /* We need to nul out the buffer passed as ARG(1). We declared it * as void, so we'll use CONVERTDATA to stuff an empty string into * it (so we don't add any comment to the zip file). We need to use * the 'FROM' option to convert from a REXX variable to a C datatype. */ text = "" CONVERTDATA(ARG(1), 'text', 'str', 'FROM') RETURN ARG(1)