DndText.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407
  1. /*
  2. * CDE - Common Desktop Environment
  3. *
  4. * Copyright (c) 1993-2012, The Open Group. All rights reserved.
  5. *
  6. * These libraries and programs are free software; you can
  7. * redistribute them and/or modify them under the terms of the GNU
  8. * Lesser General Public License as published by the Free Software
  9. * Foundation; either version 2 of the License, or (at your option)
  10. * any later version.
  11. *
  12. * These libraries and programs are distributed in the hope that
  13. * they will be useful, but WITHOUT ANY WARRANTY; without even the
  14. * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  15. * PURPOSE. See the GNU Lesser General Public License for more
  16. * details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with these libraries and programs; if not, write
  20. * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
  21. * Floor, Boston, MA 02110-1301 USA
  22. */
  23. /* $XConsortium: DndText.c /main/5 1996/08/28 17:46:27 drk $ */
  24. /*********************************************************************
  25. *
  26. * File: DndText.c
  27. *
  28. * Description: Implementation of the Text Transfer routines
  29. * for the DND Convenience API.
  30. *
  31. *********************************************************************
  32. *
  33. *+SNOTICE
  34. *
  35. * RESTRICTED CONFIDENTIAL INFORMATION:
  36. *
  37. * The information in this document is subject to special
  38. * restrictions in a confidential disclosure agreement bertween
  39. * HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
  40. * document outside HP, IBM, Sun, USL, SCO, or Univel wihtout
  41. * Sun's specific written approval. This documment and all copies
  42. * and derivative works thereof must be returned or destroyed at
  43. * Sun's request.
  44. *
  45. * Copyright 1993 Sun Microsystems, Inc. All rights reserved.
  46. *
  47. * (c) Copyright 1993, 1994 Hewlett-Packard Company
  48. * (c) Copyright 1993, 1994 International Business Machines Corp.
  49. * (c) Copyright 1993, 1994 Sun Microsystems, Inc.
  50. * (c) Copyright 1993, 1994 Novell, Inc.
  51. *
  52. *+ENOTICE
  53. */
  54. #include <stdlib.h>
  55. #include <locale.h>
  56. #include <X11/Intrinsic.h>
  57. #include <Xm/AtomMgr.h>
  58. #include <Xm/DragC.h>
  59. #include <Xm/DropSMgr.h>
  60. #include <Xm/DropTrans.h>
  61. #include "Dnd.h"
  62. #include "DndP.h"
  63. #include "DtSvcLock.h"
  64. /*
  65. * Text Transfer Function Prototypes
  66. */
  67. static void dndTextGetTargets(Atom**, Cardinal*);
  68. static void dndTextGetAvailTargets(DtDragInfo*, Atom**, Cardinal*);
  69. static void dndTextGetExportTargets(DtDragInfo*, Atom**, Cardinal*);
  70. static void dndTextGetImportTargets(DtDropInfo*, Atom**, Cardinal*);
  71. static void dndTextConvertInit(DtDragInfo*);
  72. static Boolean dndTextConvert(Widget, DtDragInfo*, Atom*, Atom*,
  73. Atom*, XtPointer*, unsigned long*, int*,
  74. XSelectionRequestEvent*);
  75. static void dndTextConvertFinish(DtDragInfo*);
  76. static void dndTextTransferTargets(DtDropInfo*,
  77. Atom*, Cardinal, Atom**, Cardinal*);
  78. static void dndTextTransfer(Widget, DtDropInfo*, Atom*, Atom*,
  79. Atom*, XtPointer, unsigned long*, int*);
  80. static void dndTextTransferFinish(DtDropInfo*);
  81. /*
  82. * Text Transfer Selection Target
  83. */
  84. static Atom XA_COMPOUND_TEXT;
  85. static Boolean dndPreferString;
  86. /*
  87. * Text Transfer ProtocolInfo
  88. */
  89. static DtDndMethods dndTextTransferProtocol = {
  90. "DtDndTextTransfer", /* name */
  91. (DtDndProtocol)DtDND_TEXT_TRANSFER, /* protocol */
  92. DtDND_DRAG_SOURCE_TEXT, /* sourceType */
  93. dndTextGetAvailTargets, /* getAvailTargets */
  94. dndTextGetExportTargets, /* getExportTargets */
  95. dndTextGetImportTargets, /* getImportTargets */
  96. dndTextConvertInit, /* convertInit */
  97. dndTextConvert, /* convert */
  98. dndTextConvertFinish, /* convertFinish */
  99. dndTextTransferTargets, /* transferTargets */
  100. dndTextTransfer, /* transfer */
  101. dndTextTransferFinish, /* transferFinish */
  102. };
  103. /*
  104. * Text transfer protocol initialization
  105. */
  106. DtDndMethods *
  107. _DtDndTextTransferProtocolInitialize(
  108. Display * display)
  109. {
  110. _DtSvcProcessLock();
  111. if (XA_COMPOUND_TEXT == 0) {
  112. XA_COMPOUND_TEXT = DtGetAtom(display, "COMPOUND_TEXT");
  113. dndPreferString = (strcmp(setlocale(LC_CTYPE,NULL),"C") == 0);
  114. #ifdef DEBUG
  115. printf("locale = %s, dndPreferString = %d\n",
  116. setlocale(LC_CTYPE,NULL), dndPreferString);
  117. #endif
  118. }
  119. _DtSvcProcessUnlock();
  120. return &dndTextTransferProtocol;
  121. }
  122. /*
  123. * Returns generic export/import targets for text transfers
  124. */
  125. static void
  126. dndTextGetTargets(
  127. Atom ** targets,
  128. Cardinal * numTargets)
  129. {
  130. int ii = 0;
  131. *numTargets = 3;
  132. *targets = (Atom *)XtMalloc(*numTargets * sizeof(Atom));
  133. (*targets)[ii++] = XA_COMPOUND_TEXT;
  134. (*targets)[ii++] = XA_TEXT;
  135. (*targets)[ii++] = XA_STRING;
  136. }
  137. /*
  138. * Returns available targets for text transfers
  139. */
  140. static void
  141. dndTextGetAvailTargets(
  142. DtDragInfo * dtDragInfo,
  143. Atom ** availTargets,
  144. Cardinal * numAvailTargets)
  145. {
  146. dndTextGetTargets(availTargets, numAvailTargets);
  147. }
  148. /*
  149. * Returns export targets for text transfers
  150. */
  151. static void
  152. dndTextGetExportTargets(
  153. DtDragInfo * dtDragInfo,
  154. Atom ** exportTargets,
  155. Cardinal * numExportTargets)
  156. {
  157. dndTextGetTargets(exportTargets, numExportTargets);
  158. }
  159. /*
  160. * Returns import targets for text transfers
  161. */
  162. static void
  163. dndTextGetImportTargets(
  164. DtDropInfo * dtDropInfo,
  165. Atom ** importTargets,
  166. Cardinal * numImportTargets)
  167. {
  168. dndTextGetTargets(importTargets, numImportTargets);
  169. }
  170. /*
  171. * Initialize protocol specific part of drag data
  172. */
  173. static void
  174. dndTextConvertInit(
  175. DtDragInfo * dtDragInfo)
  176. {
  177. DtDndContext * dragData = dtDragInfo->dragData;
  178. dragData->data.strings = (XmString *)
  179. XtMalloc(dragData->numItems * sizeof(XmString));
  180. }
  181. /*
  182. * Convert the motif strings into selection data
  183. */
  184. static Boolean
  185. dndTextConvert(
  186. Widget dragContext,
  187. DtDragInfo * dtDragInfo,
  188. Atom * selection,
  189. Atom * target,
  190. Atom * returnType,
  191. XtPointer * returnValue,
  192. unsigned long * returnLength,
  193. int * returnFormat,
  194. XSelectionRequestEvent * selectionRequestEvent)
  195. {
  196. DtDndContext * dragData = dtDragInfo->dragData;
  197. Display * dpy = XtDisplayOfObject(dragContext);
  198. XmString * stringList;
  199. Cardinal numStrings;
  200. XTextProperty textProp;
  201. XmICCEncodingStyle encStyle;
  202. int status;
  203. /*
  204. * Select the text encoding style; reject unknown targets
  205. */
  206. if (*target == XA_COMPOUND_TEXT) {
  207. encStyle = XmSTYLE_COMPOUND_TEXT;
  208. } else if (*target == XA_STRING) {
  209. encStyle = XmSTYLE_STRING;
  210. } else if (*target == XA_TEXT) {
  211. encStyle = XmSTYLE_TEXT;
  212. } else {
  213. return False;
  214. }
  215. /*
  216. * Convert the XmString list into a string list
  217. */
  218. numStrings = dragData->numItems;
  219. stringList = dragData->data.strings;
  220. status = XmCvtXmStringTableToTextProperty(dpy, stringList, numStrings,
  221. encStyle, &textProp);
  222. if (status != Success)
  223. return False;
  224. /*
  225. * Return the text property
  226. */
  227. *returnType = textProp.encoding;
  228. *returnValue = (XtPointer)textProp.value;
  229. *returnLength = textProp.nitems;
  230. *returnFormat = textProp.format;
  231. return True;
  232. }
  233. /*
  234. * Clean up from the convert init proc
  235. */
  236. static void
  237. dndTextConvertFinish(
  238. DtDragInfo * dtDragInfo)
  239. {
  240. DtDndContext * dragData = dtDragInfo->dragData;
  241. if (dragData->data.strings) {
  242. XtFree((char *)dragData->data.strings);
  243. dragData->data.strings = NULL;
  244. }
  245. }
  246. /*
  247. * Returns the transfer targets selected from the export targets
  248. */
  249. static void
  250. dndTextTransferTargets(
  251. DtDropInfo * dtDropInfo,
  252. Atom * exportTargets,
  253. Cardinal numExportTargets,
  254. Atom ** transferTargets,
  255. Cardinal * numTransferTargets)
  256. {
  257. Boolean foundCT, foundText, foundString;
  258. Atom target;
  259. int ii;
  260. foundCT = foundText = foundString = False;
  261. for (ii = 0; ii < numExportTargets; ii++) {
  262. if (exportTargets[ii] == XA_COMPOUND_TEXT) {
  263. foundCT = True;
  264. } else if (exportTargets[ii] == XA_TEXT) {
  265. foundText = True;
  266. } else if (exportTargets[ii] == XA_STRING) {
  267. foundString = True;
  268. }
  269. }
  270. if (dndPreferString && foundString) {
  271. target = XA_STRING;
  272. } else if (foundCT) {
  273. target = XA_COMPOUND_TEXT;
  274. } else if (foundText) {
  275. target = XA_TEXT;
  276. } else if (foundString) {
  277. target = XA_STRING;
  278. } else {
  279. *numTransferTargets = 0;
  280. *transferTargets = NULL;
  281. return;
  282. }
  283. *numTransferTargets = 1;
  284. *transferTargets = (Atom *)XtMalloc(*numTransferTargets * sizeof(Atom));
  285. (*transferTargets)[0] = target;
  286. }
  287. /*
  288. * Transfer the selection data into motif strings
  289. */
  290. static void
  291. dndTextTransfer(
  292. Widget dropTransfer,
  293. DtDropInfo * dtDropInfo,
  294. Atom * selection,
  295. Atom * target,
  296. Atom * type,
  297. XtPointer value,
  298. unsigned long * length,
  299. int * format)
  300. {
  301. Display * display = XtDisplayOfObject(dropTransfer);
  302. DtDndContext * dropData = dtDropInfo->dropData;
  303. XmString * stringList;
  304. XTextProperty textProp;
  305. char ** text;
  306. int ii, status, textCount;
  307. /*
  308. * Ignore transfers we don't understand or if we've already transferred
  309. */
  310. if (value == NULL || dropData->data.strings ||
  311. (*target != XA_COMPOUND_TEXT &&
  312. *target != XA_TEXT &&
  313. *target != XA_STRING) ) {
  314. if (value != NULL)
  315. XtFree(value);
  316. return;
  317. }
  318. /*
  319. * Convert the text property to a text list
  320. */
  321. textProp.value = (unsigned char *)value;
  322. textProp.encoding = *type;
  323. textProp.format = *format;
  324. textProp.nitems = *length;
  325. status = XmbTextPropertyToTextList(display, &textProp,
  326. &text, &textCount);
  327. XtFree((char *)value);
  328. if (status != Success) {
  329. dtDropInfo->status = DtDND_FAILURE;
  330. return;
  331. }
  332. /*
  333. * Convert the text list into a XmString list
  334. */
  335. stringList = (XmString *)XtMalloc(textCount * sizeof(XmString));
  336. for (ii = 0; ii < textCount; ii++) {
  337. stringList[ii] = XmStringCreateLocalized(text[ii]);
  338. }
  339. XFreeStringList(text);
  340. dropData->numItems = textCount;
  341. dropData->data.strings = stringList;
  342. }
  343. /*
  344. * Clean up from the transfer proc
  345. */
  346. static void
  347. dndTextTransferFinish(
  348. DtDropInfo * dtDropInfo)
  349. {
  350. DtDndContext * dropData = dtDropInfo->dropData;
  351. int ii;
  352. for (ii = 0; ii < dropData->numItems; ii++) {
  353. XmStringFree(dropData->data.strings[ii]);
  354. }
  355. XtFree((char *)dropData->data.strings);
  356. }