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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [tk/] [generic/] [tkClipboard.c] - Blame information for rev 1780

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

Line No. Rev Author Line
1 578 markom
/*
2
 * tkClipboard.c --
3
 *
4
 *      This file manages the clipboard for the Tk toolkit,
5
 *      maintaining a collection of data buffers that will be
6
 *      supplied on demand to requesting applications.
7
 *
8
 * Copyright (c) 1994 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: tkClipboard.c,v 1.1.1.1 2002-01-16 10:25:51 markom Exp $
15
 */
16
 
17
#include "tkInt.h"
18
#include "tkPort.h"
19
#include "tkSelect.h"
20
 
21
/*
22
 * Prototypes for procedures used only in this file:
23
 */
24
 
25
static int              ClipboardAppHandler _ANSI_ARGS_((ClientData clientData,
26
                            int offset, char *buffer, int maxBytes));
27
static int              ClipboardHandler _ANSI_ARGS_((ClientData clientData,
28
                            int offset, char *buffer, int maxBytes));
29
static int              ClipboardWindowHandler _ANSI_ARGS_((
30
                            ClientData clientData, int offset, char *buffer,
31
                            int maxBytes));
32
static void             ClipboardLostSel _ANSI_ARGS_((ClientData clientData));
33
 
34
/*
35
 *----------------------------------------------------------------------
36
 *
37
 * ClipboardHandler --
38
 *
39
 *      This procedure acts as selection handler for the
40
 *      clipboard manager.  It extracts the required chunk of
41
 *      data from the buffer chain for a given selection target.
42
 *
43
 * Results:
44
 *      The return value is a count of the number of bytes
45
 *      actually stored at buffer.
46
 *
47
 * Side effects:
48
 *      None.
49
 *
50
 *----------------------------------------------------------------------
51
 */
52
 
53
static int
54
ClipboardHandler(clientData, offset, buffer, maxBytes)
55
    ClientData clientData;      /* Information about data to fetch. */
56
    int offset;                 /* Return selection bytes starting at this
57
                                 * offset. */
58
    char *buffer;               /* Place to store converted selection. */
59
    int maxBytes;               /* Maximum # of bytes to store at buffer. */
60
{
61
    TkClipboardTarget *targetPtr = (TkClipboardTarget*) clientData;
62
    TkClipboardBuffer *cbPtr;
63
    char *srcPtr, *destPtr;
64
    int count = 0;
65
    int scanned = 0;
66
    size_t length, freeCount;
67
 
68
    /*
69
     * Skip to buffer containing offset byte
70
     */
71
 
72
    for (cbPtr = targetPtr->firstBufferPtr; ; cbPtr = cbPtr->nextPtr) {
73
        if (cbPtr == NULL) {
74
            return 0;
75
        }
76
        if (scanned + cbPtr->length > offset) {
77
            break;
78
        }
79
        scanned += cbPtr->length;
80
    }
81
 
82
    /*
83
     * Copy up to maxBytes or end of list, switching buffers as needed.
84
     */
85
 
86
    freeCount = maxBytes;
87
    srcPtr = cbPtr->buffer + (offset - scanned);
88
    destPtr = buffer;
89
    length = cbPtr->length - (offset - scanned);
90
    while (1) {
91
        if (length > freeCount) {
92
            strncpy(destPtr, srcPtr, freeCount);
93
            return maxBytes;
94
        } else {
95
            strncpy(destPtr, srcPtr, length);
96
            destPtr += length;
97
            count += length;
98
            freeCount -= length;
99
        }
100
        cbPtr = cbPtr->nextPtr;
101
        if (cbPtr == NULL) {
102
            break;
103
        }
104
        srcPtr = cbPtr->buffer;
105
        length = cbPtr->length;
106
    }
107
    return count;
108
}
109
 
110
/*
111
 *----------------------------------------------------------------------
112
 *
113
 * ClipboardAppHandler --
114
 *
115
 *      This procedure acts as selection handler for retrievals of type
116
 *      TK_APPLICATION.  It returns the name of the application that
117
 *      owns the clipboard.  Note:  we can't use the default Tk
118
 *      selection handler for this selection type, because the clipboard
119
 *      window isn't a "real" window and doesn't have the necessary
120
 *      information.
121
 *
122
 * Results:
123
 *      The return value is a count of the number of bytes
124
 *      actually stored at buffer.
125
 *
126
 * Side effects:
127
 *      None.
128
 *
129
 *----------------------------------------------------------------------
130
 */
131
 
132
static int
133
ClipboardAppHandler(clientData, offset, buffer, maxBytes)
134
    ClientData clientData;      /* Pointer to TkDisplay structure. */
135
    int offset;                 /* Return selection bytes starting at this
136
                                 * offset. */
137
    char *buffer;               /* Place to store converted selection. */
138
    int maxBytes;               /* Maximum # of bytes to store at buffer. */
139
{
140
    TkDisplay *dispPtr = (TkDisplay *) clientData;
141
    size_t length;
142
    char *p;
143
 
144
    p = dispPtr->clipboardAppPtr->winPtr->nameUid;
145
    length = strlen(p);
146
    length -= offset;
147
    if (length <= 0) {
148
        return 0;
149
    }
150
    if (length > (size_t) maxBytes) {
151
        length = maxBytes;
152
    }
153
    strncpy(buffer, p, length);
154
    return length;
155
}
156
 
157
/*
158
 *----------------------------------------------------------------------
159
 *
160
 * ClipboardWindowHandler --
161
 *
162
 *      This procedure acts as selection handler for retrievals of
163
 *      type TK_WINDOW.  Since the clipboard doesn't correspond to
164
 *      any particular window, we just return ".".  We can't use Tk's
165
 *      default handler for this selection type, because the clipboard
166
 *      window isn't a valid window.
167
 *
168
 * Results:
169
 *      The return value is 1, the number of non-null bytes stored
170
 *      at buffer.
171
 *
172
 * Side effects:
173
 *      None.
174
 *
175
 *----------------------------------------------------------------------
176
 */
177
 
178
static int
179
ClipboardWindowHandler(clientData, offset, buffer, maxBytes)
180
    ClientData clientData;      /* Not used. */
181
    int offset;                 /* Return selection bytes starting at this
182
                                 * offset. */
183
    char *buffer;               /* Place to store converted selection. */
184
    int maxBytes;               /* Maximum # of bytes to store at buffer. */
185
{
186
    buffer[0] = '.';
187
    buffer[1] = 0;
188
    return 1;
189
}
190
 
191
/*
192
 *----------------------------------------------------------------------
193
 *
194
 * ClipboardLostSel --
195
 *
196
 *      This procedure is invoked whenever clipboard ownership is
197
 *      claimed by another window.  It just sets a flag so that we
198
 *      know the clipboard was taken away.
199
 *
200
 * Results:
201
 *      None.
202
 *
203
 * Side effects:
204
 *      The clipboard is marked as inactive.
205
 *
206
 *----------------------------------------------------------------------
207
 */
208
 
209
static void
210
ClipboardLostSel(clientData)
211
    ClientData clientData;              /* Pointer to TkDisplay structure. */
212
{
213
    TkDisplay *dispPtr = (TkDisplay*) clientData;
214
 
215
    dispPtr->clipboardActive = 0;
216
}
217
 
218
/*
219
 *----------------------------------------------------------------------
220
 *
221
 * Tk_ClipboardClear --
222
 *
223
 *      Take control of the clipboard and clear out the previous
224
 *      contents.  This procedure must be invoked before any
225
 *      calls to Tk_AppendToClipboard.
226
 *
227
 * Results:
228
 *      A standard Tcl result.  If an error occurs, an error message is
229
 *      left in interp->result.
230
 *
231
 * Side effects:
232
 *      From now on, requests for the CLIPBOARD selection will be
233
 *      directed to the clipboard manager routines associated with
234
 *      clipWindow for the display of tkwin.  In order to guarantee
235
 *      atomicity, no event handling should occur between
236
 *      Tk_ClipboardClear and the following Tk_AppendToClipboard
237
 *      calls.  This procedure may cause a user-defined LostSel command
238
 *      to be invoked when the CLIPBOARD is claimed, so any calling
239
 *      function should be reentrant at the point Tk_ClipboardClear is
240
 *      invoked.
241
 *
242
 *----------------------------------------------------------------------
243
 */
244
 
245
int
246
Tk_ClipboardClear(interp, tkwin)
247
    Tcl_Interp *interp;         /* Interpreter to use for error reporting. */
248
    Tk_Window tkwin;            /* Window in application that is clearing
249
                                 * clipboard;  identifies application and
250
                                 * display. */
251
{
252
    TkWindow *winPtr = (TkWindow *) tkwin;
253
    TkDisplay *dispPtr = winPtr->dispPtr;
254
    TkClipboardTarget *targetPtr, *nextTargetPtr;
255
    TkClipboardBuffer *cbPtr, *nextCbPtr;
256
 
257
    if (dispPtr->clipWindow == NULL) {
258
        int result;
259
 
260
        result = TkClipInit(interp, dispPtr);
261
        if (result != TCL_OK) {
262
            return result;
263
        }
264
    }
265
 
266
    /*
267
     * Discard any existing clipboard data and delete the selection
268
     * handler(s) associated with that data.
269
     */
270
 
271
    for (targetPtr = dispPtr->clipTargetPtr; targetPtr != NULL;
272
            targetPtr = nextTargetPtr) {
273
        for (cbPtr = targetPtr->firstBufferPtr; cbPtr != NULL;
274
                cbPtr = nextCbPtr) {
275
            ckfree(cbPtr->buffer);
276
            nextCbPtr = cbPtr->nextPtr;
277
            ckfree((char *) cbPtr);
278
        }
279
        nextTargetPtr = targetPtr->nextPtr;
280
        Tk_DeleteSelHandler(dispPtr->clipWindow, dispPtr->clipboardAtom,
281
                targetPtr->type);
282
        ckfree((char *) targetPtr);
283
    }
284
    dispPtr->clipTargetPtr = NULL;
285
 
286
    /*
287
     * Reclaim the clipboard selection if we lost it.
288
     */
289
 
290
    if (!dispPtr->clipboardActive) {
291
        Tk_OwnSelection(dispPtr->clipWindow, dispPtr->clipboardAtom,
292
                ClipboardLostSel, (ClientData) dispPtr);
293
        dispPtr->clipboardActive = 1;
294
    }
295
    dispPtr->clipboardAppPtr = winPtr->mainPtr;
296
    return TCL_OK;
297
}
298
 
299
/*
300
 *----------------------------------------------------------------------
301
 *
302
 * Tk_ClipboardAppend --
303
 *
304
 *      Append a buffer of data to the clipboard.  The first buffer of
305
 *      a given type determines the format for that type.  Any successive
306
 *      appends to that type must have the same format or an error will
307
 *      be returned.  Tk_ClipboardClear must be called before a sequence
308
 *      of Tk_ClipboardAppend calls can be issued.  In order to guarantee
309
 *      atomicity, no event handling should occur between Tk_ClipboardClear
310
 *      and the following Tk_AppendToClipboard calls.
311
 *
312
 * Results:
313
 *      A standard Tcl result.  If an error is returned, an error message
314
 *      is left in interp->result.
315
 *
316
 * Side effects:
317
 *      The specified buffer will be copied onto the end of the clipboard.
318
 *      The clipboard maintains a list of buffers which will be used to
319
 *      supply the data for a selection get request.  The first time a given
320
 *      type is appended, Tk_ClipboardAppend will register a selection
321
 *      handler of the appropriate type.
322
 *
323
 *----------------------------------------------------------------------
324
 */
325
 
326
int
327
Tk_ClipboardAppend(interp, tkwin, type, format, buffer)
328
    Tcl_Interp *interp;         /* Used for error reporting. */
329
    Tk_Window tkwin;            /* Window that selects a display. */
330
    Atom type;                  /* The desired conversion type for this
331
                                 * clipboard item, e.g. STRING or LENGTH. */
332
    Atom format;                /* Format in which the selection
333
                                 * information should be returned to
334
                                 * the requestor. */
335
    char* buffer;               /* NULL terminated string containing the data
336
                                 * to be added to the clipboard. */
337
{
338
    TkWindow *winPtr = (TkWindow *) tkwin;
339
    TkDisplay *dispPtr = winPtr->dispPtr;
340
    TkClipboardTarget *targetPtr;
341
    TkClipboardBuffer *cbPtr;
342
 
343
    /*
344
     * If this application doesn't already own the clipboard, clear
345
     * the clipboard.  If we don't own the clipboard selection, claim it.
346
     */
347
 
348
    if (dispPtr->clipboardAppPtr != winPtr->mainPtr) {
349
        Tk_ClipboardClear(interp, tkwin);
350
    } else if (!dispPtr->clipboardActive) {
351
        Tk_OwnSelection(dispPtr->clipWindow, dispPtr->clipboardAtom,
352
                ClipboardLostSel, (ClientData) dispPtr);
353
        dispPtr->clipboardActive = 1;
354
    }
355
 
356
    /*
357
     * Check to see if the specified target is already present on the
358
     * clipboard.  If it isn't, we need to create a new target; otherwise,
359
     * we just append the new buffer to the clipboard list.
360
     */
361
 
362
    for (targetPtr = dispPtr->clipTargetPtr; targetPtr != NULL;
363
            targetPtr = targetPtr->nextPtr) {
364
        if (targetPtr->type == type)
365
            break;
366
    }
367
    if (targetPtr == NULL) {
368
        targetPtr = (TkClipboardTarget*) ckalloc(sizeof(TkClipboardTarget));
369
        targetPtr->type = type;
370
        targetPtr->format = format;
371
        targetPtr->firstBufferPtr = targetPtr->lastBufferPtr = NULL;
372
        targetPtr->nextPtr = dispPtr->clipTargetPtr;
373
        dispPtr->clipTargetPtr = targetPtr;
374
        Tk_CreateSelHandler(dispPtr->clipWindow, dispPtr->clipboardAtom,
375
                type, ClipboardHandler, (ClientData) targetPtr, format);
376
    } else if (targetPtr->format != format) {
377
        Tcl_AppendResult(interp, "format \"", Tk_GetAtomName(tkwin, format),
378
                "\" does not match current format \"",
379
                Tk_GetAtomName(tkwin, targetPtr->format),"\" for ",
380
                Tk_GetAtomName(tkwin, type), (char *) NULL);
381
        return TCL_ERROR;
382
    }
383
 
384
    /*
385
     * Append a new buffer to the buffer chain.
386
     */
387
 
388
    cbPtr = (TkClipboardBuffer*) ckalloc(sizeof(TkClipboardBuffer));
389
    cbPtr->nextPtr = NULL;
390
    if (targetPtr->lastBufferPtr != NULL) {
391
        targetPtr->lastBufferPtr->nextPtr = cbPtr;
392
    } else {
393
        targetPtr->firstBufferPtr = cbPtr;
394
    }
395
    targetPtr->lastBufferPtr = cbPtr;
396
 
397
    cbPtr->length = strlen(buffer);
398
    cbPtr->buffer = (char *) ckalloc((unsigned) (cbPtr->length + 1));
399
    strcpy(cbPtr->buffer, buffer);
400
 
401
    TkSelUpdateClipboard((TkWindow*)(dispPtr->clipWindow), targetPtr);
402
 
403
    return TCL_OK;
404
}
405
 
406
/*
407
 *----------------------------------------------------------------------
408
 *
409
 * Tk_ClipboardCmd --
410
 *
411
 *      This procedure is invoked to process the "clipboard" Tcl
412
 *      command.  See the user documentation for details on what
413
 *      it does.
414
 *
415
 * Results:
416
 *      A standard Tcl result.
417
 *
418
 * Side effects:
419
 *      See the user documentation.
420
 *
421
 *----------------------------------------------------------------------
422
 */
423
 
424
int
425
Tk_ClipboardCmd(clientData, interp, argc, argv)
426
    ClientData clientData;      /* Main window associated with
427
                                 * interpreter. */
428
    Tcl_Interp *interp;         /* Current interpreter. */
429
    int argc;                   /* Number of arguments. */
430
    char **argv;                /* Argument strings. */
431
{
432
    Tk_Window tkwin = (Tk_Window) clientData;
433
    char *path = NULL;
434
    size_t length;
435
    int count;
436
    char c;
437
    char **args;
438
 
439
    if (argc < 2) {
440
        Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
441
                " option ?arg arg ...?\"", (char *) NULL);
442
        return TCL_ERROR;
443
    }
444
    c = argv[1][0];
445
    length = strlen(argv[1]);
446
    if ((c == 'a') && (strncmp(argv[1], "append", length) == 0)) {
447
        Atom target, format;
448
        char *targetName = NULL;
449
        char *formatName = NULL;
450
 
451
        for (count = argc-2, args = argv+2; count > 1; count -= 2, args += 2) {
452
            if (args[0][0] != '-') {
453
                break;
454
            }
455
            c = args[0][1];
456
            length = strlen(args[0]);
457
            if ((c == '-') && (length == 2)) {
458
                args++;
459
                count--;
460
                break;
461
            }
462
            if ((c == 'd') && (strncmp(args[0], "-displayof", length) == 0)) {
463
                path = args[1];
464
            } else if ((c == 'f')
465
                    && (strncmp(args[0], "-format", length) == 0)) {
466
                formatName = args[1];
467
            } else if ((c == 't')
468
                    && (strncmp(args[0], "-type", length) == 0)) {
469
                targetName = args[1];
470
            } else {
471
                Tcl_AppendResult(interp, "unknown option \"", args[0],
472
                        "\"", (char *) NULL);
473
                return TCL_ERROR;
474
            }
475
        }
476
        if (count != 1) {
477
            Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
478
                    " append ?options? data\"", (char *) NULL);
479
            return TCL_ERROR;
480
        }
481
        if (path != NULL) {
482
            tkwin = Tk_NameToWindow(interp, path, tkwin);
483
        }
484
        if (tkwin == NULL) {
485
            return TCL_ERROR;
486
        }
487
        if (targetName != NULL) {
488
            target = Tk_InternAtom(tkwin, targetName);
489
        } else {
490
            target = XA_STRING;
491
        }
492
        if (formatName != NULL) {
493
            format = Tk_InternAtom(tkwin, formatName);
494
        } else {
495
            format = XA_STRING;
496
        }
497
        return Tk_ClipboardAppend(interp, tkwin, target, format, args[0]);
498
    } else if ((c == 'c') && (strncmp(argv[1], "clear", length) == 0)) {
499
        for (count = argc-2, args = argv+2; count > 0; count -= 2, args += 2) {
500
            if (args[0][0] != '-') {
501
                break;
502
            }
503
            if (count < 2) {
504
                Tcl_AppendResult(interp, "value for \"", *args,
505
                        "\" missing", (char *) NULL);
506
                return TCL_ERROR;
507
            }
508
            c = args[0][1];
509
            length = strlen(args[0]);
510
            if ((c == 'd') && (strncmp(args[0], "-displayof", length) == 0)) {
511
                path = args[1];
512
            } else {
513
                Tcl_AppendResult(interp, "unknown option \"", args[0],
514
                        "\"", (char *) NULL);
515
                return TCL_ERROR;
516
            }
517
        }
518
        if (count > 0) {
519
            Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
520
                    " clear ?options?\"", (char *) NULL);
521
            return TCL_ERROR;
522
        }
523
        if (path != NULL) {
524
            tkwin = Tk_NameToWindow(interp, path, tkwin);
525
        }
526
        if (tkwin == NULL) {
527
            return TCL_ERROR;
528
        }
529
        return Tk_ClipboardClear(interp, tkwin);
530
    } else {
531
        sprintf(interp->result,
532
                "bad option \"%.50s\": must be clear or append",
533
                argv[1]);
534
        return TCL_ERROR;
535
    }
536
}
537
 
538
/*
539
 *----------------------------------------------------------------------
540
 *
541
 * TkClipInit --
542
 *
543
 *      This procedure is called to initialize the window for claiming
544
 *      clipboard ownership and for receiving selection get results.  This
545
 *      function is called from tkSelect.c as well as tkClipboard.c.
546
 *
547
 * Results:
548
 *      The result is a standard Tcl return value, which is normally TCL_OK.
549
 *      If an error occurs then an error message is left in interp->result
550
 *      and TCL_ERROR is returned.
551
 *
552
 * Side effects:
553
 *      Sets up the clipWindow and related data structures.
554
 *
555
 *----------------------------------------------------------------------
556
 */
557
 
558
int
559
TkClipInit(interp, dispPtr)
560
    Tcl_Interp *interp;         /* Interpreter to use for error
561
                                 * reporting. */
562
    register TkDisplay *dispPtr;/* Display to initialize. */
563
{
564
    XSetWindowAttributes atts;
565
 
566
    dispPtr->clipTargetPtr = NULL;
567
    dispPtr->clipboardActive = 0;
568
    dispPtr->clipboardAppPtr = NULL;
569
 
570
    /*
571
     * Create the window used for clipboard ownership and selection retrieval,
572
     * and set up an event handler for it.
573
     */
574
 
575
    dispPtr->clipWindow = Tk_CreateWindow(interp, (Tk_Window) NULL,
576
            "_clip", DisplayString(dispPtr->display));
577
    if (dispPtr->clipWindow == NULL) {
578
        return TCL_ERROR;
579
    }
580
    atts.override_redirect = True;
581
    Tk_ChangeWindowAttributes(dispPtr->clipWindow, CWOverrideRedirect, &atts);
582
    Tk_MakeWindowExist(dispPtr->clipWindow);
583
 
584
    if (dispPtr->multipleAtom == None) {
585
        /*
586
         * Need to invoke selection initialization to make sure that
587
         * atoms we depend on below are defined.
588
         */
589
 
590
        TkSelInit(dispPtr->clipWindow);
591
    }
592
 
593
    /*
594
     * Create selection handlers for types TK_APPLICATION and TK_WINDOW
595
     * on this window.  Can't use the default handlers for these types
596
     * because this isn't a full-fledged window.
597
     */
598
 
599
    Tk_CreateSelHandler(dispPtr->clipWindow, dispPtr->clipboardAtom,
600
            dispPtr->applicationAtom, ClipboardAppHandler,
601
            (ClientData) dispPtr, XA_STRING);
602
    Tk_CreateSelHandler(dispPtr->clipWindow, dispPtr->clipboardAtom,
603
            dispPtr->windowAtom, ClipboardWindowHandler,
604
            (ClientData) dispPtr, XA_STRING);
605
    return TCL_OK;
606
}

powered by: WebSVN 2.1.0

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