Rev 13792 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
/** R : A Computer Language for Statistical Data Analysis* file dounzip.c* Copyright (C) 1998--2000 Guido Masarotto and Brian Ripley* 2001 Stefano M. Iacus and the R core team** This program is free software; you can redistribute it and/or modify* it under the terms of the GNU General Public License as published by* the Free Software Foundation; either version 2 of the License, or* (at your option) any later version.** This program is distributed in the hope that it will be useful,* but WITHOUT ANY WARRANTY; without even the implied warranty of* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the* GNU General Public License for more details.** You should have received a copy of the GNU General Public License* along with this program; if not, write to the Free Software* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA** This file implement the int.unzip function by calling an external unzip tool.* For the time being, it is assumed that the user has MacZip, the Info-Zip* porting for the Macintosh machines. The MacZip application is assumed to* reside on the same volume as the R application itself. If R fails to* find and launch MacZip it puts up an alert dialog to the user by asking* to install MacZip application. The user is also informed on where to* find MacZip (or Info-Zip) on the WWW for free dowload.** Implemented in R 1.2.2. Stefano M. Iacus, Feb 2001**/#ifdef HAVE_CONFIG_H#include <config.h>#endif#include "Defn.h"/* Specific includes for AE and Process */#include <Types.h>#include <memory.h>#include <Packages.h>#include <Errors.h>#include <quickdraw.h>#include <fonts.h>#include <dialogs.h>#include <windows.h>#include <menus.h>#include <events.h>#include <Events.h>//#include <Desk.h>#include <Menus.h>#include <Devices.h>#include <Events.h>#include <diskinit.h>#include <OSUtils.h>#include <resources.h>#include <toolutils.h>#include <AppleEvents.h>#include <EPPC.h>#include <Gestalt.h> //<GestaltEqu.h>#include <PPCToolbox.h>#include <Processes.h>#define kCMDEventClass 'DCMD' /* Event class command for MacZip */#define kCMDEvent 'DCMD' /* Event command */#define kSearch 200#define kBadCombo 129 /* ID for Alert: Switch to MacZip. Actually nto used but is here for future implementation */#define kNoFind 132 /* ID for Alert: MacZip not found */extern AEIdleUPP gAEIdleUPP; /* defined in R_Event.c */short gInteract = 1; /* 1 => R and MacZip never interact */short replyValue = 1; /* 1 => R waits for a reply from MacZip */short gSwitchLayer = false; /* We leave MacZip work background *//* Apple Events switches */short gSendInteractArray[4] ={nil, kAENeverInteract, kAECanInteract, kAEAlwaysInteract,};short replyLevels[] ={kAENoReply, kAEWaitReply,kAEQueueReply};extern SInt32 systemVersion ;/* Function prototypes */static int do_unzip(char *zipname, char *dest, int nfiles, char **files,int nxfiles, char **xfiles, int over);OSErr LaunchUnZipTool(AEDesc *theAddress);SEXP do_int_unzip(SEXP call, SEXP op, SEXP args, SEXP env){SEXP fn, ans;char zipname[PATH_MAX], *topics[500], dest[PATH_MAX];int i, ntopics, rc;checkArity(op, args);if (!isString(CAR(args)) || LENGTH(CAR(args)) != 1)errorcall(call, "invalid zip name argument");strcpy(zipname, CHAR(STRING_ELT(CAR(args), 0)));args = CDR(args);fn = CAR(args);ntopics = length(fn);if (ntopics > 0) {if (!isString(fn) || ntopics > 500)errorcall(call, "invalid topics argument");for(i = 0; i < ntopics; i++)topics[i] = CHAR(STRING_ELT(fn, i));}args = CDR(args);if (!isString(CAR(args)) || LENGTH(CAR(args)) != 1)errorcall(call, "invalid destination argument");strcpy(dest, CHAR(STRING_ELT(CAR(args), 0)));rc = do_unzip(zipname, dest, ntopics, topics, 0 , NULL, 1);PROTECT(ans = allocVector(INTSXP, 1));INTEGER(ans)[0] = rc;UNPROTECT(1);return ans;}/*************************************************************************do_unzip: sends an event ('DCMD') with a command line to MacZipIf MacZip is not open, it is searched andlaunched. MacZip must be on the same volume asthe R application is. This can be improved by abetter search algorithm.This routine can be used to pass any command line to MacZipby simply setting 'commandstr' properly. The 'commandstr'must start with 'zip' or 'unzip' depending on which kindof action MacZip should take. For complete descriptionrefere to the original MacZip doc. A free copy of MacZipcan be found at http://www.sitec.net/maczip.Implemented on 1/2/2001, Stefano M. Iacus***************************************************************************/static int do_unzip(char *zipname, char *dest, int nfiles, char **files,int nxfiles, char **xfiles, int over){int retcode, i;int my_argc;char commandstr[2000];char buffer[2000];AppleEvent ourEvent,ourReply;short sendIt = 2;OSErr err;AEDesc gTheAddress;/* prepare the command line arg for MacZip */sprintf(commandstr,"unzip -oq \"%s\" ",zipname);for(i=0;i<nfiles;i++){sprintf(buffer,"%s ",files[i]);strcat(commandstr,buffer);}if(dest && dest[0]!='\0')sprintf(commandstr,"%s -d \"%s\"",commandstr,dest);if( (err=LaunchUnZipTool(&gTheAddress)) != noErr){ /* we cannot find MacZip */StopAlert(kNoFind,nil);return -1;}/* prepares the AppleEvent */AECreateAppleEvent(kCMDEventClass, kCMDEvent, &gTheAddress,kAutoGenerateReturnID, kAnyTransactionID, &ourEvent);/* Add the command string to the AE */AEPutParamPtr(&ourEvent, keyDirectObject, typeChar, commandstr,sizeof(char)*strlen(commandstr));/* Send the Event */if (replyLevels[replyValue] == kAEWaitReply && !gSwitchLayer) {AESend(&ourEvent, &ourReply, (gSendInteractArray[gInteract] + gSwitchLayer) + replyLevels[replyValue], kAENormalPriority,kAEDefaultTimeout,gAEIdleUPP, nil);}if (sendIt == 2) {AESend(&ourEvent, &ourReply, (gSendInteractArray[gInteract] + gSwitchLayer) + replyLevels[replyValue], kAENormalPriority,kAEDefaultTimeout,gAEIdleUPP, nil);}AEDisposeDesc(&ourEvent);if(replyLevels[replyValue] == kAEWaitReply)AEDisposeDesc(&ourReply);return(err);}/* The function LaunchZipTool() is adapted to invoke MacZip by Stefano M. Iacusand is based FindReciever from the file: 'sender.c'. This function will beabandoned soon by a more efficient one (see description below).Copyrights terms follows:File: sender.cContains: Sender and Reciever are simple AppleEvent programs that demonstrateall the permutations of interaction levels for sendingand recieving APpleEvents.Have fun with them.P.S. This also uses PBCatSearch, so I've done the typing for you if you've wantedto use this call but have been confused by the param blockWritten by:Copyright: Copyright © 1984-1999 by Apple Computer, Inc., All Rights Reserved.You may incorporate this Apple sample source code into your program(s) withoutrestriction. This Apple sample source code has been provided "AS IS" and theresponsibility for its operation is yours. You are not permitted to redistributethis Apple sample source code as "Apple sample source code" after having madechanges. If you're going to re-distribute the source, we require that you makeit clear in the source that the code was descended from Apple sample sourcecode, but that you've made changes.Change History (most recent first):7/20/1999 Karl Groethe Updated for Metrowerks Codewarror Pro 2.1*/OSErr LaunchUnZipTool(AEDesc *theAddress){OSErr myError;LaunchParamBlockRec launchUnZipTool;DialogPtr search = GetNewDialog(kSearch,nil,(WindowPtr)-1);CSParamPtr csBlockPtr = (CSParamPtr)NewPtrClear(sizeof(CSParam));long dirIDUnused;Str32 nulString = "\p";/* initialize the parameter block */DrawDialog(search);if (csBlockPtr) {csBlockPtr->ioSearchInfo1 = (CInfoPBPtr)NewPtrClear(sizeof(CInfoPBRec));csBlockPtr->ioSearchInfo2 = (CInfoPBPtr)NewPtrClear(sizeof(CInfoPBRec));if (csBlockPtr->ioSearchInfo1 && csBlockPtr->ioSearchInfo2) {csBlockPtr->ioMatchPtr = (FSSpecPtr)NewPtrClear(sizeof(FSSpec) * 1); /* only looking for 1 */if (csBlockPtr->ioMatchPtr) {/* Now see if we can create an optimization buffer */csBlockPtr->ioOptBuffer = NewPtr(2048);if (csBlockPtr->ioOptBuffer)csBlockPtr->ioOptBufSize = 2048;elsecsBlockPtr->ioOptBufSize = 0; /* no buffer, sorry */csBlockPtr->ioReqMatchCount = 1;csBlockPtr->ioSearchTime = 0; /* no timeout */}}}HGetVol(nil, &csBlockPtr->ioVRefNum, &dirIDUnused); /* get default volume for search */csBlockPtr->ioSearchInfo1->hFileInfo.ioNamePtr = nil;csBlockPtr->ioSearchInfo2->hFileInfo.ioNamePtr = nil;csBlockPtr->ioSearchInfo1->hFileInfo.ioFlFndrInfo.fdCreator = 'IZip'; /* This is the MacZip signature */csBlockPtr->ioSearchInfo1->hFileInfo.ioFlFndrInfo.fdType = 'APPL';csBlockPtr->ioSearchBits = fsSBFlFndrInfo;csBlockPtr->ioSearchInfo2->hFileInfo.ioFlFndrInfo.fdCreator = 0xFFFFFFFF;csBlockPtr->ioSearchInfo2->hFileInfo.ioFlFndrInfo.fdType = 0xFFFFFFFF;myError = PBCatSearch(csBlockPtr, false); /* search sync */if (myError == noErr && csBlockPtr->ioActMatchCount != 0) {/* we found it, so launch it */launchUnZipTool.launchBlockID = extendedBlock;launchUnZipTool.launchEPBLength = extendedBlockLen;launchUnZipTool.launchFileFlags = nil;launchUnZipTool.launchControlFlags = launchContinue + launchNoFileFlags + launchDontSwitch;launchUnZipTool.launchAppSpec = &csBlockPtr->ioMatchPtr[0];myError = LaunchApplication(&launchUnZipTool);if (myError == noErr) {/* it launched fine. we can use the PSN to make a target */AECreateDesc(typeProcessSerialNumber, (Ptr)&launchUnZipTool.launchProcessSN, sizeof(ProcessSerialNumber), theAddress);}}/* no matter what happened, kill the memory we had allocated */if (csBlockPtr) {if (csBlockPtr->ioSearchInfo1)DisposePtr((Ptr)csBlockPtr->ioSearchInfo1);if (csBlockPtr->ioSearchInfo2)DisposePtr((Ptr)csBlockPtr->ioSearchInfo2);if (csBlockPtr->ioMatchPtr)DisposePtr((Ptr)csBlockPtr->ioMatchPtr);if (csBlockPtr->ioOptBuffer)DisposePtr((Ptr)csBlockPtr->ioOptBuffer);DisposePtr((Ptr)csBlockPtr);}/* catsearch section end */DisposeDialog(search);return(myError);}