/[dtapublic]/projs/trunk/shared_source/c_tk_base_7_5_w_mods/tkclipboard.c
ViewVC logotype

Annotation of /projs/trunk/shared_source/c_tk_base_7_5_w_mods/tkclipboard.c

Parent Directory Parent Directory | Revision Log Revision Log


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

Properties

Name Value
svn:eol-style native
svn:keywords Header

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25