PageRenderTime 69ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 1ms

/modules/clx/new-clx/clx.f

https://github.com/ynd/clisp-branch--ynd-devel
FORTRAN Legacy | 8276 lines | 7155 code | 885 blank | 236 comment | 487 complexity | eebc37146486bb3f5d8a83c02c77d45a MD5 | raw file
Possible License(s): LGPL-2.0, GPL-2.0, BSD-3-Clause

Large files files are truncated, but you can click here to view the full file

  1. /* -*- C -*- vim:filetype=c
  2. Copyright (c) 1996-1999 by Gilbert Baumann, distributed under GPL
  3. Bruno Haible 1998-2000
  4. Sam Steingold 2001-2008
  5. ----------------------------------------------------------------------------
  6. Title: C implementation of CLX utilizing the Xlib
  7. Created: Sat Dec 2 18:04:51 1995
  8. Author: Gilbert Baumann <unk6@rz.uni-karlsruhe.de>
  9. Copying: (c) copyright 1996 by Gilbert Baumann distributed under GPL.
  10. ----------------------------------------------------------------------------
  11. Revision 1.24 1999-10-17 bruno
  12. - Use allocate_bit_vector in place of allocate_byte_vector. Remove ->data
  13. indirection.
  14. Revision 1.23 1999-10-11 gilbert
  15. - get_font_info_and_display: XGetAtomNames is a new X11R6 addition, use
  16. XGetAtomName instead.
  17. Revision 1.22 1999-06-06 bruno
  18. - get_font_info_and_display now optionally returns the Lisp font.
  19. It also fills in the font's encoding.
  20. - New function to_XChar2b, used to convert a character sequence to a font
  21. index sequence. Works for linear non-iso8859-1 fonts (unlike Motif!).
  22. Still needs work for chinese or japanese fonts.
  23. Revision 1.21 1999-05-30 bruno
  24. - Add missing begin_callback() in `xlib_io_error_handler'.
  25. - Save subr_self during some calls in xlib:change-property.
  26. - Fix some obvious typos in `font_char_info'.
  27. - Call XFree() when done with the result of XGetAtomName().
  28. - Improved error handling in `get_font_info_and_display'.
  29. Revision 1.20 1999-04-04 bruno
  30. - Modifications for UNICODE.
  31. Revision 1.19 1998-10-19 bruno
  32. - Use the macro `nonreturning_function', not `nonreturning'.
  33. Revision 1.18 1997-06-22 bruno
  34. - replace first preprocessing with CCMP2C; then only comments need to be
  35. stripped before e2d can be applied.
  36. - compilation in WIDE mode works now (use `eq', not `==' to compare objects)
  37. - fixed buggy ESLOT4 macro (make_xatom wants a `Display*', not an `object')
  38. - DYNAMIC_ARRAY has 3 arguments since 1996-07-22
  39. - allocate_byte_array is now exported from array.d
  40. - typos and spaces here and there
  41. Revision 1.18 1997/06/12 00:23:35 gilbert
  42. - nothing special
  43. Revision 1.17 1997/06/02 16:19:27 gilbert
  44. - Lots of minor tweeks here and there
  45. - First attempt to get the IMAGE implementation right
  46. - Found memory leak in font handling code
  47. - fixed bug in xpm::read-pixmap-from-file occured when shape-mask-p = t
  48. - (xlib:open-display "localhost") works now
  49. Revision 1.16 1996/10/11 14:18:03 gilbert
  50. - Some tweakings to get it smoother compiled under 07-22
  51. Revision 1.15 1996/10/11 10:15:52 gilbert
  52. - removed all GETTEXTs because it does not compile on 07-22
  53. - error hander now calls the Lisp error handler
  54. - fixed invokation of DYNAMIC_ARRAY
  55. - removed all 'reg?' decls
  56. - lots of bug fixes
  57. - changed outlook of xlib:%restore-gcontext-components.
  58. - the clip mask and the dash list are now retrievable from a gcontext
  59. So the gcontext chapter should be complete now. [sans cache-p]
  60. Revision 1.14 1996/10/09 09:03:42 gilbert
  61. - lots of bug fixes
  62. - changed outlook of xlib:%restore-gcontext-components.
  63. - the clip mask and the dash list are now retrievable from a gcontext
  64. So the gcontext chapter should be complete now. [sans cache-p]
  65. Revision 1.13 1996/10/05 01:00:50 gilbert
  66. - begin_call / end_call should be finally added everwhere..
  67. - fixed some serve bugs in XLIB:CHANGE-PROPERTY.
  68. - providing {WINDOW,PIXMAP,DRAWABLE,FONT,COLORMAP}-LOOKUP
  69. Revision 1.12 1996/10/04 03:14:53 gilbert
  70. - Introduced new macro 'STANDARD_XID_OBJECT_LOOK'.
  71. - The {WINDOW,PIXMAP,DRAWABLE,FONT,COLORMAP}-{DISPLAY,PLIST,PLIST-SETTER,ID}
  72. functions now do proper type checking.
  73. The corresponding xx-EQUAL functions are based on the XID alone.
  74. Same needs to be done for PTR objects.
  75. - The silly (and ineffient) 'general_p' function vanished.
  76. Revision 1.11 1996/10/03 03:37:12 gilbert
  77. - all invocations of "TheFpointer()->fp_pointer"
  78. are now guarded by "fp_validp".
  79. Revision 1.10 1996/10/03 02:45:00 gilbert
  80. - made the get_[su]int?? functions do type checking
  81. - Got rid of get_string and get_stringable.
  82. Revision 1.9 1996/10/02 10:39:45 gilbert
  83. - eliminated get_xatom_name due to GC vulnerability.
  84. - got rid of most get_string due to the same reason
  85. - as always some begin/end_calls added.
  86. Revision 1.8 1996/09/28 21:59:02 gilbert
  87. - Only lots of code movements to gather stuff which belongs together
  88. also to appear together for better maintainability.
  89. Revision 1.7 1996/09/28 20:52:24 gilbert
  90. - Redone the invoke stuff, because
  91. YOU HAVE TO SAVE YOUR FILE BEFORE YOU CHECK IT IN!
  92. [Emacs does not check this 8-{ Realy angry! $%^#@#%$@ ]
  93. Revision 1.6 1996/09/28 20:41:23 gilbert
  94. - added type checking to get_{xid,ptr}_object
  95. - got rid of display_of all now done with the get_foo_and_display
  96. functions, so get_font_info is now called get_font_info_and_display.
  97. - also get rid of the 'invoke' function, it was considered too
  98. unportable.
  99. Revision 1.5 1996/09/28 01:45:06 gilbert
  100. Converted all enum definitions into the DEF_ENUM macro for code size.
  101. Revision 1.4 1996/09/27 12:48:33 gilbert
  102. Cleaned up event disassembling code
  103. Revision 1.3 1996/08/02 10:51:40 gilbert
  104. Only for Bruno.
  105. Revision 1.2 1996/07/27 02:25:31 gilbert
  106. *** empty log message ***
  107. Revision 1.1 1996/07/08 15:47:43 gilbert
  108. Initial revision
  109. ^^^ That is not true! Coding this started actually in Dec 1995.
  110. (Just around a couple of days befor chrismas?)
  111. */
  112. /* --- TODO ---
  113. - fake the REPORT-ASYNCHRONOUS-ERRORS slot on displays.
  114. - Garnet seems to loose exposure events from time to time, I do not know
  115. if it is my fault or a garnet bug? This thing is hard to trace, since
  116. it seems to depend on how fast the window gets mapped, or how fast the
  117. garnet code is!
  118. - the get_XXX functions *all* should do type checking
  119. - Most uses of 'fixnum' are wrong, since the actual type is somewhat more
  120. precise known. fixnums are only correct as indexes into sequences and
  121. such!
  122. -------
  123. When passing #<XLIB:GCONTEXT #x00000160> to FONT-ASCENT it says:
  124. "Error: XLIB:FONT-ASCENT: NIL is not of type XLIB:FONT"
  125. Why is two way wrong:
  126. a. A gcontext should be ok where a font is
  127. b. Why is dumped NIL and not the gcontext?
  128. O.k. this was due to the fact that the font was actually never set.
  129. fix that!
  130. (Maybe we just pass the gcontext down to Xlib, since Xlib is supposed
  131. to do the same here.)
  132. -------
  133. When a display is closed the host name and such sould not
  134. be available any longer
  135. -------
  136. - there should be a function called closed-p, which checks wether an given
  137. xid or ptr object is closed or not. When re-incarnating CLISP all CLX
  138. objects should get closed. get_xxx functions should check on that. But
  139. there a some nasty problems:
  140. a.) when I setup the XFree... request it is not yet at the server
  141. b.) There may be additional references in the servers queque.
  142. Maybe I open a pseudo window, just for sneeking for destruction events?
  143. - XLIB:TEXT-EXTENTS and XLIB:TEXT-WIDTH needs fixing for non simple
  144. string arguments.
  145. - Garnet accidentally used :on/:off for save under values
  146. [But only sometimes]
  147. - Scan for all funcalls and save subr_self prior to call.
  148. - Is it right that we make the list of displays public?
  149. - we should rethink a bit more the font handling stuff, because several
  150. situations could arise:
  151. . A font may not have an fid, this implies, that the font could not be
  152. hashed, furthermore we should init a finializer to discard also the
  153. fontinfo when the font object becomes inaccessible.
  154. . A font may come without per-character information.
  155. (But only when it has a 0 font id, hence a pseudo font)
  156. . If we open a pseudo font, we should then enter it into the hash table.
  157. . ensure that the font-name slot has some valid value.
  158. (It is even not guaranteed to be available.)
  159. - go thru' the whole source and find all error messages and check that they
  160. are given right. [error wants its arguments backwards!]
  161. - since some make_xxx functions use value1, I should generally push the
  162. return values onto the stack before actually returning.
  163. - since somebody could now create classes on top of window, check the xid we
  164. want to read, if it is unbound emit some reasonable error message. [If it
  165. is unbound the slot-value function returns an error on its own already.]
  166. - What about the plist slot? (Should we bind it to a useful value?)
  167. - maybe we make the clos-instance representation optional? Since it eats
  168. some speed. (Fetching a slot value is not the fastest operation.)
  169. - several X11 functions, which return lists may actually pass NULL as the
  170. empty sequence?!
  171. - some of the enumerating functions (list XListDepths etc) do not set the
  172. count_return on failure, so set it yourself to 0 before you make the call,
  173. so that we do not run into difficulties.
  174. - Maybe we dont put all those symbols in the XLIB package to be able to
  175. include the MIT-CLX also. (Generally CLISP lacks some of the nice package
  176. features Symbolics Common LISP provided. There were also anonymous or
  177. invisible packages.)
  178. - errors should be reported in a much more meaningful way.
  179. - the big export list in clx.lisp seems to export some superfluous symbols.
  180. - put also ptr objects into the hashtable.
  181. Is there any way to get 'em anyhow back?
  182. - the xlib:free-xxx routines should remove that object from the hashtable.
  183. (or shouldn`t they?) What does the Xserver with free`ed objects?
  184. And also they might be still alive, if some other application uses it.
  185. [Well simply take a look at the MIT code.] [What about GC?!]
  186. - should DISPLAY be a class? What with VISUAL-INFO, COLOR an so on ...
  187. - We should really make DISPLAY-AFTER-FUNCTION to live.
  188. The is also a XAfterFunction or something like that on the C side of life.
  189. - What exactly is a drawable? a type? a class?
  190. - We should insert a lot more type checks?
  191. - Since type checks are rather expensive think about listening to SAFTY and
  192. SPEED ...
  193. */
  194. /* --- DONE ----
  195. - some functions emit errors saying #xDDD using decimal notation!
  196. - upon disconnection we simply get a broken pipe message and exit
  197. [This is not the disired way, since we want to handle such an error.]
  198. - with-gcontext !!!
  199. - rename the 'font-name' slot of font to 'name'.
  200. - take a look at the CLUE code, what it does with the :xxx option to
  201. create-xxx functions?!
  202. - DISPLAY-AFTER-FUNCTION setter is needed.
  203. - make display/window/pixmap clos-instances (see the CLUE patches for that)
  204. - put xids into the hashtable and do not build the object new on each
  205. request.
  206. - plists (partly done)
  207. - get_visual
  208. - how to proceed with visuals? In CLX a visual is just a card29 in CLX it is
  209. a pointer to a structure.
  210. - Together with the CLX implementation should go a wholine implementation.
  211. (partly there)
  212. */
  213. /* --- NOTE ---
  214. This package is not actually optimized for speed, since my intent and BTW
  215. the overall intent of CLISP is to make the whole beast small.
  216. (Actually you gain speed due to reduced paging).
  217. Also this code is at some places BFI!
  218. The general idea behind writing this bunch of code, is to provide a CLX
  219. implementation for CLISP, which is feasible of both speed and space. I
  220. actually use the libX library, because if you want to do graphics on your
  221. machine, you will already have it in memory, so it adds no extra cost. [One
  222. disadvantage is that I am forced in some places to go into the internals of
  223. the libX, since the CLX specification is more powerful at some places than
  224. the libX implementation. This add another source of in-portability of CLISP,
  225. so *please*, if you encounter compilation problems mail me,
  226. so I could adjust the code ...]
  227. CLX adds on my machines another ~700k of memory needs for CLISP, but this
  228. implementation add only 70k [*I* know that I am telling lies here, since the
  229. libX11 itself has a size of ~500k; But as long as I have no pure LISP OS but
  230. need the UNIX to boot it ...] and a great bunch of speed.
  231. Also having this implemenation should gain a big plus against GCL. (IMHO
  232. gcl is very bad code compared to CLISP! [gcl is actually akcl]) flame,flame.
  233. BTW It should be fun to write the graph.d routines on top of CLX!
  234. */
  235. /* --- FUTURE ---
  236. Xpm Support?
  237. We should also include support for the xpm library to have a nice access to
  238. .xpm files, which is hardly needed, since I do not want to duplicate this
  239. non-trivial code in Lisp. But we have to think about a Lisp representation
  240. for pixmaps. I could also imagine a `defpixmap` macro. Just another
  241. question is if we want to put the xpm routines into another package. (called
  242. `x-pixmap` or just 'xpm'). I want also to write some documentation for the
  243. then Lisp xpm routines. But since the xpm library seems to be a changing
  244. thing it is also a question, how we cope with them.
  245. Incorporation into the FFI?
  246. Since we use could convert now a WINDOW object into a libX11 Window object,
  247. it may be worth offer this also to the FFI. When I finished this work I
  248. should take a look at the FFI.
  249. */
  250. /* --- IMPLEMENTATION NOTES ---------------------------------------------------
  251. The following types are only XID`s:
  252. window, drawable, font, pixmap, cursor, colormap, GContext, keysym
  253. No XID, but data-structures:
  254. color, display, screen, GC
  255. First I define some data types by providing get_xxx, make_xxx and xxx_p
  256. functions. Note that this set is not complete, since not all functions are
  257. actually needed. The consistent name is crucial, since some macros I define
  258. later take a "type" argument, which is concatenated with 'make_' or 'get_'.
  259. This is done to make this file more dense; (Thus save me a lot of redundant
  260. typing.)
  261. type | dpy? | XID-P | hashed-p | Note
  262. ----------+------+-------+----------+------------------------------
  263. GCONTEXT | T | NIL | NIL | Is really a pointer
  264. WINDOW | T | T | T |
  265. PIXMAP | T | T | T |
  266. CURSOR | T | T | T |
  267. COLORMAP | T | T | T |
  268. FONT | T | T/NIL | T/NIL |
  269. SCREEN | T | NIL | (should | Could also been represented as index?
  270. | | | be) |
  271. DISPLAY | NIL | NIL | NIL |
  272. Class Hierarchy
  273. --------------------
  274. xlib-object --+--> xid-object --+--> DRAWABLE -+--> WINDOW
  275. | | +--> PIXMAP
  276. | |--> CURSOR
  277. | +--> COLORMAP
  278. | +--> FONT
  279. |
  280. +--> ptr-object --+--> GCONTEXT
  281. |
  282. +--> DISPLAY
  283. Just in case you prefer a textual representation:
  284. (defclass xlib-object () (plist display))
  285. (defclass xid-object (xlib-object) (xid))
  286. (defclass ptr-object (xlib-object) (ptr))
  287. (defclass drawable (xid-object) ())
  288. (defclass window (drawable) ())
  289. (defclass pixmap (drawable) ())
  290. (defclass cursor (xid-object) ())
  291. (defclass colormap (xid-object) ())
  292. (defclass gcontext (ptr-object) ())
  293. (defclass display (ptr-object) ())
  294. (defclass font (xid-object) (font-info name))
  295. */
  296. /* -- NOTE --
  297. For further for grepability I use the following tags in comments:
  298. XXX - really bad and a major risk to safety/usability.
  299. FIXME - just fix me, something that ought to be done
  300. before next release.
  301. TODO - something, which should be done and is already
  302. considered useful.
  303. FUTURE - something which is just an idea and it is not yet
  304. decided, if I ever implement it; It may also later
  305. be considered silly.
  306. I welcome discussion about those items.
  307. OK - the opposite of XXX. Functions which are
  308. considered to be totally finished and
  309. had undergone a test are marked with this.
  310. UNDEFINED - this is thought for undefined functions at whole
  311. NOTIMPLEMENTED - is thought for not implemented features
  312. in an partly defined function.
  313. */
  314. /* enough bla bla, let's start coding, we have a long long way before us ...*/
  315. #include "clisp.h"
  316. #include <X11/Xlib.h>
  317. #include <X11/Xutil.h> /* XGetVisualInfo */
  318. #include <X11/Xcms.h> /* forXcmsCCCOfColormap() & XcmsVisualOfCCC() */
  319. #include <X11/Xauth.h>
  320. /* #include <X11/Xresource.h> */
  321. #include <stdio.h> /* sprintf() */
  322. #include <string.h> /* memcpy(), strchr(), strcpy() */
  323. #include "config.h"
  324. #if defined(TIME_WITH_SYS_TIME)
  325. # include <sys/time.h>
  326. # include <time.h>
  327. #else
  328. # if defined(HAVE_SYS_TIME_H)
  329. # include <sys/time.h>
  330. # elif defined(HAVE_TIME_H)
  331. # include <time.h>
  332. # endif
  333. #endif
  334. #if defined(HAVE_SYS_SOCKET_H)
  335. # include <sys/socket.h>
  336. #endif
  337. #if defined(HAVE_NETDB_H)
  338. # include <netdb.h>
  339. #endif
  340. #if defined(HAVE_NETINET_IN_H)
  341. # include <netinet/in.h>
  342. #endif
  343. ##if WANT_XSHAPE
  344. /* must include this before DEFMODULE so that DEFCHECKER will work */
  345. #include <X11/extensions/shape.h>
  346. ##endif
  347. #define DEBUG_CLX 0
  348. #ifndef FOREIGN
  349. #error FOREIGN is not defined.
  350. #error CLX needs a CLISP built with the foreign pointer datatype support.
  351. #error Go into the main CLISP makefile and add a -DFOREIGN=void*
  352. #error to CFLAGS make variable and rebuild CLISP before coming back here.
  353. #endif
  354. DEFMODULE(clx,"XLIB")
  355. /* ... But first we provide some prototypes for functions, which maybe worth
  356. included in libX11 and are defined at the end of this file. */
  357. /* might also been called XVisualIDFromVisual**(-1) : */
  358. static Visual *XVisualIDToVisual (Display *dpy, VisualID vid);
  359. /* Find the screen index from a Screen* : */
  360. static int XScreenNo (Display *dpy, Screen *screen);
  361. /* our own forward declaration */
  362. static Display *pop_display (void);
  363. static inline Display *get_display (object dpy)
  364. { pushSTACK(dpy); return pop_display(); }
  365. /* Some fix-ups: */
  366. #define NOTIMPLEMENTED NOTREACHED
  367. #define UNDEFINED NOTIMPLEMENTED
  368. /* debug */
  369. #if DEBUG_CLX
  370. #define dprintf(x) do{ printf x; fflush(stdout); }while(0)
  371. #else
  372. #define dprintf(x) do{}while(0)
  373. #endif
  374. /* it is not clear whether we can rely on `writing_to_subprocess' or
  375. must actually disable SIGPIPE - see src/spvw_sigpipe.d */
  376. #define RELY_ON_WRITING_TO_SUBPROCESS
  377. #if defined(RELY_ON_WRITING_TO_SUBPROCESS)
  378. /* including <signal.h> just for the sake of SIGPIPE
  379. (which is always there anyway) is a total waste */
  380. # if defined(HAVE_SIGNALS) /* && defined(SIGPIPE) */
  381. extern
  382. # endif
  383. bool writing_to_subprocess;
  384. # define begin_x_call() writing_to_subprocess=true;begin_call()
  385. # define end_x_call() end_call();writing_to_subprocess=false
  386. #else
  387. # define begin_x_call() begin_call()
  388. # define end_x_call() end_call()
  389. extern void disable_sigpipe(void);
  390. #endif
  391. #define X_CALL(f) do{ begin_x_call(); f; end_x_call(); }while(0)
  392. /* -------------------------------------------------------------------------
  393. * General purpose utilities
  394. * ------------------------------------------------------------------------- */
  395. /* sugar for funcall (used in macros, so not a macro) */
  396. static inline object funcall1 (object fun, object arg)
  397. { pushSTACK(arg); funcall(fun,1); return value1; }
  398. nonreturning_function(static,my_type_error,(object type, object datum))
  399. {
  400. pushSTACK(datum); /* TYPE-ERROR slot DATUM */
  401. pushSTACK(type); /* TYPE-ERROR slot TYPE */
  402. pushSTACK(type); pushSTACK(datum); pushSTACK(TheSubr(subr_self)->name);
  403. error (type_error, ("~S: ~S is not of type ~S"));
  404. }
  405. nonreturning_function (static, error_closed_display,
  406. (object caller, object dpy)) {
  407. pushSTACK(`XLIB::CLOSED-DISPLAY`);
  408. pushSTACK(`:DISPLAY`); pushSTACK(dpy);
  409. pushSTACK(`:CALLER`); pushSTACK(caller);
  410. funcall(L(error),5);
  411. abort(); /* ERROR does not return: avoid a compiler warning */
  412. }
  413. /* with_stringable_0 is much like with_string_0, but a symbol is also
  414. allowed as argument. This macro does type checking and may raise an error. */
  415. #define with_stringable_0_tc(obj, encoding, cvar, body) \
  416. do { \
  417. object wsa0_temp = \
  418. (symbolp(obj) ? (object)Symbol_name (obj) : (object)(obj)); \
  419. if (stringp (wsa0_temp)) { \
  420. with_string_0 (wsa0_temp, encoding, cvar, body); \
  421. } else my_type_error(`(OR STRING SYMBOL)`,obj); \
  422. } while(0)
  423. /* -----------------------------------------------------------------------
  424. * Integer data types
  425. * ----------------------------------------------------------------------- */
  426. /* Huh?! These functions do not check the type?! */
  427. #define make_uint8(i) uint8_to_I (i)
  428. #define make_uint16(i) uint16_to_I (i)
  429. #define make_uint29(ul) UL_to_I (ul)
  430. #define make_uint32(ul) UL_to_I (ul)
  431. #define make_sint8(i) sint8_to_I (i)
  432. #define make_sint16(i) sint16_to_I (i)
  433. #define make_sint32(i) L_to_I (i)
  434. #define get_bool(obj) (!nullp(obj))
  435. #define make_bool(b) ((b)?(T):(NIL))
  436. #define pixel_p(obj) integerp (obj)
  437. #define get_pixel(obj) get_uint32(obj)
  438. #define make_pixel(obj) make_uint32(obj)
  439. #define get_fixnum(obj) fixnum_to_V (obj) /* WARNING: obj should be a variable (evaluated multiple), and no range check is performed */
  440. #if 0
  441. #define get_uint8(obj) I_to_uint8(obj)
  442. #define get_uint16(obj) I_to_uint16(obj)
  443. #define get_uint29(obj) I_to_UL (obj)
  444. #define get_uint32(obj) I_to_UL (obj)
  445. #define get_sint8(obj) I_to_sint8(obj)
  446. #define get_sint16(obj) I_to_sint16(obj)
  447. #define get_sint32(obj) I_to_sint32(obj)
  448. #else
  449. #define uint29_p uint32_p /* XXX the actual type checking code is just too weird! */
  450. #define I_to_uint29 I_to_UL /* XXX ditto */
  451. #define DEFINE_INTEGER_GETTER(type, lspnam) \
  452. static inline type get_##type (object obj) { \
  453. if (type##_p (obj)) \
  454. return I_to_##type (obj); \
  455. else my_type_error(lspnam,obj); \
  456. } \
  457. static inline type get_##type##_0 (object obj) { \
  458. return missingp(obj) ? 0 : get_##type(obj); \
  459. }
  460. DEFINE_INTEGER_GETTER (uint8, `XLIB::CARD8`)
  461. DEFINE_INTEGER_GETTER (uint16, `XLIB::CARD16`)
  462. DEFINE_INTEGER_GETTER (uint29, `XLIB::CARD29`)
  463. DEFINE_INTEGER_GETTER (uint32, `XLIB::CARD32`)
  464. DEFINE_INTEGER_GETTER (sint8, `XLIB::INT8`)
  465. DEFINE_INTEGER_GETTER (sint16, `XLIB::INT16`)
  466. DEFINE_INTEGER_GETTER (sint32, `XLIB::INT32`)
  467. #endif
  468. static uint32 get_aint32 (object obj)
  469. { /* This is special routine, which accepts either an uint32 or a sint32.
  470. However returned is an uint32.
  471. Used by XLIB:CHANGE-PROPERTY */
  472. if (uint32_p (obj))
  473. return I_to_uint32 (obj);
  474. if (sint32_p (obj))
  475. return (uint32)I_to_sint32 (obj);
  476. else my_type_error(`(OR XLIB::INT32 XLIB::CARD32)`,obj);
  477. }
  478. /* -----------------------------------------------------------------------
  479. * Displays
  480. * ----------------------------------------------------------------------- */
  481. /* Objects of type DISPLAY are currently represented as structure; here are the
  482. slots: The actual defstruct definition in clx.lisp must match. There is a
  483. warning in the code. */
  484. enum {
  485. slot_DISPLAY_FOREIGN_POINTER=1,
  486. slot_DISPLAY_HASH_TABLE,
  487. slot_DISPLAY_PLIST,
  488. slot_DISPLAY_AFTER_FUNCTION,
  489. slot_DISPLAY_ERROR_HANDLER,
  490. slot_DISPLAY_DISPLAY,
  491. display_structure_size
  492. };
  493. /* The display contains a hash table. All XID objects are entered there, so
  494. that two XID objects, with equal XID are actually eq. */
  495. static object make_display (Display *dpy, int display_number)
  496. { /* Given the C representation of a display create the Lisp one and
  497. initialize it. The newly created display is added to XLIB:*DISPLAYS*. */
  498. pushSTACK(`(XLIB::DISPLAY)`); pushSTACK(fixnum(display_structure_size));
  499. funcall(L(make_structure),2); pushSTACK(value1);
  500. TheStructure(STACK_0)->recdata[slot_DISPLAY_FOREIGN_POINTER]
  501. = allocate_fpointer (dpy);
  502. #if oint_data_len<29
  503. pushSTACK(S(Ktest)); pushSTACK(S(stablehash_equal)); /* key is a cons */
  504. #else
  505. pushSTACK(S(Ktest)); pushSTACK(S(stablehash_eq)); /* key is a fixnum */
  506. #endif
  507. funcall (L(make_hash_table), 2);
  508. TheStructure(STACK_0)->recdata[slot_DISPLAY_HASH_TABLE] = value1;
  509. TheStructure(STACK_0)->recdata[slot_DISPLAY_PLIST] = NIL;
  510. TheStructure(STACK_0)->recdata[slot_DISPLAY_AFTER_FUNCTION] = NIL;
  511. TheStructure(STACK_0)->recdata[slot_DISPLAY_ERROR_HANDLER] = NIL;
  512. TheStructure(STACK_0)->recdata[slot_DISPLAY_DISPLAY] =
  513. make_uint8 (display_number);
  514. /* Now enter the display into the list of all displays: */
  515. pushSTACK(STACK_0);
  516. pushSTACK(Symbol_value(`XLIB::*DISPLAYS*`));
  517. funcall (L(cons), 2);
  518. Symbol_value(`XLIB::*DISPLAYS*`) = value1;
  519. return value1 = popSTACK();
  520. }
  521. static object find_display (Display *display)
  522. { /* Searched the XLIB:*DISPLAY* variable for `display',
  523. return NIL, if display was not found.
  524. Used by the error handler, the only callback code here. */
  525. pushSTACK(Symbol_value (`XLIB::*DISPLAYS*`));
  526. for (;consp (STACK_0); STACK_0 = Cdr (STACK_0)) {
  527. if (get_display(Car(STACK_0)) == display)
  528. return Car(popSTACK());
  529. }
  530. skipSTACK(1);
  531. return NIL;
  532. }
  533. static Bool ensure_living_display (gcv_object_t *objf)
  534. { /* ensures that the object pointed to by 'objf' is really a display.
  535. Also the display must be 'alive', meaning that it does not contain
  536. a fptr from an previous incarnation of CLISP.
  537. If all that does not hold an error is signaled.
  538. Finally, returns an indicator of whether the display has been closed.
  539. 'objf' should point into the stack due to GC. */
  540. if (typep_classname (*objf, `XLIB::DISPLAY`)) { /* Is it a display at all? */
  541. object fptr = TheStructure(*objf)->recdata[slot_DISPLAY_FOREIGN_POINTER];
  542. return (fpointerp(fptr) && fp_validp(TheFpointer(fptr))
  543. && (TheFpointer(fptr)->fp_pointer != NULL));
  544. }
  545. /* Fall through -- raise type error */
  546. my_type_error(`XLIB::DISPLAY`,*(objf));
  547. }
  548. DEFUN(XLIB:CLOSED-DISPLAY-P, display)
  549. {
  550. VALUES_IF(!ensure_living_display(&STACK_0));
  551. skipSTACK(1);
  552. }
  553. /* display_hash_table -- return the hashtable of a display object
  554. > the display object
  555. < its hash table
  556. This function is somewhat silly, since it introduces double type checking! */
  557. static object display_hash_table (object dpy)
  558. {
  559. pushSTACK(dpy);
  560. if (!ensure_living_display(&(STACK_0)))
  561. error_closed_display(TheSubr(subr_self)->name,STACK_0);
  562. return TheStructure (popSTACK())->recdata[slot_DISPLAY_HASH_TABLE];
  563. }
  564. /* pop_display --- return the C Display* of an display object
  565. > STACK_0: the Lisp DISPLAY object */
  566. static Display *pop_display (void)
  567. {
  568. if (!ensure_living_display(&(STACK_0)))
  569. error_closed_display(TheSubr(subr_self)->name,STACK_0);
  570. STACK_0 = TheStructure (STACK_0)->recdata[slot_DISPLAY_FOREIGN_POINTER];
  571. return (Display*) TheFpointer(popSTACK())->fp_pointer;
  572. }
  573. /* -----------------------------------------------------------------------
  574. * PTR and XID objects
  575. * ----------------------------------------------------------------------- */
  576. /* First the ptr ones.
  577. ptr_objs are screens and gcontexts, these objects are not hashed.
  578. (which is a bad idea btw). But on the other hand for gcontexts it is
  579. not too bad, since you get `em only once.
  580. Another story are the screen, these could be cached. Or we do not give the
  581. actual screen structure, but pass simply the index? */
  582. static object make_ptr_obj (object type, object dpy, void *ptr)
  583. { /* (make-instance type :display dpy :ptr ptr) */
  584. pushSTACK(type);
  585. pushSTACK(`:DISPLAY`); pushSTACK(dpy);
  586. pushSTACK(`:PTR`); pushSTACK(allocate_fpointer (ptr));
  587. funcall(S(make_instance),5);
  588. return value1;
  589. }
  590. /* return the fp_pointer of the foreign slot
  591. value1 is set the slot value
  592. can trigger GC */
  593. static void* foreign_slot (object obj, object slot) {
  594. pushSTACK(obj); pushSTACK(slot); funcall(L(slot_value), 2);
  595. return TheFpointer(value1 = check_fpointer(value1,false))->fp_pointer;
  596. }
  597. static void *get_ptr_object_and_display (object type, object obj,
  598. Display **dpyf)
  599. { /* 'obj' is the lisp object, whose C representation is returned.
  600. When 'dpyf' is non-0, the display of 'obj' is also returned and it is
  601. ensured that it lives. [Otherwise an error is signaled.]
  602. If 'obj' is not of type 'type', a symbol naming the desired class,
  603. an error is issued.
  604. Hence this function ensures, that a proper object is returned, or nothing. */
  605. pushSTACK(type);
  606. pushSTACK(obj);
  607. if (typep_classname (STACK_0, STACK_1)) {
  608. if (dpyf) { /* do we want the display? */
  609. pushSTACK(STACK_0); pushSTACK(`XLIB::DISPLAY`);
  610. funcall(L(slot_value), 2); pushSTACK(value1);
  611. *dpyf = pop_display ();
  612. }
  613. { void * ret = foreign_slot(STACK_0/* 'obj' */,`XLIB::PTR`);
  614. skipSTACK(2); /* clean up */
  615. return ret;
  616. }
  617. } else my_type_error(STACK_1/*type*/,STACK_0/*obj*/);
  618. }
  619. /* Now the XID objects */
  620. static object make_xid_obj_low (gcv_object_t *prealloc, gcv_object_t *type,
  621. gcv_object_t *dpy, XID xid)
  622. {
  623. if (nullp (*prealloc)) {
  624. /* (make-instance type :display dpy :id xid) */
  625. pushSTACK(*type);
  626. pushSTACK(`:DISPLAY`); pushSTACK(*dpy);
  627. pushSTACK(`:ID`); pushSTACK(make_uint29 (xid));
  628. funcall(S(make_instance),5);
  629. return value1;
  630. } else {
  631. /* TODO: We should check the type of the preallocated object?!
  632. [Is is a bug or a feature?] */
  633. pushSTACK(*prealloc);
  634. pushSTACK(`XLIB::DISPLAY`);
  635. pushSTACK(*dpy);
  636. funcall (L(set_slot_value), 3);
  637. pushSTACK(*prealloc);
  638. pushSTACK(`XLIB::ID`);
  639. pushSTACK(make_uint29 (xid));
  640. funcall (L(set_slot_value), 3);
  641. return *prealloc;
  642. }
  643. }
  644. #if oint_data_len<29
  645. DEFVAR(xlib_a_cons,allocate_cons());
  646. /* return the XID object for lookup (old) */
  647. static inline object XID_to_object_old (XID xid) {
  648. Car (O(xlib_a_cons)) = make_uint16 (xid & 0xFFFF); /* lower halfword */
  649. Cdr (O(xlib_a_cons)) = make_uint16 (xid >> 16); /* upper halfword */
  650. return O(xlib_a_cons);
  651. }
  652. /* return the XID object for creation (new) */
  653. static inline object XID_to_object_new (XID xid) {
  654. pushSTACK(make_uint16 (xid & 0xFFFF)); /* lower halfword */
  655. pushSTACK(make_uint16 (xid >> 16)); /* upper halfword */
  656. funcall(L(cons),2); /* cons them */
  657. return value1;
  658. }
  659. #else
  660. #define XID_to_object_old(xid) fixnum(xid)
  661. #define XID_to_object_new(xid) fixnum(xid)
  662. #endif
  663. /* find the resource in the display hash table
  664. < display object, XID number
  665. > returns dpy->hash-table if NOT found
  666. nullobj if found, in which case the object found is in value1 */
  667. static object lookup_xid (object dpy, XID xid) {
  668. if (xid == 0) { /* This is trivial, but is it also right?! */
  669. VALUES1(NIL);
  670. return nullobj;
  671. } else {
  672. object ht = display_hash_table(dpy);
  673. value1 = gethash(XID_to_object_old(xid),ht,false); /* look it up */
  674. if (!eq(value1,nullobj)) { /* something found? */
  675. mv_count = 1; /* simply return what we found */
  676. return nullobj;
  677. } else
  678. return ht; /* return the hash-table */
  679. }
  680. }
  681. /* set the ID to map to RESOURCE on display
  682. < display hash-table object, XID number, resource object
  683. can trigger GC */
  684. static void set_resource_id (gcv_object_t *ht, XID xid,
  685. gcv_object_t *resource) {
  686. value1 = XID_to_object_new(xid);
  687. pushSTACK(value1); /* key for puthash */
  688. pushSTACK(*ht); /* hashtable */
  689. pushSTACK(*resource); /* value */
  690. funcall (L(puthash), 3); /* put it into the hashtable */
  691. }
  692. /* delete the resource ID from the display
  693. < display hash-table object, XID number */
  694. static Values delete_resource_id (gcv_object_t *ht, XID xid) {
  695. pushSTACK(XID_to_object_old(xid)); pushSTACK(*ht); funcall(L(remhash),2);
  696. }
  697. static object make_xid_obj_2 (object type, object dpy, XID xid,
  698. object prealloc)
  699. { /* NOTE: - This code is not reentrant :-( But hence it saves consing
  700. - may be we want to check the most significant 3 bits in xid, since
  701. GC inquiry functions return those values, if slot has an unknown
  702. value.
  703. - We could add even more safty here
  704. 1. bark if lookup succeed and prealloc was specified.
  705. [But this situation should not be able to occurr, since a
  706. prealloc is only given upon creation requests.] However MIT-CLX
  707. does this check and raises a hash-error, if something is not
  708. o.k. with the hash table. [But only if you set a debug flag
  709. somewhere].
  710. 2. If lookup succeeds we could also check the type.
  711. 3. We should check the type of the preallocated object?!
  712. [Compare to make_ptr_obj] */
  713. object ht = lookup_xid(dpy,xid);
  714. if (!eq(ht,nullobj)) { /* allocate and enter object into the hashtable */
  715. pushSTACK(prealloc); /* save is save */
  716. pushSTACK(type); /* ditto */
  717. pushSTACK(dpy); /* ditto */
  718. pushSTACK(ht); /* hashtable */
  719. pushSTACK(make_xid_obj_low (&STACK_3, &STACK_2, &STACK_1, xid));
  720. set_resource_id(&STACK_1,xid,&STACK_0); /* enter it into the hashtable */
  721. VALUES1(popSTACK()); /* return freshly allocated structure */
  722. skipSTACK(4); /* remove saved prealloc, type, dpy, ht */
  723. }
  724. return value1;
  725. }
  726. static XID get_xid_object_and_display (object type, object obj, Display **dpyf)
  727. {
  728. pushSTACK(type);
  729. pushSTACK(obj);
  730. if (typep_classname (STACK_0, STACK_1)) {
  731. if (dpyf) { /* do we want the display? */
  732. pushSTACK(STACK_0); pushSTACK(`XLIB::DISPLAY`);
  733. funcall(L(slot_value), 2); pushSTACK(value1);
  734. *dpyf = pop_display();
  735. }
  736. pushSTACK(STACK_0); /* obj already on stack */ pushSTACK(`XLIB::ID`);
  737. funcall(L(slot_value), 2);
  738. ASSERT(integerp (value1)); /* FIXME */
  739. skipSTACK(2); /* clean up */
  740. return (XID)(get_uint29 (value1)); /* all done */
  741. } else my_type_error(STACK_1/*type*/,STACK_0/*obj*/);
  742. }
  743. static object get_display_obj_tc (object type, object obj)
  744. {
  745. if (typep_classname (obj, type)) {
  746. pushSTACK(obj); pushSTACK(`XLIB::DISPLAY`);
  747. funcall(L(slot_value), 2); return value1;
  748. } else my_type_error(type,obj);
  749. }
  750. static object get_display_obj (object obj)
  751. { /* XXX type checking [Well on the other hand is it really necessary?]
  752. I want to use the combined function above. */
  753. pushSTACK(obj); pushSTACK(`XLIB::DISPLAY`);
  754. funcall(L(slot_value), 2); return value1;
  755. }
  756. /* -----------------------------------------------------------------------
  757. * Specializied getters/makers/predicates
  758. * ----------------------------------------------------------------------- */
  759. /* Simple Getters */
  760. #define get_xid_object(type,obj) get_xid_object_and_display(type,obj,0)
  761. #define get_ptr_object(type,obj) get_ptr_object_and_display(type,obj,0)
  762. #define get_gcontext(obj) ((GC) get_ptr_object (`XLIB::GCONTEXT`, obj))
  763. #define get_screen(obj) ((Screen*) get_ptr_object (`XLIB::SCREEN`, obj))
  764. #define get_image(obj) ((XImage*) get_ptr_object (`XLIB::IMAGE`, obj))
  765. #define get_window(obj) ((Window) get_xid_object (`XLIB::WINDOW`, obj))
  766. #define get_pixmap(obj) ((Pixmap) get_xid_object (`XLIB::PIXMAP`, obj))
  767. #define get_cursor(obj) ((Cursor) get_xid_object (`XLIB::CURSOR`, obj))
  768. #define get_colormap(obj) ((Colormap)get_xid_object (`XLIB::COLORMAP`, obj))
  769. #define get_drawable(obj) ((Drawable)get_xid_object (`XLIB::DRAWABLE`, obj))
  770. /* Combined getters */
  771. #define get_drawable_and_display(obj, dpyf) ((Drawable)get_xid_object_and_display (`XLIB::DRAWABLE`, obj, dpyf))
  772. #define get_window_and_display(obj, dpyf) ((Window) get_xid_object_and_display (`XLIB::WINDOW`, obj, dpyf))
  773. #define get_pixmap_and_display(obj, dpyf) ((Pixmap) get_xid_object_and_display (`XLIB::PIXMAP`, obj, dpyf))
  774. #define get_cursor_and_display(obj, dpyf) ((Cursor) get_xid_object_and_display (`XLIB::CURSOR`, obj, dpyf))
  775. #define get_colormap_and_display(obj, dpyf) ((Colormap)get_xid_object_and_display (`XLIB::COLORMAP`, obj, dpyf))
  776. #define get_gcontext_and_display(obj,dpyf) ((GC) get_ptr_object_and_display (`XLIB::GCONTEXT`, obj, dpyf))
  777. #define get_screen_and_display(obj,dpyf) ((Screen*) get_ptr_object_and_display (`XLIB::SCREEN`, obj, dpyf))
  778. #define get_font_and_display(obj, dpyf) ((Font) get_xid_object_and_display (`XLIB::FONT`, obj, dpyf))
  779. /* Predicates */
  780. #define drawable_p(obj) (typep_classname (obj, `XLIB::DRAWABLE`))
  781. #define window_p(obj) (typep_classname (obj, `XLIB::WINDOW`))
  782. #define pixmap_p(obj) (typep_classname (obj, `XLIB::PIXMAP`))
  783. #define cursor_p(obj) (typep_classname (obj, `XLIB::CURSOR`))
  784. #define colormap_p(obj) (typep_classname (obj, `XLIB::COLORMAP`))
  785. #define font_p(obj) (typep_classname (obj, `XLIB::FONT`))
  786. #define gcontext_p(obj) (typep_classname (obj, `XLIB::GCONTEXT`))
  787. #define screen_p(obj) (typep_classname (obj, `XLIB::SCREEN`))
  788. #define display_p(obj) (typep_classname (obj, `XLIB::DISPLAY`))
  789. #define color_p(obj) (typep_classname (obj, `XLIB::COLOR`))
  790. /* Simple Makers */
  791. #define make_xid_obj(a,b,c) make_xid_obj_2(a,b,c,NIL)
  792. #define make_window(dpy,win) (make_window_2(dpy,win,NIL))
  793. #define make_pixmap(dpy,pix) (make_pixmap_2(dpy,pix,NIL))
  794. #define make_drawable(dpy,da) (make_window (dpy, da))
  795. #define make_cursor(dpy,cur) (make_xid_obj (`XLIB::CURSOR`, dpy, cur))
  796. #define make_colormap(dpy,cm) (make_xid_obj (`XLIB::COLORMAP`, dpy, cm))
  797. #define make_gcontext(dpy,gc) (make_ptr_obj (`XLIB::GCONTEXT`, dpy, gc))
  798. #define make_screen(dpy, srcn) (make_ptr_obj (`XLIB::SCREEN`, dpy, srcn))
  799. /* Makers with prealloc */
  800. #define make_window_2(dpy, win, prealloc) (make_xid_obj_2 (`XLIB::WINDOW`, dpy, win, prealloc))
  801. #define make_pixmap_2(dpy, pm, prealloc) (make_xid_obj_2 (`XLIB::PIXMAP`, dpy, pm, prealloc))
  802. static object make_font (object dpy, Font fn, object name)
  803. { /* This looks much more like assembler, doesn't it? */
  804. pushSTACK(name); /* save the name */
  805. pushSTACK(make_xid_obj (`XLIB::FONT`, dpy, fn)); /* make the xid-object and save it */
  806. /* fetch old FONT-INFO slot */
  807. pushSTACK(STACK_0); /* xid-object */
  808. pushSTACK(`XLIB::FONT-INFO`); /* slot */
  809. funcall(L(slot_value), 2); /* (slot-value new-xid-object `font-info) */
  810. /* do not overwrite any already fetched font info */
  811. if (!fpointerp (value1)) { /* allocate a new fpointer */
  812. pushSTACK(STACK_0); /* the new xid-object */
  813. pushSTACK(`XLIB::FONT-INFO`); /* the slot */
  814. pushSTACK(allocate_fpointer (NULL)); /* new value */
  815. funcall (L(set_slot_value), 3); /* update the :font-info slot */
  816. }
  817. if (!nullp (STACK_1)) { /* name */
  818. pushSTACK(STACK_0); /* the new xid-object */
  819. pushSTACK(`XLIB::NAME`); /* the :name slot */
  820. pushSTACK(STACK_3); /* [name] new value */
  821. funcall (L(set_slot_value), 3); /* update the :name slot */
  822. }
  823. value1 = STACK_0; /* return value = new xid-object */
  824. skipSTACK(2); /* clean up */
  825. return value1;
  826. }
  827. static Font get_font (object obj);
  828. static XFontStruct *get_font_info_and_display (object obj, object* fontf,
  829. Display **dpyf)
  830. { /* Fetches the font information from a font, if it isn't there
  831. already, query the server for it.
  832. Further more if a gcontext is passed in, fetch its font slot instead.
  833. Does type checking and raises error if unappropriate object passed in.
  834. If 'fontf' is non-0, also the font as a Lisp object is returned.
  835. If 'dpyf' is non-0, also the display of the font is returned and it is
  836. ensured that the display actually lives. */
  837. XFontStruct *info;
  838. Display *dpy;
  839. Font font;
  840. if (gcontext_p (obj)) {
  841. /* In all places where a font object is required, a gcontext should
  842. be accepted too, so fetch the font slot and go on ... */
  843. pushSTACK(obj); pushSTACK(NIL);
  844. funcall(``XLIB:GCONTEXT-FONT``,2);
  845. obj = value1; /* Now we have the font [or nothing] */
  846. }
  847. if (!font_p (obj)) my_type_error(`XLIB::FONT`,obj);
  848. pushSTACK(obj); /* save */
  849. info = (XFontStruct*) foreign_slot(obj,`XLIB::FONT-INFO`);
  850. if (!info) {
  851. /* We have no font information already, so go and ask the server for it. */
  852. pushSTACK(value1); /* but first save what we found. */
  853. font = get_font_and_display (STACK_1, &dpy);
  854. X_CALL(info = XQueryFont (dpy, font));
  855. if (!info) {
  856. pushSTACK(STACK_1); pushSTACK(TheSubr (subr_self)->name);
  857. error(error_condition,"~S: Font ~S does not exist");
  858. }
  859. if (dpyf) *dpyf = dpy;
  860. /* Store it in the foreign pointer
  861. (foreign_slot ensures that STACK_0 is a foreign pointer) */
  862. TheFpointer(STACK_0)->fp_pointer = info;
  863. skipSTACK(1);
  864. # ifdef UNICODE
  865. { /* Determine the font's encoding, so we can correctly convert
  866. characters to indices.
  867. Call (XLIB:FONT-PROPERTY font "CHARSET_REGISTRY")
  868. and (XLIB:FONT-PROPERTY font "CHARSET_ENCODING")
  869. and translate the resulting pairs to CLISP encodings. */
  870. Atom xatom;
  871. unsigned long rgstry;
  872. unsigned long encdng;
  873. begin_x_call();
  874. xatom = XInternAtom (dpy, "CHARSET_REGISTRY", 0);
  875. if (XGetFontProperty (info, xatom, &rgstry)) {
  876. xatom = XInternAtom (dpy, "CHARSET_ENCODING", 0);
  877. if (XGetFontProperty (info, xatom, &encdng)) {
  878. Atom xatoms[2];
  879. char* names[2];
  880. int status;
  881. xatoms[0] = rgstry;
  882. xatoms[1] = encdng;
  883. names[0] = NULL;
  884. names[1] = NULL;
  885. # if !defined(HAVE_XGETATOMNAMES)
  886. names[0] = XGetAtomName (dpy, xatoms[0]);
  887. names[1] = XGetAtomName (dpy, xatoms[1]);
  888. status = names[0] && names[1];
  889. # else
  890. status = XGetAtomNames (dpy, xatoms, 2, names); /* X11R6 */
  891. # endif
  892. if (status) {
  893. /* this encoding canonicalization was requested by
  894. Pascal J.Bourguignon <pjb@informatimago.com>
  895. in <http://article.gmane.org/gmane.lisp.clisp.general:7794> */
  896. char* whole = (char*) alloca(strlen(names[0])+strlen(names[1])+3);
  897. if (!strncasecmp(names[0],"iso",3) && names[0][3] != '-') {
  898. strcpy(whole,"ISO-");
  899. strcat(whole,names[0]+3);
  900. } else strcpy(whole,names[0]);
  901. strcat(whole,"-");
  902. strcat(whole,names[1]);
  903. end_x_call();
  904. pushSTACK(S(Kcharset));
  905. pushSTACK(asciz_to_string(whole,GLO(misc_encoding)));
  906. pushSTACK(S(Koutput_error_action));
  907. pushSTACK(fixnum(info->default_char));
  908. funcall(L(make_encoding),4);
  909. pushSTACK(STACK_0); /* obj */
  910. pushSTACK(`XLIB::ENCODING`);
  911. pushSTACK(value1);
  912. funcall(L(set_slot_value),3);
  913. begin_x_call();
  914. }
  915. if (names[0])
  916. XFree (names[0]);
  917. if (names[1])
  918. XFree (names[1]);
  919. }
  920. }
  921. end_x_call();
  922. }
  923. # endif
  924. } else if (dpyf) /* caller wants the display, so get it! */
  925. unused get_font_and_display (STACK_0, dpyf);
  926. if (fontf) *fontf = STACK_0;
  927. skipSTACK(1);
  928. return info; /* all done */
  929. }
  930. static object get_font_name (object obj)
  931. {
  932. pushSTACK(obj); /* the instance */
  933. pushSTACK(`XLIB::NAME`); /* slot */
  934. funcall(L(slot_value), 2); /* lookup the slot */
  935. return value1;
  936. }
  937. #define ENSURE_TYPE(datum,booli,type) if (!booli) my_type_error(type,datum)
  938. static object get_slot (object obj, object slot)
  939. { /* like gethash(): return nullobj on unbound slot and slot value otherwise */
  940. pushSTACK(obj); pushSTACK(slot); /* save for SLOT-VALUE */
  941. pushSTACK(obj); pushSTACK(slot); funcall(L(slot_boundp),2);
  942. if (nullp(value1)) { skipSTACK(2); return nullobj; }
  943. funcall(L(slot_value),2); return value1;
  944. }
  945. static Font get_font (object self)
  946. { /* Does type-checking. */
  947. object font_id;
  948. pushSTACK(self); /* save */
  949. ENSURE_TYPE (STACK_0, font_p(STACK_0), `XLIB::FONT`);
  950. font_id = get_slot(STACK_0,`XLIB::ID`);
  951. if (!eq(font_id,nullobj)) { /* We have already a fid, so return it. */
  952. skipSTACK(1); /* clean up */
  953. ASSERT(integerp(font_id));
  954. return (XID)(get_uint29(font_id));
  955. } else { /* No font id => lookup the name & open that font */
  956. object name = get_font_name(STACK_0/*self*/);
  957. if (boundp(name)) { /* Ok there is a name ... so try to open the font */
  958. Font font; Display *dpy = get_display(STACK_0);
  959. with_string_0 (name, GLO(misc_encoding), namez, { /* XXX */
  960. X_CALL(font = XLoadFont(dpy,namez));
  961. });
  962. if (font) { /* Hurra! We got a font id, so enter it */
  963. pushSTACK(`XLIB::ID`); pushSTACK(make_uint29(font));
  964. funcall(L(set_slot_value),3);
  965. /* XXX -- We should enter it also into the hash table! */
  966. return font; /* all done */
  967. } else { /* We could not open the font, so emit an error message */
  968. pushSTACK(TheSubr(subr_self)->name); /* function name */
  969. error(error_condition,"~S: Cannot open pseudo font ~S");
  970. }
  971. } else { /* We have no name, tell that the luser. */
  972. pushSTACK(TheSubr(subr_self)->name); /* function name */
  973. error(error_condition,"~S: Cannot open pseudo font ~S, since it has no name associated with it.");
  974. }
  975. }
  976. }
  977. static Atom get_xatom_general (Display *dpy, object obj, int internp)
  978. { /* Converts a symbol or a string to an xatom. If 'obj' is no symbol
  979. nor a string, an error is raised. if 'internp' is non-0 the atom
  980. is interned on the server. */
  981. Atom xatom;
  982. with_stringable_0_tc (obj, GLO(misc_encoding), atom_name, {
  983. X_CALL(xatom = XInternAtom (dpy, atom_name, !internp));
  984. });
  985. return xatom;
  986. }
  987. #define get_xatom(dpy,obj) get_xatom_general (dpy, obj, 1) /* interning version */
  988. #define get_xatom_nointern(dpy,obj) get_xatom_general (dpy, obj, 0) /* non-interning version */
  989. static object make_visual (Visual *visual)
  990. {
  991. XID id;
  992. X_CALL(id = XVisualIDFromVisual (visual));
  993. return make_uint29 (id);
  994. }
  995. static Visual *get_visual (Display *dpy, object vid)
  996. {
  997. /* no begin/end_call here XVisualIDToVisual is defined by us. */
  998. return XVisualIDToVisual (dpy, get_uint29 (vid));
  999. }
  1000. /* -----------------------------------------------------------------------
  1001. * Lots of enums
  1002. * ----------------------------------------------------------------------- */
  1003. DEFCHECKER(get_map_state,default=,UNMAPPED=IsUnmapped \
  1004. UNVIEWABLE=IsUnviewable VIEWABLE=IsViewable)
  1005. #define make_map_state get_map_state_reverse
  1006. DEFCHECKER(get_shape,default=,COMPLEX=Complex CONVEX=Convex \
  1007. NON-CONVEX=Nonconvex)
  1008. DEFCHECKER(get_W_class,default=,:COPY=CopyFromParent INPUT-OUTPUT=InputOutput \
  1009. INPUT-ONLY=InputOnly)
  1010. #define make_W_class get_W_class_reverse
  1011. DEFCHECKER(get_stack_mode,default=,ABOVE=Above BELOW=Below TOP-IF=TopIf \
  1012. BOTTOM-IF=BottomIf OPPOSITE=Opposite)
  1013. #define make_stack_mode get_stack_mode_reverse
  1014. DEFCHECKER(get_arc_mode,default=,CHORD=ArcChord PIE-SLICE=ArcPieSlice)
  1015. #define make_arc_mode get_arc_mode_reverse
  1016. DEFCHECKER(get_line_style,default=,SOLID=LineSolid DASH=LineOnOffDash \
  1017. DOUBLE-DASH=LineDoubleDash)
  1018. #define make_line_style get_line_style_reverse
  1019. DEFCHECKER(get_cap_style,default=,NOT-LAST=CapNotLast BUTT=CapButt \
  1020. ROUND=CapRound PROJECTING=CapProjecting)
  1021. #define make_cap_style get_cap_style_reverse
  1022. DEFCHECKER(get_join_style,default=, \
  1023. MITER=JoinMiter ROUND=JoinRound BEVEL=JoinBevel)
  1024. #define make_join_style get_join_style_reverse
  1025. DEFCHECKER(get_fill_style,default=,SOLID=FillSolid TILED=FillTiled \
  1026. STIPPLED=FillStippled OPAQUE-STIPPLED=FillOpaqueStippled)
  1027. #define make_fill_style get_fill_style_reverse
  1028. DEFCHECKER(get_fill_rule,default=, EVEN-ODD=EvenOddRule WINDING=WindingRule)
  1029. #define make_fill_rule get_fill_rule_reverse
  1030. DEFCHECKER(get_subwindow_mode,default=, \
  1031. CLIP-BY-CHILDREN=ClipByChildren INCLUDE-INFERIORS=IncludeInferiors)
  1032. #define make_subwindow_mode get_subwindow_mode_reverse
  1033. DEFCHECKER(get_gravity,default=,FORGET=ForgetGravity \
  1034. NORTH-WEST=NorthWestGravity NORTH=NorthGravity \
  1035. NORTH-EAST=NorthEastGravity WEST=WestGravity CENTER=CenterGravity \
  1036. EAST=EastGravity SOUTH-WEST=SouthWestGravity SOUTH=SouthGravity \
  1037. SOUTH-EAST=SouthEastGravity STATIC=StaticGravity)
  1038. #define make_gravity get_gravity_reverse
  1039. /* NIM: the :static gravity is not mentioned in the CLX manual. */
  1040. DEFCHECKER(get_visibility_state,default=, UNOBSCURED=VisibilityUnobscured \
  1041. PARTLY-OBSCURED=VisibilityPartiallyObscured \
  1042. FULLY-OBSCURED=VisibilityFullyObscured)
  1043. #define make_visibility_state get_visibility_state_reverse
  1044. DEFCHECKER(get_top_or_bottom,default=,TOP=PlaceOnTop BOTTOM=PlaceOnBottom)
  1045. #define make_top_or_bottom get_top_or_bottom_reverse
  1046. DEFCHECKER(get_new_value_or_deleted,default=, \
  1047. NEW-VALUE=PropertyNewValue DELETED=PropertyDelete)
  1048. #define make_new_value_or_deleted get_new_value_or_deleted_reverse
  1049. DEFCHECKER(get_ordering,default=Unsorted, UNSORTED=Unsorted Y-SORTED=YSorted \
  1050. YX-SORTED=YXSorted YX-BANDED=YXBanded)
  1051. DEFCHECKER(get_mapping_request

Large files files are truncated, but you can click here to view the full file