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

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [insight/] [tix/] [win/] [tkConsole81.c] - Blame information for rev 1782

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.51 97/04/25 16:52:39
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
                    char *buf, int toRead, int *errorCode));
45
static int      ConsoleOutput _ANSI_ARGS_((ClientData instanceData,
46
                    char *buf, int toWrite, int *errorCode));
47
static int      ConsoleClose _ANSI_ARGS_((ClientData instanceData,
48
                    Tcl_Interp *interp));
49
static void     ConsoleWatch _ANSI_ARGS_((ClientData instanceData,
50
                    int mask));
51
static int      ConsoleHandle _ANSI_ARGS_((ClientData instanceData,
52
                    int direction, ClientData *handlePtr));
53
 
54
 
55
void TkConsolePrint (Tcl_Interp *interp, int devId, char *buffer, long size);                   /* Size of text buffer. */
56
 
57
/*
58
 * This structure describes the channel type structure for file based IO:
59
 */
60
 
61
static Tcl_ChannelType consoleChannelType = {
62
    "console",                  /* Type name. */
63
    NULL,                       /* Always non-blocking.*/
64
    ConsoleClose,               /* Close proc. */
65
    ConsoleInput,               /* Input proc. */
66
    ConsoleOutput,              /* Output proc. */
67
    NULL,                       /* Seek proc. */
68
    NULL,                       /* Set option proc. */
69
    NULL,                       /* Get option proc. */
70
    ConsoleWatch,               /* Watch for events on console. */
71
    ConsoleHandle,              /* Get a handle from the device. */
72
};
73
 
74
/*
75
 *----------------------------------------------------------------------
76
 *
77
 * TkConsoleCreate --
78
 *
79
 *      Create the console channels and install them as the standard
80
 *      channels.  All I/O will be discarded until TkConsoleInit is
81
 *      called to attach the console to a text widget.
82
 *
83
 * Results:
84
 *      None.
85
 *
86
 * Side effects:
87
 *      Creates the console channel and installs it as the standard
88
 *      channels.
89
 *
90
 *----------------------------------------------------------------------
91
 */
92
 
93
void
94
TkConsoleCreate()
95
{
96
    Tcl_Channel consoleChannel;
97
 
98
    TclInitSubsystems(NULL);
99
 
100
    consoleChannel = Tcl_CreateChannel(&consoleChannelType, "console0",
101
            (ClientData) TCL_STDIN, TCL_READABLE);
102
    if (consoleChannel != NULL) {
103
        Tcl_SetChannelOption(NULL, consoleChannel, "-translation", "lf");
104
        Tcl_SetChannelOption(NULL, consoleChannel, "-buffering", "none");
105
    }
106
    Tcl_SetStdChannel(consoleChannel, TCL_STDIN);
107
    consoleChannel = Tcl_CreateChannel(&consoleChannelType, "console1",
108
            (ClientData) TCL_STDOUT, TCL_WRITABLE);
109
    if (consoleChannel != NULL) {
110
        Tcl_SetChannelOption(NULL, consoleChannel, "-translation", "lf");
111
        Tcl_SetChannelOption(NULL, consoleChannel, "-buffering", "none");
112
    }
113
    Tcl_SetStdChannel(consoleChannel, TCL_STDOUT);
114
    consoleChannel = Tcl_CreateChannel(&consoleChannelType, "console2",
115
            (ClientData) TCL_STDERR, TCL_WRITABLE);
116
    if (consoleChannel != NULL) {
117
        Tcl_SetChannelOption(NULL, consoleChannel, "-translation", "lf");
118
        Tcl_SetChannelOption(NULL, consoleChannel, "-buffering", "none");
119
    }
120
    Tcl_SetStdChannel(consoleChannel, TCL_STDERR);
121
}
122
 
123
/*
124
 *----------------------------------------------------------------------
125
 *
126
 * TkConsoleInit --
127
 *
128
 *      Initialize the console.  This code actually creates a new
129
 *      application and associated interpreter.  This effectivly hides
130
 *      the implementation from the main application.
131
 *
132
 * Results:
133
 *      None.
134
 *
135
 * Side effects:
136
 *      A new console it created.
137
 *
138
 *----------------------------------------------------------------------
139
 */
140
 
141
int
142
TkConsoleInit(interp)
143
    Tcl_Interp *interp;                 /* Interpreter to use for prompting. */
144
{
145
    Tcl_Interp *consoleInterp;
146
    ConsoleInfo *info;
147
    Tk_Window mainWindow = Tk_MainWindow(interp);
148
#ifdef MAC_TCL
149
    static char initCmd[] = "source -rsrc {Console}";
150
#else
151
    static char initCmd[] = "source $tk_library/console.tcl";
152
#endif
153
 
154
    consoleInterp = Tcl_CreateInterp();
155
    if (consoleInterp == NULL) {
156
        goto error;
157
    }
158
 
159
    /*
160
     * Initialized Tcl and Tk.
161
     */
162
 
163
    if (Tcl_Init(consoleInterp) != TCL_OK) {
164
        goto error;
165
    }
166
    if (Tk_Init(consoleInterp) != TCL_OK) {
167
        goto error;
168
    }
169
    gStdoutInterp = interp;
170
 
171
    /*
172
     * Add console commands to the interp
173
     */
174
    info = (ConsoleInfo *) ckalloc(sizeof(ConsoleInfo));
175
    info->interp = interp;
176
    info->consoleInterp = consoleInterp;
177
    Tcl_CreateCommand(interp, "console", ConsoleCmd, (ClientData) info,
178
            (Tcl_CmdDeleteProc *) ConsoleDeleteProc);
179
    Tcl_CreateCommand(consoleInterp, "consoleinterp", InterpreterCmd,
180
            (ClientData) info, (Tcl_CmdDeleteProc *) NULL);
181
 
182
    Tk_CreateEventHandler(mainWindow, StructureNotifyMask, ConsoleEventProc,
183
            (ClientData) info);
184
 
185
    Tcl_Preserve((ClientData) consoleInterp);
186
    if (Tcl_Eval(consoleInterp, initCmd) == TCL_ERROR) {
187
        /* goto error; -- no problem for now... */
188
        printf("Eval error: %s", consoleInterp->result);
189
    }
190
    Tcl_Release((ClientData) consoleInterp);
191
    return TCL_OK;
192
 
193
    error:
194
    if (consoleInterp != NULL) {
195
        Tcl_DeleteInterp(consoleInterp);
196
    }
197
    return TCL_ERROR;
198
}
199
 
200
/*
201
 *----------------------------------------------------------------------
202
 *
203
 * ConsoleOutput--
204
 *
205
 *      Writes the given output on the IO channel. Returns count of how
206
 *      many characters were actually written, and an error indication.
207
 *
208
 * Results:
209
 *      A count of how many characters were written is returned and an
210
 *      error indication is returned in an output argument.
211
 *
212
 * Side effects:
213
 *      Writes output on the actual channel.
214
 *
215
 *----------------------------------------------------------------------
216
 */
217
 
218
static int
219
ConsoleOutput(instanceData, buf, toWrite, errorCode)
220
    ClientData instanceData;            /* Indicates which device to use. */
221
    char *buf;                          /* The data buffer. */
222
    int toWrite;                        /* How many bytes to write? */
223
    int *errorCode;                     /* Where to store error code. */
224
{
225
    *errorCode = 0;
226
    Tcl_SetErrno(0);
227
 
228
    if (gStdoutInterp != NULL) {
229
        TkConsolePrint(gStdoutInterp, (int) instanceData, buf, toWrite);
230
    }
231
 
232
    return toWrite;
233
}
234
 
235
/*
236
 *----------------------------------------------------------------------
237
 *
238
 * ConsoleInput --
239
 *
240
 *      Read input from the console.  Not currently implemented.
241
 *
242
 * Results:
243
 *      Always returns EOF.
244
 *
245
 * Side effects:
246
 *      None.
247
 *
248
 *----------------------------------------------------------------------
249
 */
250
 
251
        /* ARGSUSED */
252
static int
253
ConsoleInput(instanceData, buf, bufSize, errorCode)
254
    ClientData instanceData;            /* Unused. */
255
    char *buf;                          /* Where to store data read. */
256
    int bufSize;                        /* How much space is available
257
                                         * in the buffer? */
258
    int *errorCode;                     /* Where to store error code. */
259
{
260
    return 0;                    /* Always return EOF. */
261
}
262
 
263
/*
264
 *----------------------------------------------------------------------
265
 *
266
 * ConsoleClose --
267
 *
268
 *      Closes the IO channel.
269
 *
270
 * Results:
271
 *      Always returns 0 (success).
272
 *
273
 * Side effects:
274
 *      Frees the dummy file associated with the channel.
275
 *
276
 *----------------------------------------------------------------------
277
 */
278
 
279
        /* ARGSUSED */
280
static int
281
ConsoleClose(instanceData, interp)
282
    ClientData instanceData;    /* Unused. */
283
    Tcl_Interp *interp;         /* Unused. */
284
{
285
    return 0;
286
}
287
 
288
/*
289
 *----------------------------------------------------------------------
290
 *
291
 * ConsoleWatch --
292
 *
293
 *      Called by the notifier to set up the console device so that
294
 *      events will be noticed. Since there are no events on the
295
 *      console, this routine just returns without doing anything.
296
 *
297
 * Results:
298
 *      None.
299
 *
300
 * Side effects:
301
 *      None.
302
 *
303
 *----------------------------------------------------------------------
304
 */
305
 
306
        /* ARGSUSED */
307
static void
308
ConsoleWatch(instanceData, mask)
309
    ClientData instanceData;            /* Device ID for the channel. */
310
    int mask;                           /* OR-ed combination of
311
                                         * TCL_READABLE, TCL_WRITABLE and
312
                                         * TCL_EXCEPTION, for the events
313
                                         * we are interested in. */
314
{
315
}
316
 
317
/*
318
 *----------------------------------------------------------------------
319
 *
320
 * ConsoleHandle --
321
 *
322
 *      Invoked by the generic IO layer to get a handle from a channel.
323
 *      Because console channels are not devices, this function always
324
 *      fails.
325
 *
326
 * Results:
327
 *      Always returns TCL_ERROR.
328
 *
329
 * Side effects:
330
 *      None.
331
 *
332
 *----------------------------------------------------------------------
333
 */
334
 
335
        /* ARGSUSED */
336
static int
337
ConsoleHandle(instanceData, direction, handlePtr)
338
    ClientData instanceData;    /* Device ID for the channel. */
339
    int direction;              /* TCL_READABLE or TCL_WRITABLE to indicate
340
                                 * which direction of the channel is being
341
                                 * requested. */
342
    ClientData *handlePtr;      /* Where to store handle */
343
{
344
    return TCL_ERROR;
345
}
346
 
347
/*
348
 *----------------------------------------------------------------------
349
 *
350
 * ConsoleCmd --
351
 *
352
 *      The console command implements a Tcl interface to the various console
353
 *      options.
354
 *
355
 * Results:
356
 *      None.
357
 *
358
 * Side effects:
359
 *      None.
360
 *
361
 *----------------------------------------------------------------------
362
 */
363
 
364
static int
365
ConsoleCmd(clientData, interp, argc, argv)
366
    ClientData clientData;              /* Not used. */
367
    Tcl_Interp *interp;                 /* Current interpreter. */
368
    int argc;                           /* Number of arguments. */
369
    char **argv;                        /* Argument strings. */
370
{
371
    ConsoleInfo *info = (ConsoleInfo *) clientData;
372
    char c;
373
    int length;
374
    int result;
375
    Tcl_Interp *consoleInterp;
376
 
377
    if (argc < 2) {
378
        Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
379
                " option ?arg arg ...?\"", (char *) NULL);
380
        return TCL_ERROR;
381
    }
382
 
383
    c = argv[1][0];
384
    length = strlen(argv[1]);
385
    result = TCL_OK;
386
    consoleInterp = info->consoleInterp;
387
    Tcl_Preserve((ClientData) consoleInterp);
388
    if ((c == 't') && (strncmp(argv[1], "title", length)) == 0) {
389
        Tcl_DString dString;
390
 
391
        Tcl_DStringInit(&dString);
392
        Tcl_DStringAppend(&dString, "wm title . ", -1);
393
        if (argc == 3) {
394
            Tcl_DStringAppendElement(&dString, argv[2]);
395
        }
396
        Tcl_Eval(consoleInterp, Tcl_DStringValue(&dString));
397
        Tcl_DStringFree(&dString);
398
    } else if ((c == 'h') && (strncmp(argv[1], "hide", length)) == 0) {
399
        Tcl_Eval(info->consoleInterp, "wm withdraw .");
400
    } else if ((c == 's') && (strncmp(argv[1], "show", length)) == 0) {
401
        Tcl_Eval(info->consoleInterp, "wm deiconify .");
402
    } else if ((c == 'e') && (strncmp(argv[1], "eval", length)) == 0) {
403
        if (argc == 3) {
404
            Tcl_Eval(info->consoleInterp, argv[2]);
405
        } else {
406
            Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
407
                    " eval command\"", (char *) NULL);
408
            return TCL_ERROR;
409
        }
410
    } else {
411
        Tcl_AppendResult(interp, "bad option \"", argv[1],
412
                "\": should be hide, show, or title",
413
                (char *) NULL);
414
        result = TCL_ERROR;
415
    }
416
    Tcl_Release((ClientData) consoleInterp);
417
    return result;
418
}
419
 
420
/*
421
 *----------------------------------------------------------------------
422
 *
423
 * InterpreterCmd --
424
 *
425
 *      This command allows the console interp to communicate with the
426
 *      main interpreter.
427
 *
428
 * Results:
429
 *      None.
430
 *
431
 * Side effects:
432
 *      None.
433
 *
434
 *----------------------------------------------------------------------
435
 */
436
 
437
static int
438
InterpreterCmd(clientData, interp, argc, argv)
439
    ClientData clientData;              /* Not used. */
440
    Tcl_Interp *interp;                 /* Current interpreter. */
441
    int argc;                           /* Number of arguments. */
442
    char **argv;                        /* Argument strings. */
443
{
444
    ConsoleInfo *info = (ConsoleInfo *) clientData;
445
    char c;
446
    int length;
447
    int result;
448
    Tcl_Interp *otherInterp;
449
 
450
    if (argc < 2) {
451
        Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
452
                " option ?arg arg ...?\"", (char *) NULL);
453
        return TCL_ERROR;
454
    }
455
 
456
    c = argv[1][0];
457
    length = strlen(argv[1]);
458
    otherInterp = info->interp;
459
    Tcl_Preserve((ClientData) otherInterp);
460
    if ((c == 'e') && (strncmp(argv[1], "eval", length)) == 0) {
461
        result = Tcl_GlobalEval(otherInterp, argv[2]);
462
        Tcl_AppendResult(interp, otherInterp->result, (char *) NULL);
463
    } else if ((c == 'r') && (strncmp(argv[1], "record", length)) == 0) {
464
        Tcl_RecordAndEval(otherInterp, argv[2], TCL_EVAL_GLOBAL);
465
        result = TCL_OK;
466
        Tcl_AppendResult(interp, otherInterp->result, (char *) NULL);
467
    } else {
468
        Tcl_AppendResult(interp, "bad option \"", argv[1],
469
                "\": should be eval or record",
470
                (char *) NULL);
471
        result = TCL_ERROR;
472
    }
473
    Tcl_Release((ClientData) otherInterp);
474
    return result;
475
}
476
 
477
/*
478
 *----------------------------------------------------------------------
479
 *
480
 * ConsoleDeleteProc --
481
 *
482
 *      If the console command is deleted we destroy the console window
483
 *      and all associated data structures.
484
 *
485
 * Results:
486
 *      None.
487
 *
488
 * Side effects:
489
 *      A new console it created.
490
 *
491
 *----------------------------------------------------------------------
492
 */
493
 
494
void
495
ConsoleDeleteProc(clientData)
496
    ClientData clientData;
497
{
498
    ConsoleInfo *info = (ConsoleInfo *) clientData;
499
 
500
    Tcl_DeleteInterp(info->consoleInterp);
501
    info->consoleInterp = NULL;
502
}
503
 
504
/*
505
 *----------------------------------------------------------------------
506
 *
507
 * ConsoleEventProc --
508
 *
509
 *      This event procedure is registered on the main window of the
510
 *      slave interpreter.  If the user or a running script causes the
511
 *      main window to be destroyed, then we need to inform the console
512
 *      interpreter by invoking "tkConsoleExit".
513
 *
514
 * Results:
515
 *      None.
516
 *
517
 * Side effects:
518
 *      Invokes the "tkConsoleExit" procedure in the console interp.
519
 *
520
 *----------------------------------------------------------------------
521
 */
522
 
523
static void
524
ConsoleEventProc(clientData, eventPtr)
525
    ClientData clientData;
526
    XEvent *eventPtr;
527
{
528
    ConsoleInfo *info = (ConsoleInfo *) clientData;
529
    Tcl_Interp *consoleInterp;
530
 
531
    if (eventPtr->type == DestroyNotify) {
532
        consoleInterp = info->consoleInterp;
533
 
534
        /*
535
         * It is possible that the console interpreter itself has
536
         * already been deleted. In that case the consoleInterp
537
         * field will be set to NULL. If the interpreter is already
538
         * gone, we do not have to do any work here.
539
         */
540
 
541
        if (consoleInterp == (Tcl_Interp *) NULL) {
542
            return;
543
        }
544
        Tcl_Preserve((ClientData) consoleInterp);
545
        Tcl_Eval(consoleInterp, "tkConsoleExit");
546
        Tcl_Release((ClientData) consoleInterp);
547
    }
548
}
549
 
550
/*
551
 *----------------------------------------------------------------------
552
 *
553
 * TkConsolePrint --
554
 *
555
 *      Prints to the give text to the console.  Given the main interp
556
 *      this functions find the appropiate console interp and forwards
557
 *      the text to be added to that console.
558
 *
559
 * Results:
560
 *      None.
561
 *
562
 * Side effects:
563
 *      None.
564
 *
565
 *----------------------------------------------------------------------
566
 */
567
 
568
void
569
TkConsolePrint(interp, devId, buffer, size)
570
    Tcl_Interp *interp;         /* Main interpreter. */
571
    int devId;                  /* TCL_STDOUT for stdout, TCL_STDERR for
572
                                 * stderr. */
573
    char *buffer;               /* Text buffer. */
574
    long size;                  /* Size of text buffer. */
575
{
576
    Tcl_DString command, output;
577
    Tcl_CmdInfo cmdInfo;
578
    char *cmd;
579
    ConsoleInfo *info;
580
    Tcl_Interp *consoleInterp;
581
    int result;
582
 
583
    if (interp == NULL) {
584
        return;
585
    }
586
 
587
    if (devId == TCL_STDERR) {
588
        cmd = "tkConsoleOutput stderr ";
589
    } else {
590
        cmd = "tkConsoleOutput stdout ";
591
    }
592
 
593
    result = Tcl_GetCommandInfo(interp, "console", &cmdInfo);
594
    if (result == 0) {
595
        return;
596
    }
597
    info = (ConsoleInfo *) cmdInfo.clientData;
598
 
599
    Tcl_DStringInit(&output);
600
    Tcl_DStringAppend(&output, buffer, size);
601
 
602
    Tcl_DStringInit(&command);
603
    Tcl_DStringAppend(&command, cmd, strlen(cmd));
604
    Tcl_DStringAppendElement(&command, output.string);
605
 
606
    consoleInterp = info->consoleInterp;
607
    Tcl_Preserve((ClientData) consoleInterp);
608
    Tcl_Eval(consoleInterp, command.string);
609
    Tcl_Release((ClientData) consoleInterp);
610
 
611
    Tcl_DStringFree(&command);
612
    Tcl_DStringFree(&output);
613
}

powered by: WebSVN 2.1.0

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