OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [itcl/] [itk/] [generic/] [itk_cmds.c] - Blame information for rev 578

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/*
2
 * ------------------------------------------------------------------------
3
 *      PACKAGE:  [incr Tk]
4
 *  DESCRIPTION:  Building mega-widgets with [incr Tcl]
5
 *
6
 *  [incr Tk] provides a framework for building composite "mega-widgets"
7
 *  using [incr Tcl] classes.  It defines a set of base classes that are
8
 *  specialized to create all other widgets.
9
 *
10
 *  This file defines the initialization and facilities common to all
11
 *  mega-widgets.
12
 *
13
 * ========================================================================
14
 *  AUTHOR:  Michael J. McLennan
15
 *           Bell Labs Innovations for Lucent Technologies
16
 *           mmclennan@lucent.com
17
 *           http://www.tcltk.com/itcl
18
 *
19
 *     RCS:  $Id: itk_cmds.c,v 1.1.1.1 2002-01-16 10:24:47 markom Exp $
20
 * ========================================================================
21
 *           Copyright (c) 1993-1998  Lucent Technologies, Inc.
22
 * ------------------------------------------------------------------------
23
 * See the file "license.terms" for information on usage and redistribution
24
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
25
 */
26
#include "itk.h"
27
 
28
/*
29
 *  FORWARD DECLARATIONS
30
 */
31
static int Initialize _ANSI_ARGS_((Tcl_Interp *interp));
32
 
33
/*
34
 * The following string is the startup script executed in new
35
 * interpreters.  It looks on disk in several different directories
36
 * for a script "init.tcl" that is compatible with this version
37
 * of Tcl.  The init.tcl script does all of the real work of
38
 * initialization.
39
 */
40
 
41
static char initScript[] = "\n\
42
namespace eval ::itk {\n\
43
    proc _find_init {} {\n\
44
        global env tcl_library\n\
45
        variable library\n\
46
        variable version\n\
47
        rename _find_init {}\n\
48
        tcl_findLibrary itk 3.0 {} itk.tcl ITK_LIBRARY ::itk::library {} {} itcl\n\
49
   }\n\
50
    _find_init\n\
51
}";
52
 
53
 
54
/*
55
 * ------------------------------------------------------------------------
56
 *  Initialize()
57
 *
58
 *  Invoked whenever a new interpeter is created to install the
59
 *  [incr Tk] package.
60
 *
61
 *  Creates the "::itk" namespace and installs access commands.
62
 *
63
 *  Returns TCL_OK on success, or TCL_ERROR (along with an error
64
 *  message in the interpreter) if anything goes wrong.
65
 * ------------------------------------------------------------------------
66
 */
67
static int
68
Initialize(interp)
69
    Tcl_Interp *interp;  /* interpreter to be updated */
70
{
71
    Tcl_Namespace *itkNs, *parserNs;
72
    ClientData parserInfo;
73
 
74
    if (Tcl_PkgRequire(interp, "Tk", TK_VERSION, 0) == NULL) {
75
        return TCL_ERROR;
76
    }
77
    if (Tcl_PkgRequire(interp, "Itcl", ITCL_VERSION, 0) == NULL) {
78
        return TCL_ERROR;
79
    }
80
 
81
    /*
82
     *  Install [incr Tk] facilities if not already installed.
83
     */
84
    itkNs = Tcl_FindNamespace(interp, "::itk", (Tcl_Namespace*)NULL,
85
        /* flags */ 0);
86
 
87
    if (itkNs) {
88
        Tcl_SetResult(interp, "already installed: [incr Tk]", TCL_STATIC);
89
        return TCL_ERROR;
90
    }
91
 
92
    /*
93
     *  Add the "itk_option" ensemble to the itcl class definition parser.
94
     */
95
    parserNs = Tcl_FindNamespace(interp, "::itcl::parser",
96
        (Tcl_Namespace*)NULL, /* flags */ 0);
97
 
98
    if (!parserNs) {
99
        Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
100
            "cannot initialize [incr Tk]: [incr Tcl] has not been installed\n",
101
            "Make sure that Itcl_Init() is called before Itk_Init()",
102
            (char*)NULL);
103
        return TCL_ERROR;
104
    }
105
    parserInfo = parserNs->clientData;
106
 
107
    if (Itcl_CreateEnsemble(interp, "::itcl::parser::itk_option") != TCL_OK) {
108
        return TCL_ERROR;
109
    }
110
    if (Itcl_AddEnsemblePart(interp, "::itcl::parser::itk_option",
111
            "define", "-switch resourceName resourceClass init ?config?",
112
            Itk_ClassOptionDefineCmd,
113
            parserInfo, Itcl_ReleaseData) != TCL_OK) {
114
 
115
        return TCL_ERROR;
116
    }
117
    Itcl_PreserveData(parserInfo);
118
 
119
    if (Itcl_AddEnsemblePart(interp, "::itcl::parser::itk_option",
120
            "add", "name ?name name...?",
121
            Itk_ClassOptionIllegalCmd,
122
            (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL) != TCL_OK ||
123
 
124
        Itcl_AddEnsemblePart(interp, "::itcl::parser::itk_option",
125
            "remove", "name ?name name...?",
126
            Itk_ClassOptionIllegalCmd,
127
            (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL) != TCL_OK) {
128
 
129
        return TCL_ERROR;
130
    }
131
 
132
    /*
133
     *  Create the "itk" namespace.  Export all the commands in
134
     *  the namespace so that they can be imported by a command
135
     *  such as "namespace import itk::*"
136
     */
137
    itkNs = Tcl_CreateNamespace(interp, "::itk",
138
        (ClientData)NULL, (Tcl_NamespaceDeleteProc*)NULL);
139
 
140
    if (!itkNs ||
141
        Tcl_Export(interp, itkNs, "*", /* resetListFirst */ 1) != TCL_OK) {
142
        return TCL_ERROR;
143
    }
144
 
145
    /*
146
     *  Setup things for itk::Archetype base class.
147
     */
148
    if (Itk_ArchetypeInit(interp) != TCL_OK) {
149
        return TCL_ERROR;
150
    }
151
 
152
    /*
153
     *  Fix the "itcl::configbody" command to recognize mega-widget
154
     *  options.
155
     */
156
    Tcl_CreateObjCommand(interp, "::itcl::configbody", Itk_ConfigBodyCmd,
157
        (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
158
 
159
    Tcl_SetVar(interp, "::itk::version", ITCL_VERSION, 0);
160
    Tcl_SetVar(interp, "::itk::patchLevel", ITCL_PATCH_LEVEL, 0);
161
 
162
    /*
163
     *  Signal that the package has been loaded.
164
     */
165
    if (Tcl_PkgProvide(interp, "Itk", ITCL_VERSION) != TCL_OK) {
166
        return TCL_ERROR;
167
    }
168
    return TCL_OK;
169
}
170
 
171
/*
172
 * ------------------------------------------------------------------------
173
 *  Itk_Init()
174
 *
175
 *  Invoked whenever a new interpeter is created to install the
176
 *  [incr Tcl] package.  Usually invoked within Tcl_AppInit() at
177
 *  the start of execution.
178
 *
179
 *  Creates the "::itk" namespace and installs access commands.
180
 *
181
 *  Returns TCL_OK on success, or TCL_ERROR (along with an error
182
 *  message in the interpreter) if anything goes wrong.
183
 * ------------------------------------------------------------------------
184
 */
185
int
186
Itk_Init(interp)
187
    Tcl_Interp *interp;  /* interpreter to be updated */
188
{
189
    if (Initialize(interp) != TCL_OK) {
190
        return TCL_ERROR;
191
    }
192
    return Tcl_Eval(interp, initScript);
193
    return TCL_OK;
194
}
195
 
196
 
197
/*
198
 * ------------------------------------------------------------------------
199
 *  Itk_ConfigBodyCmd()
200
 *
201
 *  Replacement for the usual "itcl::configbody" command.  Recognizes
202
 *  mega-widget options included in a class definition.  Options are
203
 *  identified by their "switch" name, but without the "-" prefix:
204
 *
205
 *    itcl::configbody <class>::<itkOption> <body>
206
 *
207
 *  Handles bodies for public variables as well:
208
 *
209
 *    itcl::configbody <class>::<publicVar> <body>
210
 *
211
 *  If an <itkOption> is found, it has priority over public variables.
212
 *  If <body> has the form "@name" then it is treated as a reference
213
 *  to a C handling procedure; otherwise, it is taken as a body of
214
 *  Tcl statements.
215
 *
216
 *  Returns TCL_OK/TCL_ERROR to indicate success/failure.
217
 * ------------------------------------------------------------------------
218
 */
219
/* ARGSUSED */
220
int
221
Itk_ConfigBodyCmd(dummy, interp, objc, objv)
222
    ClientData dummy;        /* unused */
223
    Tcl_Interp *interp;      /* current interpreter */
224
    int objc;                /* number of arguments */
225
    Tcl_Obj *CONST objv[];   /* argument objects */
226
{
227
    int result = TCL_OK;
228
 
229
    char *token, *head, *tail;
230
    ItclClass *cdefn;
231
    ItclMemberCode *mcode;
232
    ItkClassOptTable *optTable;
233
    Tcl_HashEntry *entry;
234
    ItkClassOption *opt;
235
    Tcl_DString buffer;
236
 
237
    if (objc != 3) {
238
        Tcl_WrongNumArgs(interp, 1, objv, "class::option body");
239
        return TCL_ERROR;
240
    }
241
 
242
    /*
243
     *  Parse the member name "namesp::namesp::class::option".
244
     *  Make sure that a class name was specified, and that the
245
     *  class exists.
246
     */
247
    token = Tcl_GetStringFromObj(objv[1], (int*)NULL);
248
    Itcl_ParseNamespPath(token, &buffer, &head, &tail);
249
 
250
    if (!head || *head == '\0') {
251
        Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
252
            "missing class specifier for body declaration \"", token, "\"",
253
            (char*)NULL);
254
        result = TCL_ERROR;
255
        goto configBodyCmdDone;
256
    }
257
 
258
    cdefn = Itcl_FindClass(interp, head, /* autoload */ 1);
259
    if (cdefn == NULL) {
260
        result = TCL_ERROR;
261
        goto configBodyCmdDone;
262
    }
263
 
264
    /*
265
     *  Look first for a configuration option with that name.
266
     *  If it is not found, assume the reference is for a public
267
     *  variable, and use the usual "configbody" implementation
268
     *  to handle it.
269
     */
270
    optTable = Itk_FindClassOptTable(cdefn);
271
    opt = NULL;
272
 
273
    if (optTable) {
274
        Tcl_DString optName;
275
 
276
        Tcl_DStringInit(&optName);
277
        Tcl_DStringAppend(&optName, "-", -1);
278
        Tcl_DStringAppend(&optName, tail, -1);
279
        entry = Tcl_FindHashEntry(&optTable->options,
280
            Tcl_DStringValue(&optName));
281
 
282
        if (entry) {
283
            opt = (ItkClassOption*)Tcl_GetHashValue(entry);
284
        }
285
        Tcl_DStringFree(&optName);
286
    }
287
 
288
    if (opt == NULL) {
289
        result = Itcl_ConfigBodyCmd(dummy, interp, objc, objv);
290
        goto configBodyCmdDone;
291
    }
292
 
293
    /*
294
     *  Otherwise, change the implementation for this option.
295
     */
296
    token = Tcl_GetStringFromObj(objv[2], (int*)NULL);
297
 
298
    if (Itcl_CreateMemberCode(interp, cdefn, (char*)NULL, token,
299
        &mcode) != TCL_OK) {
300
 
301
        result = TCL_ERROR;
302
        goto configBodyCmdDone;
303
    }
304
 
305
    Itcl_PreserveData((ClientData)mcode);
306
    Itcl_EventuallyFree((ClientData)mcode, Itcl_DeleteMemberCode);
307
 
308
    if (opt->member->code) {
309
        Itcl_ReleaseData((ClientData)opt->member->code);
310
    }
311
    opt->member->code = mcode;
312
 
313
configBodyCmdDone:
314
    Tcl_DStringFree(&buffer);
315
    return result;
316
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.