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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [tix/] [win/] [tkConsole41.c] - Blame information for rev 1771

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

Line No. Rev Author Line
1 578 markom
/*
2
 * tkConsole.c --
3
 *
4
 *      This file implements a Tcl console for systems that may not
5
 *      otherwise have access to a console.  It uses the Text widget
6
 *      and provides special access via a console command.
7
 *
8
 * Copyright (c) 1995-1996 Sun Microsystems, Inc.
9
 *
10
 * See the file "license.terms" for information on usage and redistribution
11
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
12
 *
13
 * SCCS: @(#) tkConsole.c 1.37 96/04/20 15:17:32
14
 */
15
 
16
#include "tkInt.h"
17
 
18
/*
19
 * A data structure of the following type holds information for each console
20
 * which a handler (i.e. a Tcl command) has been defined for a particular
21
 * top-level window.
22
 */
23
 
24
typedef struct ConsoleInfo {
25
    Tcl_Interp *consoleInterp;  /* Interpreter for the console. */
26
    Tcl_Interp *interp;         /* Interpreter to send console commands. */
27
} ConsoleInfo;
28
 
29
static Tcl_Interp *gStdoutInterp = NULL;
30
 
31
/*
32
 * Forward declarations for procedures defined later in this file:
33
 */
34
 
35
static int      ConsoleCmd _ANSI_ARGS_((ClientData clientData,
36
                    Tcl_Interp *interp, int argc, char **argv));
37
static void     ConsoleDeleteProc _ANSI_ARGS_((ClientData clientData));
38
static void     ConsoleEventProc _ANSI_ARGS_((ClientData clientData,
39
                    XEvent *eventPtr));
40
static int      InterpreterCmd _ANSI_ARGS_((ClientData clientData,
41
                    Tcl_Interp *interp, int argc, char **argv));
42
 
43
static int              ConsoleInput _ANSI_ARGS_((ClientData instanceData,
44
                            Tcl_File inFile, char *buf, int toRead,
45
                            int *errorCode));
46
static int              ConsoleOutput _ANSI_ARGS_((ClientData instanceData,
47
                            Tcl_File outFile, char *buf, int toWrite,
48
                            int *errorCode));
49
static int              ConsoleClose _ANSI_ARGS_((ClientData instanceData,
50
                            Tcl_Interp *interp, Tcl_File inFile,
51
                            Tcl_File outFile));
52
 
53
/*
54
 * This structure describes the channel type structure for file based IO:
55
 */
56
 
57
static Tcl_ChannelType consoleChannelType = {
58
    "console",                  /* Type name. */
59
    NULL,                       /* Always non-blocking.*/
60
    ConsoleClose,               /* Close proc. */
61
    ConsoleInput,               /* Input proc. */
62
    ConsoleOutput,              /* Output proc. */
63
    NULL,                       /* Seek proc. */
64
    NULL,                       /* Set option proc. */
65
    NULL,                       /* Get option proc. */
66
};
67
 
68
/*
69
 *----------------------------------------------------------------------
70
 *
71
 * TkConsoleCreate --
72
 *
73
 *      Create the console channels and install them as the standard
74
 *      channels.  All I/O will be discarded until TkConsoleInit is
75
 *      called to attach the console to a text widget.
76
 *
77
 * Results:
78
 *      None.
79
 *
80
 * Side effects:
81
 *      Creates the console channel and installs it as the standard
82
 *      channels.
83
 *
84
 *----------------------------------------------------------------------
85
 */
86
 
87
void
88
TkConsoleCreate()
89
{
90
    Tcl_Channel consoleChannel;
91
    Tcl_File inFile, outFile, errFile;
92
 
93
    inFile = Tcl_GetFile((ClientData) 0, 0);
94
    outFile = Tcl_GetFile((ClientData) 1, 0);
95
    errFile = Tcl_GetFile((ClientData) 2, 0);
96
 
97
    consoleChannel = Tcl_CreateChannel(&consoleChannelType, "console0",
98
            inFile, NULL, (ClientData) NULL);
99
    if (consoleChannel != NULL) {
100
        Tcl_SetChannelOption(NULL, consoleChannel, "-translation", "lf");
101
        Tcl_SetChannelOption(NULL, consoleChannel, "-buffering", "none");
102
    }
103
    Tcl_SetStdChannel(consoleChannel, TCL_STDIN);
104
    consoleChannel = Tcl_CreateChannel(&consoleChannelType, "console1",
105
            NULL, outFile, (ClientData) NULL);
106
    if (consoleChannel != NULL) {
107
        Tcl_SetChannelOption(NULL, consoleChannel, "-translation", "lf");
108
        Tcl_SetChannelOption(NULL, consoleChannel, "-buffering", "none");
109
    }
110
    Tcl_SetStdChannel(consoleChannel, TCL_STDOUT);
111
    consoleChannel = Tcl_CreateChannel(&consoleChannelType, "console2",
112
            NULL, errFile, (ClientData) NULL);
113
    if (consoleChannel != NULL) {
114
        Tcl_SetChannelOption(NULL, consoleChannel, "-translation", "lf");
115
        Tcl_SetChannelOption(NULL, consoleChannel, "-buffering", "none");
116
    }
117
    Tcl_SetStdChannel(consoleChannel, TCL_STDERR);
118
}
119
 
120
/*
121
 *----------------------------------------------------------------------
122
 *
123
 * TkConsoleInit --
124
 *
125
 *      Initialize the console.  This code actually creates a new
126
 *      application and associated interpreter.  This effectivly hides
127
 *      the implementation from the main application.
128
 *
129
 * Results:
130
 *      None.
131
 *
132
 * Side effects:
133
 *      A new console it created.
134
 *
135
 *----------------------------------------------------------------------
136
 */
137
 
138
int
139
TkConsoleInit(interp)
140
    Tcl_Interp *interp;                 /* Interpreter to use for prompting. */
141
{
142
    Tcl_Interp *consoleInterp;
143
    ConsoleInfo *info;
144
    Tk_Window mainWindow = Tk_MainWindow(interp);
145
#ifdef MAC_TCL
146
    static char initCmd[] = "source -rsrc {Console}";
147
#else
148
    static char initCmd[] = "source $tk_library/console.tcl";
149
#endif
150
 
151
    consoleInterp = Tcl_CreateInterp();
152
    if (consoleInterp == NULL) {
153
        goto error;
154
    }
155
 
156
    /*
157
     * Initialized Tcl and Tk.
158
     */
159
 
160
    if (Tcl_Init(consoleInterp) != TCL_OK) {
161
        goto error;
162
    }
163
    if (Tk_Init(consoleInterp) != TCL_OK) {
164
        goto error;
165
    }
166
    gStdoutInterp = interp;
167
 
168
    /*
169
     * Add console commands to the interp
170
     */
171
    info = (ConsoleInfo *) ckalloc(sizeof(ConsoleInfo));
172
    info->interp = interp;
173
    info->consoleInterp = consoleInterp;
174
    Tcl_CreateCommand(interp, "console", ConsoleCmd, (ClientData) info,
175
            (Tcl_CmdDeleteProc *) ConsoleDeleteProc);
176
    Tcl_CreateCommand(consoleInterp, "interp", InterpreterCmd,
177
            (ClientData) info, (Tcl_CmdDeleteProc *) NULL);
178
 
179
    Tk_CreateEventHandler(mainWindow, StructureNotifyMask, ConsoleEventProc,
180
            (ClientData) info);
181
 
182
    Tcl_Preserve((ClientData) consoleInterp);
183
    if (Tcl_Eval(consoleInterp, initCmd) == TCL_ERROR) {
184
        /* goto error; -- no problem for now... */
185
        printf("Eval error: %s", consoleInterp->result);
186
    }
187
    Tcl_Release((ClientData) consoleInterp);
188
    return TCL_OK;
189
 
190
    error:
191
    if (consoleInterp != NULL) {
192
        Tcl_DeleteInterp(consoleInterp);
193
    }
194
    return TCL_ERROR;
195
}
196
 
197
/*
198
 *----------------------------------------------------------------------
199
 *
200
 * ConsoleOutput--
201
 *
202
 *      Writes the given output on the IO channel. Returns count of how
203
 *      many characters were actually written, and an error indication.
204
 *
205
 * Results:
206
 *      A count of how many characters were written is returned and an
207
 *      error indication is returned in an output argument.
208
 *
209
 * Side effects:
210
 *      Writes output on the actual channel.
211
 *
212
 *----------------------------------------------------------------------
213
 */
214
 
215
        /* ARGSUSED */
216
static int
217
ConsoleOutput(instanceData, outFile, buf, toWrite, errorCode)
218
    ClientData instanceData;            /* Unused. */
219
    Tcl_File outFile;                   /* Output device for channel. */
220
    char *buf;                          /* The data buffer. */
221
    int toWrite;                        /* How many bytes to write? */
222
    int *errorCode;                     /* Where to store error code. */
223
{
224
    *errorCode = 0;
225
    Tcl_SetErrno(0);
226
 
227
    if (gStdoutInterp != NULL) {
228
        TkConsolePrint(gStdoutInterp, outFile, buf, toWrite);
229
    }
230
 
231
    return toWrite;
232
}
233
 
234
/*
235
 *----------------------------------------------------------------------
236
 *
237
 * ConsoleInput --
238
 *
239
 *      Read input from the console.  Not currently implemented.
240
 *
241
 * Results:
242
 *      Always returns EOF.
243
 *
244
 * Side effects:
245
 *      None.
246
 *
247
 *----------------------------------------------------------------------
248
 */
249
 
250
static int
251
ConsoleInput(instanceData, inFile, buf, bufSize, errorCode)
252
    ClientData instanceData;            /* Unused. */
253
    Tcl_File inFile;                    /* Input device for channel. */
254
    char *buf;                          /* Where to store data read. */
255
    int bufSize;                        /* How much space is available
256
                                         * in the buffer? */
257
    int *errorCode;                     /* Where to store error code. */
258
{
259
    return 0;                    /* Always return EOF. */
260
}
261
 
262
/*
263
 *----------------------------------------------------------------------
264
 *
265
 * ConsoleClose --
266
 *
267
 *      Closes the IO channel.
268
 *
269
 * Results:
270
 *      Always returns 0 (success).
271
 *
272
 * Side effects:
273
 *      Frees the dummy file associated with the channel.
274
 *
275
 *----------------------------------------------------------------------
276
 */
277
 
278
        /* ARGSUSED */
279
static int
280
ConsoleClose(instanceData, interp, inFile, outFile)
281
    ClientData instanceData;    /* Unused. */
282
    Tcl_Interp *interp; /* Unused. */
283
    Tcl_File inFile;            /* Input file to close. */
284
    Tcl_File outFile;           /* Output file to close. */
285
{
286
    if (inFile) {
287
        Tcl_FreeFile(inFile);
288
    }
289
    if (outFile && (outFile != inFile)) {
290
        Tcl_FreeFile(outFile);
291
    }
292
    return 0;
293
}
294
 
295
/*
296
 *----------------------------------------------------------------------
297
 *
298
 * ConsoleCmd --
299
 *
300
 *      The console command implements a Tcl interface to the various console
301
 *      options.
302
 *
303
 * Results:
304
 *      None.
305
 *
306
 * Side effects:
307
 *      None.
308
 *
309
 *----------------------------------------------------------------------
310
 */
311
 
312
static int
313
ConsoleCmd(clientData, interp, argc, argv)
314
    ClientData clientData;              /* Not used. */
315
    Tcl_Interp *interp;                 /* Current interpreter. */
316
    int argc;                           /* Number of arguments. */
317
    char **argv;                        /* Argument strings. */
318
{
319
    ConsoleInfo *info = (ConsoleInfo *) clientData;
320
    char c;
321
    int length;
322
    int result;
323
    Tcl_Interp *consoleInterp;
324
 
325
    if (argc < 2) {
326
        Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
327
                " option ?arg arg ...?\"", (char *) NULL);
328
        return TCL_ERROR;
329
    }
330
 
331
    c = argv[1][0];
332
    length = strlen(argv[1]);
333
    result = TCL_OK;
334
    consoleInterp = info->consoleInterp;
335
    Tcl_Preserve((ClientData) consoleInterp);
336
    if ((c == 't') && (strncmp(argv[1], "title", length)) == 0) {
337
        Tcl_DString dString;
338
        char *wmCmd = "wm title . {";
339
 
340
        Tcl_DStringInit(&dString);
341
        Tcl_DStringAppend(&dString, wmCmd, strlen(wmCmd));
342
        Tcl_DStringAppend(&dString, argv[2], strlen(argv[2]));
343
        Tcl_DStringAppend(&dString, "}", strlen("}"));
344
        Tcl_Eval(consoleInterp, dString.string);
345
        Tcl_DStringFree(&dString);
346
    } else if ((c == 'h') && (strncmp(argv[1], "hide", length)) == 0) {
347
        Tcl_Eval(info->consoleInterp, "wm withdraw .");
348
    } else if ((c == 's') && (strncmp(argv[1], "show", length)) == 0) {
349
        Tcl_Eval(info->consoleInterp, "wm deiconify .");
350
    } else {
351
        Tcl_AppendResult(interp, "bad option \"", argv[1],
352
                "\": should be hide, show, or title",
353
                (char *) NULL);
354
        result = TCL_ERROR;
355
    }
356
    Tcl_Release((ClientData) consoleInterp);
357
    return result;
358
} /* ConsoleCmd */
359
 
360
/*
361
 *----------------------------------------------------------------------
362
 *
363
 * InterpreterCmd --
364
 *
365
 *      This command allows the console interp to communicate with the
366
 *      main interpreter.
367
 *
368
 * Results:
369
 *      None.
370
 *
371
 * Side effects:
372
 *      None.
373
 *
374
 *----------------------------------------------------------------------
375
 */
376
 
377
static int
378
InterpreterCmd(clientData, interp, argc, argv)
379
    ClientData clientData;              /* Not used. */
380
    Tcl_Interp *interp;                 /* Current interpreter. */
381
    int argc;                           /* Number of arguments. */
382
    char **argv;                        /* Argument strings. */
383
{
384
    ConsoleInfo *info = (ConsoleInfo *) clientData;
385
    char c;
386
    int length;
387
    int result;
388
    Tcl_Interp *otherInterp;
389
 
390
    if (argc < 2) {
391
        Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
392
                " option ?arg arg ...?\"", (char *) NULL);
393
        return TCL_ERROR;
394
    }
395
 
396
    c = argv[1][0];
397
    length = strlen(argv[1]);
398
    result = TCL_OK;
399
    otherInterp = info->interp;
400
    Tcl_Preserve((ClientData) otherInterp);
401
    if ((c == 'e') && (strncmp(argv[1], "eval", length)) == 0) {
402
        result = Tcl_GlobalEval(otherInterp, argv[2]);
403
        Tcl_AppendResult(interp, otherInterp->result, (char *) NULL);
404
    } else if ((c == 'r') && (strncmp(argv[1], "record", length)) == 0) {
405
        Tcl_RecordAndEval(otherInterp, argv[2], TCL_EVAL_GLOBAL);
406
        result = TCL_OK;
407
        Tcl_AppendResult(interp, otherInterp->result, (char *) NULL);
408
    } else {
409
        Tcl_AppendResult(interp, "bad option \"", argv[1],
410
                "\": should be eval or record",
411
                (char *) NULL);
412
        result = TCL_ERROR;
413
    }
414
    Tcl_Release((ClientData) otherInterp);
415
    return result;
416
}
417
 
418
/*
419
 *----------------------------------------------------------------------
420
 *
421
 * ConsoleDeleteProc --
422
 *
423
 *      If the console command is deleted we destroy the console window
424
 *      and all associated data structures.
425
 *
426
 * Results:
427
 *      None.
428
 *
429
 * Side effects:
430
 *      A new console it created.
431
 *
432
 *----------------------------------------------------------------------
433
 */
434
 
435
void
436
ConsoleDeleteProc(clientData)
437
    ClientData clientData;
438
{
439
    ConsoleInfo *info = (ConsoleInfo *) clientData;
440
 
441
    Tcl_DeleteInterp(info->consoleInterp);
442
    info->consoleInterp = NULL;
443
}
444
 
445
/*
446
 *----------------------------------------------------------------------
447
 *
448
 * ConsoleEventProc --
449
 *
450
 *      This event procedure is registered on the main window of the
451
 *      slave interpreter.  If the user or a running script causes the
452
 *      main window to be destroyed, then we need to inform the console
453
 *      interpreter by invoking "tkConsoleExit".
454
 *
455
 * Results:
456
 *      None.
457
 *
458
 * Side effects:
459
 *      Invokes the "tkConsoleExit" procedure in the console interp.
460
 *
461
 *----------------------------------------------------------------------
462
 */
463
 
464
static void
465
ConsoleEventProc(clientData, eventPtr)
466
    ClientData clientData;
467
    XEvent *eventPtr;
468
{
469
    ConsoleInfo *info = (ConsoleInfo *) clientData;
470
    Tcl_Interp *consoleInterp;
471
 
472
    if (eventPtr->type == DestroyNotify) {
473
        consoleInterp = info->consoleInterp;
474
        Tcl_Preserve((ClientData) consoleInterp);
475
        Tcl_Eval(consoleInterp, "tkConsoleExit");
476
        Tcl_Release((ClientData) consoleInterp);
477
    }
478
}
479
 
480
/*
481
 *----------------------------------------------------------------------
482
 *
483
 * TkConsolePrint --
484
 *
485
 *      Prints to the give text to the console.  Given the main interp
486
 *      this functions find the appropiate console interp and forwards
487
 *      the text to be added to that console.
488
 *
489
 * Results:
490
 *      None.
491
 *
492
 * Side effects:
493
 *      None.
494
 *
495
 *----------------------------------------------------------------------
496
 */
497
 
498
void
499
TkConsolePrint(interp, outFile, buffer, size)
500
    Tcl_Interp *interp;         /* Main interpreter. */
501
    Tcl_File outFile;           /* Should be stdout or stderr. */
502
    char *buffer;               /* Text buffer. */
503
    long size;                  /* Size of text buffer. */
504
{
505
    Tcl_DString command, output;
506
    Tcl_CmdInfo cmdInfo;
507
    char *cmd;
508
    ConsoleInfo *info;
509
    Tcl_Interp *consoleInterp;
510
    int result;
511
    int fd = (int) Tcl_GetFileInfo(outFile, NULL);
512
 
513
    if (interp == NULL) {
514
        return;
515
    }
516
 
517
    if (fd == 2) {
518
        cmd = "tkConsoleOutput stderr ";
519
    } else {
520
        cmd = "tkConsoleOutput stdout ";
521
    }
522
 
523
    result = Tcl_GetCommandInfo(interp, "console", &cmdInfo);
524
    if (result == 0) {
525
        return;
526
    }
527
    info = (ConsoleInfo *) cmdInfo.clientData;
528
 
529
    Tcl_DStringInit(&output);
530
    Tcl_DStringAppend(&output, buffer, size);
531
 
532
    Tcl_DStringInit(&command);
533
    Tcl_DStringAppend(&command, cmd, strlen(cmd));
534
    Tcl_DStringAppendElement(&command, output.string);
535
 
536
    consoleInterp = info->consoleInterp;
537
    Tcl_Preserve((ClientData) consoleInterp);
538
    Tcl_Eval(consoleInterp, command.string);
539
    Tcl_Release((ClientData) consoleInterp);
540
 
541
    Tcl_DStringFree(&command);
542
    Tcl_DStringFree(&output);
543
}

powered by: WebSVN 2.1.0

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