langipc.c

Go to the documentation of this file.
00001 
00002 /*  $Id: langipc.c 1293 2006-04-18 17:49:06Z andreradke $    */
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 <land.h>
00032 #include "error.h"
00033 #include "memory.h"
00034 #include "ops.h"
00035 #include "strings.h"
00036 #include "file.h"
00037 #include "launch.h"
00038 #include "resources.h"
00039 #include "shell.h"
00040 #include "shellhooks.h"
00041 #include "oplist.h"
00042 #include "lang.h"
00043 #include "langinternal.h"
00044 #include "langipc.h"
00045 #include "langexternal.h"
00046 #include "langsystem7.h"
00047 #include "tableinternal.h" /*for error string numbers -- see langipctablemessage*/
00048 #include "tablestructure.h"
00049 #include "tableverbs.h"
00050 #include "op.h"
00051 #include "meprograms.h"
00052 #include "process.h"
00053 #include "processinternal.h"
00054 #include "byteorder.h"
00055 #ifdef flcomponent
00056     #include <uisharing.h>
00057     #include <uisinternal.h>
00058     #include "osacomponent.h"
00059     #include <SetUpA5.h>
00060 #endif
00061 
00062 #if TARGET_API_MAC_CARBON == 1 /*PBS 03/14/02: AE OS X fix.*/
00063     #include "aeutils.h"
00064 #endif
00065 
00066 
00067 // Subroutine Events:
00068 
00069 /*
00070 enum {
00071     kASSubroutineEvent          = 'psbr',
00072     keyASSubroutineName         = 'snam'
00073 };
00074 */
00075 
00076 #define keykerneltable 'ktbl'
00077 #define keycurrenttable 'ctbl'
00078 
00079 
00080 #define landnofileopenerror (lastinternalerror + 1)
00081 
00082 #define idwho 'who?'
00083 #define isruntime   0x0000
00084 #define isfrontier  0x0001
00085 
00086 #define bcdversion  0x05000000
00087 
00088 
00089 #if flruntime
00090 
00091     #define iswho (bcdversion + isruntime)
00092 
00093 #else
00094     
00095     #define iswho (bcdversion + isfrontier)
00096 
00097 #endif
00098     
00099 
00100 
00101 typedef struct tyipcaddress {
00102     
00103     OSType appid;
00104     
00105     Str32 appname;
00106     
00107     typrocessid appprocessid;
00108     
00109     boolean flcodeval; /*set if val contains address of direct handler*/
00110     
00111     boolean flrootval; /*set if val contains filespec of root handler*/
00112     
00113     tyvaluerecord val;
00114     
00115     /*remaining fields for network addresses*/
00116     
00117     boolean flnetwork; /*set if these fields are meaningful*/
00118     
00119     tynetworkaddress netaddress; /*will be null desciptor if not on network*/
00120     } tyipcaddress;
00121 
00122 
00123 typrocessid langipcself;
00124 
00125 static boolean fltoolkitinitialized = false;
00126 
00127 static hdlverbrecord hipcverb = nil; /*the verb currently being handled*/
00128 
00129 //Code change by Timothy Paustian Wednesday, June 14, 2000 8:59:44 PM
00130 //Changed to Opaque call for Carbon
00131 //This is never used except to get the zone which is never
00132 //used anywhere else in the application
00133 //static THz langipczone;
00134 
00135 //static Handle langipcresmap;
00136 
00137 static short langipcresfile;
00138 
00139 
00140 
00141 boolean langipcerrorroutine (bigstring bs, ptrvoid refcon) {
00142 #pragma unused (refcon)
00143 
00144     /*
00145     if an error occurs while processing a runscript verb, we want to 
00146     return the text that would normally go into the langerror window as 
00147     an error string to our caller.
00148     
00149     we can't call landreturnerror because our error string doesn't have 
00150     anything to do with our stringlist.  so we push our error values 
00151     manually.
00152     
00153     7/2/91 dmb: we can only get called when a process is running that 
00154     was dispatched from this file, or when an error occurs while no 
00155     process is running.  to support multiple threads, we get the verb handle 
00156     from the process refcon if one is running.
00157     
00158     2/4/92 dmb: don't call langerrorenabled or set fllangerror here; now 
00159     handled by langerrormessage
00160     
00161     4/1/93 dmb: allow for the possibility that the process is non-nil, but 
00162     doesn't have the verbrecord attached
00163     */
00164     
00165     register hdlverbrecord hv = nil;
00166     
00167     if (currentprocess != nil)
00168         hv = (hdlverbrecord) (**currentprocess).processrefcon;
00169     
00170     if (hv == nil)
00171         hv = hipcverb;
00172     
00173     if ((**hv).verbtoken != idscriptcompleted) { /*this isn't a menu sharing return message*/
00174         
00175         if (!landstartreturn (hv)) /*error returning error!*/
00176             return (true);
00177         }
00178     
00179     if (!landpushstringparam (hv, bs, errorstringkey))
00180         return (true);
00181     
00182     landpushintparam (hv, errAEEventFailed, errornumberkey); /*non-zero.  descriptiveness comes from string*/
00183     
00184     return (false); /*consume the error*/
00185     } /*langipcerrorroutine*/
00186 
00187 
00188 static void langipchookerrors (hdlverbrecord hverb, callback *savecallback) {
00189     
00190     *savecallback = (callback) langcallbacks.errormessagecallback;
00191     
00192     langcallbacks.errormessagecallback = &langipcerrorroutine;
00193     
00194     shellpusherrorhook ((errorhookcallback) &langipcerrorroutine);
00195     
00196     hipcverb = hverb; /*make visible to errorroutine*/
00197     } /*langipchookerrors*/
00198 
00199 
00200 static boolean langipcunhookerrors (callback savecallback) {
00201     
00202     shellpoperrorhook ();
00203     
00204     langcallbacks.errormessagecallback = (langerrormessagecallback) savecallback;
00205     
00206     fllangerror = false; /*make sure error flag is cleared*/
00207     
00208     hipcverb = nil;
00209     
00210     return (true);
00211     } /*langipcunhookerrors*/
00212 
00213 
00214 boolean langipcpushparam (tyvaluerecord *valparam, typaramkeyword key, hdlverbrecord hverb) {
00215     
00216     /*
00217     convert our internal value format into the format used for interprocess
00218     communications and push the result on the accumulating packet.
00219     
00220     4/29/92 dmb: added fldontexempt flag to fix memory leak when sending rgb, pattern 
00221     and rect values
00222     
00223     2.1b2 dmb: don't push values w/no type
00224     
00225     2.1b3 dmb: rewrote; no longer use land paramrecords
00226     
00227     2.1b9 dmb: need special case for addressvaluetype
00228     
00229     2.1b12 dmb: take valparam by reference so we can zero it when when we 
00230     steal the handle.
00231     */
00232     
00233     register tyvaluerecord *v = valparam;
00234     OSType type;
00235     void *pval = nil;
00236     Handle hval = nil;
00237     long len = 0;
00238     byte flval;
00239     bigstring bsval;
00240     AEDesc aelist;
00241     
00242     #if __powerc
00243     extended80 x80;
00244     #endif
00245     
00246     type = langgettypeid ((*v).valuetype);
00247     
00248     switch ((*v).valuetype) { /*set hval or pval/len*/
00249         
00250         case novaluetype: /*2.1b2*/
00251             return (true);
00252         
00253         case booleanvaluetype: /*our booleans are 2 bytes, but AE Booleans are 1 byte*/
00254             flval = bitboolean ((*v).data.flvalue);
00255             
00256             pval = &flval;
00257             
00258             len = sizeof (flval);
00259             
00260             break;
00261         
00262         case charvaluetype:
00263             pval = &(*v).data.chvalue;
00264             
00265             len = sizeof ((*v).data.chvalue);
00266             
00267             break;
00268         
00269         case intvaluetype:
00270             pval = &(*v).data.intvalue;
00271             
00272             len = sizeof ((*v).data.intvalue);
00273             
00274             break;
00275         
00276         case directionvaluetype:
00277             pval = &(*v).data.dirvalue;
00278             
00279             len = sizeof ((*v).data.dirvalue);
00280             
00281             break;
00282         
00283         case longvaluetype: /*all of these are normal, four-byte types  */
00284         case datevaluetype: /*whose langtypeid matches their AE DescType*/
00285         case ostypevaluetype:
00286         case enumvaluetype:
00287         case fixedvaluetype:
00288         case pointvaluetype:
00289         case singlevaluetype:
00290             pval = &(*v).data.longvalue;
00291             
00292             len = sizeof ((*v).data.longvalue);
00293             
00294             break;
00295         
00296         case binaryvaluetype: /*binary values need their AE type extracted*/
00297             if (!copyvaluedata (v))
00298                 return (false);
00299             
00300             hval = (*v).data.binaryvalue;
00301             
00302             pullfromhandle (hval, 0L, sizeof (OSType), &type);
00303             
00304             break;
00305         
00306         case objspecvaluetype: /*special case of nil objects*/
00307             hval = (*v).data.objspecvalue;
00308             
00309             if (hval == nil)
00310                 type = typeNull;
00311             
00312             break;
00313         
00314         #if __powerc
00315         
00316             case doublevaluetype: {
00317                 long double x = **(*v).data.doublevalue;
00318                  
00319                 safeldtox80 (&x, &x80);
00320                  
00321                 pval = &x80;
00322                  
00323                 len = sizeof (x80);
00324                  
00325                 break;
00326                 }
00327         #else
00328         
00329             case doublevaluetype:
00330             
00331         #endif
00332         
00333         case stringvaluetype:   /*all of these are normal, handle-based types */
00334         case rectvaluetype:     /*whose langtypeid matches their AE DescType  */
00335         case patternvaluetype:
00336         case rgbvaluetype:
00337         case filespecvaluetype:
00338         case aliasvaluetype:
00339     #ifndef oplanglists
00340         case listvaluetype:
00341         case recordvaluetype:
00342     #endif
00343             hval = (*v).data.stringvalue;
00344             
00345             break;
00346         
00347     #ifdef oplanglists
00348         case listvaluetype:
00349         case recordvaluetype:
00350             if (!langipcconvertoplist (v, &aelist))
00351                 return (false);
00352             
00353             #if TARGET_API_MAC_CARBON == 1 /*PBS 03/14/02: AE OS X fix.*/
00354             
00355                 copydatahandle (&aelist, &hval);
00356                 
00357             #else
00358             
00359                 hval = aelist.dataHandle;
00360             
00361             #endif
00362             
00363             disposevaluerecord (*v, false); /*override exempt, below*/
00364         
00365             setnilvalue (v); /*clear out value*/
00366             
00367             break;
00368     
00369     #endif
00370     
00371         case addressvaluetype:  /*addresses need to be sent as strings for safety*/
00372             getaddresspath (*v, bsval);
00373             
00374             pval = bsval + 1;
00375             
00376             len = stringlength (bsval);
00377             
00378             break;
00379         
00380         default: /*not a supported type for ipc*/
00381             langerror (badoutgoingipctypeerror);
00382             
00383             return (false);
00384         
00385         } /*switch*/
00386     
00387     if (!landpushparam (hverb, (typaramtype) type, hval, pval, len, key))
00388         return (false);
00389     
00390     if (hval != nil) { /*handle was merged into hverb*/
00391         
00392         exemptfromtmpstack (v);
00393         
00394         initvalue (v, novaluetype); /*clear out value*/
00395         }
00396     
00397     return (true);
00398     } /*langipcpushparam*/
00399 
00400 
00401 static boolean langipccoerceparam (AEDesc *param, tyvaluerecord *vreturned) {
00402     
00403     /*
00404     convert a value returned by UserLand IPC into lang.c's a valuerecord,
00405     consuming it.  for binary types, we save memory by stealing the binary 
00406     handle itself and setting the param record's handle to nil (instead of 
00407     making a copy of it).  if the caller is working with a copy of a parmater 
00408     record, then it must update the original after this call
00409     
00410     4/28/92 dmb: consume param
00411     
00412     8/12/92 dmb: special case for international text ('itxt')
00413     
00414     2.1b3 dmb: rewrote
00415     
00416     2.1b6 dmb: map a typeNull descriptor into a nil value, not a null objspec
00417     
00418     2.1b9 dmb: need special case for addressvaluetype
00419     
00420     4.1b6 dmb: handling incomine double floating values by asking the AE 
00421     manager to convert to extended for us.
00422     
00423     03/14/2002 PBS: AE OS X fix
00424     
00425     2002-11-15 AR: rewritten to make sure we _always_ consume param and also the data handle,
00426     but don't modify, i.e. set to nil, the dataHandle field of any AEDesc param record
00427     */
00428     
00429     register AEDesc *p = param;
00430     register DescType desctype = (*p).descriptorType;
00431     register tyvaluerecord *v = vreturned;
00432     Handle hdata;   
00433     bigstring bs;
00434     tyvaluetype vtype;
00435     boolean fl = true;
00436 
00437     if (desctype == typeLongFloat) {  /*4.1b6 dmb: convert to extended so we understand it*/
00438         
00439         AEDesc pnew;
00440         OSErr errorcode;
00441         
00442         errorcode = AECoerceDesc (p, typeExtended, &pnew);
00443         
00444         AEDisposeDesc (p);
00445     
00446         if (oserror (errorcode))
00447             return (false);
00448         
00449         *p = pnew;
00450         
00451         desctype = (*p).descriptorType;
00452         }
00453     
00454     vtype = langgetvaluetype (desctype);
00455 
00456     #ifdef oplanglists
00457         
00458         if (vtype == listvaluetype || vtype == recordvaluetype) {   /*only case that actually needs AEDesc record*/
00459         
00460             fl = langipcconvertaelist (p, v);
00461             
00462             AEDisposeDesc (p);
00463             
00464             return (fl);
00465             }
00466 
00467     #endif
00468     
00469     #if TARGET_API_MAC_CARBON == 1
00470         
00471         copydatahandle (p, &hdata); /*make a copy of the opaque data handle*/
00472 
00473     #else
00474     
00475         hdata = (*p).dataHandle;    /*get a reference to the data handle*/
00476         
00477         (*p).dataHandle = nil;  /*we own the original now, make sure AE manager won't dispose*/
00478 
00479     #endif
00480     
00481     AEDisposeDesc (p);
00482     
00483     initvalue (v, vtype); /*don't leave garbage in unassigned fields*/
00484     
00485     switch (vtype) {
00486         
00487         case booleanvaluetype:
00488             (*v).data.flvalue = numberfromhandle (hdata) != 0;
00489             
00490             break;
00491         
00492         case charvaluetype:
00493             (*v).data.chvalue = numberfromhandle (hdata);
00494             
00495             break;
00496         
00497         case intvaluetype:
00498             (*v).data.intvalue = numberfromhandle (hdata);
00499             
00500             break;
00501         
00502         case directionvaluetype:
00503             (*v).data.dirvalue = (tydirection) numberfromhandle (hdata);
00504             
00505             break;
00506         
00507         case longvaluetype: /*all of these are normal, four-byte types  */
00508         case datevaluetype: /*whose langtypeid matches their AE DescType*/
00509         case ostypevaluetype:
00510         case enumvaluetype:
00511         case fixedvaluetype:
00512         case pointvaluetype:
00513         case singlevaluetype:
00514             (*v).data.longvalue = numberfromhandle (hdata);
00515             
00516             break;
00517         
00518         case objspecvaluetype:
00519             
00520             fl = setheapvalue (hdata, objspecvaluetype, v); /*consumes hdata*/
00521             
00522             hdata = nil;
00523             
00524             break;
00525         
00526         #if __powerc
00527         
00528             case doublevaluetype: {
00529                 long double ld;
00530                 
00531                 assert (gethandlesize (hdata) == sizeof (extended80));
00532                 
00533                 safex80told (*(extended80 **) hdata, &ld);
00534                 
00535                 fl = setdoublevalue (ld, v);
00536                 
00537                 break;
00538                 }
00539         
00540         #else
00541         
00542             case doublevaluetype:
00543         
00544         #endif
00545         
00546         case stringvaluetype:   /*all of these are normal, handle-based types */
00547         case rectvaluetype:     /*whose langtypeid matches their AE DescType  */
00548         case patternvaluetype:
00549         case rgbvaluetype:
00550         case filespecvaluetype:
00551         case aliasvaluetype:
00552     #ifndef oplanglists
00553         case listvaluetype:
00554         case recordvaluetype:
00555     #endif
00556         case binaryvaluetype:
00557             
00558             fl = setheapvalue (hdata, vtype, v);    /*consumes hdata*/
00559             
00560             hdata = nil;
00561             
00562             break;
00563     
00564     /*
00565     #ifdef oplanglists  //now handled as a special case above
00566         case listvaluetype:
00567         case recordvaluetype:
00568             if (!langipcconvertaelist (p, v))
00569                 return (false);
00570             
00571             break;
00572     #endif
00573     */
00574         case addressvaluetype: /*addresses must be converted back from strings*/
00575             
00576             fl = setheapvalue (hdata, stringvaluetype, v);  /*consumes hdata*/
00577             
00578             hdata = nil;
00579             
00580             break;
00581         
00582         default:
00583             switch (desctype) {
00584                 
00585                 case pathtype: /*these are so ancient they're almost certain not to come up*/
00586                 case stringtype:
00587                     copyheapstring ((hdlstring) hdata, bs);
00588                     
00589                     fl = setstringvalue (bs, v);
00590                     
00591                     break;
00592                 
00593                 case typeNull:
00594                     /*
00595                     if (!setheapvalue (nil, objspecvaluetype, v))
00596                         return  (false);
00597                     */
00598                     
00599                     (*v).valuetype = novaluetype;
00600                     
00601                     break;
00602                 
00603                 case typeTrue:
00604                     setbooleanvalue (true, v);
00605                     
00606                     break;
00607                 
00608                 case typeFalse:
00609                     setbooleanvalue (false, v);
00610                     
00611                     break;
00612                 
00613                 case typeIntlText:
00614                     
00615                     if (**(short **) hdata == smRoman) {
00616                         
00617                         pullfromhandle (hdata, 0, 4, nil); /*strip off script & language codes*/
00618                         
00619                         fl = setheapvalue (hdata, stringvaluetype, v);  /*consumes hdata*/
00620                         }
00621                     else {
00622                         
00623                         fl = setbinaryvalue (hdata, desctype, v);   /*consumes hdata*/
00624                         }
00625             
00626                     hdata = nil;
00627                     
00628                     break;
00629                 
00630                 default:
00631                     
00632                     fl = setbinaryvalue (hdata, desctype, v);   /*consumes hdata*/
00633             
00634                     hdata = nil;
00635 
00636                     break;
00637                 }
00638             
00639             break;
00640         
00641         } /*switch*/
00642 
00643     disposehandle (hdata);  /*checks for nil*/
00644     
00645     return (fl);
00646     } /*langipccoerceparam*/
00647 
00648 
00649 boolean setdescriptorvalue (AEDesc desc, tyvaluerecord *val) {
00650     
00651     /*
00652     if the descriptor corresponds to one of our types, set val to that type; 
00653     otherwise, set val to a binary value.
00654     
00655     the descriptor handle ends up on the temp stack, or is disposed 
00656     on error.
00657     
00658     11/6/92 dmb: use new langgoodbinarytype
00659     
00660     2.1b3 dmb: finally, we can just call langipccoerceparam -- cool!
00661     */
00662     
00663     return (langipccoerceparam (&desc, val));
00664     } /*setdescriptorvalue*/
00665 
00666 
00667 boolean valuetodescriptor (tyvaluerecord *val, AEDesc *desc) {
00668     
00669     /*
00670     2.1b3 dmb: create a descriptor corresponding to the given value 
00671     record, consuming it.  the resulting descriptor handle is not in
00672     the temp stack, and must be disposed by the caller.
00673     
00674     this routine could be made more efficient by extracting & using 
00675     langipcpushparam logic. note, however, that charactertypes are 
00676     treated differently. (this routine results in a 'TEXT' descriptor)
00677     
00678     2.1b6 dmb: special case for novaluetype -> typeNull
00679     
00680     2.1b14 dmb: special case for addressvaluetype, pass as string
00681     */
00682     
00683     boolean fl;
00684     
00685     switch ((*val).valuetype) {
00686         
00687         case novaluetype:
00688             (*desc).descriptorType = typeNull;
00689             
00690             #if TARGET_API_MAC_CARBON == 1 /*PBS 03/14/02: AE OS X fix.*/
00691             
00692                 newdescnull (desc, typeNull);
00693                 
00694             #else
00695     
00696                 (*desc).descriptorType = typeNull;
00697                                 
00698             #endif
00699 
00700             return (true);
00701     
00702         case addressvaluetype: { /*2.1b14*/
00703             bigstring bspath;
00704             OSType typeid = langgettypeid (addressvaluetype);
00705             
00706             getaddresspath (*val, bspath);
00707             
00708             return (!oserror (AECreateDesc (typeid, bspath + 1, stringlength (bspath), desc)));
00709             }
00710         
00711     #ifdef oplanglists
00712         case listvaluetype:
00713         case recordvaluetype:
00714             if (!langipcconvertoplist (val, desc))
00715                 return (false);
00716             
00717             disposevaluerecord (*val, false);
00718             
00719             setnilvalue (val);
00720             
00721             return (true);
00722     #endif
00723         
00724         default:
00725             fl = coercetobinary (val);
00726             
00727             if (fl) {
00728                 
00729                 binarytodesc ((*val).data.binaryvalue, desc);
00730                 
00731                 exemptfromtmpstack (val);
00732                 }
00733             else
00734                 disposevaluerecord (*val, true);
00735             
00736             (*val).data.binaryvalue = nil; /*handle has been consumed*/
00737             
00738             return (fl);
00739         }
00740     } /*valuetodescriptor*/
00741 
00742 
00743 static boolean langipcfileopen (hdlverbrecord hverb) {
00744     
00745     /*
00746     6/26/92 dmb: don't call shellsetsuperglobals; require that globals 
00747     already be properly set -- which they should be.  this avoids a dependency 
00748     on the Mac WindowList, which isn't valid when system handlers are running
00749     */
00750     
00751     /*
00752     if (!shellsetsuperglobals ()) {
00753     */
00754     
00755     if (roottable == nil) {
00756         
00757         landreturnerror (hverb, landnofileopenerror);
00758         
00759         return (false);
00760         }
00761     
00762     return (true);
00763     } /*langipcfileopen*/
00764 
00765 
00766 static boolean langipcprocessstarted (void) {
00767     
00768     /*
00769     we don't want Frontier's menus to dim when serving another application's 
00770     doscript or trap call.
00771     */
00772     
00773     processnotbusy ();
00774     
00775     return (true);
00776     } /*langipcprocessstarted*/
00777 
00778 
00779 static boolean langipcruncode (hdlverbrecord hverb, hdltreenode hcode, hdlhashtable hcontext, boolean flstringresult) {
00780     
00781     /*
00782     2.1b12 dmb: shared code between trap and doscript verbs.
00783     
00784     we always consume hcode
00785     
00786     2.1b14 dmb: take hcontext parameter for special kernel call case
00787     
00788     4.0b7 dmb: fixed double-dispose memory bug when
00789     */
00790     
00791     hdlprocessrecord hprocess;
00792     register hdlprocessrecord hp;
00793     register boolean fl;
00794     tyvaluerecord val;
00795     
00796     if (!newprocess (hcode, true, nil, 0L, &hprocess)) {
00797         
00798         langdisposetree (hcode);
00799         
00800         return (false);
00801         }
00802     
00803     hp = hprocess; /*copy into register*/
00804     
00805     (**hp).processrefcon = (long) hverb;
00806     
00807     (**hp).errormessagecallback = &langipcerrorroutine;
00808     
00809     (**hp).processstartedroutine = &langipcprocessstarted;
00810     
00811     (**hp).hcontext = hcontext;
00812     
00813     fl = processruncode (hprocess, &val);
00814     
00815     disposeprocess (hprocess);
00816     
00817     /*if no error occurred, return value to caller.  error hook handles error values*/
00818     
00819     if (fl) {
00820         
00821         if (flstringresult)
00822             coercetostring (&val);
00823         
00824         landstartreturn (hverb);
00825         
00826         if (!langipcpushparam (&val, returnedvaluekey, hverb)) {    // grabs handle unless it fails
00827         
00828             exemptfromtmpstack (&val);  // may or may not be a temp value now
00829             
00830             disposetmpvalue (&val);     // get rid of it
00831             }
00832         }
00833     
00834     return (fl);
00835     } /*langipcruncode*/
00836 
00837 
00838 static boolean langipchandlerunscript (hdlverbrecord hverb) {
00839     
00840     /*
00841     6/26/91 dmb: instead of blocking events, block ourselves until 
00842     the previous script is done
00843     
00844     2/5/92 dmb: restoring errormessagecallback must occur _after_ exit label.
00845     
00846     2/15/93 dmb: don't fork if verb is direct
00847     */
00848     
00849     Handle htext;
00850     callback savecallback;
00851     hdltreenode hcode;
00852     register boolean fl = false;
00853     
00854     if (!langipcfileopen (hverb))
00855         return (false);
00856     
00857     if (!landgettextparam (hverb, idscriptvalue, &htext))
00858         return (false);
00859     
00860     langipchookerrors (hverb, &savecallback);
00861     
00862     if (!langbuildtree (htext, false, &hcode)) /*syntax error*/
00863         goto exit;
00864     
00865     fl = langipcruncode (hverb, hcode, nil, true);
00866     
00867     exit:
00868     
00869     langipcunhookerrors (savecallback);
00870     
00871     return (fl); /*we will get here & return false if new thread didn't fork*/
00872     } /*langipchandlerunscript*/
00873 
00874 
00875 static boolean issubroutineverb (hdlverbrecord hverb) {
00876     
00877     register hdlverbrecord hv = hverb;
00878     
00879     return ( /*((**hv).verbclass == kOSASuite) && */ ((**hv).verbtoken == kASSubroutineEvent));
00880     } /*issubroutineverb*/
00881 
00882 
00883 static boolean iskernelverb (hdlverbrecord hverb) {
00884     
00885     register hdlverbrecord hv = hverb;
00886     
00887     return (issubroutineverb (hv) && ((**hv).verbclass == 'LAND'));
00888     } /*iskernelverb*/
00889 
00890 
00891 static boolean handlerexpectsnames (hdltreenode hcode, AERecord *event, hdltreenode *hparams) {
00892 
00893     /*
00894     5.0d14 dmb: look at the parameter list of the script in hcode, and 
00895     decide of it should be called with named parameters. we answer true
00896     if it takes more than one parameter, and all but the first parameter 
00897     have 4-character names that match keys of parameters in the event
00898     */
00899     
00900     hdltreenode hnames;
00901     hdltreenode nomad;
00902     tyvaluerecord osacode;
00903     bigstring bs;
00904     OSType key;
00905     DescType type;
00906     long size;
00907     
00908     if (hcode == nil)
00909         return (false);
00910     
00911     if ((**hcode).nodetype != moduleop)
00912         return (false);
00913     
00914     hcode = (**hcode).param1;
00915     
00916     if ((hcode == nil) || ((**hcode).nodetype == kernelop))
00917         return (false);
00918     
00919     if (isosascriptnode (hcode, &osacode))
00920         return (false);
00921     
00922     hcode = (**hcode).param2;
00923     
00924     if ((**hcode).nodetype != procop)
00925         return (false);
00926     
00927     hnames = (**hcode).param2;
00928     
00929     if (hnames == nil) // no formal params
00930         return (false);
00931     
00932     nomad = (**hnames).link; //advance to next name in list*/
00933     
00934     if (nomad == nil) // there was only one param
00935         return (false);
00936     
00937     while (true) { //step through remaining names in list
00938         
00939         if ((**nomad).nodetype == assignlocalop) {
00940             
00941             if (!langgetidentifier ((**nomad).param1, bs))
00942                 break;
00943             }
00944         else {
00945             
00946             if (!langgetidentifier (nomad, bs))
00947                 break;
00948             }
00949         
00950         if (stringlength (bs) != 4)
00951             break;
00952         
00953         if ((**nomad).nodetype != assignlocalop) { // not an optional param
00954             
00955             stringtoostype (bs, &key);
00956             
00957             if (AESizeOfKeyDesc (event, key, &type, &size) == errAEDescNotFound)
00958                 break;
00959             }
00960         
00961         nomad = (**nomad).link; //advance to next name in list
00962         
00963         if (nomad == nil) { //reached the end of list
00964             
00965             *hparams = hnames;
00966             
00967             return (true);
00968             }
00969         } /*while*/
00970     
00971     return (false);
00972     } /*handlerexpectsnames*/
00973 
00974 
00975 static boolean findnamedparam (hdltreenode hnames, bigstring bsname) {
00976     
00977     /*
00978     given the function parameter list, see if it contains the given (string4) name
00979     */
00980     
00981     hdltreenode nomad;
00982     bigstring bs;
00983     
00984     for (nomad = (**hnames).link; nomad != nil; nomad = (**nomad).link) {
00985     
00986         if ((**nomad).nodetype == assignlocalop) {
00987             
00988             if (!langgetidentifier ((**nomad).param1, bs))
00989                 continue;
00990             }
00991         else {
00992             
00993             if (!langgetidentifier (nomad, bs))
00994                 continue;
00995             }
00996         
00997         if (equalidentifiers (bs, bsname)) //5.0a8 dmb: case-insensitive
00998             return (true);
00999         }
01000     
01001     return (false);
01002     } /*findnamedparam*/
01003 
01004 
01005 boolean langipcbuildparamlist (hdltreenode hcode, hdlverbrecord hverb, hdltreenode *hparams) {
01006     
01007     /*
01008     take all of the parameters in the incoming verb hverb and build a code 
01009     tree for the corresponding lang paramter list
01010     
01011     2.1b5 dmb: special case for subroutine events
01012     
01013     2.1b12 dmb: push the root table to make sure address values will work
01014     
01015     3.0.1b2 dmb: for subroutine events, the direct parameter is optional
01016     
01017     5.0d14 dmb: take hcode parameter, so we can see of trap script takes 
01018     parameters by name. the first (direct) parameter can have any name. if
01019     all others are 4 characters long, and appear in the event, we use names.
01020     */
01021     
01022     register short i;
01023     long ctparams;
01024     hdltreenode hlist = nil;
01025     AEDescList directparam;
01026     typaramrecord param;
01027     tyvaluerecord val;
01028     hdltreenode hparam;
01029     AERecord event, reply;
01030     AERecord *list;
01031     boolean flpushedroot;
01032     boolean flnamedparams;
01033     byte bskey [6];
01034     tyvaluerecord vkey;
01035     hdltreenode hname, hnamelist;
01036     OSErr err;
01037     register boolean fl = false;
01038     
01039     landsystem7geteventrecords (hverb, &event, &reply);
01040     
01041     if (issubroutineverb (hverb)) {
01042         
01043         err = AEGetKeyDesc (&event, keyDirectObject, typeAEList, &directparam);
01044         
01045         if (err == errAEDescNotFound) {
01046             
01047             *hparams = nil;
01048             
01049             return (true);
01050             }
01051         
01052         if (oserror (err))
01053             return (false);
01054         
01055         flnamedparams = false;
01056         
01057         list = &directparam;
01058         }
01059     else {
01060         
01061         flnamedparams = handlerexpectsnames (hcode, &event, &hnamelist);
01062         
01063         list = &event;
01064         }
01065     
01066     if (currenthashtable == nil)
01067         flpushedroot = pushhashtable (roottable);
01068     else
01069         flpushedroot = false;
01070     
01071     if (oserror (AECountItems (list, &ctparams)))
01072         goto exit;
01073     
01074     for (i = 1; i <= ctparams; i++) {
01075         
01076         if (!landsystem7getnthparam (list, i, &param))
01077             goto exit;
01078         
01079         if (!langipccoerceparam (&param.desc, &val))
01080             goto exit;
01081         
01082         exemptfromtmpstack (&val); /*its data is about to belong to code tree*/
01083         
01084         if (!newconstnode (val, &hparam))
01085             goto exit;
01086         
01087         if (flnamedparams && i > 1) { // 5.0d14 dmb
01088             
01089             ostypetostring (param.key, bskey);
01090             
01091             if (!findnamedparam (hnamelist, bskey)) { // trap isn't expecting this param
01092                 
01093                 langdisposetree (hparam);
01094                 
01095                 continue;
01096                 }
01097             
01098             if (!setstringvalue (bskey, &vkey) || !newidnode (vkey, &hname)) {
01099                 
01100                 langdisposetree (hparam);
01101                 
01102                 goto exit;
01103                 }
01104             
01105             exemptfromtmpstack (&vkey);
01106             
01107             if (!pushbinaryoperation (fieldop, hname, hparam, &hparam))
01108                 goto exit;
01109             }
01110         
01111         if (hlist == nil)
01112             hlist = hparam;
01113         else
01114             pushlastlink (hparam, hlist);
01115         } /*for*/
01116     
01117     fl = true;
01118     
01119     exit:
01120     
01121     if (flpushedroot)
01122         pophashtable ();
01123     
01124     if (issubroutineverb (hverb)) /*need to dispose of parameter list record*/
01125         AEDisposeDesc (list);
01126     
01127     if (fl)
01128         *hparams = hlist; /*nil if there weren't any params*/
01129     else
01130         langdisposetree (hlist); /*checks for nil*/
01131     
01132     return (fl);
01133     } /*langipcbuildparamlist*/
01134 
01135 
01136 static boolean langipcvalhascode (const tyvaluerecord *val) {
01137     
01138     /*
01139     4/30/92 dmb: created as part of new code extension support
01140     */
01141     
01142     register const tyvaluerecord *v = val;
01143     hdltreenode hcode;
01144     
01145     switch ((*v).valuetype) {
01146         
01147         case externalvaluetype:
01148             return (langexternalvaltocode (*v, &hcode));
01149         
01150         case binaryvaluetype: /*maybe should qualify by binarytype*/
01151             return (true);
01152         
01153         default:
01154             return (false);
01155         }
01156     } /*langipcvalhascode*/
01157 
01158 
01159 static boolean langipcfindtraphandler (hdlverbrecord hverb, tyvaluerecord *adr) {
01160     
01161     /*
01162     search the traps table for a handler for the given verb.
01163     
01164     if there's a script named after the verb at the top level of the traps table, use it.
01165     
01166     otherwise, look for a subtable named after the verb class, and see if it contains 
01167     the desired handler.
01168     
01169     2.1b1 dmb: don't leave trap address value in the temp stack.  langipchandletrapverb 
01170     now takes care of disposal
01171     
01172     2.1b5 dmb: added support for subroutine traps
01173     */
01174     
01175     register hdlverbrecord hv = hverb;
01176     register hdlhashtable ht;
01177     hdlhashtable htable;
01178     tyvaluerecord val;
01179     bigstring bsclass;
01180     bigstring bstrap;
01181     boolean fl;
01182     hdlhashnode hnode;
01183     
01184     if (issubroutineverb (hv)) {
01185         
01186         if (!landgetstringparam (hv, keyASSubroutineName, bstrap)) 
01187             return (false);
01188         
01189         if (iskernelverb (hv)) { /*special case -- kernel verb specifies table*/
01190             
01191             if (!landgetlongparam (hv, keykerneltable, (long *) &htable))
01192                 return (false);
01193             
01194             ht = htable;
01195             
01196             goto exit;
01197             }
01198         
01199         disablelangerror ();
01200         
01201         fl = langexpandtodotparams (bstrap, &htable, bstrap);
01202         
01203         enablelangerror ();
01204         
01205         if (!fl)
01206             return (false);
01207         
01208         if ((htable == nil) && !langsearchpathlookup (bstrap, &htable))
01209             return (false);
01210         
01211         if (!landpushstringparam (hv, bstrap, keyASSubroutineName)) /*substitute name only*/
01212             return (false);
01213         
01214         ht = htable;
01215         
01216         goto exit;
01217         }
01218     
01219     if (iachandlertable == nil) /*no traps table*/
01220         return (false);
01221     
01222     ostypetostring ((**hv).verbtoken, bstrap);
01223     
01224     if (hashtablelookup (iachandlertable, bstrap, &val, &hnode)) {
01225         
01226         if (langipcvalhascode (&val)) {
01227             
01228             ht = iachandlertable;
01229             
01230             goto exit;
01231             }
01232         }
01233     
01234     ostypetostring ((**hv).verbclass, bsclass);
01235     
01236     if (!hashtablelookup (iachandlertable, bsclass, &val, &hnode))
01237         return (false);
01238     
01239     if (!langexternalvaltotable (val, &htable, hnode))
01240         return (false);
01241     
01242     ht = htable; /*copy into register*/
01243     
01244     if (!hashtablelookup (ht, bstrap, &val, &hnode)) { /*not found literally; check for spaces*/
01245         
01246         if (!poptrailingwhitespace (bstrap)) /*nothing to pop off*/
01247             return (false);
01248         
01249         if (!hashtablelookup (ht, bstrap, &val, &hnode)) /*oh well*/
01250             return (false);
01251         }
01252     
01253     if (!langipcvalhascode (&val)) { /*make sure it can be called*/
01254         
01255         langparamerror (notfunctionerror, bstrap);
01256         
01257         return (false);
01258         }
01259     
01260     exit:
01261     
01262     if (!setaddressvalue (ht, bstrap, adr))
01263         return (false);
01264     
01265     exemptfromtmpstack (adr);
01266     
01267     return (true);
01268     } /*langipcfindtraphandler*/
01269 
01270 /*
01271 static setglobaltransactionid (long idtransaction) {
01272     
01273     tyvaluerecord val;
01274     
01275     setlongvalue (idtransaction, &val);
01276     
01277     if (iachandlertable != nil)
01278         hashtableassign (iachandlertable, "\ptrapTransaction", val);
01279     } /%setglobaltransactionid%/
01280 */
01281 
01282 #if TARGET_API_MAC_CARBON == 0
01283 #if GENERATINGCFM
01284 
01285 #define BUILD_68K_ROUTINE_DESCRIPTOR(procInfo, m68kProcPtr)  \
01286     {                               \
01287     _MixedModeMagic,                \
01288     kRoutineDescriptorVersion,      \
01289     kSelectorsAreNotIndexable,      \
01290     0,                              \
01291     0,                              \
01292     0,                              \
01293     0,                              \
01294     {                               \
01295     {                               \
01296     (procInfo),                     \
01297     0,                              \
01298     kM68kISA,                       \
01299     kProcDescriptorIsAbsolute |     \
01300     kUseCurrentISA,                 \
01301     (ProcPtr)(m68kProcPtr),         \
01302     0,                              \
01303     0,                              \
01304     },                              \
01305     },                              \
01306     }
01307 
01308 static RoutineDescriptor UCMDDesc = BUILD_68K_ROUTINE_DESCRIPTOR (uppAEEventHandlerProcInfo, nil);
01309 
01310 #endif
01311 #endif
01312 
01313 
01314 static boolean langipchandletrapverb (hdlverbrecord hverb, boolean *flfoundhandler) {
01315     
01316     /*
01317     10/24/91 dmb: support 2-level traps table using langipcfindtraphandler routine
01318     
01319     12/2/91 dmb: hooked up new langipcprocessstarted to prevent menu dimming 
01320     and recalculation
01321     
01322     9/22/92 dmb: removed call to setglobaltransactionid. this was never documented, 
01323     and has been superceeded by the getEventAttribute verb
01324     
01325     2/15/93 dmb: don't fork if verb is direct
01326     
01327     4/1/93 dmb: added code to handle executing osa scripts. also moved landstartreturn
01328     block to before the exit rather than after it.
01329     
01330     2.1b13 dmb: oops, forgot to set last parameter to new langipcruncode to false.
01331     
01332     2.1b14 dmb: a special case for the kernelverb -- actual context is passed along. 
01333     the context must also be used while evaluating address parameters.
01334     */
01335     
01336     register hdlverbrecord hv = hverb;
01337     bigstring bsverb;
01338     register boolean fl = false;
01339     tyvaluerecord val;
01340     callback savecallback;
01341     hdltreenode hfunctioncall;
01342     hdltreenode hparamlist;
01343     hdltreenode hcode;
01344     hdlhashtable htable;
01345     hdlhashtable hcontext = nil;
01346     long refcon;
01347     tyvaluerecord vhandler;
01348     tyvaluerecord osacode;
01349     //Handle hthread = nil;
01350     hdlhashnode handlernode;
01351     AppleEvent event, reply;
01352     
01353     *flfoundhandler = false;
01354     
01355     if (!langipcfileopen (hv))
01356         return (false);
01357     
01358     refcon = (**hv).landrefcon;
01359     
01360     if (refcon == 0) { /*haven't already looked it up*/
01361         
01362         if (!langipcfindtraphandler (hv, &val)) /*no trap handler exists for this verb*/
01363             return (false);
01364         }
01365     else {
01366         initvalue (&val, addressvaluetype);
01367         
01368         val.data.addressvalue = (hdlstring) refcon;
01369         }
01370     
01371     pushvalueontmpstack (&val); /*make sure it's cleaned up in the end*/
01372     
01373     if (!getaddressvalue (val, &htable, bsverb))
01374         return (false);
01375     
01376     if (!hashtablelookupnode (htable, bsverb, &handlernode))
01377         return (false);
01378     
01379     vhandler = (**handlernode).val;
01380     
01381     *flfoundhandler = true;
01382     
01383     landsystem7geteventrecords (hv, &event, &reply);
01384     
01385     if (vhandler.valuetype == binaryvaluetype) {
01386         
01387         Handle h = vhandler.data.binaryvalue;
01388         
01389     #ifdef flcomponent
01390         if (**(OSType **) h != 'UCMD') {
01391             
01392             /*
01393             langparamerror (notucmderror, bsverb);
01394             */
01395             
01396             fl = evaluateosascriptevent (&vhandler, &event, &reply);
01397             
01398             return (fl);
01399             }
01400     #endif
01401         
01402         loadhandleremains (sizeof (OSType), h, &h);  //skip binarytype
01403         
01404         lockhandle ((Handle) h);
01405         
01406         /*
01407         bundle {
01408             RoutineDescriptor ucmddesc = BUILD_ROUTINE_DESCRIPTOR (uppAEEventHandlerProcInfo, nil);
01409             ucmddesc.routineRecords [0].procDescriptor = (ProcPtr) *h;  // fill in the blank
01410             fl = !oserror (CallAEEventHandlerProc (&ucmddesc, &event, &reply, 0L));
01411             }
01412         */
01413         
01414         //MakeDataExecutable (*h, gethandlesize (h)); //5.0.2 dmb
01415         
01416         /*
01417         fl = !oserror ((*(AEEventHandlerProcPtr) *h) (&event, &reply, 0L));
01418         */
01419         
01420         
01421         #if TARGET_API_MAC_CARBON == 1
01422         
01423             langerrormessage ("\pUCMDs are not supported in the Carbon version.");
01424             
01425         #else
01426         
01427             #if __powerc
01428                 fl = !oserror (CallAEEventHandlerProc ((UniversalProcPtr) (*h), &event, &reply, 0L));
01429             #else
01430                 fl = !oserror (CallAEEventHandlerProc ((tyeventhandler) (*h), &event, &reply, 0L));
01431             #endif
01432         
01433         #endif
01434         
01435         unlockhandle ((Handle) h);
01436         
01437         disposehandle (h);
01438         
01439         return (fl);
01440         }
01441     
01442     /*
01443     setglobaltransactionid ((**hv).idtransaction);
01444     */
01445     
01446     /*build a code tree and call the handler, with our error hook in place*/
01447     
01448     langipchookerrors (hv, &savecallback);
01449     
01450     hcode = nil;
01451     
01452     if ((**htable).valueroutine == nil) { /*not a kernel table*/
01453         
01454         if (!langexternalvaltocode (vhandler, &hcode))
01455             goto exit;
01456         
01457         if (hcode == nil) { /*needs compilation*/
01458             
01459             if (!langcompilescript (handlernode, &hcode))
01460                 goto exit;
01461             }
01462         
01463         #ifdef flcomponent
01464     
01465             if (isosascriptnode (hcode, &osacode)) {
01466                 
01467                 fl = evaluateosascriptevent (&osacode, &event, &reply);
01468                 
01469                 goto exit;
01470                 }
01471             
01472         #endif
01473         }
01474     
01475     if (iskernelverb (hv)) { /*special case -- kernel verb specifies context*/
01476         
01477         if (!landgetlongparam (hv, keycurrenttable, (long *) &hcontext))
01478             goto exit;
01479         }
01480     
01481     if (!pushfunctionreference (val, &hfunctioncall))
01482         goto exit;
01483     
01484     if (hcontext != nil)
01485         pushhashtable (hcontext);
01486     
01487     fl = langipcbuildparamlist (hcode, hv, &hparamlist);
01488     
01489     if (hcontext != nil)
01490         pophashtable ();
01491     
01492     if (!fl) {
01493         
01494         langdisposetree (hfunctioncall);
01495         
01496         goto exit;
01497         }
01498     
01499     if (!pushfunctioncall (hfunctioncall, hparamlist, &hcode)) /*consumes input parameters*/
01500         goto exit;
01501     
01502     if (!pushbinaryoperation (moduleop, hcode, nil, &hcode)) /*needs this level*/
01503         goto exit;
01504     
01505     fl = langipcruncode (hv, hcode, hcontext, false);
01506     
01507     exit:
01508     
01509     langipcunhookerrors (savecallback);
01510     
01511     return (fl);
01512     } /*langipchandletrapverb*/
01513 
01514 
01515 #if TARGET_API_MAC_OS8
01516 
01517 static boolean langipcgetmenuarrayverb (hdlverbrecord hverb) {
01518     
01519     long id;
01520     Handle h = nil; /*4.1b2 dmb*/
01521     short firstmenuresource;
01522     
01523     if (!langipcfileopen (hverb))
01524         return (false);
01525     
01526     if (!landgetlongparam (hverb, idmenuprogram, &id))
01527         return (false);
01528     
01529     if (!landgetintparam (hverb, idstartingresource, &firstmenuresource))
01530         return (false);
01531     
01532     if (!langipcgetmenuarray (id, firstmenuresource, false, &h)) {
01533         
01534         landreturnerror (hverb, outofmemoryerror); /*ran out of memory in menu server*/
01535         
01536         return (false);
01537         }
01538     
01539     return (landreturnbinary (hverb, h));
01540     } /*langipcgetmenuarrayverb*/
01541 
01542 
01543 static boolean langipcgetmenuhandleverb (hdlverbrecord hverb) {
01544     
01545     long id;
01546     short ixarray;
01547     Handle h;
01548     
01549     if (!langipcfileopen (hverb))
01550         return (false);
01551     
01552     if (!landgetlongparam (hverb, idmenuprogram, &id))
01553         return (false);
01554     
01555     if (!landgetintparam (hverb, idarrayindex, &ixarray))
01556         return (false);
01557     
01558     if (!langipcgetmenuhandle (id, ixarray, &h)) {
01559         
01560         landreturnerror (hverb, outofmemoryerror);
01561         
01562         return (false);
01563         }
01564     
01565     return (landreturnbinary (hverb, h));
01566     } /*langipcgetmenuhandleverb*/
01567 
01568 
01569 static boolean langipcrunmenuitemverb (hdlverbrecord hverb) {
01570     
01571     long id;
01572     short idmenu, iditem;
01573     long refcon;
01574     register hdlverbrecord hv = hverb;
01575     
01576     if (!langipcfileopen (hverb))
01577         return (false);
01578     
01579     if (!landgetlongparam (hv, idmenuprogram, &id))
01580         return (false);
01581     
01582     if (!landgetintparam (hv, idmenuidvalue, &idmenu))
01583         return (false);
01584     
01585     if (!landgetintparam (hv, idmenuitemvalue, &iditem))
01586         return (false);
01587     
01588     if (!langipcrunitem (id, idmenu, iditem, &refcon)) {
01589         
01590         landreturnerror (hv, outofmemoryerror);
01591         
01592         return (false);
01593         }
01594     
01595     return (landreturnlong (hv, refcon));
01596     } /*langipcrunmenuitemverb*/
01597 
01598 
01599 static boolean langipckillscriptverb (hdlverbrecord hverb) {
01600     
01601     /*
01602     the long parameter shoud be the refcon returned by runmenuitem.  since 
01603     we count count on perfect synchonization, we shouldn't assume that the 
01604     process still exists, so we're using the code instead of the process 
01605     handle itself.  the down side is that it won't find the process if the 
01606     current process list isn't the original one.  we can make this more 
01607     robust if necessary.
01608     
01609     7/17/92 dmb: refcon parameter uses directparamkey, not idmenuprogram
01610     */
01611     
01612     long refcon;
01613     boolean fl;
01614     
01615     if (!langipcfileopen (hverb))
01616         return (false);
01617     
01618     if (!landgetlongparam (hverb, directparamkey, &refcon))
01619         return (false);
01620     
01621     fl = processdisposecode ((hdltreenode) refcon);
01622     
01623     return (landreturnboolean (hverb, fl));
01624     } /*langipckillscriptverb*/
01625 
01626 #endif
01627 
01628 
01629 static pascal boolean langipchandleverb (hdlverbrecord hverb) {
01630     
01631     /*
01632     10/29/91 dmb: let traps have a chance at runscripttoken before executing 
01633     built-in code
01634     
01635     4.1b7 dmb: allow a specific root file to be targed with the "subject" 
01636     event attribute. Bug: right now, langipcfindhandler doesn't have this 
01637     logic. So if an event doesn't have a handler in this root, landsystem7
01638     will return eventnothandled even if the target root does have a handler.
01639     */
01640     
01641     boolean fl;
01642     boolean flfoundhandler;
01643     AEDesc subject;
01644     WindowPtr wroot = nil;
01645     
01646     oserror (noErr); /*make sure it's clear*/
01647     
01648     if (landgetverbattr (hverb, 'subj', typeFSS, &subject) == noErr) { /*4.1b7 dmb*/
01649         
01650         #if TARGET_API_MAC_CARBON == 1 /*PBS 03/14/02: AE OS X fix.*/
01651         
01652             FSSpec fs;
01653             
01654             Handle h;
01655             
01656             copydatahandle (&subject, &h);
01657             
01658             fs = **(FSSpec **) h;
01659             
01660             disposehandle (h);
01661         
01662         #else
01663         
01664             FSSpec fs = **(FSSpec **) subject.dataHandle;
01665         
01666         #endif
01667         
01668         wroot = shellfindfilewindow (&fs);
01669         
01670         if (wroot == nil) {
01671         
01672             // landreturnerror 
01673             }
01674         else {
01675             
01676             (**hverb).landrefcon = 0; /*don't use trap script found in other root*/
01677             
01678             shellpushglobals (wroot);
01679             
01680             (*shellglobals.setsuperglobalsroutine) ();
01681             }
01682         }
01683     
01684     switch ((**hverb).verbtoken) {
01685         
01686         case idrunning:
01687             fl = landreturnboolean (hverb, true); /*for old IACTK compatibility*/
01688             
01689             break;
01690         
01691         case idwho:
01692             fl = landreturnlong (hverb, iswho);
01693             
01694             break;
01695         
01696         case runscripttoken:
01697             fl = langipchandletrapverb (hverb, &flfoundhandler); /*let traps have a shot at it first*/
01698             
01699             if (!flfoundhandler)
01700                 fl = langipchandlerunscript (hverb);
01701             
01702             break;
01703         
01704         /*
01705         case schedulescripttoken:
01706             fl = langipchandleschedulescript (hverb);
01707             
01708             break;
01709         */
01710         
01711 #ifndef PIKE
01712     #if TARGET_API_MAC_OS8
01713         case getmenuarraytoken:
01714             fl = langipcgetmenuarrayverb (hverb);
01715             
01716             break;
01717         
01718         case getmenuhandletoken:
01719             fl = langipcgetmenuhandleverb (hverb);
01720             
01721             break;
01722         
01723         case idrunmenuitem:
01724             fl = langipcrunmenuitemverb (hverb);
01725             
01726             break;
01727         
01728         case killscripttoken:
01729             fl = langipckillscriptverb (hverb);
01730             
01731             break;
01732     #endif
01733 #endif
01734         
01735         default:
01736             fl = langipchandletrapverb (hverb, &flfoundhandler);
01737             
01738             if (!flfoundhandler) /*getoserror () == noErr*/
01739                 landreturnerror (hverb, undefinedverberror);
01740             
01741             break;
01742         }
01743     
01744     if (!fl) {
01745         
01746         if (landgeterror () == noErr)
01747             landseterror (getoserror ());
01748         }
01749     
01750     if (wroot != nil) {
01751         
01752         shellpopglobals ();
01753         
01754         (*shellglobals.setsuperglobalsroutine) ();
01755         }
01756 
01757     return (fl);
01758     } /*langipchandleverb*/
01759 
01760 
01761 static pascal boolean langipcfindhandler (hdlverbrecord hverb) {
01762     
01763     /*
01764     4/29/92 dmb: make sure we can actually handle this wildcard verb
01765     */
01766     
01767     tyvaluerecord val;
01768     
01769     if (!langipcfindtraphandler (hverb, &val)) /*no trap handler exists for this verb*/
01770         return (false);
01771     
01772     (**hverb).landrefcon = (long) val.data.addressvalue;
01773     
01774     return (true);
01775     } /*langipcfindhandler*/
01776 
01777 
01778 static boolean setbinarysymbolval (hdlhashtable htable, bigstring bs, Handle x, OSType typeid) {
01779     
01780     /*
01781     encapsulate some code that appears in the file more than once
01782     */
01783     
01784     tyvaluerecord val;
01785     
01786     if (!setbinaryvalue (x, typeid, &val))
01787         return (false);
01788     
01789     if (!langsetsymboltableval (htable, bs, val))
01790         return (false);
01791     
01792     exemptfromtmpstack (&val);
01793     
01794     return (true);
01795     } /*setbinarysymbolval*/
01796 
01797 
01798 static void langipcexpandnetaddress (tyipcaddress *ipcaddress) {
01799     
01800     /*
01801     fill out all fields in the ipc network address, seeded from netaddress
01802     */
01803     
01804     register tyipcaddress *adr = ipcaddress;
01805     
01806     (*adr).flnetwork = true;
01807     
01808     copystring ((*adr).netaddress.target.name.name, (*adr).appname); /*macnetglobals.location;*/
01809     
01810     if ((*adr).netaddress.target.name.portKindSelector == ppcByString)
01811         moveleft ((*adr).netaddress.target.name.u.portTypeStr + 1, &(*adr).appid, sizeof (OSType));
01812     else
01813         (*adr).appid = (*adr).netaddress.target.name.u.port.portCreator;
01814     } /*langipcexpandnetaddress*/
01815 
01816 
01817 static boolean getnetaddress (hdlhashtable htable, bigstring bsvarname, tyipcaddress *ipcaddress) {
01818     
01819     tyvaluerecord val;
01820     long ix = sizeof (OSType);
01821     hdlhashnode hnode;
01822     
01823     if (!hashtablelookup (htable, bsvarname, &val, &hnode))
01824         return (false);
01825     
01826     if (val.valuetype != binaryvaluetype)
01827         return (false);
01828     
01829     if (getbinarytypeid (val.data.binaryvalue) != 'targ')
01830         return (false);
01831     
01832     return (loadfromhandle (val.data.binaryvalue, &ix, sizeof (tynetworkaddress), &(*ipcaddress).netaddress));
01833     } /*getnetaddress*/
01834     
01835     
01836 boolean langipcbrowsenetwork (hdltreenode hparam1, tyvaluerecord *vreturned) {
01837     
01838     /*
01839     2/11/92 dmb: added support for prompt
01840     
01841     6/8/92 dmb: use landgeterror to make sure that user cancel doesn't terminate 
01842     the script
01843     */
01844     
01845     register hdltreenode hp1 = hparam1;
01846     tyapplicationid appid;
01847     tyipcaddress ipcaddress;
01848     hdlhashtable htable;
01849     bigstring bs;
01850     Handle x;
01851     bigstring bsprompt;
01852     short pnum = 1;
01853     
01854     setbooleanvalue (false, vreturned);
01855     
01856     setemptystring (bsprompt);
01857     
01858     if (langgetparamcount (hp1) != 2) { /*new calling conventions: require prompt*/
01859         
01860         if (!getstringvalue (hp1, pnum++, bsprompt))
01861             return (false);
01862         }
01863     
01864     if (!getostypevalue (hp1, pnum++, &appid))
01865         return (false);
01866     
01867     flnextparamislast = true;
01868     
01869     if (!getvarparam (hp1, pnum++, &htable, bs))
01870         return (false);
01871     
01872     if (!getnetaddress (htable, bs, &ipcaddress))
01873         clearbytes (&ipcaddress, sizeof (ipcaddress));
01874     
01875     if (!landbrowsenetworkapps (bsprompt, &ipcaddress.netaddress, appid))
01876         return (landgeterror () == userCanceledErr);
01877     
01878     /*
01879     langipcexpandnetaddress (&ipcaddress);
01880     */
01881     
01882     if (!newfilledhandle (&ipcaddress.netaddress, sizeof (tynetworkaddress), &x))
01883         return (false);
01884     
01885     if (!setbinarysymbolval (htable, bs, x, 'targ')) /*'netx'*/
01886         return (false);
01887     
01888     (*vreturned).data.flvalue = true;
01889     
01890     return (true);
01891     } /*langipcbrowsenetwork*/
01892 
01893 
01894 static boolean getipcaddressvalue (hdltreenode hparam1, short pnum, tyipcaddress *ipcaddress) {
01895     
01896     /*
01897     2/12/93 dmb: always use landglobals for find our own application id
01898     
01899     4/9/93 dmb: if the address parameter is zero, send to self
01900     
01901     5.0d19 dmb: handle 'psn ' binary address values
01902     */
01903     
01904     register tyipcaddress *padr = ipcaddress;
01905     tyvaluerecord val;
01906     
01907     if (!getparamvalue (hparam1, pnum, &val))
01908         return (false);
01909     
01910     if (val.valuetype == binaryvaluetype) {
01911         
01912         long ix = sizeof (OSType); // skip the binary type
01913         
01914         switch (getbinarytypeid (val.data.binaryvalue)) {
01915             
01916             case 'psn ':
01917                 (*padr).appid = 0;
01918                 
01919                 return (loadfromhandle (val.data.binaryvalue, &ix, sizeof (ProcessSerialNumber), &(*padr).appprocessid));
01920             
01921             case 'targ':
01922                 if (!loadfromhandle (val.data.binaryvalue, &ix, sizeof (tynetworkaddress), &(*padr).netaddress))
01923                     return (false);
01924                 
01925                 langipcexpandnetaddress (padr);
01926                 
01927                 return (true);
01928             }
01929         }
01930     
01931     if (val.valuetype == addressvaluetype) {
01932         /*
01933         hdlhashtable htable;
01934         bigstring bs;
01935         */
01936         
01937         (*padr).appid = (**landgetglobals ()).applicationid;
01938         
01939         (*padr).flcodeval = true;
01940         
01941         /*
01942         (*padr).addressval = val;
01943         
01944         if (!getaddressvalue (val, &htable, bs))
01945             return (false);
01946         
01947         if (!hashtablelookup (htable, bs, &val))
01948             return (false);
01949         */
01950         
01951         (*padr).val = val;
01952         
01953         return (true);
01954         }
01955     
01956     if (val.valuetype == stringvaluetype) {
01957         bigstring bsaddress;
01958         bigstring bs;
01959         OSErr errcode;
01960         
01961         texthandletostring ((Handle) val.data.stringvalue, bsaddress);
01962         
01963         if (stringfindchar (':', bsaddress)) { /*maybe a network address*/
01964             
01965             if (landstring2networkaddress (bsaddress, &(*padr).netaddress)) {
01966                 
01967                 langipcexpandnetaddress (padr);
01968                 
01969                 return (true);
01970                 }
01971             
01972             errcode = landgeterror ();
01973             
01974             if (errcode < 0) {
01975                 
01976                 langgetstringlist (onthisnetstring, bs);
01977                 
01978                 lang2paramerror (iacaddresserror, bsaddress, bs); /*can't make sense out of network address*/
01979                 
01980                 return (false);
01981                 }
01982             }
01983         
01984         (*padr).appid = 0;
01985         
01986         if (findrunningapplication (&(*padr).appid, bsaddress, &(*padr).appprocessid)) { /*got an application name*/
01987             
01988             copystring (bsaddress, (*padr).appname);
01989             
01990             return (true);
01991             }
01992         
01993         if (stringlength (bsaddress) != 4) { /*can't be coerced into a string4*/
01994             
01995             langgetstringlist (onthismacstring, bs);
01996             
01997             lang2paramerror (iacaddresserror, bsaddress, bs); /*can't make sense out of local address*/
01998             
01999             return (false);
02000             }
02001         }
02002     
02003     if (val.valuetype == filespecvaluetype) { /*4.1b7 dmb: send to another open root*/
02004         
02005         FSSpec fs = **val.data.filespecvalue;
02006         
02007         if (shellfindfilewindow (&fs) == nil) {
02008             
02009             langparamerror (dbnotopenederror, fs.name);
02010             
02011             return (false);
02012             }
02013         
02014         (*padr).flrootval = true;
02015         
02016         (*padr).val = val;
02017         
02018         val.data.ostypevalue = 0; /*pick up app signature as event target*/
02019         }
02020     else {
02021     
02022         if (!coercetoostype (&val))
02023             return (false);
02024         }
02025     
02026     if (val.data.ostypevalue == 0)
02027         (*padr).appid = (**landgetglobals ()).applicationid;
02028     else
02029         (*padr).appid = val.data.ostypevalue;
02030     
02031     findrunningapplication (&val.data.ostypevalue, (*padr).appname, nil); /*set if running*/
02032     
02033     return (true);
02034     } /*getipcaddressvalue*/
02035 
02036 
02037 boolean langipcgetaddressvalue (hdltreenode hparam1, tyvaluerecord *vreturned) {
02038 #pragma unused (hparam1)
02039 
02040     return (setbooleanvalue (false, vreturned));
02041     } /*langipcgetaddressvalue*/
02042 
02043 
02044 static boolean getlistpositionvalue (hdltreenode hparam1, short pnum, tyvaluerecord *posval) {
02045     
02046     /*
02047     get a list position parameter -- either an index (number) or a keyword (string4)
02048     
02049     a new ae list is created. the original oplist is untouched.
02050     */
02051     
02052     tyvaluerecord *v = posval;
02053     
02054     if (!getparamvalue (hparam1, pnum, v))
02055         return (false);
02056     
02057     return (coercetolistposition (v));
02058     } /*getlistpositionvalue*/
02059 
02060 
02061 boolean langipcconvertoplist (const tyvaluerecord *vlist, AEDesc *list) {
02062     
02063     /*
02064     5.0a24 dmb: convert an op list or record to an AE list. the op list 
02065     is left intact
02066     */
02067     
02068     boolean flrecord = (*vlist).valuetype == recordvaluetype;
02069     tyvaluerecord vitem;
02070     AEDesc item;
02071     long ix, ctitems;
02072     bigstring bskey;
02073     OSType key;
02074     OSErr err;
02075     
02076     if (!langgetlistsize (vlist, &ctitems))
02077         return (false);
02078     
02079     if (oserror (AECreateList (nil, 0, flrecord, list)))
02080         return (false);
02081     
02082     for (ix = 1; ix <= ctitems; ++ix) { /*process each item in the list*/
02083         
02084         if (!langgetlistitem (vlist, ix, bskey, &vitem))
02085             goto error;
02086         
02087         stringtoostype (bskey, &key);
02088         
02089         if (!valuetodescriptor (&vitem, &item)) // consumes value
02090             goto error;
02091         
02092         if (flrecord)
02093             err = AEPutKeyDesc (list, key, &item);
02094         else
02095             err = AEPutDesc (list, 0, &item);
02096         
02097         AEDisposeDesc (&item);
02098         
02099         if (oserror (err))
02100             goto error;
02101         }
02102     
02103     return (true);
02104         
02105     error: {
02106         
02107         AEDisposeDesc (list);
02108         
02109         return (false);
02110         }
02111     } /*langipcconvertoplist*/
02112 
02113 
02114 boolean langipcconvertaelist (const AEDesc *list, tyvaluerecord *vlist) {
02115     
02116     /*
02117     5.0a24 dmb: convert an AE list or record to a usertalk oplist.
02118     
02119     a new oplist is created on the temp stack. the original aelist is untouched.
02120     
02121     5.0b7 dmb: disposevaluerecord, fix leak
02122     */
02123     
02124     boolean flrecord = (*list).descriptorType == typeAERecord;
02125     hdllistrecord hlist;
02126     AEDesc item;
02127     OSType key;
02128     bigstring bskey;
02129     tyvaluerecord vitem;
02130     long ix, ctitems;
02131     boolean fl;
02132     
02133     if (oserror (AECountItems (list, &ctitems)))
02134         return (false);
02135     
02136     if (!opnewlist (&hlist, flrecord))
02137         return (false);
02138     
02139     for (ix = 1; ix <= ctitems; ++ix) { // process each item in the list*/
02140     
02141         if (oserror (AEGetNthDesc (list, ix, typeWildCard, &key, &item)))
02142             goto error;
02143         
02144         if (!setdescriptorvalue (item, &vitem)) // consumes item
02145             goto error;
02146         
02147         ostypetostring (key, bskey);
02148         
02149         if (flrecord)
02150             fl = langpushlistval (hlist, bskey, &vitem);
02151         else
02152             fl = langpushlistval (hlist, nil, &vitem);
02153         
02154         disposevaluerecord (vitem, true);
02155         
02156         if (!fl)
02157             goto error;
02158         }
02159     
02160     return (setheapvalue ((Handle) hlist, flrecord? recordvaluetype: listvaluetype, vlist));
02161     
02162     error: {
02163     
02164         opdisposelist (hlist);
02165         
02166         return (false);
02167         }
02168     } /*langipcconvertaelist*/
02169 
02170 
02171 void binarytodesc (Handle hbinary, AEDesc *desc) {
02172     
02173     /*
02174     6/24/92 dmb: need special-case for boolean values; must extract extra 
02175     (high order) byte
02176     
02177     8/11/92 dmb: also special-case character values; they must go out as standard 
02178     typeChar descriptors.
02179     
02180     2006-04-17 aradke: Must byte-swap valtype id extracted from binary value on Intel Macs.
02181     */
02182     
02183     register AEDesc *d = desc;
02184 
02185     #if TARGET_API_MAC_CARBON == 1 /*PBS 03/14/02: AE OS X fix.*/   
02186         
02187         Handle hcopy;
02188         DescType dtype;
02189         
02190         copyhandle (hbinary, &hcopy);
02191         
02192         pullfromhandle (hcopy, 0L, sizeof (DescType), &dtype);
02193         
02194         disktomemlong (dtype);
02195         
02196         newdescwithhandle (d, dtype, hcopy);
02197         
02198         disposehandle (hcopy);
02199     
02200     #else
02201     
02202         (*d).dataHandle = hbinary;
02203     
02204         pullfromhandle ((*d).dataHandle, 0L, sizeof (DescType), &(*d).descriptorType);
02205         
02206         disktomemlong ((*d).descriptorType);
02207     
02208     #endif
02209     
02210     
02211     switch ((*d).descriptorType) {
02212         
02213     #ifndef version42orgreater
02214     
02215         case 'bool': {
02216         
02217             #if TARGET_API_MAC_CARBON == 1 /*PBS 03/14/02: AE OS X fix.*/
02218             
02219                 Handle hcopy;
02220                 
02221                 copydatahandle (d, &hcopy);
02222                 
02223                 pullfromhandle (hcopy, 0L, 1L, nil);
02224                 
02225                 putdeschandle (d, (*d).descriptorType, hcopy);
02226                 
02227                 disposehandle (hcopy);
02228             
02229             #else
02230     
02231                 pullfromhandle ((*d).dataHandle, 0L, 1L, nil);
02232             
02233             #endif
02234             
02235             break;
02236             }
02237     
02238     #endif
02239         
02240         case 'char':
02241             (*d).descriptorType = 'TEXT';
02242             
02243             break;
02244         }
02245     } /*binarytodesc*/
02246 
02247 
02248 static boolean stealbinaryhandle (tyvaluerecord *val, Handle *x) {
02249     
02250     if (exemptfromtmpstack (val)) {
02251         
02252         *x = (*val).data.binaryvalue;
02253         
02254         return (true);
02255         }
02256     
02257     return (copyhandle ((*val).data.binaryvalue, x));
02258     } /*stealbinaryhandle*/
02259 
02260             
02261 static boolean getbinarylistdesc (boolean flrecord, tyvaluerecord val, AEDescList *listdesc) {
02262     
02263     /*
02264     5.0a25 dmb: closer to 4.x code, must let binary list values stay as such
02265     */
02266     
02267     Handle x;
02268     
02269     switch (val.valuetype) {
02270         
02271         case binaryvaluetype:
02272             
02273             if (!stealbinaryhandle (&val, &x))
02274                 return (false);
02275             
02276             binarytodesc (x, listdesc);
02277             
02278             return (true);
02279         
02280         case listvaluetype:
02281         case recordvaluetype:
02282             #ifdef version5orgreater
02283                 return (langipcconvertoplist (&val, listdesc));
02284             #else
02285             
02286                 #if TARGET_API_MAC_CARBON == 1 /*PBS 03/14/02: AE OS X fix.*/
02287                 
02288                     {
02289                     Handle hcopy;
02290                     
02291                     copydatahandle (listdesc, &hcopy);
02292                     
02293                     if (!stealbinaryhandle (&val, &hcopy))
02294                         return (false);
02295                         
02296                     disposehandle (hcopy);
02297                     }
02298                 
02299                 #else
02300                 
02301                     if (!stealbinaryhandle (&val, &(*listdesc).dataHandle))
02302                         return (false);
02303                                 
02304                 #endif
02305                     
02306                 (*listdesc).descriptorType = typeAERecord;
02307                 
02308                 return (true);
02309             #endif
02310         
02311         case novaluetype:
02312         case longvaluetype:
02313             
02314             if (val.data.longvalue == 0) { /*uninitialized variable - create empty list*/
02315                 
02316                 return (!oserror (AECreateList (nil, 0, flrecord, listdesc)));
02317                 }
02318             
02319             break;
02320         
02321         default:
02322             /* do nothing */
02323             break;
02324         }
02325     
02326     langerror (badipclistvalerror);
02327     
02328     return (false);
02329     } /*getbinarylistdesc*/
02330 
02331 
02332 boolean langipcputlistitem (hdltreenode hparam1, tyvaluerecord *vreturned) {
02333     
02334     /*
02335     10/14/91 dmb: created.
02336     
02337     verb: putlistitem (value, key/index, @list); returns boolean.  adds an 
02338     item to an AEDescList or an AERecord, creating the list if it doesn't 
02339     already exist.
02340     
02341     value is any database value.
02342     
02343     list is the address of a binary value that should be an AEList.  if no 
02344     object exists at list, a new binary value is created.
02345     
02346     if second parameter is an index, list is assumed to be (or created as) a 
02347     normal descriptor list.  if the second parameter is a key, list 
02348     is assumed to be (or created as) an AE record.
02349     */
02350     
02351     register hdltreenode hp1 = hparam1;
02352     tyvaluerecord posval;
02353     tyvaluerecord itemval;
02354     tyvaluerecord listval;
02355     hdlhashtable htable;
02356     bigstring bsname;
02357     boolean flrecord;
02358     AEDesc itemdesc;
02359     AEDescList listdesc;
02360     OSErr errcode;
02361     hdlhashnode hnode;
02362     
02363     setbooleanvalue (false, vreturned); /*default return*/
02364     
02365     if (!getbinaryparam (hp1, 1, &itemval))
02366         return (false);
02367     
02368     if (!getlistpositionvalue (hp1, 2, &posval))
02369         return (false);
02370     
02371     #ifdef oplanglists
02372         if (posval.valuetype == stringvaluetype)
02373             coercetoostype (&posval);
02374     #endif
02375     
02376     flnextparamislast = true;
02377     
02378     if (!getvarparam (hp1, 3, &htable, bsname)) /*this list address*/
02379         return (false);
02380     
02381     if (isemptystring (bsname)) {
02382         
02383         langerror (binaryrequirederror);
02384         
02385         return (false);
02386         }
02387     
02388     flrecord = posval.valuetype == ostypevaluetype; /*was passed a key*/
02389         
02390     if (hashtablelookup (htable, bsname, &listval, &hnode)) { /*something there; make sure it's a list*/
02391         
02392         if (!getbinarylistdesc (flrecord, listval, &listdesc))
02393             return (false);
02394         }
02395     else {
02396         if (oserror (AECreateList (nil, 0, flrecord, &listdesc)))
02397             return (false);
02398         }
02399     
02400     binarytodesc (itemval.data.binaryvalue, &itemdesc); /*steal the handle -- it's a temp*/
02401     
02402     if (flrecord)
02403         errcode = AEPutKeyDesc (&listdesc, posval.data.ostypevalue, &itemdesc);
02404     else
02405         errcode = AEPutDesc (&listdesc, posval.data.longvalue, &itemdesc);
02406     
02407     if (oserror (errcode)) {
02408         
02409         AEDisposeDesc (&listdesc);
02410         
02411         return (false);
02412         }
02413     
02414     /*don't dispose itemdesc handle -- it's in the temp stack*/
02415     
02416     #if TARGET_API_MAC_CARBON == 1 /*PBS 03/14/02: AE OS X fix.*/
02417     
02418         {
02419         Handle hcopy;
02420         boolean fl = false;
02421         
02422         copydatahandle (&listdesc, &hcopy);
02423         
02424         fl = setbinarysymbolval (htable, bsname, hcopy, listdesc.descriptorType);
02425         
02426         //disposehandle (hcopy);
02427         
02428         if (!fl)
02429             return (false);
02430         }
02431     
02432     #else
02433     
02434         if (!setbinarysymbolval (htable, bsname, listdesc.dataHandle, listdesc.descriptorType))
02435             return (false);
02436     
02437     #endif
02438     
02439     (*vreturned).data.flvalue = true;
02440     
02441     return (true);
02442     } /*langipcputlistitem*/
02443 
02444 
02445 boolean langipcgetlistitem (hdltreenode hparam1, tyvaluerecord *vreturned) {
02446     
02447     /*
02448     11/6/92 dmb: use new langgoodbinarytype
02449     */
02450     
02451     register hdltreenode hp1 = hparam1;
02452     tyvaluerecord posval;
02453     tyvaluerecord itemval;
02454     tyvaluerecord listval;
02455     hdlhashtable htable;
02456     bigstring bsname;
02457     boolean flrecord;
02458     AEDesc itemdesc;
02459     AEDescList listdesc;
02460     OSErr errcode;
02461     DescType key;
02462     
02463     setbooleanvalue (false, vreturned); /*default return*/
02464     
02465     if (!getbinaryparam (hp1, 1, &listval))
02466         return (false);
02467     
02468     if (!getlistpositionvalue (hp1, 2, &posval))
02469         return (false);
02470     
02471     #ifdef oplanglists
02472         if (posval.valuetype == stringvaluetype)
02473             coercetoostype (&posval);
02474     #endif
02475     
02476     flnextparamislast = true;
02477     
02478     if (!getvarparam (hp1, 3, &htable, bsname)) /*this item address*/
02479         return (false);
02480     
02481     if (isemptystring (bsname)) {
02482         
02483         langerror (binaryrequirederror);
02484         
02485         return (false);
02486         }
02487     
02488     flrecord = posval.valuetype == ostypevaluetype; /*was passed a key*/
02489     
02490     if (!getbinarylistdesc (flrecord, listval, &listdesc))
02491         return (false);
02492     
02493     if (flrecord)
02494         errcode = AEGetKeyDesc (&listdesc, posval.data.ostypevalue, typeWildCard, &itemdesc);
02495     else
02496         errcode = AEGetNthDesc (&listdesc, posval.data.longvalue, typeWildCard, &key, &itemdesc);
02497     
02498     AEDisposeDesc (&listdesc);
02499     
02500     if (errcode == errAEDescNotFound) /*not fatal; just return false value*/
02501         return (true);
02502     
02503     if (oserror (errcode))
02504         return (false);
02505     
02506     if (!setdescriptorvalue (itemdesc, &itemval))
02507         return (false);
02508     
02509     /*
02510     if (!setbinaryvalue (itemdesc.dataHandle, itemdesc.descriptorType, &itemval))
02511         return (false);
02512     
02513     valuetype = langgetvaluetype (itemdesc.descriptorType);
02514     
02515     if (langgoodbinarytype (valuetype)) { /%unpackable%/
02516         
02517         if (!coercevalue (&itemval, valuetype))
02518             return (false);
02519         }
02520     */
02521     
02522     if (!langsetsymboltableval (htable, bsname, itemval))
02523         return (false);
02524     
02525     exemptfromtmpstack (&itemval);
02526     
02527     (*vreturned).data.flvalue = true;
02528     
02529     return (true);
02530     } /*langipcgetlistitem*/
02531 
02532 
02533 boolean langipccountlistitems (hdltreenode hparam1, tyvaluerecord *vreturned) {
02534     
02535     /*
02536     4/15/92 dmb: created.
02537     
02538     6/24/92 dmb: resurrected.
02539     
02540     12/21/92 dmb: don't special-case binarytype; we have real list types now.
02541     */
02542     
02543     register hdltreenode hp1 = hparam1;
02544     tyvaluerecord listval;
02545     hdlhashtable htable;
02546     bigstring bsname;
02547     AEDescList listdesc;
02548     OSErr errcode;
02549     hdlhashnode hnode;
02550     
02551     setlongvalue (0, vreturned); /*default return*/
02552     
02553     flnextparamislast = true;
02554     
02555     if (!getvarvalue (hp1, 1, &htable, bsname, &listval, &hnode)) /*the list*/
02556         return (false);
02557     
02558     if (!getbinarylistdesc (false, listval, &listdesc))
02559         return (false);
02560     
02561     errcode = AECountItems (&listdesc, &(*vreturned).data.longvalue);
02562     
02563     AEDisposeDesc (&listdesc);
02564     
02565     return (!oserror (errcode));
02566     } /*langipccountlistitems*/
02567 
02568 
02569 boolean langipcsettimeout (hdltreenode hparam1, tyvaluerecord *vreturned) {
02570     
02571     /*
02572     set the timeout for all outgoing events in this thread
02573     */
02574     
02575     long timeout;
02576     
02577     flnextparamislast = true;
02578     
02579     if (!getlongvalue (hparam1, 1, &timeout))
02580         return (false);
02581     
02582     setbooleanvalue (landsettimeout (timeout), vreturned);
02583     
02584     return (true);
02585     } /*langipcsettimeout*/
02586 
02587 
02588 boolean langipcsettransactionid (hdltreenode hparam1, tyvaluerecord *vreturned) {
02589     
02590     /*
02591     set the transaction id for all outgoing events in this thread
02592     */
02593     
02594     long id;
02595     
02596     flnextparamislast = true;
02597     
02598     if (!getlongvalue (hparam1, 1, &id))
02599         return (false);
02600     
02601     setbooleanvalue (landsettransactionid (id), vreturned);
02602     
02603     return (true);
02604     } /*langipcsettransactionid*/
02605 
02606 
02607 boolean langipcsetinteractionlevel (hdltreenode hparam1, tyvaluerecord *vreturned) {
02608     
02609     /*
02610     set the interaction level for all outgoing events in this thread
02611     */
02612     
02613     short level;
02614     
02615     flnextparamislast = true;
02616     
02617     if (!getintvalue (hparam1, 1, &level))
02618         return (false);
02619     
02620     setbooleanvalue (landsetinteractionlevel (level), vreturned);
02621     
02622     return (true);
02623     } /*langipcsetinteractionlevel*/
02624 
02625 
02626 boolean langipcgeteventattr (hdltreenode hparam1, tyvaluerecord *vreturned) {
02627     
02628     register hdlverbrecord hv;
02629     OSType attr;
02630     AEDesc attrdesc;
02631     OSErr errcode;
02632     
02633     setbooleanvalue (false, vreturned);
02634     
02635     flnextparamislast = true;
02636     
02637     if (!getostypevalue (hparam1, 1, &attr))
02638         return (false);
02639     
02640     if (currentprocess == nil)
02641         goto error;
02642     
02643     hv = (hdlverbrecord) (**currentprocess).processrefcon;
02644     
02645     if (hv == nil)
02646         goto error;
02647     
02648     errcode = landgetverbattr (hv, attr, typeWildCard, &attrdesc);
02649     
02650     if (oserror (errcode))
02651         return (false);
02652     
02653     return (setdescriptorvalue (attrdesc, vreturned));
02654     
02655     error: {
02656         
02657         langparamerror (trapnotrunningerror, bsfunctionname);
02658         
02659         return (false);
02660         }
02661     } /*langipcgeteventattr*/
02662 
02663 
02664 boolean langipccoerceappleitem (hdltreenode hparam1, tyvaluerecord *vreturned) {
02665     
02666     /*
02667     5.0b1 dmb: use valuetodescriptor to handle oplists
02668     */
02669     
02670     tyvaluerecord val;
02671     DescType type;
02672     AEDesc desc, result;
02673     OSErr err;
02674     
02675     setbooleanvalue (false, vreturned);
02676     
02677     if (!getparamvalue (hparam1, 1, &val))
02678         return (false);
02679     
02680     flnextparamislast = true;
02681     
02682     if (!getostypevalue (hparam1, 2, &type))
02683         return (false);
02684     
02685     if (!valuetodescriptor (&val, &desc))
02686         return (false);
02687     
02688     err = AECoerceDesc (&desc, type, &result);
02689     
02690     AEDisposeDesc (&desc);
02691     
02692     if (oserror (err)) /*old desc is in temp stack*/
02693         return (false);
02694     
02695     return (setdescriptorvalue (result, vreturned ));
02696     } /*langipccoerceappleitem*/
02697 
02698 
02699 /*
02700 boolean langipcapprunning (hdltreenode hparam1, tyvaluerecord *vreturned) {
02701     
02702     tyapplicationid appid;
02703     
02704     flnextparamislast = true;
02705     
02706     if (!getostypevalue (hparam1, 1, &appid))
02707         return (false);
02708     
02709     setbooleanvalue (landapprunning (appid), vreturned);
02710     
02711     return (true);
02712     } /%langipcapprunning%/
02713 */
02714 
02715 static boolean langipcgetparamvisit (bigstring bs, hdlhashnode hnode, tyvaluerecord val, ptrvoid refcon) {
02716 #pragma unused (hnode)
02717 
02718     hdlverbrecord hv = (hdlverbrecord) refcon;
02719     OSType key;
02720     
02721     if (!stringtoostype (bs, &key)) {
02722         
02723         langparamerror (ostypecoerceerror, bs);
02724         
02725         return (true); /*stop visit*/
02726         }
02727     
02728     if (!copyvaluerecord (val, &val))
02729         return (false);
02730     
02731     return (!langipcpushparam (&val, key, hv));
02732     } /*langipcgetparamvisit*/
02733 
02734 
02735 static boolean langipcpushrecordparams (const tyvaluerecord *vrecord, hdlverbrecord hverb) {
02736     
02737     /*
02738     2.1a7 dmb: add all of the items in the record to the apple event we're 
02739     building in hverb
02740     */
02741     
02742     register hdlverbrecord hv = hverb;
02743     OSType key;
02744     tyvaluerecord vitem;
02745     long ix, ctitems;
02746     
02747     if (!langgetlistsize (vrecord, &ctitems))
02748         return (false);
02749     
02750     for (ix = 1; ix <= ctitems; ++ix) {
02751         
02752         bigstring bskey;
02753         
02754         if (!langgetlistitem (vrecord, ix, bskey, &vitem))
02755             return (false);
02756         
02757         stringtoostype (bskey, &key);
02758         
02759         if (!langipcpushparam (&vitem, key, hv)) /*clears vitem if handle is stolen*/
02760             return (false);
02761         
02762         disposevaluerecord (vitem, true);
02763         }
02764     
02765     return (true);
02766     } /*langipcpushrecordparams*/
02767 
02768 
02769 static boolean langipcbuildmessage (hdltreenode hparam1, short paramnum, tyipcmessageflags msgflags, tyipcaddress *ipcadr, hdlverbrecord *hverb) {
02770     
02771     /*
02772     12/18/91 dmb seperated tranaction functionality from microsoft DDE functionality
02773     
02774     6/29/92 dmb: now take special cases as tyipcmessageflags. added support for systemmsg
02775     
02776     9/7/92 dmb: accept a table in the parameter list to provide a group a values, like 
02777     tableevent. (in fact, this makes tableevent redundant.)
02778     
02779     2/12/93 dmb: always use landglobals for find our own application id
02780     
02781     2.1a7 dmb: allow a record to replace any key/value pair, just like a table
02782     
02783     4.1b7 dmb: access rootval in address to specify another root as the event subject
02784     
02785     5.1.5 dmb: use tablesortedinversesearch for guest databases
02786     */
02787     
02788     register hdltreenode hp1 = hparam1;
02789     register hdllandglobals hlg = landgetglobals ();
02790     tyverbclass classid;
02791     tyverbtoken verbid;
02792     register hdlverbrecord hv;
02793     register short pnum = paramnum;
02794     tyvaluerecord val;
02795     tyipcaddress ipcaddress;
02796     long savetransid = 0, transactionid;
02797     boolean fl;
02798     
02799     clearbytes (&ipcaddress, sizeof (tyipcaddress)); /*unassigned fields must be zero*/
02800     
02801     if (msgflags & systemmsg) {
02802         
02803         ipcaddress.appid = (**hlg).applicationid;
02804         
02805         findrunningapplication (&val.data.ostypevalue, ipcaddress.appname, nil);
02806         }
02807     else {
02808         
02809         if (!getipcaddressvalue (hp1, pnum++, &ipcaddress))
02810             return (false);
02811         }
02812     
02813     *ipcadr = ipcaddress; /*return to caller*/
02814     
02815     if (msgflags & microsoftmsg)
02816         classid = 'DDE ';
02817     else
02818         if (!getostypevalue (hp1, pnum++, &classid))
02819             return (false);
02820     
02821     if (!getostypevalue (hp1, pnum++, &verbid))
02822         return (false);
02823     
02824     if (!fltoolkitinitialized) {
02825         
02826         langerror (iactoolkitnotintializederror);
02827         
02828         return (false);
02829         }
02830     
02831     if (msgflags & transactionmsg) {
02832         
02833         savetransid = (**hlg).eventsettings.transactionid;
02834         
02835         if (!getlongvalue (hp1, pnum++, &transactionid))
02836             return (false);
02837         
02838         (**hlg).eventsettings.transactionid = transactionid;
02839         }
02840     
02841     if (ipcaddress.flnetwork)
02842         fl = landnewnetworkverb (&ipcaddress.netaddress, classid, verbid, 0, hverb);
02843     else
02844         fl = landnewverb (ipcaddress.appid, &ipcaddress.appprocessid, classid, verbid, 0, hverb);
02845     
02846     if (msgflags & transactionmsg)
02847         (**hlg).eventsettings.transactionid = savetransid; /*restore*/
02848     
02849     if (!fl) {
02850         
02851         langostypeparamerror (appnotloadederror, ipcaddress.appid);
02852         
02853         return (false);
02854         }
02855     
02856     hv = *hverb; /*move into register*/
02857     
02858     if (ipcaddress.flcodeval) { /*4/30/92 dmb*/
02859         
02860         (**hv).flverbisdirect = true;
02861         
02862         (**hv).landrefcon = (long) ipcaddress.val.data.addressvalue;
02863         
02864         exemptfromtmpstack (&ipcaddress.val);
02865         }
02866     
02867     if (ipcaddress.flrootval) { /*4.1b7 dmb*/
02868     
02869         FSSpec fs = **ipcaddress.val.data.filespecvalue;
02870         
02871         landsetverbattr (hv, 'subj', typeFSS, &fs, sizeof (fs));
02872         }
02873     
02874     while (true) { /*pop off pairs of key+param combos*/
02875     
02876         tyvaluerecord valparam;
02877         tyvaluerecord valkey;
02878         hdlhashtable htable;
02879         boolean lfl;
02880         
02881         flparamerrorenabled = false; /*no error dialog on getparamvalue call*/
02882         
02883         lfl = getparamvalue (hp1, pnum++, &valkey);
02884         
02885         flparamerrorenabled = true; /*restore*/
02886         
02887         if (!lfl) { /*didn't get another key*/
02888             
02889             if (fllangerror) /*was a bad parameter; didn't run out*/
02890                 goto error;
02891             
02892             return (true); /*success*/
02893             }
02894         
02895         if (langexternalvaltotable (valkey, &htable, HNoNode)) { /*got a table; grab all values*/
02896             
02897             // hipcverb = hv; /*make visible to visit routine*/
02898             
02899             if (tablesortedinversesearch (htable, &langipcgetparamvisit, hv)) /*true means error occurred*/
02900                 goto error;
02901             }
02902         else {
02903             
02904             if (valkey.valuetype == recordvaluetype) {
02905                 
02906                 if (!langipcpushrecordparams (&valkey, hv))
02907                     goto error;
02908                 }
02909             else {
02910                 
02911                 if (!coercetoostype (&valkey))
02912                     goto error;
02913                 
02914                 flinhibitnilcoercion = true;
02915                 
02916                 lfl = getparamvalue (hp1, pnum++, &valparam);
02917                 
02918                 flinhibitnilcoercion = false;
02919                 
02920                 if (fllangerror) /*wasn't just nil coercion failure*/
02921                     goto error;
02922                 
02923                 if (!lfl) /*must be nil coercion error*/
02924                     continue;
02925                 
02926                 if (!langipcpushparam (&valparam, valkey.data.ostypevalue, hv))
02927                     goto error;
02928                 }
02929             }
02930         } /*while*/
02931     
02932     error: /*goto here on error before sending verb*/
02933     
02934     landdisposeverb (hv);
02935     
02936     return (false);
02937     } /*langipcbuildmessage*/
02938 
02939 
02940 typedef struct appvisitinfo {
02941 
02942     OSType idlookfor;
02943     
02944     hdlhashtable apptablefound;
02945     
02946     boolean fluseappinfoname;
02947     } tyappvisitinfo, *ptrappvisitinfo;
02948 
02949 
02950 static boolean appinfovisit (hdlhashtable happtable, bigstring bsname, tyappvisitinfo *appvisitinfo) {
02951     
02952     bigstring bs;
02953     tyvaluerecord val;
02954     hdlhashtable hinfotable;
02955     hdlhashnode hnode;
02956     
02957     langgetstringlist (appinfotablestring, bs); /*name of appinfo table*/
02958     
02959     if (!hashtablelookup (happtable, bs, &val, &hnode))
02960         return (false);
02961     
02962     if (!langexternalvaltotable (val, &hinfotable, hnode)) /*not an info table*/
02963         return (false);
02964     
02965     langgetstringlist (appidfieldstring, bs); /*name of id entry*/
02966     
02967     if (!hashtablelookup (hinfotable, bs, &val, &hnode))
02968         return (false);
02969     
02970     if (val.valuetype != ostypevaluetype)
02971         return (false);
02972     
02973     if (val.data.ostypevalue != (*appvisitinfo).idlookfor)
02974         return (false);
02975     
02976     if ((*appvisitinfo).fluseappinfoname) { /*use appinfo.name, not the name of the app table*/
02977         
02978         langgetstringlist (appnamefieldstring, bs); /*name of name entry*/
02979         
02980         if (hashtablelookup (hinfotable, bs, &val, &hnode)) {
02981             
02982             if (val.valuetype == stringvaluetype)
02983                 texthandletostring (val.data.stringvalue, bsname);
02984             }
02985         }
02986     
02987     return (true); /*where or not we got the name, we did find the entry*/
02988     } /*appinfovisit*/
02989 
02990 
02991 static boolean apptablevisit (bigstring bsname, hdlhashnode hnode, tyvaluerecord val, ptrvoid refcon) {
02992     
02993     /*
02994     2.1b2 dmb: added this layer of tableinternal-level code to 
02995     prevent a bunch of memory from being consumed by an id search
02996     */
02997     
02998     tyappvisitinfo *appvisitinfo = (tyappvisitinfo*) refcon;
02999     register hdltablevariable hv;
03000     register hdlhashtable ht;
03001     register boolean fltempload;
03002     hdltablevariable hvariable;
03003     short errorcode;
03004     
03005     if (!gettablevariable (val, &hvariable, &errorcode))
03006         return (false);
03007     
03008     hv = hvariable;
03009     
03010     fltempload = !(**hv).flinmemory;
03011     
03012     if (!tableverbinmemory ((hdlexternalvariable) hv, hnode))
03013         return (false);
03014     
03015     ht = (hdlhashtable) (**hv).variabledata; 
03016     
03017     if (appinfovisit (ht, bsname, appvisitinfo)) {
03018         
03019         (*appvisitinfo).apptablefound = ht;
03020         
03021         return (true);
03022         }
03023     
03024     if (fltempload)
03025         tableverbunload ((hdlexternalvariable) hv);
03026     
03027     return (false);
03028     } /*apptablevisit*/
03029 
03030 
03031 boolean langipcfindapptable (OSType appsignature, boolean fluseinfoname, hdlhashtable *happtable, bigstring bsname) {
03032     
03033     /*
03034     2.1b1 dmb: search all appinfo tables for an id matching appsignature
03035     
03036     if fluseinfo is true, use appinfo.name as the result, otherwise return 
03037     the name of the app table itself
03038     
03039     common code shared with osacomponent.
03040     */
03041     
03042     tyappvisitinfo appvisitinfo;
03043     
03044     setemptystring (bsname);
03045     
03046     if (iacgluetable == nil)
03047         return (false);
03048     
03049     appvisitinfo.idlookfor = appsignature;
03050     
03051     appvisitinfo.fluseappinfoname = fluseinfoname;
03052     
03053     hashinversesearch (iacgluetable, &apptablevisit, &appvisitinfo, bsname);
03054     
03055     if (isemptystring (bsname))
03056         return (false);
03057     
03058     *happtable = appvisitinfo.apptablefound;
03059     
03060     return (true);
03061     } /*langipcfindapptable*/
03062 
03063 
03064 static void langipcerrormessage (short iderror, tyipcaddress *ipcaddress, bigstring bsparam, short idoserr) {
03065     
03066     /*
03067     do the best job we can at identifying the application at the ipcaddress;
03068     
03069     8/11/92 dmb: centralized dealing with error codes returned by the target 
03070     app here (idoserr).
03071     */
03072     
03073     register tyipcaddress *adr = ipcaddress;
03074     bigstring bsname, bswhoseid;
03075     bigstring bsoserr;
03076     hdlhashtable happtable;
03077     
03078     /*check for os error code*/
03079     
03080     if ((bsparam == nil) && (idoserr != 0)) {
03081         
03082         langgetmiscstring (unknownstring, bsname);
03083         
03084         /*
03085         setoserrorparam (bsoserr);
03086         */
03087         
03088         getsystemerrorstring (idoserr, bsoserr);
03089         
03090         parsedialogstring (bsoserr, bsname, nil, nil, nil, bsoserr);
03091         
03092         bsparam = bsoserr;
03093         }
03094     
03095     /*if message was to a code extension, just report back the error straight*/
03096     
03097     if ((*adr).flcodeval && (bsparam != nil)) {
03098         
03099         langerrormessage (bsparam);
03100         
03101         return;
03102         }
03103     
03104     setemptystring (bsname);
03105     
03106     setemptystring (bswhoseid);
03107     
03108     /*first, try using the appInfo table*/
03109     
03110     if (!langipcfindapptable ((*adr).appid, true, &happtable, bsname)) /*not found; see if it's part of address*/
03111         copystring ((*adr).appname, bsname);
03112     
03113     if (isemptystring (bsname)) { /*oh well, we'll have to use id*/
03114         
03115         ostypetostring ((*adr).appid, bsname);
03116         
03117         langgetstringlist (appwhoseidstring, bswhoseid);
03118         }
03119     
03120     lang3paramerror (iderror, bsname, bswhoseid, bsparam);
03121     } /*langipcerrormessage*/
03122 
03123 
03124 boolean langipcmessage (hdltreenode hparam1, tyipcmessageflags msgflags, tyvaluerecord *vreturned) {
03125     
03126     /*
03127     1/2/91 dmb: added fltoolkitinitialized flag & corresponding error message
03128     
03129     12/18/91 dmb: added fltransaction param
03130     
03131     6/29/92 dmb: now take special cases as tyipcmessageflags
03132     
03133     3.0b15 dmb: on a userCanceledErr, we need to call oserror so that 
03134     getoserror will yield the appropriate result.
03135     */
03136     
03137     tyipcaddress ipcaddress;
03138     hdlverbrecord hverb;
03139     typaramrecord param;
03140     bigstring bserror;
03141     short iderror;
03142     boolean fl = true;
03143     
03144     if (!langipcbuildmessage (hparam1, 1, msgflags, &ipcaddress, &hverb))
03145         return (false);
03146     
03147     if (msgflags & noreplymsg)
03148         landverbgetsnoreply (hverb);
03149     
03150     if (!landsendverb (hverb, &param, bserror, &iderror)) {
03151         
03152         if (iderror == 0)
03153             iderror = landgeterror ();
03154         
03155         switch (iderror) {
03156             
03157             case 0: /*no error returned -- assume app not running*/
03158             case connectionInvalid:
03159                 
03160                 langipcerrormessage (appnotloadederror, &ipcaddress, nil, 0);
03161                 
03162                 /*
03163                 ostypetostring (ipcaddress.appid, bs);
03164                 
03165                 langparamerror (appnotloadederror, bs);
03166                 */
03167                 
03168                 break;
03169             
03170             case userCanceledErr:
03171             case usercancellederror: /*user cancelled -- don't put up an error message*/
03172                 
03173                 oserror (userCanceledErr); /*3.0b15: set the error code*/
03174                 
03175                 break;
03176             
03177             default:
03178                 if (isemptystring (bserror)) {
03179                     
03180                     short idmsg;
03181                     
03182                     idmsg = ipcappleerror; /*"couldn't complete the message..."*/
03183                     
03184                     switch (iderror) {
03185                         
03186                         case errAEWaitCanceled:
03187                         case errAETimeout:
03188                             break;
03189                         
03190                         default:
03191                             if ((-1700 >= iderror) && (iderror > -1800)) /*other AE Mgr error*/
03192                                 idmsg = ipcerror; /*"xxx" reported the following error...*/
03193                             
03194                             break;
03195                         }
03196                     
03197                     langipcerrormessage (idmsg, &ipcaddress, nil, iderror);
03198                     }
03199                 else
03200                     langipcerrormessage (ipcerror, &ipcaddress, bserror, 0);
03201                 
03202                 /*
03203                 copystring (ipcaddress.appname, bs);
03204                 
03205                 if (isemptystring (bserror))
03206                     numbertostring (iderror, bserror);
03207                 
03208                 lang2paramerror (ipcerror, bs, bserror);
03209                 */
03210                 
03211                 break;
03212             }
03213         
03214         return (false);
03215         }
03216     
03217     if (param.desc.descriptorType == 0) /*nothing returned to us -- assume true*/
03218         setbooleanvalue (true, vreturned);
03219         
03220     else {
03221         
03222         fl = langipccoerceparam (&param.desc, vreturned); /*consumes param*/
03223         }
03224     
03225     return (fl);
03226     } /*langipcmessage*/
03227 
03228 
03229 static boolean langipccomplexsend (hdlverbrecord hverb, tyipcaddress *ipcaddress, hdlhashtable htable) {
03230     
03231     /*
03232     send the message in hverb, and stuff all the values in the reply into htable.
03233     
03234     consumes hverb.
03235     
03236     3.0b15 dmb: on a userCanceledErr, we need to call oserror so that 
03237     getoserror will yield the appropriate result.
03238     */
03239     
03240     hdlverbrecord hreturned;
03241     register hdlverbrecord hv;
03242     register short i;
03243     boolean fl;
03244     
03245     if (!landcomplexsend (hverb, &hreturned)) {
03246         
03247         OSErr iderror;
03248         
03249         iderror = landgeterror ();
03250         
03251         if ((iderror != userCanceledErr) && (iderror != usercancellederror)) {
03252             
03253             if ((iderror == 0) || (iderror == connectionInvalid))
03254                 langipcerrormessage (appnotloadederror, ipcaddress, nil, 0);
03255             else
03256                 langipcerrormessage (ipcappleerror, ipcaddress, nil, iderror);
03257             }
03258         else
03259             oserror (userCanceledErr); /*3.0b15: set the error code*/
03260         
03261         return (false);
03262         }
03263     
03264     hv = hreturned; /*move into register*/
03265     
03266     fl = true; /*think positive*/
03267     
03268     pushhashtable (htable);
03269     
03270     for (i = 1; i <= (**hv).ctparams; i++) {
03271         
03272         typaramrecord param;
03273         tyvaluerecord val;
03274         bigstring bs;
03275         
03276         if (!landgetnthparam (hv, i, &param))
03277             return (false);
03278         
03279         if (!langipccoerceparam (&param.desc, &val))
03280             break;
03281         
03282         ostypetostring (param.key, bs);
03283         
03284         fl = hashassign (bs, val);
03285         
03286         if (!fl)
03287             break;
03288         
03289         exemptfromtmpstack (&val);
03290         } /*for*/
03291     
03292     pophashtable ();
03293     
03294     landdisposeverb (hv); /*dispose returned verb*/
03295     
03296     return (fl);
03297     } /*langipccomplexsend*/
03298 
03299 
03300 static boolean langipcggettableparam (hdltreenode hparam1, short pnum, boolean flcreate, hdlhashtable *htableparam) {
03301     
03302     hdlhashtable htable;
03303     register hdlhashtable ht;
03304     bigstring bs;
03305     boolean fl;
03306     
03307     if (!getvarparam (hparam1, pnum, &htable, bs))
03308         return (false);
03309     
03310     ht = htable; /*copy into register*/
03311     
03312     assert (ht != nil);
03313     
03314     pushhashtable (ht);
03315     
03316     fl = langexternalgettable (bs, htableparam);
03317     
03318     if (!fl) {
03319         
03320         if (flcreate)
03321             fl = tablenewsubtable (ht, bs, htableparam);
03322         
03323         else {
03324             bigstring bserror;
03325             
03326             getstringlist (tableerrorlist, namenottableerror, bserror);
03327             
03328             langerrormessage (bserror);
03329             }
03330         }
03331     
03332     pophashtable ();
03333     
03334     return (fl);
03335     } /*langipcggettableparam*/
03336 
03337 
03338 boolean langipccomplexmessage (hdltreenode hparam1, tyvaluerecord *vreturned) {
03339 #pragma unused(vreturned)
03340 
03341     hdlhashtable htable;
03342     tyipcaddress ipcaddress;
03343     hdlverbrecord hverb;
03344     
03345     if (!langipcggettableparam (hparam1, 1, true, &htable))
03346         return (false);
03347     
03348     if (!langipcbuildmessage (hparam1, 2, normalmsg, &ipcaddress, &hverb))
03349         return (false);
03350     
03351     return (langipccomplexsend (hverb, &ipcaddress, htable));
03352     } /*langipccomplexmessage*/
03353 
03354 
03355 boolean langipctablemessage (hdltreenode hparam1, tyvaluerecord *vreturned) {
03356 #pragma unused(vreturned)
03357 
03358     /*
03359     5.1.5 dmb: use tablesortedinversesearch for guest databases
03360     */
03361     
03362     hdlhashtable hsourcetable;
03363     hdlhashtable hdesttable;
03364     hdlverbrecord hverb;
03365     tyipcaddress ipcaddress;
03366     
03367     if (!langipcggettableparam (hparam1, 1, false, &hsourcetable))
03368         return (false);
03369     
03370     if (!langipcggettableparam (hparam1, 2, true, &hdesttable))
03371         return (false);
03372     
03373     if (!langipcbuildmessage (hparam1, 3, normalmsg, &ipcaddress, &hverb))
03374         return (false);
03375     
03376     // hipcverb = hverb; /*make visible to visit routine*/
03377     
03378     if (tablesortedinversesearch (hsourcetable, &langipcgetparamvisit, hverb)) { /*true means error occurred*/
03379         
03380         landdisposeverb (hverb);
03381         
03382         return (false);
03383         }
03384     
03385     return (langipccomplexsend (hverb, &ipcaddress, hdesttable)); /*consumes hverb*/
03386     } /*langipctablemessage*/
03387 
03388 
03389 static AEDesc *fastreply;
03390 
03391 static langerrormessagecallback fastsavecallback;
03392 
03393 
03394 static boolean langipcfasterror (bigstring bs, ptrvoid refcon) {
03395 #pragma unused (refcon)
03396 
03397     long n;
03398     OSErr err;
03399     
03400     n = getoserror ();
03401     
03402     if (n == noErr)
03403         n = -errAEEventFailed;
03404     
03405     err = AEPutKeyPtr (fastreply, 'errn', typeLongInteger, (Ptr) &n, sizeof (n));
03406     
03407     err = AEPutKeyPtr (fastreply, 'errs', typeChar, (Ptr) bs + 1, stringlength (bs));
03408     
03409     return (true);
03410     } /*langipcfasterror*/
03411 
03412 
03413 static void langipchookfasterrors (AEDesc *reply) {
03414     
03415     fastsavecallback = langcallbacks.errormessagecallback;
03416     
03417     langcallbacks.errormessagecallback = &langipcfasterror;
03418     
03419     shellpusherrorhook ((errorhookcallback) &langipcfasterror);
03420     
03421     fastreply = reply;
03422     } /*langipchookfasterrors*/
03423 
03424 
03425 static boolean langipcunhookfasterrors (void) {
03426     
03427     shellpoperrorhook ();
03428     
03429     langcallbacks.errormessagecallback = fastsavecallback;
03430     
03431     oserror (noErr); /*clear it out to avoid conflicts with current thread*/
03432     
03433     fllangerror = false; /*ditto*/
03434     
03435     return (true);
03436     } /*langipcunhookfasterrors*/
03437 
03438 
03439 static boolean langipcnewevent (ProcessSerialNumber *psn, AEEventClass class, AEEventID id, AppleEvent *event) {
03440     
03441     AEDesc desc;
03442     OSErr err;
03443     
03444     err = AECreateDesc (typeProcessSerialNumber, (Ptr) psn, sizeof (*psn), &desc);
03445     
03446     if (oserror (err))
03447         return (false);
03448     
03449     err = AECreateAppleEvent (class, id, &desc, kAutoGenerateReturnID, kAnyTransactionID, event);
03450     
03451     AEDisposeDesc (&desc);
03452     
03453     return (!oserror (err));
03454     } /*langipcnewevent*/
03455 
03456 
03457 boolean newselfaddressedevent (AEEventID id, AppleEvent *event) {
03458     
03459     ProcessSerialNumber psn = langipcself;
03460     
03461     if (iscurrentapplication (psn)) {
03462         
03463         psn.highLongOfPSN = 0;
03464         
03465         psn.lowLongOfPSN =  kCurrentProcess;
03466         }
03467     
03468     return (langipcnewevent (&psn, 'LAND', id, event));
03469     } /*newselfaddressedevent*/
03470 
03471 
03472 static OSErr langipcsendevent (AppleEvent *event, AppleEvent *reply) {
03473 
03474     register hdllandglobals hlg;
03475     OSErr err;
03476     
03477     hlg = landgetglobals ();
03478     
03479     err = (*(**hlg).eventsendcallback) (event, reply, 
03480         
03481         (AESendMode) kAEWaitReply + kAEAlwaysInteract + kAECanSwitchLayer, 
03482         
03483         (AESendPriority) kAEHighPriority, (long) kNoTimeOut, nil, nil);
03484     
03485     return (err);
03486     } /*langipcsendevent*/
03487 
03488 
03489 static boolean langipcgeterrorstring (const AppleEvent *reply, bigstring bserror) {
03490     
03491     AEDesc desc;
03492     
03493     if (AEGetParamDesc (reply, 'errs', typeChar, &desc) == noErr) {
03494         
03495         #if TARGET_API_MAC_CARBON == 1 /*PBS 03/14/02: AE OS X fix.*/   
03496         
03497             datahandletostring (&desc, bserror);
03498         
03499         #else
03500         
03501             texthandletostring (desc.dataHandle, bserror);
03502         
03503         #endif
03504         
03505         AEDisposeDesc (&desc);
03506         
03507         return (true);
03508         }
03509     
03510     return (false);
03511     } /*langipcgeterrorstring*/
03512 
03513 
03514 boolean langipcbuildsubroutineevent (AppleEvent *event, bigstring bsname, hdltreenode hparam1) {
03515     
03516     /*
03517     2.1b3 dmb: build an OSA subroutine event given the name and parameter list
03518     
03519     2.1b4 dmb: handle named parameters. if a name is defined, try to use its value 
03520     as the key. otherwise, use the name itself.
03521     
03522     2.1b12 dmb: moved into langipc.c from osacomponent.c. the caller is now 
03523     responsible for creating the apple event itself, but we dispose of it on error.
03524     */
03525     
03526     AEDesc params = {typeNull, nil};
03527     AEDesc desc;
03528     tyvaluerecord vparam;
03529     tyvaluerecord vkey;
03530     OSType key;
03531     register hdltreenode hp;
03532     register OSErr err;
03533     register boolean fl = false;
03534     hdlhashnode hnode;
03535     
03536     err = AEPutParamPtr (event, keyASSubroutineName, typeChar, (Ptr) bsname + 1, stringlength (bsname));
03537     
03538     if (err != noErr)
03539         goto exit;
03540     
03541     err = AECreateList (nil, 0, false, &params);
03542     
03543     if (err != noErr)
03544         goto exit;
03545     
03546     for (hp = hparam1; hp != nil; hp = (**hp).link) {
03547         
03548         if ((**hp).nodetype == fieldop) {
03549         
03550             if (!langgetidentifier ((**hp).param1, bsname))
03551                 goto exit;
03552             
03553             if (langgetsymbolval (bsname, &vkey, &hnode) && (vkey.valuetype == ostypevaluetype))
03554                 key = vkey.data.ostypevalue;
03555             else
03556                 stringtoostype (bsname, &key);
03557             
03558             if (!evaluatetree ((**hp).param2, &vparam))
03559                 goto exit;
03560             
03561             if (!valuetodescriptor (&vparam, &desc))
03562                 goto exit;
03563             
03564             err = AEPutKeyDesc (event, key, &desc);
03565             }
03566         else {
03567             
03568             if (!evaluatetree (hp, &vparam))
03569                 goto exit;
03570             
03571             if (!valuetodescriptor (&vparam, &desc))
03572                 goto exit;
03573             
03574             err = AEPutDesc (&params, 0, &desc);
03575             }
03576         
03577         AEDisposeDesc (&desc);
03578         
03579         if (err != noErr)
03580             goto exit;
03581         }
03582     
03583     err = AEPutParamDesc (event, keyDirectObject, &params);
03584     
03585     if (err != noErr)
03586         goto exit;
03587     
03588     fl = true;
03589     
03590     exit:
03591     
03592     AEDisposeDesc (&params);
03593     
03594     if (!fl) {
03595         
03596         oserror (err); /*set error code, if available*/
03597         
03598         AEDisposeDesc (event);
03599         }
03600     
03601     return (fl);
03602     } /*langipcbuildsubroutineevent*/
03603 
03604 
03605 boolean langipchandlercall (hdltreenode htree, bigstring bsverb, hdltreenode hparam1, tyvaluerecord *vreturned) {
03606     
03607     /*
03608     3.0a dmb: htree/hparam1 are a standard function call, but the function 
03609     isn't defined.  if the current process isn't frontier, and the function 
03610     name is a simple identifier (not a dotted id), then send a subroutine 
03611     event to the current process and see if it handles the call.
03612     
03613     return true if the subroutine event is handled successfully. if an 
03614     attempt is made to handle it and we generate an error, it will override 
03615     the error that langhandlercall will subsequently generate.
03616     */
03617     
03618     tytreetype op;
03619     AppleEvent event = {typeNull, nil};
03620     AppleEvent reply = {typeNull, nil};
03621     ProcessSerialNumber psn = {0, kCurrentProcess};
03622     OSErr err;
03623     boolean fl = false;
03624     
03625     if (iscurrentapplication (langipcself)) /*if frontier could handle this, we wouldn't get here*/
03626         return (false);
03627     
03628     op = (**htree).nodetype;
03629     
03630     if ((op != identifierop) && (op != bracketop))
03631         return (false);
03632      
03633     if (!langipcnewevent (&psn, kOSASuite, kASSubroutineEvent, &event))
03634         return (false);
03635     
03636     if (!langipcbuildsubroutineevent (&event, bsverb, hparam1)) /*disposes event on error*/
03637         return (false);
03638     
03639     err = langipcsendevent (&event, &reply);
03640     
03641     AEDisposeDesc (&event);
03642     
03643     if (err != errAEEventNotHandled) {
03644         
03645         if (err != noErr) {
03646             
03647             bigstring bs;
03648             
03649             if (langipcgeterrorstring (&reply, bs))
03650                 langerrormessage (bs);
03651             else
03652                 oserror (err);
03653             }
03654         else {
03655             
03656             AEDesc desc;
03657             
03658             err = AEGetParamDesc (&reply, '----', typeWildCard, &desc);
03659             
03660             switch (err) {
03661                 
03662                 case noErr:
03663                     fl = setdescriptorvalue (desc, vreturned);
03664                     
03665                     break;
03666                 
03667                 case errAEDescNotFound:
03668                     fl = setbooleanvalue (true, vreturned);
03669                     
03670                     break;
03671                 
03672                 default:
03673                     oserror (err);
03674                     
03675                     break;
03676                 }
03677             }
03678         }
03679     
03680     AEDisposeDesc (&reply);
03681     
03682     return (fl);
03683     } /*langipchandlercall*/
03684 
03685 
03686 #if 1
03687 
03688 /*
03689 static boolean handlekernelfunction (hdlverbrecord hverb) {
03690     
03691     /%
03692     2.1b14: this is what langipchandletrapverb boils down to in 
03693     its handling of the kernel event. but to avoid all this code 
03694     duplication, we'll just add yet another special case to the trap 
03695     hander.
03696     %/
03697     
03698     register hdlverbrecord hv = hverb;
03699     register boolean fl = false;
03700     bigstring bsverb;
03701     tyvaluerecord val;
03702     callback savecallback;
03703     hdltreenode hfunctioncall;
03704     hdltreenode hparamlist;
03705     hdltreenode hcode;
03706     hdlhashtable hkernel;
03707     hdlhashtable hcontext;
03708     
03709     if (!landgetstringparam (hv, keyASSubroutineName, bsverb)) 
03710         return (false);
03711     
03712     if (!landgetlongparam (hv, keykerneltable, (long *) &hkernel))
03713         return (false);
03714     
03715     if (!landgetlongparam (hv, keycurrenttable, (long *) &hcontext))
03716         return (false);
03717     
03718     /%build a code tree and call the handler, with our error hook in place%/
03719     
03720     langipchookerrors (hv, &savecallback);
03721     
03722     if (!setaddressvalue (hkernel, bsverb, &val))
03723         goto exit;
03724     
03725     if (!pushfunctionreference (val, &hfunctioncall))
03726         goto exit;
03727     
03728     pushhashtable (hcontext); /%need context to evaluate local address params%/
03729     
03730     fl = langipcbuildparamlist (hv, &hparamlist);
03731     
03732     pophashtable ();
03733     
03734     if (!fl) {
03735         
03736         langdisposetree (hfunctioncall);
03737         
03738         goto exit;
03739         }
03740     
03741     if (!pushfunctioncall (hfunctioncall, hparamlist, &hcode)) /%consumes input parameters%/
03742         goto exit;
03743     
03744     if (!pushbinaryoperation (moduleop, hcode, nil, &hcode)) /%needs this level%/
03745         goto exit;
03746     
03747     fl = langipcruncode (hv, hcode, hcontext, false);
03748     
03749     exit:
03750     
03751     langipcunhookerrors (savecallback);
03752     
03753     return (fl);
03754     } /%handlekernelfunction%/
03755 */
03756 
03757 boolean langipckernelfunction (hdlhashtable htable, bigstring bsverb, hdltreenode hparam1, tyvaluerecord *vreturned) {
03758     
03759     /*
03760     5/18/93 dmb: paired with handlerkernelfunction above, this routine decouples 
03761     kernel functions so that they can be called from client processes via an AE.
03762     
03763     2.1b11 dmb: to reliably continue execution in the event handler, we need to 
03764     pass the thread globals, not just the langcallbacks
03765     
03766     2.1b12 dmb: ok, so it wasn't thinking this through. passing the entire context 
03767     and trying to run the same code tree on the other side of an AE/process swap 
03768     is doomed to failure. what if one of the parameter trees sends an AE back to 
03769     the caller? deadlock. no, the only reliable way to do this is the slow way: 
03770     evaluate all the parameters now, and send the resulting values in the kernel 
03771     event. forunately, the subroutine event is much like this, so there's code to 
03772     share.
03773     
03774     3.0a dmb: fixed memory leak in failure case, getting text
03775     
03776     5.0a23 dmb: handle no value in the reply, meaning nil was returned
03777     */
03778     
03779     AppleEvent event = {typeNull, nil};
03780     AppleEvent reply = {typeNull, nil};
03781     OSErr err;
03782     boolean fl = false;
03783     
03784     if (!newselfaddressedevent (kASSubroutineEvent, &event)) /*note: class is 'LAND'*/
03785         return (false);
03786     
03787     if (!langipcbuildsubroutineevent (&event, bsverb, hparam1)) /*disposes event on error*/
03788         return (false);
03789     
03790     err = AEPutParamPtr (&event, keykerneltable, typeLongInteger, (Ptr) &htable, sizeof (long));
03791     
03792     if (err == noErr)
03793         err = AEPutParamPtr (&event, keycurrenttable, typeLongInteger, (Ptr) &currenthashtable, sizeof (long));
03794     
03795     if (err == noErr)
03796         err = langipcsendevent (&event, &reply);
03797     
03798     AEDisposeDesc (&event);
03799     
03800     if (!oserror (err)) {
03801         
03802         bigstring bs;
03803         AEDesc desc;
03804         
03805         if (langipcgeterrorstring (&reply, bs))
03806             langerrormessage (bs);
03807         
03808         else {
03809             
03810             err = AEGetParamDesc (&reply, '----', typeWildCard, &desc);
03811             
03812             if (err == errAEDescNotFound)
03813                 fl = setnilvalue (vreturned);
03814             else
03815                 if (!oserror (err))
03816                     fl = setdescriptorvalue (desc, vreturned);
03817             }
03818         }
03819     
03820     AEDisposeDesc (&reply);
03821     
03822     return (fl);
03823     } /*langipckernelfunction*/
03824 
03825 #else
03826 
03827 static pascal OSErr handlekernelfunction (AppleEvent *event, AppleEvent *reply, long refcon) {
03828     
03829     /*
03830     2.1b11 dmb: we're now pass the thread globals of the caller, so we can 
03831     cleanly do our stuff.  also, since this isn't a fast event handler, we 
03832     don't need to push/pop a fast context (and probably shouldn't)
03833     */
03834     
03835     AEDesc desc;
03836     OSType type;
03837     long size;
03838     hdlhashtable htable;
03839     bigstring bsverb;
03840     hdlhashtable hcontext;
03841     hdltreenode hparam1;
03842     tyvaluerecord vreturned;
03843     hdlthreadglobals hthreadglobals, hsaveglobals;
03844     /*
03845     tyfastverbcontext savecontext;
03846     tylangcallbacks savecallbacks;
03847     boolean flscriptwasrunning;
03848     */
03849     OSErr err;
03850     
03851     /*
03852     landpushfastcontext (&savecontext);
03853     */
03854     
03855     err = AEGetParamPtr (event, 'ktbl', typeLongInteger, &type, (Ptr) &htable, sizeof (long), &size);
03856     
03857     if (err != noErr)
03858         goto exit;
03859     
03860     err = AEGetParamPtr (event, 'kvrb', typeChar, &type, (Ptr) bsverb + 1, lenbigstring, &size);
03861     
03862     if (err != noErr)
03863         goto exit;
03864     
03865     setstringlength (bsverb, size);
03866     
03867     err = AEGetParamPtr (event, 'ctbl', typeLongInteger, &type, (Ptr) &hcontext, sizeof (long), &size);
03868     
03869     if (err != noErr)
03870         goto exit;
03871     
03872     err = AEGetParamPtr (event, 'parm', typeLongInteger, &type, (Ptr) &hparam1, sizeof (long), &size);
03873     
03874     if (err != noErr)
03875         goto exit;
03876     
03877     err = AEGetParamPtr (event, 'thrd', typeLongInteger, &type, (Ptr) &hthreadglobals, sizeof (hthreadglobals), &size);
03878     
03879     if (err != noErr)
03880         goto exit;
03881     
03882     hsaveglobals = getcurrentthreadglobals ();
03883     
03884     copythreadglobals (hsaveglobals);
03885     
03886     swapinthreadglobals (hthreadglobals);
03887     
03888     langipchookfasterrors (reply);
03889     
03890     if (kernelfunctionvalue (htable, bsverb, hparam1, &vreturned)) {
03891         
03892         if (valuetodescriptor (&vreturned, &desc)) { /*consumes val*/
03893             
03894             AEPutParamDesc (reply, '----', &desc);
03895             
03896             AEDisposeDesc (&desc);
03897             }
03898         }
03899     
03900     langipcunhookfasterrors ();
03901     
03902     copythreadglobals (hthreadglobals);
03903     
03904     swapinthreadglobals (hsaveglobals);
03905     
03906     exit:
03907     
03908     /*
03909     landpopfastcontext (&savecontext);
03910     */
03911     
03912     return (err);
03913     } /*handlekernelfunction*/
03914 
03915 boolean langipckernelfunction (hdlhashtable htable, bigstring bsverb, hdltreenode hparam1, tyvaluerecord *vreturned) {
03916     
03917     /*
03918     5/18/93 dmb: paired with handlerkernelfunction above, this routine decouples 
03919     kernel functions so that they can be called from client processes via an AE.
03920     
03921     2.1b11 dmb: to reliably continue execution in the event handler, we need to 
03922     pass the thread globals, not just the langcallbacks
03923     */
03924     
03925     AEDesc desc;
03926     AppleEvent event = {typeNull, nil};
03927     AppleEvent reply = {typeNull, nil};
03928     OSErr err;
03929     boolean fl = false;
03930     hdlthreadglobals hthreadglobals;
03931     
03932     if (!newselfaddressedevent ('krnl', &event))
03933         return (false);
03934     
03935     err = AEPutParamPtr (&event, 'ktbl', typeLongInteger, (Ptr) &htable, sizeof (long));
03936     
03937     if (err == noErr)
03938         err = AEPutParamPtr (&event, 'kvrb', typeChar, (Ptr) bsverb + 1, stringlength (bsverb));
03939     
03940     if (err == noErr)
03941         err = AEPutParamPtr (&event, 'ctbl', typeLongInteger, (Ptr) &currenthashtable, sizeof (long));
03942     
03943     if (err == noErr)
03944         err = AEPutParamPtr (&event, 'parm', typeLongInteger, (Ptr) &hparam1, sizeof (long));
03945     
03946     /*
03947     if (err == noErr)
03948         err = AEPutParamPtr (&event, 'cbck', typeChar, (Ptr) &langcallbacks, sizeof (langcallbacks));
03949     */
03950     
03951     if (err == noErr) {
03952         
03953         hthreadglobals = getcurrentthreadglobals ();
03954         
03955         err = AEPutParamPtr (&event, 'thrd', typeLongInteger, (Ptr) &hthreadglobals, sizeof (hthreadglobals));
03956         }
03957     
03958     if (err == noErr)
03959         err = langipcsendevent (&event, &reply);
03960     
03961     AEDisposeDesc (&event);
03962     
03963     if (!oserror (err)) {
03964         
03965         if (AEGetParamDesc (&reply, 'errs', typeChar, &desc) == noErr) {
03966             
03967             bigstring bs;
03968             
03969             #if TARGET_API_MAC_CARBON == 1 /*PBS 03/14/02: AE OS X fix.*/
03970             
03971                 datahandletostring (&desc, bs);
03972             
03973             #else
03974 
03975                 texthandletostring (desc.dataHandle, bs);
03976             
03977             #endif
03978             
03979             langerrormessage (bs);
03980             }
03981         else {
03982             
03983             err = AEGetParamDesc (&reply, '----', typeWildCard, &desc);
03984             
03985             if (!oserror (err))
03986                 fl = setdescriptorvalue (desc, vreturned);
03987             }
03988         }
03989     
03990     AEDisposeDesc (&reply);
03991     
03992     return (fl);
03993     } /*langipckernelfunction*/
03994 
03995 #endif
03996 
03997 #if !flruntime
03998 
03999 static pascal OSErr handleshowmenunode (const AppleEvent *event, AppleEvent *reply, long refcon) {
04000 #pragma unused (reply, refcon)
04001 
04002     /*
04003     4.1b14 dmb: added outline parameter; can't count on outline data not changing
04004     */
04005     
04006     OSType type;
04007     long size;
04008     hdloutlinerecord houtline;
04009     hdlheadrecord hnode;
04010     OSErr err;
04011     
04012     err = AEGetParamPtr (event, 'outl', typeLongInteger, &type, (Ptr) &houtline, sizeof (long), &size);
04013     
04014     if (err == noErr)
04015         err = AEGetParamPtr (event, 'node', typeLongInteger, &type, (Ptr) &hnode, sizeof (long), &size);
04016     
04017     if (err == noErr) {
04018         
04019         SetFrontProcess (&langipcself);
04020         
04021         oppushoutline (houtline);
04022         
04023         meshownode (hnode);
04024         
04025         oppopoutline ();
04026         }
04027     
04028     return (err);
04029     } /*handleshowmenunode*/
04030 
04031 #endif
04032 
04033 boolean langipcshowmenunode (long hnode) {
04034     
04035     /*
04036     4.1b14 dmb: added outline parameter; can't count on outline data not changing
04037     */
04038     
04039     AppleEvent event, reply;
04040     OSErr err;
04041     
04042     if (!newselfaddressedevent ('show', &event))
04043         return (false);
04044     
04045     err = AEPutParamPtr (&event, 'outl', typeLongInteger, (Ptr) &outlinedata, sizeof (long));
04046     
04047     err = AEPutParamPtr (&event, 'node', typeLongInteger, (Ptr) &hnode, sizeof (long));
04048     
04049     if (err == noErr) {
04050         
04051         err = langipcsendevent (&event, &reply);
04052         
04053         AEDisposeDesc (&reply);
04054         }
04055     
04056     AEDisposeDesc (&event);
04057     
04058     return (!oserror (err));
04059     } /*langipcshowmenunode*/
04060 
04061 
04062 boolean langipcnoop (void) {
04063     
04064     AppleEvent event, reply;
04065     
04066     if (!newselfaddressedevent ('noop', &event))
04067         return (false);
04068     
04069     langipcsendevent (&event, &reply);
04070     
04071     AEDisposeDesc (&event);
04072     
04073     AEDisposeDesc (&reply);
04074     
04075     return (true);
04076     } /*langipcshowmenunode*/
04077 
04078 
04079 static pascal OSErr handleyield (const AppleEvent *event, AppleEvent *reply, long refcon) {
04080 #pragma unused (event, reply, refcon)
04081 
04082     processyield ();
04083     
04084     return (noErr);
04085     } /*handleyield*/
04086 
04087 
04088 static pascal boolean langipcbreakembrace (EventRecord *ev) {
04089     
04090     /*
04091     7/3/91 dmb: it turns out that try to do background processing during the 
04092     breakembraceroutine doesn't work out very well.  for one thing, we aren't 
04093     getting the event information from the Apple Event Manager, and shouldn't be
04094     handling any events other than those that it would be giving us.  secondly, 
04095     it slows things down quite a bit.
04096     
04097     to allow user input while we're waiting for a message reply, we'll have to 
04098     add more bandwidth to the Toolkit interface.
04099     */
04100     
04101     if ((*ev).what != nullEvent) {
04102         
04103         shellblockevents (); /*just in case*/
04104         
04105         shellprocessevent (ev);
04106         
04107         shellpopevents ();
04108         }
04109     
04110     /*
04111     shellpushblock (highLevelEventMask, true); /%just in case%/
04112     
04113     fl = langbackgroundtask ();
04114     
04115     shellpopblock ();
04116     
04117     if (!fl)
04118         return (true);
04119     */
04120     
04121     return (landefaultbreakembrace (ev));
04122     } /*langipcbreakembrace*/
04123 
04124 
04125 static pascal OSErr langipcopenapproutine (void) {
04126     
04127     if (!shellopendefaultfile ())
04128         return (getoserror ());
04129     
04130     return (noErr);
04131     } /*langipcopenapproutine*/
04132 
04133 
04134 static pascal OSErr langipcopendocroutine (FSSpec *fs) {
04135     
04136     if (!shellopenfile (fs, false, nil))
04137         return (getoserror ());
04138     
04139     return (noErr);
04140     } /*langipcopendocroutine*/
04141 
04142 
04143 static pascal OSErr langipcquitapproutine (void) {
04144     
04145     /*
04146     8/12/91 dmb: use new shellexitmaineventloop to defer quit until after
04147     we've had a chance to reply to caller
04148     */
04149     
04150     if (!shellcloseall (nil, true)) /*user hit Cancel button in save dialog*/
04151         return (userCanceledErr);
04152     
04153     shellexitmaineventloop (); /*sets flag for next iteration*/
04154     
04155     return (noErr);
04156     } /*langipcquitapproutine*/
04157 
04158 
04159 static boolean getpackedobject (Handle htext, Handle *hpacked) {
04160     
04161     /*
04162     htext is a text handle with the name of an object that you want packed from
04163     the object database. if we return true, hpacked contains the packed version
04164     of the database object.
04165     
04166     on exit, htext is in the temp stack, and will be disposed automatically
04167     */
04168     
04169     tyvaluerecord val;
04170     bigstring bs;
04171     hdlhashtable htable;
04172     hdlhashnode hnode;
04173     
04174     if (!setheapvalue (htext, stringvaluetype, &val))
04175         return (false);
04176     
04177     if (!stringtoaddress (&val))
04178         return (false);
04179         
04180     if (!getaddressvalue (val, &htable, bs))
04181         return (false);
04182     
04183     if (!langsymbolreference (htable, bs, &val, &hnode))
04184         return (false);
04185     
04186     return (langpackvalue (val, hpacked, hnode));
04187     } /*getpackedobject*/
04188     
04189 
04190 static boolean setpackedobject (Handle htext, Handle hpacked) {
04191     
04192     /*
04193     we unpack the packed handle into the object database location indicated by
04194     htext.
04195     
04196     on exit, htext is in the temp stack, and hpacked is consumed
04197     */
04198     
04199     tyvaluerecord val;
04200     bigstring bs;
04201     hdlhashtable htable;
04202     boolean fl = false;
04203     
04204     if (!setheapvalue (htext, stringvaluetype, &val))
04205         goto exit;
04206     
04207     if (!stringtoaddress (&val))
04208         goto exit;
04209         
04210     if (!getaddressvalue (val, &htable, bs))
04211         goto exit;
04212     
04213     if (!langunpackvalue (hpacked, &val))
04214         goto exit;
04215     
04216     fl = langsetsymboltableval (htable, bs, val);
04217     
04218     exit:
04219     
04220     disposehandle (hpacked);
04221     
04222     return (fl);
04223     } /*setpackedobject*/
04224 
04225 
04226 static pascal OSErr langipcfastgetobject (AppleEvent *event, AppleEvent *reply, long refcon) {
04227 #pragma unused (refcon)
04228 
04229     /*
04230     7/3/92 DW: this one will be hot!
04231     */
04232     
04233     OSErr err;
04234     AEDesc desc;
04235     tyfastverbcontext savecontext;
04236     long curA5;
04237     
04238     #if flcomponent
04239         
04240         curA5 = SetUpAppA5 ();
04241     
04242     #endif
04243     
04244     landpushfastcontext (&savecontext);
04245     
04246     langipchookfasterrors (reply);
04247     
04248     err = noErr;
04249     
04250     if (oserror (AEGetKeyDesc (event, '----', typeChar, &desc)))
04251         goto exit;
04252     
04253     
04254     #if TARGET_API_MAC_CARBON == 1 /*PBS 03/14/02: AE OS X fix.*/
04255     
04256         {
04257         Handle hcopy;
04258         boolean fl = false;
04259         
04260         copydatahandle (&desc, &hcopy);
04261         
04262         fl = getpackedobject (hcopy, &hcopy);
04263         
04264         if (fl)
04265             
04266             newdescwithhandle (&desc, desc.descriptorType, hcopy);
04267             
04268         disposehandle (hcopy);
04269         
04270         if (!fl)
04271             goto exit;
04272         }
04273     
04274     #else
04275     
04276         if (!getpackedobject (desc.dataHandle, &desc.dataHandle)) /*consumes input handle*/
04277             goto exit;
04278         
04279     #endif
04280     
04281     desc.descriptorType = 'data';
04282     
04283     err = AEPutKeyDesc (reply, '----', &desc);
04284     
04285     AEDisposeDesc (&desc);
04286     
04287     exit:
04288     
04289     langipcunhookfasterrors ();
04290     
04291     landpopfastcontext (&savecontext);
04292     
04293     #if flcomponent
04294         
04295         RestoreA5 (curA5);
04296     
04297     #endif
04298     
04299     return (err);
04300     } /*langipcfastgetobject*/
04301 
04302 
04303 static pascal OSErr
04304 langipcfastsetobject (
04305         AppleEvent  *event,
04306         AppleEvent  *reply,
04307         long         refcon)
04308 {
04309 #pragma unused(refcon)
04310     
04311     /*
04312     7/3/92 DW: this one will be hot!
04313     */
04314     
04315     OSErr err;
04316     AEDesc desc1, desc2;
04317     tyfastverbcontext savecontext;
04318     Boolean fl;
04319     
04320     #if flcomponent && TARGET_API_MAC_OS8
04321         
04322         long curA5 = SetUpAppA5 ();
04323     
04324     #endif
04325     
04326     landpushfastcontext (&savecontext);
04327     
04328     langipchookfasterrors (reply);
04329     
04330     err = noErr;
04331     
04332     if (oserror (AEGetKeyDesc (event, '----', typeChar, &desc1)))
04333         goto exit;
04334     
04335     if (oserror (AEGetKeyDesc (event, 'pack', 'data', &desc2))) {
04336         
04337         AEDisposeDesc (&desc1);
04338         
04339         goto exit;
04340         }
04341     
04342     #if TARGET_API_MAC_CARBON == 1 /*PBS 03/14/02: AE OS X fix.*/
04343     
04344         {
04345         Handle hcopy1, hcopy2;
04346         
04347         copydatahandle (&desc1, &hcopy1);
04348         
04349         copydatahandle (&desc2, &hcopy2);
04350         
04351         if (!setpackedobject (hcopy1, hcopy2))
04352             goto exit;
04353         }
04354     
04355     #else
04356     
04357         if (!setpackedobject (desc1.dataHandle, desc2.dataHandle)) /*consumes handles*/
04358             goto exit;
04359     
04360     #endif
04361     
04362     fl = true;
04363     
04364     err = AEPutParamPtr (
04365         
04366         reply, keyDirectObject, typeBoolean, (Ptr) &fl, 
04367         
04368         (Size) sizeof (Boolean));
04369     
04370     exit:
04371     
04372     langipcunhookfasterrors ();
04373     
04374     landpopfastcontext (&savecontext);
04375     
04376     #if flcomponent && TARGET_API_MAC_OS8
04377         
04378         RestoreA5 (curA5);
04379     
04380     #endif
04381     
04382     return (err);
04383     } /*langipcfastsetobject*/
04384 
04385 
04386 static pascal OSErr
04387 langipchandlefastscript (
04388         AppleEvent  *event,
04389         AppleEvent  *reply,
04390         long         refcon)
04391 {
04392 #pragma unused(refcon)
04393 
04394     /*
04395     3.0.2b1 dmb: reverted to original, 2.0.1 implementation that doesn't rely
04396     on the component manager being present.
04397     */
04398     
04399     /*
04400     ComponentInstance comp;
04401     */
04402     AEDesc script;
04403     tyfastverbcontext savecontext;
04404     boolean flscriptwasrunning;
04405     bigstring bs;
04406     boolean fl;
04407     OSErr err;
04408     
04409     #if flcomponent && TARGET_API_MAC_OS8
04410         
04411         long curA5 = SetUpThisA5 (refcon);
04412     
04413     #endif
04414     
04415     #if 1
04416     
04417         landpushfastcontext (&savecontext);
04418         
04419         langipchookfasterrors (reply);
04420         
04421         ++fldisableyield;
04422         
04423         err = AEGetKeyDesc (event, '----', typeChar, &script);
04424         
04425         if (oserror (err))
04426             goto exit;
04427         
04428         pushhashtable (roottable); /*make sure we don't tromple current script's tmpstack*/
04429         
04430         flscriptwasrunning = flscriptrunning;
04431         
04432         flscriptrunning = false;
04433         
04434         setemptystring (bs);
04435         
04436         #if TARGET_API_MAC_CARBON == 1 /*PBS 03/14/02: AE OS X fix.*/
04437         
04438             {
04439             Handle h;
04440             
04441             copydatahandle (&script, &h);
04442             
04443             fl = langrunhandle (h, bs);
04444             }
04445         
04446         #else
04447         
04448             fl = langrunhandle (script.dataHandle, bs); /*consumes dataHandle*/
04449         
04450         #endif
04451         
04452         flscriptrunning = flscriptwasrunning;
04453         
04454         cleartmpstack (); /*make sure we're livin' clean*/
04455         
04456         pophashtable ();
04457         
04458         if (fl)
04459             AEPutKeyPtr (reply, '----', typeChar, (Ptr) bs + 1, stringlength (bs));
04460         
04461         exit:
04462         
04463         --fldisableyield;
04464         
04465         langipcunhookfasterrors ();
04466         
04467         landpopfastcontext (&savecontext);
04468         
04469     #else /*this code assumes that the component manger is present*/
04470         
04471         comp = OpenComponent (osacomponent);
04472         
04473         if (comp == nil)
04474             err = memFullErr;
04475         
04476         else {
04477             
04478             err = AEGetKeyDesc (event, '----', typeChar, &script);
04479             
04480             if (err == noErr) {
04481                 
04482                 err = OSADoScript (comp, &script, kOSANullScript, typeChar, kOSANullMode, &result);
04483                 
04484                 AEDisposeDesc (&script);
04485                 
04486                 if (err == noErr) {
04487                     
04488                     err = AEPutKeyDesc (reply, '----', &result);
04489                     
04490                     AEDisposeDesc (&result);
04491                     }
04492                 }
04493             
04494             CloseComponent (comp);
04495             }
04496     
04497     #endif
04498     
04499     #if flcomponent && TARGET_API_MAC_OS8
04500         
04501         RestoreA5 (curA5);
04502     
04503     #endif
04504     
04505     return (err);
04506     } /*langipchandlefastscript*/
04507 
04508 
04509 static boolean langipcinstallfastscript (void) {
04510     
04511     /*
04512     5/7/92 dmb: install the fastscript handler into the system dispatch table.
04513     
04514     as per IM VI-64, the handler must reside in the system heap.  we assume that 
04515     the handler, right above us in the source, directly preceeds us in the code.
04516     */
04517     //This is never used in the app
04518     //Code change by Timothy Paustian Wednesday, June 14, 2000 8:59:58 PM
04519     //Changed to Opaque call for Carbon
04520     //langipczone = GetZone ();
04521     
04522     langipcresfile = CurResFile ();
04523     
04524     //langipcresmap = LMGetTopMapHndl ();
04525     
04526     if (!landsystem7installfasthandler ('fast', 'dosc', langipchandlefastscript))
04527         return (false);
04528     
04529     /*
04530     landsystem7installfasthandler ('app0', 'clck', langipchandleapp0verb);
04531     */
04532     
04533     if (!landsystem7installfasthandler ('fast', 'gobj', langipcfastgetobject))
04534         return (false);
04535     
04536     if (!landsystem7installfasthandler ('fast', 'sobj', langipcfastsetobject))
04537         return (false);
04538     
04539     return (true);
04540     } /*langipcinstallfastscript*/
04541 
04542 
04543 static void langipcremovefastscript (void) {
04544     
04545     /*
04546     11/17/92 dmb: remove fast sojb & gobj
04547     */
04548     
04549     landsystem7removefasthandler ('fast', 'dosc');
04550     
04551     landsystem7removefasthandler ('fast', 'gobj');
04552     
04553     landsystem7removefasthandler ('fast', 'sobj');
04554     
04555     landsystem7removefasthandler ('app0', 'clck');
04556     } /*langipcremovefastscript*/
04557 
04558 
04559 boolean langipcstart (void) {
04560     
04561     /*
04562     register with the IAC toolkit, using the identifier defined in land.h, 
04563     and registering the verbs that scriptrunners must implement.
04564     */
04565     
04566     register hdllandglobals hg;
04567     
04568     fltoolkitinitialized = landinit ();
04569     
04570     if (!fltoolkitinitialized) /*report failure, but program may still run*/
04571         return (false);
04572     
04573     hg = landgetglobals (); /*move into register*/
04574     
04575     GetCurrentProcess (&langipcself);
04576     
04577     (**hg).iderrorlist = langerrorlist; /*3.0.1; was 136*/
04578     
04579     (**hg).handleverbroutine = &langipchandleverb;
04580     
04581     (**hg).findhandlerroutine = &langipcfindhandler;
04582     
04583     (**hg).breakembraceroutine = &langipcbreakembrace;
04584     
04585     (**hg).macopenapproutine = &langipcopenapproutine;
04586     
04587     (**hg).macopendocroutine = &langipcopendocroutine;
04588     
04589     (**hg).macquitapproutine = &langipcquitapproutine;
04590     
04591     #ifdef flcomponent
04592     
04593     (**hg).eventcreatecallback = &landsystem7defaultcreate;
04594     
04595     (**hg).eventsendcallback = &landsystem7defaultsend;
04596     
04597     #endif
04598     
04599 
04600     /*
04601     AEInstallEventHandler ('LAND', 'krnl', NewAEEventHandlerProc (handlekernelfunction), 0, false);
04602     */
04603     
04604     #if !flruntime
04605     
04606         #if TARGET_API_MAC_CARBON == 1
04607     
04608             AEInstallEventHandler ('LAND', 'show', NewAEEventHandlerUPP (handleshowmenunode), 0, false);
04609         
04610         #else
04611 
04612             AEInstallEventHandler ('LAND', 'show', NewAEEventHandlerProc (handleshowmenunode), 0, false);
04613         
04614         #endif
04615     
04616     #endif
04617     
04618     #if TARGET_API_MAC_CARBON == 1
04619 
04620         AEInstallEventHandler ('LAND', 'yiel', NewAEEventHandlerUPP (handleyield), 0, false);
04621     
04622     #else
04623 
04624         AEInstallEventHandler ('LAND', 'yiel', NewAEEventHandlerProc (handleyield), 0, false);
04625     
04626     #endif
04627         
04628     langipcinstallfastscript ();
04629     
04630     landaddverb (runscripttoken);
04631     
04632     /*
04633     landaddverb (schedulescripttoken);
04634     */
04635     
04636     landaddfastverb (getmenuarraytoken);
04637     
04638     landaddfastverb (getmenuhandletoken);
04639     
04640     landaddfastverb (idwho);
04641     
04642     landaddverb (idrunmenuitem); /*if option key is down, this may open the scipt*/
04643     
04644     landaddfastverb (killscripttoken);
04645     
04646     landacceptanyverb (true); /*although we only register above two, we'll try anything*/
04647     
04648     #if flcomponent
04649     
04650     wsGlobals.windowserver = nil;
04651     
04652     #endif
04653     
04654     return (langipcmenuinit ());
04655     } /*langipcstart*/
04656 
04657 
04658 void langipcshutdown (void) {
04659     
04660     langipcremovefastscript ();
04661     
04662     landclose ();
04663     
04664     #if flcomponent
04665         uisClose ();
04666     #endif
04667     } /*langipcshutdown*/
04668 
04669 
04670 #if flruntime
04671 
04672 boolean langipcinit (void) {
04673     
04674     #ifdef flcomponent
04675     
04676         #if !TARGET_API_MAC_CARBON
04677         RememberA5 ();
04678         #endif
04679     
04680     #endif
04681     
04682     return (true);
04683     } /*langipcinit*/
04684 
04685 #else
04686 
04687 static boolean langipceventhook (EventRecord *ev, WindowPtr w) {
04688 #pragma unused(w)
04689 
04690     /*
04691     7/3/91 dmb: under system 7, we fork off a new thread for every 
04692     incoming IAC event we handle.  under system 6, handling IAC events 
04693     blocks normal event handling until completion.
04694     */
04695     
04696     if (!fltoolkitinitialized)
04697         return (true);
04698     
04699     return (!landeventfilter (ev));
04700     } /*langipceventhook*/
04701 
04702 boolean langipcinit (void) {
04703     
04704     #ifdef flcomponent
04705         //Code change by Timothy Paustian Wednesday, June 14, 2000 9:02:24 PM
04706         //Changed to Opaque call for Carbon
04707         //we don't need this in carbon
04708         #if !TARGET_CARBON
04709         RememberA5 ();
04710         #endif
04711     #endif
04712     shellpusheventhook (&langipceventhook);
04713     
04714     return (true);
04715     } /*langipcinit*/
04716 
04717 #endif
04718 
04719 
04720 

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