Rev 206 | Rev 211 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
210 | daniel-mar | 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 | data = (char*)malloc(0x300); |
||
82 | if (!data) return 'xxxx'; |
||
83 | sprintf(data, "%s %s %c", |
||
84 | INPLACEP2CSTR(parm->category), |
||
85 | INPLACEP2CSTR(parm->title), |
||
86 | c); |
||
87 | hash = printablehash(djb2(data)); |
||
88 | free(data); |
||
89 | return hash; |
||
90 | } else { |
||
91 | // char* debug = malloc(2000); |
||
92 | // sprintf(debug, "getAeteKey %c in MAIN PLUGIN", c); |
||
93 | // simplealert(debug); |
||
94 | |||
95 | // Attention: AETE keys (xpr#, cTl#) must be equal in scripting.r, scripting.rc and scripting.c(getAeteKey)! |
||
96 | if (c == 'R') return 'xprR'; |
||
97 | if (c == 'G') return 'xprG'; |
||
98 | if (c == 'B') return 'xprB'; |
||
99 | if (c == 'A') return 'xprA'; |
||
100 | return 'cTl0' + (c - '0'); |
||
101 | } |
||
102 | } |
||
103 | |||
104 | /* return true if dialog should be shown */ |
||
105 | enum ScriptingShowDialog ReadScriptParamsOnRead(void) |
||
106 | { |
||
107 | PIReadDescriptor token; |
||
108 | DescriptorKeyID key; |
||
109 | DescriptorTypeID type; |
||
110 | DescriptorKeyIDArray array = { NULLID }; |
||
111 | int32 flags; |
||
112 | //OSErr stickyError; |
||
113 | int32 v; |
||
114 | |||
115 | if (DescriptorAvailable(NULL)){ /* playing back. Do our thing. */ |
||
116 | token = OpenReader(array); |
||
117 | if (token) { |
||
118 | while (PIGetKey(token, &key, &type, &flags)) { |
||
119 | if (key == getAeteKey('R', gdata->standalone ? &gdata->parm : NULL)) { |
||
120 | expr[0] = get_cstring(token); |
||
121 | } else if (key == getAeteKey('G', gdata->standalone ? &gdata->parm : NULL)) { |
||
122 | expr[1] = get_cstring(token); |
||
123 | } else if (key == getAeteKey('B', gdata->standalone ? &gdata->parm : NULL)) { |
||
124 | expr[2] = get_cstring(token); |
||
125 | } else if (key == getAeteKey('A', gdata->standalone ? &gdata->parm : NULL)) { |
||
126 | expr[3] = get_cstring(token); |
||
127 | } else { |
||
128 | int i; |
||
129 | for (i=0; i<=7; ++i) { |
||
130 | if (key == getAeteKey('0'+i, gdata->standalone ? &gdata->parm : NULL)) { |
||
131 | PIGetInt(token, &v); |
||
132 | slider[i] = v; |
||
133 | } |
||
134 | } |
||
135 | } |
||
136 | } |
||
137 | |||
138 | /*stickyError =*/ CloseReader(&token); // closes & disposes. |
||
139 | |||
140 | // all Filter Foundry parameters are optional, |
||
141 | // so we needn't worry if any are missing |
||
142 | } |
||
143 | |||
144 | return gpb->descriptorParameters->playInfo == plugInDialogDisplay ? SCR_SHOW_DIALOG : SCR_HIDE_DIALOG; |
||
145 | } else { |
||
146 | return SCR_NO_SCRIPT; |
||
147 | } |
||
148 | } |
||
149 | |||
150 | OSErr WriteScriptParamsOnRead(void) |
||
151 | { |
||
152 | PIWriteDescriptor token; |
||
153 | OSErr gotErr = noErr; |
||
154 | extern int ctls[],maps[],nplanes; |
||
155 | int i,allctls; |
||
156 | |||
157 | if (DescriptorAvailable(NULL)){ /* recording. Do our thing. */ |
||
158 | token = OpenWriter(); |
||
159 | if (token){ |
||
160 | // write keys here |
||
161 | if(!gdata->standalone){ |
||
162 | if (nplanes > 0) put_cstring(token, getAeteKey('R', gdata->standalone ? &gdata->parm : NULL), expr[0]); |
||
163 | if (nplanes > 1) put_cstring(token, getAeteKey('G', gdata->standalone ? &gdata->parm : NULL), expr[1]); |
||
164 | if (nplanes > 2) put_cstring(token, getAeteKey('B', gdata->standalone ? &gdata->parm : NULL), expr[2]); |
||
165 | if (nplanes > 3) put_cstring(token, getAeteKey('A', gdata->standalone ? &gdata->parm : NULL), expr[3]); |
||
166 | } |
||
167 | |||
168 | /* only write values for the sliders that are actually used! */ |
||
169 | allctls = checksliders(4,ctls,maps); |
||
170 | for (i=0; i<=7; ++i) { |
||
171 | if (allctls || ctls[i]) { |
||
172 | PIPutInt(token, getAeteKey('0'+i, gdata->standalone ? &gdata->parm : NULL), slider[i]); |
||
173 | } |
||
174 | } |
||
175 | |||
176 | gotErr = CloseWriter(&token); /* closes and sets dialog optional */ |
||
177 | /* done. Now pass handle on to Photoshop */ |
||
178 | } |
||
179 | } |
||
180 | return gotErr; |
||
181 | } |
||
182 | |||
183 | |||
184 | //------------------------------------------------------------------------------- |
||
185 | // |
||
186 | // HostDescriptorAvailable |
||
187 | // |
||
188 | // Determines whether the PIDescriptorParameters callback is available. |
||
189 | // |
||
190 | // Check for valid suite version, routine suite version, and routine count. |
||
191 | // Also check that the subset of routines we actually use is actually present. |
||
192 | // |
||
193 | //------------------------------------------------------------------------------- |
||
194 | |||
195 | Boolean HostDescriptorAvailable (PIDescriptorParameters *procs, |
||
196 | Boolean *outNewerVersion) |
||
197 | { |
||
198 | if(outNewerVersion) |
||
199 | *outNewerVersion = procs->descriptorParametersVersion > kCurrentDescriptorParametersVersion |
||
200 | || procs->readDescriptorProcs->readDescriptorProcsVersion > kCurrentReadDescriptorProcsVersion |
||
201 | || procs->writeDescriptorProcs->writeDescriptorProcsVersion > kCurrentWriteDescriptorProcsVersion ; |
||
202 | |||
203 | return procs != NULL |
||
204 | && procs->descriptorParametersVersion == kCurrentDescriptorParametersVersion |
||
205 | |||
206 | && procs->readDescriptorProcs != NULL |
||
207 | && procs->readDescriptorProcs->readDescriptorProcsVersion == kCurrentReadDescriptorProcsVersion |
||
208 | && (unsigned int)(procs->readDescriptorProcs->numReadDescriptorProcs) >= kCurrentReadDescriptorProcsCount |
||
209 | && procs->readDescriptorProcs->openReadDescriptorProc != NULL |
||
210 | && procs->readDescriptorProcs->closeReadDescriptorProc != NULL |
||
211 | && procs->readDescriptorProcs->getKeyProc != NULL |
||
212 | && procs->readDescriptorProcs->getTextProc != NULL |
||
213 | && procs->readDescriptorProcs->getIntegerProc != NULL |
||
214 | |||
215 | && procs->writeDescriptorProcs != NULL |
||
216 | && procs->writeDescriptorProcs->writeDescriptorProcsVersion == kCurrentWriteDescriptorProcsVersion |
||
217 | && (unsigned int)(procs->writeDescriptorProcs->numWriteDescriptorProcs) >= kCurrentWriteDescriptorProcsCount |
||
218 | && procs->writeDescriptorProcs->openWriteDescriptorProc != NULL |
||
219 | && procs->writeDescriptorProcs->closeWriteDescriptorProc != NULL |
||
220 | && procs->writeDescriptorProcs->putTextProc != NULL |
||
221 | && procs->writeDescriptorProcs->putIntegerProc != NULL ; |
||
222 | } |
||
223 | |||
224 | |||
225 | //------------------------------------------------------------------------------- |
||
226 | // |
||
227 | // HostCloseReader |
||
228 | // |
||
229 | // Closes a read token, disposes its handle, sets the token to NULL, and |
||
230 | // sets the parameter blocks' descriptor to NULL. |
||
231 | // |
||
232 | // The Descriptor Parameters suite are callbacks designed for |
||
233 | // scripting and automation. See PIActions.h. |
||
234 | // |
||
235 | // Inputs: |
||
236 | // PIDescriptorParameters *procs Pointer to Descriptor Parameters suite. |
||
237 | // |
||
238 | // HandleProcs *hProcs Pointer to HandleProcs callback. |
||
239 | // |
||
240 | // PIReadDescriptor *token Pointer to token to close. |
||
241 | // |
||
242 | // procs->descriptor Pointer to original read handle. |
||
243 | // |
||
244 | // Outputs: |
||
245 | // PIReadDescriptor *token Set to NULL. |
||
246 | // |
||
247 | // procs->descriptor Disposed then set to NULL. |
||
248 | // |
||
249 | // returns OSErr noErr or error if one occurred. |
||
250 | // |
||
251 | //------------------------------------------------------------------------------- |
||
252 | |||
253 | OSErr HostCloseReader (PIDescriptorParameters *procs, |
||
254 | HandleProcs *hProcs, |
||
255 | PIReadDescriptor *token) |
||
256 | { |
||
257 | // Close token: |
||
258 | OSErr err = procs->readDescriptorProcs->closeReadDescriptorProc(*token); |
||
259 | |||
260 | // Dispose the parameter block descriptor: |
||
261 | hProcs->disposeProc(procs->descriptor); |
||
262 | |||
263 | // Set the descriptor and the read token to NULL: |
||
264 | procs->descriptor = NULL; |
||
265 | *token = NULL; |
||
266 | |||
267 | return err; |
||
268 | |||
269 | } // end HostCloseReader |
||
270 | |||
271 | //------------------------------------------------------------------------------- |
||
272 | // |
||
273 | // HostCloseWriter |
||
274 | // |
||
275 | // Closes a write token, stores its handle in the global parameter block for |
||
276 | // the host to use, sets the token to NULL, and sets the recordInfo to |
||
277 | // plugInDialogOptional (the default). |
||
278 | // |
||
279 | // The Descriptor Parameters suite are callbacks designed for |
||
280 | // scripting and automation. See PIActions.h. |
||
281 | // |
||
282 | // Inputs: |
||
283 | // PIDescriptorParameters *procs Pointer to Descriptor Parameters suite. |
||
284 | // |
||
285 | // HandleProcs *hProcs Pointer to HandleProcs callback. |
||
286 | // |
||
287 | // PIWriteDescriptor *token Pointer to token to close and pass on. |
||
288 | // |
||
289 | // procs->descriptor Should be NULL. If not, its contents |
||
290 | // will be disposed and replaced. |
||
291 | // |
||
292 | // Outputs: |
||
293 | // PIWriteDescriptor *token Set to NULL. |
||
294 | // |
||
295 | // procs->descriptor Set to descriptor handle. |
||
296 | // |
||
297 | // returns OSErr noErr or error if one occurred. |
||
298 | // |
||
299 | //------------------------------------------------------------------------------- |
||
300 | |||
301 | OSErr HostCloseWriter(PIDescriptorParameters *procs, |
||
302 | HandleProcs *hProcs, |
||
303 | PIWriteDescriptor *token) |
||
304 | { |
||
305 | OSErr err = noErr; // assume no error |
||
306 | PIDescriptorHandle h = NULL; |
||
307 | |||
308 | if (procs->descriptor != NULL) // don't need descriptor passed to us |
||
309 | hProcs->disposeProc(procs->descriptor); // dispose. |
||
310 | procs->writeDescriptorProcs->closeWriteDescriptorProc(*token, &h); |
||
311 | procs->descriptor = h; |
||
312 | |||
313 | // Set recordInfo to default. Options are: plugInDialogOptional, |
||
314 | // plugInDialogRequire, plugInDialogNone: |
||
315 | procs->recordInfo = plugInDialogOptional; |
||
316 | |||
317 | *token = NULL; |
||
318 | |||
319 | return err; |
||
320 | |||
321 | } // end HostCloseWriter |