\begindata{text,538611048} \textdsversion{12} \template{default} \majorheading{ASlot - Class for Widget Attributes} ASlot and classes derived from it form a family of types and slots for AWidget attributes. New types can be added in separate source files. The files aslot.H and aslot.C define these classes: \leftindent{ASlotInt, ASlotReal, ASlotString, ASlotFile, ASlotPtr, \ ASlotATK, ASlotFunction, ASlotDataObj, ASlotFigure } (Moreover, ASlotBoolean is defined to be ASlotInt). \ Appropriate conversions and assignments between ASlot values and C++ values are supported for \indent{int, long, double , const char *, const char, void *, ATK *, aaction *, dataobject *, text *, figure} * Objects of type aaction can be called as functions. \section{Examples} Usually a slot is part of an AWidget object or an object in a class derived from AWidget. Let us suppose we are deriving class GoodWidget from AWidget and GoodWidget is to have an integer slot "elasticity". The declaration of GoodWidget would include: goodwidget.H #include <awidget.H> class GoodWidget : AWidget \{ . . . ASlotInt elasticity; . . . \} Slots behave like C++ values. have: For instance a client of GoodWidget could client.C: #include <goodwidget.H> . . . GoodWidget *obj = . . . ; int size = obj->elasticity * localsize; obj->elasticity = 1; If the elasticity slot is private in goodwidget.H, accessor functions can be provided. goodwidget.H inline int GetElasticity() \ \{return elasticity;\} inline void SetElasticity(int v) \{elasticity = v; \} client.C: AWidget *obj = . . .; int size = obj->GetElasticity() * localsize; obj->SetElasticity(1);\} \section{Slot Names} Slots can have names that are usable at runtime, although these are of little value until the slot is incorporated in a collection as in an AVarSet. A slot name is an atom. To simplify constructing and declaring slot names in code, aslot.H defines three features: \bold{ASlot_NAME(name)} \leftindent{This macro creates an atom for "name" and makes it the value of a const identifier, slot_name. A name for the elasticity slot would be declared \leftindent{Aslot_NAME(elasticity);} The resulting declared name constant is "slot_elasticity".} \bold{ASlot_NameVar} \leftindent{It is possible to declare a variable to hold a slot name. The type of this variable should be ASlot_NameVar. This is NOT used for function parameters.} \bold{ASlot_NameParam} \leftindent{If a slot name is to be passed to a function, its type should be ASlot_NameParam.} The value assigned to an ASlot_NameVar or passed to an ASlot_NameParam can be another such value or an atom, an atom *, a const atom *, an atom_def, or even a plain string: ASlot_NAME(elasticity); // slot_elasticity ASlot_NameVar nv; nv = slot_elasticity; // ok nv = atom_def("elasticity"); // ok nv = "elasticity"; // even this is okay \section{ASlot public methods }\ \bold{static void Init()} This function must be called during initialization of any module which uses one of the ASlot::xxxreg values. \bold{ASlot()} Constructor \bold{virtual ~ASlot()} Destructor\bold{ } \bold{virtual ASlot &Default()} \leftindent{Sets slot to its default value. Usually zero.} \bold{virtual boolean IsDefault()} \leftindent{TRUE iff latest assign is via Default()} \bold{operator avalue_u()} \leftindent{Returns value as an avalue_u.} \bold{virtual ASlot &operator=(const ASlot *v)} \ \leftindent{Assigns value of one slot to another. must accept type of source.} Type of destination \subsection{Input/output} A line written has the form: \ slot-name : ( type ) string-basis-for-value \\n where type is the suffix after "ASlot" in the class name. \bold{void Write(FILE *fp)} Writes a string representation to a file stream \bold{static ASlot *Read(FILE *fp)} Reads a representation from the file stream. // value<->string conversion caller of ReadValue or WriteValue should check the newline avoid duplication from WriteValue do NOT send it to ReadValue \bold{virtual void WriteValue(AString *dest)} \leftindent{Writes the value as a string to dest. type. No trailing newline.} No slotname, colon, or \bold{virtual boolean ReadValue(const char *src)} \leftindent{Reads value from src. trailing newline.} No slotname, colon, or type. No // each function converts from its argument to a string // and calls ReadValue on the string // interprets TAGS on the front of strings \bold{virtual boolean EatString(const char *src)} \bold{virtual boolean EatAaction(const aaction *act)} \bold{virtual boolean EatATK(const ATK *obj)} \bold{virtual boolean EatAvalue(const avalue *v)} \leftindent{A derived class should override any of these if it can do a better job of interpreting a string than the default would do. For instance, if this derived type stores ATK values in some special way, it would override EatATK to interpret the object for itself. }\ \leftindent{The default behaviors are these: \ \indent{EatString - checks the string for an initial tag of PROC, NESS, NESSEXP, or FILE and calls the function or reads the file to get a string for further processing. EatAaction - execute the function and call EatAvalue on the result. EatAvalue - for a string or atom value, call EatString on the value; for ATK values, call EatATK; otherwise fail. EatATK -if value is a text or simpletext, EatString is called on the text; if the value is an aaction, EatAaction is called on the result; otherwise fail.}} \ // Flags: the next two set/reset the todatastream flag // it will be set again if fromresources is true \ // and the value is modified \bold{void Remember()} \leftindent{Sets flags to cause attribute to be written to data stream.} void\bold{ DisRemember()} Sets flags so the attribute will not be written to data stream. // ASlot: The following are for AWidget and other driver modules // Normal clients should not need these \bold{static const char *ASlotPrefix(const char *name)} // returns name prefixed with "ASlot" \bold{const char *GetSlotType()} // could be \{return GetTypeName();\} // but strip off leading "ASlot" \bold{static ATKregistryEntry *LoadType(const char *typenm)} // for AWidget::AddSlot(atom *name, char *typenm) // creates a slot of the named type // almost is: \{return ATK::LoadClass(typenm);\} // but have to prefix typename w/ "ASlot" \bold{static ASlot *NewASlot(const char *typenm)} // typenm does not have leading "ASlot" \bold{void SetName(ASlot_NameParam nm)} \bold{ASlot_NameVar GetName()} \bold{void SetSource(const char *src)} set string that will be written to data stream uses NewString to make a copy of its argument \bold{const char *GetSource()} returns a pointer to the string \ that will be written to the data stream \bold{void SetAssign(aaction *newset)} sets the setit function associated with the slot deletes the old (assumes ownership) \bold{aaction *GetAssign()} \bold{void UseOnlyFromAnAssignFunction (const avalue_u *src)} \leftindent{a setit functionshould use this function todo the actual assignment of a new value to the slot} the setit function for an ASlotString slot should NOT use NewString the setit function for an ASlotFile slot should NOT use NewString // ASlotAssign - class for aactions supplied as Assign function \bold{DEFINE_AACTION_FUNC_CLASS(ASlotAssign, ASlot);} \bold{inline char *Client(const char *objnm) }\ saves the objname for use in error messages objname string continues to be owned by the caller, but must not be deallocated until a call \ has been made to restore the old value, \ establish a new value, or clear the client \ string (via ASlot::ClearClient()). \bold{inline void ClearClient() }\ Forgets about the client. Error messages will be anonymous. the client is assumed to own the string intention is that Client() is called on entry to a function like Update and the old value is restored on exit \bold{void DumpSlot()} \bold{static const char *Client(const char *objnm)} // ASlot: Operations on flags \ \bold{void EnableFlags(unsigned short f)} \bold{void DisableFlags(unsigned short f)} \bold{unsigned int GetFlags(unsigned short mask =~0)} // ASlot: Constants for flag values. \bold{static const unsigned short fromresources;} // value came from resource file or inherited in tree \bold{static const unsigned short todatastream;} // will save in datastream \bold{static const unsigned short isowner;} // ~ASlot must free val.obj \bold{static const unsigned short isdefault;} // most recent value given by Default() // ASlot: operator typenm() conversions // must be overridden to be useful \bold{virtual operator int() virtual operator long() virtual operator double() virtual operator char() virtual operator const() virtual operator void() virtual operator ATK() virtual operator aaction() virtual operator dataobject() virtual operator text() virtual operator figure()} // ASlot: operator=(type) // conversions must be overridden to be useful \bold{virtual ASlot & operator= (typenm v); virtual ASlot & operator= (int v) virtual ASlot & operator= (long v) virtual ASlot & operator= (double v) virtual ASlot & operator= (char v) virtual ASlot & operator= (const char *v) virtual ASlot & operator= (void *v) virtual ASlot & operator= (ATK *v) virtual ASlot & operator= (aaction *v) virtual ASlot & operator= (proctable_Entry *v) virtual ASlot & operator= (figure *v)} // ASlot: Function call operations (using aaction) // no in or out virtual avalue operator()(ATK *obj=NULL) // no out virtual avalue operator()(ATK *obj, const avalueflex &in) // both in and out supplied virtual avalue operator()(ATK *obj, \ const avalueflex &in, avalueflex &out) \bold{static atom *in0type} \section{ASlotInt }\ \bold{#define ASlotBoolean ASlotInt} \bold{ASlotInt() \{ val.integer = -999; \}} \bold{ASlotInt(int i)} \bold{ASlotInt(atom *name) \{ val.integer = -999;} \bold{ASlotInt(atom *name, int i) }\ \bold{ASlot &Default()} \bold{operator int()} \bold{operator long()} \bold{ASlot &operator=(long i) }\ \ \bold{ASlot &operator=(int i)} \bold{void WriteValue(AString *dest)} \bold{boolean ReadValue(const char *src)} \bold{boolean EatAvalue(const avalue *v)} \section{ASlotReal} \bold{ASlotReal() \{ val.real = -999.0; \}} \bold{ASlotReal(double r)} \bold{ASlotReal(atom *name) }\ \bold{ASlotReal(atom *name, double r) }\ \bold{ASlot &Default(); }\ \bold{operator double()} \bold{ASlot &operator=(double r) }\ \bold{void WriteValue(AString *dest);} \bold{boolean ReadValue(const char *src);} \bold{boolean EatAvalue(const avalue *v);} \section{ASlotString} conversion to char gives first char value will never be NULL. \ At smallest it is "", the empty string. if there is no (type) in a resource line, string is used in that case, \ leading whitespace is stripped from the string value \bold{ASlotString() \{ val.cstr = empty; \}} \bold{ASlotString(const char*s) }\ \bold{ASlotString(atom *name) }\ \bold{ASlotString(atom *name, const char *s) }\ \bold{virtual ~ASlotString() }\ \bold{ASlot &Default();} \bold{operator const char () // 1st ch.} \bold{operator const char *()} \bold{ASlot &operator=(const ASlot *s);} \bold{ASlot &operator=(const char *s);} \bold{ASlot &operator=(const char s) }\ \{ char buf[2]; buf[0]=s; buf[1]='\\0'; \ *this = (const char *)buf; \} \bold{void WriteValue(AString *dest);} \bold{boolean ReadValue(const char *src);} \section{ASlotFile }\ // ASlotFile holds a string value during execution // it overrides ReadValue and WriteValue and \ // saves various access paths to file // Default is /dev/null If ReadFile or Open fails, the string name is \ replaced with the default. ReadFile Open(flags) Exactly one of these three is needed: O_RDONLY, O_WRONLY, O_RDWR This is needed if the file may not already exist: O_CREAT (mode 644) This is needed if writing to the end of file is desired: O_APPEND O_TRUNC Use this with O_WRONLY or O_RDWR to cause an existing file to be truncated when opened. These are probably not useful: O_NDELAY, O_SYNC, O_NOCTTY, O_NONBLOCK, O_EXCL \ string value will be actual file name that's all that's needed internally init to "" set up string (and save info) on any assign to the field file format saves various ways of addressing the file: absolute, relative, $HOME, $ANDREWDIR /usr/local, ... Created by WriteValue Interpreted by ReadValue (anything that can be resolved by UnfoldPathName) ASlot and derived classes form a family of types and slots for AWidget attributes. The design permits a typed attribute \ to be added to an AWidget even if that widget was compiled before the particular ASlot derived class was implemented. ASlotBoolean (#defined to ASlotInt) XXX ??? Should constructors with initializations use operator= (as they do now) \ or assign directly to val.obj ??? \bold{ASlotFile() \{ val.cstr = devnull; \}} \bold{ASlotFile(const char *s) \{val.cstr = devnull; *this = s;\}} \bold{ASlotFile(atom *name) }\ \bold{ASlotFile(atom *name, const char *s) }\ \bold{virtual ~ASlotFile() }\ \bold{ASlot &Default()} \bold{ASlot &operator=(const ASlot *s);} \bold{ASlot &operator=(const char *s);} \bold{operator const char *()} \bold{void WriteValue(AString *dest);} \bold{boolean ReadValue(const char *src);} \bold{virtual boolean ReadFile(AString *dest);} // read the entire file into dest // returns FALSE for failure \bold{virtual int OpenFile(int flags)} // return a file descriptor for the file (or -1) \{ const char *nm = *this; \ return (nm) ? open(nm, flags, 0644) : -1; \} \section{ASlotPtr} \bold{ASlotPtr()} \bold{ASlotPtr(atom *n)} \bold{ASlotPtr(void *s)} \bold{ASlotPtr(atom *n, void *s)} // There is no destructor to free the pointee \bold{ASlot &Default();} \bold{virtual operator void *()} \bold{virtual operator ATK *();} \bold{virtual ASlot &operator=(void *s) }\ \bold{virtual ASlot &operator=(long s);} \bold{virtual ASlot &operator=(int s)} \bold{void WriteValue(AString *dest);} // Derived classes MUST override WriteValue & ReadValue. \bold{boolean EatAvalue(const avalue *v);} \bold{boolean EatATK(const ATK *obj);} \section{ASlotATK} sole advantage is that it is convertible to an ATK* value there is no test to ensure that value really is ATK* \bold{ASlotATK()} \bold{ASlotATK(ATK *s)} \bold{ASlotATK(atom *n)} \bold{ASlotATK(atom *n, ATK *s) }\ \bold{operator ATK *()} \bold{operator figure *();} \bold{operator text *();} \bold{operator dataobject *();} \bold{ASlot &operator= (ATK *s) }\ \bold{boolean EatAvalue(const avalue *v);} \bold{boolean EatATK(const ATK *obj);} \section{ASlotDataObj} \bold{ASlotDataObj() \{ val.obj = NULL; \}} \bold{ASlotDataObj(dataobject *s) }\ \bold{ASlotDataObj(atom *n) }\ \bold{ASlotDataObj(atom *n, dataobject *s) \bold{virtual ~ASlotDataObj();} \bold{ASlot &Default();} }\ \bold{operator dataobject *() }\ \bold{ASlot &operator=(const void *a) }\ \bold{ASlot &operator=(dataobject *s);} \bold{ASlot &operator=(ASlot *src); }\ \bold{void WriteValue(AString *dest);} \bold{boolean ReadValue(const char *src);} \bold{virtual boolean EatATK(const ATK *obj);} \section{ASlotFigure} \bold{ASlotFigure()} \bold{ASlotFigure(atom *n)} \bold{ASlotFigure(figure *s)} \bold{ASlotFigure(atom *n, figure *s) }\ \bold{operator figure *()} \bold{ASlot &operator=(figure *s);} \bold{virtual ASlot &operator=(ASlot *src);} \bold{virtual boolean EatATK(const ATK *obj);} \section{ASlotFunction} can assign: aaction * proctable_Entry * char * If string begins with "proc:", \ the name is that of a proctable function. Otherwise, sets to Default. the aaction remains owned by the caller, but the value must not be deleted until the callee is finished with (UGH) \section{ASlotColor} \section{ASlotBool} \section{ASlotFont} \subsection{Function Call} An aaction value is a function and can be called in one of these forms: aaction(obj) aaction(obj, inflex) aaction(obj, inflex, outflex); An inflex may be a single value, or "avalueflex()|" followed by a sequence of values separated with '|'. The outflex should be an empty avalueflex. It will be assigned the return values(s). If there are any return values, the first is returned by the function call in the form of an avalue. Suppose we have ASlotFunction f; avalueflex out; then we can make these calls (*f)() // no object, no arguments, no result (*f)(this) (*f)(this, 9L) // pass only an (ATK *) object (maybe NULL) // pass an (ATK *) object & another arg (*f)(this, avalueflex()|9L|2) \ // pass an (ATK *) object and multiple arguments (*f)(this, 9L, out) // pass an (ATK *) object and an argument // expect back one or more values in 'out' The use of 'L' after integers avoids an ambiguity with real values. alternative is to use a cast: (int)9. \bold{ASlotFunction();} \bold{ASlotFunction(atom *n);} \bold{ASlotFunction(aaction *s);} \bold{ASlotFunction(atom *n, aaction *s);} \bold{virtual ~ASlotFunction() }\ \bold{ASlot &Default();} \bold{operator aaction *()} \bold{ASlot &operator=(const void *a) }\ \bold{ASlot &operator=(const aaction *a);} \bold{ASlot &operator=(proctable_Entry *p);} \bold{ASlot &operator=(const char *s);} \bold{ASlot &operator=(const ASlotFunction *s);} \bold{ASlot &operator=(const ASlotString *s);} \bold{ASlot &operator=(const ASlotFile *s);} \bold{void WriteValue(AString *dest);} \bold{boolean ReadValue(const char *src);} \bold{boolean EatAaction(const aaction *act);} The \bold{boolean EatATK(const ATK *obj);} \begindata{bp,538912840} Version 2 n 0 \enddata{bp,538912840} \view{bpv,538912840,1,0,0} \section{Adding New Types} A class derived from ASlot must have a name beginning "ASlot". It may override or supply the following items ATKregistryEntry *ATKregistry(); // ATK standard (Required in every derived class.) ASlotXxx(); // constructor Set `val` to its default value. The class may add additional \ constructors which have appropriate arguments and create \ values of the given type. If no name is given to the slot, it will have the name "NO_NAME". Before the constructor is called, the constructor for ASlot and other base classes will have been called. All the fields of the slot will be initialized as though the slot has the value zero. If it should have some other value, that value should be established by direct assignment to the val field. A constructor should NOT use one of the assignment functions to give a value to the slot because that will interfere with the 'isdefault' flag which has been set by the constructor for ASlot. ~ASlotXxx(); // destructor If the val field is assigned a pointer to data elsewhere, the destructor ~ASlotXxx must destroy that data. (Required only if data must be deallocated.) (The source field is destroyed by ASlot::~ASlot().) ASlot Default() Sets the slot to the default value for its type. This may be used for initialization, error handling, \ or whatever. Preferably, the default value does not \ require memory allocation or the presence of \ any particular library or server. (ASlot::ASlot initializes val.obj to NULL.) (Warning: Default returns an ASlot even though it actually retuirns the object that has been defaulted. A cast will be needed to get back to the object's type.) operator type() const // value access This returns 'val', but first checks or converts its type. (May be provided for any number of types.) inline ASlot &operator=(<appropriate type> src) \ Assigns the src value to the aslot. The implementation should use Assign to actually set values because it maintains flags and calls setit. (May be provided for any number of types.) (Warning: Operator= returns an ASlot even though it actually retuirns the object that has been defaulted. A cast will be needed to get back to the object's type.) void WriteValue(AString *dest) const; The dest will be empty initially. The method fills it with a string representing the value such that the same string can be parsed by ReadValue to produce the same value. (Must override in every derived class.) boolean ReadValue(const AString *src); Read characters from src and produce an appropriate val value. \ The value should be such that a subsequent WriteValue and ReadValue will reconstruct the same value. Return TRUE iff parse succeeds, else FALSE. (Must override in every derived class.) Derived classes may define additional conversions and operations on the type. Accessible field: val the value itself as an avalue_u. Other methods (especially operator=) should use Assign() to modify val. Most classes derived from ASlot will use the (void *) member in val's avalue_u. source string or object from which value is derived If the value stored in val is derived from some non-obvious string, that string can be presereved here for later writing out the data stream. The source has three options, which appear as alternatives in a union. The choice between them is made by the SourceType bits of the flags, values of which are SourceNone, SourceString, SourceFormula, and SourceFile. source.original - a string Example: the val for ASlotColor might be a \ class color object. Its file definition could be \ saved in source.original. source.formula - ASlotFunction The function computes the val value. source.file - ASlotFile The val value is fetched from the named file. ASlot protected avalue_u val; // the actual value ASlot &Assign(const avalue_u *src); // used by derived classes to perform assignment // uses setit, if defined // clears source ASlot &Assign(const ASlot *src); // uses setit; retains source virtual void CantTake(const char *invalid); // string is invalid for type virtual void CantTake(const ASlot *got); // got is an incorrect type for assignment to dest virtual void InvalidAs(const char *desiredtype) const; // slot cannot be converted to desiredtype There are additional methods which should be of use only to widget drivers like AWidget: ASlot::ASlotPrefix, GetSlotType, LoadType, \ ASlot::NewASlot, EnableFlags, DisableFlags, GetFlags, SetName, GetName, SetAssign, ()() virtual boolean EatString(const char *src) virtual boolean EatAaction(const aaction *act) virtual boolean EatATK(const ATK *obj) virtual boolean EatAvalue(const avalue *v) The EatXxxx methods have a value as an argument and conspire to transform that value into one suitable for storage in *this. They return FALSE if that cannot be done. In general, it is better to call EatXxxx(string) rather than ReadValue because EatXxxx \ interprets TAGS at the beginning of the string PROC: NESS: NESSEXPR: STRING: FILE: no prefix PROC: remainder of string is a proctable entry name NESS: remainder of string is a ness function NESSEXPR: remainder of string is a ness expression STRING: remainder of string is the string value FILE: remainder of string specifies a file no prefix: whole string is the string value \enddata{text,538611048}