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

通讯编程

开发平台:

Visual C++

  1. /*
  2.  * tkMacOSXClipboard.c --
  3.  *
  4.  * This file manages the clipboard for the Tk toolkit.
  5.  *
  6.  * Copyright (c) 1995-1997 Sun Microsystems, Inc.
  7.  * Copyright 2001, Apple Computer, Inc.
  8.  * Copyright (c) 2006-2007 Daniel A. Steffen <das@users.sourceforge.net>
  9.  *
  10.  * See the file "license.terms" for information on usage and redistribution
  11.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  12.  *
  13.  * RCS: @(#) $Id: tkMacOSXClipboard.c,v 1.2.2.7 2007/06/29 03:22:01 das Exp $
  14.  */
  15. #include "tkMacOSXPrivate.h"
  16. #include "tkSelect.h"
  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(
  38.     Tcl_Interp *interp, /* Interpreter to use for reporting errors. */
  39.     Tk_Window tkwin, /* Window on whose behalf to retrieve the
  40.  * selection (determines display from which to
  41.  * retrieve). */
  42.     Atom selection, /* Selection to retrieve. */
  43.     Atom target, /* Desired form in which selection is to be
  44.  * returned. */
  45.     Tk_GetSelProc *proc, /* Procedure to call to process the selection,
  46.  * once it has been retrieved. */
  47.     ClientData clientData) /* Arbitrary value to pass to proc. */
  48. {
  49.     int result;
  50.     OSStatus err;
  51.     long length;
  52.     ScrapRef scrapRef;
  53.     char *buf;
  54.     if ((selection == Tk_InternAtom(tkwin, "CLIPBOARD"))
  55.     && (target == XA_STRING)) {
  56. /*
  57.  * Get the scrap from the Macintosh global clipboard.
  58.  */
  59. err = ChkErr(GetCurrentScrap, &scrapRef);
  60. if (err != noErr) {
  61.     Tcl_AppendResult(interp, Tk_GetAtomName(tkwin, selection),
  62.     " GetCurrentScrap failed.", NULL);
  63.     return TCL_ERROR;
  64. }
  65. /*
  66.  * Try UNICODE first
  67.  */
  68. err = ChkErr(GetScrapFlavorSize, scrapRef, kScrapFlavorTypeUnicode,
  69. &length);
  70. if (err == noErr && length > 0) {
  71.     Tcl_DString ds;
  72.     char *data;
  73.     buf = (char *) ckalloc(length + 2);
  74.     buf[length] = 0;
  75.     buf[length+1] = 0; /* 2-byte unicode null */
  76.     err = ChkErr(GetScrapFlavorData, scrapRef, kScrapFlavorTypeUnicode,
  77.     &length, buf);
  78.     if (err == noErr) {
  79. Tcl_DStringInit(&ds);
  80. Tcl_UniCharToUtfDString((Tcl_UniChar *)buf,
  81. Tcl_UniCharLen((Tcl_UniChar *)buf), &ds);
  82. for (data = Tcl_DStringValue(&ds); *data != ''; data++) {
  83.     if (*data == 'r') {
  84. *data = 'n';
  85.     }
  86. }
  87. result = (*proc)(clientData, interp, Tcl_DStringValue(&ds));
  88. Tcl_DStringFree(&ds);
  89. ckfree(buf);
  90. return result;
  91.     }
  92. }
  93. err = ChkErr(GetScrapFlavorSize, scrapRef, 'TEXT', &length);
  94. if (err != noErr) {
  95.     Tcl_AppendResult(interp, Tk_GetAtomName(tkwin, selection),
  96.     " GetScrapFlavorSize failed.", NULL);
  97.     return TCL_ERROR;
  98. }
  99. if (length > 0) {
  100.     Tcl_DString encodedText;
  101.     char *data;
  102.     buf = (char *) ckalloc(length + 1);
  103.     buf[length] = 0;
  104.     err = ChkErr(GetScrapFlavorData, scrapRef, 'TEXT', &length, buf);
  105.     if (err != noErr) {
  106.     Tcl_AppendResult(interp, Tk_GetAtomName(tkwin, selection),
  107. " GetScrapFlavorData failed.", NULL);
  108.     return TCL_ERROR;
  109.     }
  110.     /*
  111.      * Tcl expects 'n' not 'r' as the line break character.
  112.      */
  113.     for (data = buf; *data != ''; data++) {
  114. if (*data == 'r') {
  115.     *data = 'n';
  116. }
  117.     }
  118.     Tcl_ExternalToUtfDString(TkMacOSXCarbonEncoding, buf, length,
  119.     &encodedText);
  120.     result = (*proc)(clientData, interp,
  121.     Tcl_DStringValue(&encodedText));
  122.     Tcl_DStringFree(&encodedText);
  123.     ckfree(buf);
  124.     return result;
  125. }
  126.     }
  127.     Tcl_AppendResult(interp, Tk_GetAtomName(tkwin, selection),
  128.     " selection doesn't exist or form "",
  129.     Tk_GetAtomName(tkwin, target), "" not defined", NULL);
  130.     return TCL_ERROR;
  131. }
  132. /*
  133.  *----------------------------------------------------------------------
  134.  *
  135.  * TkSetSelectionOwner --
  136.  *
  137.  * This function claims ownership of the specified selection.
  138.  * If the selection is CLIPBOARD, then we empty the system
  139.  * clipboard.
  140.  *
  141.  * Results:
  142.  * None.
  143.  *
  144.  * Side effects:
  145.  * None.
  146.  *
  147.  *----------------------------------------------------------------------
  148.  */
  149. void
  150. XSetSelectionOwner(
  151.     Display *display, /* X Display. */
  152.     Atom selection, /* What selection to own. */
  153.     Window owner, /* Window to be the owner. */
  154.     Time time) /* The current time? */
  155. {
  156.     Tk_Window tkwin;
  157.     TkDisplay *dispPtr;
  158.     /*
  159.      * This is a gross hack because the Tk_InternAtom interface is broken.
  160.      * It expects a Tk_Window, even though it only needs a Tk_Display.
  161.      */
  162.     tkwin = (Tk_Window) TkGetMainInfoList()->winPtr;
  163.     if (selection == Tk_InternAtom(tkwin, "CLIPBOARD")) {
  164. /*
  165.  * Only claim and empty the clipboard if we aren't already the
  166.  * owner of the clipboard.
  167.  */
  168. dispPtr = TkGetMainInfoList()->winPtr->dispPtr;
  169. if (dispPtr->clipboardActive) {
  170.     return;
  171. }
  172. ClearCurrentScrap();
  173.     }
  174. }
  175. /*
  176.  *----------------------------------------------------------------------
  177.  *
  178.  * TkSelUpdateClipboard --
  179.  *
  180.  * This function is called to force the clipboard to be updated
  181.  * after new data is added. On the Mac we don't need to do
  182.  * anything.
  183.  *
  184.  * Results:
  185.  * None.
  186.  *
  187.  * Side effects:
  188.  * None.
  189.  *
  190.  *----------------------------------------------------------------------
  191.  */
  192. void
  193. TkSelUpdateClipboard(
  194.     TkWindow *winPtr, /* Window associated with clipboard. */
  195.     TkClipboardTarget *targetPtr)
  196. /* Info about the content. */
  197. {
  198. }
  199. /*
  200.  *--------------------------------------------------------------
  201.  *
  202.  * TkSelEventProc --
  203.  *
  204.  * This procedure is invoked whenever a selection-related
  205.  * event occurs.
  206.  *
  207.  * Results:
  208.  * None.
  209.  *
  210.  * Side effects:
  211.  * Lots: depends on the type of event.
  212.  *
  213.  *--------------------------------------------------------------
  214.  */
  215. void
  216. TkSelEventProc(
  217.     Tk_Window tkwin, /* Window for which event was targeted. */
  218.     register XEvent *eventPtr) /* X event: either SelectionClear,
  219.  * SelectionRequest, or SelectionNotify. */
  220. {
  221.     if (eventPtr->type == SelectionClear) {
  222. TkSelClearSelection(tkwin, eventPtr);
  223.     }
  224. }
  225. /*
  226.  *----------------------------------------------------------------------
  227.  *
  228.  * TkSelPropProc --
  229.  *
  230.  * This procedure is invoked when property-change events
  231.  * occur on windows not known to the toolkit. This is a stub
  232.  * function under Windows.
  233.  *
  234.  * Results:
  235.  * None.
  236.  *
  237.  * Side effects:
  238.  * None.
  239.  *
  240.  *----------------------------------------------------------------------
  241.  */
  242. void
  243. TkSelPropProc(
  244.     register XEvent *eventPtr) /* X PropertyChange event. */
  245. {
  246. }
  247. /*
  248.  *----------------------------------------------------------------------
  249.  *
  250.  * TkSuspendClipboard --
  251.  *
  252.  * Handle clipboard conversion as required by the suppend event.
  253.  * This function is also called on exit.
  254.  *
  255.  * Results:
  256.  * None.
  257.  *
  258.  * Side effects:
  259.  * The local scrap is moved to the global scrap.
  260.  *
  261.  *----------------------------------------------------------------------
  262.  */
  263. void
  264. TkSuspendClipboard(void)
  265. {
  266.     TkClipboardTarget *targetPtr;
  267.     TkClipboardBuffer *cbPtr;
  268.     TkDisplay *dispPtr;
  269.     char *buffer, *p, *endPtr, *buffPtr;
  270.     long length;
  271.     ScrapRef scrapRef;
  272.     dispPtr = TkGetDisplayList();
  273.     if ((dispPtr == NULL) || !dispPtr->clipboardActive) {
  274. return;
  275.     }
  276.     for (targetPtr = dispPtr->clipTargetPtr; targetPtr != NULL;
  277.     targetPtr = targetPtr->nextPtr) {
  278. if (targetPtr->type == XA_STRING) {
  279.     break;
  280. }
  281.     }
  282.     if (targetPtr != NULL) {
  283. Tcl_DString encodedText, unicodedText;
  284. length = 0;
  285. for (cbPtr = targetPtr->firstBufferPtr; cbPtr != NULL;
  286. cbPtr = cbPtr->nextPtr) {
  287.     length += cbPtr->length;
  288. }
  289. buffer = ckalloc(length);
  290. buffPtr = buffer;
  291. for (cbPtr = targetPtr->firstBufferPtr; cbPtr != NULL;
  292. cbPtr = cbPtr->nextPtr) {
  293.     for (p = cbPtr->buffer, endPtr = p + cbPtr->length;
  294.     p < endPtr; p++) {
  295. if (*p == 'n') {
  296.     *buffPtr++ = 'r';
  297. } else {
  298.     *buffPtr++ = *p;
  299. }
  300.     }
  301. }
  302. ClearCurrentScrap();
  303. GetCurrentScrap(&scrapRef);
  304. Tcl_UtfToExternalDString(TkMacOSXCarbonEncoding, buffer, length,
  305. &encodedText);
  306. PutScrapFlavor(scrapRef, 'TEXT', 0, Tcl_DStringLength(&encodedText),
  307. Tcl_DStringValue(&encodedText));
  308. Tcl_DStringFree(&encodedText);
  309. /*
  310.  * Also put unicode data on scrap.
  311.  */
  312. Tcl_DStringInit(&unicodedText);
  313. Tcl_UtfToUniCharDString(buffer, length, &unicodedText);
  314. PutScrapFlavor(scrapRef, kScrapFlavorTypeUnicode, 0,
  315. Tcl_DStringLength(&unicodedText),
  316. Tcl_DStringValue(&unicodedText));
  317. Tcl_DStringFree(&unicodedText);
  318. ckfree(buffer);
  319.     }
  320.     /*
  321.      * The system now owns the scrap. We tell Tk that it has
  322.      * lost the selection so that it will look for it the next time
  323.      * it needs it. (Window list NULL if quiting.)
  324.      */
  325.     if (TkGetMainInfoList() != NULL) {
  326. Tk_ClearSelection((Tk_Window) TkGetMainInfoList()->winPtr,
  327. Tk_InternAtom((Tk_Window) TkGetMainInfoList()->winPtr,
  328. "CLIPBOARD"));
  329.     }
  330.     return;
  331. }