URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
Compare Revisions
- This comparison shows the changes necessary to convert path
/or1k/trunk/insight/itcl/itk/generic
- from Rev 578 to Rev 1765
- ↔ Reverse comparison
Rev 578 → Rev 1765
/itk_option.c
0,0 → 1,586
/* |
* ------------------------------------------------------------------------ |
* PACKAGE: [incr Tk] |
* DESCRIPTION: Building mega-widgets with [incr Tcl] |
* |
* [incr Tk] provides a framework for building composite "mega-widgets" |
* using [incr Tcl] classes. It defines a set of base classes that are |
* specialized to create all other widgets. |
* |
* This file defines procedures used to manage mega-widget options |
* specified within class definitions. |
* |
* ======================================================================== |
* AUTHOR: Michael J. McLennan |
* Bell Labs Innovations for Lucent Technologies |
* mmclennan@lucent.com |
* http://www.tcltk.com/itcl |
* |
* RCS: $Id: itk_option.c,v 1.1.1.1 2002-01-16 10:24:47 markom Exp $ |
* ======================================================================== |
* Copyright (c) 1993-1998 Lucent Technologies, Inc. |
* ------------------------------------------------------------------------ |
* See the file "license.terms" for information on usage and redistribution |
* of this file, and for a DISCLAIMER OF ALL WARRANTIES. |
*/ |
#include "itk.h" |
|
/* |
* FORWARD DECLARATIONS |
*/ |
static char* ItkTraceClassDestroy _ANSI_ARGS_((ClientData cdata, |
Tcl_Interp *interp, char *name1, char *name2, int flags)); |
static Tcl_HashTable* ItkGetClassesWithOptInfo _ANSI_ARGS_(( |
Tcl_Interp *interp)); |
static void ItkFreeClassesWithOptInfo _ANSI_ARGS_((ClientData cdata, |
Tcl_Interp *interp)); |
|
|
/* |
* ------------------------------------------------------------------------ |
* Itk_ClassOptionDefineCmd() |
* |
* Invoked when a class definition is being parse to handle an |
* itk_option declaration. Adds a new option to a mega-widget |
* declaration, with some code that will be executed whenever the |
* option is changed via "configure". If there is already an existing |
* option by that name, then this new option is folded into the |
* existing option, but the <init> value is ignored. The X11 resource |
* database names must be consistent with the existing option. |
* |
* Handles the following syntax: |
* |
* itk_option define <switch> <resName> <resClass> <init> ?<config>? |
* |
* Returns TCL_OK/TCL_ERROR to indicate success/failure. |
* ------------------------------------------------------------------------ |
*/ |
/* ARGSUSED */ |
int |
Itk_ClassOptionDefineCmd(clientData, interp, objc, objv) |
ClientData clientData; /* class parser info */ |
Tcl_Interp *interp; /* current interpreter */ |
int objc; /* number of arguments */ |
Tcl_Obj *CONST objv[]; /* argument objects */ |
{ |
ItclObjectInfo *info = (ItclObjectInfo*)clientData; |
ItclClass *cdefn = (ItclClass*)Itcl_PeekStack(&info->cdefnStack); |
|
int newEntry; |
char *switchName, *resName, *resClass, *init, *config; |
ItkClassOptTable *optTable; |
Tcl_HashEntry *entry; |
ItkClassOption *opt; |
|
/* |
* Make sure that the arguments look right. The option switch |
* name must start with a '-'. |
*/ |
if (objc < 5 || objc > 6) { |
Tcl_WrongNumArgs(interp, 1, objv, |
"-switch resourceName resourceClass init ?config?"); |
return TCL_ERROR; |
} |
|
switchName = Tcl_GetStringFromObj(objv[1], (int*)NULL); |
if (*switchName != '-') { |
Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), |
"bad option name \"", switchName, "\": should be -", switchName, |
(char*)NULL); |
return TCL_ERROR; |
} |
if (strstr(switchName, ".")) { |
Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), |
"bad option name \"", switchName, "\": illegal character \".\"", |
(char*)NULL); |
return TCL_ERROR; |
} |
|
resName = Tcl_GetStringFromObj(objv[2], (int*)NULL); |
if (!islower((int)*resName)) { |
Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), |
"bad resource name \"", resName, |
"\": should start with a lower case letter", |
(char*)NULL); |
return TCL_ERROR; |
} |
|
resClass = Tcl_GetStringFromObj(objv[3], (int*)NULL); |
if (!isupper((int)*resClass)) { |
Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), |
"bad resource class \"", resClass, |
"\": should start with an upper case letter", |
(char*)NULL); |
return TCL_ERROR; |
} |
|
/* |
* Make sure that this option has not already been defined in |
* the context of this class. Options can be redefined in |
* other classes, but can only be defined once in a given |
* class. This ensures that there will be no confusion about |
* which option is being referenced if the configuration code |
* is redefined by a subsequent "body" command. |
*/ |
optTable = Itk_CreateClassOptTable(interp, cdefn); |
entry = Tcl_CreateHashEntry(&optTable->options, switchName, &newEntry); |
|
if (!newEntry) { |
Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), |
"option \"", switchName, "\" already defined in class \"", |
cdefn->fullname, "\"", |
(char*)NULL); |
return TCL_ERROR; |
} |
|
/* |
* Create a new option record and add it to the table for this |
* class. |
*/ |
init = Tcl_GetStringFromObj(objv[4], (int*)NULL); |
|
if (objc == 6) { |
config = Tcl_GetStringFromObj(objv[5], (int*)NULL); |
} else { |
config = NULL; |
} |
|
if (Itk_CreateClassOption(interp, cdefn, switchName, resName, resClass, |
init, config, &opt) != TCL_OK) { |
return TCL_ERROR; |
} |
|
Tcl_SetHashValue(entry, (ClientData)opt); |
Itk_OptListAdd(&optTable->order, entry); |
return TCL_OK; |
} |
|
|
/* |
* ------------------------------------------------------------------------ |
* Itk_ClassOptionIllegalCmd() |
* |
* Invoked when a class definition is being parse to handle an |
* itk_option declaration. Handles an "illegal" declaration like |
* "add" or "remove", which can only be used after a widget has |
* been created. Returns TCL_ERROR along with an error message. |
* ------------------------------------------------------------------------ |
*/ |
/* ARGSUSED */ |
int |
Itk_ClassOptionIllegalCmd(clientData, interp, objc, objv) |
ClientData clientData; /* class parser info */ |
Tcl_Interp *interp; /* current interpreter */ |
int objc; /* number of arguments */ |
Tcl_Obj *CONST objv[]; /* argument objects */ |
{ |
char *op = Tcl_GetStringFromObj(objv[0], (int*)NULL); |
|
Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), |
"can only ", op, " options for a specific widget\n", |
"(move this command into the constructor)", |
(char*)NULL); |
|
return TCL_ERROR; |
} |
|
|
/* |
* ------------------------------------------------------------------------ |
* Itk_ConfigClassOption() |
* |
* Invoked whenever a class-based configuration option has been |
* configured with a new value. If the option has any extra code |
* associated with it, the code is invoked at this point to bring |
* the widget up-to-date. |
* |
* Returns TCL_OK on success, or TCL_ERROR (along with an error |
* message in the interpreter) if anything goes wrong. |
* ------------------------------------------------------------------------ |
*/ |
/* ARGSUSED */ |
int |
Itk_ConfigClassOption(interp, contextObj, cdata, newval) |
Tcl_Interp *interp; /* interpreter managing the class */ |
ItclObject *contextObj; /* object being configured */ |
ClientData cdata; /* class option */ |
char *newval; /* new value for this option */ |
{ |
ItkClassOption *opt = (ItkClassOption*)cdata; |
int result = TCL_OK; |
ItclMemberCode *mcode; |
|
/* |
* If the option has any config code, execute it now. |
* Make sure that the namespace context is set up correctly. |
*/ |
mcode = opt->member->code; |
if (mcode && mcode->procPtr->bodyPtr) { |
result = Itcl_EvalMemberCode(interp, (ItclMemberFunc*)NULL, |
opt->member, contextObj, 0, (Tcl_Obj**)NULL); |
} |
return result; |
} |
|
|
/* |
* ------------------------------------------------------------------------ |
* Itk_CreateClassOptTable() |
* |
* Finds or creates an option table which will contain all of the |
* class-based configuration options for a mega-widget. These are |
* the options included in the class definition which add new behavior |
* to the mega-widget. |
* |
* This table is automatically deleted by ItkTraceClassDestroy |
* whenever the class namespace is destroyed. The "unset" operation |
* of a private class variable is used to detect the destruction of |
* the namespace. |
* |
* Returns a pointer to an option table which will contain pointers to |
* ItkClassOption records. |
* ------------------------------------------------------------------------ |
*/ |
ItkClassOptTable* |
Itk_CreateClassOptTable(interp, cdefn) |
Tcl_Interp *interp; /* interpreter managing the class */ |
ItclClass *cdefn; /* class definition */ |
{ |
int newEntry, result; |
Tcl_HashTable *itkClasses; |
Tcl_HashEntry *entry; |
ItkClassOptTable *optTable; |
Tcl_CallFrame frame; |
|
/* |
* Look for the specified class definition in the table. |
* If it does not yet exist, then create a new slot for it. |
* When a table is created for the first time, add a |
* special sentinel variable "_itk_option_data" to the |
* class namespace, and put a trace on this variable. |
* Whenever it is destroyed, have it delete the option table |
* for this class. |
*/ |
itkClasses = ItkGetClassesWithOptInfo(interp); |
|
entry = Tcl_CreateHashEntry(itkClasses, (char*)cdefn, &newEntry); |
if (newEntry) { |
optTable = (ItkClassOptTable*)ckalloc(sizeof(ItkClassOptTable)); |
Tcl_InitHashTable(&optTable->options, TCL_STRING_KEYS); |
Itk_OptListInit(&optTable->order, &optTable->options); |
|
Tcl_SetHashValue(entry, (ClientData)optTable); |
|
result = Tcl_PushCallFrame(interp, &frame, |
cdefn->namesp, /* isProcCallFrame */ 0); |
|
if (result == TCL_OK) { |
Tcl_TraceVar(interp, "_itk_option_data", |
(TCL_TRACE_UNSETS | TCL_NAMESPACE_ONLY), |
ItkTraceClassDestroy, (ClientData)cdefn); |
Tcl_PopCallFrame(interp); |
} |
} |
else { |
optTable = (ItkClassOptTable*)Tcl_GetHashValue(entry); |
} |
return optTable; |
} |
|
|
/* |
* ------------------------------------------------------------------------ |
* Itk_FindClassOptTable() |
* |
* Looks for an option table containing all of the class-based |
* configuration options for a mega-widget. These are the options |
* included in a class definition which add new behavior to the |
* mega-widget. |
* |
* Returns a pointer to an option table which will contain pointers to |
* Itk_ClassOption records. If a table does not exist for this class, |
* this returns NULL. |
* ------------------------------------------------------------------------ |
*/ |
ItkClassOptTable* |
Itk_FindClassOptTable(cdefn) |
ItclClass *cdefn; /* class definition */ |
{ |
Tcl_HashTable *itkClasses; |
Tcl_HashEntry *entry; |
|
/* |
* Look for the specified class definition in the table. |
*/ |
itkClasses = ItkGetClassesWithOptInfo(cdefn->interp); |
entry = Tcl_FindHashEntry(itkClasses, (char*)cdefn); |
if (entry) { |
return (ItkClassOptTable*)Tcl_GetHashValue(entry); |
} |
return NULL; |
} |
|
|
/* |
* ------------------------------------------------------------------------ |
* ItkTraceClassDestroy() |
* |
* Invoked automatically whenever the "_itk_option_data" variable |
* is destroyed within a class namespace. This should be a signal |
* that the namespace is being destroyed. |
* |
* Releases any option data that exists for the class. |
* |
* Returns NULL on success, or a pointer to a string describing any |
* error that is encountered. |
* ------------------------------------------------------------------------ |
*/ |
/* ARGSUSED */ |
static char* |
ItkTraceClassDestroy(cdata, interp, name1, name2, flags) |
ClientData cdata; /* class definition data */ |
Tcl_Interp *interp; /* interpreter managing the class */ |
char *name1; /* name of variable involved in trace */ |
char *name2; /* name of array element within variable */ |
int flags; /* flags describing trace */ |
{ |
ItclClass *cdefn = (ItclClass*)cdata; |
|
Tcl_HashTable *itkClasses; |
Tcl_HashEntry *entry; |
ItkClassOptTable *optTable; |
Tcl_HashSearch place; |
ItkClassOption *opt; |
|
/* |
* Look for the specified class definition in the table. |
* If it is found, delete all the option records and tear |
* down the table. |
*/ |
itkClasses = ItkGetClassesWithOptInfo(cdefn->interp); |
entry = Tcl_FindHashEntry(itkClasses, (char*)cdefn); |
if (entry) { |
optTable = (ItkClassOptTable*)Tcl_GetHashValue(entry); |
Tcl_DeleteHashEntry(entry); |
|
entry = Tcl_FirstHashEntry(&optTable->options, &place); |
while (entry) { |
opt = (ItkClassOption*)Tcl_GetHashValue(entry); |
Itk_DelClassOption(opt); |
entry = Tcl_NextHashEntry(&place); |
} |
Tcl_DeleteHashTable(&optTable->options); |
Itk_OptListFree(&optTable->order); |
ckfree((char*)optTable); |
} |
return NULL; |
} |
|
|
/* |
* ------------------------------------------------------------------------ |
* Itk_CreateClassOption() |
* |
* Creates the data representing a configuration option for an |
* Archetype mega-widget. This record represents an option included |
* in the class definition. It adds new behavior to the mega-widget |
* class. |
* |
* If successful, returns TCL_OK along with a pointer to the option |
* record. Returns TCL_ERROR (along with an error message in the |
* interpreter) if anything goes wrong. |
* ------------------------------------------------------------------------ |
*/ |
int |
Itk_CreateClassOption(interp, cdefn, switchName, resName, resClass, |
defVal, config, optPtr) |
|
Tcl_Interp *interp; /* interpreter managing the class */ |
ItclClass *cdefn; /* class containing this option */ |
char *switchName; /* name of command-line switch */ |
char *resName; /* resource name in X11 database */ |
char *resClass; /* resource class name in X11 database */ |
char *defVal; /* last-resort default value */ |
char *config; /* configuration code */ |
ItkClassOption **optPtr; /* returns: option record */ |
{ |
ItkClassOption *opt; |
ItclMemberCode *mcode; |
|
/* |
* If this option has any "config" code, then try to create |
* an implementation for it. |
*/ |
if (config) { |
if (Itcl_CreateMemberCode(interp, cdefn, (char*)NULL, config, |
&mcode) != TCL_OK) { |
|
return TCL_ERROR; |
} |
Itcl_PreserveData((ClientData)mcode); |
Itcl_EventuallyFree((ClientData)mcode, Itcl_DeleteMemberCode); |
} |
else { |
mcode = NULL; |
} |
|
/* |
* Create the record to represent this option. |
*/ |
opt = (ItkClassOption*)ckalloc(sizeof(ItkClassOption)); |
opt->member = Itcl_CreateMember(interp, cdefn, switchName); |
opt->member->code = mcode; |
|
opt->resName = (char*)ckalloc((unsigned)(strlen(resName)+1)); |
strcpy(opt->resName, resName); |
|
opt->resClass = (char*)ckalloc((unsigned)(strlen(resClass)+1)); |
strcpy(opt->resClass, resClass); |
|
opt->init = (char*)ckalloc((unsigned)(strlen(defVal)+1)); |
strcpy(opt->init, defVal); |
|
*optPtr = opt; |
return TCL_OK; |
} |
|
/* |
* ------------------------------------------------------------------------ |
* Itk_FindClassOption() |
* |
* Searches for a class-based configuration option for an Archetype |
* mega-widget. The specified name is treated as the "switch" name |
* (e.g., "-option"), but this procedure will recognize it even without |
* the leading "-". |
* |
* If an option is found that was defined in the specified class, |
* then this procedure returns a pointer to the option definition. |
* Otherwise, it returns NULL. |
* ------------------------------------------------------------------------ |
*/ |
ItkClassOption* |
Itk_FindClassOption(cdefn, switchName) |
ItclClass *cdefn; /* class containing this option */ |
char *switchName; /* name of command-line switch */ |
{ |
ItkClassOption *opt = NULL; |
|
Tcl_DString buffer; |
ItkClassOptTable *optTable; |
Tcl_HashEntry *entry; |
|
/* |
* If the switch does not have a leading "-", add it on. |
*/ |
Tcl_DStringInit(&buffer); |
if (*switchName != '-') { |
Tcl_DStringAppend(&buffer, "-", -1); |
Tcl_DStringAppend(&buffer, switchName, -1); |
switchName = Tcl_DStringValue(&buffer); |
} |
|
/* |
* Look for the option table for the specified class, and check |
* for the requested switch. |
*/ |
optTable = Itk_FindClassOptTable(cdefn); |
if (optTable) { |
entry = Tcl_FindHashEntry(&optTable->options, switchName); |
if (entry) { |
opt = (ItkClassOption*)Tcl_GetHashValue(entry); |
} |
} |
Tcl_DStringFree(&buffer); |
return opt; |
} |
|
/* |
* ------------------------------------------------------------------------ |
* Itk_DelClassOption() |
* |
* Destroys a configuration option previously created by |
* Itk_CreateClassOption(). |
* ------------------------------------------------------------------------ |
*/ |
void |
Itk_DelClassOption(opt) |
ItkClassOption *opt; /* pointer to option data */ |
{ |
Itcl_DeleteMember(opt->member); |
ckfree(opt->resName); |
ckfree(opt->resClass); |
ckfree(opt->init); |
|
ckfree((char*)opt); |
} |
|
|
/* |
* ------------------------------------------------------------------------ |
* ItkGetClassesWithOptInfo() |
* |
* Returns a pointer to a hash table containing the list of registered |
* classes in the specified interpreter. If the hash table does not |
* already exist, it is created. |
* ------------------------------------------------------------------------ |
*/ |
static Tcl_HashTable* |
ItkGetClassesWithOptInfo(interp) |
Tcl_Interp *interp; /* interpreter handling this registration */ |
{ |
Tcl_HashTable* classesTable; |
|
/* |
* If the registration table does not yet exist, then create it. |
*/ |
classesTable = (Tcl_HashTable*)Tcl_GetAssocData(interp, |
"itk_classesWithOptInfo", (Tcl_InterpDeleteProc**)NULL); |
|
if (!classesTable) { |
classesTable = (Tcl_HashTable*)ckalloc(sizeof(Tcl_HashTable)); |
Tcl_InitHashTable(classesTable, TCL_ONE_WORD_KEYS); |
Tcl_SetAssocData(interp, "itk_classesWithOptInfo", |
ItkFreeClassesWithOptInfo, (ClientData)classesTable); |
} |
return classesTable; |
} |
|
/* |
* ------------------------------------------------------------------------ |
* ItkFreeClassesWithOptInfo() |
* |
* When an interpreter is deleted, this procedure is called to |
* free up the associated data created by ItkGetClassesWithOptInfo. |
* ------------------------------------------------------------------------ |
*/ |
static void |
ItkFreeClassesWithOptInfo(clientData, interp) |
ClientData clientData; /* associated data */ |
Tcl_Interp *interp; /* interpreter being freed */ |
{ |
Tcl_HashTable *tablePtr = (Tcl_HashTable*)clientData; |
Tcl_HashSearch place, place2; |
Tcl_HashEntry *entry, *entry2; |
ItkClassOptTable *optTable; |
ItkClassOption *opt; |
|
entry = Tcl_FirstHashEntry(tablePtr, &place); |
while (entry) { |
optTable = (ItkClassOptTable*)Tcl_GetHashValue(entry); |
|
entry2 = Tcl_FirstHashEntry(&optTable->options, &place2); |
while (entry2) { |
opt = (ItkClassOption*)Tcl_GetHashValue(entry2); |
Itk_DelClassOption(opt); |
entry2 = Tcl_NextHashEntry(&place2); |
} |
Tcl_DeleteHashTable(&optTable->options); |
Itk_OptListFree(&optTable->order); |
ckfree((char*)optTable); |
|
entry = Tcl_NextHashEntry(&place); |
} |
|
Tcl_DeleteHashTable(tablePtr); |
ckfree((char*)tablePtr); |
} |
itk_option.c
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: itk_util.c
===================================================================
--- itk_util.c (nonexistent)
+++ itk_util.c (revision 1765)
@@ -0,0 +1,200 @@
+/*
+ * ------------------------------------------------------------------------
+ * PACKAGE: [incr Tk]
+ * DESCRIPTION: Building mega-widgets with [incr Tcl]
+ *
+ * [incr Tk] provides a framework for building composite "mega-widgets"
+ * using [incr Tcl] classes. It defines a set of base classes that are
+ * specialized to create all other widgets.
+ *
+ * This part defines some utility procedures that are useful for
+ * [incr Tk].
+ *
+ * ========================================================================
+ * AUTHOR: Michael J. McLennan
+ * Bell Labs Innovations for Lucent Technologies
+ * mmclennan@lucent.com
+ * http://www.tcltk.com/itcl
+ *
+ * RCS: $Id: itk_util.c,v 1.1.1.1 2002-01-16 10:24:47 markom Exp $
+ * ========================================================================
+ * Copyright (c) 1993-1998 Lucent Technologies, Inc.
+ * ------------------------------------------------------------------------
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+#include "itk.h"
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itk_OptListInit()
+ *
+ * Initializes an ordered option list, allocating a certain amount of
+ * memory for an initial option list.
+ * ------------------------------------------------------------------------
+ */
+void
+Itk_OptListInit(olist, options)
+ ItkOptList *olist; /* list to be initialized */
+ Tcl_HashTable *options; /* table containing the real option entries */
+{
+ olist->options = options;
+ olist->len = 0;
+ olist->max = 10;
+ olist->list = (Tcl_HashEntry**)ckalloc(
+ (unsigned)(olist->max*sizeof(Tcl_HashEntry*))
+ );
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itk_OptListFree()
+ *
+ * Frees an ordered option list created by Itk_OptListInit().
+ * This only frees the memory associated with the list, not the
+ * list itself.
+ * ------------------------------------------------------------------------
+ */
+void
+Itk_OptListFree(olist)
+ ItkOptList *olist; /* list to be freed */
+{
+ ckfree((char*)olist->list);
+ olist->len = olist->max = 0;
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itk_OptListAdd()
+ *
+ * Adds the hash table entry for an option like '-background' to an
+ * ordered list of options. The list is kept in alphabetical order,
+ * so that it can be searched quickly and printed out in order.
+ * ------------------------------------------------------------------------
+ */
+void
+Itk_OptListAdd(olist, entry)
+ ItkOptList *olist; /* ordered list */
+ Tcl_HashEntry *entry; /* entry to be added to the list */
+{
+ int i, first, last, cmp, pos, size;
+ Tcl_HashEntry** newOrder;
+ char *swname, *optname;
+
+ /*
+ * Make sure that the option list is big enough. Resize
+ * if needed.
+ */
+ if (olist->len >= olist->max) {
+ size = olist->max*sizeof(Tcl_HashEntry*);
+ newOrder = (Tcl_HashEntry**)ckalloc((unsigned)2*size);
+ memcpy((VOID*)newOrder, (VOID*)olist->list, (size_t)size);
+ ckfree((char*)olist->list);
+
+ olist->list = newOrder;
+ olist->max *= 2;
+ }
+
+ /*
+ * Perform a binary search to find the option switch quickly.
+ */
+ first = 0;
+ last = olist->len-1;
+ swname = Tcl_GetHashKey(olist->options, entry) + 1;
+
+ while (last >= first) {
+ pos = (first+last)/2;
+ optname = Tcl_GetHashKey(olist->options, olist->list[pos]) + 1;
+ if (*swname == *optname) {
+ cmp = strcmp(swname, optname);
+ if (cmp == 0) {
+ break; /* found it! */
+ }
+ }
+ else if (*swname < *optname) {
+ cmp = -1;
+ }
+ else {
+ cmp = 1;
+ }
+
+ if (cmp > 0)
+ first = pos+1;
+ else
+ last = pos-1;
+ }
+
+ /*
+ * If a matching entry was not found, then insert one.
+ */
+ if (last < first) {
+ pos = first;
+
+ for (i=olist->len; i > pos; i--) {
+ olist->list[i] = olist->list[i-1];
+ }
+ olist->list[pos] = entry;
+ olist->len++;
+ }
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itk_OptListRemove()
+ *
+ * Removes a hash table entry from an ordered list of options.
+ * This negates the action of Itk_OptionListAdd(), and is usually
+ * called when an option is completely removed from a mega-widget.
+ * This should be called before the entry is removed from the
+ * real option table.
+ * ------------------------------------------------------------------------
+ */
+void
+Itk_OptListRemove(olist, entry)
+ ItkOptList *olist; /* ordered list */
+ Tcl_HashEntry *entry; /* entry to be removed from the list */
+{
+ int pos = 0;
+ int i, first, last, cmp;
+ char *swname, *optname;
+
+ first = 0;
+ last = olist->len-1;
+ swname = Tcl_GetHashKey(olist->options, entry) + 1;
+
+ while (last >= first) {
+ pos = (first+last)/2;
+ optname = Tcl_GetHashKey(olist->options, olist->list[pos]) + 1;
+ if (*swname == *optname) {
+ cmp = strcmp(swname, optname);
+ if (cmp == 0) {
+ break; /* found it! */
+ }
+ }
+ else if (*swname < *optname) {
+ cmp = -1;
+ }
+ else {
+ cmp = 1;
+ }
+
+ if (cmp > 0)
+ first = pos+1;
+ else
+ last = pos-1;
+ }
+
+ /*
+ * If a matching entry was found, then remove it.
+ */
+ if (last >= first) {
+ olist->len--;
+ for (i=pos; i < olist->len; i++) {
+ olist->list[i] = olist->list[i+1];
+ }
+ }
+}
itk_util.c
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: itk_archetype.c
===================================================================
--- itk_archetype.c (nonexistent)
+++ itk_archetype.c (revision 1765)
@@ -0,0 +1,4172 @@
+/*
+ * ------------------------------------------------------------------------
+ * PACKAGE: [incr Tk]
+ * DESCRIPTION: Building mega-widgets with [incr Tcl]
+ *
+ * [incr Tk] provides a framework for building composite "mega-widgets"
+ * using [incr Tcl] classes. It defines a set of base classes that are
+ * specialized to create all other widgets.
+ *
+ * This part adds C implementations for some of the methods in the
+ * base class itk::Archetype.
+ *
+ * Itk_ArchComponentCmd <=> itk_component
+ * Itk_ArchOptionCmd <=> itk_option
+ * Itk_ArchInitCmd <=> itk_initialize
+ * Itk_ArchCompAccessCmd <=> component
+ * Itk_ArchConfigureCmd <=> configure
+ * Itk_ArchCgetCmd <=> cget
+ *
+ * Itk_ArchInitOptsCmd <=> _initOptionInfo (used to set things up)
+ * Itk_ArchDeleteOptsCmd <=> _deleteOptionInfo (used to clean things up)
+ *
+ * ========================================================================
+ * AUTHOR: Michael J. McLennan
+ * Bell Labs Innovations for Lucent Technologies
+ * mmclennan@lucent.com
+ * http://www.tcltk.com/itcl
+ *
+ * RCS: $Id: itk_archetype.c,v 1.1.1.1 2002-01-16 10:24:47 markom Exp $
+ * ========================================================================
+ * Copyright (c) 1993-1998 Lucent Technologies, Inc.
+ * ------------------------------------------------------------------------
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+#include
+#include "itk.h"
+
+/*
+ * Info associated with each Archetype mega-widget:
+ */
+typedef struct ArchInfo {
+ ItclObject *itclObj; /* object containing this info */
+ Tk_Window tkwin; /* window representing this mega-widget */
+ Tcl_HashTable components; /* list of all mega-widget components */
+ Tcl_HashTable options; /* list of all mega-widget options */
+ ItkOptList order; /* gives ordering of options */
+} ArchInfo;
+
+/*
+ * Each component widget in an Archetype mega-widget:
+ */
+typedef struct ArchComponent {
+ ItclMember *member; /* contains protection level for this comp */
+ Tcl_Command accessCmd; /* access command for component widget */
+ Tk_Window tkwin; /* Tk window for this component widget */
+} ArchComponent;
+
+/*
+ * Each option in an Archetype mega-widget:
+ */
+typedef struct ArchOption {
+ char *switchName; /* command-line switch for this option */
+ char *resName; /* resource name in X11 database */
+ char *resClass; /* resource class name in X11 database */
+ char *init; /* initial value for option */
+ int flags; /* flags representing option state */
+ Itcl_List parts; /* parts relating to this option */
+} ArchOption;
+
+/*
+ * Flag bits for ArchOption state:
+ */
+#define ITK_ARCHOPT_INIT 0x01 /* option has been initialized */
+
+/*
+ * Various parts of a composite option in an Archetype mega-widget:
+ */
+typedef int (Itk_ConfigOptionPartProc) _ANSI_ARGS_((Tcl_Interp *interp,
+ ItclObject *contextObj, ClientData cdata, char* newVal));
+
+typedef struct ArchOptionPart {
+ ClientData clientData; /* data associated with this part */
+ Itk_ConfigOptionPartProc *configProc; /* update when new vals arrive */
+ Tcl_CmdDeleteProc *deleteProc; /* clean up after clientData */
+
+ ClientData from; /* token that indicates who
+ * contributed this option part */
+} ArchOptionPart;
+
+
+/*
+ * Info kept by the itk::option-parser namespace and shared by
+ * all option processing commands:
+ */
+typedef struct ArchMergeInfo {
+ Tcl_HashTable usualCode; /* usual option handling code for the
+ * various widget classes */
+
+ ArchInfo *archInfo; /* internal option info for mega-widget */
+ ArchComponent *archComp; /* component being merged into mega-widget */
+ Tcl_HashTable *optionTable; /* table of valid configuration options
+ * for component being merged */
+} ArchMergeInfo;
+
+/*
+ * Used to capture component widget configuration options when a
+ * new component is being merged into a mega-widget:
+ */
+typedef struct GenericConfigOpt {
+ char *switchName; /* command-line switch for this option */
+ char *resName; /* resource name in X11 database */
+ char *resClass; /* resource class name in X11 database */
+ char *init; /* initial value for this option */
+ char *value; /* current value for this option */
+ char **storage; /* storage for above strings */
+
+ ArchOption *integrated; /* integrated into this mega-widget option */
+ ArchOptionPart *optPart; /* integrated as this option part */
+} GenericConfigOpt;
+
+/*
+ * Options that are propagated by a "configure" method:
+ */
+typedef struct ConfigCmdline {
+ Tcl_Obj *objv[4]; /* objects representing "configure" command */
+} ConfigCmdline;
+
+
+/*
+ * FORWARD DECLARATIONS
+ */
+static void Itk_DelMergeInfo _ANSI_ARGS_((char* cdata));
+
+static int Itk_ArchInitOptsCmd _ANSI_ARGS_((ClientData cdata,
+ Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+static void Itk_DelArchInfo _ANSI_ARGS_((ClientData cdata));
+static int Itk_ArchDeleteOptsCmd _ANSI_ARGS_((ClientData cdata,
+ Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+
+static int Itk_ArchComponentCmd _ANSI_ARGS_((ClientData cdata,
+ Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+static int Itk_ArchCompAddCmd _ANSI_ARGS_((ClientData cdata,
+ Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+static int Itk_ArchCompDeleteCmd _ANSI_ARGS_((ClientData cdata,
+ Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+static int Itk_ArchOptKeepCmd _ANSI_ARGS_((ClientData cdata,
+ Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+static int Itk_ArchOptIgnoreCmd _ANSI_ARGS_((ClientData cdata,
+ Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+static int Itk_ArchOptRenameCmd _ANSI_ARGS_((ClientData cdata,
+ Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+static int Itk_ArchOptUsualCmd _ANSI_ARGS_((ClientData cdata,
+ Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+
+static int Itk_ArchInitCmd _ANSI_ARGS_((ClientData cdata,
+ Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+static int Itk_ArchOptionCmd _ANSI_ARGS_((ClientData cdata,
+ Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+static int Itk_ArchOptionAddCmd _ANSI_ARGS_((ClientData cdata,
+ Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+static int Itk_ArchOptionRemoveCmd _ANSI_ARGS_((ClientData cdata,
+ Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+
+static int Itk_ArchCompAccessCmd _ANSI_ARGS_((ClientData cdata,
+ Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+static int Itk_ArchConfigureCmd _ANSI_ARGS_((ClientData cdata,
+ Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+static int Itk_ArchCgetCmd _ANSI_ARGS_((ClientData cdata,
+ Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+static int Itk_PropagateOption _ANSI_ARGS_((Tcl_Interp *interp,
+ ItclObject *contextObj, ClientData cdata, char *newval));
+static int Itk_PropagatePublicVar _ANSI_ARGS_((Tcl_Interp *interp,
+ ItclObject *contextObj, ClientData cdata, char *newval));
+
+static int Itk_ArchSetOption _ANSI_ARGS_((Tcl_Interp *interp,
+ ArchInfo *info, char *name, char *value));
+static int Itk_ArchConfigOption _ANSI_ARGS_((Tcl_Interp *interp,
+ ArchInfo *info, char *name, char *value));
+static void Itk_ArchOptConfigError _ANSI_ARGS_((Tcl_Interp *interp,
+ ArchInfo *info, ArchOption *archOpt));
+static void Itk_ArchOptAccessError _ANSI_ARGS_((Tcl_Interp *interp,
+ ArchInfo *info, ArchOption *archOpt));
+
+static int Itk_GetArchInfo _ANSI_ARGS_((Tcl_Interp *interp,
+ ItclObject* contextObj, ArchInfo **infoPtr));
+
+static ArchComponent* Itk_CreateArchComponent _ANSI_ARGS_((
+ Tcl_Interp *interp, ArchInfo *info, char *name,
+ ItclClass *cdefn, Tcl_Command accessCmd));
+static void Itk_DelArchComponent _ANSI_ARGS_((ArchComponent *archComp));
+
+static int Itk_GetArchOption _ANSI_ARGS_((Tcl_Interp *interp,
+ ArchInfo *info, char *switchName, char *resName, char *resClass,
+ char *defVal, char *currVal, ArchOption **aoPtr));
+static void Itk_InitArchOption _ANSI_ARGS_((Tcl_Interp *interp,
+ ArchInfo *info, ArchOption *archOpt, char *defVal,
+ char *currVal));
+static void Itk_DelArchOption _ANSI_ARGS_((ArchOption *archOpt));
+
+static ArchOptionPart* Itk_CreateOptionPart _ANSI_ARGS_((
+ Tcl_Interp *interp, ClientData cdata, Itk_ConfigOptionPartProc* cproc,
+ Tcl_CmdDeleteProc *dproc, ClientData from));
+static int Itk_AddOptionPart _ANSI_ARGS_((Tcl_Interp *interp,
+ ArchInfo *info, char *switchName, char *resName, char *resClass,
+ char *defVal, char *currVal, ArchOptionPart *optPart,
+ ArchOption **raOpt));
+static ArchOptionPart* Itk_FindArchOptionPart _ANSI_ARGS_((
+ ArchInfo *info, char *switchName, ClientData from));
+static int Itk_RemoveArchOptionPart _ANSI_ARGS_((ArchInfo *info,
+ char *switchName, ClientData from));
+static int Itk_IgnoreArchOptionPart _ANSI_ARGS_((ArchInfo *info,
+ GenericConfigOpt *opt));
+static void Itk_DelOptionPart _ANSI_ARGS_((ArchOptionPart *optPart));
+
+static ConfigCmdline* Itk_CreateConfigCmdline _ANSI_ARGS_((
+ Tcl_Interp *interp, Tcl_Command accessCmd, char *switchName));
+static void Itk_DeleteConfigCmdline _ANSI_ARGS_((ClientData cdata));
+
+static Tcl_HashTable* Itk_CreateGenericOptTable _ANSI_ARGS_((Tcl_Interp *interp,
+ char *options));
+static void Itk_DelGenericOptTable _ANSI_ARGS_((Tcl_HashTable *tPtr));
+
+static GenericConfigOpt* Itk_CreateGenericOpt _ANSI_ARGS_((Tcl_Interp *interp,
+ char *switchName, Tcl_Command accessCmd));
+static void Itk_DelGenericOpt _ANSI_ARGS_((GenericConfigOpt* opt));
+
+static Tcl_HashTable* ItkGetObjsWithArchInfo _ANSI_ARGS_((Tcl_Interp *interp));
+static void ItkFreeObjsWithArchInfo _ANSI_ARGS_((ClientData cdata,
+ Tcl_Interp *interp));
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itk_ArchetypeInit()
+ *
+ * Invoked by Itk_Init() whenever a new interpreter is created to
+ * declare the procedures used in the itk::Archetype base class.
+ * ------------------------------------------------------------------------
+ */
+int
+Itk_ArchetypeInit(interp)
+ Tcl_Interp *interp; /* interpreter to be updated */
+{
+ ArchMergeInfo *mergeInfo;
+ Tcl_Namespace *parserNs;
+
+ /*
+ * Declare all of the C routines that are integrated into
+ * the Archetype base class.
+ */
+ if (Itcl_RegisterObjC(interp,
+ "Archetype-init", Itk_ArchInitOptsCmd,
+ (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL) != TCL_OK ||
+
+ Itcl_RegisterObjC(interp,
+ "Archetype-delete", Itk_ArchDeleteOptsCmd,
+ (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL) != TCL_OK ||
+
+ Itcl_RegisterObjC(interp,
+ "Archetype-itk_component", Itk_ArchComponentCmd,
+ (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL) != TCL_OK ||
+
+ Itcl_RegisterObjC(interp,
+ "Archetype-itk_option", Itk_ArchOptionCmd,
+ (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL) != TCL_OK ||
+
+ Itcl_RegisterObjC(interp,
+ "Archetype-itk_initialize", Itk_ArchInitCmd,
+ (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL) != TCL_OK ||
+
+ Itcl_RegisterObjC(interp,
+ "Archetype-component", Itk_ArchCompAccessCmd,
+ (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL) != TCL_OK ||
+
+ Itcl_RegisterObjC(interp,
+ "Archetype-configure",Itk_ArchConfigureCmd,
+ (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL) != TCL_OK ||
+
+ Itcl_RegisterObjC(interp,
+ "Archetype-cget",Itk_ArchCgetCmd,
+ (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL) != TCL_OK) {
+
+ return TCL_ERROR;
+ }
+
+ /*
+ * Create the namespace containing the option parser commands.
+ */
+ mergeInfo = (ArchMergeInfo*)ckalloc(sizeof(ArchMergeInfo));
+ Tcl_InitHashTable(&mergeInfo->usualCode, TCL_STRING_KEYS);
+ mergeInfo->archInfo = NULL;
+ mergeInfo->archComp = NULL;
+ mergeInfo->optionTable = NULL;
+
+ parserNs = Tcl_CreateNamespace(interp, "::itk::option-parser",
+ (ClientData)mergeInfo, Itcl_ReleaseData);
+
+ if (!parserNs) {
+ Itk_DelMergeInfo((char*)mergeInfo);
+ Tcl_AddErrorInfo(interp, "\n (while initializing itk)");
+ return TCL_ERROR;
+ }
+ Itcl_PreserveData((ClientData)mergeInfo);
+ Itcl_EventuallyFree((ClientData)mergeInfo, Itk_DelMergeInfo);
+
+ Tcl_CreateObjCommand(interp, "::itk::option-parser::keep",
+ Itk_ArchOptKeepCmd,
+ (ClientData)mergeInfo, (Tcl_CmdDeleteProc*)NULL);
+
+ Tcl_CreateObjCommand(interp, "::itk::option-parser::ignore",
+ Itk_ArchOptIgnoreCmd,
+ (ClientData)mergeInfo, (Tcl_CmdDeleteProc*)NULL);
+
+ Tcl_CreateObjCommand(interp, "::itk::option-parser::rename",
+ Itk_ArchOptRenameCmd,
+ (ClientData)mergeInfo, (Tcl_CmdDeleteProc*)NULL);
+
+ Tcl_CreateObjCommand(interp, "::itk::option-parser::usual",
+ Itk_ArchOptUsualCmd,
+ (ClientData)mergeInfo, (Tcl_CmdDeleteProc*)NULL);
+
+ /*
+ * Add the "itk::usual" command to register option handling code.
+ */
+ Tcl_CreateObjCommand(interp, "::itk::usual", Itk_UsualCmd,
+ (ClientData)mergeInfo, Itcl_ReleaseData);
+ Itcl_PreserveData((ClientData)mergeInfo);
+
+ return TCL_OK;
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itk_DelMergeInfo()
+ *
+ * Destroys the "merge" info record shared by commands in the
+ * itk::option-parser namespace. Invoked automatically when the
+ * namespace containing the parsing commands is destroyed and there
+ * are no more uses of the data.
+ * ------------------------------------------------------------------------
+ */
+static void
+Itk_DelMergeInfo(cdata)
+ char* cdata; /* data to be destroyed */
+{
+ ArchMergeInfo *mergeInfo = (ArchMergeInfo*)cdata;
+
+ Tcl_HashEntry *entry;
+ Tcl_HashSearch place;
+ Tcl_Obj *codePtr;
+
+ assert(mergeInfo->optionTable == NULL);
+
+ entry = Tcl_FirstHashEntry(&mergeInfo->usualCode, &place);
+ while (entry) {
+ codePtr = (Tcl_Obj*)Tcl_GetHashValue(entry);
+ Tcl_DecrRefCount(codePtr);
+ entry = Tcl_NextHashEntry(&place);
+ }
+ Tcl_DeleteHashTable(&mergeInfo->usualCode);
+
+ ckfree((char*)mergeInfo);
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itk_ArchInitOptsCmd()
+ *
+ * Invoked by [incr Tcl] to handle the itk::Archetype::_initOptionInfo
+ * method. This method should be called out in the constructor for
+ * each object, to initialize the object so that it can be used with
+ * the other access methods in this file. Allocates some extra
+ * data associated with the object at the C-language level.
+ *
+ * Returns TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+Itk_ArchInitOptsCmd(dummy, interp, objc, objv)
+ ClientData dummy; /* unused */
+ Tcl_Interp *interp; /* current interpreter */
+ int objc; /* number of arguments */
+ Tcl_Obj *CONST objv[]; /* argument objects */
+{
+ int newEntry, result;
+ ArchInfo *info;
+ ItclClass *contextClass;
+ ItclObject *contextObj;
+ Tcl_HashTable *objsWithArchInfo;
+ Tcl_HashEntry *entry;
+ Command *cmdPtr;
+
+ if (objc != 1) {
+ Tcl_WrongNumArgs(interp, 1, objv, "");
+ return TCL_ERROR;
+ }
+
+ if (Itcl_GetContext(interp, &contextClass, &contextObj) != TCL_OK ||
+ !contextObj) {
+
+ char *token = Tcl_GetStringFromObj(objv[0], (int*)NULL);
+ Tcl_ResetResult(interp);
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "cannot use \"", token, "\" without an object context",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Create some archetype info for the current object and
+ * register it on the list of all known objects.
+ */
+ objsWithArchInfo = ItkGetObjsWithArchInfo(interp);
+
+ info = (ArchInfo*)ckalloc(sizeof(ArchInfo));
+ info->itclObj = contextObj;
+ info->tkwin = NULL; /* not known yet */
+ Tcl_InitHashTable(&info->components, TCL_STRING_KEYS);
+ Tcl_InitHashTable(&info->options, TCL_STRING_KEYS);
+ Itk_OptListInit(&info->order, &info->options);
+
+ entry = Tcl_CreateHashEntry(objsWithArchInfo, (char*)contextObj, &newEntry);
+ if (!newEntry) {
+ Itk_DelArchInfo( Tcl_GetHashValue(entry) );
+ }
+ Tcl_SetHashValue(entry, (ClientData)info);
+
+ /*
+ * Make sure that the access command for this object
+ * resides in the global namespace. If need be, move
+ * the command.
+ */
+ result = TCL_OK;
+ cmdPtr = (Command*)contextObj->accessCmd;
+
+ if (cmdPtr->nsPtr != (Namespace*)Tcl_GetGlobalNamespace(interp)) {
+ Tcl_Obj *oldNamePtr, *newNamePtr;
+
+ oldNamePtr = Tcl_NewStringObj((char*)NULL, 0);
+ Tcl_GetCommandFullName(interp, contextObj->accessCmd, oldNamePtr);
+ Tcl_IncrRefCount(oldNamePtr);
+
+ newNamePtr = Tcl_NewStringObj("::", -1);
+ Tcl_AppendToObj(newNamePtr,
+ Tcl_GetCommandName(interp, contextObj->accessCmd), -1);
+ Tcl_IncrRefCount(newNamePtr);
+
+ result = TclRenameCommand(interp,
+ Tcl_GetStringFromObj(oldNamePtr, (int*)NULL),
+ Tcl_GetStringFromObj(newNamePtr, (int*)NULL));
+
+ Tcl_DecrRefCount(oldNamePtr);
+ Tcl_DecrRefCount(newNamePtr);
+ }
+
+ return result;
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itk_DelArchInfo()
+ *
+ * Invoked when the option info associated with an itk::Archetype
+ * widget is no longer needed. This usually happens when a widget
+ * is destroyed. Frees the given bundle of data and removes it
+ * from the global list of Archetype objects.
+ * ------------------------------------------------------------------------
+ */
+static void
+Itk_DelArchInfo(cdata)
+ ClientData cdata; /* client data for Archetype objects */
+{
+ ArchInfo *info = (ArchInfo*)cdata;
+
+ Tcl_HashEntry *entry;
+ Tcl_HashSearch place;
+ ArchOption *archOpt;
+ ArchComponent *archComp;
+
+ /*
+ * Destroy all component widgets.
+ */
+ entry = Tcl_FirstHashEntry(&info->components, &place);
+ while (entry) {
+ archComp = (ArchComponent*)Tcl_GetHashValue(entry);
+ Itk_DelArchComponent(archComp);
+ entry = Tcl_NextHashEntry(&place);
+ }
+ Tcl_DeleteHashTable(&info->components);
+
+ /*
+ * Destroy all information associated with configuration options.
+ */
+ entry = Tcl_FirstHashEntry(&info->options, &place);
+ while (entry) {
+ archOpt = (ArchOption*)Tcl_GetHashValue(entry);
+ Itk_DelArchOption(archOpt);
+ entry = Tcl_NextHashEntry(&place);
+ }
+ Tcl_DeleteHashTable(&info->options);
+ Itk_OptListFree(&info->order);
+
+ ckfree((char*)info);
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itk_ArchDeleteOptsCmd()
+ *
+ * Invoked by [incr Tcl] to handle the itk::Archetype::_deleteOptionInfo
+ * method. This method should be called out in the destructor for each
+ * object, to clean up data allocated by Itk_ArchInitOptsCmd().
+ *
+ * Returns TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+Itk_ArchDeleteOptsCmd(dummy, interp, objc, objv)
+ ClientData dummy; /* unused */
+ Tcl_Interp *interp; /* current interpreter */
+ int objc; /* number of arguments */
+ Tcl_Obj *CONST objv[]; /* argument objects */
+{
+ ItclClass *contextClass;
+ ItclObject *contextObj;
+ Tcl_HashTable *objsWithArchInfo;
+ Tcl_HashEntry *entry;
+
+ if (objc != 1) {
+ Tcl_WrongNumArgs(interp, 1, objv, "");
+ return TCL_ERROR;
+ }
+ if (Itcl_GetContext(interp, &contextClass, &contextObj) != TCL_OK ||
+ !contextObj) {
+
+ char *token = Tcl_GetStringFromObj(objv[0], (int*)NULL);
+ Tcl_ResetResult(interp);
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "cannot use \"", token, "\" without an object context",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Find the info associated with this object.
+ * Destroy the data and remove it from the global list.
+ */
+ objsWithArchInfo = ItkGetObjsWithArchInfo(interp);
+ entry = Tcl_FindHashEntry(objsWithArchInfo, (char*)contextObj);
+
+ if (entry) {
+ Itk_DelArchInfo( Tcl_GetHashValue(entry) );
+ Tcl_DeleteHashEntry(entry);
+ }
+ return TCL_OK;
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itk_ArchComponentCmd()
+ *
+ * Invoked by [incr Tcl] to handle the itk::Archetype::itk_component
+ * method. Handles the following options:
+ *
+ * itk_component add ?-protected? ?-private? ?--? \
+ * ??
+ *
+ * itk_component delete ?...?
+ *
+ * Returns TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+Itk_ArchComponentCmd(dummy, interp, objc, objv)
+ ClientData dummy; /* unused */
+ Tcl_Interp *interp; /* current interpreter */
+ int objc; /* number of arguments */
+ Tcl_Obj *CONST objv[]; /* argument objects */
+{
+ char *cmd, *token, c;
+ int length;
+
+ /*
+ * Check arguments and handle the various options...
+ */
+ if (objc < 2) {
+ cmd = Tcl_GetStringFromObj(objv[0], (int*)NULL);
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "wrong # args: should be one of...\n",
+ " ", cmd, " add ?-protected? ?-private? ?--? name createCmds ?optionCmds?\n",
+ " ", cmd, " delete name ?name name...?",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+
+ token = Tcl_GetStringFromObj(objv[1], (int*)NULL);
+ c = *token;
+ length = strlen(token);
+
+ /*
+ * Handle: itk_component add...
+ */
+ if (c == 'a' && strncmp(token, "add", length) == 0) {
+ if (objc < 4) {
+ Tcl_WrongNumArgs(interp, 1, objv,
+ "add ?-protected? ?-private? ?--? name createCmds ?optionCmds?");
+ return TCL_ERROR;
+ }
+ return Itk_ArchCompAddCmd(dummy, interp, objc-1, objv+1);
+ }
+
+ /*
+ * Handle: itk_component delete...
+ */
+ else if (c == 'd' && strncmp(token, "delete", length) == 0) {
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "delete name ?name name...?");
+ return TCL_ERROR;
+ }
+ return Itk_ArchCompDeleteCmd(dummy, interp, objc-1, objv+1);
+ }
+
+ /*
+ * Flag any errors.
+ */
+ cmd = Tcl_GetStringFromObj(objv[0], (int*)NULL);
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "bad option \"", token,
+ "\": should be one of...\n",
+ " ", cmd, " add name createCmds ?optionCmds?\n",
+ " ", cmd, " delete name ?name name...?",
+ (char*)NULL);
+ return TCL_ERROR;
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itk_ArchCompAddCmd()
+ *
+ * Invoked by [incr Tcl] to handle the itk::Archetype::itk_component
+ * method. Adds a new component widget into the mega-widget,
+ * integrating its configuration options into the master list.
+ *
+ * itk_component add ?-protected? ?-private? ?--? \
+ *
+ *
+ * Returns TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+Itk_ArchCompAddCmd(dummy, interp, objc, objv)
+ ClientData dummy; /* unused */
+ Tcl_Interp *interp; /* current interpreter */
+ int objc; /* number of arguments */
+ Tcl_Obj *CONST objv[]; /* argument objects */
+{
+ Tcl_HashEntry *entry = NULL;
+ char *path = NULL;
+ ArchComponent *archComp = NULL;
+ ArchMergeInfo *mergeInfo = NULL;
+ Tcl_Obj *objNamePtr = NULL;
+ Tcl_Obj *tmpNamePtr = NULL;
+ Tcl_Obj *winNamePtr = NULL;
+ Tcl_Obj *hullNamePtr = NULL;
+ int pLevel = ITCL_PUBLIC;
+
+ int newEntry, result;
+ char *cmd, *token, *name, *resultStr;
+ Tcl_Namespace *parserNs;
+ ItclClass *contextClass, *ownerClass;
+ ItclObject *contextObj;
+ ArchInfo *info;
+ Tcl_CallFrame frame, *uplevelFramePtr, *oldFramePtr;
+ Tcl_Command accessCmd;
+ Tcl_Obj *objPtr;
+ Tcl_DString buffer;
+
+ /*
+ * Get the Archetype info associated with this widget.
+ */
+ if (Itcl_GetContext(interp, &contextClass, &contextObj) != TCL_OK ||
+ !contextObj) {
+
+ Tcl_ResetResult(interp);
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "cannot access components without an object context",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+
+ if (Itk_GetArchInfo(interp, contextObj, &info) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Look for options like "-protected" or "-private".
+ */
+ cmd = Tcl_GetStringFromObj(objv[0], (int*)NULL);
+
+ while (objc > 1) {
+ token = Tcl_GetStringFromObj(objv[1], (int*)NULL);
+ if (*token != '-') {
+ break;
+ }
+ else if (strcmp(token,"-protected") == 0) {
+ pLevel = ITCL_PROTECTED;
+ }
+ else if (strcmp(token,"-private") == 0) {
+ pLevel = ITCL_PRIVATE;
+ }
+ else if (strcmp(token,"--") == 0) {
+ objc--;
+ objv++;
+ break;
+ }
+ else {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "bad option \"", token,
+ "\": should be -private, -protected or --",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+ objc--;
+ objv++;
+ }
+
+ if (objc < 3 || objc > 4) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "wrong # args: should be \"", cmd,
+ " ?-protected? ?-private? ?--? name createCmds ?optionCmds?",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * See if a component already exists with the symbolic name.
+ */
+ name = Tcl_GetStringFromObj(objv[1], (int*)NULL);
+ entry = Tcl_CreateHashEntry(&info->components, name, &newEntry);
+ if (!newEntry) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "component \"", name, "\" already defined",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * If this component is the "hull" for the mega-widget, then
+ * move the object access command out of the way before
+ * creating the component, so it is not accidentally deleted.
+ */
+ Tcl_DStringInit(&buffer);
+
+ objNamePtr = Tcl_NewStringObj((char*)NULL, 0);
+ Tcl_GetCommandFullName(contextObj->classDefn->interp,
+ contextObj->accessCmd, objNamePtr);
+ Tcl_IncrRefCount(objNamePtr);
+
+ if (strcmp(name, "hull") == 0) {
+ tmpNamePtr = Tcl_NewStringObj((char*)NULL, 0);
+ Tcl_GetCommandFullName(contextObj->classDefn->interp,
+ contextObj->accessCmd, tmpNamePtr);
+ Tcl_AppendToObj(tmpNamePtr, "-widget-", -1);
+ Tcl_IncrRefCount(tmpNamePtr);
+
+ result = TclRenameCommand(interp,
+ Tcl_GetStringFromObj(objNamePtr, (int*)NULL),
+ Tcl_GetStringFromObj(tmpNamePtr, (int*)NULL));
+
+ if (result != TCL_OK) {
+ goto compFail;
+ }
+ }
+
+ /*
+ * Execute the to create the component widget.
+ * Do this one level up, in the scope of the calling routine.
+ */
+ uplevelFramePtr = _Tcl_GetCallFrame(interp, 1);
+ oldFramePtr = _Tcl_ActivateCallFrame(interp, uplevelFramePtr);
+
+ /* CYGNUS LOCAL - Fix for Tcl8.1 */
+#if TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION == 0
+ if (Tcl_EvalObj(interp, objv[2]) != TCL_OK) {
+#else
+ if (Tcl_EvalObj(interp, objv[2], 0) != TCL_OK) {
+#endif
+ /* END CYGNUS LOCAL */
+ goto compFail;
+ }
+
+ /*
+ * Take the result from the widget creation commands as the
+ * path name for the new component. Make a local copy of
+ * this, since the interpreter will get used in the mean time.
+ */
+ resultStr = Tcl_GetStringResult(interp);
+ path = (char*)ckalloc((unsigned)(strlen(resultStr)+1));
+ strcpy(path, resultStr);
+
+ /*
+ * Look for the access command token in the context of the
+ * calling namespace. By-pass any protection at this point.
+ */
+ accessCmd = Tcl_FindCommand(interp, path, (Tcl_Namespace*)NULL,
+ /* flags */ 0);
+
+ if (!accessCmd) {
+ Tcl_ResetResult(interp);
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "cannot find component access command \"",
+ path, "\" for component \"", name, "\"",
+ (char*)NULL);
+ goto compFail;
+ }
+
+ winNamePtr = Tcl_NewStringObj((char*)NULL, 0);
+ Tcl_GetCommandFullName(interp, accessCmd, winNamePtr);
+ Tcl_IncrRefCount(winNamePtr);
+
+ (void) _Tcl_ActivateCallFrame(interp, oldFramePtr);
+
+ /*
+ * Create the component record. Set the protection level
+ * according to the "-protected" or "-private" option.
+ */
+ ownerClass = contextClass;
+ uplevelFramePtr = _Tcl_GetCallFrame(interp, 1);
+ if (uplevelFramePtr && Itcl_IsClassNamespace(uplevelFramePtr->nsPtr)) {
+ ownerClass = (ItclClass*)uplevelFramePtr->nsPtr->clientData;
+ }
+
+ archComp = Itk_CreateArchComponent(interp, info, name, ownerClass,
+ accessCmd);
+
+ if (!archComp) {
+ goto compFail;
+ }
+
+ Tcl_SetHashValue(entry, (ClientData)archComp);
+ archComp->member->protection = pLevel;
+
+ /*
+ * If this component is the "hull" for the mega-widget, then
+ * move the hull widget access command to a different name,
+ * and move the object access command back into place. This
+ * way, when the widget name is used as a command, the object
+ * access command will handle all requests.
+ */
+ if (strcmp(name, "hull") == 0) {
+ hullNamePtr = Tcl_NewStringObj((char*)NULL, 0);
+ Tcl_GetCommandFullName(interp, accessCmd, hullNamePtr);
+ Tcl_AppendToObj(hullNamePtr, "-itk_hull", -1);
+ Tcl_IncrRefCount(hullNamePtr);
+
+ result = TclRenameCommand(interp,
+ Tcl_GetStringFromObj(winNamePtr, (int*)NULL),
+ Tcl_GetStringFromObj(hullNamePtr, (int*)NULL));
+
+ if (result != TCL_OK) {
+ goto compFail;
+ }
+
+ Tcl_DecrRefCount(winNamePtr); /* winNamePtr keeps current name */
+ winNamePtr = hullNamePtr;
+ hullNamePtr = NULL;
+
+ result = TclRenameCommand(interp,
+ Tcl_GetStringFromObj(tmpNamePtr, (int*)NULL),
+ Tcl_GetStringFromObj(objNamePtr, (int*)NULL));
+
+ if (result != TCL_OK) {
+ goto compFail;
+ }
+ }
+
+ /*
+ * Add a binding onto the new component, so that when its
+ * window is destroyed, it will automatically remove itself
+ * from its parent's component list. Avoid doing these things
+ * for the "hull" component, since it is a special case and
+ * these things are not really necessary.
+ */
+ else {
+ Tcl_DStringSetLength(&buffer, 0);
+ Tcl_DStringAppend(&buffer, "bindtags ", -1);
+ Tcl_DStringAppend(&buffer, path, -1);
+ if (Tcl_Eval(interp, Tcl_DStringValue(&buffer)) != TCL_OK) {
+ goto compFail;
+ }
+
+ Tcl_DStringSetLength(&buffer, 0);
+ Tcl_DStringAppend(&buffer, "bind itk-destroy-", -1);
+ Tcl_DStringAppend(&buffer, path, -1);
+ Tcl_DStringAppend(&buffer, " [itcl::code ", -1);
+
+ Tcl_DStringAppend(&buffer,
+ Tcl_GetStringFromObj(objNamePtr,(int*)NULL), -1);
+
+ Tcl_DStringAppend(&buffer, " itk_component delete ", -1);
+ Tcl_DStringAppend(&buffer, name, -1);
+ Tcl_DStringAppend(&buffer, "]\n", -1);
+ Tcl_DStringAppend(&buffer, "bindtags ", -1);
+ Tcl_DStringAppend(&buffer, path, -1);
+ Tcl_DStringAppend(&buffer, " {itk-destroy-", -1);
+ Tcl_DStringAppend(&buffer, path, -1);
+ Tcl_DStringAppend(&buffer, " ", -1);
+ Tcl_DStringAppend(&buffer, Tcl_GetStringResult(interp), -1);
+ Tcl_DStringAppend(&buffer, "}", -1);
+ if (Tcl_Eval(interp, Tcl_DStringValue(&buffer)) != TCL_OK) {
+ goto compFail;
+ }
+ }
+
+ /*
+ * Query the list of configuration options for this widget,
+ * so we will know which ones are valid. Build an option
+ * table to represent these, so they can be found quickly
+ * by the option parsing commands in "itk::option-parser".
+ */
+ Tcl_DStringTrunc(&buffer, 0);
+ Tcl_DStringAppendElement(&buffer,
+ Tcl_GetStringFromObj(winNamePtr, (int*)NULL));
+ Tcl_DStringAppendElement(&buffer, "configure");
+
+ result = Tcl_Eval(interp, Tcl_DStringValue(&buffer));
+
+ if (result != TCL_OK) {
+ goto compFail;
+ }
+ Tcl_DStringSetLength(&buffer, 0);
+ Tcl_DStringAppend(&buffer, Tcl_GetStringResult(interp), -1);
+
+ /*
+ * Find the "itk::option-parser" namespace and get the data
+ * record shared by all of the parsing commands.
+ */
+ parserNs = Tcl_FindNamespace(interp, "::itk::option-parser",
+ (Tcl_Namespace*)NULL, TCL_LEAVE_ERR_MSG);
+
+ if (!parserNs) {
+ goto compFail;
+ }
+ mergeInfo = (ArchMergeInfo*)parserNs->clientData;
+ assert(mergeInfo);
+
+ /*
+ * Initialize the data record used by the option parsing commands.
+ * Store a table of valid configuration options, along with the
+ * info for the mega-widget that is being updated.
+ */
+ mergeInfo->optionTable = Itk_CreateGenericOptTable(interp,
+ Tcl_DStringValue(&buffer));
+
+ if (!mergeInfo->optionTable) {
+ goto compFail;
+ }
+ mergeInfo->archInfo = info;
+ mergeInfo->archComp = archComp;
+
+ /*
+ * Execute the option-handling commands in the "itk::option-parser"
+ * namespace. If there are no option-handling commands, invoke
+ * the "usual" command instead.
+ */
+ if (objc != 4) {
+ objPtr = Tcl_NewStringObj("usual", -1);
+ Tcl_IncrRefCount(objPtr);
+ } else {
+ objPtr = objv[3];
+ }
+
+ result = Tcl_PushCallFrame(interp, &frame,
+ parserNs, /* isProcCallFrame */ 0);
+
+ if (result == TCL_OK) {
+ /* CYGNUS LOCAL - Fix for Tcl8.1 */
+#if TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION == 0
+ result = Tcl_EvalObj(interp, objPtr);
+#else
+ result = Tcl_EvalObj(interp, objPtr, 0);
+#endif
+ /* END CYGNUS LOCAL */
+ Tcl_PopCallFrame(interp);
+ }
+
+ if (objPtr != objv[3]) {
+ Tcl_DecrRefCount(objPtr);
+ }
+ if (result != TCL_OK) {
+ goto compFail;
+ }
+
+ Itk_DelGenericOptTable(mergeInfo->optionTable);
+ mergeInfo->optionTable = NULL;
+ mergeInfo->archInfo = NULL;
+ mergeInfo->archComp = NULL;
+
+ ckfree(path);
+
+ Tcl_DStringFree(&buffer);
+ if (objNamePtr) {
+ Tcl_DecrRefCount(objNamePtr);
+ }
+ if (tmpNamePtr) {
+ Tcl_DecrRefCount(tmpNamePtr);
+ }
+ if (winNamePtr) {
+ Tcl_DecrRefCount(winNamePtr);
+ }
+ if (hullNamePtr) {
+ Tcl_DecrRefCount(hullNamePtr);
+ }
+
+ Tcl_SetResult(interp, name, TCL_VOLATILE);
+ return TCL_OK;
+
+ /*
+ * If any errors were encountered, clean up and return.
+ */
+compFail:
+ if (archComp) {
+ Itk_DelArchComponent(archComp);
+ }
+ if (entry) {
+ Tcl_DeleteHashEntry(entry);
+ }
+ if (path) {
+ ckfree(path);
+ }
+ if (mergeInfo && mergeInfo->optionTable) {
+ Itk_DelGenericOptTable(mergeInfo->optionTable);
+ mergeInfo->optionTable = NULL;
+ mergeInfo->archInfo = NULL;
+ mergeInfo->archComp = NULL;
+ }
+
+ Tcl_DStringFree(&buffer);
+ if (objNamePtr) {
+ Tcl_DecrRefCount(objNamePtr);
+ }
+ if (tmpNamePtr) {
+ Tcl_DecrRefCount(tmpNamePtr);
+ }
+ if (winNamePtr) {
+ Tcl_DecrRefCount(winNamePtr);
+ }
+ if (hullNamePtr) {
+ Tcl_DecrRefCount(hullNamePtr);
+ }
+
+ /*
+ * Add error info and return.
+ */
+ objPtr = Tcl_NewStringObj((char*)NULL, 0);
+ Tcl_AppendToObj(objPtr, "\n (while creating component \"", -1);
+ Tcl_AppendToObj(objPtr, name, -1);
+ Tcl_AppendToObj(objPtr, "\" for widget \"", -1);
+ Tcl_GetCommandFullName(contextObj->classDefn->interp,
+ contextObj->accessCmd, objPtr);
+ Tcl_AppendToObj(objPtr, "\")", -1);
+ Tcl_IncrRefCount(objPtr);
+
+ Tcl_AddErrorInfo(interp, Tcl_GetStringFromObj(objPtr, (int*)NULL));
+ Tcl_DecrRefCount(objPtr);
+
+
+ return TCL_ERROR;
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itk_ArchCompDeleteCmd()
+ *
+ * Invoked by [incr Tcl] to handle the itk::Archetype::itk_component
+ * method. Removes an existing component widget from a mega-widget,
+ * and removes any configuration options associated with it.
+ *
+ * itk_component delete ? ...?
+ *
+ * Returns TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+Itk_ArchCompDeleteCmd(dummy, interp, objc, objv)
+ ClientData dummy; /* unused */
+ Tcl_Interp *interp; /* current interpreter */
+ int objc; /* number of arguments */
+ Tcl_Obj *CONST objv[]; /* argument objects */
+{
+ int i;
+ char *token;
+ ItclClass *contextClass;
+ ItclObject *contextObj;
+ ArchInfo *info;
+ Tcl_HashEntry *entry;
+ Tcl_HashSearch place;
+ Itcl_ListElem *elem;
+ ArchComponent *archComp;
+ ArchOption *archOpt;
+ ArchOptionPart *optPart;
+
+ /*
+ * Get the Archetype info associated with this widget.
+ */
+ if (Itcl_GetContext(interp, &contextClass, &contextObj) != TCL_OK ||
+ !contextObj) {
+
+ Tcl_ResetResult(interp);
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "cannot access components without an object context",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+ if (Itk_GetArchInfo(interp, contextObj, &info) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Scan through the list of component names and delete each
+ * one. Make sure that each component exists.
+ */
+ for (i=1; i < objc; i++) {
+ token = Tcl_GetStringFromObj(objv[i], (int*)NULL);
+ entry = Tcl_FindHashEntry(&info->components, token);
+ if (!entry) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "name \"", token, "\" is not a component",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+ archComp = (ArchComponent*)Tcl_GetHashValue(entry);
+ Tcl_DeleteHashEntry(entry);
+
+ entry = Tcl_FirstHashEntry(&info->options, &place);
+ while (entry) {
+ archOpt = (ArchOption*)Tcl_GetHashValue(entry);
+ elem = Itcl_FirstListElem(&archOpt->parts);
+ while (elem) {
+ optPart = (ArchOptionPart*)Itcl_GetListValue(elem);
+ if (optPart->from == (ClientData)archComp) {
+ Itk_DelOptionPart(optPart);
+ elem = Itcl_DeleteListElem(elem);
+ }
+ else {
+ elem = Itcl_NextListElem(elem);
+ }
+ }
+ entry = Tcl_NextHashEntry(&place);
+ }
+
+ Itk_DelArchComponent(archComp);
+ }
+ return TCL_OK;
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itk_ArchOptKeepCmd()
+ *
+ * Invoked by [incr Tcl] to handle the "keep" command in the itk
+ * option parser. Integrates a list of component configuration options
+ * into a mega-widget, so that whenever the mega-widget is updated,
+ * the component will be updated as well.
+ *
+ * Handles the following syntax:
+ *
+ * keep
itk_archetype.c
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: itk.h
===================================================================
--- itk.h (nonexistent)
+++ itk.h (revision 1765)
@@ -0,0 +1,157 @@
+/*
+ * ------------------------------------------------------------------------
+ * PACKAGE: [incr Tk]
+ * DESCRIPTION: Building mega-widgets with [incr Tcl]
+ *
+ * [incr Tk] provides a framework for building composite "mega-widgets"
+ * using [incr Tcl] classes. It defines a set of base classes that are
+ * specialized to create all other widgets.
+ *
+ * ADDING [incr Tk] TO A Tcl-BASED APPLICATION:
+ *
+ * To add [incr Tk] facilities to a Tcl application, modify the
+ * Tcl_AppInit() routine as follows:
+ *
+ * 1) Include the header files for [incr Tcl] and [incr Tk] near
+ * the top of the file containing Tcl_AppInit():
+ *
+ * #include "itcl.h"
+ * #include "itk.h"
+ *
+ * 2) Within the body of Tcl_AppInit(), add the following lines:
+ *
+ * if (Itcl_Init(interp) == TCL_ERROR) {
+ * return TCL_ERROR;
+ * }
+ * if (Itk_Init(interp) == TCL_ERROR) {
+ * return TCL_ERROR;
+ * }
+ *
+ * 3) Link your application with libitcl.a and libitk.a
+ *
+ * NOTE: An example file "tkAppInit.c" containing the changes shown
+ * above is included in this distribution.
+ *
+ * ========================================================================
+ * AUTHOR: Michael J. McLennan
+ * Bell Labs Innovations for Lucent Technologies
+ * mmclennan@lucent.com
+ * http://www.tcltk.com/itcl
+ *
+ * RCS: $Id: itk.h,v 1.1.1.1 2002-01-16 10:24:47 markom Exp $
+ * ========================================================================
+ * Copyright (c) 1993-1998 Lucent Technologies, Inc.
+ * ------------------------------------------------------------------------
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+#ifndef ITK_H
+#define ITK_H
+
+/*
+ * A special definition used to allow this header file to be included
+ * in resource files so that they can get obtain version information from
+ * this file. Resource compilers don't like all the C stuff, like typedefs
+ * and procedure declarations, that occur below.
+ */
+
+#ifndef RESOURCE_INCLUDED
+
+#include "itclInt.h"
+#include "tk.h"
+
+#ifdef BUILD_itk
+# undef TCL_STORAGE_CLASS
+# define TCL_STORAGE_CLASS DLLEXPORT
+#endif
+
+/*
+ * List of options in alphabetical order:
+ */
+typedef struct ItkOptList {
+ Tcl_HashTable *options; /* list containing the real options */
+ Tcl_HashEntry **list; /* gives ordering of options */
+ int len; /* number of entries in order list */
+ int max; /* maximum size of order list */
+} ItkOptList;
+
+/*
+ * List of options created in the class definition:
+ */
+typedef struct ItkClassOptTable {
+ Tcl_HashTable options; /* option storage with fast lookup */
+ ItkOptList order; /* gives ordering of options */
+} ItkClassOptTable;
+
+/*
+ * Each option created in the class definition:
+ */
+typedef struct ItkClassOption {
+ ItclMember *member; /* info about this option */
+ char *resName; /* resource name in X11 database */
+ char *resClass; /* resource class name in X11 database */
+ char *init; /* initial value for option */
+} ItkClassOption;
+
+
+/*
+ * Exported functions:
+ */
+EXTERN int Itk_Init _ANSI_ARGS_((Tcl_Interp *interp));
+EXTERN int Itk_SafeInit _ANSI_ARGS_((Tcl_Interp *interp));
+
+/*
+ * Functions used internally by this package:
+ */
+EXTERN int Itk_ConfigBodyCmd _ANSI_ARGS_((ClientData cdata,
+ Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+EXTERN int Itk_UsualCmd _ANSI_ARGS_((ClientData cdata,
+ Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+
+/*
+ * Functions for managing options included in class definitions:
+ */
+EXTERN int Itk_ClassOptionDefineCmd _ANSI_ARGS_((ClientData cdata,
+ Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+EXTERN int Itk_ClassOptionIllegalCmd _ANSI_ARGS_((ClientData cdata,
+ Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]));
+
+EXTERN int Itk_ConfigClassOption _ANSI_ARGS_((Tcl_Interp *interp,
+ ItclObject *contextObj, ClientData cdata, char* newVal));
+
+EXTERN ItkClassOptTable* Itk_CreateClassOptTable _ANSI_ARGS_((
+ Tcl_Interp *interp, ItclClass *cdefn));
+EXTERN ItkClassOptTable* Itk_FindClassOptTable _ANSI_ARGS_((
+ ItclClass *cdefn));
+EXTERN void Itk_DeleteClassOptTable _ANSI_ARGS_((Tcl_Interp *interp,
+ ItclClass *cdefn));
+
+EXTERN int Itk_CreateClassOption _ANSI_ARGS_((Tcl_Interp *interp,
+ ItclClass *cdefn, char *switchName, char *resName, char *resClass,
+ char *defVal, char *config, ItkClassOption **optPtr));
+EXTERN ItkClassOption* Itk_FindClassOption _ANSI_ARGS_((
+ ItclClass *cdefn, char *switchName));
+EXTERN void Itk_DelClassOption _ANSI_ARGS_((ItkClassOption *opt));
+
+/*
+ * Functions needed for the Archetype base class:
+ */
+EXTERN int Itk_ArchetypeInit _ANSI_ARGS_((Tcl_Interp* interp));
+
+/*
+ * Functions for maintaining the ordered option list:
+ */
+EXTERN void Itk_OptListInit _ANSI_ARGS_((ItkOptList* olist,
+ Tcl_HashTable *options));
+EXTERN void Itk_OptListFree _ANSI_ARGS_((ItkOptList* olist));
+
+EXTERN void Itk_OptListAdd _ANSI_ARGS_((ItkOptList* olist,
+ Tcl_HashEntry *entry));
+EXTERN void Itk_OptListRemove _ANSI_ARGS_((ItkOptList* olist,
+ Tcl_HashEntry *entry));
+
+# undef TCL_STORAGE_CLASS
+# define TCL_STORAGE_CLASS DLLIMPORT
+
+#endif /* RESOURCE INCLUDED */
+#endif /* ITK_H */
itk.h
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: itk_cmds.c
===================================================================
--- itk_cmds.c (nonexistent)
+++ itk_cmds.c (revision 1765)
@@ -0,0 +1,316 @@
+/*
+ * ------------------------------------------------------------------------
+ * PACKAGE: [incr Tk]
+ * DESCRIPTION: Building mega-widgets with [incr Tcl]
+ *
+ * [incr Tk] provides a framework for building composite "mega-widgets"
+ * using [incr Tcl] classes. It defines a set of base classes that are
+ * specialized to create all other widgets.
+ *
+ * This file defines the initialization and facilities common to all
+ * mega-widgets.
+ *
+ * ========================================================================
+ * AUTHOR: Michael J. McLennan
+ * Bell Labs Innovations for Lucent Technologies
+ * mmclennan@lucent.com
+ * http://www.tcltk.com/itcl
+ *
+ * RCS: $Id: itk_cmds.c,v 1.1.1.1 2002-01-16 10:24:47 markom Exp $
+ * ========================================================================
+ * Copyright (c) 1993-1998 Lucent Technologies, Inc.
+ * ------------------------------------------------------------------------
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+#include "itk.h"
+
+/*
+ * FORWARD DECLARATIONS
+ */
+static int Initialize _ANSI_ARGS_((Tcl_Interp *interp));
+
+/*
+ * The following string is the startup script executed in new
+ * interpreters. It looks on disk in several different directories
+ * for a script "init.tcl" that is compatible with this version
+ * of Tcl. The init.tcl script does all of the real work of
+ * initialization.
+ */
+
+static char initScript[] = "\n\
+namespace eval ::itk {\n\
+ proc _find_init {} {\n\
+ global env tcl_library\n\
+ variable library\n\
+ variable version\n\
+ rename _find_init {}\n\
+ tcl_findLibrary itk 3.0 {} itk.tcl ITK_LIBRARY ::itk::library {} {} itcl\n\
+ }\n\
+ _find_init\n\
+}";
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Initialize()
+ *
+ * Invoked whenever a new interpeter is created to install the
+ * [incr Tk] package.
+ *
+ * Creates the "::itk" namespace and installs access commands.
+ *
+ * Returns TCL_OK on success, or TCL_ERROR (along with an error
+ * message in the interpreter) if anything goes wrong.
+ * ------------------------------------------------------------------------
+ */
+static int
+Initialize(interp)
+ Tcl_Interp *interp; /* interpreter to be updated */
+{
+ Tcl_Namespace *itkNs, *parserNs;
+ ClientData parserInfo;
+
+ if (Tcl_PkgRequire(interp, "Tk", TK_VERSION, 0) == NULL) {
+ return TCL_ERROR;
+ }
+ if (Tcl_PkgRequire(interp, "Itcl", ITCL_VERSION, 0) == NULL) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Install [incr Tk] facilities if not already installed.
+ */
+ itkNs = Tcl_FindNamespace(interp, "::itk", (Tcl_Namespace*)NULL,
+ /* flags */ 0);
+
+ if (itkNs) {
+ Tcl_SetResult(interp, "already installed: [incr Tk]", TCL_STATIC);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Add the "itk_option" ensemble to the itcl class definition parser.
+ */
+ parserNs = Tcl_FindNamespace(interp, "::itcl::parser",
+ (Tcl_Namespace*)NULL, /* flags */ 0);
+
+ if (!parserNs) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "cannot initialize [incr Tk]: [incr Tcl] has not been installed\n",
+ "Make sure that Itcl_Init() is called before Itk_Init()",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+ parserInfo = parserNs->clientData;
+
+ if (Itcl_CreateEnsemble(interp, "::itcl::parser::itk_option") != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (Itcl_AddEnsemblePart(interp, "::itcl::parser::itk_option",
+ "define", "-switch resourceName resourceClass init ?config?",
+ Itk_ClassOptionDefineCmd,
+ parserInfo, Itcl_ReleaseData) != TCL_OK) {
+
+ return TCL_ERROR;
+ }
+ Itcl_PreserveData(parserInfo);
+
+ if (Itcl_AddEnsemblePart(interp, "::itcl::parser::itk_option",
+ "add", "name ?name name...?",
+ Itk_ClassOptionIllegalCmd,
+ (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL) != TCL_OK ||
+
+ Itcl_AddEnsemblePart(interp, "::itcl::parser::itk_option",
+ "remove", "name ?name name...?",
+ Itk_ClassOptionIllegalCmd,
+ (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL) != TCL_OK) {
+
+ return TCL_ERROR;
+ }
+
+ /*
+ * Create the "itk" namespace. Export all the commands in
+ * the namespace so that they can be imported by a command
+ * such as "namespace import itk::*"
+ */
+ itkNs = Tcl_CreateNamespace(interp, "::itk",
+ (ClientData)NULL, (Tcl_NamespaceDeleteProc*)NULL);
+
+ if (!itkNs ||
+ Tcl_Export(interp, itkNs, "*", /* resetListFirst */ 1) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Setup things for itk::Archetype base class.
+ */
+ if (Itk_ArchetypeInit(interp) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Fix the "itcl::configbody" command to recognize mega-widget
+ * options.
+ */
+ Tcl_CreateObjCommand(interp, "::itcl::configbody", Itk_ConfigBodyCmd,
+ (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
+
+ Tcl_SetVar(interp, "::itk::version", ITCL_VERSION, 0);
+ Tcl_SetVar(interp, "::itk::patchLevel", ITCL_PATCH_LEVEL, 0);
+
+ /*
+ * Signal that the package has been loaded.
+ */
+ if (Tcl_PkgProvide(interp, "Itk", ITCL_VERSION) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itk_Init()
+ *
+ * Invoked whenever a new interpeter is created to install the
+ * [incr Tcl] package. Usually invoked within Tcl_AppInit() at
+ * the start of execution.
+ *
+ * Creates the "::itk" namespace and installs access commands.
+ *
+ * Returns TCL_OK on success, or TCL_ERROR (along with an error
+ * message in the interpreter) if anything goes wrong.
+ * ------------------------------------------------------------------------
+ */
+int
+Itk_Init(interp)
+ Tcl_Interp *interp; /* interpreter to be updated */
+{
+ if (Initialize(interp) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ return Tcl_Eval(interp, initScript);
+ return TCL_OK;
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itk_ConfigBodyCmd()
+ *
+ * Replacement for the usual "itcl::configbody" command. Recognizes
+ * mega-widget options included in a class definition. Options are
+ * identified by their "switch" name, but without the "-" prefix:
+ *
+ * itcl::configbody ::
+ *
+ * Handles bodies for public variables as well:
+ *
+ * itcl::configbody ::
+ *
+ * If an is found, it has priority over public variables.
+ * If has the form "@name" then it is treated as a reference
+ * to a C handling procedure; otherwise, it is taken as a body of
+ * Tcl statements.
+ *
+ * Returns TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+int
+Itk_ConfigBodyCmd(dummy, interp, objc, objv)
+ ClientData dummy; /* unused */
+ Tcl_Interp *interp; /* current interpreter */
+ int objc; /* number of arguments */
+ Tcl_Obj *CONST objv[]; /* argument objects */
+{
+ int result = TCL_OK;
+
+ char *token, *head, *tail;
+ ItclClass *cdefn;
+ ItclMemberCode *mcode;
+ ItkClassOptTable *optTable;
+ Tcl_HashEntry *entry;
+ ItkClassOption *opt;
+ Tcl_DString buffer;
+
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "class::option body");
+ return TCL_ERROR;
+ }
+
+ /*
+ * Parse the member name "namesp::namesp::class::option".
+ * Make sure that a class name was specified, and that the
+ * class exists.
+ */
+ token = Tcl_GetStringFromObj(objv[1], (int*)NULL);
+ Itcl_ParseNamespPath(token, &buffer, &head, &tail);
+
+ if (!head || *head == '\0') {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "missing class specifier for body declaration \"", token, "\"",
+ (char*)NULL);
+ result = TCL_ERROR;
+ goto configBodyCmdDone;
+ }
+
+ cdefn = Itcl_FindClass(interp, head, /* autoload */ 1);
+ if (cdefn == NULL) {
+ result = TCL_ERROR;
+ goto configBodyCmdDone;
+ }
+
+ /*
+ * Look first for a configuration option with that name.
+ * If it is not found, assume the reference is for a public
+ * variable, and use the usual "configbody" implementation
+ * to handle it.
+ */
+ optTable = Itk_FindClassOptTable(cdefn);
+ opt = NULL;
+
+ if (optTable) {
+ Tcl_DString optName;
+
+ Tcl_DStringInit(&optName);
+ Tcl_DStringAppend(&optName, "-", -1);
+ Tcl_DStringAppend(&optName, tail, -1);
+ entry = Tcl_FindHashEntry(&optTable->options,
+ Tcl_DStringValue(&optName));
+
+ if (entry) {
+ opt = (ItkClassOption*)Tcl_GetHashValue(entry);
+ }
+ Tcl_DStringFree(&optName);
+ }
+
+ if (opt == NULL) {
+ result = Itcl_ConfigBodyCmd(dummy, interp, objc, objv);
+ goto configBodyCmdDone;
+ }
+
+ /*
+ * Otherwise, change the implementation for this option.
+ */
+ token = Tcl_GetStringFromObj(objv[2], (int*)NULL);
+
+ if (Itcl_CreateMemberCode(interp, cdefn, (char*)NULL, token,
+ &mcode) != TCL_OK) {
+
+ result = TCL_ERROR;
+ goto configBodyCmdDone;
+ }
+
+ Itcl_PreserveData((ClientData)mcode);
+ Itcl_EventuallyFree((ClientData)mcode, Itcl_DeleteMemberCode);
+
+ if (opt->member->code) {
+ Itcl_ReleaseData((ClientData)opt->member->code);
+ }
+ opt->member->code = mcode;
+
+configBodyCmdDone:
+ Tcl_DStringFree(&buffer);
+ return result;
+}
itk_cmds.c
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property