Back to index

lightning-sunbird  0.9+nobinonly
GUSIBasics.h
Go to the documentation of this file.
00001 // <GUSIBasics.h>=                                                         
00002 #ifndef _GUSIBasics_
00003 #define _GUSIBasics_
00004 
00005 #ifdef GUSI_SOURCE
00006 
00007 #include <errno.h>
00008 #include <sys/cdefs.h>
00009 #include <stdarg.h>
00010 
00011 #include <ConditionalMacros.h>
00012 
00013 // \section{Definition of compiler features}                               
00014 //                                                                         
00015 // If possible, we use unnamed namespaces to wrap internal code.           
00016 //                                                                         
00017 // <Definition of compiler features>=                                      
00018 #ifdef __MWERKS__
00019 #define GUSI_COMPILER_HAS_NAMESPACE
00020 #endif
00021 
00022 #ifdef GUSI_COMPILER_HAS_NAMESPACE
00023 #define GUSI_USING_STD_NAMESPACE using namespace std; using namespace std::rel_ops;
00024 #else
00025 #define GUSI_USING_STD_NAMESPACE
00026 #endif
00027 
00028 // Asynchronous MacOS calls need completion procedures which in classic 68K code 
00029 // often take parameters in address registers. The way to handle this differs
00030 // a bit between compilers. Note that the [[pascal]] keyword is ignored when
00031 // generating CFM code.                                                    
00032 //                                                                         
00033 // <Definition of compiler features>=                                      
00034 #if GENERATINGCFM
00035 #define GUSI_COMPLETION_PROC_A0(proc, type) \
00036        void (*const proc##Entry)(type * param)   =      proc;
00037 #define GUSI_COMPLETION_PROC_A1(proc, type) \
00038        void (*const proc##Entry)(type * param)   =      proc;
00039 #elif defined(__MWERKS__)
00040 #define GUSI_COMPLETION_PROC_A0(proc, type) \
00041        static pascal void proc##Entry(type * param : __A0) { proc(param); }
00042 #define GUSI_COMPLETION_PROC_A1(proc, type) \
00043        static pascal void proc##Entry(type * param : __A1) { proc(param); }
00044 #else
00045 void * GUSIGetA0()  ONEWORDINLINE(0x2008);
00046 void * GUSIGetA1()  ONEWORDINLINE(0x2009);
00047 #define GUSI_COMPLETION_PROC_A0(proc, type) \
00048        static pascal void proc##Entry()          \
00049               { proc(reinterpret_cast<type *>(GUSIGetA0())); }
00050 #define GUSI_COMPLETION_PROC_A1(proc, type) \
00051        static pascal void proc##Entry()          \
00052               { proc(reinterpret_cast<type *>(GUSIGetA1())); }
00053 #endif
00054 // %define GUSI_COMPLETION_PROC_A0 GUSI_COMPLETION_PROC_A1                 
00055 //                                                                         
00056 // SC seems to have an issue with mutable fields.                          
00057 //                                                                         
00058 // <Definition of compiler features>=                                      
00059 #if defined(__SC__)
00060 #define mutable
00061 #define GUSI_MUTABLE(class, field) const_cast<class *>(this)->field
00062 #else
00063 #define GUSI_MUTABLE(class, field) field
00064 #endif
00065 // SC pretends to support standard scoping rules, but is in fact broken in 
00066 // some cases.                                                             
00067 //                                                                         
00068 // <Definition of compiler features>=                                      
00069 #if defined(__SC__)
00070 #define for   if (0) ; else for
00071 #endif
00072 // The MPW compilers don't predeclare [[qd]].                              
00073 //                                                                         
00074 // <Definition of compiler features>=                                      
00075 #if defined(__SC__) || defined(__MRC__)
00076 #define GUSI_NEEDS_QD       QDGlobals     qd;
00077 #else
00078 #define GUSI_NEEDS_QD       
00079 #endif
00080 // \section{Definition of hook handling}                                   
00081 //                                                                         
00082 // GUSI supports a number of hooks. Every one of them has a different prototype, 
00083 // but is passed as a [[GUSIHook]]. Hooks are encoded with an [[OSType]].  
00084 //                                                                         
00085 // <Definition of hook handling>=                                          
00086 typedef unsigned long OSType;
00087 typedef void (*GUSIHook)(void);
00088 void GUSISetHook(OSType code, GUSIHook hook);
00089 GUSIHook GUSIGetHook(OSType code);
00090 // Currently, three hooks are supported: [[GUSI_SpinHook]] defines a function to 
00091 // be called when GUSI waits on an event.                                  
00092 // [[GUSI_ExecHook]] defines a function that determines whether a file is to be 
00093 // considered ``executable''. [[GUSI_EventHook]] defines a routine that is called
00094 // when a certain event happens. To install an event hook, pass [[GUSI_EventHook]]
00095 // plus the event code. A few events, that is mouse-down and high level events,
00096 // are handled automatically by GUSI. Passing [[-1]] for the hook disables default
00097 // handling of an event.                                                   
00098 //                                                                         
00099 // <Definition of hook handling>=                                          
00100 typedef bool  (*GUSISpinFn)(bool wait);
00101 #define GUSI_SpinHook       'spin'
00102 
00103 struct FSSpec;
00104 typedef bool  (*GUSIExecFn)(const FSSpec * file);
00105 #define GUSI_ExecHook       'exec'
00106 
00107 struct EventRecord;
00108 typedef void (*GUSIEventFn)(EventRecord * ev);
00109 #define GUSI_EventHook      'evnt'
00110 // For the purposes of the functions who actually call the hooks, here's the direct
00111 // interface.                                                              
00112 //                                                                         
00113 // <Definition of hook handling>=                                          
00114 #ifdef GUSI_INTERNAL
00115 extern GUSISpinFn    gGUSISpinHook;
00116 extern GUSIExecFn    gGUSIExecHook;
00117 #endif /* GUSI_INTERNAL */
00118 // \section{Definition of error handling}                                  
00119 //                                                                         
00120 // Like a good POSIX citizen, GUSI reports all errors in the [[errno]] global
00121 // variable. This happens either through the [[GUSISetPosixError]] routine, which
00122 // stores its argument untranslated, or through the [[GUSISetMacError]] routine,
00123 // which translates MacOS error codes into the correct POSIX codes. The mapping
00124 // of [[GUSISetMacError]] is not always appropriate, so some routines will have to
00125 // preprocess some error codes. [[GUSIMapMacError]] returns the POSIX error corresponding
00126 // to a MacOS error.                                                       
00127 //                                                                         
00128 // The domain name routines use an analogous variable [[h_errno]], which is 
00129 // manipulated with [[GUSISetHostError]] and [[GUSISetMacHostError]].      
00130 //                                                                         
00131 // All routines return 0 if 0 was passed and -1 otherwise.                 
00132 //                                                                         
00133 // <Definition of error handling>=                                         
00134 typedef short OSErr;
00135 
00136 int GUSISetPosixError(int error);
00137 int GUSISetMacError(OSErr error);
00138 int GUSIMapMacError(OSErr error);
00139 int GUSISetHostError(int error);
00140 int GUSISetMacHostError(OSErr error);
00141 // POSIX routines should never set [[errno]] from nonzero to zero. On the other
00142 // hand, it's sometimes useful to see whether some particular region of the
00143 // program set the error code or not. Therefore, we have such regions allocate
00144 // a [[GUSIErrorSaver]] statically, which guarantees that previous error codes 
00145 // get restored if necessary.                                              
00146 //                                                                         
00147 // <Definition of error handling>=                                         
00148 class GUSIErrorSaver {
00149 public:
00150        GUSIErrorSaver()            { fSavedErrno = ::errno; ::errno = 0;     }
00151        ~GUSIErrorSaver()           { if (!::errno) ::errno = fSavedErrno;  }
00152 private:
00153        int fSavedErrno;
00154 };
00155 // \section{Definition of event handling}                                  
00156 //                                                                         
00157 // [[GUSIHandleNextEvent]] events by calling handlers installed            
00158 // using the [[GUSI_EventHook]] mechanism.                                 
00159 //                                                                         
00160 // <Definition of event handling>=                                         
00161 void GUSIHandleNextEvent(long sleepTime);
00162 // \section{Definition of string formatting}                               
00163 //                                                                         
00164 // We occasionally need sprintf. To keep compatibility with MSL, Stdio, and Sfio, 
00165 // we use an internal version which can be overridden.                     
00166 //                                                                         
00167 // <Definition of string formatting>=                                      
00168 int GUSI_vsprintf(char * s, const char * format, va_list args);
00169 int GUSI_sprintf(char * s, const char * format, ...);
00170 
00171 #endif /* GUSI_SOURCE */
00172 
00173 #endif /* _GUSIBasics_ */