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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [tix/] [win/] [tkConsole80a1.c] - Blame information for rev 1765

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

powered by: WebSVN 2.1.0

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