PageRenderTime 61ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/libgxim/gximmisc.c

https://bitbucket.org/tagoh/libgxim
C | 3748 lines | 3086 code | 568 blank | 94 comment | 427 complexity | 9ea8c823d030f144d3f31c6845184b52 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
  2. /*
  3. * gximmisc.c
  4. * Copyright (C) 2008-2011 Akira TAGOH
  5. *
  6. * Authors:
  7. * Akira TAGOH <akira@tagoh.org>
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation; either
  12. * version 2 of the License, or (at your option) any later version.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the
  21. * Free Software Foundation, Inc., 51 Franklin Street, Fifth
  22. * Floor, Boston, MA 02110-1301 USA
  23. */
  24. #ifdef HAVE_CONFIG_H
  25. #include "config.h"
  26. #endif
  27. #ifdef HAVE_STRING_H
  28. #include <string.h>
  29. #endif
  30. #ifdef HAVE_STDINT_H
  31. #include <stdint.h>
  32. #endif
  33. #include <gdk/gdkprivate.h>
  34. #include <gdk/gdkkeysyms.h>
  35. #include <gdk/gdkx.h>
  36. #include "gximattr.h"
  37. #include "gximerror.h"
  38. #include "gximmessages.h"
  39. #include "gximmisc.h"
  40. #include "gximprotocol.h"
  41. #define N_REALLOC_NESTED_LIST 16
  42. static GXimMessages *master_message = NULL;
  43. /*
  44. * Private functions
  45. */
  46. static gint
  47. g_xim_gdkevent_translate_event_type(GdkEvent *event)
  48. {
  49. switch (event->type) {
  50. case GDK_NOTHING:
  51. case GDK_DELETE:
  52. goto unsupported;
  53. case GDK_DESTROY:
  54. return DestroyNotify;
  55. case GDK_EXPOSE:
  56. return Expose;
  57. case GDK_MOTION_NOTIFY:
  58. return MotionNotify;
  59. case GDK_BUTTON_PRESS:
  60. case GDK_2BUTTON_PRESS:
  61. case GDK_3BUTTON_PRESS:
  62. return ButtonPress;
  63. case GDK_BUTTON_RELEASE:
  64. return ButtonRelease;
  65. case GDK_KEY_PRESS:
  66. return KeyPress;
  67. case GDK_KEY_RELEASE:
  68. return KeyRelease;
  69. case GDK_ENTER_NOTIFY:
  70. return EnterNotify;
  71. case GDK_LEAVE_NOTIFY:
  72. return LeaveNotify;
  73. case GDK_FOCUS_CHANGE:
  74. if (event->focus_change.in)
  75. return FocusIn;
  76. else
  77. return FocusOut;
  78. case GDK_CONFIGURE:
  79. return ConfigureNotify;
  80. case GDK_MAP:
  81. return MapNotify;
  82. case GDK_UNMAP:
  83. return UnmapNotify;
  84. case GDK_PROPERTY_NOTIFY:
  85. return PropertyNotify;
  86. case GDK_SELECTION_CLEAR:
  87. return SelectionClear;
  88. case GDK_SELECTION_REQUEST:
  89. return SelectionRequest;
  90. case GDK_SELECTION_NOTIFY:
  91. return SelectionNotify;
  92. case GDK_PROXIMITY_IN:
  93. case GDK_PROXIMITY_OUT:
  94. case GDK_DRAG_ENTER:
  95. case GDK_DRAG_LEAVE:
  96. case GDK_DRAG_MOTION:
  97. case GDK_DRAG_STATUS:
  98. case GDK_DROP_START:
  99. case GDK_DROP_FINISHED:
  100. goto unsupported;
  101. case GDK_CLIENT_EVENT:
  102. return ClientMessage;
  103. case GDK_VISIBILITY_NOTIFY:
  104. return VisibilityNotify;
  105. case GDK_NO_EXPOSE:
  106. return NoExpose;
  107. case GDK_SCROLL:
  108. return ButtonPress;
  109. case GDK_WINDOW_STATE:
  110. case GDK_SETTING:
  111. case GDK_OWNER_CHANGE:
  112. case GDK_GRAB_BROKEN:
  113. default:
  114. unsupported:
  115. break;
  116. }
  117. return 0;
  118. }
  119. static GdkEventType
  120. g_xim_xevent_translate_event_type(gint type)
  121. {
  122. switch (type & 0x7f) {
  123. case KeyPress:
  124. return GDK_KEY_PRESS;
  125. case KeyRelease:
  126. return GDK_KEY_RELEASE;
  127. case ButtonPress:
  128. return GDK_BUTTON_PRESS;
  129. case ButtonRelease:
  130. return GDK_BUTTON_RELEASE;
  131. case MotionNotify:
  132. return GDK_MOTION_NOTIFY;
  133. case EnterNotify:
  134. return GDK_ENTER_NOTIFY;
  135. case LeaveNotify:
  136. return GDK_LEAVE_NOTIFY;
  137. case FocusIn:
  138. case FocusOut:
  139. return GDK_FOCUS_CHANGE;
  140. case KeymapNotify:
  141. goto unsupported;
  142. case Expose:
  143. case GraphicsExpose:
  144. return GDK_EXPOSE;
  145. case NoExpose:
  146. return GDK_NO_EXPOSE;
  147. case VisibilityNotify:
  148. return GDK_VISIBILITY_NOTIFY;
  149. case CreateNotify:
  150. goto unsupported;
  151. case DestroyNotify:
  152. return GDK_DESTROY;
  153. case UnmapNotify:
  154. return GDK_UNMAP;
  155. case MapNotify:
  156. return GDK_MAP;
  157. case MapRequest:
  158. case ReparentNotify:
  159. goto unsupported;
  160. case ConfigureNotify:
  161. return GDK_CONFIGURE;
  162. case ConfigureRequest:
  163. case GravityNotify:
  164. case ResizeRequest:
  165. case CirculateNotify:
  166. case CirculateRequest:
  167. goto unsupported;
  168. case PropertyNotify:
  169. return GDK_PROPERTY_NOTIFY;
  170. case SelectionClear:
  171. return GDK_SELECTION_CLEAR;
  172. case SelectionRequest:
  173. return GDK_SELECTION_REQUEST;
  174. case SelectionNotify:
  175. return GDK_SELECTION_NOTIFY;
  176. case ColormapNotify:
  177. goto unsupported;
  178. case ClientMessage:
  179. return GDK_CLIENT_EVENT;
  180. case MappingNotify:
  181. goto unsupported;
  182. default:
  183. unsupported:
  184. break;
  185. }
  186. return GDK_NOTHING;
  187. }
  188. static const gchar *
  189. g_xim_gdkevent_type_name(gint type)
  190. {
  191. static const gchar *event_names =
  192. "\0"
  193. "KeyPress\0"
  194. "KeyRelease\0"
  195. "ButtonPress\0"
  196. "ButtonRelease\0"
  197. "MotionNotify\0"
  198. "EnterNotify\0"
  199. "LeaveNotify\0"
  200. "FocusIn\0"
  201. "FocusOut\0"
  202. "KeymapNotify\0"
  203. "Expose\0"
  204. "GraphicsExpose\0"
  205. "NoExpose\0"
  206. "VisibilityNotify\0"
  207. "CreateNotify\0"
  208. "DestroyNotify\0"
  209. "UnmapNotify\0"
  210. "MapNotify\0"
  211. "ReparentNotify\0"
  212. "ConfigureNotify\0"
  213. "ConfigureRequest\0"
  214. "GravityNotify\0"
  215. "ResizeRequest\0"
  216. "CirculateNotify\0"
  217. "CirculateRequest\0"
  218. "PropertyNotify\0"
  219. "SelectionClear\0"
  220. "SelectionRequest\0"
  221. "SelectionNotify\0"
  222. "ColormapNotify\0"
  223. "ClientMessage\0"
  224. "MappingNotify\0";
  225. static guint type2pos[LASTEvent];
  226. static gboolean initialized = FALSE;
  227. if (!initialized) {
  228. memset(type2pos, 0, sizeof (guint) * (LASTEvent - 1));
  229. type2pos[KeyPress] = 1;
  230. type2pos[KeyRelease] = 10;
  231. type2pos[ButtonPress] = 21;
  232. type2pos[ButtonRelease] = 33;
  233. type2pos[MotionNotify] = 47;
  234. type2pos[EnterNotify] = 60;
  235. type2pos[LeaveNotify] = 72;
  236. type2pos[FocusIn] = 84;
  237. type2pos[FocusOut] = 92;
  238. type2pos[KeymapNotify] = 101;
  239. type2pos[Expose] = 114;
  240. type2pos[GraphicsExpose] = 121;
  241. type2pos[NoExpose] = 136;
  242. type2pos[VisibilityNotify] = 145;
  243. type2pos[CreateNotify] = 162;
  244. type2pos[DestroyNotify] = 175;
  245. type2pos[UnmapNotify] = 189;
  246. type2pos[MapNotify] = 201;
  247. type2pos[MapRequest] = 211;
  248. type2pos[ReparentNotify] = 226;
  249. type2pos[ConfigureNotify] = 242;
  250. type2pos[ConfigureRequest] = 259;
  251. type2pos[GravityNotify] = 273;
  252. type2pos[ResizeRequest] = 287;
  253. type2pos[CirculateNotify] = 303;
  254. type2pos[CirculateRequest] = 320;
  255. type2pos[PropertyNotify] = 335;
  256. type2pos[SelectionClear] = 350;
  257. type2pos[SelectionRequest] = 367;
  258. type2pos[SelectionNotify] = 383;
  259. type2pos[ColormapNotify] = 398;
  260. type2pos[ClientMessage] = 412;
  261. type2pos[MappingNotify] = 426;
  262. initialized = TRUE;
  263. }
  264. return (&event_names[type2pos[type]])[0] == 0 ? "<UnknownEvent>" : &event_names[type2pos[type]];
  265. }
  266. static GXimNestedListNode *
  267. g_xim_nested_list_node_new(void)
  268. {
  269. GXimNestedListNode *retval;
  270. retval = g_new0(GXimNestedListNode, 1);
  271. G_XIM_CHECK_ALLOC (retval, NULL);
  272. retval->vtype = G_XIM_TYPE_INVALID;
  273. return retval;
  274. }
  275. static GXimNestedListNode *
  276. g_xim_nested_list_node_copy(GXimNestedListNode *node)
  277. {
  278. GXimNestedListNode *retval;
  279. GType gtype;
  280. g_return_val_if_fail (node != NULL, NULL);
  281. gtype = g_xim_value_type_to_gtype(node->vtype);
  282. g_return_val_if_fail (gtype != G_TYPE_INVALID, NULL);
  283. retval = g_xim_nested_list_node_new();
  284. retval->vtype = node->vtype;
  285. retval->name = g_strdup(node->name);
  286. retval->value = g_xim_copy_by_gtype(gtype, node->value);
  287. return retval;
  288. }
  289. static void
  290. g_xim_nested_list_node_free(GXimNestedListNode *node)
  291. {
  292. GType gtype;
  293. if (node == NULL)
  294. return;
  295. gtype = g_xim_value_type_to_gtype(node->vtype);
  296. if (gtype == G_TYPE_INVALID)
  297. g_warning("Invalid NestedList node for %s to be freed", node->name);
  298. g_free(node->name);
  299. g_xim_free_by_gtype(gtype, node->value);
  300. g_free(node);
  301. }
  302. /*
  303. * Public functions
  304. */
  305. void
  306. g_xim_init(void)
  307. {
  308. const gchar *env;
  309. gchar **tokens;
  310. gint i;
  311. if (master_message == NULL) {
  312. master_message = g_xim_messages_new();
  313. G_XIM_CHECK_ALLOC_WITH_NO_RET (master_message);
  314. g_object_set(G_OBJECT (master_message), "master", TRUE, NULL);
  315. }
  316. env = g_getenv("LIBGXIM_DEBUG");
  317. if (env) {
  318. tokens = g_strsplit(env, ",", 0);
  319. for (i = 0; tokens && tokens[i] != NULL; i++) {
  320. g_xim_messages_enable_filter(master_message, tokens[i]);
  321. }
  322. g_xim_messages_activate(master_message, TRUE);
  323. }
  324. }
  325. void
  326. g_xim_finalize(void)
  327. {
  328. g_object_unref(master_message);
  329. }
  330. GDataStreamByteOrder
  331. g_xim_get_byte_order(void)
  332. {
  333. gint i = 1;
  334. gchar *p = (gchar *)&i;
  335. if (*p == 1)
  336. return G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN;
  337. return G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN;
  338. }
  339. GXimValueType
  340. g_xim_gtype_to_value_type(GType gtype)
  341. {
  342. switch (gtype) {
  343. case G_TYPE_CHAR:
  344. case G_TYPE_UCHAR:
  345. return G_XIM_TYPE_BYTE;
  346. case G_TYPE_INT:
  347. case G_TYPE_UINT:
  348. return G_XIM_TYPE_WORD;
  349. case G_TYPE_LONG:
  350. case G_TYPE_ULONG:
  351. return G_XIM_TYPE_LONG;
  352. case G_TYPE_STRING:
  353. return G_XIM_TYPE_CHAR;
  354. case G_TYPE_BOXED:
  355. default:
  356. if (g_type_is_a(gtype, G_TYPE_XIM_STYLES)) {
  357. return G_XIM_TYPE_XIMSTYLES;
  358. } else if (g_type_is_a(gtype, GDK_TYPE_WINDOW)) {
  359. return G_XIM_TYPE_WINDOW;
  360. } else if (g_type_is_a(gtype, G_TYPE_XIM_NESTEDLIST)) {
  361. return G_XIM_TYPE_NESTEDLIST;
  362. } else if (g_type_is_a(gtype, G_TYPE_XIM_RECTANGLE)) {
  363. return G_XIM_TYPE_XRECTANGLE;
  364. } else if (g_type_is_a(gtype, G_TYPE_XIM_POINT)) {
  365. return G_XIM_TYPE_XPOINT;
  366. } else if (g_type_is_a(gtype, G_TYPE_XIM_FONTSET)) {
  367. return G_XIM_TYPE_XFONTSET;
  368. } else if (g_type_is_a(gtype, G_TYPE_XIM_SEP_NESTEDLIST)) {
  369. return G_XIM_TYPE_SEPARATOR;
  370. }
  371. g_warning("Unsupported object type: %s",
  372. g_type_name(gtype));
  373. break;
  374. }
  375. return G_XIM_TYPE_INVALID;
  376. }
  377. GType
  378. g_xim_value_type_to_gtype(GXimValueType vtype)
  379. {
  380. switch (vtype) {
  381. case G_XIM_TYPE_SEPARATOR:
  382. return G_TYPE_XIM_SEP_NESTEDLIST;
  383. case G_XIM_TYPE_BYTE:
  384. return G_TYPE_UCHAR;
  385. case G_XIM_TYPE_WORD:
  386. return G_TYPE_UINT;
  387. case G_XIM_TYPE_LONG:
  388. return G_TYPE_ULONG;
  389. case G_XIM_TYPE_CHAR:
  390. return G_TYPE_STRING;
  391. case G_XIM_TYPE_WINDOW:
  392. return GDK_TYPE_WINDOW;
  393. case G_XIM_TYPE_XIMSTYLES:
  394. return G_TYPE_XIM_STYLES;
  395. case G_XIM_TYPE_XRECTANGLE:
  396. return G_TYPE_XIM_RECTANGLE;
  397. case G_XIM_TYPE_XPOINT:
  398. return G_TYPE_XIM_POINT;
  399. case G_XIM_TYPE_XFONTSET:
  400. return G_TYPE_XIM_FONTSET;
  401. case G_XIM_TYPE_HOTKEYTRIGGERS:
  402. case G_XIM_TYPE_HOTKEYSTATE:
  403. case G_XIM_TYPE_STRINGCONVERSION:
  404. case G_XIM_TYPE_PREEDITSTATE:
  405. case G_XIM_TYPE_RESETSTATE:
  406. break;
  407. case G_XIM_TYPE_NESTEDLIST:
  408. return G_TYPE_XIM_NESTEDLIST;
  409. case G_XIM_TYPE_INVALID:
  410. break;
  411. case G_XIM_TYPE_PADDING:
  412. case G_XIM_TYPE_AUTO_PADDING:
  413. case G_XIM_TYPE_MARKER_N_BYTES_1:
  414. case G_XIM_TYPE_MARKER_N_BYTES_2:
  415. case G_XIM_TYPE_MARKER_N_BYTES_4:
  416. case G_XIM_TYPE_MARKER_N_ITEMS_2:
  417. break;
  418. case G_XIM_TYPE_STR:
  419. return G_TYPE_XIM_STR;
  420. case G_XIM_TYPE_GSTRING:
  421. return G_TYPE_GSTRING;
  422. case G_XIM_TYPE_PREEDIT_CARET:
  423. return G_TYPE_XIM_PREEDIT_CARET;
  424. case G_XIM_TYPE_PREEDIT_DRAW:
  425. return G_TYPE_XIM_PREEDIT_DRAW;
  426. case G_XIM_TYPE_GDKEVENT:
  427. return GDK_TYPE_EVENT;
  428. case G_XIM_TYPE_XIMTEXT:
  429. return G_TYPE_XIM_TEXT;
  430. case G_XIM_TYPE_HOTKEY_TRIGGER:
  431. return G_TYPE_XIM_HOTKEY_TRIGGER;
  432. case G_XIM_TYPE_PIXMAP:
  433. return GDK_TYPE_PIXMAP;
  434. case G_XIM_TYPE_STATUS_DRAW:
  435. return G_TYPE_XIM_STATUS_DRAW;
  436. case G_XIM_TYPE_LIST_OF_IMATTR:
  437. case G_XIM_TYPE_LIST_OF_ICATTR:
  438. case G_XIM_TYPE_LIST_OF_IMATTRIBUTE:
  439. case G_XIM_TYPE_LIST_OF_ICATTRIBUTE:
  440. case G_XIM_TYPE_LIST_OF_EXT:
  441. case G_XIM_TYPE_LIST_OF_STRING:
  442. case G_XIM_TYPE_LIST_OF_STR:
  443. case G_XIM_TYPE_LIST_OF_ENCODINGINFO:
  444. case G_XIM_TYPE_LIST_OF_BYTE:
  445. case G_XIM_TYPE_LIST_OF_CARD16:
  446. case G_XIM_TYPE_LIST_OF_HOTKEY_TRIGGER:
  447. default:
  448. break;
  449. }
  450. return G_TYPE_INVALID;
  451. }
  452. const gchar *
  453. g_xim_value_type_name(GXimValueType vtype)
  454. {
  455. static const gchar vtype_name[] =
  456. "\0"
  457. "SeparatorofNestedList\0"
  458. "CARD8\0"
  459. "CARD16\0"
  460. "CARD32\0"
  461. "STRING8\0"
  462. "Window\0"
  463. "XIMStyles\0"
  464. "XRectangle\0"
  465. "XPoint\0"
  466. "XFontSet\0"
  467. "XIMHotKeyTriggers\0"
  468. "XIMHotKeyState\0"
  469. "XIMStringConversion\0"
  470. "XIMPreeditState\0"
  471. "XIMResetState\0"
  472. "NestedList\0"
  473. "<Invalid>\0"
  474. "Padding\0"
  475. "AutoPadding\0"
  476. "n-bytes-marker[CARD8]\0"
  477. "n-bytes-marker[CARD16]\0"
  478. "n-bytes-marker[CARD32]\0"
  479. "n-items-marker[CARD16]\0"
  480. "STR\0"
  481. "GString\0"
  482. "GXimPreeditCaret\0"
  483. "GXimPreeditDraw\0"
  484. "GdkEvent\0"
  485. "GXimText\0"
  486. "GXimHotkeyTrigger\0"
  487. "Pixmap\0"
  488. "GXimStatusDraw\0"
  489. "LISTofXIMATTR\0"
  490. "LISTofXICATTR\0"
  491. "LISTofXIMATTRIBUTE\0"
  492. "LISTofXICATTRIBUTE\0"
  493. "LISTofEXT\0"
  494. "LISTofSTRING\0"
  495. "LISTofSTR\0"
  496. "LISTofENCODINGINFO\0"
  497. "LISTofBYTE\0"
  498. "LISTofCARD16\0"
  499. "LISTofXIMTRIGGERKEY\0";
  500. static guint type2pos[LAST_VALUE_TYPE];
  501. static gboolean initialized = FALSE;
  502. static gchar tmp[256];
  503. if (!initialized) {
  504. memset(type2pos, 0, sizeof (guint) * (LAST_VALUE_TYPE - 1));
  505. type2pos[G_XIM_TYPE_SEPARATOR] = 1;
  506. type2pos[G_XIM_TYPE_BYTE] = 23;
  507. type2pos[G_XIM_TYPE_WORD] = 29;
  508. type2pos[G_XIM_TYPE_LONG] = 36;
  509. type2pos[G_XIM_TYPE_CHAR] = 43;
  510. type2pos[G_XIM_TYPE_WINDOW] = 51;
  511. type2pos[G_XIM_TYPE_XIMSTYLES] = 58;
  512. type2pos[G_XIM_TYPE_XRECTANGLE] = 68;
  513. type2pos[G_XIM_TYPE_XPOINT] = 79;
  514. type2pos[G_XIM_TYPE_XFONTSET] = 86;
  515. type2pos[G_XIM_TYPE_HOTKEYTRIGGERS] = 95;
  516. type2pos[G_XIM_TYPE_HOTKEYSTATE] = 113;
  517. type2pos[G_XIM_TYPE_STRINGCONVERSION] = 128;
  518. type2pos[G_XIM_TYPE_PREEDITSTATE] = 148;
  519. type2pos[G_XIM_TYPE_RESETSTATE] = 164;
  520. type2pos[G_XIM_TYPE_NESTEDLIST] = 178;
  521. type2pos[G_XIM_TYPE_INVALID] = 189;
  522. type2pos[G_XIM_TYPE_PADDING] = 199;
  523. type2pos[G_XIM_TYPE_AUTO_PADDING] = 207;
  524. type2pos[G_XIM_TYPE_MARKER_N_BYTES_1] = 219;
  525. type2pos[G_XIM_TYPE_MARKER_N_BYTES_2] = 241;
  526. type2pos[G_XIM_TYPE_MARKER_N_BYTES_4] = 264;
  527. type2pos[G_XIM_TYPE_MARKER_N_ITEMS_2] = 287;
  528. type2pos[G_XIM_TYPE_STR] = 310;
  529. type2pos[G_XIM_TYPE_GSTRING] = 314;
  530. type2pos[G_XIM_TYPE_PREEDIT_CARET] = 322;
  531. type2pos[G_XIM_TYPE_PREEDIT_DRAW] = 339;
  532. type2pos[G_XIM_TYPE_GDKEVENT] = 355;
  533. type2pos[G_XIM_TYPE_XIMTEXT] = 364;
  534. type2pos[G_XIM_TYPE_HOTKEY_TRIGGER] = 373;
  535. type2pos[G_XIM_TYPE_PIXMAP] = 391;
  536. type2pos[G_XIM_TYPE_STATUS_DRAW] = 398;
  537. type2pos[G_XIM_TYPE_LIST_OF_IMATTR] = 413;
  538. type2pos[G_XIM_TYPE_LIST_OF_ICATTR] = 427;
  539. type2pos[G_XIM_TYPE_LIST_OF_IMATTRIBUTE] = 441;
  540. type2pos[G_XIM_TYPE_LIST_OF_ICATTRIBUTE] = 460;
  541. type2pos[G_XIM_TYPE_LIST_OF_EXT] = 479;
  542. type2pos[G_XIM_TYPE_LIST_OF_STRING] = 489;
  543. type2pos[G_XIM_TYPE_LIST_OF_STR] = 502;
  544. type2pos[G_XIM_TYPE_LIST_OF_ENCODINGINFO] = 512;
  545. type2pos[G_XIM_TYPE_LIST_OF_BYTE] = 531;
  546. type2pos[G_XIM_TYPE_LIST_OF_CARD16] = 542;
  547. type2pos[G_XIM_TYPE_LIST_OF_HOTKEY_TRIGGER] = 555;
  548. }
  549. if (vtype >= LAST_VALUE_TYPE ||
  550. type2pos[vtype] == 0) {
  551. snprintf(tmp, 255, "0x%x", vtype);
  552. return tmp;
  553. }
  554. return &vtype_name[type2pos[vtype]];
  555. }
  556. const gchar *
  557. g_xim_protocol_name(guint16 major_opcode)
  558. {
  559. static const gchar op2str[] = {
  560. "\0"
  561. "XIM_CONNECT\0"
  562. "XIM_CONNECT_REPLY\0"
  563. "XIM_DISCONNECT\0"
  564. "XIM_DISCONNECT_REPLY\0"
  565. "\0"
  566. "\0"
  567. "\0"
  568. "\0"
  569. "\0"
  570. "XIM_AUTH_REQUIRED\0"
  571. "XIM_AUTH_REPLY\0"
  572. "XIM_AUTH_NEXT\0"
  573. "XIM_AUTH_SETUP\0"
  574. "XIM_AUTH_NG\0"
  575. "\0"
  576. "\0"
  577. "\0"
  578. "\0"
  579. "\0"
  580. "XIM_ERROR\0"
  581. "\0"
  582. "\0"
  583. "\0"
  584. "\0"
  585. "\0"
  586. "\0"
  587. "\0"
  588. "\0"
  589. "\0"
  590. "XIM_OPEN\0"
  591. "XIM_OPEN_REPLY\0"
  592. "XIM_CLOSE\0"
  593. "XIM_CLOSE_REPLY\0"
  594. "XIM_REGISTER_TRIGGERKEYS\0"
  595. "XIM_TRIGGER_NOTIFY\0"
  596. "XIM_TRIGGER_NOTIFY_REPLY\0"
  597. "XIM_SET_EVENT_MASK\0"
  598. "XIM_ENCODING_NEGOTIATION\0"
  599. "XIM_ENCODING_NEGOTIATION_REPLY\0"
  600. "XIM_QUERY_EXTENSION\0"
  601. "XIM_QUERY_EXTENSION_REPLY\0"
  602. "XIM_SET_IM_VALUES\0"
  603. "XIM_SET_IM_VALUES_REPLY\0"
  604. "XIM_GET_IM_VALUES\0"
  605. "XIM_GET_IM_VALUES_REPLY\0"
  606. "\0"
  607. "\0"
  608. "\0"
  609. "\0"
  610. "XIM_CREATE_IC\0"
  611. "XIM_CREATE_IC_REPLY\0"
  612. "XIM_DESTROY_IC\0"
  613. "XIM_DESTROY_IC_REPLY\0"
  614. "XIM_SET_IC_VALUES\0"
  615. "XIM_SET_IC_VALUES_REPLY\0"
  616. "XIM_GET_IC_VALUES\0"
  617. "XIM_GET_IC_VALUES_REPLY\0"
  618. "XIM_SET_IC_FOCUS\0"
  619. "XIM_UNSET_IC_FOCUS\0"
  620. "XIM_FORWARD_EVENT\0"
  621. "XIM_SYNC\0"
  622. "XIM_SYNC_REPLY\0"
  623. "XIM_COMMIT\0"
  624. "XIM_RESET_IC\0"
  625. "XIM_RESET_IC_REPLY\0"
  626. "\0"
  627. "\0"
  628. "\0"
  629. "\0"
  630. "XIM_GEOMETRY\0"
  631. "XIM_STR_CONVERSION\0"
  632. "XIM_STR_CONVERSION_REPLY\0"
  633. "XIM_PREEDIT_START\0"
  634. "XIM_PREEDIT_START_REPLY\0"
  635. "XIM_PREEDIT_DRAW\0"
  636. "XIM_PREEDIT_CARET\0"
  637. "XIM_PREEDIT_CARET_REPLY\0"
  638. "XIM_PREEDIT_DONE\0"
  639. "XIM_STATUS_START\0"
  640. "XIM_STATUS_DRAW\0"
  641. "XIM_STATUS_DONE\0"
  642. "XIM_PREEDITSTATE\0"
  643. };
  644. static gsize opindexes[] = {
  645. 0, 1, 13, 31, 46, 67, 68, 69, 70, 71,
  646. 72, 90, 105, 119, 134, 146, 147, 148, 149, 150,
  647. 151, 161, 162, 163, 164, 165, 166, 167, 168, 169,
  648. 170, 179, 194, 204, 220, 245, 264, 289, 308, 333,
  649. 364, 384, 410, 428, 452, 470, 494, 495, 496, 497,
  650. 498, 512, 532, 547, 568, 586, 610, 628, 652, 669,
  651. 688, 706, 715, 730, 741, 754, 773, 774, 775, 776,
  652. 777, 790, 809, 834, 852, 876, 893, 911, 935, 952,
  653. 969, 985, 1001, 1018,
  654. };
  655. if (major_opcode >= LAST_XIM_EVENTS)
  656. return NULL;
  657. return &op2str[opindexes[major_opcode]];
  658. }
  659. GdkWindow *
  660. g_xim_get_window(GdkDisplay *dpy,
  661. GdkNativeWindow window)
  662. {
  663. GdkWindow *retval;
  664. guint32 error_code;
  665. g_xim_error_push();
  666. retval = gdk_window_lookup_for_display(dpy, window);
  667. if (retval == NULL ||
  668. !GDK_IS_WINDOW (retval) ||
  669. GDK_WINDOW_DESTROYED (retval)) {
  670. if (retval)
  671. gdk_window_destroy(retval);
  672. retval = gdk_window_foreign_new_for_display(dpy, window);
  673. }
  674. error_code = g_xim_error_pop();
  675. if (G_XIM_ERROR_DECODE_X_ERROR_CODE (error_code) != 0) {
  676. g_printerr("Unable to convert the native window to GdkWindow: %p",
  677. G_XIM_NATIVE_WINDOW_TO_POINTER (window));
  678. }
  679. return retval != NULL ? g_object_ref(retval) : NULL;
  680. }
  681. GdkPixmap *
  682. g_xim_get_pixmap(GdkDisplay *dpy,
  683. GdkNativeWindow window)
  684. {
  685. GdkPixmap *retval;
  686. retval = gdk_pixmap_lookup_for_display(dpy, window);
  687. if (retval == NULL ||
  688. !GDK_IS_PIXMAP (retval)) {
  689. if (retval)
  690. g_object_unref(retval);
  691. retval = gdk_pixmap_foreign_new_for_display(dpy, window);
  692. }
  693. return retval;
  694. }
  695. GdkWindow *
  696. g_xim_get_selection_owner(GdkDisplay *display,
  697. GdkAtom selection)
  698. {
  699. Window xwindow;
  700. GdkWindow *retval;
  701. g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
  702. g_return_val_if_fail (selection != GDK_NONE, NULL);
  703. if (display->closed)
  704. return NULL;
  705. xwindow = XGetSelectionOwner(GDK_DISPLAY_XDISPLAY (display),
  706. gdk_x11_atom_to_xatom_for_display(display,
  707. selection));
  708. if (xwindow == None)
  709. return NULL;
  710. retval = g_xim_get_window(display, (GdkNativeWindow)xwindow);
  711. /* just decrease a counter to not mind unref outside this function */
  712. g_object_unref(retval);
  713. return retval;
  714. }
  715. GdkWindow *
  716. g_xim_lookup_xim_server(GdkDisplay *dpy,
  717. GdkAtom atom_server,
  718. gboolean *is_valid)
  719. {
  720. GdkAtom atom_xim_servers, atom_type, *atom_prop = NULL;
  721. gint format, bytes, i;
  722. GdkWindow *retval = NULL;
  723. guint32 error_code;
  724. g_return_val_if_fail (atom_server != GDK_NONE, NULL);
  725. g_return_val_if_fail (is_valid != NULL, NULL);
  726. atom_xim_servers = gdk_atom_intern_static_string("XIM_SERVERS");
  727. g_xim_error_push();
  728. gdk_property_get(gdk_screen_get_root_window(gdk_display_get_default_screen(dpy)),
  729. atom_xim_servers, GDK_SELECTION_TYPE_ATOM,
  730. 0, 8192, FALSE,
  731. &atom_type, &format, &bytes,
  732. (guchar **)(uintptr_t)&atom_prop);
  733. error_code = g_xim_error_pop();
  734. if (error_code != 0) {
  735. *is_valid = FALSE;
  736. return NULL;
  737. }
  738. if (atom_type != GDK_SELECTION_TYPE_ATOM ||
  739. format != 32) {
  740. *is_valid = FALSE;
  741. return NULL;
  742. }
  743. for (i = 0; i < (bytes / sizeof (gulong)); i++) {
  744. if (atom_prop[i] == atom_server) {
  745. retval = g_xim_get_selection_owner(dpy, atom_server);
  746. break;
  747. }
  748. }
  749. g_free(atom_prop);
  750. *is_valid = TRUE;
  751. return retval;
  752. }
  753. GdkWindow *
  754. g_xim_lookup_xim_server_from_string(GdkDisplay *dpy,
  755. const gchar *server_name,
  756. gboolean *is_valid)
  757. {
  758. GdkWindow *retval;
  759. GdkAtom atom_server;
  760. g_return_val_if_fail (server_name != NULL, NULL);
  761. atom_server = g_xim_get_server_atom(server_name);
  762. retval = g_xim_lookup_xim_server(dpy, atom_server, is_valid);
  763. return retval;
  764. }
  765. GdkAtom
  766. g_xim_get_server_atom(const gchar *server_name)
  767. {
  768. gchar *s;
  769. GdkAtom retval;
  770. s = g_strdup_printf("@server=%s", server_name);
  771. retval = gdk_atom_intern(s, FALSE);
  772. g_free(s);
  773. return retval;
  774. }
  775. gpointer
  776. g_xim_copy_by_gtype(GType gtype,
  777. gpointer value)
  778. {
  779. gpointer retval;
  780. if (G_TYPE_IS_BOXED (gtype))
  781. retval = g_boxed_copy(gtype, value);
  782. else if (G_TYPE_IS_OBJECT (gtype))
  783. retval = g_object_ref(value);
  784. else if (gtype == G_TYPE_STRING)
  785. retval = g_strdup(value);
  786. else
  787. retval = value;
  788. return retval;
  789. }
  790. void
  791. g_xim_free_by_gtype(GType gtype,
  792. gpointer value)
  793. {
  794. if (G_TYPE_IS_BOXED (gtype))
  795. g_boxed_free(gtype, value);
  796. else if (G_TYPE_IS_OBJECT (gtype))
  797. g_object_unref(value);
  798. else if (gtype == G_TYPE_STRING)
  799. g_free(value);
  800. }
  801. #if 0
  802. /* GXimStrConv */
  803. GXimStrConvText *
  804. g_xim_str_conv_text_new(const gchar *string,
  805. guint16 length)
  806. {
  807. GXimStrConvText *retval;
  808. g_return_val_if_fail (string != NULL, NULL);
  809. retval = g_new0(GXimStrConvText, 1);
  810. G_XIM_CHECK_ALLOC (retval, NULL);
  811. retval->string = g_strndup(string, length);
  812. retval->length = length;
  813. return retval;
  814. }
  815. GXimStrConvText *
  816. g_xim_str_conv_text_new_full(const gchar *string,
  817. guint16 length,
  818. guint16 feedback)
  819. {
  820. GXimStrConvText *retval = g_xim_str_conv_text_new(string, length);
  821. if (retval)
  822. g_xim_str_conv_set_feedback(retval, feedback);
  823. return retval;
  824. }
  825. void
  826. g_xim_str_conv_text_free(GXimStrConvText *text)
  827. {
  828. g_return_if_fail (text != NULL);
  829. g_free(text->string);
  830. g_free(text);
  831. }
  832. void
  833. g_xim_str_conv_set_feedback(GXimStrConvText *text,
  834. guint16 feedback)
  835. {
  836. g_return_if_fail (text != NULL);
  837. text->feedback = feedback;
  838. }
  839. guint16
  840. g_xim_str_conv_get_feedback(GXimStrConvText *text)
  841. {
  842. g_return_val_if_fail (text != NULL, 0);
  843. return text->feedback;
  844. }
  845. #endif
  846. /* XIMStyles */
  847. GType
  848. g_xim_styles_get_type(void)
  849. {
  850. static volatile gsize type_id_volatile = 0;
  851. if (g_once_init_enter(&type_id_volatile)) {
  852. GType type_id;
  853. type_id = g_boxed_type_register_static(g_intern_static_string("GXimStyles"),
  854. g_xim_styles_copy,
  855. g_xim_styles_free);
  856. g_once_init_leave(&type_id_volatile, type_id);
  857. }
  858. return type_id_volatile;
  859. }
  860. GQuark
  861. g_xim_styles_get_error_quark(void)
  862. {
  863. static GQuark quark = 0;
  864. if (!quark)
  865. quark = g_quark_from_static_string("g-xim-styles-error");
  866. return quark;
  867. }
  868. GXimStyles *
  869. g_xim_styles_new(void)
  870. {
  871. GXimStyles *retval = g_new0(GXimStyles, 1);
  872. G_XIM_CHECK_ALLOC (retval, NULL);
  873. retval->count_styles = 0;
  874. retval->supported_styles = NULL;
  875. return retval;
  876. }
  877. gboolean
  878. g_xim_styles_append(GXimStyles *styles,
  879. GXimStyle style,
  880. GError **error)
  881. {
  882. g_return_val_if_fail (styles != NULL, FALSE);
  883. return g_xim_styles_insert(styles, styles->count_styles, style, error);
  884. }
  885. gboolean
  886. g_xim_styles_insert(GXimStyles *styles,
  887. guint index_,
  888. GXimStyle style,
  889. GError **error)
  890. {
  891. gboolean retval = TRUE;
  892. g_return_val_if_fail (styles != NULL, FALSE);
  893. g_return_val_if_fail (error != NULL, FALSE);
  894. if (styles->count_styles <= index_) {
  895. gpointer data;
  896. data = g_realloc(styles->supported_styles,
  897. sizeof (GXimStyle) * (index_ + 1));
  898. G_XIM_GERROR_CHECK_ALLOC (data,
  899. error, G_XIM_STYLES_ERROR,
  900. FALSE);
  901. styles->supported_styles = data;
  902. styles->count_styles = index_ + 1;
  903. }
  904. styles->supported_styles[index_] = style;
  905. return retval;
  906. }
  907. gpointer
  908. g_xim_styles_copy(gpointer boxed)
  909. {
  910. GXimStyles *retval, *orig = boxed;
  911. if (boxed == NULL)
  912. return NULL;
  913. retval = g_new(GXimStyles, 1);
  914. G_XIM_CHECK_ALLOC (retval, NULL);
  915. retval->count_styles = orig->count_styles;
  916. retval->supported_styles = g_new(GXimStyle, sizeof (GXimStyle) * retval->count_styles);
  917. G_XIM_CHECK_ALLOC (retval->supported_styles, NULL);
  918. memcpy(retval->supported_styles,
  919. orig->supported_styles,
  920. sizeof (GXimStyle) * retval->count_styles);
  921. return retval;
  922. }
  923. void
  924. g_xim_styles_free(gpointer boxed)
  925. {
  926. GXimStyles *s = boxed;
  927. if (boxed == NULL)
  928. return;
  929. g_free(s->supported_styles);
  930. g_free(s);
  931. }
  932. gsize
  933. g_xim_styles_put_to_stream(GXimStyles *styles,
  934. GXimProtocol *proto,
  935. GCancellable *cancellable,
  936. GError **error)
  937. {
  938. gsize retval = 0;
  939. guint16 i;
  940. g_return_val_if_fail (G_IS_XIM_PROTOCOL (proto), 0);
  941. g_return_val_if_fail (styles != NULL, 0);
  942. g_return_val_if_fail (error != NULL, 0);
  943. retval = g_xim_protocol_send_format(proto, cancellable, error, 2,
  944. G_XIM_TYPE_WORD, styles->count_styles,
  945. G_XIM_TYPE_PADDING, 2);
  946. if (*error)
  947. return 0;
  948. /* XIMStyle */
  949. for (i = 0; i < styles->count_styles; i++) {
  950. retval += g_xim_protocol_send_format(proto, cancellable, error, 1,
  951. G_XIM_TYPE_LONG, styles->supported_styles[i]);
  952. if (*error)
  953. return 0;
  954. }
  955. return retval;
  956. }
  957. gpointer
  958. g_xim_styles_get_from_stream(GXimProtocol *proto,
  959. GDataInputStream *stream,
  960. GCancellable *cancellable,
  961. GError **error)
  962. {
  963. GXimStyles *retval;
  964. guint16 i;
  965. GXimStyle style;
  966. g_return_val_if_fail (G_IS_XIM_PROTOCOL (proto), NULL);
  967. g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), NULL);
  968. g_return_val_if_fail (error != NULL, NULL);
  969. retval = g_xim_styles_new();
  970. G_XIM_CHECK_ALLOC (retval, NULL);
  971. if (!g_xim_protocol_read_format(proto, stream, cancellable, error,
  972. 2,
  973. G_XIM_TYPE_WORD, &retval->count_styles,
  974. G_XIM_TYPE_PADDING, 2)) {
  975. g_xim_styles_free(retval);
  976. return NULL;
  977. }
  978. retval->supported_styles = g_new0(GXimStyle, retval->count_styles);
  979. G_XIM_GERROR_CHECK_ALLOC (retval->supported_styles, error,
  980. G_XIM_PROTOCOL_ERROR, NULL);
  981. for (i = 0; i < retval->count_styles; i++) {
  982. if (!g_xim_protocol_read_format(proto, stream, cancellable, error,
  983. 1,
  984. G_XIM_TYPE_LONG, &style)) {
  985. /* keep the values as much as possible */
  986. retval->count_styles = i;
  987. G_XIM_GERROR_RESET_NOTICE_FLAG (*error);
  988. G_XIM_GERROR_SET_NOTICE_FLAG (*error,
  989. G_XIM_NOTICE_WARNING);
  990. break;
  991. }
  992. if (!g_xim_styles_insert(retval, i, style, error)) {
  993. retval->count_styles = i;
  994. G_XIM_GERROR_RESET_NOTICE_FLAG (*error);
  995. G_XIM_GERROR_SET_NOTICE_FLAG (*error,
  996. G_XIM_NOTICE_WARNING);
  997. break;
  998. }
  999. }
  1000. return retval;
  1001. }
  1002. /* XRectangle */
  1003. GType
  1004. g_xim_rectangle_get_type(void)
  1005. {
  1006. static volatile gsize type_id_volatile = 0;
  1007. if (g_once_init_enter(&type_id_volatile)) {
  1008. GType type_id;
  1009. type_id = g_boxed_type_register_static(g_intern_static_string("GXimRectangle"),
  1010. g_xim_rectangle_copy,
  1011. g_xim_rectangle_free);
  1012. g_once_init_leave(&type_id_volatile, type_id);
  1013. }
  1014. return type_id_volatile;
  1015. }
  1016. gpointer
  1017. g_xim_rectangle_new(void)
  1018. {
  1019. return g_new0(GXimRectangle, 1);
  1020. }
  1021. gpointer
  1022. g_xim_rectangle_copy(gpointer boxed)
  1023. {
  1024. GXimRectangle *retval, *val = boxed;
  1025. if (boxed == NULL)
  1026. return NULL;
  1027. retval = g_xim_rectangle_new();
  1028. G_XIM_CHECK_ALLOC (retval, NULL);
  1029. retval->x = val->x;
  1030. retval->y = val->y;
  1031. retval->width = val->width;
  1032. retval->height = val->height;
  1033. return retval;
  1034. }
  1035. void
  1036. g_xim_rectangle_free(gpointer boxed)
  1037. {
  1038. g_free(boxed);
  1039. }
  1040. gsize
  1041. g_xim_rectangle_put_to_stream(GXimRectangle *rectangle,
  1042. GXimProtocol *proto,
  1043. GCancellable *cancellable,
  1044. GError **error)
  1045. {
  1046. g_return_val_if_fail (G_IS_XIM_PROTOCOL (proto), 0);
  1047. g_return_val_if_fail (rectangle != NULL, 0);
  1048. g_return_val_if_fail (error != NULL, 0);
  1049. return g_xim_protocol_send_format(proto, cancellable, error, 4,
  1050. G_XIM_TYPE_WORD, rectangle->x,
  1051. G_XIM_TYPE_WORD, rectangle->y,
  1052. G_XIM_TYPE_WORD, rectangle->width,
  1053. G_XIM_TYPE_WORD, rectangle->height);
  1054. }
  1055. gpointer
  1056. g_xim_rectangle_get_from_stream(GXimProtocol *proto,
  1057. GDataInputStream *stream,
  1058. GCancellable *cancellable,
  1059. GError **error)
  1060. {
  1061. GXimRectangle *retval;
  1062. guint16 x, y, width, height;
  1063. g_return_val_if_fail (G_IS_XIM_PROTOCOL (proto), NULL);
  1064. g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), NULL);
  1065. g_return_val_if_fail (error != NULL, NULL);
  1066. if (!g_xim_protocol_read_format(proto, stream, cancellable, error,
  1067. 4,
  1068. G_XIM_TYPE_WORD, &x,
  1069. G_XIM_TYPE_WORD, &y,
  1070. G_XIM_TYPE_WORD, &width,
  1071. G_XIM_TYPE_WORD, &height))
  1072. return NULL;
  1073. retval = g_xim_rectangle_new();
  1074. G_XIM_GERROR_CHECK_ALLOC (retval, error,
  1075. G_XIM_PROTOCOL_ERROR, NULL);
  1076. retval->x = x;
  1077. retval->y = y;
  1078. retval->width = width;
  1079. retval->height = height;
  1080. return retval;
  1081. }
  1082. /* XPoint */
  1083. GType
  1084. g_xim_point_get_type(void)
  1085. {
  1086. static volatile gsize type_id_volatile = 0;
  1087. if (g_once_init_enter(&type_id_volatile)) {
  1088. GType type_id;
  1089. type_id = g_boxed_type_register_static(g_intern_static_string("GXimPoint"),
  1090. g_xim_point_copy,
  1091. g_xim_point_free);
  1092. g_once_init_leave(&type_id_volatile, type_id);
  1093. }
  1094. return type_id_volatile;
  1095. }
  1096. gpointer
  1097. g_xim_point_new(void)
  1098. {
  1099. return g_new0(GXimPoint, 1);
  1100. }
  1101. gpointer
  1102. g_xim_point_copy(gpointer boxed)
  1103. {
  1104. GXimPoint *retval, *val = boxed;
  1105. if (boxed == NULL)
  1106. return NULL;
  1107. retval = g_xim_point_new();
  1108. G_XIM_CHECK_ALLOC (retval, NULL);
  1109. retval->x = val->x;
  1110. retval->y = val->y;
  1111. return retval;
  1112. }
  1113. void
  1114. g_xim_point_free(gpointer boxed)
  1115. {
  1116. g_free(boxed);
  1117. }
  1118. gsize
  1119. g_xim_point_put_to_stream(GXimPoint *point,
  1120. GXimProtocol *proto,
  1121. GCancellable *cancellable,
  1122. GError **error)
  1123. {
  1124. g_return_val_if_fail (G_IS_XIM_PROTOCOL (proto), 0);
  1125. g_return_val_if_fail (point != NULL, 0);
  1126. g_return_val_if_fail (error != NULL, 0);
  1127. return g_xim_protocol_send_format(proto, cancellable, error, 2,
  1128. G_XIM_TYPE_WORD, point->x,
  1129. G_XIM_TYPE_WORD, point->y);
  1130. }
  1131. gpointer
  1132. g_xim_point_get_from_stream(GXimProtocol *proto,
  1133. GDataInputStream *stream,
  1134. GCancellable *cancellable,
  1135. GError **error)
  1136. {
  1137. GXimPoint *retval;
  1138. guint16 x, y;
  1139. g_return_val_if_fail (G_IS_XIM_PROTOCOL (proto), NULL);
  1140. g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), NULL);
  1141. g_return_val_if_fail (error != NULL, NULL);
  1142. if (!g_xim_protocol_read_format(proto, stream, cancellable, error,
  1143. 2,
  1144. G_XIM_TYPE_WORD, &x,
  1145. G_XIM_TYPE_WORD, &y))
  1146. return NULL;
  1147. retval = g_xim_point_new();
  1148. G_XIM_GERROR_CHECK_ALLOC (retval, error,
  1149. G_XIM_PROTOCOL_ERROR, NULL);
  1150. retval->x = x;
  1151. retval->y = y;
  1152. return retval;
  1153. }
  1154. /* XFontSet */
  1155. GType
  1156. g_xim_fontset_get_type(void)
  1157. {
  1158. static volatile gsize type_id_volatile = 0;
  1159. if (g_once_init_enter(&type_id_volatile)) {
  1160. GType type_id;
  1161. type_id = g_boxed_type_register_static(g_intern_static_string("GXimFontSet"),
  1162. g_xim_fontset_copy,
  1163. g_xim_fontset_free);
  1164. g_once_init_leave(&type_id_volatile, type_id);
  1165. }
  1166. return type_id_volatile;
  1167. }
  1168. gpointer
  1169. g_xim_fontset_copy(gpointer boxed)
  1170. {
  1171. GString *retval, *val = boxed;
  1172. if (boxed == NULL)
  1173. return NULL;
  1174. retval = g_string_sized_new(val->len);
  1175. G_XIM_CHECK_ALLOC (retval, NULL);
  1176. g_string_append(retval, val->str);
  1177. return retval;
  1178. }
  1179. void
  1180. g_xim_fontset_free(gpointer boxed)
  1181. {
  1182. if (boxed == NULL)
  1183. return;
  1184. g_string_free(boxed, TRUE);
  1185. }
  1186. gsize
  1187. g_xim_fontset_put_to_stream(GXimFontSet *fontset,
  1188. GXimProtocol *proto,
  1189. GCancellable *cancellable,
  1190. GError **error)
  1191. {
  1192. g_return_val_if_fail (fontset != NULL, 0);
  1193. g_return_val_if_fail (G_IS_XIM_PROTOCOL (proto), 0);
  1194. g_return_val_if_fail (error != NULL, 0);
  1195. return g_xim_protocol_send_format(proto, cancellable, error, 1,
  1196. G_XIM_TYPE_GSTRING, fontset);
  1197. }
  1198. gpointer
  1199. g_xim_fontset_get_from_stream(GXimProtocol *proto,
  1200. GDataInputStream *stream,
  1201. GCancellable *cancellable,
  1202. GError **error)
  1203. {
  1204. GXimFontSet *retval = NULL;
  1205. g_return_val_if_fail (G_IS_XIM_PROTOCOL (proto), NULL);
  1206. g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), NULL);
  1207. g_return_val_if_fail (error != NULL, NULL);
  1208. if (!g_xim_protocol_read_format(proto, stream, cancellable, error,
  1209. 1,
  1210. G_XIM_TYPE_GSTRING, &retval))
  1211. return NULL;
  1212. return retval;
  1213. }
  1214. /* GString */
  1215. gsize
  1216. g_xim_gstring_put_to_stream(GString *string,
  1217. GDataOutputStream *stream,
  1218. GCancellable *cancellable,
  1219. GError **error)
  1220. {
  1221. gint i;
  1222. gsize retval = 2;
  1223. g_return_val_if_fail (G_IS_DATA_OUTPUT_STREAM (stream), 0);
  1224. g_return_val_if_fail (string != NULL, 0);
  1225. g_return_val_if_fail (string->len <= 0xffff, 0);
  1226. g_return_val_if_fail (error != NULL, 0);
  1227. g_data_output_stream_put_uint16(stream, string->len, cancellable, error);
  1228. if (*error)
  1229. return 0;
  1230. for (i = 0; i < string->len; i++) {
  1231. g_data_output_stream_put_byte(stream, string->str[i], cancellable, error);
  1232. if (*error)
  1233. return 0;
  1234. retval++;
  1235. }
  1236. return retval;
  1237. }
  1238. gpointer
  1239. g_xim_gstring_get_from_stream(GDataInputStream *stream,
  1240. GCancellable *cancellable,
  1241. GError **error)
  1242. {
  1243. GString *retval = NULL;
  1244. gsize size, avail, read = 2, i;
  1245. g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), NULL);
  1246. g_return_val_if_fail (error != NULL, NULL);
  1247. size = g_data_input_stream_read_uint16(stream, cancellable, error);
  1248. if (*error)
  1249. return NULL;
  1250. if ((avail = g_buffered_input_stream_get_buffer_size(G_BUFFERED_INPUT_STREAM (stream))) < size) {
  1251. g_set_error(error, G_XIM_PROTOCOL_ERROR,
  1252. G_XIM_PROTOCOL_ERROR_INVALID_PACKETS_RECEIVED | G_XIM_NOTICE_ERROR,
  1253. "Unable to compose a string with the remaining packets: %" G_GSIZE_FORMAT " for %" G_GSIZE_FORMAT,
  1254. size, avail);
  1255. return NULL;
  1256. }
  1257. retval = g_string_sized_new(size);
  1258. G_XIM_GERROR_CHECK_ALLOC (retval, error,
  1259. G_XIM_PROTOCOL_ERROR, NULL);
  1260. for (i = 0; i < size; i++) {
  1261. gchar c;
  1262. c = g_data_input_stream_read_byte(stream, cancellable, error);
  1263. if (*error)
  1264. goto fail;
  1265. g_string_append_c(retval, c);
  1266. read++;
  1267. }
  1268. return retval;
  1269. fail:
  1270. if (retval)
  1271. g_string_free(retval, TRUE);
  1272. return NULL;
  1273. }
  1274. /* STRING */
  1275. GType
  1276. g_xim_string_get_type(void)
  1277. {
  1278. static volatile gsize type_id_volatile = 0;
  1279. if (g_once_init_enter(&type_id_volatile)) {
  1280. GType type_id;
  1281. type_id = g_boxed_type_register_static(g_intern_static_string("GXimString"),
  1282. g_xim_string_copy,
  1283. g_xim_string_free);
  1284. g_once_init_leave(&type_id_volatile, type_id);
  1285. }
  1286. return type_id_volatile;
  1287. }
  1288. gpointer
  1289. g_xim_string_new(void)
  1290. {
  1291. GString *retval = g_string_new(NULL);
  1292. return retval;
  1293. }
  1294. gpointer
  1295. g_xim_string_copy(gpointer boxed)
  1296. {
  1297. GString *retval, *orig = boxed;
  1298. if (boxed == NULL)
  1299. return NULL;
  1300. retval = g_string_sized_new(orig->len);
  1301. G_XIM_CHECK_ALLOC (retval, NULL);
  1302. g_string_append(retval, orig->str);
  1303. return retval;
  1304. }
  1305. void
  1306. g_xim_string_free(gpointer boxed)
  1307. {
  1308. if (boxed == NULL)
  1309. return;
  1310. g_string_free(boxed, TRUE);
  1311. }
  1312. const gchar *
  1313. g_xim_string_get_string(const GXimString *string)
  1314. {
  1315. g_return_val_if_fail (string != NULL, NULL);
  1316. return ((GString *)string)->str;
  1317. }
  1318. gsize
  1319. g_xim_string_get_length(GXimString *string)
  1320. {
  1321. GString *str = (GString *)string;
  1322. g_return_val_if_fail (string != NULL, 0);
  1323. return str->len;
  1324. }
  1325. gsize
  1326. g_xim_string_put_to_stream(GXimString *string,
  1327. GDataOutputStream *stream,
  1328. GCancellable *cancellable,
  1329. GError **error)
  1330. {
  1331. gsize retval = 2, i;
  1332. GString *str = (GString *)string;
  1333. g_return_val_if_fail (G_IS_DATA_OUTPUT_STREAM (stream), 0);
  1334. g_return_val_if_fail (string != NULL, 0);
  1335. g_return_val_if_fail (error != NULL, 0);
  1336. /* length of string in bytes */
  1337. g_data_output_stream_put_uint16(stream,
  1338. str->len,
  1339. cancellable,
  1340. error);
  1341. if (*error)
  1342. return 0;
  1343. /* LIST of LPCE */
  1344. for (i = 0; i < str->len; i++) {
  1345. g_data_output_stream_put_byte(stream,
  1346. str->str[i],
  1347. cancellable,
  1348. error);
  1349. if (*error)
  1350. return 0;
  1351. retval++;
  1352. }
  1353. /* padding */
  1354. for (i = 0; i < g_xim_protocol_n_pad4 (2 + str->len); i++) {
  1355. g_data_output_stream_put_byte(stream, 0, cancellable, error);
  1356. if (*error)
  1357. return 0;
  1358. retval++;
  1359. }
  1360. return retval;
  1361. }
  1362. gpointer
  1363. g_xim_string_get_from_stream(GDataInputStream *stream,
  1364. GCancellable *cancellable,
  1365. GError **error)
  1366. {
  1367. guint16 n, i;
  1368. GString *str = NULL;
  1369. GInputStream *base_stream;
  1370. g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), NULL);
  1371. g_return_val_if_fail (error != NULL, NULL);
  1372. n = g_data_input_stream_read_uint16(stream, cancellable, error);
  1373. if (*error)
  1374. return NULL;
  1375. str = g_string_sized_new(n);
  1376. G_XIM_GERROR_CHECK_ALLOC (str, error,
  1377. G_XIM_PROTOCOL_ERROR, NULL);
  1378. for (i = 0; i < n; i++) {
  1379. guint8 c;
  1380. c = g_data_input_stream_read_byte(stream, cancellable, error);
  1381. if (*error)
  1382. goto fail;
  1383. g_string_append_c(str, c);
  1384. }
  1385. /* skip padding */
  1386. base_stream = g_filter_input_stream_get_base_stream(G_FILTER_INPUT_STREAM (stream));
  1387. g_seekable_seek(G_SEEKABLE (base_stream),
  1388. g_xim_protocol_n_pad4 (2 + n),
  1389. G_SEEK_CUR, cancellable, error);
  1390. return str;
  1391. fail:
  1392. if (str)
  1393. g_string_free(str, TRUE);
  1394. return NULL;
  1395. }
  1396. /* STR */
  1397. GType
  1398. g_xim_str_get_type(void)
  1399. {
  1400. static volatile gsize type_id_volatile = 0;
  1401. if (g_once_init_enter(&type_id_volatile)) {
  1402. GType type_id;
  1403. type_id = g_boxed_type_register_static(g_intern_static_string("GXimStr"),
  1404. g_xim_str_copy,
  1405. g_xim_str_free);
  1406. g_once_init_leave(&type_id_volatile, type_id);
  1407. }
  1408. return type_id_volatile;
  1409. }
  1410. gpointer
  1411. g_xim_str_new(void)
  1412. {
  1413. GString *retval = g_string_new(NULL);
  1414. return retval;
  1415. }
  1416. gpointer
  1417. g_xim_str_copy(gpointer boxed)
  1418. {
  1419. GString *retval, *orig = boxed;
  1420. g_return_val_if_fail (boxed != NULL, NULL);
  1421. retval = g_string_sized_new(orig->len);
  1422. G_XIM_CHECK_ALLOC (retval, NULL);
  1423. g_string_append(retval, orig->str);
  1424. return retval;
  1425. }
  1426. void
  1427. g_xim_str_free(gpointer boxed)
  1428. {
  1429. if (boxed == NULL)
  1430. return;
  1431. g_string_free(boxed, TRUE);
  1432. }
  1433. const gchar *
  1434. g_xim_str_get_string(const GXimStr *string)
  1435. {
  1436. g_return_val_if_fail (string != NULL, NULL);
  1437. return ((GString *)string)->str;
  1438. }
  1439. gsize
  1440. g_xim_str_get_length(const GXimStr *string)
  1441. {
  1442. const GString *str = (const GString *)string;
  1443. g_return_val_if_fail (string != NULL, 0);
  1444. return str->len;
  1445. }
  1446. GXimStr *
  1447. g_xim_str_append(GXimStr *string,
  1448. const gchar *val)
  1449. {
  1450. g_return_val_if_fail (string != NULL, NULL);
  1451. g_return_val_if_fail (val != NULL, string);
  1452. return g_xim_str_append_len(string, val, strlen(val));
  1453. }
  1454. GXimStr *
  1455. g_xim_str_append_len(GXimStr *string,
  1456. const gchar *val,
  1457. gssize len)
  1458. {
  1459. g_return_val_if_fail (string != NULL, NULL);
  1460. g_return_val_if_fail (val != NULL, string);
  1461. if (len < 0)
  1462. len = strlen(val);
  1463. return (GXimStr *)g_string_append_len((GString *)string,
  1464. val,
  1465. len);
  1466. }
  1467. gsize
  1468. g_xim_str_put_to_stream(GXimStr *string,
  1469. GDataOutputStream *stream,
  1470. GCancellable *cancellable,
  1471. GError **error)
  1472. {
  1473. gsize retval = 1, i;
  1474. GString *str = (GString *)string;
  1475. g_return_val_if_fail (G_IS_DATA_OUTPUT_STREAM (stream), 0);
  1476. g_return_val_if_fail (string != NULL, 0);
  1477. g_return_val_if_fail (str->len < 0x100, 0);
  1478. g_return_val_if_fail (error != NULL, 0);
  1479. /* length of string in bytes */
  1480. g_data_output_stream_put_byte(stream,
  1481. str->len,
  1482. cancellable,
  1483. error);
  1484. if (*error)
  1485. return 0;
  1486. /* STRING8 */
  1487. for (i = 0; i < str->len; i++) {
  1488. g_data_output_stream_put_byte(stream,
  1489. str->str[i],
  1490. cancellable,
  1491. error);
  1492. if (*error)
  1493. return 0;
  1494. retval++;
  1495. }
  1496. return retval;
  1497. }
  1498. gpointer
  1499. g_xim_str_get_from_stream(GDataInputStream *stream,
  1500. GCancellable *cancellable,
  1501. GError **error)
  1502. {
  1503. guint8 n, i;
  1504. GString *str = NULL;
  1505. g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), NULL);
  1506. g_return_val_if_fail (error != NULL, NULL);
  1507. n = g_data_input_stream_read_byte(stream, cancellable, error);
  1508. if (*error)
  1509. return NULL;
  1510. str = g_string_sized_new(n);
  1511. G_XIM_GERROR_CHECK_ALLOC (str, error,
  1512. G_XIM_PROTOCOL_ERROR, NULL);
  1513. for (i = 0; i < n; i++) {
  1514. guint8 c;
  1515. c = g_data_input_stream_read_byte(stream, cancellable, error);
  1516. if (*error)
  1517. goto fail;
  1518. g_string_append_c(str, c);
  1519. }
  1520. return str;
  1521. fail:
  1522. if (str)
  1523. g_string_free(str, TRUE);
  1524. return NULL;
  1525. }
  1526. /* ENCODINGINFO */
  1527. GType
  1528. g_xim_encodinginfo_get_type(void)
  1529. {
  1530. static volatile gsize type_id_volatile = 0;
  1531. if (g_once_init_enter(&type_id_volatile)) {
  1532. GType type_id;
  1533. type_id = g_boxed_type_register_static(g_intern_static_string("ENCODINGINFO"),
  1534. g_xim_encodinginfo_copy,
  1535. g_xim_encodinginfo_free);
  1536. g_once_init_leave(&type_id_volatile, type_id);
  1537. }
  1538. return type_id_volatile;
  1539. }
  1540. gpointer
  1541. g_xim_encodinginfo_new(void)
  1542. {
  1543. GString *retval = g_string_new(NULL);
  1544. return retval;
  1545. }
  1546. gpointer
  1547. g_xim_encodinginfo_copy(gpointer boxed)
  1548. {
  1549. GString *retval, *orig = boxed;
  1550. g_return_val_if_fail (boxed != NULL, NULL);
  1551. retval = g_string_sized_new(orig->len);
  1552. G_XIM_CHECK_ALLOC (retval, NULL);
  1553. g_string_append(retval, orig->str);
  1554. return retval;
  1555. }
  1556. void
  1557. g_xim_encodinginfo_free(gpointer boxed)
  1558. {
  1559. if (boxed == NULL)
  1560. return;
  1561. g_string_free(boxed, TRUE);
  1562. }
  1563. const gchar *
  1564. g_xim_encodinginfo_get_string(const GXimEncodingInfo *encoding)
  1565. {
  1566. g_return_val_if_fail (encoding != NULL, NULL);
  1567. return ((GString *)encoding)->str;
  1568. }
  1569. gsize
  1570. g_xim_encodinginfo_get_length(GXimEncodingInfo *encoding)
  1571. {
  1572. GString *str = (GString *)encoding;
  1573. g_return_val_if_fail (encoding != NULL, 0);
  1574. return str->len;
  1575. }
  1576. gsize
  1577. g_xim_encodinginfo_put_to_stream(GXimEncodingInfo *encoding,
  1578. GDataOutputStream *stream,
  1579. GCancellable *cancellable,
  1580. GError **error)
  1581. {
  1582. gsize retval = 2, i;
  1583. GString *str = (GString *)encoding;
  1584. g_return_val_if_fail (G_IS_DATA_OUTPUT_STREAM (stream), 0);
  1585. g_return_val_if_fail (encoding != NULL, 0);
  1586. g_return_val_if_fail (error != NULL, 0);
  1587. /* length of string in bytes */
  1588. g_data_output_stream_put_uint16(stream,
  1589. str->len,
  1590. cancellable,
  1591. error);
  1592. if (*error)
  1593. return 0;
  1594. /* STRING8 */
  1595. for (i = 0; i < str->len; i++) {
  1596. g_data_output_stream_put_byte(stream,
  1597. str->str[i],
  1598. cancellable,
  1599. error);
  1600. if (*error)
  1601. return 0;
  1602. retval++;
  1603. }
  1604. /* padding */
  1605. for (i = 0; i < g_xim_protocol_n_pad4 (2 + str->len); i++) {
  1606. g_data_output_stream_put_byte(stream, 0, cancellable, error);
  1607. if (*error)
  1608. return 0;
  1609. retval++;
  1610. }
  1611. return retval;
  1612. }
  1613. gpointer
  1614. g_xim_encodinginfo_get_from_stream(GDataInputStream *stream,
  1615. GCancellable *cancellable,
  1616. GError **error)
  1617. {
  1618. guint16 n, i;
  1619. GString *str = NULL;
  1620. GInputStream *base_stream;
  1621. g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), NULL);
  1622. g_return_val_if_fail (error != NULL, NULL);
  1623. n = g_data_input_stream_read_uint16(stream, cancellable, error);
  1624. if (*error)
  1625. return NULL;
  1626. str = g_string_sized_new(n);
  1627. G_XIM_GERROR_CHECK_ALLOC (str, error,
  1628. G_XIM_PROTOCOL_ERROR, NULL);
  1629. for (i = 0; i < n; i++) {
  1630. guint8 c;
  1631. c = g_data_input_stream_read_byte(stream, cancellable, error);
  1632. if (*error)
  1633. goto fail;
  1634. g_string_append_c(str, c);
  1635. }
  1636. /* skip padding */
  1637. base_stream = g_filter_input_stream_get_base_stream(G_FILTER_INPUT_STREAM (stream));
  1638. g_seekable_seek(G_SEEKABLE (base_stream),
  1639. g_xim_protocol_n_pad4 (2 + n),
  1640. G_SEEK_CUR, cancellable, error);
  1641. return str;
  1642. fail:
  1643. if (str)
  1644. g_string_free(str, TRUE);
  1645. return NULL;
  1646. }
  1647. /* ATTR */
  1648. GType
  1649. g_xim_raw_attr_get_type(void)
  1650. {
  1651. static volatile gsize type_id_volatile = 0;
  1652. if (g_once_init_enter(&type_id_volatile)) {
  1653. GType type_id;
  1654. type_id = g_boxed_type_register_static(g_intern_static_string("GXimRawAttr"),
  1655. g_xim_raw_attr_copy,
  1656. g_xim_raw_attr_free);
  1657. g_once_init_leave(&type_id_volatile, type_id);
  1658. }
  1659. return type_id_volatile;
  1660. }
  1661. gpointer
  1662. g_xim_raw_attr_new(void)
  1663. {
  1664. GXimRawAttr *retval;
  1665. retval = g_new0(GXimRawAttr, 1);
  1666. G_XIM_CHECK_ALLOC (retval, NULL);
  1667. retval->base.vtype = G_XIM_TYPE_INVALID;
  1668. return retval;
  1669. }
  1670. gpointer
  1671. g_xim_raw_attr_new_with_value(guint16 id,
  1672. GString *name,
  1673. GXimValueType vtype)
  1674. {
  1675. GXimRawAttr *retval;
  1676. g_return_val_if_fail (vtype != G_XIM_TYPE_INVALID, NULL);
  1677. g_return_val_if_fail (name != NULL, NULL);
  1678. retval = g_xim_raw_attr_new();
  1679. G_XIM_CHECK_ALLOC (retval, NULL);
  1680. g_xim_raw_attr_set_name(retval, name);
  1681. retval->base.id = id;
  1682. retval->base.vtype = vtype;
  1683. return retval;
  1684. }
  1685. void
  1686. g_xim_raw_attr_set_name(GXimRawAttr *attr,
  1687. GString *name)
  1688. {
  1689. g_return_if_fail (attr != NULL);
  1690. g_return_if_fail (name != NULL);
  1691. g_return_if_fail (name->len > 0);
  1692. if (attr->attribute_name)
  1693. g_string_free(attr->attribute_name, TRUE);
  1694. attr->attribute_name = g_string_sized_new(name->len);
  1695. G_XIM_CHECK_ALLOC_WITH_NO_RET (attr->attribute_name);
  1696. g_string_append(attr->attribute_name, name->str);
  1697. }
  1698. void
  1699. g_xim_raw_attr_clear(GXimRawAttr *attr)
  1700. {
  1701. g_return_if_fail (attr != NULL);
  1702. attr->base.vtype = G_XIM_TYPE_INVALID;
  1703. g_string_free(attr->attribute_name, TRUE);
  1704. attr->attribute_name = NULL;
  1705. }
  1706. gpointer
  1707. g_xim_raw_attr_copy(gpointer boxed)
  1708. {
  1709. GXimRawAttr *retval, *orig;
  1710. if (boxed == NULL)
  1711. return NULL;
  1712. orig = boxed;
  1713. retval = g_xim_raw_attr_new_with_value(orig->base.id,
  1714. orig->attribute_name,
  1715. orig->base.vtype);
  1716. return retval;
  1717. }
  1718. void
  1719. g_xim_raw_attr_free(gpointer boxed)
  1720. {
  1721. if (boxed == NULL)
  1722. return;
  1723. g_xim_raw_attr_clear(boxed);
  1724. g_free(boxed);
  1725. }
  1726. gsize
  1727. g_xim_raw_attr_put_to_stream(GXimRawAttr *attr,
  1728. GXimProtocol *proto,
  1729. GCancellable *cancellable,
  1730. GError **error)
  1731. {
  1732. g_return_val_if_fail (attr != NULL, 0);
  1733. g_return_val_if_fail (G_IS_XIM_PROTOCOL (proto), 0);
  1734. g_return_val_if_fail (error != NULL, 0);
  1735. return g_xim_protocol_send_format(proto, cancellable, error, 4,
  1736. G_XIM_TYPE_WORD, attr->base.id,
  1737. G_XIM_TYPE_WORD, attr->base.vtype,
  1738. /* G_XIM_TYPE_GSTRING puts the size as CARD16 first then STRING8 */
  1739. G_XIM_TYPE_GSTRING, attr->attribute_name,
  1740. G_XIM_TYPE_AUTO_PADDING, 2);
  1741. }
  1742. gpointer
  1743. g_xim_raw_attr_get_from_stream(GXimProtocol *proto,
  1744. GDataInputStream *stream,
  1745. GCancellable *cancellable,
  1746. GError **error)
  1747. {
  1748. GXimRawAttr *retval;
  1749. guint16 id;
  1750. GXimValueType vtype = 0;
  1751. GString *name = NULL;
  1752. g_return_val_if_fail (G_IS_XIM_PROTOCOL (proto), NULL);
  1753. g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), NULL);
  1754. g_return_val_if_fail (error != NULL, NULL);
  1755. if (!g_xim_protocol_read_format(proto, stream, cancellable, error,
  1756. 4,
  1757. G_XIM_TYPE_WORD, &id,
  1758. G_XIM_TYPE_WORD, &vtype,
  1759. G_XIM_TYPE_GSTRING, &name,
  1760. G_XIM_TYPE_AUTO_PADDING, 2))
  1761. return NULL;
  1762. retval = g_xim_raw_attr_new_with_value(id, name, vtype);
  1763. return retval;
  1764. }
  1765. /* ATTRIBUTE */
  1766. GType
  1767. g_xim_attribute_get_type(void)
  1768. {
  1769. static volatile gsize type_id_volatile = 0;
  1770. if (g_once_init_enter(&type_id_volatile)) {
  1771. GType type_id;
  1772. type_id = g_boxed_type_register_static(g_intern_static_string("GXimAttribute"),
  1773. g_xim_attribute_copy,
  1774. g_xim_attribute_free);
  1775. g_once_init_leave(&type_id_volatile, type_id);
  1776. }
  1777. return type_id_volatile;
  1778. }
  1779. gpointer
  1780. g_xim_attribute_new(void)
  1781. {
  1782. GXimAttribute *retval;
  1783. retval = g_new0(GXimAttribute, 1);
  1784. G_XIM_CHECK_ALLOC (retval, NULL);
  1785. retval->vtype = G_XIM_TYPE_INVALID;
  1786. return retval;
  1787. }
  1788. gpointer
  1789. g_xim_attribute_new_with_value(guint16 id,
  1790. GXimValueType vtype,
  1791. gpointer value)
  1792. {
  1793. GXimAttribute *retval;
  1794. g_return_val_if_fail (vtype != G_XIM_TYPE_INVALID, NULL);
  1795. retval = g_xim_attribute_new();
  1796. G_XIM_CHECK_ALLOC (retval, NULL);
  1797. g_xim_attribute_set(retval, id, vtype, value);
  1798. return retval;
  1799. }
  1800. void
  1801. g_xim_attribute_set(GXimAttribute *attr,
  1802. guint16 id,
  1803. GXimValueType vtype,
  1804. gpointer value)
  1805. {
  1806. GType gtype;
  1807. g_return_if_fail (attr != NULL);
  1808. g_return_if_fail (vtype != G_XIM_TYPE_INVALID);
  1809. gtype = g_xim_value_type_to_gtype(vtype);
  1810. g_return_if_fail (gtype != G_TYPE_INVALID);
  1811. g_xim_attribute_clear(attr);
  1812. attr->id = id;
  1813. attr->vtype = vtype;
  1814. if (vtype == G_XIM_TYPE_WORD)
  1815. attr->v.i = GPOINTER_TO_UINT (value);
  1816. else if (vtype == G_XIM_TYPE_LONG)
  1817. attr->v.l = (gulong)value;
  1818. else
  1819. attr->v.pointer = g_xim_copy_by_gtype(gtype, value);
  1820. }
  1821. void
  1822. g_xim_attribute_clear(GXimAttribute *attr)
  1823. {
  1824. GType gtype;
  1825. g_return_if_fail (attr != NULL);
  1826. if (attr->vtype == G_XIM_TYPE_INVALID)
  1827. return;
  1828. gtype = g_xim_value_type_to_gtype(attr->vtype);
  1829. g_return_if_fail (gtype != G_TYPE_INVALID);
  1830. g_xim_free_by_gtype(gtype, attr->v.pointer);
  1831. attr->v.pointer = NULL;
  1832. attr->vtype = G_XIM_TYPE_INVALID;
  1833. }
  1834. gpointer
  1835. g_xim_attribute_copy(gpointer boxed)
  1836. {
  1837. GXimAttribute *retval, *orig;
  1838. if (boxed == NULL)
  1839. return NULL;
  1840. orig = boxed;
  1841. retval = g_xim_attribute_new();
  1842. G_XIM_CHECK_ALLOC (retval, NULL);
  1843. g_xim_attribute_set(retval, orig->id, orig->vtype, orig->v.pointer);
  1844. return retval;
  1845. }
  1846. void
  1847. g_xim_attribute_free(gpointer boxed)
  1848. {
  1849. if (boxed == NULL)
  1850. return;
  1851. g_xim_attribute_clear(boxed);
  1852. g_free(boxed);
  1853. }
  1854. gsize
  1855. g_xim_attribute_put_to_stream(GXimAttribute *attr,
  1856. GXimProtocol *proto,
  1857. GCancellable *cancellable,
  1858. GError **error)
  1859. {
  1860. g_return_val_if_fail (G_IS_XIM_PROTOCOL (proto), 0);
  1861. g_return_val_if_fail (attr != NULL, 0);
  1862. g_return_val_if_fail (error != NULL, 0);
  1863. return g_xim_protocol_send_format(proto, cancellable, error, 4,
  1864. G_XIM_TYPE_WORD, attr->id,
  1865. G_XIM_TYPE_MARKER_N_BYTES_2, attr->vtype,
  1866. attr->vtype, attr->v.pointer,
  1867. G_XIM_TYPE_AUTO_PADDING, 0);
  1868. }
  1869. /* NESTEDLIST */
  1870. GType
  1871. g_xim_nested_list_get_type(void)
  1872. {
  1873. static volatile gsize type_id_volatile = 0;
  1874. if (g_once_init_enter(&type_id_volatile)) {
  1875. GType type_id;
  1876. type_id = g_boxed_type_register_static(g_intern_static_string("NESTEDLIST"),
  1877. g_xim_nested_list_copy,
  1878. g_xim_nested_list_free);
  1879. g_once_init_leave(&type_id_volatile, type_id);
  1880. }
  1881. return type_id_volatile;
  1882. }
  1883. gpointer
  1884. g_xim_nested_list_new(GXimAttr *attr,
  1885. guint n_nodes)
  1886. {
  1887. GXimNestedList *retval;
  1888. retval = g_new0(GXimNestedList, 1);
  1889. G_XIM_CHECK_ALLOC (retval, NULL);
  1890. retval->attr = g_object_ref(attr);
  1891. if (n_nodes > 0) {
  1892. retval->nodes = g_new0(GXimNestedListNode *, n_nodes);
  1893. G_XIM_CHECK_ALLOC (retval->nodes, NULL);
  1894. }
  1895. retval->allocated_len = n_nodes;
  1896. return retval;
  1897. }
  1898. gpointer
  1899. g_xim_nested_list_copy(gpointer boxed)
  1900. {
  1901. GXimNestedList *retval, *orig = boxed;
  1902. guint16 i;
  1903. if (boxed == NULL)
  1904. return NULL;
  1905. retval = g_xim_nested_list_new(orig->attr, orig->n_nodes);
  1906. G_XIM_CHECK_ALLOC (retval, NULL);
  1907. for (i = 0; i < orig->n_nodes; i++) {
  1908. retval->nodes[i] = g_xim_nested_list_node_copy(orig->nodes[i]);
  1909. G_XIM_CHECK_ALLOC_WITH_CODE (retval->nodes[i],
  1910. {retval->n_nodes = i; g_xim_nested_list_free(retval);},
  1911. NULL);
  1912. }
  1913. retval->n_nodes = orig->n_nodes;
  1914. return retval;
  1915. }
  1916. void
  1917. g_xim_nested_list_free(gpointer boxed)
  1918. {
  1919. GXimNestedList *list = boxed;
  1920. guint16 i;
  1921. if (boxed == NULL)
  1922. return;
  1923. for (i = 0; i < list->n_nodes; i++) {
  1924. GXimNestedListNode *node;
  1925. node = list->nodes[i];
  1926. g_xim_nested_list_node_free(node);
  1927. }
  1928. g_object_unref(list->attr);
  1929. g_free(list->nodes);
  1930. g_free(list);
  1931. }
  1932. gboolean
  1933. g_xim_nested_list_append(GXimNestedList *list,
  1934. const gchar *name,
  1935. gpointer value)
  1936. {
  1937. GXimNestedListNode *node, *tmp;
  1938. GXimValueType vtype;
  1939. GType gtype;
  1940. g_return_val_if_fail (list != NULL, FALSE);
  1941. g_return_val_if_fail (name != NULL, FALSE);
  1942. if (list->n_nodes == list->allocated_len) {
  1943. gpointer data;
  1944. data = (gpointer)g_realloc(list->nodes,
  1945. sizeof (gpointer) * (list->allocated_len + N_REALLOC_NESTED_LIST));
  1946. G_XIM_CHECK_ALLOC (data, FALSE);
  1947. list->nodes = data;
  1948. list->allocated_len += N_REALLOC_NESTED_LIST;
  1949. }
  1950. gtype = g_xim_attr_get_gtype_by_name(list->attr, name);
  1951. g_return_val_if_fail (gtype != G_TYPE_INVALID, FALSE);
  1952. vtype = g_xim_gtype_to_value_type(gtype);
  1953. g_return_val_if_fail (vtype != G_XIM_TYPE_INVALID, FALSE);
  1954. tmp = g_xim_nested_list_node_new();
  1955. G_XIM_CHECK_ALLOC (tmp, FALSE);
  1956. tmp->vtype = vtype;
  1957. tmp->name = (gchar *)name;
  1958. tmp->value = value;
  1959. node = g_xim_nested_list_node_copy(tmp);
  1960. G_XIM_CHECK_ALLOC_WITH_CODE (node, g_free(tmp), FALSE);
  1961. g_free(tmp);
  1962. list->nodes[list->n_nodes] = node;
  1963. list->n_nodes++;
  1964. return TRUE;
  1965. }
  1966. gboolean
  1967. g_xim_nested_list_foreach(GXimNestedList *list,
  1968. GXimNestedFunc func,
  1969. gpointer data)
  1970. {
  1971. guint16 i;
  1972. g_return_val_if_fail (list != NULL, FALSE);
  1973. g_return_val_if_fail (func != NULL, FALSE);
  1974. for (i = 0; i < list->n_nodes; i++) {
  1975. GXimNestedListNode *node = list->nodes[i];
  1976. if (func(node, data))
  1977. break;
  1978. }
  1979. return TRUE;
  1980. }
  1981. gsize
  1982. g_xim_nested_list_put_to_stream(GXimNestedList *list,
  1983. GXimProtocol *proto,
  1984. GCancellable *cancellable,
  1985. GError **error)
  1986. {
  1987. gsize retval = 0;
  1988. guint16 i;
  1989. g_return_val_if_fail (list != NULL, 0);
  1990. g_return_val_if_fail (G_IS_XIM_PROTOCOL (proto), 0);
  1991. g_return_val_if_fail (error != NULL, 0);
  1992. for (i = 0; i < list->n_nodes; i++) {
  1993. GXimNestedListNode *node;
  1994. gint16 attr_id;
  1995. node = list->nodes[i];
  1996. attr_id = g_xim_attr_get_attribute_id(list->attr, node->name);
  1997. if (attr_id < 0) {
  1998. g_xim_messages_warning(G_XIM_PROTOCOL_GET_IFACE (proto)->message,
  1999. "No attribute id available for %s in %s",
  2000. node->name, g_type_name(G_TYPE_FROM_INSTANCE (list->attr)));
  2001. continue;
  2002. }
  2003. retval += g_xim_protocol_send_format(proto, cancellable, error, 3,
  2004. G_XIM_TYPE_WORD, attr_id,
  2005. G_XIM_TYPE_MARKER_N_BYTES_2, node->vtype,
  2006. node->vtype, node->value);
  2007. }
  2008. return retval;
  2009. }
  2010. /* SeparatorofNestedList */
  2011. GType
  2012. g_xim_sep_nested_list_get_type(void)
  2013. {
  2014. static volatile gsize type_id_volatile = 0;
  2015. if (g_once_init_enter(&type_id_volatile)) {
  2016. GType type_id;
  2017. type_id = g_boxed_type_register_static(g_intern_static_string("SeparatorofNestedList"),
  2018. g_xim_sep_nested_list_copy,
  2019. g_xim_sep_nested_list_free);
  2020. g_once_init_leave(&type_id_volatile, type_id);
  2021. }
  2022. return type_id_volatile;
  2023. }
  2024. gpointer
  2025. g_xim_sep_nested_list_new(void)
  2026. {
  2027. return g_new0(GXimSepNestedList, 1);
  2028. }
  2029. gpointer
  2030. g_xim_sep_nested_list_copy(gpointer boxed)
  2031. {
  2032. if (boxed == NULL)
  2033. return NULL;
  2034. return g_xim_sep_nested_list_new();
  2035. }
  2036. void
  2037. g_xim_sep_nested_list_free(gpointer boxed)
  2038. {
  2039. g_free(boxed);
  2040. }
  2041. /* EXT */
  2042. GType
  2043. g_xim_ext_get_type(void)
  2044. {
  2045. static volatile gsize type_id_volatile = 0;
  2046. if (g_once_init_enter(&type_id_volatile)) {
  2047. GType type_id;
  2048. type_id = g_boxed_type_register_static(g_intern_static_string("GXimExt"),
  2049. g_xim_ext_copy,
  2050. g_xim_ext_free);
  2051. g_once_init_leave(&type_id_volatile, type_id);
  2052. }
  2053. return type_id_volatile;
  2054. }
  2055. gpointer
  2056. g_xim_ext_new(guint8 major_opcode,
  2057. guint8 minor_opcode,
  2058. const gchar *name)
  2059. {
  2060. GXimExt *retval;
  2061. retval = g_new0(GXimExt, 1);
  2062. G_XIM_CHECK_ALLOC (retval, NULL);
  2063. retval->major_opcode = major_opcode;
  2064. retval->minor_opcode = minor_opcode;
  2065. retval->name = g_string_new(name);
  2066. return retval;
  2067. }
  2068. gpointer
  2069. g_xim_ext_copy(gpointer boxed)
  2070. {
  2071. GXimExt *orig = boxed;
  2072. if (boxed == NULL)
  2073. return NULL;
  2074. return g_xim_ext_new(orig->major_opcode,
  2075. orig->minor_opcode,
  2076. orig->name->str);
  2077. }
  2078. void
  2079. g_xim_ext_free(gpointer boxed)
  2080. {
  2081. GXimExt *ext = boxed;
  2082. if (boxed == NULL)
  2083. return;
  2084. g_string_free(ext->name, TRUE);
  2085. g_free(ext);
  2086. }
  2087. gsize
  2088. g_xim_ext_put_to_stream(GXimExt *ext,
  2089. GXimProtocol *proto,
  2090. GCancellable *cancellable,
  2091. GError **error)
  2092. {
  2093. g_return_val_if_fail (ext != NULL, 0);
  2094. g_return_val_if_fail (G_IS_XIM_PROTOCOL (proto), 0);
  2095. g_return_val_if_fail (error != NULL, 0);
  2096. return g_xim_protocol_send_format(proto, cancellable, error, 4,
  2097. G_XIM_TYPE_BYTE, ext->major_opcode,
  2098. G_XIM_TYPE_BYTE, ext->minor_opcode,
  2099. G_XIM_TYPE_GSTRING, ext->name,
  2100. G_XIM_TYPE_AUTO_PADDING, 0);
  2101. }
  2102. gpointer
  2103. g_xim_ext_get_from_stream(GXimProtocol *proto,
  2104. GDataInputStream *stream,
  2105. GCancellable *cancellable,
  2106. GError **error)
  2107. {
  2108. GXimExt *retval;
  2109. guint8 major, minor;
  2110. GString *name;
  2111. g_return_val_if_fail (G_IS_XIM_PROTOCOL (proto), NULL);
  2112. g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), NULL);
  2113. g_return_val_if_fail (error != NULL, NULL);
  2114. if (!g_xim_protocol_read_format(proto, stream, cancellable, error,
  2115. 4,
  2116. G_XIM_TYPE_BYTE, &major,
  2117. G_XIM_TYPE_BYTE, &minor,
  2118. G_XIM_TYPE_GSTRING, &name,
  2119. G_XIM_TYPE_AUTO_PADDING, 0))
  2120. return NULL;
  2121. retval = g_xim_ext_new(major, minor, name->str);
  2122. g_string_free(name, TRUE);
  2123. return retval;
  2124. }
  2125. /* GXimText */
  2126. GType
  2127. g_xim_text_get_type(void)
  2128. {
  2129. static volatile gsize type_id_volatile = 0;
  2130. if (g_once_init_enter(&type_id_volatile)) {
  2131. GType type_id;
  2132. type_id = g_boxed_type_register_static(g_intern_static_string("GXimText"),
  2133. g_xim_text_copy,
  2134. g_xim_text_free);
  2135. g_once_init_leave(&type_id_volatile, type_id);
  2136. }
  2137. return type_id_volatile;
  2138. }
  2139. gpointer
  2140. g_xim_text_new(void)
  2141. {
  2142. return g_new0(GXimText, 1);
  2143. }
  2144. gboolean
  2145. g_xim_text_set_mbstring(GXimText *text,
  2146. const gchar *string,
  2147. gssize length)
  2148. {
  2149. g_return_val_if_fail (text != NULL, FALSE);
  2150. g_return_val_if_fail (string != NULL, FALSE);
  2151. g_xim_text_clear_string(text);
  2152. text->encoding_is_wchar = FALSE;
  2153. if (length < 0)
  2154. length = strlen(string);
  2155. g_return_val_if_fail (length < 65536, FALSE);
  2156. text->length = length;
  2157. text->string.multi_byte = g_strdup(string);
  2158. text->feedback = g_new0(GXimFeedback, length + 1);
  2159. return TRUE;
  2160. }
  2161. gboolean
  2162. g_xim_text_set_wcstring(GXimText *text,
  2163. const gunichar2 *string,
  2164. gssize length)
  2165. {
  2166. g_return_val_if_fail (text != NULL, FALSE);
  2167. g_return_val_if_fail (string != NULL, FALSE);
  2168. g_return_val_if_fail (length > 0 && length < 65536, FALSE);
  2169. g_xim_text_clear_string(text);
  2170. text->encoding_is_wchar = TRUE;
  2171. text->length = length;
  2172. text->string.wide_char = g_new0(gunichar2, length + 1);
  2173. G_XIM_CHECK_ALLOC (text->string.wide_char, FALSE);
  2174. memcpy(text->string.wide_char, string, sizeof(gunichar2) * length);
  2175. text->string.wide_char[length] = 0;
  2176. text->feedback = g_new0(GXimFeedback, length + 1);
  2177. return TRUE;
  2178. }
  2179. void
  2180. g_xim_text_clear_string(GXimText *text)
  2181. {
  2182. g_return_if_fail (text != NULL);
  2183. if (text->encoding_is_wchar) {
  2184. g_free(text->string.wide_char);
  2185. } else {
  2186. g_free(text->string.multi_byte);
  2187. }
  2188. g_free(text->feedback);
  2189. }
  2190. void
  2191. g_xim_text_set_feedback(GXimText *text,
  2192. GXimFeedback feedback,
  2193. gshort position)
  2194. {
  2195. g_return_if_fail (text != NULL);
  2196. g_return_if_fail (text->length > position);
  2197. text->feedback[position] = feedback;
  2198. }
  2199. GXimFeedback
  2200. g_xim_text_get_feedback(GXimText *text,
  2201. gshort position)
  2202. {
  2203. g_return_val_if_fail (text != NULL, 0);
  2204. g_return_val_if_fail (text->length > position, 0);
  2205. g_return_val_if_fail (text->feedback != NULL, 0);
  2206. return text->feedback[position];
  2207. }
  2208. gpointer
  2209. g_xim_text_copy(gpointer boxed)
  2210. {
  2211. GXimText *retval, *orig;
  2212. if (boxed == NULL)
  2213. return NULL;
  2214. orig = boxed;
  2215. retval = g_xim_text_new();
  2216. G_XIM_CHECK_ALLOC (retval, NULL);
  2217. retval->length = orig->length;
  2218. retval->encoding_is_wchar = orig->encoding_is_wchar;
  2219. if (orig->encoding_is_wchar) {
  2220. g_xim_text_set_wcstring(retval,
  2221. orig->string.wide_char,
  2222. orig->length);
  2223. } else {
  2224. g_xim_text_set_mbstring(retval,
  2225. orig->string.multi_byte,
  2226. orig->length);
  2227. }
  2228. g_return_val_if_fail (retval->feedback != NULL, NULL);
  2229. g_return_val_if_fail (orig->feedback != NULL, NULL);
  2230. memcpy(retval->feedback, orig->feedback, sizeof (GXimFeedback) * orig->length);
  2231. return retval;
  2232. }
  2233. void
  2234. g_xim_text_free(gpointer boxed)
  2235. {
  2236. GXimText *text = boxed;
  2237. if (boxed == NULL)
  2238. return;
  2239. if (text->encoding_is_wchar)
  2240. g_free(text->string.wide_char);
  2241. else
  2242. g_free(text->string.multi_byte);
  2243. g_free(text->feedback);
  2244. g_free(text);
  2245. }
  2246. gsize
  2247. g_xim_text_put_to_stream(GXimText *text,
  2248. GXimProtocol *proto,
  2249. GCancellable *cancellable,
  2250. GError **error)
  2251. {
  2252. guint32 mask = 0;
  2253. gsize retval;
  2254. gboolean no_feedback = FALSE, no_string = FALSE;
  2255. gint i, len;
  2256. g_return_val_if_fail (text != NULL, 0);
  2257. g_return_val_if_fail (G_IS_XIM_PROTOCOL (proto), 0);
  2258. g_return_val_if_fail (error != NULL, 0);
  2259. if (text->length == 0 ||
  2260. (text->encoding_is_wchar && text->string.wide_char[0] == 0) ||
  2261. (!text->encoding_is_wchar && text->string.multi_byte[0] == 0))
  2262. no_string = TRUE;
  2263. if (text->feedback[0] == 0)
  2264. no_feedback = TRUE;
  2265. if (no_string)
  2266. mask |= (1L << 0);
  2267. if (no_feedback)
  2268. mask |= (1L << 1);
  2269. retval = g_xim_protocol_send_format(proto, cancellable, error, 1,
  2270. G_XIM_TYPE_LONG, mask);
  2271. if (*error)
  2272. return 0;
  2273. if (no_string)
  2274. retval += g_xim_protocol_send_format(proto, cancellable, error, 2,
  2275. G_XIM_TYPE_WORD, 0,
  2276. G_XIM_TYPE_PADDING, 2);
  2277. else
  2278. retval += g_xim_protocol_send_format(proto, cancellable, error, 3,
  2279. G_XIM_TYPE_MARKER_N_BYTES_2, G_XIM_TYPE_CHAR,
  2280. G_XIM_TYPE_CHAR, text->string.multi_byte,
  2281. G_XIM_TYPE_AUTO_PADDING, 2);
  2282. if (*error)
  2283. return 0;
  2284. if (no_feedback) {
  2285. retval += g_xim_protocol_send_format(proto, cancellable, error, 2,
  2286. G_XIM_TYPE_WORD, 0,
  2287. G_XIM_TYPE_PADDING, 2);
  2288. } else {
  2289. for (len = 0; len < text->length; len++)
  2290. if (text->feedback[len] == 0)
  2291. break;
  2292. retval += g_xim_protocol_send_format(proto, cancellable, error, 2,
  2293. G_XIM_TYPE_WORD, len * 4,
  2294. G_XIM_TYPE_PADDING, 2);
  2295. if (*error)
  2296. return 0;
  2297. for (i = 0; i < len; i++) {
  2298. guint32 val = 0;
  2299. if (text->feedback[i] & G_XIM_XIMReverse)
  2300. val |= (1L << 0);
  2301. if (text->feedback[i] & G_XIM_XIMUnderline)
  2302. val |= (1L << 1);
  2303. if (text->feedback[i] & G_XIM_XIMHighlight)
  2304. val |= (1L << 2);
  2305. if (text->feedback[i] & G_XIM_XIMPrimary)
  2306. val |= (1L << 3);
  2307. if (text->feedback[i] & G_XIM_XIMSecondary)
  2308. val |= (1L << 4);
  2309. if (text->feedback[i] & G_XIM_XIMTertiary)
  2310. val |= (1L << 5);
  2311. if (text->feedback[i] & G_XIM_XIMVisibleToForward)
  2312. val |= (1L << 6);
  2313. if (text->feedback[i] & G_XIM_XIMVisibleToBackward)
  2314. val |= (1L << 7);
  2315. if (text->feedback[i] & G_XIM_XIMVisibleToCenter)
  2316. val |= (1L << 8);
  2317. retval += g_xim_protocol_send_format(proto, cancellable, error, 1,
  2318. G_XIM_TYPE_LONG, val);
  2319. if (*error)
  2320. return 0;
  2321. }
  2322. }
  2323. return retval;
  2324. }
  2325. gpointer
  2326. g_xim_text_get_from_stream(GXimProtocol *proto,
  2327. GDataInputStream *stream,
  2328. GCancellable *cancellable,
  2329. GError **error)
  2330. {
  2331. GXimText *retval;
  2332. guint32 mask;
  2333. GString *string;
  2334. guint16 length, i;
  2335. g_return_val_if_fail (G_IS_XIM_PROTOCOL (proto), NULL);
  2336. g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), NULL);
  2337. g_return_val_if_fail (error != NULL, NULL);
  2338. if (!g_xim_protocol_read_format(proto, stream, cancellable, error, 5,
  2339. G_XIM_TYPE_LONG, &mask,
  2340. G_XIM_TYPE_GSTRING, &string,
  2341. G_XIM_TYPE_AUTO_PADDING, 2,
  2342. G_XIM_TYPE_WORD, &length,
  2343. G_XIM_TYPE_PADDING, 2))
  2344. return NULL;
  2345. retval = g_xim_text_new();
  2346. G_XIM_GERROR_CHECK_ALLOC (retval, error,
  2347. G_XIM_PROTOCOL_ERROR, NULL);
  2348. g_xim_text_set_mbstring(retval, string->str, string->len);
  2349. g_string_free(string, TRUE);
  2350. if ((mask & (1L << 1)) == 0) {
  2351. if (length < 4 ||
  2352. (length % 4) != 0) {
  2353. g_xim_messages_warning(G_XIM_PROTOCOL_GET_IFACE (proto)->message,
  2354. "The length of feedback isn't aligned to 4 bytes: %" G_GUINT16_FORMAT,
  2355. length);
  2356. }
  2357. length /= 4;
  2358. } else {
  2359. length = 0;
  2360. }
  2361. for (i = 0; i < length; i++) {
  2362. guint32 val = 0, xval = 0;
  2363. if (!g_xim_protocol_read_format(proto, stream, cancellable, error, 1,
  2364. G_XIM_TYPE_LONG, &val)) {
  2365. length = i;
  2366. G_XIM_GERROR_RESET_NOTICE_FLAG (*error);
  2367. G_XIM_GERROR_SET_NOTICE_FLAG (*error,
  2368. G_XIM_NOTICE_WARNING);
  2369. break;
  2370. }
  2371. if (val & (1L << 0))
  2372. xval |= G_XIM_XIMReverse;
  2373. if (val & (1L << 1))
  2374. xval |= G_XIM_XIMUnderline;
  2375. if (val & (1L << 2))
  2376. xval |= G_XIM_XIMHighlight;
  2377. if (val & (1L << 3))
  2378. xval |= G_XIM_XIMPrimary;
  2379. if (val & (1L << 4))
  2380. xval |= G_XIM_XIMSecondary;
  2381. if (val & (1L << 5))
  2382. xval |= G_XIM_XIMTertiary;
  2383. if (val & (1L << 6))
  2384. xval |= G_XIM_XIMVisibleToForward;
  2385. if (val & (1L << 7))
  2386. xval |= G_XIM_XIMVisibleToBackward;
  2387. if (val & (1L << 8))
  2388. xval |= G_XIM_XIMVisibleToCenter;
  2389. g_xim_text_set_feedback(retval, xval, i);
  2390. }
  2391. if (mask & (1L << 0))
  2392. retval->length = length;
  2393. return retval;
  2394. }
  2395. /* GXimPreeditCaret */
  2396. GType
  2397. g_xim_preedit_caret_get_type(void)
  2398. {
  2399. static volatile gsize type_id_volatile = 0;
  2400. if (g_once_init_enter(&type_id_volatile)) {
  2401. GType type_id;
  2402. type_id = g_boxed_type_register_static(g_intern_static_string("GXimPreeditCaret"),
  2403. g_xim_preedit_caret_copy,
  2404. g_xim_preedit_caret_free);
  2405. g_once_init_leave(&type_id_volatile, type_id);
  2406. }
  2407. return type_id_volatile;
  2408. }
  2409. gpointer
  2410. g_xim_preedit_caret_new(void)
  2411. {
  2412. return g_new0(GXimPreeditCaret, 1);
  2413. }
  2414. gpointer
  2415. g_xim_preedit_caret_copy(gpointer boxed)
  2416. {
  2417. GXimPreeditCaret *retval, *orig;
  2418. if (boxed == NULL)
  2419. return NULL;
  2420. orig = boxed;
  2421. retval = g_xim_preedit_caret_new();
  2422. G_XIM_CHECK_ALLOC (retval, NULL);
  2423. retval->position = orig->position;
  2424. retval->direction = orig->direction;
  2425. retval->style = orig->style;
  2426. return retval;
  2427. }
  2428. void
  2429. g_xim_preedit_caret_free(gpointer boxed)
  2430. {
  2431. g_free(boxed);
  2432. }
  2433. gsize
  2434. g_xim_preedit_caret_put_to_stream(GXimPreeditCaret *caret,
  2435. GXimProtocol *proto,
  2436. GCancellable *cancellable,
  2437. GError **error)
  2438. {
  2439. g_return_val_if_fail (caret != NULL, 0);
  2440. g_return_val_if_fail (G_IS_XIM_PROTOCOL (proto), 0);
  2441. g_return_val_if_fail (error != NULL, 0);
  2442. return g_xim_protocol_send_format(proto, cancellable, error, 3,
  2443. G_XIM_TYPE_LONG, caret->position,
  2444. G_XIM_TYPE_LONG, caret->direction,
  2445. G_XIM_TYPE_LONG, caret->style);
  2446. }
  2447. gpointer
  2448. g_xim_preedit_caret_get_from_stream(GXimProtocol *proto,
  2449. GDataInputStream *stream,
  2450. GCancellable *cancellable,
  2451. GError **error)
  2452. {
  2453. GXimPreeditCaret *retval;
  2454. gint32 position;
  2455. GXimCaretDirection direction;
  2456. GXimCaretStyle style;
  2457. g_return_val_if_fail (G_IS_XIM_PROTOCOL (proto), NULL);
  2458. g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), NULL);
  2459. g_return_val_if_fail (error != NULL, NULL);
  2460. if (!g_xim_protocol_read_format(proto, stream, cancellable, error,
  2461. 3,
  2462. G_XIM_TYPE_LONG, &position,
  2463. G_XIM_TYPE_LONG, &direction,
  2464. G_XIM_TYPE_LONG, &style))
  2465. return NULL;
  2466. retval = g_xim_preedit_caret_new();
  2467. G_XIM_GERROR_CHECK_ALLOC (retval, error,
  2468. G_XIM_PROTOCOL_ERROR, NULL);
  2469. retval->position = position;
  2470. retval->direction = direction;
  2471. retval->style = style;
  2472. return retval;
  2473. }
  2474. /* GXimPreeditDraw */
  2475. GType
  2476. g_xim_preedit_draw_get_type(void)
  2477. {
  2478. static volatile gsize type_id_volatile = 0;
  2479. if (g_once_init_enter(&type_id_volatile)) {
  2480. GType type_id;
  2481. type_id = g_boxed_type_register_static(g_intern_static_string("GXimPreeditDraw"),
  2482. g_xim_preedit_draw_copy,
  2483. g_xim_preedit_draw_free);
  2484. g_once_init_leave(&type_id_volatile, type_id);
  2485. }
  2486. return type_id_volatile;
  2487. }
  2488. gpointer
  2489. g_xim_preedit_draw_new(void)
  2490. {
  2491. return g_new0(GXimPreeditDraw, 1);
  2492. }
  2493. gpointer
  2494. g_xim_preedit_draw_copy(gpointer boxed)
  2495. {
  2496. GXimPreeditDraw *retval, *orig = boxed;
  2497. if (boxed == NULL)
  2498. return NULL;
  2499. retval = g_xim_preedit_draw_new();
  2500. G_XIM_CHECK_ALLOC (retval, NULL);
  2501. retval->text = g_xim_text_copy(orig->text);
  2502. retval->caret = orig->caret;
  2503. retval->chg_first = orig->chg_first;
  2504. retval->chg_length = orig->chg_length;
  2505. return retval;
  2506. }
  2507. void
  2508. g_xim_preedit_draw_free(gpointer boxed)
  2509. {
  2510. GXimPreeditDraw *draw = boxed;
  2511. if (boxed == NULL)
  2512. return;
  2513. g_xim_text_free(draw->text);
  2514. g_free(draw);
  2515. }
  2516. gsize
  2517. g_xim_preedit_draw_put_to_stream(GXimPreeditDraw *draw,
  2518. GXimProtocol *proto,
  2519. GCancellable *cancellable,
  2520. GError **error)
  2521. {
  2522. g_return_val_if_fail (draw != NULL, 0);
  2523. g_return_val_if_fail (G_IS_XIM_PROTOCOL (proto), 0);
  2524. g_return_val_if_fail (error != NULL, 0);
  2525. return g_xim_protocol_send_format(proto, cancellable, error, 4,
  2526. G_XIM_TYPE_LONG, draw->caret,
  2527. G_XIM_TYPE_LONG, draw->chg_first,
  2528. G_XIM_TYPE_LONG, draw->chg_length,
  2529. G_XIM_TYPE_XIMTEXT, draw->text);
  2530. }
  2531. gpointer
  2532. g_xim_preedit_draw_get_from_stream(GXimProtocol *proto,
  2533. GDataInputStream *stream,
  2534. GCancellable *cancellable,
  2535. GError **error)
  2536. {
  2537. GXimPreeditDraw *retval;
  2538. gint32 caret, chg_first, chg_length;
  2539. GXimText *text;
  2540. g_return_val_if_fail (G_IS_XIM_PROTOCOL (proto), NULL);
  2541. g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), NULL);
  2542. g_return_val_if_fail (error != NULL, NULL);
  2543. if (!g_xim_protocol_read_format(proto, stream, cancellable, error, 4,
  2544. G_XIM_TYPE_LONG, &caret,
  2545. G_XIM_TYPE_LONG, &chg_first,
  2546. G_XIM_TYPE_LONG, &chg_length,
  2547. G_XIM_TYPE_XIMTEXT, &text))
  2548. return NULL;
  2549. retval = g_xim_preedit_draw_new();
  2550. G_XIM_GERROR_CHECK_ALLOC (retval, error,
  2551. G_XIM_PROTOCOL_ERROR, NULL);
  2552. retval->caret = caret;
  2553. retval->chg_first = chg_first;
  2554. retval->chg_length = chg_length;
  2555. retval->text = text;
  2556. return retval;
  2557. }
  2558. /* GXimStatusDraw */
  2559. GType
  2560. g_xim_status_draw_get_type(void)
  2561. {
  2562. static volatile gsize type_id_volatile = 0;
  2563. if (g_once_init_enter(&type_id_volatile)) {
  2564. GType type_id;
  2565. type_id = g_boxed_type_register_static(g_intern_static_string("GXimStatusDraw"),
  2566. g_xim_status_draw_copy,
  2567. g_xim_status_draw_free);
  2568. g_once_init_leave(&type_id_volatile, type_id);
  2569. }
  2570. return type_id_volatile;
  2571. }
  2572. gpointer
  2573. g_xim_status_draw_new(void)
  2574. {
  2575. GXimStatusDraw *retval;
  2576. retval = g_new0(GXimStatusDraw, 1);
  2577. return retval;
  2578. }
  2579. gpointer
  2580. g_xim_status_draw_copy(gpointer boxed)
  2581. {
  2582. GXimStatusDraw *retval, *orig = boxed;
  2583. if (boxed == NULL)
  2584. return NULL;
  2585. retval = g_xim_status_draw_new();
  2586. G_XIM_CHECK_ALLOC (retval, NULL);
  2587. switch (orig->type) {
  2588. case G_XIM_XIMTextType:
  2589. retval->data.text = g_xim_text_copy(orig->data.text);
  2590. break;
  2591. case G_XIM_XIMBitmapType:
  2592. retval->data.bitmap = g_object_ref(orig->data.bitmap);
  2593. break;
  2594. default:
  2595. g_xim_status_draw_free(retval);
  2596. return NULL;
  2597. }
  2598. return retval;
  2599. }
  2600. void
  2601. g_xim_status_draw_free(gpointer boxed)
  2602. {
  2603. GXimStatusDraw *draw = boxed;
  2604. if (boxed == NULL)
  2605. return;
  2606. switch (draw->type) {
  2607. case G_XIM_XIMTextType:
  2608. g_xim_text_free(draw->data.text);
  2609. break;
  2610. case G_XIM_XIMBitmapType:
  2611. if (draw->data.bitmap)
  2612. g_object_unref(draw->data.bitmap);
  2613. default:
  2614. break;
  2615. }
  2616. g_free(draw);
  2617. }
  2618. gsize
  2619. g_xim_status_draw_put_to_stream(GXimStatusDraw *draw,
  2620. GXimProtocol *proto,
  2621. GCancellable *cancellable,
  2622. GError **error)
  2623. {
  2624. gsize retval;
  2625. g_return_val_if_fail (draw != NULL, 0);
  2626. g_return_val_if_fail (G_IS_XIM_PROTOCOL (proto), 0);
  2627. g_return_val_if_fail (error != NULL, 0);
  2628. retval = g_xim_protocol_send_format(proto, cancellable, error, 1,
  2629. G_XIM_TYPE_LONG, draw->type);
  2630. if (*error)
  2631. return 0;
  2632. switch (draw->type) {
  2633. case G_XIM_XIMTextType:
  2634. retval += g_xim_protocol_send_format(proto, cancellable, error, 1,
  2635. G_XIM_TYPE_XIMTEXT, draw->data.text);
  2636. break;
  2637. case G_XIM_XIMBitmapType:
  2638. retval += g_xim_protocol_send_format(proto, cancellable, error, 1,
  2639. G_XIM_TYPE_PIXMAP, draw->data.bitmap);
  2640. break;
  2641. default:
  2642. g_set_error(error, G_XIM_PROTOCOL_ERROR,
  2643. G_XIM_STD_ERROR_INVALID_ARGUMENT | G_XIM_NOTICE_BUG,
  2644. "sending an Incomplete status draw object.");
  2645. return 0;
  2646. }
  2647. return retval;
  2648. }
  2649. gpointer
  2650. g_xim_status_draw_get_from_stream(GXimProtocol *proto,
  2651. GDataInputStream *stream,
  2652. GCancellable *cancellable,
  2653. GError **error)
  2654. {
  2655. GXimStatusDraw *retval;
  2656. GXimStatusDataType type = 0;
  2657. g_return_val_if_fail (G_IS_XIM_PROTOCOL (proto), NULL);
  2658. g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), NULL);
  2659. g_return_val_if_fail (error != NULL, NULL);
  2660. if (!g_xim_protocol_read_format(proto, stream, cancellable, error, 1,
  2661. G_XIM_TYPE_LONG, &type))
  2662. return NULL;
  2663. retval = g_xim_status_draw_new();
  2664. G_XIM_GERROR_CHECK_ALLOC (retval, error, G_XIM_PROTOCOL_ERROR, NULL);
  2665. retval->type = type;
  2666. switch (type) {
  2667. case G_XIM_XIMTextType:
  2668. if (!g_xim_protocol_read_format(proto, stream, cancellable, error, 1,
  2669. G_XIM_TYPE_XIMTEXT, &retval->data.text))
  2670. goto fail;
  2671. break;
  2672. case G_XIM_XIMBitmapType:
  2673. if (!g_xim_protocol_read_format(proto, stream, cancellable, error, 1,
  2674. G_XIM_TYPE_PIXMAP, &retval->data.bitmap))
  2675. goto fail;
  2676. break;
  2677. default:
  2678. g_set_error(error, G_XIM_PROTOCOL_ERROR,
  2679. G_XIM_PROTOCOL_ERROR_INVALID_PACKETS_RECEIVED | G_XIM_NOTICE_ERROR,
  2680. "Unknown drawable type %d for status", type);
  2681. fail:
  2682. g_xim_status_draw_free(retval);
  2683. return NULL;
  2684. }
  2685. return retval;
  2686. }
  2687. /* GXimHotkeyTrigger */
  2688. GType
  2689. g_xim_hotkey_trigger_get_type(void)
  2690. {
  2691. static volatile gsize type_id_volatile = 0;
  2692. if (g_once_init_enter(&type_id_volatile)) {
  2693. GType type_id;
  2694. type_id = g_boxed_type_register_static(g_intern_static_string("GXimHotkeyTrigger"),
  2695. g_xim_hotkey_trigger_copy,
  2696. g_xim_hotkey_trigger_free);
  2697. g_once_init_leave(&type_id_volatile, type_id);
  2698. }
  2699. return type_id_volatile;
  2700. }
  2701. gpointer
  2702. g_xim_hotkey_trigger_new(guint32 keysym,
  2703. guint32 modifier,
  2704. guint32 modifier_mask)
  2705. {
  2706. GXimHotkeyTrigger *retval;
  2707. retval = g_new0(GXimHotkeyTrigger, 1);
  2708. G_XIM_CHECK_ALLOC (retval, NULL);
  2709. retval->keysym = keysym;
  2710. retval->modifier = modifier;
  2711. retval->modifier_mask = modifier_mask;
  2712. return retval;
  2713. }
  2714. gpointer
  2715. g_xim_hotkey_trigger_copy(gpointer boxed)
  2716. {
  2717. GXimHotkeyTrigger *orig = boxed;
  2718. if (boxed == NULL)
  2719. return NULL;
  2720. return g_xim_hotkey_trigger_new(orig->keysym,
  2721. orig->modifier,
  2722. orig->modifier_mask);
  2723. }
  2724. void
  2725. g_xim_hotkey_trigger_free(gpointer boxed)
  2726. {
  2727. if (boxed == NULL)
  2728. return;
  2729. g_free(boxed);
  2730. }
  2731. gsize
  2732. g_xim_hotkey_trigger_put_to_stream(GXimHotkeyTrigger *hotkey,
  2733. GXimProtocol *proto,
  2734. GCancellable *cancellable,
  2735. GError **error)
  2736. {
  2737. g_return_val_if_fail (hotkey != NULL, 0);
  2738. g_return_val_if_fail (G_IS_XIM_PROTOCOL (proto), 0);
  2739. g_return_val_if_fail (error != NULL, 0);
  2740. return g_xim_protocol_send_format(proto, cancellable, error, 3,
  2741. G_XIM_TYPE_LONG, hotkey->keysym,
  2742. G_XIM_TYPE_LONG, hotkey->modifier,
  2743. G_XIM_TYPE_LONG, hotkey->modifier_mask);
  2744. }
  2745. gpointer
  2746. g_xim_hotkey_trigger_get_from_stream(GXimProtocol *proto,
  2747. GDataInputStream *stream,
  2748. GCancellable *cancellable,
  2749. GError **error)
  2750. {
  2751. guint32 keysym, modifier, modifier_mask;
  2752. g_return_val_if_fail (G_IS_XIM_PROTOCOL (proto), NULL);
  2753. g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), NULL);
  2754. g_return_val_if_fail (error != NULL, NULL);
  2755. if (!g_xim_protocol_read_format(proto, stream, cancellable, error, 3,
  2756. G_XIM_TYPE_LONG, &keysym,
  2757. G_XIM_TYPE_LONG, &modifier,
  2758. G_XIM_TYPE_LONG, &modifier_mask))
  2759. return NULL;
  2760. return g_xim_hotkey_trigger_new(keysym, modifier, modifier_mask);
  2761. }
  2762. /* GdkEvent */
  2763. GQuark
  2764. g_xim_gdkevent_get_error_quark(void)
  2765. {
  2766. static GQuark quark = 0;
  2767. if (!quark)
  2768. quark = g_quark_from_static_string("g-xim-gdkevent-error");
  2769. return quark;
  2770. }
  2771. gsize
  2772. g_xim_gdkevent_put_to_stream(GdkEvent *event,
  2773. GXimProtocol *proto,
  2774. GCancellable *cancellable,
  2775. GError **error)
  2776. {
  2777. gint xtype;
  2778. gsize size = 0;
  2779. g_return_val_if_fail (event != NULL, 0);
  2780. g_return_val_if_fail (G_IS_XIM_PROTOCOL (proto), 0);
  2781. g_return_val_if_fail (error != NULL, 0);
  2782. /* XXX: better move this into GXimTransport? */
  2783. xtype = g_xim_gdkevent_translate_event_type(event);
  2784. if (xtype == 0) {
  2785. g_set_error(error, G_XIM_GDKEVENT_ERROR,
  2786. G_XIM_GDKEVENT_ERROR_UNSUPPORTED_EVENT | G_XIM_NOTICE_BUG,
  2787. "Unable to convert GdkEvent %d to any X event. this may be a libgxim bug. please report a bug.",
  2788. event->type);
  2789. return 0;
  2790. }
  2791. /* No serial number provided in GdkEvent */
  2792. size = g_xim_protocol_send_format(proto, cancellable, error, 2,
  2793. G_XIM_TYPE_WORD, 0,
  2794. G_XIM_TYPE_BYTE, xtype);
  2795. if (*error)
  2796. return 0;
  2797. switch (event->type) {
  2798. case GDK_DESTROY:
  2799. size += g_xim_protocol_send_format(proto, cancellable, error, 4,
  2800. G_XIM_TYPE_BYTE, 0, /* detail */
  2801. G_XIM_TYPE_WORD, 0, /* serial */
  2802. G_XIM_TYPE_WINDOW, event->any.window,
  2803. G_XIM_TYPE_WINDOW, event->any.window);
  2804. break;
  2805. case GDK_EXPOSE:
  2806. /* XXX: We may need to correct the rectangle area.
  2807. * because GTK+ modifies them.
  2808. */
  2809. size += g_xim_protocol_send_format(proto, cancellable, error, 9,
  2810. G_XIM_TYPE_BYTE, 0, /* detail */
  2811. G_XIM_TYPE_WORD, 0, /* serial */
  2812. G_XIM_TYPE_WINDOW, event->expose.window,
  2813. G_XIM_TYPE_WORD, event->expose.area.x,
  2814. G_XIM_TYPE_WORD, event->expose.area.y,
  2815. G_XIM_TYPE_WORD, event->expose.area.width,
  2816. G_XIM_TYPE_WORD, event->expose.area.height,
  2817. G_XIM_TYPE_WORD, event->expose.count,
  2818. G_XIM_TYPE_PADDING, 2);
  2819. break;
  2820. case GDK_MOTION_NOTIFY:
  2821. /* XXX: GTK+ doesn't deal with a child window. */
  2822. size += g_xim_protocol_send_format(proto, cancellable, error, 13,
  2823. G_XIM_TYPE_BYTE, event->motion.is_hint, /* detail */
  2824. G_XIM_TYPE_WORD, 0, /* serial */
  2825. G_XIM_TYPE_LONG, event->motion.time,
  2826. G_XIM_TYPE_WINDOW, gdk_screen_get_root_window(gdk_display_get_default_screen(gdk_drawable_get_display(event->motion.window))),
  2827. G_XIM_TYPE_WINDOW, event->motion.window,
  2828. G_XIM_TYPE_WINDOW, event->motion.window,
  2829. G_XIM_TYPE_WORD, (gint)event->motion.x_root,
  2830. G_XIM_TYPE_WORD, (gint)event->motion.y_root,
  2831. G_XIM_TYPE_WORD, (gint)event->motion.x,
  2832. G_XIM_TYPE_WORD, (gint)event->motion.y,
  2833. G_XIM_TYPE_WORD, event->motion.state,
  2834. G_XIM_TYPE_BYTE, 1, /* sameScreen */
  2835. G_XIM_TYPE_PADDING, 1);
  2836. break;
  2837. case GDK_BUTTON_PRESS:
  2838. case GDK_2BUTTON_PRESS:
  2839. case GDK_3BUTTON_PRESS:
  2840. case GDK_BUTTON_RELEASE:
  2841. /* XXX: GTK+ doesn't deal with a child window. */
  2842. size += g_xim_protocol_send_format(proto, cancellable, error, 13,
  2843. G_XIM_TYPE_BYTE, event->button.button, /* detail */
  2844. G_XIM_TYPE_WORD, 0, /* serial */
  2845. G_XIM_TYPE_LONG, event->button.time,
  2846. G_XIM_TYPE_WINDOW, gdk_screen_get_root_window(gdk_display_get_default_screen(gdk_drawable_get_display(event->button.window))),
  2847. G_XIM_TYPE_WINDOW, event->button.window,
  2848. G_XIM_TYPE_WINDOW, event->button.window,
  2849. G_XIM_TYPE_WORD, (gint)event->button.x_root,
  2850. G_XIM_TYPE_WORD, (gint)event->button.y_root,
  2851. G_XIM_TYPE_WORD, (gint)event->button.x,
  2852. G_XIM_TYPE_WORD, (gint)event->button.y,
  2853. G_XIM_TYPE_WORD, event->button.state,
  2854. G_XIM_TYPE_BYTE, 1, /* sameScreen */
  2855. G_XIM_TYPE_PADDING, 1);
  2856. break;
  2857. case GDK_KEY_PRESS:
  2858. case GDK_KEY_RELEASE:
  2859. /* XXX: GTK+ doesn't deal with a child window nor positions the event occurred on. */
  2860. size += g_xim_protocol_send_format(proto, cancellable, error, 13,
  2861. G_XIM_TYPE_BYTE, event->key.hardware_keycode, /* detail */
  2862. G_XIM_TYPE_WORD, 0, /* serial */
  2863. G_XIM_TYPE_LONG, event->key.time,
  2864. G_XIM_TYPE_WINDOW, gdk_screen_get_root_window(gdk_display_get_default_screen(gdk_drawable_get_display(event->key.window))),
  2865. G_XIM_TYPE_WINDOW, event->key.window,
  2866. G_XIM_TYPE_WINDOW, event->key.window,
  2867. G_XIM_TYPE_WORD, 0,
  2868. G_XIM_TYPE_WORD, 0,
  2869. G_XIM_TYPE_WORD, 0,
  2870. G_XIM_TYPE_WORD, 0,
  2871. G_XIM_TYPE_WORD, event->key.state,
  2872. G_XIM_TYPE_BYTE, 1, /* sameScreen */
  2873. G_XIM_TYPE_PADDING, 1);
  2874. break;
  2875. case GDK_ENTER_NOTIFY:
  2876. // return EnterNotify;
  2877. case GDK_LEAVE_NOTIFY:
  2878. // return LeaveNotify;
  2879. case GDK_FOCUS_CHANGE:
  2880. // if (event->focus_change.in)
  2881. // return FocusIn;
  2882. // else
  2883. // return FocusOut;
  2884. case GDK_CONFIGURE:
  2885. // return ConfigureNotify;
  2886. case GDK_MAP:
  2887. // return MapNotify;
  2888. case GDK_UNMAP:
  2889. // return UnmapNotify;
  2890. case GDK_PROPERTY_NOTIFY:
  2891. // return PropertyNotify;
  2892. case GDK_SELECTION_CLEAR:
  2893. // return SelectionClear;
  2894. case GDK_SELECTION_REQUEST:
  2895. // return SelectionRequest;
  2896. case GDK_SELECTION_NOTIFY:
  2897. // return SelectionNotify;
  2898. case GDK_CLIENT_EVENT:
  2899. // return ClientMessage;
  2900. case GDK_VISIBILITY_NOTIFY:
  2901. // return VisibilityNotify;
  2902. case GDK_NO_EXPOSE:
  2903. // return NoExpose;
  2904. case GDK_SCROLL:
  2905. // return ButtonPress;
  2906. default:
  2907. g_set_error(error, G_XIM_GDKEVENT_ERROR,
  2908. G_XIM_GDKEVENT_ERROR_UNSUPPORTED_EVENT | G_XIM_NOTICE_BUG,
  2909. "Not yet implemented for the event type %d",
  2910. event->type);
  2911. break;
  2912. }
  2913. if (*error)
  2914. size = 0;
  2915. return size;
  2916. }
  2917. gpointer
  2918. g_xim_gdkevent_get_from_stream(GXimProtocol *proto,
  2919. GDataInputStream *stream,
  2920. GCancellable *cancellable,
  2921. GError **error)
  2922. {
  2923. GXimProtocolIface *iface;
  2924. guint16 msb_serial, lsb_serial;
  2925. gint xtype = 0;
  2926. GdkEventType type;
  2927. GdkEvent *retval;
  2928. g_return_val_if_fail (G_IS_XIM_PROTOCOL (proto), NULL);
  2929. g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), NULL);
  2930. g_return_val_if_fail (error != NULL, NULL);
  2931. if (!g_xim_protocol_read_format(proto, stream, cancellable, error, 2,
  2932. G_XIM_TYPE_WORD, &msb_serial,
  2933. G_XIM_TYPE_BYTE, &xtype))
  2934. return NULL;
  2935. iface = G_XIM_PROTOCOL_GET_IFACE (proto);
  2936. g_xim_messages_debug(iface->message, "proto/gdkevent",
  2937. "Event type: %s", g_xim_gdkevent_type_name(xtype));
  2938. type = g_xim_xevent_translate_event_type(xtype);
  2939. retval = gdk_event_new(type);
  2940. G_XIM_GERROR_CHECK_ALLOC (retval, error,
  2941. G_XIM_PROTOCOL_ERROR, NULL);
  2942. switch (type) {
  2943. case GDK_DESTROY:
  2944. G_STMT_START {
  2945. GdkWindow *ev, *window;
  2946. if (!g_xim_protocol_read_format(proto, stream, cancellable, error, 4,
  2947. G_XIM_TYPE_PADDING, 1, /* detail(unused) */
  2948. G_XIM_TYPE_WORD, &lsb_serial, /* serial */
  2949. G_XIM_TYPE_WINDOW, &ev,
  2950. G_XIM_TYPE_WINDOW, &window))
  2951. goto end;
  2952. if (ev != window) {
  2953. /* we don't deal with it */
  2954. g_set_error(error, G_XIM_PROTOCOL_ERROR,
  2955. G_XIM_PROTOCOL_ERROR_INVALID_PACKETS_RECEIVED | G_XIM_NOTICE_ERROR,
  2956. "Received different window for DestroyNotify: event: %p, window: %p",
  2957. G_XIM_NATIVE_WINDOW_TO_POINTER (GDK_WINDOW_XID (ev)),
  2958. G_XIM_NATIVE_WINDOW_TO_POINTER (GDK_WINDOW_XID (window)));
  2959. goto end;
  2960. }
  2961. retval->any.window = g_object_ref(ev);
  2962. } G_STMT_END;
  2963. break;
  2964. case GDK_EXPOSE:
  2965. G_STMT_START {
  2966. GdkWindow *window;
  2967. gint16 x, y, width, height, count;
  2968. if (!g_xim_protocol_read_format(proto, stream, cancellable, error, 9,
  2969. G_XIM_TYPE_PADDING, 1, /* detail(unused) */
  2970. G_XIM_TYPE_WORD, &lsb_serial, /* serial */
  2971. G_XIM_TYPE_WINDOW, &window,
  2972. G_XIM_TYPE_WORD, &x,
  2973. G_XIM_TYPE_WORD, &y,
  2974. G_XIM_TYPE_WORD, &width,
  2975. G_XIM_TYPE_WORD, &height,
  2976. G_XIM_TYPE_WORD, &count,
  2977. G_XIM_TYPE_PADDING, 2))
  2978. goto end;
  2979. retval->expose.window = g_object_ref(window);
  2980. retval->expose.area.x = x;
  2981. retval->expose.area.y = y;
  2982. retval->expose.area.width = width;
  2983. retval->expose.area.height = height;
  2984. retval->expose.count = count;
  2985. } G_STMT_END;
  2986. break;
  2987. case GDK_MOTION_NOTIFY:
  2988. G_STMT_START {
  2989. gint16 is_hint = 0, x_root, y_root, x, y;
  2990. guint16 state;
  2991. guint32 time;
  2992. GdkWindow *root, *ev, *window;
  2993. gboolean same_screen = FALSE;
  2994. if (!g_xim_protocol_read_format(proto, stream, cancellable, error, 13,
  2995. G_XIM_TYPE_BYTE, &is_hint, /* detail */
  2996. G_XIM_TYPE_WORD, &lsb_serial, /* serial */
  2997. G_XIM_TYPE_LONG, &time,
  2998. G_XIM_TYPE_WINDOW, &root,
  2999. G_XIM_TYPE_WINDOW, &ev,
  3000. G_XIM_TYPE_WINDOW, &window,
  3001. G_XIM_TYPE_WORD, &x_root,
  3002. G_XIM_TYPE_WORD, &y_root,
  3003. G_XIM_TYPE_WORD, &x,
  3004. G_XIM_TYPE_WORD, &y,
  3005. G_XIM_TYPE_WORD, &state,
  3006. G_XIM_TYPE_BYTE, &same_screen,
  3007. G_XIM_TYPE_PADDING, 1))
  3008. goto end;
  3009. if (!same_screen) {
  3010. g_set_error(error, G_XIM_GDKEVENT_ERROR,
  3011. G_XIM_GDKEVENT_ERROR_UNSUPPORTED_EVENT | G_XIM_NOTICE_ERROR,
  3012. "Event %d occurred on the different screen.",
  3013. type);
  3014. goto end;
  3015. }
  3016. retval->motion.window = g_object_ref(ev);
  3017. retval->motion.time = time;
  3018. retval->motion.x = x;
  3019. retval->motion.y = y;
  3020. retval->motion.state = state;
  3021. retval->motion.is_hint = is_hint;
  3022. retval->motion.x_root = x_root;
  3023. retval->motion.y_root = y_root;
  3024. retval->motion.axes = NULL;
  3025. retval->motion.device = gdk_drawable_get_display(ev)->core_pointer;
  3026. } G_STMT_END;
  3027. break;
  3028. case GDK_BUTTON_PRESS:
  3029. case GDK_BUTTON_RELEASE:
  3030. G_STMT_START {
  3031. guint16 button = 0, state;
  3032. gint16 x_root, y_root, x, y;
  3033. guint32 time;
  3034. GdkWindow *root, *ev, *window;
  3035. gboolean same_screen = FALSE;
  3036. if (!g_xim_protocol_read_format(proto, stream, cancellable, error, 13,
  3037. G_XIM_TYPE_BYTE, &button, /* detail */
  3038. G_XIM_TYPE_WORD, &lsb_serial, /* serial */
  3039. G_XIM_TYPE_LONG, &time,
  3040. G_XIM_TYPE_WINDOW, &root,
  3041. G_XIM_TYPE_WINDOW, &ev,
  3042. G_XIM_TYPE_WINDOW, &window,
  3043. G_XIM_TYPE_WORD, &x_root,
  3044. G_XIM_TYPE_WORD, &y_root,
  3045. G_XIM_TYPE_WORD, &x,
  3046. G_XIM_TYPE_WORD, &y,
  3047. G_XIM_TYPE_WORD, &state,
  3048. G_XIM_TYPE_BYTE, &same_screen,
  3049. G_XIM_TYPE_PADDING, 1))
  3050. goto end;
  3051. if (!same_screen) {
  3052. g_set_error(error, G_XIM_GDKEVENT_ERROR,
  3053. G_XIM_GDKEVENT_ERROR_UNSUPPORTED_EVENT | G_XIM_NOTICE_ERROR,
  3054. "Event %d occurred on the different screen.",
  3055. type);
  3056. goto end;
  3057. }
  3058. retval->button.window = g_object_ref(ev);
  3059. retval->button.time = time;
  3060. retval->button.x = x;
  3061. retval->button.y = y;
  3062. retval->button.state = state;
  3063. retval->button.button = button;
  3064. retval->button.x_root = x_root;
  3065. retval->button.y_root = y_root;
  3066. retval->button.axes = NULL;
  3067. retval->button.device = gdk_drawable_get_display(ev)->core_pointer;
  3068. } G_STMT_END;
  3069. break;
  3070. case GDK_KEY_PRESS:
  3071. case GDK_KEY_RELEASE:
  3072. G_STMT_START {
  3073. guint16 keycode = 0, state;
  3074. gint16 x_root, y_root, x, y;
  3075. guint32 time;
  3076. GdkWindow *root, *ev, *window;
  3077. gboolean same_screen = FALSE;
  3078. GdkDisplay *dpy;
  3079. GdkKeymap *keymap;
  3080. gunichar c = 0;
  3081. gchar buf[7];
  3082. if (!g_xim_protocol_read_format(proto, stream, cancellable, error, 13,
  3083. G_XIM_TYPE_BYTE, &keycode, /* detail */
  3084. G_XIM_TYPE_WORD, &lsb_serial, /* serial */
  3085. G_XIM_TYPE_LONG, &time,
  3086. G_XIM_TYPE_WINDOW, &root,
  3087. G_XIM_TYPE_WINDOW, &ev,
  3088. G_XIM_TYPE_WINDOW, &window,
  3089. G_XIM_TYPE_WORD, &x_root,
  3090. G_XIM_TYPE_WORD, &y_root,
  3091. G_XIM_TYPE_WORD, &x,
  3092. G_XIM_TYPE_WORD, &y,
  3093. G_XIM_TYPE_WORD, &state,
  3094. G_XIM_TYPE_BYTE, &same_screen,
  3095. G_XIM_TYPE_PADDING, 1))
  3096. goto end;
  3097. if (!same_screen) {
  3098. g_set_error(error, G_XIM_GDKEVENT_ERROR,
  3099. G_XIM_GDKEVENT_ERROR_UNSUPPORTED_EVENT | G_XIM_NOTICE_ERROR,
  3100. "Event %d occurred on the different screen.",
  3101. type);
  3102. goto end;
  3103. }
  3104. dpy = gdk_drawable_get_display(ev);
  3105. keymap = gdk_keymap_get_for_display(dpy);
  3106. retval->key.window = g_object_ref(ev);
  3107. retval->key.time = time;
  3108. retval->key.state = state;
  3109. retval->key.hardware_keycode = keycode;
  3110. // retval->key.group =;
  3111. retval->key.keyval = GDK_VoidSymbol;
  3112. /* borrow code from gdkevents-x11.c */
  3113. gdk_keymap_translate_keyboard_state(keymap,
  3114. retval->key.hardware_keycode,
  3115. retval->key.state,
  3116. retval->key.group,
  3117. &retval->key.keyval,
  3118. NULL, NULL, NULL);
  3119. // retval->key.is_modifier =;
  3120. retval->key.string = NULL;
  3121. if (retval->key.keyval != GDK_VoidSymbol)
  3122. c = gdk_keyval_to_unicode(retval->key.keyval);
  3123. if (c) {
  3124. gsize bytes_written;
  3125. gint len;
  3126. /* Apply the control key - Taken from Xlib
  3127. */
  3128. if (retval->key.state & GDK_CONTROL_MASK) {
  3129. if ((c >= '@' && c < '\177') || c == ' ') {
  3130. c &= 0x1F;
  3131. } else if (c == '2') {
  3132. retval->key.string = g_memdup ("\0\0", 2);
  3133. retval->key.length = 1;
  3134. buf[0] = '\0';
  3135. goto end;
  3136. } else if (c >= '3' && c <= '7') {
  3137. c -= ('3' - '\033');
  3138. } else if (c == '8') {
  3139. c = '\177';
  3140. } else if (c == '/') {
  3141. c = '_' & 0x1F;
  3142. }
  3143. }
  3144. len = g_unichar_to_utf8 (c, buf);
  3145. buf[len] = '\0';
  3146. retval->key.string = g_locale_from_utf8 (buf, len,
  3147. NULL, &bytes_written,
  3148. NULL);
  3149. if (retval->key.string)
  3150. retval->key.length = bytes_written;
  3151. } else if (retval->key.keyval == GDK_Escape) {
  3152. retval->key.length = 1;
  3153. retval->key.string = g_strdup ("\033");
  3154. } else if (retval->key.keyval == GDK_Return ||
  3155. retval->key.keyval == GDK_KP_Enter) {
  3156. retval->key.length = 1;
  3157. retval->key.string = g_strdup ("\r");
  3158. }
  3159. if (!retval->key.string) {
  3160. retval->key.length = 0;
  3161. retval->key.string = g_strdup ("");
  3162. }
  3163. } G_STMT_END;
  3164. break;
  3165. default:
  3166. g_set_error(error, G_XIM_GDKEVENT_ERROR,
  3167. G_XIM_GDKEVENT_ERROR_UNSUPPORTED_EVENT | G_XIM_NOTICE_BUG,
  3168. "Noet yet implemented for the event type %d",
  3169. type);
  3170. break;
  3171. }
  3172. end:
  3173. if (*error) {
  3174. if (!G_XIM_GERROR_IS_RECOVERABLE (*error)) {
  3175. gdk_event_free(retval);
  3176. retval = NULL;
  3177. }
  3178. }
  3179. return retval;
  3180. }