iowascript.c

Go to the documentation of this file.
00001 
00002 /*  $Id: iowascript.c 1192 2006-04-05 21:26:48Z karstenw $    */
00003 
00004 /******************************************************************************
00005 
00006     UserLand Frontier(tm) -- High performance Web content management,
00007     object database, system-level and Internet scripting environment,
00008     including source code editing and debugging.
00009 
00010     Copyright (C) 1992-2004 UserLand Software, Inc.
00011 
00012     This program is free software; you can redistribute it and/or modify
00013     it under the terms of the GNU General Public License as published by
00014     the Free Software Foundation; either version 2 of the License, or
00015     (at your option) any later version.
00016 
00017     This program is distributed in the hope that it will be useful,
00018     but WITHOUT ANY WARRANTY; without even the implied warranty of
00019     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020     GNU General Public License for more details.
00021 
00022     You should have received a copy of the GNU General Public License
00023     along with this program; if not, write to the Free Software
00024     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00025 
00026 ******************************************************************************/
00027 
00028 #include "frontier.h"
00029 #include "standard.h"
00030 
00031 #include <iac.h>
00032 #include <UserTalk.h>
00033 #include <appletdefs.h>
00034 #include <appletmemory.h>
00035 #include <appletprocess.h>
00036 #include <appletstrings.h>
00037 #include <appletfiledesktop.h>
00038 #include "iowascript.h"
00039 
00040 #if TARGET_API_MAC_CARBON == 1 /*PBS 03/14/02: AE OS X fix.*/
00041     #include "aeutils.h" /*PBS 03/14/02: AE OS X fix.*/
00042 #endif
00043 
00044 #define idnetscapeurl 'NURL'
00045 #define idnetscapejavascript 'NJVS'
00046 
00047 #define iowaWeb /*undefine this to eliminate minor hacks*/
00048 
00049 #define noAppleScript /*if we include it we crash on exiting*/
00050 
00051 #ifdef iowaWeb
00052     
00053     #define idnetscape 'MOSS'
00054     
00055 #endif
00056  
00057 tylangcomponentrecord **langcomponentarray = nil; /*dynamic array of components*/
00058 
00059 
00060 
00061 #ifdef isFrontier
00062 
00063 void initlangcomponents (void) {
00064     } /*initlangcomponents*/
00065 
00066 void closelangcomponents (void) {
00067     } /*closelangcomponents*/
00068 
00069 ComponentInstance findlangcomponent (long idlanguage) {
00070     
00071     extern ComponentInstance getosaserver (OSType type);
00072 
00073     return (getosaserver (idlanguage));
00074     } /*findlangcomponent*/
00075 
00076 #else
00077 
00078 
00079     
00080 short countlangcomponents (void) {
00081     
00082     if (langcomponentarray == nil)
00083         return (0);
00084         
00085     return ((short) (GetHandleSize ((Handle) langcomponentarray) / longsizeof (tylangcomponentrecord)));
00086     } /*countlangcomponents*/
00087     
00088     
00089 static boolean addlangcomponent (ComponentInstance instance, long idlanguage, Handle hname, boolean flrealcomponent) {
00090 
00091     tylangcomponentrecord rec;
00092     short ct;
00093     
00094     rec.instance = instance;
00095     
00096     rec.idlanguage = idlanguage;
00097     
00098     rec.hname = hname;
00099     
00100     rec.flrealcomponent = flrealcomponent;
00101     
00102     if (langcomponentarray == nil)
00103         return (newfilledhandle (&rec, longsizeof (tylangcomponentrecord), (Handle *) &langcomponentarray));
00104     
00105     ct = countlangcomponents ();
00106     
00107     SetHandleSize ((Handle) langcomponentarray, (ct + 1) * longsizeof (tylangcomponentrecord));
00108 
00109     if (MemError () != noErr)
00110         return (false);
00111     
00112     (*langcomponentarray) [ct] = rec;
00113     
00114     return (true);
00115     } /*addlangcomponent*/
00116     
00117     
00118 static boolean addwebcomponent (long idlanguage, bigstring bsname) {
00119     
00120     Handle hname;
00121     
00122     if (!newtexthandle (bsname, &hname))
00123         return (false);
00124     
00125     return (addlangcomponent (0, idlanguage, hname, false));
00126     } /*addwebcomponent*/
00127     
00128     
00129 static void getcomponentdetails (Component comp, ComponentDescription *details, Handle *hname) {
00130     
00131     Handle h;
00132     
00133     newclearhandle (0, &h);
00134     
00135     GetComponentInfo (comp, details, h, nil, nil);
00136     
00137     /*mystery: why is there one garbage char at beginning of name?*/ {
00138         
00139         if (h != nil) {
00140         
00141             long newsize = GetHandleSize (h) - 1;
00142         
00143             moveleft (*h + 1, *h, newsize);
00144         
00145             SetHandleSize (h, newsize);
00146             }
00147         }
00148     
00149     *hname = h;
00150     } /*getcomponentdetails*/
00151     
00152     
00153 void initlangcomponents (void) {
00154     
00155     static boolean componentsinitialized = false;
00156     ComponentDescription desc, details;
00157     Component comp;
00158     Component prevcomponent;
00159     ComponentInstance instance;
00160     long i, ct;
00161     Handle hname;
00162     
00163     if (componentsinitialized) /*DW 12/5/93 -- with Iowa Runtime inside CE, we are called twice*/
00164         return;
00165         
00166     componentsinitialized = true;
00167     
00168     clearbytes (&desc, longsizeof (desc));
00169     
00170     desc.componentType = kOSAComponentType;
00171     
00172     #ifdef noAppleScript
00173     
00174         desc.componentSubType = 'LAND'; /*DW 1/20/95 -- only connect with Frontier, AS crashes when we close*/
00175 
00176     #endif
00177     
00178     ct = CountComponents (&desc);
00179     
00180     prevcomponent = nil; /*start with the first one*/
00181     
00182     for (i = 0; i < ct; i++) {
00183         
00184         comp = FindNextComponent (prevcomponent, &desc);
00185         
00186         instance = OpenComponent (comp);
00187         
00188         getcomponentdetails (comp, &details, &hname);
00189         
00190         if (details.componentSubType != kOSAGenericScriptingComponentSubtype)
00191             addlangcomponent (instance, details.componentSubType, hname, true);
00192         else
00193             disposehandle (hname);
00194         
00195         prevcomponent = comp;
00196         } /*for*/
00197         
00198     #ifdef iowaWeb /*DW 12/27/94*/
00199         
00200         addwebcomponent (0, "\p(-"); /*oh this is really cute*/
00201         
00202         addwebcomponent (idnetscapeurl, "\pNetscape URL");
00203         
00204         addwebcomponent (idnetscapejavascript, "\pNetscape JavaScript");
00205         
00206     #endif
00207     } /*initlangcomponents*/
00208     
00209     
00210 ComponentInstance findlangcomponent (long idlanguage) {
00211     
00212     /*
00213     DW 1/21/95 -- soften it. before returning false, we try to
00214     find the component using the Component Manager.
00215     
00216     dmb 7/31/96: make sure instance isn't stale by trying to get its version
00217     */
00218     
00219     short ct, i;
00220     tylangcomponentrecord rec;
00221     
00222     ct = countlangcomponents ();
00223     
00224     for (i = 0; i < ct; i++) {
00225         
00226         rec = (*langcomponentarray) [i];
00227         
00228         if (rec.idlanguage == idlanguage) {
00229         
00230             if (GetComponentVersion (rec.instance) == badComponentInstance) { /*dmb 1.0b19: no longer valid*/
00231             
00232                 rec.instance = 0;
00233                 
00234                 rec.idlanguage = 0;
00235                 
00236                 disposehandle (rec.hname);
00237                 
00238                 rec.hname = nil;
00239                 
00240                 (*langcomponentarray) [i] = rec;
00241                 }
00242             else
00243                 return (rec.instance);
00244             }
00245         } /*for*/
00246         
00247     /*DW 1/21/95 -- not in the array -- see if it's in memory*/ {
00248     
00249         ComponentDescription desc, details;
00250         long ct;
00251         
00252         /*DebugStr ("\pnot in the array -- see if it's in memory");*/
00253         
00254         clearbytes (&desc, longsizeof (desc));
00255     
00256         desc.componentType = kOSAComponentType;
00257     
00258         desc.componentSubType = idlanguage;
00259     
00260         ct = CountComponents (&desc);
00261         
00262         if (ct > 0) {
00263         
00264             Component comp;
00265             ComponentInstance instance;
00266             Handle hname;
00267             
00268             comp = FindNextComponent (nil, &desc);
00269         
00270             instance = OpenComponent (comp);
00271         
00272             getcomponentdetails (comp, &details, &hname);
00273         
00274             addlangcomponent (instance, details.componentSubType, hname, true);
00275             
00276             return (instance);
00277             }
00278         }
00279     
00280     return (0); /*not found*/
00281     } /*findlangcomponent*/
00282     
00283 
00284 boolean getlangmenu (MenuHandle *hlangmenu) {
00285     
00286     /*
00287     return a menu filled with the names of all the installed scripting
00288     components.
00289     */
00290     
00291     MenuHandle hmenu;
00292     short ct, i;
00293     bigstring bs;
00294     
00295     hmenu = NewMenu (25000, "\px");
00296     
00297     ct = countlangcomponents ();
00298     
00299     for (i = 0; i < ct; i++) {
00300         
00301         texthandletostring ((*langcomponentarray) [i].hname, bs);
00302         
00303         if (equalstrings (bs, "\pUserTalk")) /*DW 12/30/95*/
00304             copystring ("\pFrontier Script", bs);
00305     
00306         AppendMenu (hmenu, bs);
00307         } /*for*/
00308         
00309     *hlangmenu = hmenu;
00310     
00311     return (true);
00312     } /*getlangmenu*/
00313     
00314     
00315 void getlanguageid (short ixlanguage, OSType *idlanguage) {
00316     
00317     *idlanguage = (*langcomponentarray) [ixlanguage].idlanguage;
00318     } /*getlanguageid*/
00319     
00320     
00321 void closelangcomponents (void) {
00322     
00323     short ct, i;
00324     
00325     ct = countlangcomponents ();
00326     
00327     for (i = 0; i < ct; i++) {
00328         
00329         CloseComponent ((*langcomponentarray) [i].instance);
00330         
00331         disposehandle ((*langcomponentarray) [i].hname);
00332         } /*for*/
00333         
00334     if (langcomponentarray != nil)
00335         disposehandle ((Handle) langcomponentarray);
00336     
00337     langcomponentarray = nil;
00338     } /*closelangcomponents*/
00339 
00340 #endif  // isFrontier
00341 
00342 #ifdef macBirdPlugin
00343 
00344     extern boolean runworldwideurl (Handle hscript, bigstring errorstring);
00345 
00346 #else
00347 
00348     static boolean runworldwideurl (Handle hscript, bigstring errorstring) {
00349         
00350         AppleEvent event, reply;
00351         boolean fl;
00352         
00353         setstringlength (errorstring, 0);
00354         
00355         /*launch the netscape app, if necessary*/ {
00356             
00357             if (!assureappisrunning (idnetscape, true)) {
00358                 
00359                 copystring ("\pCouldn't follow the worldwide web link because Netscape isn't running", errorstring);
00360                 
00361                 return (false);
00362                 }
00363             }
00364             
00365         if (!IACnewverb (idnetscape, 'GURL', 'GURL', &event))
00366             return (false);
00367         
00368         IACglobals.event = &event;
00369         
00370         if (!IACpushtextparam (hscript, '----'))
00371             return (false);
00372             
00373         if (!IACpushlongparam (0, 'cwin'))
00374             return (false);
00375             
00376         if (!IACsendverb (&event, &reply))
00377             return (false);
00378         
00379         IACglobals.reply = &reply;
00380         
00381         fl = !IACiserrorreply (errorstring);
00382         
00383         IACdisposeverb (&reply);
00384         
00385         return (fl);
00386         } /*runworldwideurl*/
00387 
00388 #endif
00389 
00390 static boolean rungraphicalurl (Handle hscript, bigstring errorstring) {
00391 #pragma unused(hscript)
00392 
00393     setstringlength (errorstring, 0);
00394     
00395     return (true);
00396     } /*rungraphicalurl*/
00397     
00398     
00399 boolean runlangscript (Handle hscript, Handle tablename, long idlanguage, boolean flgetreturn, bigstring errorstring, Handle *hreturns) {
00400     
00401     /*
00402     execute the script in the card's context. consume hscript.
00403     
00404     dmb 1.0b23 - add a "with" statement to establish our context. we
00405     no longer rely on frontSetRuntimeCard being called.
00406     */
00407     
00408     ComponentInstance scriptcomp;
00409     AEDesc scriptdesc;
00410     AEDesc resultdesc;
00411     OSErr ec = noErr;
00412     bigstring bswith;
00413     
00414     if (flgetreturn)
00415         *hreturns = nil;
00416     
00417     #ifdef iowaWeb
00418     
00419         if (idlanguage == idnetscapeurl) 
00420             return (runworldwideurl (hscript, errorstring));
00421             
00422         if (idlanguage == idnetscapejavascript) 
00423             return (rungraphicalurl (hscript, errorstring));
00424     
00425     #endif
00426     
00427     if (idlanguage == 'LAND') {
00428         
00429         if (tablename != nil) { /*1.0b23 dmb*/
00430         
00431             texthandletostring (tablename, bswith);
00432             
00433             insertstring ("\pwith system.compiler.cards.[\"", bswith);
00434             
00435             pushstring ("\p\"] {", bswith);
00436             
00437             if (!pushathandlestart (bswith + 1, stringlength (bswith), hscript)) {
00438                 
00439                 disposehandle (hscript);
00440                 
00441                 return (false);
00442                 }
00443             
00444             copystring ("\p}", bswith);
00445             
00446             pushtexthandle (bswith, hscript);
00447             }
00448         
00449         #ifdef isFrontier
00450         
00451         /*bypass the component manager; run script directly*/ {
00452         
00453             extern boolean langrunhandletraperror (Handle, bigstring, bigstring);
00454             bigstring bsresult;
00455             
00456             if (!langrunhandletraperror (hscript, bsresult, errorstring))
00457                 return (false); /***need to trap error info*/
00458             
00459             if (flgetreturn)
00460                 return (newtexthandle (bsresult, hreturns));
00461             
00462             return (true);
00463             }
00464             
00465         #endif
00466         }
00467     
00468     setstringlength (errorstring, 0);   
00469     
00470     #if TARGET_API_MAC_CARBON == 1 /*PBS 03/14/02: AE OS X fix.*/
00471     
00472         newdescwithhandle (&scriptdesc, typeChar, hscript);
00473     
00474     #else
00475         
00476         scriptdesc.descriptorType = typeChar;
00477 
00478         scriptdesc.dataHandle = hscript;
00479     
00480     #endif
00481     
00482     scriptcomp = findlangcomponent (idlanguage);
00483     
00484     if (scriptcomp == 0) { /*didn't find the component*/
00485         
00486         bigstring bs;
00487         
00488         AEDisposeDesc (&scriptdesc);
00489     
00490         copystring ("\pCouldn't find the '", errorstring);
00491         
00492         setstringlength (bs, 4);
00493         
00494         moveleft (&idlanguage, &bs [1], 4);
00495         
00496         pushstring (bs, errorstring);
00497         
00498         pushstring ("\p' scripting component.", errorstring);
00499         
00500         return (false);
00501         }
00502     
00503     ec = OSADoScript (scriptcomp, &scriptdesc, kOSANullScript, typeChar, kOSAModeTransparentScope, &resultdesc);
00504     
00505     if (ec != noErr)
00506         goto error;
00507     
00508     AEDisposeDesc (&scriptdesc);
00509     
00510     if (flgetreturn)
00511     
00512         #if TARGET_API_MAC_CARBON == 1 /*PBS 03/14/02: AE OS X fix.*/
00513     
00514             copydatahandle (&resultdesc, hreturns);
00515             
00516         #else
00517         
00518             *hreturns = resultdesc.dataHandle;
00519         
00520         #endif
00521     else
00522         AEDisposeDesc (&resultdesc);
00523     
00524     return (true);
00525     
00526     error:
00527     
00528     AEDisposeDesc (&scriptdesc);
00529     
00530     if (ec == errOSAScriptError) { /*try to get an error message*/ 
00531         
00532         AEDesc errordesc;
00533         
00534         ec = OSAScriptError (scriptcomp, kOSAErrorMessage, typeChar, &errordesc);
00535         
00536         if (ec == noErr) {
00537             
00538             #if TARGET_API_MAC_CARBON == 1 /*PBS 03/14/02: AE OS X fix.*/
00539             
00540                 datahandletostring (&errordesc, errorstring);
00541             
00542             #else
00543             
00544                 texthandletostring (errordesc.dataHandle, errorstring);
00545             
00546             #endif
00547             
00548             AEDisposeDesc (&errordesc);
00549             }
00550         else 
00551             copystring ("\pThe script generated an error, but no message was provided.", errorstring);
00552         }
00553     
00554     if (ec == -128) /*1.0b15 DW -- user cancelled the script with cmd-period*/
00555         return (false);
00556     
00557     if (stringlength (errorstring) == 0) {
00558         
00559         copystring ("\pComponent Manager error. Its code number is ", errorstring);
00560         
00561         pushlong (ec, errorstring);
00562         
00563         pushstring ("\p.", errorstring);
00564         }
00565     
00566     return (false);
00567     } /*runlangscript*/
00568 

Generated on Wed May 31 18:19:50 2006 for frontierkernel 10.1.10a by  doxygen 1.4.6