Subversion Repositories filter_foundry

Rev

Rev 210 | Rev 217 | 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-2009 Toby Thain, toby@telegraphics.com.au
  4.     Copyright (C) 2018-2021 Daniel Marschall, ViaThinkSoft
  5.  
  6.     This program is free software; you can redistribute it and/or modify
  7.     it under the terms of the GNU General Public License as published by
  8.     the Free Software Foundation; either version 2 of the License, or
  9.     (at your option) any later version.
  10.  
  11.     This program is distributed in the hope that it will be useful,
  12.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.     GNU General Public License for more details.
  15.  
  16.     You should have received a copy of the GNU General Public License
  17.     along with this program; if not, write to the Free Software
  18.     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19. */
  20.  
  21. /* Portions Copyright 1996 - 1999 Adobe Systems Incorporated                */
  22. /* All Rights Reserved.                                            */
  23.  
  24. //#include <stdio.h>
  25.  
  26. //#include "world.h" // must come before Photoshop includes
  27.  
  28. #include "ff.h"
  29.  
  30. #include "scripting.h"
  31. //#include "ui.h"
  32. #include "dbg.h"
  33.  
  34. //extern FilterRecordPtr gpb;
  35.  
  36. OSErr put_cstring(PIWriteDescriptor token,DescriptorKeyID key,char *s){
  37.         size_t n = strlen(s);
  38.         Ptr p;
  39.         Handle h = PINEWHANDLE((int32)n);
  40.         p = PILOCKHANDLE(h,false);
  41.         memcpy(p,s,n);
  42.         PIUNLOCKHANDLE(h);
  43.         return PIPutText(token,key,h);
  44.         /* FIXME: not sure if we are supposed to dispose of handle */
  45. }
  46.  
  47. char *get_cstring(PIReadDescriptor token){
  48.         int n;
  49.         Ptr p;
  50.         char *str = NULL;
  51.         Handle h;
  52.         OSErr e = PIGetText(token,&h);
  53.  
  54.         if(!e && h){
  55.                 n = PIGETHANDLESIZE(h);
  56.                 p = PILOCKHANDLE(h,false);
  57.                 //sprintf(str,"get_cstring: token=%#x s=%#x h=%#x p=%#x n=%d",token,s,h,p,n); dbg(str);
  58.                 if( (str = (char*)malloc(n+1)) ){
  59.                         memcpy(str,p,n);
  60.                         str[n] = 0;
  61.                 }
  62.                 PIUNLOCKHANDLE(h);
  63.                 /* FIXME: not sure if we are supposed to dispose of handle */
  64.         }
  65.         return str;
  66. }
  67.  
  68. // If parm is NULL, then it is standalone, otherwise it is the main plugin
  69. OSType getAeteKey(char c, PARM_T* parm) {
  70.         // To make our plugin compatible with AppleScript, each key must
  71.         // be unique, since the namespace is global!
  72.         // Furthermore, the "uniqueID/scope" hstm-field in the PIPL must be empty.
  73.  
  74.         if (parm != NULL) {
  75.                 unsigned long hash;
  76.                 char *data;
  77.                 // char* debug = malloc(2000);
  78.                 // sprintf(debug, "getAeteKey %c with title %s/%s in STANDALONE PLUGIN", c, INPLACEP2CSTR(parm->title), INPLACEP2CSTR(parm->category));
  79.                 // simplealert(debug);
  80.  
  81.                 // Use random AETE keys, because AppleScript has a global namespace
  82.                 // and therefore requires unique AETE keys
  83.                 data = (char*)malloc(0x300);
  84.                 if (!data) return 0;
  85.                 sprintf(data, "%s %s %c",
  86.                         INPLACEP2CSTR(parm->category),
  87.                         INPLACEP2CSTR(parm->title),
  88.                         c);
  89.                 hash = printablehash(djb2(data));
  90.                 free(data);
  91.                 return hash;
  92.         } else {
  93.                 // char* debug = malloc(2000);
  94.                 // sprintf(debug, "getAeteKey %c in MAIN PLUGIN", c);
  95.                 // simplealert(debug);
  96.  
  97.                                 // Attention: AETE keys (xpr#, cTl#) must be equal in scripting.r, scripting.rc and scripting.c(getAeteKey)!
  98.                 if (c == 'R') return 'xprR';
  99.                 if (c == 'G') return 'xprG';
  100.                 if (c == 'B') return 'xprB';
  101.                 if (c == 'A') return 'xprA';
  102.                 if ((c >= '0') && (c <= '9')) return 'cTl0' + (c - '0');
  103.                 return 0;
  104.         }
  105. }
  106.  
  107. /* return true if dialog should be shown */
  108. enum ScriptingShowDialog ReadScriptParamsOnRead(void)
  109. {
  110.         PIReadDescriptor token;
  111.         DescriptorKeyID key;
  112.         DescriptorTypeID type;
  113.         DescriptorKeyIDArray array = { NULLID };
  114.         int32 flags;
  115.         //OSErr stickyError;
  116.         int32 v;
  117.  
  118.         if (DescriptorAvailable(NULL)){ /* playing back.  Do our thing. */
  119.                 token = OpenReader(array);
  120.                 if (token) {
  121.                         while (PIGetKey(token, &key, &type, &flags)) {
  122.                                 if (key == getAeteKey('R', gdata->standalone ? &gdata->parm : NULL)) {
  123.                                         expr[0] = get_cstring(token);
  124.                                 } else if (key == getAeteKey('G', gdata->standalone ? &gdata->parm : NULL)) {
  125.                                         expr[1] = get_cstring(token);
  126.                                 } else if (key == getAeteKey('B', gdata->standalone ? &gdata->parm : NULL)) {
  127.                                         expr[2] = get_cstring(token);
  128.                                 } else if (key == getAeteKey('A', gdata->standalone ? &gdata->parm : NULL)) {
  129.                                         expr[3] = get_cstring(token);
  130.                                 } else {
  131.                                         int i;
  132.                                         for (i=0; i<=7; ++i) {
  133.                                                 if (key == getAeteKey('0'+i, gdata->standalone ? &gdata->parm : NULL)) {
  134.                                                         PIGetInt(token, &v);
  135.                                                         slider[i] = v;
  136.                                                 }
  137.                                         }
  138.                                 }
  139.                         }
  140.  
  141.                         /*stickyError =*/ CloseReader(&token); // closes & disposes.
  142.  
  143.                         // all Filter Foundry parameters are optional,
  144.                         // so we needn't worry if any are missing
  145.                 }
  146.  
  147.                 return gpb->descriptorParameters->playInfo == plugInDialogDisplay ? SCR_SHOW_DIALOG : SCR_HIDE_DIALOG;
  148.         } else {
  149.                 return SCR_NO_SCRIPT;
  150.         }
  151. }
  152.  
  153. OSErr WriteScriptParamsOnRead(void)
  154. {
  155.         PIWriteDescriptor token;
  156.         OSErr gotErr = noErr;
  157.         extern int ctls[],maps[],nplanes;
  158.         int i,allctls;
  159.  
  160.         if (DescriptorAvailable(NULL)){ /* recording.  Do our thing. */
  161.                 token = OpenWriter();
  162.                 if (token){
  163.                         // write keys here
  164.                         if(!gdata->standalone){
  165.                                 if (nplanes > 0) put_cstring(token, getAeteKey('R', gdata->standalone ? &gdata->parm : NULL), expr[0]);
  166.                                 if (nplanes > 1) put_cstring(token, getAeteKey('G', gdata->standalone ? &gdata->parm : NULL), expr[1]);
  167.                                 if (nplanes > 2) put_cstring(token, getAeteKey('B', gdata->standalone ? &gdata->parm : NULL), expr[2]);
  168.                                 if (nplanes > 3) put_cstring(token, getAeteKey('A', gdata->standalone ? &gdata->parm : NULL), expr[3]);
  169.                         }
  170.  
  171.                         /* only write values for the sliders that are actually used! */
  172.                         allctls = checksliders(4,ctls,maps);
  173.                         for (i=0; i<=7; ++i) {
  174.                                 if (allctls || ctls[i]) {
  175.                                         PIPutInt(token, getAeteKey('0'+i, gdata->standalone ? &gdata->parm : NULL), slider[i]);
  176.                                 }
  177.                         }
  178.  
  179.                         gotErr = CloseWriter(&token); /* closes and sets dialog optional */
  180.                         /* done.  Now pass handle on to Photoshop */
  181.                 }
  182.         }
  183.         return gotErr;
  184. }
  185.  
  186.  
  187. //-------------------------------------------------------------------------------
  188. //
  189. //      HostDescriptorAvailable
  190. //
  191. //      Determines whether the PIDescriptorParameters callback is available.
  192. //
  193. //      Check for valid suite version, routine suite version, and routine count.
  194. //      Also check that the subset of routines we actually use is actually present.
  195. //
  196. //-------------------------------------------------------------------------------
  197.  
  198. Boolean HostDescriptorAvailable (PIDescriptorParameters *procs,
  199.                                                                  Boolean *outNewerVersion)
  200. {
  201.         if(outNewerVersion)
  202.                 *outNewerVersion = procs->descriptorParametersVersion > kCurrentDescriptorParametersVersion
  203.                         || procs->readDescriptorProcs->readDescriptorProcsVersion > kCurrentReadDescriptorProcsVersion
  204.                         || procs->writeDescriptorProcs->writeDescriptorProcsVersion > kCurrentWriteDescriptorProcsVersion ;
  205.  
  206.         return procs != NULL
  207.                 && procs->descriptorParametersVersion == kCurrentDescriptorParametersVersion
  208.  
  209.                 && procs->readDescriptorProcs != NULL
  210.                 && procs->readDescriptorProcs->readDescriptorProcsVersion == kCurrentReadDescriptorProcsVersion
  211.                 && (unsigned int)(procs->readDescriptorProcs->numReadDescriptorProcs) >= kCurrentReadDescriptorProcsCount
  212.                 && procs->readDescriptorProcs->openReadDescriptorProc != NULL
  213.                 && procs->readDescriptorProcs->closeReadDescriptorProc != NULL
  214.                 && procs->readDescriptorProcs->getKeyProc != NULL
  215.                 && procs->readDescriptorProcs->getTextProc != NULL
  216.                 && procs->readDescriptorProcs->getIntegerProc != NULL
  217.  
  218.                 && procs->writeDescriptorProcs != NULL
  219.                 && procs->writeDescriptorProcs->writeDescriptorProcsVersion == kCurrentWriteDescriptorProcsVersion
  220.                 && (unsigned int)(procs->writeDescriptorProcs->numWriteDescriptorProcs) >= kCurrentWriteDescriptorProcsCount
  221.                 && procs->writeDescriptorProcs->openWriteDescriptorProc != NULL
  222.                 && procs->writeDescriptorProcs->closeWriteDescriptorProc != NULL
  223.                 && procs->writeDescriptorProcs->putTextProc != NULL
  224.                 && procs->writeDescriptorProcs->putIntegerProc != NULL ;
  225. }
  226.  
  227.  
  228. //-------------------------------------------------------------------------------
  229. //
  230. //      HostCloseReader
  231. //
  232. //      Closes a read token, disposes its handle, sets the token to NULL, and
  233. //      sets the parameter blocks' descriptor to NULL.
  234. //
  235. //      The Descriptor Parameters suite are callbacks designed for
  236. //      scripting and automation.  See PIActions.h.
  237. //
  238. //      Inputs:
  239. //              PIDescriptorParameters *procs   Pointer to Descriptor Parameters suite.
  240. //
  241. //              HandleProcs *hProcs                             Pointer to HandleProcs callback.
  242. //
  243. //              PIReadDescriptor *token                 Pointer to token to close.
  244. //
  245. //              procs->descriptor                               Pointer to original read handle.
  246. //
  247. //      Outputs:
  248. //              PIReadDescriptor *token                 Set to NULL.
  249. //
  250. //              procs->descriptor                               Disposed then set to NULL.
  251. //
  252. //              returns OSErr                                   noErr or error if one occurred.
  253. //
  254. //-------------------------------------------------------------------------------
  255.  
  256. OSErr HostCloseReader (PIDescriptorParameters *procs,
  257.                                            HandleProcs *hProcs,
  258.                                            PIReadDescriptor *token)
  259. {
  260.         // Close token:
  261.         OSErr err = procs->readDescriptorProcs->closeReadDescriptorProc(*token);
  262.  
  263.         // Dispose the parameter block descriptor:
  264.         hProcs->disposeProc(procs->descriptor);
  265.  
  266.         // Set the descriptor and the read token to NULL:
  267.         procs->descriptor = NULL;
  268.         *token = NULL;
  269.  
  270.         return err;
  271.  
  272. } // end HostCloseReader
  273.  
  274. //-------------------------------------------------------------------------------
  275. //
  276. //      HostCloseWriter
  277. //
  278. //      Closes a write token, stores its handle in the global parameter block for
  279. //      the host to use, sets the token to NULL, and sets the recordInfo to
  280. //      plugInDialogOptional (the default).
  281. //
  282. //      The Descriptor Parameters suite are callbacks designed for
  283. //      scripting and automation.  See PIActions.h.
  284. //
  285. //      Inputs:
  286. //              PIDescriptorParameters *procs   Pointer to Descriptor Parameters suite.
  287. //
  288. //              HandleProcs *hProcs                             Pointer to HandleProcs callback.
  289. //
  290. //              PIWriteDescriptor *token                Pointer to token to close and pass on.
  291. //
  292. //              procs->descriptor                               Should be NULL.  If not, its contents
  293. //                                                                              will be disposed and replaced.
  294. //
  295. //      Outputs:
  296. //              PIWriteDescriptor *token                Set to NULL.
  297. //
  298. //              procs->descriptor                               Set to descriptor handle.
  299. //
  300. //              returns OSErr                                   noErr or error if one occurred.
  301. //
  302. //-------------------------------------------------------------------------------
  303.  
  304. OSErr   HostCloseWriter(PIDescriptorParameters *procs,
  305.                                                 HandleProcs *hProcs,
  306.                                                 PIWriteDescriptor *token)
  307. {
  308.         OSErr err = noErr; // assume no error
  309.         PIDescriptorHandle h = NULL;
  310.  
  311.         if (procs->descriptor != NULL) // don't need descriptor passed to us
  312.                 hProcs->disposeProc(procs->descriptor); // dispose.
  313.         procs->writeDescriptorProcs->closeWriteDescriptorProc(*token, &h);
  314.         procs->descriptor = h;
  315.  
  316.         // Set recordInfo to default.  Options are: plugInDialogOptional,
  317.         // plugInDialogRequire, plugInDialogNone:
  318.         procs->recordInfo = plugInDialogOptional;
  319.  
  320.         *token = NULL;
  321.  
  322.         return err;
  323.  
  324. } // end HostCloseWriter
  325.