land.c

Go to the documentation of this file.
00001 
00002 /*  $Id: land.c 1191 2006-04-05 21:18:25Z karstenw $    */
00003 
00004 /******************************************************************************
00005 
00006     UserLand Frontier(tm) -- High performance Web content management,
00007     object database, system-level and Internet scripting environment,
00008     including source code editing and debugging.
00009 
00010     Copyright (C) 1992-2004 UserLand Software, Inc.
00011 
00012     This program is free software; you can redistribute it and/or modify
00013     it under the terms of the GNU General Public License as published by
00014     the Free Software Foundation; either version 2 of the License, or
00015     (at your option) any later version.
00016 
00017     This program is distributed in the hope that it will be useful,
00018     but WITHOUT ANY WARRANTY; without even the implied warranty of
00019     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020     GNU General Public License for more details.
00021 
00022     You should have received a copy of the GNU General Public License
00023     along with this program; if not, write to the Free Software
00024     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00025 
00026 ******************************************************************************/
00027 
00028 #include "frontier.h"
00029 #include "standard.h"
00030 
00031 #include "landinternal.h"
00032 
00033 #include "ops.h"
00034 #include "process.h"
00035 
00036 #if TARGET_API_MAC_CARBON == 1 /*PBS 03/14/02: AE OS X fix.*/
00037     #include "aeutils.h" /*PBS 03/14/02: AE OS X fix.*/
00038 #endif
00039 
00040 
00041 /*
00042 4/28/92 dmb: use this static instead of asm global stuff
00043 */
00044     
00045     static hdllandglobals hlandglobals = nil;
00046     
00047     #define landsetlandglobals(x)   (hlandglobals = x)
00048     #define landgetlandglobals()    (hlandglobals)
00049 
00050 
00051 typedef struct tytransportinfo { 
00052     
00053     hdlprocessthread hthread; /*must be first field*/
00054     
00055     } tytransportinfo, *ptrtransportinfo, **hdltransportinfo;
00056 
00057 
00058 
00059 static THz landzone;
00060 
00061 #if !TARGET_API_MAC_CARBON
00062     static Handle landresmap;
00063 #endif
00064 
00065 static short landresfile;
00066 
00067 
00068 
00069 pascal boolean landpushfastcontext (tyfastverbcontext *savecontext) {
00070     
00071     register tyfastverbcontext *x = savecontext;
00072     //Code change by Timothy Paustian Monday, June 26, 2000 3:19:32 PM
00073     //
00074     #if TARGET_API_MAC_CARBON == 1
00075     (*x).savezone = LMGetApplZone();
00076     #else
00077     (*x).savezone = GetZone ();
00078     #endif
00079         
00080     (*x).saveresfile = CurResFile ();
00081     
00082     //I wonder if these calls are needed. Can we get away with
00083     //UseResFile and CurResFile
00084     #if !TARGET_API_MAC_CARBON
00085     (*x).savemaphandle = LMGetTopMapHndl ();
00086     #endif
00087 
00088     #if TARGET_API_MAC_CARBON == 1
00089     LMSetApplZone(landzone);
00090     #else   
00091     SetZone (landzone);
00092     #endif
00093     #if !TARGET_API_MAC_CARBON
00094     LMSetTopMapHndl (landresmap);
00095     #endif
00096 
00097     UseResFile (landresfile);
00098     
00099     return (true);
00100     } /*landpushfastcontext*/
00101 
00102 
00103 pascal void landpopfastcontext (const tyfastverbcontext *savecontext) {
00104     
00105     register const tyfastverbcontext *x = savecontext;
00106     
00107     #if !TARGET_API_MAC_CARBON
00108     LMSetTopMapHndl ((*x).savemaphandle);
00109     #endif
00110 
00111     UseResFile ((*x).saveresfile);
00112     #if TARGET_API_MAC_CARBON == 1
00113     LMSetApplZone((*x).savezone);
00114     #else
00115     SetZone ((*x).savezone);
00116     #endif
00117     } /*landpopfastcontext*/
00118 
00119     
00120 pascal hdllandglobals landgetglobals (void) {
00121         
00122     return (landgetlandglobals ()); /*return value of asm routine*/
00123     } /*landgetglobals*/
00124 
00125 
00126 pascal boolean landdisposeparamrecord (const typaramrecord *p) {
00127     
00128     /*
00129     dispose of any storage linked into the parameter record.  
00130     
00131     assume all non-scalars are simple handles, with nothing linked to it.  if
00132     we add more complex types, this routine will get more complex.
00133 
00134     docnote: param now passed by reference for Pascal compatability.
00135     */
00136     
00137     #if TARGET_API_MAC_CARBON == 1
00138     
00139         AEDisposeDesc ((AEDesc*) &(*p).desc);
00140         
00141     #else
00142     
00143         register Handle h;
00144         
00145         h = (*p).desc.dataHandle;
00146         
00147         landdisposehandle (h);
00148     
00149     #endif
00150     
00151     return (true);
00152     } /*landdisposeparamrecord*/
00153     
00154 
00155 pascal boolean landdisposeverb (hdlverbrecord hverb) {
00156     
00157     /*
00158     dispose of all storage owned by the indicated verb record, and the handle
00159     that stores the record.
00160     
00161     we assume that the transportinfo record has no handles linked to it, if 
00162     it does, call your transport mechanism here to dispose of the fields of 
00163     the transportinfo handle.
00164     */
00165     
00166     register hdlverbrecord hv = hverb;
00167     
00168     if (hv == nil)
00169         return (false);
00170     
00171     /*
00172     landdisposeallparams (hv);
00173     */
00174     
00175     landsystem7disposeverb (hv); /*dispose linked handles in transport info*/
00176     
00177     landdisposehandle ((**hv).transportinfo); /*assume no linked handles*/
00178     
00179     landdisposehandle ((Handle) hv);
00180     
00181     return (true);
00182     } /*landdisposeverb*/
00183 
00184 
00185 static boolean landsetupnewverb (tyapplicationid idreceiver, tyverbclass class, tyverbtoken token, short ctparams, hdlverbrecord *hverb) {
00186     
00187     /*
00188     allocate a new verb record with room for the indicated number of parameters.
00189     
00190     the caller will then push parameters, and finally send the verb.
00191     
00192     if you don't know up-front how many parameters you will push, just send in 0
00193     and we'll enlarge the handle every time you push a parameter.
00194     */
00195     
00196     register hdllandglobals hg = landgetglobals ();
00197     register hdlverbrecord hv;
00198     
00199     if (!(**hg).flconnected)
00200         return (false);
00201     
00202     if (!landnewclearhandle (longsizeof (tyverbrecord), (Handle *) hverb)) /*allocation failure*/
00203         return (false);
00204     
00205     hv = *hverb; /*copy into register*/
00206     
00207     (**hv).idsender = (**hg).applicationid;
00208     
00209     (**hv).idreceiver = idreceiver;
00210     
00211     (**hv).idtransaction = (**hg).eventsettings.transactionid;
00212     
00213     (**hv).verbclass = class;
00214     
00215     (**hv).verbtoken = token;
00216     
00217     (**hv).ctparams = ctparams;
00218     
00219     return (true);
00220     } /*landsetupnewverb*/
00221 
00222 
00223 pascal boolean landnewverb (tyapplicationid idreceiver, ProcessSerialNumber *psn, tyverbclass class, tyverbtoken token, short ctparams, hdlverbrecord *hverb) {
00224     
00225     /*
00226     allocate a new verb record with room for the indicated number of parameters.
00227     
00228     the caller will then push parameters, and finally send the verb.
00229     
00230     if you don't know up-front how many parameters you will push, just send in 0
00231     and we'll enlarge the handle every time you push a parameter.
00232     
00233     2.1a7 dmb: take psn param
00234     */
00235     
00236     register hdlverbrecord hv;
00237     register boolean fl;
00238     
00239     if (!landsetupnewverb (idreceiver, class, token, ctparams, hverb))
00240         return (false);
00241     
00242     hv = *hverb; /*copy into register*/
00243     
00244     fl = landsystem7newverb (hv, psn);
00245     
00246     /*
00247     if ((**hg).transport == macsystem7) 
00248         fl = landsystem7newverb (hv);
00249     else
00250         fl = landsystem6newverb (hv);
00251     */
00252     
00253     if (!fl) {
00254         
00255         landdisposeverb (hv);
00256         
00257         *hverb = nil;
00258         
00259         return (false);
00260         }
00261     
00262     return (true);
00263     } /*landnewverb*/
00264 
00265 
00266 pascal boolean landnewnetworkverb (tynetworkaddress *adr, tyverbclass class, tyverbtoken token, short ctparams, hdlverbrecord *hverb) {
00267 
00268     /*
00269     7/15/91 DW: return false on system 6.
00270     */
00271     
00272     register hdlverbrecord hv;
00273     
00274     if (!landsetupnewverb (idnet, class, token, ctparams, hverb))
00275         return (false);
00276     
00277     hv = *hverb; /*copy into register*/
00278     
00279     if (!landsystem7newnetworkverb (hv, adr)) {
00280         
00281         landdisposeverb (hv);
00282         
00283         *hverb = nil;
00284         
00285         return (false);
00286         }
00287     
00288     return (true);
00289     } /*landnewnetworkverb*/
00290     
00291 
00292 pascal boolean landcomplexsend (hdlverbrecord hverb, hdlverbrecord *hresult) {
00293     
00294     /*
00295     the low-level send routine.  call this directly if you want to look 
00296     at multiple return values.  otherwise, use landsendverb, below
00297     */
00298     
00299     register hdlverbrecord hv = hverb;
00300     register hdllandglobals hg = landgetglobals ();
00301     register boolean fl;
00302     
00303     if (!(**hg).flconnected)
00304         return (false);
00305     
00306     (**hg).landerrorcode = noErr;
00307     
00308     fl = landsystem7send (hv, hresult);
00309     
00310     /*
00311     if ((**hg).transport == macsystem7) 
00312         fl = landsystem7send (hv, hresult);
00313     else
00314         fl = landsystem6send (hv, hresult);
00315     */
00316     
00317     landdisposeverb (hv);
00318     
00319     return (fl);
00320     } /*landcomplexsend*/
00321 
00322 
00323 pascal boolean landsendverb (hdlverbrecord hverb, typaramrecord *result, bigstring bserror, short *iderror) {
00324     
00325     /*
00326     the simpler way to send a verb record.  we assume there is a single returned
00327     value, if there are any others, we throw them away.  if you can use more than
00328     one returned value, call the more complex verb sender -- landcomplexsend.
00329     
00330     result holds the returned value, unless the return is an error, in which case
00331     we copy the error string and the error id (a 16-bit signed number) into the
00332     returned bserror and iderror.
00333     
00334     we return true if there's a valid value in *result.  the client is responsible
00335     for disposing of any handles in the result.
00336     
00337     if we return false with iderror == 0 there has been a communications breakdown
00338     of some kind.  the client should stop trying to process the verb and get back
00339     to its main event loop ASAP.
00340     
00341     if there was an error, we look for an error string as well.  if none is found, 
00342     bserror will be the empty string
00343     
00344     8/17/92 dmb: fixed handling of zero error numbers
00345     
00346     1/25/93 dmb: make sure that an 'errn' that can't be coerced to a short is still 
00347     recognized as an error condition
00348     
00349     3.0.1b1 dmb: #if'd out the special handling of "land" errors, 1-6. archaic, and 
00350     in the way.
00351     */
00352     
00353     hdlverbrecord hresult;
00354     register boolean fl = false;
00355     typaramrecord errorparam;
00356     
00361     *iderror = 0; /*default --no error*/
00362     
00363     setemptystring (bserror); /* no error*/
00364     
00365     landclearbytes (result, longsizeof (*result));
00366     
00367     if (!landcomplexsend (hverb, &hresult))
00368         return (false);
00369     
00370     landnextparamisoptional (hresult); /*don't require that any reply values exist*/
00371     
00372     if (landgetparam (hresult, errornumberkey, notype, &errorparam)) { /*got an error*/
00373         
00374         if (!landgetintparam (hresult, errornumberkey, iderror)) { /*couldn't coerce to short*/
00375             
00376             landseterror (noErr); /*clear coercion error*/
00377             
00378             *iderror = errAEEventFailed;
00379             }
00380         
00381         landnextparamisoptional (hresult); /*don't require next parameter...*/
00382         
00383         if (*iderror == 0) { /*'errn' was zero, not an error; check for direct param*/
00384             
00385             fl = true; /*not an error*/
00386             
00387             landgetparam (hresult, returnedvaluekey, notype, result); /*take it if it's there*/
00388             }
00389         else {
00390             
00391             if (!landgetstringparam (hresult, errorstringkey, bserror)) { /*no string*/
00392                 
00393                 #if 0
00394                 
00395                 register hdllandglobals hg = landgetglobals ();
00396                 short ixstring = *iderror;
00397                 
00398                 if ((ixstring > 0) && (ixstring <= usercancellederror)) /*one of our errors*/
00399                     GetIndString (bserror, (**hg).iderrorlist, ixstring);
00400                 
00401                 #endif
00402                 }
00403             }
00404         }
00405     else {
00406         
00407         fl =
00408             (**hresult).ctparams == 0 || /*OK not to have anything returned*/
00409             
00410             landgetparam (hresult, returnedvaluekey, notype, result) || /*take return key first*/
00411             
00412             landgetnthparam (hresult, 1, result); /*got a returned value of some type*/
00413         }
00414     
00415     landdisposeverb (hresult);
00416     
00417     return (fl);
00418     } /*landsendverb*/
00419 
00420 
00421 boolean landhandleverb (hdlverbrecord hverb) {
00422     
00423     /*
00424     a jacket for handling verbs -- we catch all those that are implemented by the
00425     API, never calling the using program's handler -- we just return the value that's
00426     being asked for.
00427 
00428     6/27/91 DW: stats window supported two ways -- we display the stats info on
00429     receipt of the verb, and reset the memory message on the idrunning message.
00430     
00431     7/6/91 DW: if a script has been cancelled, and we receive a message from
00432     the scripting system we send back usercancellederror. 
00433     */
00434     
00435     register hdllandglobals hg = landgetglobals ();
00436     register hdlverbrecord hv = hverb;
00437     
00438     register boolean fl;
00439     register landverbrecordcallback cb = (**hg).handleverbroutine;
00440     
00441     fl = (*cb) (hv);
00442     
00443     landdisposeverb (hv);
00444     
00445     return (fl);
00446     } /*landhandleverb*/
00447 
00448 
00449 pascal boolean landsettimeout (long ticks) {
00450     
00451     register hdllandglobals hg = landgetglobals ();
00452     
00453     (**hg).eventsettings.timeoutticks = ticks;
00454     
00455     return (true);
00456     } /*landsettimeout*/
00457 
00458 
00459 pascal boolean landsettransactionid (long id) {
00460     
00461     register hdllandglobals hg = landgetglobals ();
00462     
00463     (**hg).eventsettings.transactionid = id;
00464     
00465     return (true);
00466     } /*landsettransactionid*/
00467 
00468 
00469 pascal boolean landsetinteractionlevel (short level) {
00470     
00471     register hdllandglobals hg = landgetglobals ();
00472     
00473     switch (level) {
00474         
00475         case -1:
00476             level = 0; break;
00477         
00478         case 0:
00479             level = kAENeverInteract; break;
00480         
00481         default:
00482             level = kAEAlwaysInteract + kAECanSwitchLayer;
00483         }
00484     
00485     (**hg).eventsettings.interactionlevel = level;
00486     
00487     return (true);
00488     } /*landsetinteractionlevel*/
00489 
00490 #if !flruntime
00491 
00492 pascal boolean landeventfilter (EventRecord *ev) {
00493     
00494     /*
00495     insert a call to this routine in your main event loop to check for incoming
00496     verbs.  if one is available, we will call the landglobals callback routine
00497     for message handling.
00498     
00499     we filter all events.  the system 7 transport watches for high level 
00500     events, while the system 6 transport polls during null events.
00501     
00502     return true if the event record is consumed, false otherwise.
00503     
00504     10/30/90 DW: add call to landpoll so that using program doesn't have to install
00505     two wires to us in the main event loop.
00506     
00507     11/6/90 dmb: polling now happens in landsystem6eventfilter.
00508     
00509     6/26/91 DW: add filter for events sent to the stats window.
00510     */
00511     
00512     register hdllandglobals hg = landgetglobals ();
00513     
00514     /*
00515     if (landwindoweventfilter (ev)) /%event consumed by stats window%/
00516         return (true);
00517     */
00518     
00519     if (!(**hg).flconnected)
00520         return (false);
00521         
00522     return (landsystem7eventfilter (ev));
00523     
00524     /*
00525     if ((**hg).transport == macsystem7)
00526         return (landsystem7eventfilter (ev));
00527     else 
00528         return (landsystem6eventfilter (ev));
00529     */
00530     } /*landeventfilter*/
00531 
00532 #endif
00533 
00534 
00535 pascal boolean landclose (void) {
00536         
00537     register hdllandglobals hg = landgetglobals ();
00538     
00539     landsystem7close ();
00540     
00541     landdisposehandle ((Handle) (**hg).verbarray);
00542     
00543     return (true);
00544     
00545     /*
00546     if (!(**hg).flconnected)
00547         return (false);
00548     */
00549     
00550     /*
00551     if ((**hg).transport == macsystem7) 
00552         return (landsystem7close ());
00553     else
00554         return (landsystem6close ());
00555     */
00556     
00557     landdisposehandle ((Handle) hg);
00558     } /*landclose*/
00559     
00560     
00561 pascal boolean landefaultbreakembrace (EventRecord *ev) {
00562 #pragma unused (ev)
00563 
00564     /*
00565     return true if the user is holding down the cmd, option and shift keys.
00566     */
00567     
00568     #pragma unused (ev)
00569     
00570     register Ptr p;
00571     KeyMap keys;
00572     
00573     GetKeys (keys);
00574 
00575     p = (Ptr) keys; 
00576 
00577     return (BitTst (p, 63) && BitTst (p, 48) && BitTst (p, 61));
00578     } /*landefaultbreakembrace*/
00579 
00580 
00581 pascal void landseterror (OSErr errorcode) {
00582     
00583     /*
00584     set the global error code for later retrieval via landgeterror
00585     */
00586     
00587     register hdllandglobals hg = landgetglobals ();
00588     
00589     (**hg).landerrorcode = errorcode;
00590     } /*landseterror*/
00591 
00592 
00593 pascal OSErr landgeterror (void) {
00594     
00595     /*
00596     return the OSError that cause the last land call to return false.
00597     
00598     the value returned by this routine has no meaning if the last call 
00599     did not return false
00600     */
00601     
00602     register hdllandglobals hg = landgetglobals ();
00603     
00604     return ((**hg).landerrorcode);
00605     } /*landgeterror*/
00606 
00607 
00608 pascal boolean landnextparamisoptional (hdlverbrecord hverb) {
00609     
00610     (**hverb).flnextparamisoptional = true;
00611     
00612     return (true);
00613     } /*landnextparamisoptional*/
00614 
00615 
00616 pascal boolean landverbgetsnoreply (hdlverbrecord hverb) {
00617     
00618     (**hverb).flverbgetsnoreply = true;
00619     
00620     return (true);
00621     } /*landverbgetsnoreply*/
00622 
00623 
00624 pascal boolean landacceptanyverb (boolean flacceptanyverb) {
00625 
00626     register hdllandglobals hg = landgetglobals ();
00627     
00628     (**hg).flacceptanyverb = flacceptanyverb;
00629     
00630     if ((**hg).transport == macsystem7) /*dmb 10/8/91*/
00631         landsystem7acceptanyverb ();
00632     
00633     return (true);
00634     } /*landacceptanyverb*/
00635 
00636 
00637 pascal boolean landsetapplicationid (tyapplicationid tynewid) {
00638     
00639     return (false);
00640     
00641     /*
00642     register hdllandglobals hg = landgetglobals ();
00643     
00644     if ((**hg).transport == macsystem7) /%DW 6/25/91%/
00645         return (false);
00646     
00647     return (landsystem6setapplicationid (tynewid));
00648     */
00649     
00650     } /*landsetapplicationid*/
00651 
00652 
00653 static landqueuepopcallback threadvisit;
00654 
00655 static pascal boolean sleepingthreadvisit (Handle htinfo, long refcon) {
00656     
00657     hdltransportinfo ht = (hdltransportinfo) htinfo;
00658     
00659     if ((*threadvisit) ((Handle) (**ht).hthread, refcon)) {
00660         
00661         processwake ((**ht).hthread);
00662         
00663         return (true);
00664         }
00665     
00666     return (false);
00667     } /*sleepingthreadvisit*/
00668 
00669 
00670 pascal boolean landvisitsleepingthreads (landqueuepopcallback visitroutine, long refcon) {
00671     
00672     /*
00673     return true (andk stop visiting) if the visit routine ever returns true.
00674     
00675     note that when the visit routine does return true, the thread is awakended 
00676     and the item is popped from the queue
00677     */
00678     
00679     hdltransportinfo ht;
00680     
00681     threadvisit = visitroutine; /*make visible to our visit routine*/
00682     
00683     return (landpopqueueitem (&sleepingthreadvisit, refcon, (Handle *) &ht));
00684     } /*landvisitsleepingthreads*/
00685 
00686 
00687 pascal boolean landinit (void) {
00688     
00689     /*
00690     start up UserLand IAC Toolkit.  must be called before the application opens
00691     any files -- so we can call landgetappcreator to get the application id.
00692     
00693     determine what transport to use, and initialize landglobals fields
00694     
00695     add the two default verbs to the verb list
00696     
00697     3.0.1b1 dmb: don't initialize iderrorlist to 129; if the client doesn't 
00698     set it, it's not valid.
00699     */
00700     
00701     register hdllandglobals hg = landgetglobals ();
00702     /*
00703     SysEnvRec world;
00704     */
00705     long result;
00706     hdllandglobals hglobals;
00707     tyapplicationid id;
00708     
00709     #if TARGET_API_MAC_CARBON == 1
00710     landzone = LMGetApplZone();
00711     #else   
00712     landzone = GetZone ();
00713     #endif
00714         
00715     #if !TARGET_API_MAC_CARBON
00716     landresmap = LMGetTopMapHndl ();
00717     #endif
00718 
00719     landresfile = CurResFile ();
00720     
00721     if (hg == nil) { /*if someone hasn't already put something there*/
00722         
00723         if (!landnewclearhandle (longsizeof (tylandglobals), (Handle *) &hglobals))
00724             return (false);
00725             
00726         landsetlandglobals (hglobals);  /*stick the handle in*/
00727         
00728         hg = hglobals;
00729         }
00730     
00731     (**hg).transport = macsystem7;
00732     
00733     (**hg).applicationid = '    ';
00734     
00735     /*
00736     (**hg).iderrorlist = 129;
00737     
00738     (**hg).flconnected = false;
00739     
00740     (**hg).flacceptanyverb = false;
00741     
00742     (**hg).verbarray = nil;
00743     
00744     (**hg).handleverbroutine = nil;
00745     
00746     (**hg).breakembraceroutine = nil;
00747     
00748     (**hg).macopenapproutine = nil;
00749     
00750     (**hg).macopendocroutine = nil;
00751     
00752     (**hg).macprintdocroutine = nil;
00753     
00754     (**hg).macquitapproutine = nil;
00755     
00756     (**hg).mactypes = nil;
00757     
00758     (**hg).hqueue = nil;
00759     
00760     (**hg).ipcrefnum = 0;
00761     */
00762     
00763     (**hg).breakembraceroutine = &landefaultbreakembrace;
00764     
00765     if (!landgetappcreator (&id))
00766         return (false);
00767     
00768     (**hg).applicationid = id;
00769     
00770     if (!gestalt (gestaltAppleEventsAttr, &result) || (result == 0))
00771         return (false);
00772     
00773     if (!landsystem7init ())
00774         return (false);
00775     
00776     landaddclass (userlandclass); /*add built-in, API-supported verbs*/
00777     
00778     landaddverb (idrunning);
00779     
00780     landaddclass (id); /*initial verbs are in the app's creator id class*/
00781     
00782     (**hg).flconnected = true;
00783     
00784     //landsetmemstats (); /*copy freemem into globals -- for use in stats window*/
00785     
00786     return (true);
00787     } /*landinit*/
00788 
00789 

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