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

Subversion Repositories or1k

[/] [or1k/] [tags/] [start/] [insight/] [tk/] [generic/] [tkSelect.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
 * tkSelect.c --
3
 *
4
 *      This file manages the selection for the Tk toolkit,
5
 *      translating between the standard X ICCCM conventions
6
 *      and Tcl commands.
7
 *
8
 * Copyright (c) 1990-1993 The Regents of the University of California.
9
 * Copyright (c) 1994-1995 Sun Microsystems, Inc.
10
 *
11
 * See the file "license.terms" for information on usage and redistribution
12
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
13
 *
14
 * RCS: @(#) $Id: tkSelect.c,v 1.1.1.1 2002-01-16 10:25:52 markom Exp $
15
 */
16
 
17
#include "tkInt.h"
18
#include "tkSelect.h"
19
 
20
/*
21
 * When a selection handler is set up by invoking "selection handle",
22
 * one of the following data structures is set up to hold information
23
 * about the command to invoke and its interpreter.
24
 */
25
 
26
typedef struct {
27
    Tcl_Interp *interp;         /* Interpreter in which to invoke command. */
28
    int cmdLength;              /* # of non-NULL bytes in command. */
29
    char command[4];            /* Command to invoke.  Actual space is
30
                                 * allocated as large as necessary.  This
31
                                 * must be the last entry in the structure. */
32
} CommandInfo;
33
 
34
/*
35
 * When selection ownership is claimed with the "selection own" Tcl command,
36
 * one of the following structures is created to record the Tcl command
37
 * to be executed when the selection is lost again.
38
 */
39
 
40
typedef struct LostCommand {
41
    Tcl_Interp *interp;         /* Interpreter in which to invoke command. */
42
    char command[4];            /* Command to invoke.  Actual space is
43
                                 * allocated as large as necessary.  This
44
                                 * must be the last entry in the structure. */
45
} LostCommand;
46
 
47
/*
48
 * Shared variables:
49
 */
50
 
51
TkSelInProgress *pendingPtr = NULL;
52
                                /* Topmost search in progress, or
53
                                 * NULL if none. */
54
 
55
/*
56
 * Forward declarations for procedures defined in this file:
57
 */
58
 
59
static int              HandleTclCommand _ANSI_ARGS_((ClientData clientData,
60
                            int offset, char *buffer, int maxBytes));
61
static void             LostSelection _ANSI_ARGS_((ClientData clientData));
62
static int              SelGetProc _ANSI_ARGS_((ClientData clientData,
63
                            Tcl_Interp *interp, char *portion));
64
 
65
/*
66
 *--------------------------------------------------------------
67
 *
68
 * Tk_CreateSelHandler --
69
 *
70
 *      This procedure is called to register a procedure
71
 *      as the handler for selection requests of a particular
72
 *      target type on a particular window for a particular
73
 *      selection.
74
 *
75
 * Results:
76
 *      None.
77
 *
78
 * Side effects:
79
 *      In the future, whenever the selection is in tkwin's
80
 *      window and someone requests the selection in the
81
 *      form given by target, proc will be invoked to provide
82
 *      part or all of the selection in the given form.  If
83
 *      there was already a handler declared for the given
84
 *      window, target and selection type, then it is replaced.
85
 *      Proc should have the following form:
86
 *
87
 *      int
88
 *      proc(clientData, offset, buffer, maxBytes)
89
 *          ClientData clientData;
90
 *          int offset;
91
 *          char *buffer;
92
 *          int maxBytes;
93
 *      {
94
 *      }
95
 *
96
 *      The clientData argument to proc will be the same as
97
 *      the clientData argument to this procedure.  The offset
98
 *      argument indicates which portion of the selection to
99
 *      return:  skip the first offset bytes.  Buffer is a
100
 *      pointer to an area in which to place the converted
101
 *      selection, and maxBytes gives the number of bytes
102
 *      available at buffer.  Proc should place the selection
103
 *      in buffer as a string, and return a count of the number
104
 *      of bytes of selection actually placed in buffer (not
105
 *      including the terminating NULL character).  If the
106
 *      return value equals maxBytes, this is a sign that there
107
 *      is probably still more selection information available.
108
 *
109
 *--------------------------------------------------------------
110
 */
111
 
112
void
113
Tk_CreateSelHandler(tkwin, selection, target, proc, clientData, format)
114
    Tk_Window tkwin;            /* Token for window. */
115
    Atom selection;             /* Selection to be handled. */
116
    Atom target;                /* The kind of selection conversions
117
                                 * that can be handled by proc,
118
                                 * e.g. TARGETS or STRING. */
119
    Tk_SelectionProc *proc;     /* Procedure to invoke to convert
120
                                 * selection to type "target". */
121
    ClientData clientData;      /* Value to pass to proc. */
122
    Atom format;                /* Format in which the selection
123
                                 * information should be returned to
124
                                 * the requestor. XA_STRING is best by
125
                                 * far, but anything listed in the ICCCM
126
                                 * will be tolerated (blech). */
127
{
128
    register TkSelHandler *selPtr;
129
    TkWindow *winPtr = (TkWindow *) tkwin;
130
 
131
    if (winPtr->dispPtr->multipleAtom == None) {
132
        TkSelInit(tkwin);
133
    }
134
 
135
    /*
136
     * See if there's already a handler for this target and selection on
137
     * this window.  If so, re-use it.  If not, create a new one.
138
     */
139
 
140
    for (selPtr = winPtr->selHandlerList; ; selPtr = selPtr->nextPtr) {
141
        if (selPtr == NULL) {
142
            selPtr = (TkSelHandler *) ckalloc(sizeof(TkSelHandler));
143
            selPtr->nextPtr = winPtr->selHandlerList;
144
            winPtr->selHandlerList = selPtr;
145
            break;
146
        }
147
        if ((selPtr->selection == selection) && (selPtr->target == target)) {
148
 
149
            /*
150
             * Special case:  when replacing handler created by
151
             * "selection handle", free up memory.  Should there be a
152
             * callback to allow other clients to do this too?
153
             */
154
 
155
            if (selPtr->proc == HandleTclCommand) {
156
                ckfree((char *) selPtr->clientData);
157
            }
158
            break;
159
        }
160
    }
161
    selPtr->selection = selection;
162
    selPtr->target = target;
163
    selPtr->format = format;
164
    selPtr->proc = proc;
165
    selPtr->clientData = clientData;
166
    if (format == XA_STRING) {
167
        selPtr->size = 8;
168
    } else {
169
        selPtr->size = 32;
170
    }
171
}
172
 
173
/*
174
 *----------------------------------------------------------------------
175
 *
176
 * Tk_DeleteSelHandler --
177
 *
178
 *      Remove the selection handler for a given window, target, and
179
 *      selection, if it exists.
180
 *
181
 * Results:
182
 *      None.
183
 *
184
 * Side effects:
185
 *      The selection handler for tkwin and target is removed.  If there
186
 *      is no such handler then nothing happens.
187
 *
188
 *----------------------------------------------------------------------
189
 */
190
 
191
void
192
Tk_DeleteSelHandler(tkwin, selection, target)
193
    Tk_Window tkwin;                    /* Token for window. */
194
    Atom selection;                     /* The selection whose handler
195
                                         * is to be removed. */
196
    Atom target;                        /* The target whose selection
197
                                         * handler is to be removed. */
198
{
199
    TkWindow *winPtr = (TkWindow *) tkwin;
200
    register TkSelHandler *selPtr, *prevPtr;
201
    register TkSelInProgress *ipPtr;
202
 
203
    /*
204
     * Find the selection handler to be deleted, or return if it doesn't
205
     * exist.
206
     */
207
 
208
    for (selPtr = winPtr->selHandlerList, prevPtr = NULL; ;
209
            prevPtr = selPtr, selPtr = selPtr->nextPtr) {
210
        if (selPtr == NULL) {
211
            return;
212
        }
213
        if ((selPtr->selection == selection) && (selPtr->target == target)) {
214
            break;
215
        }
216
    }
217
 
218
    /*
219
     * If ConvertSelection is processing this handler, tell it that the
220
     * handler is dead.
221
     */
222
 
223
    for (ipPtr = pendingPtr; ipPtr != NULL; ipPtr = ipPtr->nextPtr) {
224
        if (ipPtr->selPtr == selPtr) {
225
            ipPtr->selPtr = NULL;
226
        }
227
    }
228
 
229
    /*
230
     * Free resources associated with the handler.
231
     */
232
 
233
    if (prevPtr == NULL) {
234
        winPtr->selHandlerList = selPtr->nextPtr;
235
    } else {
236
        prevPtr->nextPtr = selPtr->nextPtr;
237
    }
238
    if (selPtr->proc == HandleTclCommand) {
239
        ckfree((char *) selPtr->clientData);
240
    }
241
    ckfree((char *) selPtr);
242
}
243
 
244
/*
245
 *--------------------------------------------------------------
246
 *
247
 * Tk_OwnSelection --
248
 *
249
 *      Arrange for tkwin to become the owner of a selection.
250
 *
251
 * Results:
252
 *      None.
253
 *
254
 * Side effects:
255
 *      From now on, requests for the selection will be directed
256
 *      to procedures associated with tkwin (they must have been
257
 *      declared with calls to Tk_CreateSelHandler).  When the
258
 *      selection is lost by this window, proc will be invoked
259
 *      (see the manual entry for details).  This procedure may
260
 *      invoke callbacks, including Tcl scripts, so any calling
261
 *      function should be reentrant at the point where
262
 *      Tk_OwnSelection is invoked.
263
 *
264
 *--------------------------------------------------------------
265
 */
266
 
267
void
268
Tk_OwnSelection(tkwin, selection, proc, clientData)
269
    Tk_Window tkwin;            /* Window to become new selection
270
                                 * owner. */
271
    Atom selection;             /* Selection that window should own. */
272
    Tk_LostSelProc *proc;       /* Procedure to call when selection
273
                                 * is taken away from tkwin. */
274
    ClientData clientData;      /* Arbitrary one-word argument to
275
                                 * pass to proc. */
276
{
277
    register TkWindow *winPtr = (TkWindow *) tkwin;
278
    TkDisplay *dispPtr = winPtr->dispPtr;
279
    TkSelectionInfo *infoPtr;
280
    Tk_LostSelProc *clearProc = NULL;
281
    ClientData clearData = NULL;        /* Initialization needed only to
282
                                         * prevent compiler warning. */
283
 
284
 
285
    if (dispPtr->multipleAtom == None) {
286
        TkSelInit(tkwin);
287
    }
288
    Tk_MakeWindowExist(tkwin);
289
 
290
    /*
291
     * This code is somewhat tricky.  First, we find the specified selection
292
     * on the selection list.  If the previous owner is in this process, and
293
     * is a different window, then we need to invoke the clearProc.  However,
294
     * it's dangerous to call the clearProc right now, because it could
295
     * invoke a Tcl script that wrecks the current state (e.g. it could
296
     * delete the window).  To be safe, defer the call until the end of the
297
     * procedure when we no longer care about the state.
298
     */
299
 
300
    for (infoPtr = dispPtr->selectionInfoPtr; infoPtr != NULL;
301
            infoPtr = infoPtr->nextPtr) {
302
        if (infoPtr->selection == selection) {
303
            break;
304
        }
305
    }
306
    if (infoPtr == NULL) {
307
        infoPtr = (TkSelectionInfo*) ckalloc(sizeof(TkSelectionInfo));
308
        infoPtr->selection = selection;
309
        infoPtr->nextPtr = dispPtr->selectionInfoPtr;
310
        dispPtr->selectionInfoPtr = infoPtr;
311
    } else if (infoPtr->clearProc != NULL) {
312
        if (infoPtr->owner != tkwin) {
313
            clearProc = infoPtr->clearProc;
314
            clearData = infoPtr->clearData;
315
        } else if (infoPtr->clearProc == LostSelection) {
316
            /*
317
             * If the selection handler is one created by "selection own",
318
             * be sure to free the record for it;  otherwise there will be
319
             * a memory leak.
320
             */
321
 
322
            ckfree((char *) infoPtr->clearData);
323
        }
324
    }
325
 
326
    infoPtr->owner = tkwin;
327
    infoPtr->serial = NextRequest(winPtr->display);
328
    infoPtr->clearProc = proc;
329
    infoPtr->clearData = clientData;
330
 
331
    /*
332
     * Note that we are using CurrentTime, even though ICCCM recommends against
333
     * this practice (the problem is that we don't necessarily have a valid
334
     * time to use).  We will not be able to retrieve a useful timestamp for
335
     * the TIMESTAMP target later.
336
     */
337
 
338
    infoPtr->time = CurrentTime;
339
 
340
    /*
341
     * Note that we are not checking to see if the selection claim succeeded.
342
     * If the ownership does not change, then the clearProc may never be
343
     * invoked, and we will return incorrect information when queried for the
344
     * current selection owner.
345
     */
346
 
347
    XSetSelectionOwner(winPtr->display, infoPtr->selection, winPtr->window,
348
            infoPtr->time);
349
 
350
    /*
351
     * Now that we are done, we can invoke clearProc without running into
352
     * reentrancy problems.
353
     */
354
 
355
    if (clearProc != NULL) {
356
        (*clearProc)(clearData);
357
    }
358
}
359
 
360
/*
361
 *----------------------------------------------------------------------
362
 *
363
 * Tk_ClearSelection --
364
 *
365
 *      Eliminate the specified selection on tkwin's display, if there is one.
366
 *
367
 * Results:
368
 *      None.
369
 *
370
 * Side effects:
371
 *      The specified selection is cleared, so that future requests to retrieve
372
 *      it will fail until some application owns it again.  This procedure
373
 *      invokes callbacks, possibly including Tcl scripts, so any calling
374
 *      function should be reentrant at the point Tk_ClearSelection is invoked.
375
 *
376
 *----------------------------------------------------------------------
377
 */
378
 
379
void
380
Tk_ClearSelection(tkwin, selection)
381
    Tk_Window tkwin;            /* Window that selects a display. */
382
    Atom selection;             /* Selection to be cancelled. */
383
{
384
    register TkWindow *winPtr = (TkWindow *) tkwin;
385
    TkDisplay *dispPtr = winPtr->dispPtr;
386
    TkSelectionInfo *infoPtr;
387
    TkSelectionInfo *prevPtr;
388
    TkSelectionInfo *nextPtr;
389
    Tk_LostSelProc *clearProc = NULL;
390
    ClientData clearData = NULL;        /* Initialization needed only to
391
                                         * prevent compiler warning. */
392
 
393
    if (dispPtr->multipleAtom == None) {
394
        TkSelInit(tkwin);
395
    }
396
 
397
    for (infoPtr = dispPtr->selectionInfoPtr, prevPtr = NULL;
398
             infoPtr != NULL; infoPtr = nextPtr) {
399
        nextPtr = infoPtr->nextPtr;
400
        if (infoPtr->selection == selection) {
401
            if (prevPtr == NULL) {
402
                dispPtr->selectionInfoPtr = nextPtr;
403
            } else {
404
                prevPtr->nextPtr = nextPtr;
405
            }
406
            break;
407
        }
408
        prevPtr = infoPtr;
409
    }
410
 
411
    if (infoPtr != NULL) {
412
        clearProc = infoPtr->clearProc;
413
        clearData = infoPtr->clearData;
414
        ckfree((char *) infoPtr);
415
    }
416
    XSetSelectionOwner(winPtr->display, selection, None, CurrentTime);
417
 
418
    if (clearProc != NULL) {
419
        (*clearProc)(clearData);
420
    }
421
}
422
 
423
/*
424
 *--------------------------------------------------------------
425
 *
426
 * Tk_GetSelection --
427
 *
428
 *      Retrieve the value of a selection and pass it off (in
429
 *      pieces, possibly) to a given procedure.
430
 *
431
 * Results:
432
 *      The return value is a standard Tcl return value.
433
 *      If an error occurs (such as no selection exists)
434
 *      then an error message is left in interp->result.
435
 *
436
 * Side effects:
437
 *      The standard X11 protocols are used to retrieve the
438
 *      selection.  When it arrives, it is passed to proc.  If
439
 *      the selection is very large, it will be passed to proc
440
 *      in several pieces.  Proc should have the following
441
 *      structure:
442
 *
443
 *      int
444
 *      proc(clientData, interp, portion)
445
 *          ClientData clientData;
446
 *          Tcl_Interp *interp;
447
 *          char *portion;
448
 *      {
449
 *      }
450
 *
451
 *      The interp and clientData arguments to proc will be the
452
 *      same as the corresponding arguments to Tk_GetSelection.
453
 *      The portion argument points to a character string
454
 *      containing part of the selection, and numBytes indicates
455
 *      the length of the portion, not including the terminating
456
 *      NULL character.  If the selection arrives in several pieces,
457
 *      the "portion" arguments in separate calls will contain
458
 *      successive parts of the selection.  Proc should normally
459
 *      return TCL_OK.  If it detects an error then it should return
460
 *      TCL_ERROR and leave an error message in interp->result; the
461
 *      remainder of the selection retrieval will be aborted.
462
 *
463
 *--------------------------------------------------------------
464
 */
465
 
466
int
467
Tk_GetSelection(interp, tkwin, selection, target, proc, clientData)
468
    Tcl_Interp *interp;         /* Interpreter to use for reporting
469
                                 * errors. */
470
    Tk_Window tkwin;            /* Window on whose behalf to retrieve
471
                                 * the selection (determines display
472
                                 * from which to retrieve). */
473
    Atom selection;             /* Selection to retrieve. */
474
    Atom target;                /* Desired form in which selection
475
                                 * is to be returned. */
476
    Tk_GetSelProc *proc;        /* Procedure to call to process the
477
                                 * selection, once it has been retrieved. */
478
    ClientData clientData;      /* Arbitrary value to pass to proc. */
479
{
480
    TkWindow *winPtr = (TkWindow *) tkwin;
481
    TkDisplay *dispPtr = winPtr->dispPtr;
482
    TkSelectionInfo *infoPtr;
483
 
484
    if (dispPtr->multipleAtom == None) {
485
        TkSelInit(tkwin);
486
    }
487
 
488
    /*
489
     * If the selection is owned by a window managed by this
490
     * process, then call the retrieval procedure directly,
491
     * rather than going through the X server (it's dangerous
492
     * to go through the X server in this case because it could
493
     * result in deadlock if an INCR-style selection results).
494
     */
495
 
496
    for (infoPtr = dispPtr->selectionInfoPtr; infoPtr != NULL;
497
            infoPtr = infoPtr->nextPtr) {
498
        if (infoPtr->selection == selection)
499
            break;
500
    }
501
    if (infoPtr != NULL) {
502
        register TkSelHandler *selPtr;
503
        int offset, result, count;
504
        char buffer[TK_SEL_BYTES_AT_ONCE+1];
505
        TkSelInProgress ip;
506
 
507
        for (selPtr = ((TkWindow *) infoPtr->owner)->selHandlerList;
508
                selPtr != NULL; selPtr = selPtr->nextPtr) {
509
            if ((selPtr->target == target)
510
                    && (selPtr->selection == selection)) {
511
                break;
512
            }
513
        }
514
        if (selPtr == NULL) {
515
            Atom type;
516
 
517
            count = TkSelDefaultSelection(infoPtr, target, buffer,
518
                    TK_SEL_BYTES_AT_ONCE, &type);
519
            if (count > TK_SEL_BYTES_AT_ONCE) {
520
                panic("selection handler returned too many bytes");
521
            }
522
            if (count < 0) {
523
                goto cantget;
524
            }
525
            buffer[count] = 0;
526
            result = (*proc)(clientData, interp, buffer);
527
        } else {
528
            offset = 0;
529
            result = TCL_OK;
530
            ip.selPtr = selPtr;
531
            ip.nextPtr = pendingPtr;
532
            pendingPtr = &ip;
533
            while (1) {
534
                count = (selPtr->proc)(selPtr->clientData, offset, buffer,
535
                        TK_SEL_BYTES_AT_ONCE);
536
                if ((count < 0) || (ip.selPtr == NULL)) {
537
                    pendingPtr = ip.nextPtr;
538
                    goto cantget;
539
                }
540
                if (count > TK_SEL_BYTES_AT_ONCE) {
541
                    panic("selection handler returned too many bytes");
542
                }
543
                buffer[count] = '\0';
544
                result = (*proc)(clientData, interp, buffer);
545
                if ((result != TCL_OK) || (count < TK_SEL_BYTES_AT_ONCE)
546
                        || (ip.selPtr == NULL)) {
547
                    break;
548
                }
549
                offset += count;
550
            }
551
            pendingPtr = ip.nextPtr;
552
        }
553
        return result;
554
    }
555
 
556
    /*
557
     * The selection is owned by some other process.
558
     */
559
 
560
    return TkSelGetSelection(interp, tkwin, selection, target, proc,
561
            clientData);
562
 
563
    cantget:
564
    Tcl_AppendResult(interp, Tk_GetAtomName(tkwin, selection),
565
        " selection doesn't exist or form \"", Tk_GetAtomName(tkwin, target),
566
        "\" not defined", (char *) NULL);
567
    return TCL_ERROR;
568
}
569
 
570
/*
571
 *--------------------------------------------------------------
572
 *
573
 * Tk_SelectionCmd --
574
 *
575
 *      This procedure is invoked to process the "selection" Tcl
576
 *      command.  See the user documentation for details on what
577
 *      it does.
578
 *
579
 * Results:
580
 *      A standard Tcl result.
581
 *
582
 * Side effects:
583
 *      See the user documentation.
584
 *
585
 *--------------------------------------------------------------
586
 */
587
 
588
int
589
Tk_SelectionCmd(clientData, interp, argc, argv)
590
    ClientData clientData;      /* Main window associated with
591
                                 * interpreter. */
592
    Tcl_Interp *interp;         /* Current interpreter. */
593
    int argc;                   /* Number of arguments. */
594
    char **argv;                /* Argument strings. */
595
{
596
    Tk_Window tkwin = (Tk_Window) clientData;
597
    char *path = NULL;
598
    Atom selection;
599
    char *selName = NULL;
600
    int c, count;
601
    size_t length;
602
    char **args;
603
 
604
    if (argc < 2) {
605
        sprintf(interp->result,
606
                "wrong # args: should be \"%.50s option ?arg arg ...?\"",
607
                argv[0]);
608
        return TCL_ERROR;
609
    }
610
    c = argv[1][0];
611
    length = strlen(argv[1]);
612
    if ((c == 'c') && (strncmp(argv[1], "clear", length) == 0)) {
613
        for (count = argc-2, args = argv+2; count > 0; count -= 2, args += 2) {
614
            if (args[0][0] != '-') {
615
                break;
616
            }
617
            if (count < 2) {
618
                Tcl_AppendResult(interp, "value for \"", *args,
619
                        "\" missing", (char *) NULL);
620
                return TCL_ERROR;
621
            }
622
            c = args[0][1];
623
            length = strlen(args[0]);
624
            if ((c == 'd') && (strncmp(args[0], "-displayof", length) == 0)) {
625
                path = args[1];
626
            } else if ((c == 's')
627
                    && (strncmp(args[0], "-selection", length) == 0)) {
628
                selName = args[1];
629
            } else {
630
                Tcl_AppendResult(interp, "unknown option \"", args[0],
631
                        "\"", (char *) NULL);
632
                return TCL_ERROR;
633
            }
634
        }
635
        if (count == 1) {
636
            path = args[0];
637
        } else if (count > 1) {
638
            Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
639
                    " clear ?options?\"", (char *) NULL);
640
            return TCL_ERROR;
641
        }
642
        if (path != NULL) {
643
            tkwin = Tk_NameToWindow(interp, path, tkwin);
644
        }
645
        if (tkwin == NULL) {
646
            return TCL_ERROR;
647
        }
648
        if (selName != NULL) {
649
            selection = Tk_InternAtom(tkwin, selName);
650
        } else {
651
            selection = XA_PRIMARY;
652
        }
653
 
654
        Tk_ClearSelection(tkwin, selection);
655
        return TCL_OK;
656
    } else if ((c == 'g') && (strncmp(argv[1], "get", length) == 0)) {
657
        Atom target;
658
        char *targetName = NULL;
659
        Tcl_DString selBytes;
660
        int result;
661
 
662
        for (count = argc-2, args = argv+2; count > 0; count -= 2, args += 2) {
663
            if (args[0][0] != '-') {
664
                break;
665
            }
666
            if (count < 2) {
667
                Tcl_AppendResult(interp, "value for \"", *args,
668
                        "\" missing", (char *) NULL);
669
                return TCL_ERROR;
670
            }
671
            c = args[0][1];
672
            length = strlen(args[0]);
673
            if ((c == 'd') && (strncmp(args[0], "-displayof", length) == 0)) {
674
                path = args[1];
675
            } else if ((c == 's')
676
                    && (strncmp(args[0], "-selection", length) == 0)) {
677
                selName = args[1];
678
            } else if ((c == 't')
679
                    && (strncmp(args[0], "-type", length) == 0)) {
680
                targetName = args[1];
681
            } else {
682
                Tcl_AppendResult(interp, "unknown option \"", args[0],
683
                        "\"", (char *) NULL);
684
                return TCL_ERROR;
685
            }
686
        }
687
        if (path != NULL) {
688
            tkwin = Tk_NameToWindow(interp, path, tkwin);
689
        }
690
        if (tkwin == NULL) {
691
            return TCL_ERROR;
692
        }
693
        if (selName != NULL) {
694
            selection = Tk_InternAtom(tkwin, selName);
695
        } else {
696
            selection = XA_PRIMARY;
697
        }
698
        if (count > 1) {
699
            Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
700
                    " get ?options?\"", (char *) NULL);
701
            return TCL_ERROR;
702
        } else if (count == 1) {
703
            target = Tk_InternAtom(tkwin, args[0]);
704
        } else if (targetName != NULL) {
705
            target = Tk_InternAtom(tkwin, targetName);
706
        } else {
707
            target = XA_STRING;
708
        }
709
 
710
        Tcl_DStringInit(&selBytes);
711
        result = Tk_GetSelection(interp, tkwin, selection, target, SelGetProc,
712
                (ClientData) &selBytes);
713
        if (result == TCL_OK) {
714
            Tcl_DStringResult(interp, &selBytes);
715
        } else {
716
            Tcl_DStringFree(&selBytes);
717
        }
718
        return result;
719
    } else if ((c == 'h') && (strncmp(argv[1], "handle", length) == 0)) {
720
        Atom target, format;
721
        char *targetName = NULL;
722
        char *formatName = NULL;
723
        register CommandInfo *cmdInfoPtr;
724
        int cmdLength;
725
 
726
        for (count = argc-2, args = argv+2; count > 0; count -= 2, args += 2) {
727
            if (args[0][0] != '-') {
728
                break;
729
            }
730
            if (count < 2) {
731
                Tcl_AppendResult(interp, "value for \"", *args,
732
                        "\" missing", (char *) NULL);
733
                return TCL_ERROR;
734
            }
735
            c = args[0][1];
736
            length = strlen(args[0]);
737
            if ((c == 'f') && (strncmp(args[0], "-format", length) == 0)) {
738
                formatName = args[1];
739
            } else if ((c == 's')
740
                    && (strncmp(args[0], "-selection", length) == 0)) {
741
                selName = args[1];
742
            } else if ((c == 't')
743
                    && (strncmp(args[0], "-type", length) == 0)) {
744
                targetName = args[1];
745
            } else {
746
                Tcl_AppendResult(interp, "unknown option \"", args[0],
747
                        "\"", (char *) NULL);
748
                return TCL_ERROR;
749
            }
750
        }
751
 
752
        if ((count < 2) || (count > 4)) {
753
            Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
754
                    " handle ?options? window command\"", (char *) NULL);
755
            return TCL_ERROR;
756
        }
757
        tkwin = Tk_NameToWindow(interp, args[0], tkwin);
758
        if (tkwin == NULL) {
759
            return TCL_ERROR;
760
        }
761
        if (selName != NULL) {
762
            selection = Tk_InternAtom(tkwin, selName);
763
        } else {
764
            selection = XA_PRIMARY;
765
        }
766
 
767
        if (count > 2) {
768
            target = Tk_InternAtom(tkwin, args[2]);
769
        } else if (targetName != NULL) {
770
            target = Tk_InternAtom(tkwin, targetName);
771
        } else {
772
            target = XA_STRING;
773
        }
774
        if (count > 3) {
775
            format = Tk_InternAtom(tkwin, args[3]);
776
        } else if (formatName != NULL) {
777
            format = Tk_InternAtom(tkwin, formatName);
778
        } else {
779
            format = XA_STRING;
780
        }
781
        cmdLength = strlen(args[1]);
782
        if (cmdLength == 0) {
783
            Tk_DeleteSelHandler(tkwin, selection, target);
784
        } else {
785
            cmdInfoPtr = (CommandInfo *) ckalloc((unsigned) (
786
                    sizeof(CommandInfo) - 3 + cmdLength));
787
            cmdInfoPtr->interp = interp;
788
            cmdInfoPtr->cmdLength = cmdLength;
789
            strcpy(cmdInfoPtr->command, args[1]);
790
            Tk_CreateSelHandler(tkwin, selection, target, HandleTclCommand,
791
                    (ClientData) cmdInfoPtr, format);
792
        }
793
        return TCL_OK;
794
    } else if ((c == 'o') && (strncmp(argv[1], "own", length) == 0)) {
795
        register LostCommand *lostPtr;
796
        char *script = NULL;
797
        int cmdLength;
798
 
799
        for (count = argc-2, args = argv+2; count > 0; count -= 2, args += 2) {
800
            if (args[0][0] != '-') {
801
                break;
802
            }
803
            if (count < 2) {
804
                Tcl_AppendResult(interp, "value for \"", *args,
805
                        "\" missing", (char *) NULL);
806
                return TCL_ERROR;
807
            }
808
            c = args[0][1];
809
            length = strlen(args[0]);
810
            if ((c == 'c') && (strncmp(args[0], "-command", length) == 0)) {
811
                script = args[1];
812
            } else if ((c == 'd')
813
                    && (strncmp(args[0], "-displayof", length) == 0)) {
814
                path = args[1];
815
            } else if ((c == 's')
816
                    && (strncmp(args[0], "-selection", length) == 0)) {
817
                selName = args[1];
818
            } else {
819
                Tcl_AppendResult(interp, "unknown option \"", args[0],
820
                        "\"", (char *) NULL);
821
                return TCL_ERROR;
822
            }
823
        }
824
 
825
        if (count > 2) {
826
            Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
827
                    " own ?options? ?window?\"", (char *) NULL);
828
            return TCL_ERROR;
829
        }
830
        if (selName != NULL) {
831
            selection = Tk_InternAtom(tkwin, selName);
832
        } else {
833
            selection = XA_PRIMARY;
834
        }
835
        if (count == 0) {
836
            TkSelectionInfo *infoPtr;
837
            TkWindow *winPtr;
838
            if (path != NULL) {
839
                tkwin = Tk_NameToWindow(interp, path, tkwin);
840
            }
841
            if (tkwin == NULL) {
842
                return TCL_ERROR;
843
            }
844
            winPtr = (TkWindow *)tkwin;
845
            for (infoPtr = winPtr->dispPtr->selectionInfoPtr; infoPtr != NULL;
846
                    infoPtr = infoPtr->nextPtr) {
847
                if (infoPtr->selection == selection)
848
                    break;
849
            }
850
 
851
            /*
852
             * Ignore the internal clipboard window.
853
             */
854
 
855
            if ((infoPtr != NULL)
856
                    && (infoPtr->owner != winPtr->dispPtr->clipWindow)) {
857
                interp->result = Tk_PathName(infoPtr->owner);
858
            }
859
            return TCL_OK;
860
        }
861
        tkwin = Tk_NameToWindow(interp, args[0], tkwin);
862
        if (tkwin == NULL) {
863
            return TCL_ERROR;
864
        }
865
        if (count == 2) {
866
            script = args[1];
867
        }
868
        if (script == NULL) {
869
            Tk_OwnSelection(tkwin, selection, (Tk_LostSelProc *) NULL,
870
                    (ClientData) NULL);
871
            return TCL_OK;
872
        }
873
        cmdLength = strlen(script);
874
        lostPtr = (LostCommand *) ckalloc((unsigned) (sizeof(LostCommand)
875
                -3 + cmdLength));
876
        lostPtr->interp = interp;
877
        strcpy(lostPtr->command, script);
878
        Tk_OwnSelection(tkwin, selection, LostSelection, (ClientData) lostPtr);
879
        return TCL_OK;
880
    } else {
881
        sprintf(interp->result,
882
                "bad option \"%.50s\": must be clear, get, handle, or own",
883
                argv[1]);
884
        return TCL_ERROR;
885
    }
886
}
887
 
888
/*
889
 *----------------------------------------------------------------------
890
 *
891
 * TkSelDeadWindow --
892
 *
893
 *      This procedure is invoked just before a TkWindow is deleted.
894
 *      It performs selection-related cleanup.
895
 *
896
 * Results:
897
 *      None.
898
 *
899
 * Side effects:
900
 *      Frees up memory associated with the selection.
901
 *
902
 *----------------------------------------------------------------------
903
 */
904
 
905
void
906
TkSelDeadWindow(winPtr)
907
    register TkWindow *winPtr;  /* Window that's being deleted. */
908
{
909
    register TkSelHandler *selPtr;
910
    register TkSelInProgress *ipPtr;
911
    TkSelectionInfo *infoPtr, *prevPtr, *nextPtr;
912
 
913
    /*
914
     * While deleting all the handlers, be careful to check whether
915
     * ConvertSelection or TkSelPropProc are about to process one of the
916
     * deleted handlers.
917
     */
918
 
919
    while (winPtr->selHandlerList != NULL) {
920
        selPtr = winPtr->selHandlerList;
921
        winPtr->selHandlerList = selPtr->nextPtr;
922
        for (ipPtr = pendingPtr; ipPtr != NULL; ipPtr = ipPtr->nextPtr) {
923
            if (ipPtr->selPtr == selPtr) {
924
                ipPtr->selPtr = NULL;
925
            }
926
        }
927
        if (selPtr->proc == HandleTclCommand) {
928
            ckfree((char *) selPtr->clientData);
929
        }
930
        ckfree((char *) selPtr);
931
    }
932
 
933
    /*
934
     * Remove selections owned by window being deleted.
935
     */
936
 
937
    for (infoPtr = winPtr->dispPtr->selectionInfoPtr, prevPtr = NULL;
938
             infoPtr != NULL; infoPtr = nextPtr) {
939
        nextPtr = infoPtr->nextPtr;
940
        if (infoPtr->owner == (Tk_Window) winPtr) {
941
            if (infoPtr->clearProc == LostSelection) {
942
                ckfree((char *) infoPtr->clearData);
943
            }
944
            ckfree((char *) infoPtr);
945
            infoPtr = prevPtr;
946
            if (prevPtr == NULL) {
947
                winPtr->dispPtr->selectionInfoPtr = nextPtr;
948
            } else {
949
                prevPtr->nextPtr = nextPtr;
950
            }
951
        }
952
        prevPtr = infoPtr;
953
    }
954
}
955
 
956
/*
957
 *----------------------------------------------------------------------
958
 *
959
 * TkSelInit --
960
 *
961
 *      Initialize selection-related information for a display.
962
 *
963
 * Results:
964
 *      None.
965
 *
966
 * Side effects:
967
 *      Selection-related information is initialized.
968
 *
969
 *----------------------------------------------------------------------
970
 */
971
 
972
void
973
TkSelInit(tkwin)
974
    Tk_Window tkwin;            /* Window token (used to find
975
                                 * display to initialize). */
976
{
977
    register TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr;
978
 
979
    /*
980
     * Fetch commonly-used atoms.
981
     */
982
 
983
    dispPtr->multipleAtom = Tk_InternAtom(tkwin, "MULTIPLE");
984
    dispPtr->incrAtom = Tk_InternAtom(tkwin, "INCR");
985
    dispPtr->targetsAtom = Tk_InternAtom(tkwin, "TARGETS");
986
    dispPtr->timestampAtom = Tk_InternAtom(tkwin, "TIMESTAMP");
987
    dispPtr->textAtom = Tk_InternAtom(tkwin, "TEXT");
988
    dispPtr->compoundTextAtom = Tk_InternAtom(tkwin, "COMPOUND_TEXT");
989
    dispPtr->applicationAtom = Tk_InternAtom(tkwin, "TK_APPLICATION");
990
    dispPtr->windowAtom = Tk_InternAtom(tkwin, "TK_WINDOW");
991
    dispPtr->clipboardAtom = Tk_InternAtom(tkwin, "CLIPBOARD");
992
}
993
 
994
/*
995
 *----------------------------------------------------------------------
996
 *
997
 * TkSelClearSelection --
998
 *
999
 *      This procedure is invoked to process a SelectionClear event.
1000
 *
1001
 * Results:
1002
 *      None.
1003
 *
1004
 * Side effects:
1005
 *      Invokes the clear procedure for the window which lost the
1006
 *      selection.
1007
 *
1008
 *----------------------------------------------------------------------
1009
 */
1010
 
1011
void
1012
TkSelClearSelection(tkwin, eventPtr)
1013
    Tk_Window tkwin;            /* Window for which event was targeted. */
1014
    register XEvent *eventPtr;  /* X SelectionClear event. */
1015
{
1016
    register TkWindow *winPtr = (TkWindow *) tkwin;
1017
    TkDisplay *dispPtr = winPtr->dispPtr;
1018
    TkSelectionInfo *infoPtr;
1019
    TkSelectionInfo *prevPtr;
1020
 
1021
    /*
1022
     * Invoke clear procedure for window that just lost the selection.  This
1023
     * code is a bit tricky, because any callbacks due to selection changes
1024
     * between windows managed by the process have already been made.  Thus,
1025
     * ignore the event unless it refers to the window that's currently the
1026
     * selection owner and the event was generated after the server saw the
1027
     * SetSelectionOwner request.
1028
     */
1029
 
1030
    for (infoPtr = dispPtr->selectionInfoPtr, prevPtr = NULL;
1031
         infoPtr != NULL; infoPtr = infoPtr->nextPtr) {
1032
        if (infoPtr->selection == eventPtr->xselectionclear.selection) {
1033
            break;
1034
        }
1035
        prevPtr = infoPtr;
1036
    }
1037
 
1038
    if (infoPtr != NULL && (infoPtr->owner == tkwin)
1039
            && (eventPtr->xselectionclear.serial >= (unsigned) infoPtr->serial)) {
1040
        if (prevPtr == NULL) {
1041
            dispPtr->selectionInfoPtr = infoPtr->nextPtr;
1042
        } else {
1043
            prevPtr->nextPtr = infoPtr->nextPtr;
1044
        }
1045
 
1046
        /*
1047
         * Because of reentrancy problems, calling clearProc must be done
1048
         * after the infoPtr has been removed from the selectionInfoPtr
1049
         * list (clearProc could modify the list, e.g. by creating
1050
         * a new selection).
1051
         */
1052
 
1053
        if (infoPtr->clearProc != NULL) {
1054
            (*infoPtr->clearProc)(infoPtr->clearData);
1055
        }
1056
        ckfree((char *) infoPtr);
1057
    }
1058
}
1059
 
1060
/*
1061
 *--------------------------------------------------------------
1062
 *
1063
 * SelGetProc --
1064
 *
1065
 *      This procedure is invoked to process pieces of the selection
1066
 *      as they arrive during "selection get" commands.
1067
 *
1068
 * Results:
1069
 *      Always returns TCL_OK.
1070
 *
1071
 * Side effects:
1072
 *      Bytes get appended to the dynamic string pointed to by the
1073
 *      clientData argument.
1074
 *
1075
 *--------------------------------------------------------------
1076
 */
1077
 
1078
        /* ARGSUSED */
1079
static int
1080
SelGetProc(clientData, interp, portion)
1081
    ClientData clientData;      /* Dynamic string holding partially
1082
                                 * assembled selection. */
1083
    Tcl_Interp *interp;         /* Interpreter used for error
1084
                                 * reporting (not used). */
1085
    char *portion;              /* New information to be appended. */
1086
{
1087
    Tcl_DStringAppend((Tcl_DString *) clientData, portion, -1);
1088
    return TCL_OK;
1089
}
1090
 
1091
/*
1092
 *----------------------------------------------------------------------
1093
 *
1094
 * HandleTclCommand --
1095
 *
1096
 *      This procedure acts as selection handler for handlers created
1097
 *      by the "selection handle" command.  It invokes a Tcl command to
1098
 *      retrieve the selection.
1099
 *
1100
 * Results:
1101
 *      The return value is a count of the number of bytes actually
1102
 *      stored at buffer, or -1 if an error occurs while executing
1103
 *      the Tcl command to retrieve the selection.
1104
 *
1105
 * Side effects:
1106
 *      None except for things done by the Tcl command.
1107
 *
1108
 *----------------------------------------------------------------------
1109
 */
1110
 
1111
static int
1112
HandleTclCommand(clientData, offset, buffer, maxBytes)
1113
    ClientData clientData;      /* Information about command to execute. */
1114
    int offset;                 /* Return selection bytes starting at this
1115
                                 * offset. */
1116
    char *buffer;               /* Place to store converted selection. */
1117
    int maxBytes;               /* Maximum # of bytes to store at buffer. */
1118
{
1119
    CommandInfo *cmdInfoPtr = (CommandInfo *) clientData;
1120
    int spaceNeeded, length;
1121
#define MAX_STATIC_SIZE 100
1122
    char staticSpace[MAX_STATIC_SIZE];
1123
    char *command;
1124
    Tcl_Interp *interp;
1125
    Tcl_DString oldResult;
1126
 
1127
    /*
1128
     * We must copy the interpreter pointer from CommandInfo because the
1129
     * command could delete the handler, freeing the CommandInfo data before we
1130
     * are done using it. We must also protect the interpreter from being
1131
     * deleted too soo.
1132
     */
1133
 
1134
    interp = cmdInfoPtr->interp;
1135
    Tcl_Preserve((ClientData) interp);
1136
 
1137
    /*
1138
     * First, generate a command by taking the command string
1139
     * and appending the offset and maximum # of bytes.
1140
     */
1141
 
1142
    spaceNeeded = cmdInfoPtr->cmdLength + 30;
1143
    if (spaceNeeded < MAX_STATIC_SIZE) {
1144
        command = staticSpace;
1145
    } else {
1146
        command = (char *) ckalloc((unsigned) spaceNeeded);
1147
    }
1148
    sprintf(command, "%s %d %d", cmdInfoPtr->command, offset, maxBytes);
1149
 
1150
    /*
1151
     * Execute the command.  Be sure to restore the state of the
1152
     * interpreter after executing the command.
1153
     */
1154
 
1155
    Tcl_DStringInit(&oldResult);
1156
    Tcl_DStringGetResult(interp, &oldResult);
1157
    if (TkCopyAndGlobalEval(interp, command) == TCL_OK) {
1158
        length = strlen(interp->result);
1159
        if (length > maxBytes) {
1160
            length = maxBytes;
1161
        }
1162
        memcpy((VOID *) buffer, (VOID *) interp->result, (size_t) length);
1163
        buffer[length] = '\0';
1164
    } else {
1165
        length = -1;
1166
    }
1167
    Tcl_DStringResult(interp, &oldResult);
1168
 
1169
    if (command != staticSpace) {
1170
        ckfree(command);
1171
    }
1172
 
1173
    Tcl_Release((ClientData) interp);
1174
    return length;
1175
}
1176
 
1177
/*
1178
 *----------------------------------------------------------------------
1179
 *
1180
 * TkSelDefaultSelection --
1181
 *
1182
 *      This procedure is called to generate selection information
1183
 *      for a few standard targets such as TIMESTAMP and TARGETS.
1184
 *      It is invoked only if no handler has been declared by the
1185
 *      application.
1186
 *
1187
 * Results:
1188
 *      If "target" is a standard target understood by this procedure,
1189
 *      the selection is converted to that form and stored as a
1190
 *      character string in buffer.  The type of the selection (e.g.
1191
 *      STRING or ATOM) is stored in *typePtr, and the return value is
1192
 *      a count of the # of non-NULL bytes at buffer.  If the target
1193
 *      wasn't understood, or if there isn't enough space at buffer
1194
 *      to hold the entire selection (no INCR-mode transfers for this
1195
 *      stuff!), then -1 is returned.
1196
 *
1197
 * Side effects:
1198
 *      None.
1199
 *
1200
 *----------------------------------------------------------------------
1201
 */
1202
 
1203
int
1204
TkSelDefaultSelection(infoPtr, target, buffer, maxBytes, typePtr)
1205
    TkSelectionInfo *infoPtr;   /* Info about selection being retrieved. */
1206
    Atom target;                /* Desired form of selection. */
1207
    char *buffer;               /* Place to put selection characters. */
1208
    int maxBytes;               /* Maximum # of bytes to store at buffer. */
1209
    Atom *typePtr;              /* Store here the type of the selection,
1210
                                 * for use in converting to proper X format. */
1211
{
1212
    register TkWindow *winPtr = (TkWindow *) infoPtr->owner;
1213
    TkDisplay *dispPtr = winPtr->dispPtr;
1214
 
1215
    if (target == dispPtr->timestampAtom) {
1216
        if (maxBytes < 20) {
1217
            return -1;
1218
        }
1219
        sprintf(buffer, "0x%x", (unsigned int) infoPtr->time);
1220
        *typePtr = XA_INTEGER;
1221
        return strlen(buffer);
1222
    }
1223
 
1224
    if (target == dispPtr->targetsAtom) {
1225
        register TkSelHandler *selPtr;
1226
        char *atomString;
1227
        int length, atomLength;
1228
 
1229
        if (maxBytes < 50) {
1230
            return -1;
1231
        }
1232
        strcpy(buffer, "MULTIPLE TARGETS TIMESTAMP TK_APPLICATION TK_WINDOW");
1233
        length = strlen(buffer);
1234
        for (selPtr = winPtr->selHandlerList; selPtr != NULL;
1235
                selPtr = selPtr->nextPtr) {
1236
            if ((selPtr->selection == infoPtr->selection)
1237
                    && (selPtr->target != dispPtr->applicationAtom)
1238
                    && (selPtr->target != dispPtr->windowAtom)) {
1239
                atomString = Tk_GetAtomName((Tk_Window) winPtr,
1240
                        selPtr->target);
1241
                atomLength = strlen(atomString) + 1;
1242
                if ((length + atomLength) >= maxBytes) {
1243
                    return -1;
1244
                }
1245
                sprintf(buffer+length, " %s", atomString);
1246
                length += atomLength;
1247
            }
1248
        }
1249
        *typePtr = XA_ATOM;
1250
        return length;
1251
    }
1252
 
1253
    if (target == dispPtr->applicationAtom) {
1254
        int length;
1255
        char *name = winPtr->mainPtr->winPtr->nameUid;
1256
 
1257
        length = strlen(name);
1258
        if (maxBytes <= length) {
1259
            return -1;
1260
        }
1261
        strcpy(buffer, name);
1262
        *typePtr = XA_STRING;
1263
        return length;
1264
    }
1265
 
1266
    if (target == dispPtr->windowAtom) {
1267
        int length;
1268
        char *name = winPtr->pathName;
1269
 
1270
        length = strlen(name);
1271
        if (maxBytes <= length) {
1272
            return -1;
1273
        }
1274
        strcpy(buffer, name);
1275
        *typePtr = XA_STRING;
1276
        return length;
1277
    }
1278
 
1279
    return -1;
1280
}
1281
 
1282
/*
1283
 *----------------------------------------------------------------------
1284
 *
1285
 * LostSelection --
1286
 *
1287
 *      This procedure is invoked when a window has lost ownership of
1288
 *      the selection and the ownership was claimed with the command
1289
 *      "selection own".
1290
 *
1291
 * Results:
1292
 *      None.
1293
 *
1294
 * Side effects:
1295
 *      A Tcl script is executed;  it can do almost anything.
1296
 *
1297
 *----------------------------------------------------------------------
1298
 */
1299
 
1300
static void
1301
LostSelection(clientData)
1302
    ClientData clientData;              /* Pointer to CommandInfo structure. */
1303
{
1304
    LostCommand *lostPtr = (LostCommand *) clientData;
1305
    char *oldResultString;
1306
    Tcl_FreeProc *oldFreeProc;
1307
    Tcl_Interp *interp;
1308
 
1309
    interp = lostPtr->interp;
1310
    Tcl_Preserve((ClientData) interp);
1311
 
1312
    /*
1313
     * Execute the command.  Save the interpreter's result, if any, and
1314
     * restore it after executing the command.
1315
     */
1316
 
1317
    oldFreeProc = interp->freeProc;
1318
    if (oldFreeProc != TCL_STATIC) {
1319
        oldResultString = interp->result;
1320
    } else {
1321
        oldResultString = (char *) ckalloc((unsigned)
1322
                (strlen(interp->result) + 1));
1323
        strcpy(oldResultString, interp->result);
1324
        oldFreeProc = TCL_DYNAMIC;
1325
    }
1326
    interp->freeProc = TCL_STATIC;
1327
    if (TkCopyAndGlobalEval(interp, lostPtr->command) != TCL_OK) {
1328
        Tcl_BackgroundError(interp);
1329
    }
1330
    Tcl_FreeResult(interp);
1331
    interp->result = oldResultString;
1332
    interp->freeProc = oldFreeProc;
1333
 
1334
    Tcl_Release((ClientData) interp);
1335
 
1336
    /*
1337
     * Free the storage for the command, since we're done with it now.
1338
     */
1339
 
1340
    ckfree((char *) lostPtr);
1341
}

powered by: WebSVN 2.1.0

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