Subversion Repositories filter_foundry

Rev

Rev 23 | Rev 62 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. /*
  2.     This file is part of "Filter Foundry", a filter plugin for Adobe Photoshop
  3.     Copyright (C) 2003-5 Toby Thain, toby@telegraphics.com.au
  4.  
  5.     This program is free software; you can redistribute it and/or modify
  6.     it under the terms of the GNU General Public License as published by  
  7.     the Free Software Foundation; either version 2 of the License, or
  8.     (at your option) any later version.
  9.  
  10.     This program is distributed in the hope that it will be useful,
  11.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.     GNU General Public License for more details.
  14.  
  15.     You should have received a copy of the GNU General Public License  
  16.     along with this program; if not, write to the Free Software
  17.     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18. */
  19.  
  20. #include <plstringfuncs.h>
  21. #include <ASRegistry.h>
  22. #include <ctype.h>
  23.  
  24. #include "ff.h"
  25.  
  26. #include "file_compat.h"
  27.  
  28. // MoreFiles headers
  29. #include "FileCopy.h"
  30. #include "MoreFilesExtras.h"
  31.  
  32. OSErr wrstr(FILEREF rn,char *s);
  33. OSErr dopkginfo(FILEREF rn);
  34. OSErr make_bundle(StandardFileReply *sfr, short plugvol,long plugdir,StringPtr plugname);
  35. OSErr doresources(FSSpec *srcplug, FSSpec *rsrccopyfss);
  36. OSErr make_singlefile(StandardFileReply *sfr, short plugvol,long plugdir,StringPtr plugname);
  37. OSErr copyplist(FSSpec *fss, short dstvol,long dstdir);
  38. int copyletters(char *dst,StringPtr src);
  39.  
  40. // prototype for a function included in Carbon's stdlib and declared in /usr/include/string.h
  41. // but missing from MPW Universal header string.h
  42. #ifndef _STRING_H_
  43.         char    *strnstr(const char *, const char *, size_t);
  44. #endif
  45.  
  46. OSErr wrstr(FILEREF rn,char *s){
  47.         long count = strlen(s);
  48.         return FSWrite(rn,&count,s);
  49. }
  50.  
  51. OSErr doresources(FSSpec *srcplug, FSSpec *rsrccopy){
  52.         short srcrn,dstrn;
  53.         Handle hpipl,h;
  54.         long origsize,newsize;
  55.         OSErr e = noErr;
  56.         Str255 title;
  57.  
  58. #ifdef MACMACHO
  59.   FSRef inref,outref;
  60.   // work with resources in data fork
  61.   if( !(e = FSpMakeFSRef(srcplug,&inref))
  62.     &&!(e = FSOpenResourceFile(&inref,0/*forkNameLength*/,NULL/*forkName*/,fsRdPerm,&srcrn))
  63.     &&!(e = FSpMakeFSRef(rsrccopy,&outref))
  64.     && (e = FSOpenResourceFile(&outref,0/*forkNameLength*/,NULL/*forkName*/,fsWrPerm,&dstrn)) )
  65.       CloseResFile(srcrn);
  66. #else
  67.   // ordinary resource fork files
  68.   srcrn = FSpOpenResFile(srcplug,fsRdPerm);
  69.   if(srcrn != -1){
  70.     dstrn = FSpOpenResFile(rsrccopy,fsWrPerm);
  71.     if(dstrn == -1){
  72.       e = ResError();
  73.       CloseResFile(srcrn);
  74.     }
  75.   }else e = ResError();
  76. #endif
  77.  
  78.         if(!e){
  79.                 /* create a new PiPL resource for the standalone plugin,
  80.                    with updated title and category strings */
  81.        
  82.                 if( (hpipl = Get1Resource('DATA',16000))
  83.                  && (h = Get1Resource('PiPL',16000)) )
  84.                 {
  85.                         RemoveResource(h);
  86.                        
  87.                         DetachResource(hpipl);
  88.  
  89.                         PLstrcpy(title,gdata->parm.title);
  90.                         if(gdata->parm.popDialog)
  91.                                 PLstrcat(title,"\pÉ");
  92.  
  93.                         origsize = GetHandleSize(hpipl);
  94.                         SetHandleSize(hpipl,origsize+0x300); /* some slop for fixup to work with */
  95.                         HLock(hpipl);
  96.                         newsize = fixpipl((PIPropertyList*) *hpipl,origsize,title);
  97.                         HUnlock(hpipl);
  98.                         SetHandleSize(hpipl,newsize);
  99.                        
  100.                         AddResource(hpipl,'PiPL',16000,"\p");
  101.                        
  102.                         if( !(e = ResError()) ){
  103.                                 /* do a similar trick with the terminology resource,
  104.                                    so the scripting system can distinguish the standalone plugin */
  105.                
  106.                                 if( (h = Get1Resource(typeAETE,AETE_ID)) ){
  107.                                         origsize = GetHandleSize(h);
  108.                                         SetHandleSize(h,origsize+0x100); /* slop for fixup to work with */
  109.                                         HLock(h);
  110.                                         newsize = fixaete((unsigned char*)*h,origsize,gdata->parm.title);
  111.                                         HUnlock(h);
  112.                                         SetHandleSize(h,newsize);
  113.                                        
  114.                                         ChangedResource(h);
  115.                                        
  116.                                         if( !(e = ResError()) ){
  117.                                                 /* add PARM resource */
  118.                                                 if( !(e = PtrToHand(&gdata->parm,&h,sizeof(PARM_T))) )
  119.                                                         AddResource(h,'PARM',PARM_ID,"\p");
  120.                                         }
  121.                                 }
  122.                                        
  123.                         }
  124.                        
  125.                 }
  126.                 if(!e)
  127.                         e = ResError();
  128.  
  129.                 CloseResFile(dstrn);
  130.                 CloseResFile(srcrn);
  131.         }
  132.        
  133.         return e;
  134. }
  135.  
  136. int copyletters(char *dst,StringPtr src){
  137.   int i,n=0;
  138.   for(i=src[0];i--;)
  139.     if(isalpha(*++src)){
  140.       *dst++ = *src;
  141.       ++n;
  142.     }
  143.   return n;
  144. }
  145.  
  146. // Info.plist in new standalone copy needs to be edited
  147. // at least the CFBundleIdentifier property must be unique
  148.  
  149. OSErr copyplist(FSSpec *fss, short dstvol, long dstdir){
  150.   static char *key = "com.telegraphics.FilterFoundry";
  151.   static unsigned char *fname="\pInfo.plist";
  152.   char *buf,*save,*p;
  153.   short rn,dstrn,i,n,m;
  154.   long eof,count;
  155.   OSErr e;
  156.  
  157.   if( !(e = HCreate(dstvol,dstdir,fname,'pled','TEXT')) ){
  158.     if( !(e = HOpenDF(dstvol,dstdir,fname,fsWrPerm,&dstrn)) ){
  159.       if( !(e = FSpOpenDF(fss,fsRdPerm,&rn)) ){
  160.         if( !(e = GetEOF(rn,&eof)) && (buf = malloc(eof+1024)) ){
  161.           if( !(e = FSRead(rn,&eof,buf)) ){
  162.             buf[eof] = 0;
  163.             if( (p = strnstr(buf,key,eof)) && (save = malloc(eof-(p-buf)+1)) ){
  164.               p += strlen(key);
  165.               // store text after matched string
  166.               strcpy(save,p);
  167.    
  168.               *p++ = '.';
  169.               n = copyletters(p,gdata->parm.category);
  170.               p += n;
  171.               if(n) *p++ = '.';
  172.               m = copyletters(p,gdata->parm.title);
  173.               p += m;
  174.               if(!m){
  175.                 // generate a random ASCII identifier
  176.                 srand(TICKCOUNT());
  177.                 for(i=8;i--;) *p++ = 'a' + (rand() % 26);
  178.               }
  179.               strcpy(p,save);
  180.    
  181.               count = strlen(buf);
  182.               e = FSWrite(dstrn,&count,buf);
  183.    
  184.               free(save);
  185.             }else e = paramErr; // not found?? shouldn't happen
  186.           }
  187.           free(buf);
  188.         }
  189.         FSClose(rn);
  190.       }
  191.       FSClose(dstrn);
  192.     }
  193.     if(e) HDelete(dstvol,dstdir,fname);
  194.   }
  195.   return e;
  196. }
  197.  
  198. OSErr make_bundle(StandardFileReply *sfr, short plugvol, long plugdir, StringPtr plugname){
  199.         short dstvol = sfr->sfFile.vRefNum;
  200.         long bundledir,contentsdir,macosdir,rsrcdir;
  201.         DInfo fndrInfo;
  202.         OSErr e;
  203.         FSSpec fss,macosfss,rsrcfss,rsrccopyfss;
  204.  
  205.         if( !(e = FSpDirCreate(&sfr->sfFile,sfr->sfScript,&bundledir)) ){
  206.                 if(!(e = FSpGetDInfo(&sfr->sfFile,&fndrInfo)) ){
  207.                         fndrInfo.frFlags |= kHasBundle;
  208.                         FSpSetDInfo(&sfr->sfFile,&fndrInfo);
  209.                 }
  210.                 if( !(e = DirCreate(dstvol,bundledir,"\pContents",&contentsdir)) ){
  211.                         if( !(e = DirCreate(dstvol,contentsdir,"\pMacOS",&macosdir)) ){
  212.                                 if( !(e = DirCreate(dstvol,contentsdir,"\pResources",&rsrcdir)) ){
  213.  
  214.                                         /* directories created ; now we need to copy the Info.plist file, resource file, and executable */
  215.  
  216.                                         if( !(e = FSMakeFSSpec(plugvol,plugdir,"\p::MacOS:FilterFoundry",&macosfss))
  217.                                          && !(e = FileCopy(macosfss.vRefNum,macosfss.parID,macosfss.name, dstvol,macosdir,NULL, NULL,NULL,0,false)) ){
  218.                                                 /* now we add PARM resources to each binary, and edit PiPLs */
  219.             if( !(e = FSMakeFSSpec(plugvol,plugdir,"\p::Resources:FilterFoundry.rsrc",&rsrcfss))
  220.                && !(e = FileCopy(rsrcfss.vRefNum,rsrcfss.parID,rsrcfss.name, dstvol,rsrcdir,NULL, NULL,NULL,0,false))
  221.                && !(e = FSMakeFSSpec(dstvol,rsrcdir,"\pFilterFoundry.rsrc",&rsrccopyfss)) ){
  222.                
  223.                                                    if( !(e = doresources(&rsrcfss, &rsrccopyfss))
  224.               && !(e = FSMakeFSSpec(plugvol,plugdir,"\p::Info.plist",&fss)) ){
  225.                 e = copyplist(&fss,dstvol,contentsdir);
  226.                
  227.                 if(e) FSpDelete(&rsrccopyfss);
  228.                }
  229.                
  230.               if(e) HDelete(dstvol,macosdir,"\pFilterFoundry");
  231.                                                 }
  232.                                                 if(e) HDelete(dstvol,rsrcdir,plugname);
  233.                                         }
  234.                                         if(e) HDelete(dstvol,contentsdir,"\pResources");
  235.                                 }
  236.                                 if(e) HDelete(dstvol,contentsdir,"\pMacOS");
  237.                         }
  238.                         if(e) HDelete(dstvol,bundledir,"\pContents");
  239.                 }
  240.                 if(e) FSpDelete(&sfr->sfFile);
  241.         }
  242.                
  243.         return e;
  244. }
  245.  
  246. OSErr make_singlefile(StandardFileReply *sfr, short plugvol,long plugdir,StringPtr plugname){
  247.         OSErr e;
  248.         FSSpec origfss;
  249.  
  250.         e = FSpDelete(&sfr->sfFile);
  251.         if(e && e != fnfErr){
  252.                 alertuser("Can't replace the existing file. Try a different name or location.","");
  253.                 return userCanceledErr;
  254.         }
  255.  
  256.         if( !(e = FileCopy(plugvol,plugdir,plugname, sfr->sfFile.vRefNum,sfr->sfFile.parID,NULL, sfr->sfFile.name,NULL,0,false))
  257.         && !(e = FSMakeFSSpec(plugvol,plugdir,plugname,&origfss)) )
  258.                 /* now we add PARM resources, and edit PiPL */
  259.                 e = doresources(&origfss, &sfr->sfFile);
  260.  
  261.         return e;
  262. }
  263.  
  264. OSErr make_standalone(StandardFileReply *sfr){
  265.         OSErr e;
  266.         short plugvol;
  267.         long plugdir;
  268.         Str255 plugname;
  269.        
  270.         if(!(e = GetFileLocation(CurResFile(),&plugvol,&plugdir,plugname)))
  271. #ifdef MACMACHO
  272.     e = make_bundle(sfr,plugvol,plugdir,plugname);
  273. #else
  274.                 e = make_singlefile(sfr,plugvol,plugdir,plugname);
  275. #endif
  276.  
  277.         if(e && e != userCanceledErr)
  278.                 alertuser("Could not create standalone plugin.","");
  279.        
  280.         return e;
  281. }
  282.