tkWinClipboard.c
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:10k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /* 
  2.  * tkWinClipboard.c --
  3.  *
  4.  * This file contains functions for managing the clipboard.
  5.  *
  6.  * Copyright (c) 1995-1997 Sun Microsystems, Inc.
  7.  * Copyright (c) 1998-2000 by Scriptics Corporation.
  8.  *
  9.  * See the file "license.terms" for information on usage and redistribution
  10.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  11.  *
  12.  * RCS: @(#) $Id: tkWinClipboard.c,v 1.7 2000/04/12 18:51:11 hobbs Exp $
  13.  */
  14. #include "tkWinInt.h"
  15. #include "tkSelect.h"
  16. static void UpdateClipboard _ANSI_ARGS_((HWND hwnd));
  17. /*
  18.  *----------------------------------------------------------------------
  19.  *
  20.  * TkSelGetSelection --
  21.  *
  22.  * Retrieve the specified selection from another process.  For
  23.  * now, only fetching XA_STRING from CLIPBOARD is supported.
  24.  * Eventually other types should be allowed.
  25.  * 
  26.  * Results:
  27.  * The return value is a standard Tcl return value.
  28.  * If an error occurs (such as no selection exists)
  29.  * then an error message is left in the interp's result.
  30.  *
  31.  * Side effects:
  32.  * None.
  33.  *
  34.  *----------------------------------------------------------------------
  35.  */
  36. int
  37. TkSelGetSelection(interp, tkwin, selection, target, proc, clientData)
  38.     Tcl_Interp *interp; /* Interpreter to use for reporting
  39.  * errors. */
  40.     Tk_Window tkwin; /* Window on whose behalf to retrieve
  41.  * the selection (determines display
  42.  * from which to retrieve). */
  43.     Atom selection; /* Selection to retrieve. */
  44.     Atom target; /* Desired form in which selection
  45.  * is to be returned. */
  46.     Tk_GetSelProc *proc; /* Procedure to call to process the
  47.  * selection, once it has been retrieved. */
  48.     ClientData clientData; /* Arbitrary value to pass to proc. */
  49. {
  50.     char *data, *destPtr;
  51.     Tcl_DString ds;
  52.     HGLOBAL handle;
  53.     Tcl_Encoding encoding;
  54.     int result, locale;
  55.     if ((selection != Tk_InternAtom(tkwin, "CLIPBOARD"))
  56.     || (target != XA_STRING)
  57.     || !OpenClipboard(NULL)) {
  58. goto error;
  59.     }
  60.     /*
  61.      * Attempt to get the data in Unicode form if available as this is
  62.      * less work that CF_TEXT.
  63.      */
  64.     result = TCL_ERROR;
  65.     if (IsClipboardFormatAvailable(CF_UNICODETEXT)) {
  66. handle = GetClipboardData(CF_UNICODETEXT);
  67. if (!handle) {
  68.     CloseClipboard();
  69.     goto error;
  70. }
  71. data = GlobalLock(handle);
  72. Tcl_DStringInit(&ds);
  73. Tcl_UniCharToUtfDString((Tcl_UniChar *)data,
  74. Tcl_UniCharLen((Tcl_UniChar *)data), &ds);
  75. GlobalUnlock(handle);
  76.     } else if (IsClipboardFormatAvailable(CF_TEXT)) {
  77. /*
  78.  * Determine the encoding to use to convert this text.
  79.  */
  80. if (IsClipboardFormatAvailable(CF_LOCALE)) {
  81.     handle = GetClipboardData(CF_LOCALE);
  82.     if (!handle) {
  83. CloseClipboard();
  84. goto error;
  85.     }
  86.     /*
  87.      * Get the locale identifier, determine the proper code page
  88.      * to use, and find the corresponding encoding.
  89.      */
  90.     Tcl_DStringInit(&ds);
  91.     Tcl_DStringAppend(&ds, "cp######", -1);
  92.     data = GlobalLock(handle);
  93.     
  94.     /*
  95.      * Even though the documentation claims that GetLocaleInfo 
  96.      * expects an LCID, on Windows 9x it really seems to expect
  97.      * a LanguageID.
  98.      */
  99.     locale = LANGIDFROMLCID(*((int*)data));
  100.     GetLocaleInfo(locale, LOCALE_IDEFAULTANSICODEPAGE,
  101.     Tcl_DStringValue(&ds)+2, Tcl_DStringLength(&ds)-2);
  102.     GlobalUnlock(handle);
  103.     encoding = Tcl_GetEncoding(NULL, Tcl_DStringValue(&ds));
  104.     Tcl_DStringFree(&ds);
  105. } else {
  106.     encoding = NULL;
  107. }
  108. /*
  109.  * Fetch the text and convert it to UTF.
  110.  */
  111. handle = GetClipboardData(CF_TEXT);
  112. if (!handle) {
  113.     if (encoding) {
  114. Tcl_FreeEncoding(encoding);
  115.     }
  116.     CloseClipboard();
  117.     goto error;
  118. }
  119. data = GlobalLock(handle);
  120. Tcl_ExternalToUtfDString(encoding, data, -1, &ds);
  121. GlobalUnlock(handle);
  122. if (encoding) {
  123.     Tcl_FreeEncoding(encoding);
  124. }
  125.     } else {
  126. CloseClipboard();
  127. goto error;
  128.     }
  129.     /*
  130.      * Translate CR/LF to LF.
  131.      */
  132.     data = destPtr = Tcl_DStringValue(&ds);
  133.     while (*data) {
  134. if (data[0] == 'r' && data[1] == 'n') {
  135.     data++;
  136. } else {
  137.     *destPtr++ = *data++;
  138. }
  139.     }
  140.     *destPtr = '';
  141.     /*
  142.      * Pass the data off to the selection procedure.
  143.      */
  144.     result = (*proc)(clientData, interp, Tcl_DStringValue(&ds));
  145.     Tcl_DStringFree(&ds);
  146.     CloseClipboard();
  147.     return result;
  148.      
  149. error:
  150.     Tcl_AppendResult(interp, Tk_GetAtomName(tkwin, selection),
  151.     " selection doesn't exist or form "",
  152.     Tk_GetAtomName(tkwin, target),
  153.     "" not defined", (char *) NULL);
  154.     return TCL_ERROR;
  155. }
  156. /*
  157.  *----------------------------------------------------------------------
  158.  *
  159.  * TkSetSelectionOwner --
  160.  *
  161.  * This function claims ownership of the specified selection.
  162.  * If the selection is CLIPBOARD, then we empty the system
  163.  * clipboard.
  164.  *
  165.  * Results:
  166.  * None.
  167.  *
  168.  * Side effects:
  169.  * Empties the system clipboard, and claims ownership.
  170.  *
  171.  *----------------------------------------------------------------------
  172.  */
  173. void
  174. XSetSelectionOwner(display, selection, owner, time)
  175.     Display* display;
  176.     Atom selection;
  177.     Window owner;
  178.     Time time;
  179. {
  180.     HWND hwnd = owner ? TkWinGetHWND(owner) : NULL;
  181.     Tk_Window tkwin;
  182.     /*
  183.      * This is a gross hack because the Tk_InternAtom interface is broken.
  184.      * It expects a Tk_Window, even though it only needs a Tk_Display.
  185.      */
  186.     tkwin = (Tk_Window) TkGetMainInfoList()->winPtr;
  187.     if (selection == Tk_InternAtom(tkwin, "CLIPBOARD")) {
  188. /*
  189.  * Only claim and empty the clipboard if we aren't already the
  190.  * owner of the clipboard.
  191.  */
  192. if (GetClipboardOwner() != hwnd) {
  193.     UpdateClipboard(hwnd);
  194. }
  195.     }
  196. }
  197. /*
  198.  *----------------------------------------------------------------------
  199.  *
  200.  * TkWinClipboardRender --
  201.  *
  202.  * This function supplies the contents of the clipboard in
  203.  * response to a WM_RENDERFORMAT message.
  204.  *
  205.  * Results:
  206.  * None.
  207.  *
  208.  * Side effects:
  209.  * Sets the contents of the clipboard.
  210.  *
  211.  *----------------------------------------------------------------------
  212.  */
  213. void
  214. TkWinClipboardRender(dispPtr, format)
  215.     TkDisplay *dispPtr;
  216.     UINT format;
  217. {
  218.     TkClipboardTarget *targetPtr;
  219.     TkClipboardBuffer *cbPtr;
  220.     HGLOBAL handle;
  221.     char *buffer, *p, *rawText, *endPtr;
  222.     int length;
  223.     Tcl_DString ds;
  224.     for (targetPtr = dispPtr->clipTargetPtr; targetPtr != NULL;
  225.     targetPtr = targetPtr->nextPtr) {
  226. if (targetPtr->type == XA_STRING)
  227.     break;
  228.     }
  229.     /*
  230.      * Count the number of newlines so we can add space for them in
  231.      * the resulting string.
  232.      */
  233.     length = 0;
  234.     if (targetPtr != NULL) {
  235. for (cbPtr = targetPtr->firstBufferPtr; cbPtr != NULL;
  236. cbPtr = cbPtr->nextPtr) {
  237.     length += cbPtr->length;
  238.     for (p = cbPtr->buffer, endPtr = p + cbPtr->length;
  239.     p < endPtr; p++) {
  240. if (*p == 'n') {
  241.     length++;
  242. }
  243.     }
  244. }
  245.     }
  246.     /*
  247.      * Copy the data and change EOL characters.
  248.      */
  249.     buffer = rawText = ckalloc(length + 1);
  250.     if (targetPtr != NULL) {
  251. for (cbPtr = targetPtr->firstBufferPtr; cbPtr != NULL;
  252. cbPtr = cbPtr->nextPtr) {
  253.     for (p = cbPtr->buffer, endPtr = p + cbPtr->length;
  254.     p < endPtr; p++) {
  255. if (*p == 'n') {
  256.     *buffer++ = 'r';
  257. }
  258. *buffer++ = *p;
  259.     }
  260. }
  261.     }
  262.     *buffer = '';
  263.     /*
  264.      * Depending on the platform, turn the data into Unicode or the
  265.      * system encoding before placing it on the clipboard.
  266.      */
  267.     if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_NT) {
  268. Tcl_DStringInit(&ds);
  269. Tcl_UtfToUniCharDString(rawText, -1, &ds);
  270. ckfree(rawText);
  271. handle = GlobalAlloc(GMEM_MOVEABLE|GMEM_DDESHARE,
  272. Tcl_DStringLength(&ds)+2);
  273. if (!handle) {
  274.     Tcl_DStringFree(&ds);
  275.     return;
  276. }
  277. buffer = GlobalLock(handle);
  278. memcpy(buffer, Tcl_DStringValue(&ds), Tcl_DStringLength(&ds) + 2);
  279. GlobalUnlock(handle);
  280. Tcl_DStringFree(&ds);
  281. SetClipboardData(CF_UNICODETEXT, handle);
  282.     } else {
  283. Tcl_UtfToExternalDString(NULL, rawText, -1, &ds);
  284. ckfree(rawText);
  285. handle = GlobalAlloc(GMEM_MOVEABLE|GMEM_DDESHARE,
  286. Tcl_DStringLength(&ds)+1);
  287. if (!handle) {
  288.     Tcl_DStringFree(&ds);
  289.     return;
  290. }
  291. buffer = GlobalLock(handle);
  292. memcpy(buffer, Tcl_DStringValue(&ds), Tcl_DStringLength(&ds) + 1);
  293. GlobalUnlock(handle);
  294. Tcl_DStringFree(&ds);
  295. SetClipboardData(CF_TEXT, handle);
  296.     }
  297.     return;
  298. }
  299. /*
  300.  *----------------------------------------------------------------------
  301.  *
  302.  * TkSelUpdateClipboard --
  303.  *
  304.  * This function is called to force the clipboard to be updated
  305.  * after new data is added.
  306.  *
  307.  * Results:
  308.  * None.
  309.  *
  310.  * Side effects:
  311.  * Clears the current contents of the clipboard.
  312.  *
  313.  *----------------------------------------------------------------------
  314.  */
  315. void
  316. TkSelUpdateClipboard(winPtr, targetPtr)
  317.     TkWindow *winPtr;
  318.     TkClipboardTarget *targetPtr;
  319. {
  320.     HWND hwnd = TkWinGetHWND(winPtr->window);
  321.     UpdateClipboard(hwnd);
  322. }
  323. /*
  324.  *----------------------------------------------------------------------
  325.  *
  326.  * UpdateClipboard --
  327.  *
  328.  * Take ownership of the clipboard, clear it, and indicate to the
  329.  * system the supported formats.
  330.  *
  331.  * Results:
  332.  * None.
  333.  *
  334.  * Side effects:
  335.  * None.
  336.  *
  337.  *----------------------------------------------------------------------
  338.  */
  339. static void
  340. UpdateClipboard(hwnd)
  341.     HWND hwnd;
  342. {
  343.     TkWinUpdatingClipboard(TRUE);
  344.     OpenClipboard(hwnd);
  345.     EmptyClipboard();
  346.     /*
  347.      * CF_UNICODETEXT is only supported on NT, but it it is prefered
  348.      * when possible.
  349.      */
  350.     if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_NT) {
  351. SetClipboardData(CF_UNICODETEXT, NULL);
  352.     } else {
  353. SetClipboardData(CF_TEXT, NULL);
  354.     }
  355.     CloseClipboard();
  356.     TkWinUpdatingClipboard(FALSE);
  357. }
  358. /*
  359.  *--------------------------------------------------------------
  360.  *
  361.  * TkSelEventProc --
  362.  *
  363.  * This procedure is invoked whenever a selection-related
  364.  * event occurs. 
  365.  *
  366.  * Results:
  367.  * None.
  368.  *
  369.  * Side effects:
  370.  * Lots:  depends on the type of event.
  371.  *
  372.  *--------------------------------------------------------------
  373.  */
  374. void
  375. TkSelEventProc(tkwin, eventPtr)
  376.     Tk_Window tkwin; /* Window for which event was
  377.  * targeted. */
  378.     register XEvent *eventPtr; /* X event:  either SelectionClear,
  379.  * SelectionRequest, or
  380.  * SelectionNotify. */
  381. {
  382.     if (eventPtr->type == SelectionClear) {
  383. TkSelClearSelection(tkwin, eventPtr);
  384.     }
  385. }
  386. /*
  387.  *----------------------------------------------------------------------
  388.  *
  389.  * TkSelPropProc --
  390.  *
  391.  * This procedure is invoked when property-change events
  392.  * occur on windows not known to the toolkit.  This is a stub
  393.  * function under Windows.
  394.  *
  395.  * Results:
  396.  * None.
  397.  *
  398.  * Side effects:
  399.  * None.
  400.  *
  401.  *----------------------------------------------------------------------
  402.  */
  403. void
  404. TkSelPropProc(eventPtr)
  405.     register XEvent *eventPtr; /* X PropertyChange event. */
  406. {
  407. }