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

Diff of /projs/ets/trunk/src/c_tk_base_7_5_w_mods/tkclipboard.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

to_be_filed/sf_code/esrgpcpj/shared/tk_base/tkclipboard.c revision 29 by dashley, Sat Oct 8 07:08:47 2016 UTC projs/dtats/trunk/shared_source/c_tk_base_7_5_w_mods/tkclipboard.c revision 98 by dashley, Sun Dec 18 00:57:31 2016 UTC
# Line 1  Line 1 
 /* $Header: /cvsroot/esrg/sfesrg/esrgpcpj/shared/tk_base/tkclipboard.c,v 1.1.1.1 2001/06/13 04:58:07 dtashley Exp $ */  
   
 /*  
  * tkClipboard.c --  
  *  
  *      This file manages the clipboard for the Tk toolkit,  
  *      maintaining a collection of data buffers that will be  
  *      supplied on demand to requesting applications.  
  *  
  * Copyright (c) 1994 The Regents of the University of California.  
  * Copyright (c) 1994-1997 Sun Microsystems, Inc.  
  *  
  * See the file "license.terms" for information on usage and redistribution  
  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.  
  *  
  * RCS: @(#) $Id: tkclipboard.c,v 1.1.1.1 2001/06/13 04:58:07 dtashley Exp $  
  */  
   
 #include "tkInt.h"  
 #include "tkPort.h"  
 #include "tkSelect.h"  
   
 /*  
  * Prototypes for procedures used only in this file:  
  */  
   
 static int              ClipboardAppHandler _ANSI_ARGS_((ClientData clientData,  
                             int offset, char *buffer, int maxBytes));  
 static int              ClipboardHandler _ANSI_ARGS_((ClientData clientData,  
                             int offset, char *buffer, int maxBytes));  
 static int              ClipboardWindowHandler _ANSI_ARGS_((  
                             ClientData clientData, int offset, char *buffer,  
                             int maxBytes));  
 static void             ClipboardLostSel _ANSI_ARGS_((ClientData clientData));  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * ClipboardHandler --  
  *  
  *      This procedure acts as selection handler for the  
  *      clipboard manager.  It extracts the required chunk of  
  *      data from the buffer chain for a given selection target.  
  *  
  * Results:  
  *      The return value is a count of the number of bytes  
  *      actually stored at buffer.  
  *  
  * Side effects:  
  *      None.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 static int  
 ClipboardHandler(clientData, offset, buffer, maxBytes)  
     ClientData clientData;      /* Information about data to fetch. */  
     int offset;                 /* Return selection bytes starting at this  
                                  * offset. */  
     char *buffer;               /* Place to store converted selection. */  
     int maxBytes;               /* Maximum # of bytes to store at buffer. */  
 {  
     TkClipboardTarget *targetPtr = (TkClipboardTarget*) clientData;  
     TkClipboardBuffer *cbPtr;  
     char *srcPtr, *destPtr;  
     int count = 0;  
     int scanned = 0;  
     size_t length, freeCount;  
   
     /*  
      * Skip to buffer containing offset byte  
      */  
   
     for (cbPtr = targetPtr->firstBufferPtr; ; cbPtr = cbPtr->nextPtr) {  
         if (cbPtr == NULL) {  
             return 0;  
         }  
         if (scanned + cbPtr->length > offset) {  
             break;  
         }  
         scanned += cbPtr->length;  
     }  
   
     /*  
      * Copy up to maxBytes or end of list, switching buffers as needed.  
      */  
   
     freeCount = maxBytes;  
     srcPtr = cbPtr->buffer + (offset - scanned);  
     destPtr = buffer;  
     length = cbPtr->length - (offset - scanned);  
     while (1) {  
         if (length > freeCount) {  
             strncpy(destPtr, srcPtr, freeCount);  
             return maxBytes;  
         } else {  
             strncpy(destPtr, srcPtr, length);  
             destPtr += length;  
             count += length;  
             freeCount -= length;  
         }  
         cbPtr = cbPtr->nextPtr;  
         if (cbPtr == NULL) {  
             break;  
         }  
         srcPtr = cbPtr->buffer;  
         length = cbPtr->length;  
     }  
     return count;  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * ClipboardAppHandler --  
  *  
  *      This procedure acts as selection handler for retrievals of type  
  *      TK_APPLICATION.  It returns the name of the application that  
  *      owns the clipboard.  Note:  we can't use the default Tk  
  *      selection handler for this selection type, because the clipboard  
  *      window isn't a "real" window and doesn't have the necessary  
  *      information.  
  *  
  * Results:  
  *      The return value is a count of the number of bytes  
  *      actually stored at buffer.  
  *  
  * Side effects:  
  *      None.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 static int  
 ClipboardAppHandler(clientData, offset, buffer, maxBytes)  
     ClientData clientData;      /* Pointer to TkDisplay structure. */  
     int offset;                 /* Return selection bytes starting at this  
                                  * offset. */  
     char *buffer;               /* Place to store converted selection. */  
     int maxBytes;               /* Maximum # of bytes to store at buffer. */  
 {  
     TkDisplay *dispPtr = (TkDisplay *) clientData;  
     size_t length;  
     char *p;  
   
     p = dispPtr->clipboardAppPtr->winPtr->nameUid;  
     length = strlen(p);  
     length -= offset;  
     if (length <= 0) {  
         return 0;  
     }  
     if (length > (size_t) maxBytes) {  
         length = maxBytes;  
     }  
     strncpy(buffer, p, length);  
     return length;  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * ClipboardWindowHandler --  
  *  
  *      This procedure acts as selection handler for retrievals of  
  *      type TK_WINDOW.  Since the clipboard doesn't correspond to  
  *      any particular window, we just return ".".  We can't use Tk's  
  *      default handler for this selection type, because the clipboard  
  *      window isn't a valid window.  
  *  
  * Results:  
  *      The return value is 1, the number of non-null bytes stored  
  *      at buffer.  
  *  
  * Side effects:  
  *      None.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 static int  
 ClipboardWindowHandler(clientData, offset, buffer, maxBytes)  
     ClientData clientData;      /* Not used. */  
     int offset;                 /* Return selection bytes starting at this  
                                  * offset. */  
     char *buffer;               /* Place to store converted selection. */  
     int maxBytes;               /* Maximum # of bytes to store at buffer. */  
 {  
     buffer[0] = '.';  
     buffer[1] = 0;  
     return 1;  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * ClipboardLostSel --  
  *  
  *      This procedure is invoked whenever clipboard ownership is  
  *      claimed by another window.  It just sets a flag so that we  
  *      know the clipboard was taken away.  
  *  
  * Results:  
  *      None.  
  *  
  * Side effects:  
  *      The clipboard is marked as inactive.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 static void  
 ClipboardLostSel(clientData)  
     ClientData clientData;              /* Pointer to TkDisplay structure. */  
 {  
     TkDisplay *dispPtr = (TkDisplay*) clientData;  
   
     dispPtr->clipboardActive = 0;  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * Tk_ClipboardClear --  
  *  
  *      Take control of the clipboard and clear out the previous  
  *      contents.  This procedure must be invoked before any  
  *      calls to Tk_ClipboardAppend.  
  *  
  * Results:  
  *      A standard Tcl result.  If an error occurs, an error message is  
  *      left in the interp's result.  
  *  
  * Side effects:  
  *      From now on, requests for the CLIPBOARD selection will be  
  *      directed to the clipboard manager routines associated with  
  *      clipWindow for the display of tkwin.  In order to guarantee  
  *      atomicity, no event handling should occur between  
  *      Tk_ClipboardClear and the following Tk_ClipboardAppend  
  *      calls.  This procedure may cause a user-defined LostSel command  
  *      to be invoked when the CLIPBOARD is claimed, so any calling  
  *      function should be reentrant at the point Tk_ClipboardClear is  
  *      invoked.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 int  
 Tk_ClipboardClear(interp, tkwin)  
     Tcl_Interp *interp;         /* Interpreter to use for error reporting. */  
     Tk_Window tkwin;            /* Window in application that is clearing  
                                  * clipboard;  identifies application and  
                                  * display. */  
 {  
     TkWindow *winPtr = (TkWindow *) tkwin;  
     TkDisplay *dispPtr = winPtr->dispPtr;  
     TkClipboardTarget *targetPtr, *nextTargetPtr;  
     TkClipboardBuffer *cbPtr, *nextCbPtr;  
   
     if (dispPtr->clipWindow == NULL) {  
         int result;  
   
         result = TkClipInit(interp, dispPtr);  
         if (result != TCL_OK) {  
             return result;  
         }  
     }  
   
     /*  
      * Discard any existing clipboard data and delete the selection  
      * handler(s) associated with that data.  
      */  
   
     for (targetPtr = dispPtr->clipTargetPtr; targetPtr != NULL;  
             targetPtr = nextTargetPtr) {  
         for (cbPtr = targetPtr->firstBufferPtr; cbPtr != NULL;  
                 cbPtr = nextCbPtr) {  
             ckfree(cbPtr->buffer);  
             nextCbPtr = cbPtr->nextPtr;  
             ckfree((char *) cbPtr);  
         }  
         nextTargetPtr = targetPtr->nextPtr;  
         Tk_DeleteSelHandler(dispPtr->clipWindow, dispPtr->clipboardAtom,  
                 targetPtr->type);  
         ckfree((char *) targetPtr);  
     }  
     dispPtr->clipTargetPtr = NULL;  
   
     /*  
      * Reclaim the clipboard selection if we lost it.  
      */  
   
     if (!dispPtr->clipboardActive) {  
         Tk_OwnSelection(dispPtr->clipWindow, dispPtr->clipboardAtom,  
                 ClipboardLostSel, (ClientData) dispPtr);  
         dispPtr->clipboardActive = 1;  
     }  
     dispPtr->clipboardAppPtr = winPtr->mainPtr;  
     return TCL_OK;  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * Tk_ClipboardAppend --  
  *  
  *      Append a buffer of data to the clipboard.  The first buffer of  
  *      a given type determines the format for that type.  Any successive  
  *      appends to that type must have the same format or an error will  
  *      be returned.  Tk_ClipboardClear must be called before a sequence  
  *      of Tk_ClipboardAppend calls can be issued.  In order to guarantee  
  *      atomicity, no event handling should occur between Tk_ClipboardClear  
  *      and the following Tk_ClipboardAppend calls.  
  *  
  * Results:  
  *      A standard Tcl result.  If an error is returned, an error message  
  *      is left in the interp's result.  
  *  
  * Side effects:  
  *      The specified buffer will be copied onto the end of the clipboard.  
  *      The clipboard maintains a list of buffers which will be used to  
  *      supply the data for a selection get request.  The first time a given  
  *      type is appended, Tk_ClipboardAppend will register a selection  
  *      handler of the appropriate type.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 int  
 Tk_ClipboardAppend(interp, tkwin, type, format, buffer)  
     Tcl_Interp *interp;         /* Used for error reporting. */  
     Tk_Window tkwin;            /* Window that selects a display. */  
     Atom type;                  /* The desired conversion type for this  
                                  * clipboard item, e.g. STRING or LENGTH. */  
     Atom format;                /* Format in which the selection  
                                  * information should be returned to  
                                  * the requestor. */  
     char* buffer;               /* NULL terminated string containing the data  
                                  * to be added to the clipboard. */  
 {  
     TkWindow *winPtr = (TkWindow *) tkwin;  
     TkDisplay *dispPtr = winPtr->dispPtr;  
     TkClipboardTarget *targetPtr;  
     TkClipboardBuffer *cbPtr;  
   
     /*  
      * If this application doesn't already own the clipboard, clear  
      * the clipboard.  If we don't own the clipboard selection, claim it.  
      */  
   
     if (dispPtr->clipboardAppPtr != winPtr->mainPtr) {  
         Tk_ClipboardClear(interp, tkwin);  
     } else if (!dispPtr->clipboardActive) {  
         Tk_OwnSelection(dispPtr->clipWindow, dispPtr->clipboardAtom,  
                 ClipboardLostSel, (ClientData) dispPtr);  
         dispPtr->clipboardActive = 1;  
     }  
   
     /*  
      * Check to see if the specified target is already present on the  
      * clipboard.  If it isn't, we need to create a new target; otherwise,  
      * we just append the new buffer to the clipboard list.  
      */  
   
     for (targetPtr = dispPtr->clipTargetPtr; targetPtr != NULL;  
             targetPtr = targetPtr->nextPtr) {  
         if (targetPtr->type == type)  
             break;  
     }  
     if (targetPtr == NULL) {  
         targetPtr = (TkClipboardTarget*) ckalloc(sizeof(TkClipboardTarget));  
         targetPtr->type = type;  
         targetPtr->format = format;  
         targetPtr->firstBufferPtr = targetPtr->lastBufferPtr = NULL;  
         targetPtr->nextPtr = dispPtr->clipTargetPtr;  
         dispPtr->clipTargetPtr = targetPtr;  
         Tk_CreateSelHandler(dispPtr->clipWindow, dispPtr->clipboardAtom,  
                 type, ClipboardHandler, (ClientData) targetPtr, format);  
     } else if (targetPtr->format != format) {  
         Tcl_AppendResult(interp, "format \"", Tk_GetAtomName(tkwin, format),  
                 "\" does not match current format \"",  
                 Tk_GetAtomName(tkwin, targetPtr->format),"\" for ",  
                 Tk_GetAtomName(tkwin, type), (char *) NULL);  
         return TCL_ERROR;  
     }  
   
     /*  
      * Append a new buffer to the buffer chain.  
      */  
   
     cbPtr = (TkClipboardBuffer*) ckalloc(sizeof(TkClipboardBuffer));  
     cbPtr->nextPtr = NULL;  
     if (targetPtr->lastBufferPtr != NULL) {  
         targetPtr->lastBufferPtr->nextPtr = cbPtr;  
     } else {  
         targetPtr->firstBufferPtr = cbPtr;  
     }  
     targetPtr->lastBufferPtr = cbPtr;  
   
     cbPtr->length = strlen(buffer);  
     cbPtr->buffer = (char *) ckalloc((unsigned) (cbPtr->length + 1));  
     strcpy(cbPtr->buffer, buffer);  
   
     TkSelUpdateClipboard((TkWindow*)(dispPtr->clipWindow), targetPtr);  
   
     return TCL_OK;  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * Tk_ClipboardCmd --  
  *  
  *      This procedure is invoked to process the "clipboard" Tcl  
  *      command.  See the user documentation for details on what  
  *      it does.  
  *  
  * Results:  
  *      A standard Tcl result.  
  *  
  * Side effects:  
  *      See the user documentation.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 int  
 Tk_ClipboardCmd(clientData, interp, argc, argv)  
     ClientData clientData;      /* Main window associated with  
                                  * interpreter. */  
     Tcl_Interp *interp;         /* Current interpreter. */  
     int argc;                   /* Number of arguments. */  
     char **argv;                /* Argument strings. */  
 {  
     Tk_Window tkwin = (Tk_Window) clientData;  
     char *path = NULL;  
     size_t length;  
     int count;  
     char c;  
     char **args;  
   
     if (argc < 2) {  
         Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],  
                 " option ?arg arg ...?\"", (char *) NULL);  
         return TCL_ERROR;  
     }  
     c = argv[1][0];  
     length = strlen(argv[1]);  
     if ((c == 'a') && (strncmp(argv[1], "append", length) == 0)) {  
         Atom target, format;  
         char *targetName = NULL;  
         char *formatName = NULL;  
   
         for (count = argc-2, args = argv+2; count > 1; count -= 2, args += 2) {  
             if (args[0][0] != '-') {  
                 break;  
             }  
             c = args[0][1];  
             length = strlen(args[0]);  
             if ((c == '-') && (length == 2)) {  
                 args++;  
                 count--;  
                 break;  
             }  
             if ((c == 'd') && (strncmp(args[0], "-displayof", length) == 0)) {  
                 path = args[1];  
             } else if ((c == 'f')  
                     && (strncmp(args[0], "-format", length) == 0)) {  
                 formatName = args[1];  
             } else if ((c == 't')  
                     && (strncmp(args[0], "-type", length) == 0)) {  
                 targetName = args[1];  
             } else {  
                 Tcl_AppendResult(interp, "unknown option \"", args[0],  
                         "\"", (char *) NULL);  
                 return TCL_ERROR;  
             }  
         }  
         if (count != 1) {  
             Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],  
                     " append ?options? data\"", (char *) NULL);  
             return TCL_ERROR;  
         }  
         if (path != NULL) {  
             tkwin = Tk_NameToWindow(interp, path, tkwin);  
         }  
         if (tkwin == NULL) {  
             return TCL_ERROR;  
         }  
         if (targetName != NULL) {  
             target = Tk_InternAtom(tkwin, targetName);  
         } else {  
             target = XA_STRING;  
         }  
         if (formatName != NULL) {  
             format = Tk_InternAtom(tkwin, formatName);  
         } else {  
             format = XA_STRING;  
         }  
         return Tk_ClipboardAppend(interp, tkwin, target, format, args[0]);  
     } else if ((c == 'c') && (strncmp(argv[1], "clear", length) == 0)) {  
         for (count = argc-2, args = argv+2; count > 0; count -= 2, args += 2) {  
             if (args[0][0] != '-') {  
                 break;  
             }  
             if (count < 2) {  
                 Tcl_AppendResult(interp, "value for \"", *args,  
                         "\" missing", (char *) NULL);  
                 return TCL_ERROR;  
             }  
             c = args[0][1];  
             length = strlen(args[0]);  
             if ((c == 'd') && (strncmp(args[0], "-displayof", length) == 0)) {  
                 path = args[1];  
             } else {  
                 Tcl_AppendResult(interp, "unknown option \"", args[0],  
                         "\"", (char *) NULL);  
                 return TCL_ERROR;  
             }  
         }  
         if (count > 0) {  
             Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],  
                     " clear ?options?\"", (char *) NULL);  
             return TCL_ERROR;  
         }  
         if (path != NULL) {  
             tkwin = Tk_NameToWindow(interp, path, tkwin);  
         }  
         if (tkwin == NULL) {  
             return TCL_ERROR;  
         }  
         return Tk_ClipboardClear(interp, tkwin);  
     } else {  
         char buf[100 + TCL_INTEGER_SPACE];  
           
         sprintf(buf, "bad option \"%.50s\": must be clear or append", argv[1]);  
         Tcl_SetResult(interp, buf, TCL_VOLATILE);  
         return TCL_ERROR;  
     }  
 }  
   
 /*  
  *----------------------------------------------------------------------  
  *  
  * TkClipInit --  
  *  
  *      This procedure is called to initialize the window for claiming  
  *      clipboard ownership and for receiving selection get results.  This  
  *      function is called from tkSelect.c as well as tkClipboard.c.  
  *  
  * Results:  
  *      The result is a standard Tcl return value, which is normally TCL_OK.  
  *      If an error occurs then an error message is left in the interp's  
  *      result and TCL_ERROR is returned.  
  *  
  * Side effects:  
  *      Sets up the clipWindow and related data structures.  
  *  
  *----------------------------------------------------------------------  
  */  
   
 int  
 TkClipInit(interp, dispPtr)  
     Tcl_Interp *interp;         /* Interpreter to use for error  
                                  * reporting. */  
     register TkDisplay *dispPtr;/* Display to initialize. */  
 {  
     XSetWindowAttributes atts;  
   
     dispPtr->clipTargetPtr = NULL;  
     dispPtr->clipboardActive = 0;  
     dispPtr->clipboardAppPtr = NULL;  
       
     /*  
      * Create the window used for clipboard ownership and selection retrieval,  
      * and set up an event handler for it.  
      */  
   
     dispPtr->clipWindow = Tk_CreateWindow(interp, (Tk_Window) NULL,  
             "_clip", DisplayString(dispPtr->display));  
     if (dispPtr->clipWindow == NULL) {  
         return TCL_ERROR;  
     }  
     atts.override_redirect = True;  
     Tk_ChangeWindowAttributes(dispPtr->clipWindow, CWOverrideRedirect, &atts);  
     Tk_MakeWindowExist(dispPtr->clipWindow);  
   
     if (dispPtr->multipleAtom == None) {  
         /*  
          * Need to invoke selection initialization to make sure that  
          * atoms we depend on below are defined.  
          */  
   
         TkSelInit(dispPtr->clipWindow);  
     }  
   
     /*  
      * Create selection handlers for types TK_APPLICATION and TK_WINDOW  
      * on this window.  Can't use the default handlers for these types  
      * because this isn't a full-fledged window.  
      */  
   
     Tk_CreateSelHandler(dispPtr->clipWindow, dispPtr->clipboardAtom,  
             dispPtr->applicationAtom, ClipboardAppHandler,  
             (ClientData) dispPtr, XA_STRING);  
     Tk_CreateSelHandler(dispPtr->clipWindow, dispPtr->clipboardAtom,  
             dispPtr->windowAtom, ClipboardWindowHandler,  
             (ClientData) dispPtr, XA_STRING);  
     return TCL_OK;  
 }  
   
   
 /* $History: tkClipboard.c $  
  *  
  * *****************  Version 1  *****************  
  * User: Dtashley     Date: 1/02/01    Time: 2:41a  
  * Created in $/IjuScripter, IjuConsole/Source/Tk Base  
  * Initial check-in.  
  */  
   
 /* End of TKCLIPBOARD.C */  
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 */

Legend:
Removed from v.29  
changed lines
  Added in v.98

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25