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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 69 - (show annotations) (download)
Sat Nov 5 10:54:17 2016 UTC (6 years, 3 months ago) by dashley
File MIME type: text/plain
File size: 18575 byte(s)
License and property (keyword) changes.
1 /* $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:keywords Header

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25