1 ;;; xlib-xc.el --- X Connection.
3 ;; Copyright (C) 2003-2005 by XWEM Org.
5 ;; Author: Zajcev Evgeny <zevlg@yandex.ru>
6 ;; Created: 18 October 2003
7 ;; Keywords: xlib, xwem
8 ;; X-CVS: $Id: xlib-xc.el,v 1.7 2005-04-04 19:55:29 lg Exp $
9 ;; X-URL: http://lgarc.narod.ru/xwem/index.html
11 ;; This file is part of XWEM.
13 ;; XWEM is free software; you can redistribute it and/or modify it
14 ;; under the terms of the GNU General Public License as published by
15 ;; the Free Software Foundation; either version 2, or (at your option)
18 ;; XWEM is distributed in the hope that it will be useful, but WITHOUT
19 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
21 ;; License for more details.
23 ;; You should have received a copy of the GNU General Public License
24 ;; along with XEmacs; see the file COPYING. If not, write to the Free
25 ;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
28 ;;; Synched up with: Not in FSF
40 (autoload el "xlib-xwin"))
41 '(X-Win-event-handlers X-Win-EventHandler-runall make-X-Rect
42 X-Win-find-or-make X-Atom-find-or-make X-Win-p))
48 (defvar X-Dpy-dpys-list nil
49 "List of all opened displays.")
62 visuals) ; List of X-Visual
68 white-pixel black-pixel
69 root-event-mask ; Event mask for root window
74 width height ; in pixels
75 mwidth mheight ; in millimeters
78 root-depth ; Root depth
79 depths ; List of X-Depth
82 (defstruct X-ScreenFormat
87 (defstruct (X-Dpy (:predicate X-Dpy-isxdpy-p))
88 proc ; process, which holds X connection
89 log-buffer ; buffer for logs, when debugging is non-nil
90 properties ; User defined plist
93 (readings 0) ; non-zero mean we are in reading mode
94 evq ; saved events queue, normally should be nil
96 snd-queue ; Send queue, each call to
97 ; `X-Dpy-send' adds data to
100 (parse-guess-dispatcher 'X-Dpy-parse-message-guess)
101 (events-dispatcher 'X-Dpy-default-events-dispatcher)
103 event-handlers ; event handlers, same as in X-Win
109 proto-maj proto-min ; major and minor numbers for X protocol
110 vendor ; Vendor string
111 min-keycode max-keycode ; keycodes allowed
112 resource-base resource-mask (resource-id 1)
113 (rseq-id 0) ; requests sequence number
114 max-request-size ; Maximum request size allowed
116 byte-order ; Images byte order
122 formats ; List of X-ScreenFormat
124 (default-screen 0) ; default screen number
125 screens ; List of X-Screen
127 error-hooks ; Hooks called when X error occurs
129 ;; Various display lists
130 atoms ; list of atoms
131 windows ; list of windows
132 fonts ; list of opened fonts
133 extensions ; list of extensions
136 (defmacro X-Dpy-put-property (xdpy prop val)
137 "Put property PROP with value VAL in XDPY's properties list."
138 `(setf (X-Dpy-properties ,xdpy)
139 (plist-put (X-Dpy-properties ,xdpy) ,prop ,val)))
141 (defmacro X-Dpy-get-property (xdpy prop)
142 "Get property PROP from XDPY's properties list."
143 `(plist-get (X-Dpy-properties ,xdpy) ,prop))
145 (defsetf X-Dpy-get-property X-Dpy-put-property)
147 (defmacro X-Dpy-rem-property (xdpy prop)
148 "Remove property PROP from XDPY's properties list."
149 `(setf (X-Dpy-properties ,xdpy) (plist-remprop (X-Dpy-properties ,xdpy) ,prop)))
151 (defsubst X-Dpy-EventHandler-add (dpy handler &optional priority evtypes-list)
152 "To DPY's event handlers list add HANDLER."
153 (setf (X-Dpy-event-handlers dpy)
154 (X-EventHandler-add (X-Dpy-event-handlers dpy) handler priority evtypes-list)))
156 (defsubst X-Dpy-EventHandler-isset (dpy handler &optional priority evtypes-list)
157 "Return non-nil if on DPY event HANDLER is set."
158 (X-EventHandler-isset (X-Dpy-event-handlers dpy) handler priority evtypes-list))
160 (defsubst X-Dpy-EventHandler-rem (dpy handler &optional priority evtypes-list)
161 "From DPY's event handlers list, remove HANDLER."
162 (setf (X-Dpy-event-handlers dpy)
163 (X-EventHandler-rem (X-Dpy-event-handlers dpy) handler priority evtypes-list)))
165 (defsubst X-Dpy-EventHandler-enable (dpy handler &optional priority evtypes-list)
166 "In DPY's list of event handlers activate HANDLER."
167 (X-EventHandler-enable (X-Dpy-event-handlers dpy) handler priority evtypes-list))
169 (defsubst X-Dpy-EventHandler-disable (dpy handler &optional priority evtypes-list)
170 "In DPY's list of event handlers disable HANDLER."
171 (X-EventHandler-disable (X-Dpy-event-handlers dpy) handler priority evtypes-list))
173 (defsubst X-Dpy-EventHandler-runall (dpy xev)
174 "Run all DPY's event handlers on XEV.
175 Signal `X-Events-stop' to stop events processing."
176 (X-EventHandler-runall (X-Dpy-event-handlers dpy) xev))
178 ;; Formats operations
179 (defun X-formatfind (xdpy depth)
180 "On display XDPY find proper X-ScreenFormat for gived DEPTH."
181 (let ((formats (X-Dpy-formats xdpy)))
182 (while (and formats (not (= depth (X-ScreenFormat-depth (car formats)))))
183 (setq formats (cdr formats)))
187 (defun X-formatint (xdpy depth num)
188 "On display XDPY convert NUM to string."
189 (let ((fmt (X-formatfind xdpy depth))
191 (if (not (X-ScreenFormat-p fmt))
194 (setq bpp (/ (X-ScreenFormat-bits-per-pixel fmt) 8))
195 (setq cfun (intern (format "int->string%d" bpp)))
196 (funcall cfun num))))
198 (defun X-formatpad (xdpy depth str)
200 (let ((fmt (X-formatfind xdpy depth))
203 ;; XXX Can't deal with bits
204 (if (not (X-ScreenFormat-p fmt))
205 ;; XXX Assume depth is 1 for bitmaps
208 (setq bp (/ (X-ScreenFormat-scanline-pad fmt) 8))
210 (make-string (% (- bp (% (length str) bp)) bp) ?\x00)))))
212 (defun X-Dpy-p (xdpy &optional sig)
213 "Return non-nil if XDPY is X display.
214 If SIG is given and XDPY is not X display, SIG will be signaled."
215 (let ((isdpy (X-Dpy-isxdpy-p xdpy)))
216 (if (and (not isdpy) sig)
217 (signal 'wrong-type-argument (list sig 'X-Dpy-p xdpy))
220 (defun X-Dpy-get-id (xdpy)
221 "Get id to be used on X display XDPY."
222 (X-Dpy-p xdpy 'X-Dpy-get-id)
224 (let* ((newid (X-Dpy-resource-id xdpy))
226 (bitcnt 0) ;bit counter in mask
227 (idcnt 0) ;bit counter in id
228 (servmask (X-Dpy-resource-mask xdpy)) ;service mask (our unique bits)
229 (servbase (X-Dpy-resource-base xdpy))) ;service base (always set)
230 ;; we can say <30 because top 3 bits are always 0
231 (while (< bitcnt 30) ;while there is more in the mask
232 (if (Xtest servmask (Xmask bitcnt))
234 (if (Xtest newid (Xmask idcnt)) ;set bit in id if it is
235 ;set in the id value.
236 (setq newword (Xmask-or newword (Xmask bitcnt))))
237 (setq idcnt (1+ idcnt)))) ;inc idcnt when we have a mask match
238 (setq bitcnt (1+ bitcnt))) ;always inc bitmask cnter
240 (incf (X-Dpy-resource-id xdpy)) ;inc to next id counter value
241 (Xmask-or newword servbase))) ;return the id with base attached
243 ;;; Process functions
244 (defun X-Dpy-create-connection (dname dnum)
245 "Create X connection to display with name DNAME and number DNUM."
247 (let* ((xcon (open-network-stream (format "X-%s:%d" dname dnum)
251 (xdpy (make-X-Dpy :proc xcon :name (format "%s:%d" dname dnum))))
253 (set-process-filter xcon 'X-Dpy-filter)
254 (set-process-sentinel xcon 'X-Dpy-sentinel)
256 (add-to-list 'X-Dpy-dpys-list xdpy)
259 (defun X-Dpy-find-dpy (proc)
260 "Find xdpy by process PROC."
261 (let ((dpys X-Dpy-dpys-list))
262 (while (and dpys (not (eq proc (X-Dpy-proc (car dpys)))))
263 (setq dpys (cdr dpys)))
266 (defun X-Dpy-filter (proc out)
267 "Filter for X nework connections."
268 (let ((xdpy (X-Dpy-find-dpy proc)))
269 (X-Dpy-p xdpy 'X-Dpy-filter)
271 (setf (X-Dpy-message-buffer xdpy)
272 (concat (X-Dpy-message-buffer xdpy) out))
274 (funcall (X-Dpy-parse-guess-dispatcher xdpy) xdpy)))
276 (defun X-Dpy-sentinel (proc &optional event)
277 "Sentinel for X connections."
278 (let ((xdpy (X-Dpy-find-dpy proc)))
279 (X-Dpy-p xdpy 'X-Dpy-sentinel)
281 (message "X: Removing process %S" proc)
283 (delete-process proc)
285 (setq X-Dpy-dpys-list (delq xdpy X-Dpy-dpys-list))))
287 (defun X-Dpy-close (xdpy)
288 "Close connection associated with XDPY."
289 (X-Dpy-p xdpy 'X-Dpy-close)
290 (X-Dpy-send-flush xdpy)
291 (X-Dpy-sentinel (X-Dpy-proc xdpy)))
294 ;; Supported routines are:
295 ;; x-display - display related
296 ;; x-error - X Errors related
297 ;; x-event - X Event related
298 ;; x-tray - X tray related
299 ;; x-misc - Misc stuff
300 ;; x-record - RECORD extension
302 (defun X-Dpy-set-log-routines (xdpy routines)
303 "Set XDPY's log routines to ROUTINES."
304 (X-Dpy-put-property xdpy 'log-routines routines))
306 (defun X-Dpy-get-log-routines (xdpy)
307 "Return XDPY's log routines."
308 (X-Dpy-get-property xdpy 'log-routines))
310 (defun X-Dpy-has-log-routine-p (xdpy routine)
311 "Return non-nil if XDPY has log ROUTINE."
312 (memq routine (X-Dpy-get-log-routines xdpy)))
314 (defun X-Dpy-log (xdpy routine &rest args)
315 "Put a ROUTINE's message in the in the log buffer specified by XDPY.
316 If XDPY is nil, then put into current buffer. Log additional ARGS as well."
317 (X-Dpy-p xdpy 'X-Dpy-log)
319 (when (and (X-Dpy-log-buffer xdpy)
320 (X-Dpy-has-log-routine-p xdpy routine)
321 (bufferp (get-buffer-create (X-Dpy-log-buffer xdpy))))
322 (with-current-buffer (get-buffer-create (X-Dpy-log-buffer xdpy))
324 (goto-char (point-min))
325 (insert (format "%d %S: " (nth 1 (current-time)) routine))
326 (insert (apply 'format (mapcar 'eval args)))
329 (defun X-Dpy-log-verbatim (xdpy arg)
330 (X-Dpy-p xdpy 'X-Dpy-log-verbatim)
332 (when (bufferp (X-Dpy-log-buffer xdpy))
333 (with-current-buffer (X-Dpy-log-buffer xdpy)
334 (goto-char (point-min))
335 (insert "[" arg "]" "\n"))
338 ;;; Sending/receiving functions
339 (defun X-Dpy-send-flush (xdpy)
340 "Send XDPY's send buffer to X server."
341 (process-send-string (X-Dpy-proc xdpy)
342 (mapconcat 'identity (nreverse (X-Dpy-snd-queue xdpy)) ""))
343 (setf (X-Dpy-snd-queue xdpy) nil))
345 (defun X-Dpy-send (xdpy s)
346 "Send the X server DPY the string S. Increase request id rseq-id.
347 There is special mode when we are collecting X output to send it all at once."
348 (setf (X-Dpy-snd-queue xdpy)
349 (cons s (X-Dpy-snd-queue xdpy)))
350 (enqueue-eval-event 'X-Dpy-send-flush xdpy)
351 ;; increase request sequence number
352 (incf (X-Dpy-rseq-id xdpy)))
355 (defmacro X-Force-char-num (maybechar)
356 "Force MAYBECHAR to be a number for XEmacs platform."
357 ;; This is an annoying XEmacs problem To bad it slows down
359 (if (fboundp 'characterp)
360 (list 'if (list 'characterp maybechar)
361 (list 'setq maybechar (list 'char-to-int maybechar)))))
363 (defconst X-byte-order ?l "Byte order used by emacs X. B MSB, l LSB.")
364 (defconst X-protocol-minor-version 0 "Minor version of client.")
365 (defconst X-protocol-major-version 11 "Major version of client.")
367 (defconst X-client-to-open
368 (list [1 X-byte-order]
370 [2 X-protocol-major-version]
371 [2 X-protocol-minor-version]
375 ;; No auth name or data, so empty
377 "XStruct list of sizes when opening a connection.")
379 (defun X-Create-message (message-s &optional pad-notneed)
380 "Takes the MESSAGE-S structure and builds a net string.
381 MESSAGE-S is a list of vectors and symbols which formulate the message
382 to be sent to the XServer. Each vector is of this form:
384 SIZE is the number of BYTES used by the message.
385 VALUE is the lisp object whose value is to take up SIZE bytes.
386 If VALUE or SIZE is a symbol or list, extract that elements value.
387 If the resulting value is still a list or symbol, extract it's value
388 until it is no longer a symbol or a list.
389 If VALUE is a number, massage it to the correct size.
390 If VALUE is a string, append that string verbatum.
391 If VALUE is nil, fill it with that many NULL characters.
393 When PAD-NOTNEED is non-nil, then do not pad to 4 bytes."
395 (let ((gc-cons-threshold most-positive-fixnum) ;inhibit gc'ing
402 (setq tvec (car message-s))
403 (setq tval (aref tvec 1))
404 (setq tlen (aref tvec 0))
406 ;; Check for symbols, or symbols containing symbols.
407 (while (and tlen (or (listp tlen) (symbolp tlen)))
408 (setq tlen (eval tlen)))
410 ;; Check for symbols, or symbols containing symbols.
411 (while (and (not (null tval)) ; nil symbol allowed
412 (not (eq tval t)) ; t symbol allowed
413 (or (listp tval) (symbolp tval)))
414 (setq tval (eval tval)))
416 ;; Fix XEmacs 20 broken characters
417 (X-Force-char-num tval)
421 ;; numbers get converted based on size.
425 (setq ts (int->string1 tval)))
427 (setq ts (int->string tval)))
429 (setq ts (int->string4 tval)))
431 (error "Wrong size for a message part to be a number!"))))
433 ;; strings get appended onto the end.
437 ;; nil is usually filler, so stuff on some 0s
439 (setq ts (make-string tlen ?\x00)))
441 ;; t is alias for True
443 (setq ts (concat (make-string (- tlen 1) ?\x00) (make-string 1 ?\x01))))
445 ;; some sort of error
447 (error "Invalid type to be put into an Xmessage")))
449 (setq ts (concat ts "\0\0\0\0")) ; make sure we fill length req.
450 (setq ts (substring ts 0 tlen))
451 (setq news (concat news ts))
452 (setq message-s (cdr message-s)))
455 (if (and (not pad-notneed)
456 (/= (% (length news) 4) 0))
457 (let ((s "\0\0\0\0"))
458 (setq news (concat news (substring s 0 (- 4 (% (length news) 4)))))))
461 ;;;; NEW stuff, X types declarations
465 ;; Why is this needed? Gives flexibility in implementing and
466 ;; accessing X server and its resources.
468 ;; Autogenerator can be written, which will generate types according
469 ;; to proto.TXT or other papers.
471 (defmacro define-X-type (type type-description)
472 "Define new X value type.
473 TYPE-DESCRIPTION is list where car of it is one of:
475 `type' - Specifies static type, next values are - LENGTH
476 VALUE-PACKER VALUE-EXTRACTOR.
478 `resource' - Specifies some resource which has PREDICATE and
479 ID-EXTRACTOR functions.
481 `alias' - Alias to some already defined type.
483 `enum' - for use by SETofXXXX types.
485 `struct' - Define stucture.
487 `or' - One of other type.
489 `(put (quote ,type) 'X-type-description ,type-description))
491 (defun X-type-pack (dpy type val)
492 (let* ((xtd (or (and (listp type) type)
493 (get type 'X-type-description)))
495 (cond ((and (eq xt 'resource) (funcall (cadr xtd) val))
496 (int32->string (funcall (caddr xtd) val)))
499 (funcall (caddr xtd) val))
501 ((and (eq xt 'enum) (memq val (cddr xtd)))
505 (X-type-pack dpy (cadr xtd) val))
508 (apply 'concat (mapcar #'(lambda (el)
509 (X-type-pack dpy (cadr xtd) el))
513 (funcall (cond ((= (cadr xtd) 1) 'int->string1)
514 ((= (cadr xtd) 2) 'int->string2)
515 ((= (cadr xtd) 4) 'int->string4))
516 (apply 'Xmask-or val)))
519 (apply 'concat (mapcar #'(lambda (tt)
520 (X-type-pack dpy (cdr tt)
521 (funcall (car tt) val)))
527 (while (and xt (not orval))
528 (setq orval (X-type-pack dpy (car xt) val)
532 (defun X-type-extract (dpy type &optional llen)
533 (let* ((xtd (or (and (listp type) type)
534 (get type 'X-type-description)))
536 (cond ((eq xt 'resource)
537 (funcall (cadddr xtd) dpy (string->int32 (X-Dpy-grab-bytes dpy 4))))
540 (funcall (cadddr xtd) (X-Dpy-grab-bytes dpy (cadr xtd))))
543 (string->int (X-Dpy-grab-bytes dpy (cadr xtd))))
546 (X-type-extract dpy (cadr xtd)))
552 (setq rval (X-type-extract dpy (cadr xtd)))
557 (let ((smask (funcall (cond ((= (cadr xtd) 1) 'string1->int)
558 ((= (cadr xtd) 2) 'string->int)
559 ((= (cadr xtd) 4) 'string4->int))
560 (X-Dpy-grab-bytes dpy (cadr xtd))))
561 (dd (get (caddr xtd) 'X-type-description))
564 (when (eq (car dd) 'enum)
567 (when (Xtest smask cmask)
568 (setq rval (cons (car dd) rval)))
569 (setq cmask (lsh cmask 1)
574 (let ((rval (funcall (cadr xtd))))
576 (eval `(setf (,(car tt) rval)
577 (X-type-extract dpy ,(cdr tt)))))
581 ;; Add some built-in types
582 (define-X-type WINDOW '(resource X-Win-p X-Win-id X-Win-find-or-make))
583 (define-X-type PIXMAP '(resource X-Pixmap-p X-Pixmap-id X-Pixmap-find-or-make))
584 (define-X-type CURSOR '(resource X-Cursor-p X-Cursor-id X-Cursor-find-or-make))
585 (define-X-type FONT '(resource X-Font-p X-Font-id X-Font-find))
586 (define-X-type GCONTEXT '(resource X-Gc-p X-Gc-id ignore))
587 (define-X-type COLORMAP '(resource X-Colormap-p X-Colormap-id))
588 (define-X-type DRAWABLE '(or WINDOW PIXMAP))
589 (define-X-type FONTABLE '(or FONT GCONTEXT))
590 (define-X-type ATOM '(resource X-Atom-p X-Atom-id X-Atom-find-or-make))
591 (define-X-type VISUALID '(resource X-Visual-p X-Visual-id ignore))
592 (define-X-type BYTE '(type 1 char-to-string string-to-char))
593 (define-X-type INT8 '(type 1 x-int8->string x-string->int8))
594 (define-X-type INT16 '(type 2 x-int16->string x-string->int16))
595 (define-X-type INT32 '(type 4 x-int32->string x-string->int32))
596 (define-X-type CARD8 '(type 1 x-card8->string x-string->card8))
597 (define-X-type CARD16 '(type 2 x-card16->string x-string->card16))
598 (define-X-type CARD32 '(type 4 x-card32->string x-string->card32))
599 (define-X-type TIMESTAMP '(alias CARD32))
600 (define-X-type BITGRAVITY (list 'enum 1
601 X-ForgetGravity X-StaticGravity X-NorthWestGravity
602 X-NorthGravity X-NorthEastGravity X-WestGravity
603 X-CenterGravity X-EastGravity X-SouthWestGravity
604 X-SouthGravity X-SouthEastGravity))
605 (define-X-type WINGRAVITY (list 'enum 1
606 X-UnmapGravity X-StaticGravity X-NorthWestGravity
607 X-NorthGravity X-NorthEastGravity X-WestGravity
608 X-CenterGravity X-EastGravity X-SouthWestGravity
609 X-SouthGravity X-SouthEastGravity))
610 (define-X-type BOOL (list 'enum 1 X-True X-False))
611 (define-X-type EVENT (list 'enum 4
612 XM-KeyPress XM-KeyRelease XM-OwnerGrabButton XM-ButtonPress
613 XM-ButtonRelease XM-EnterWindow XM-LeaveWindow XM-PointerMotion
614 XM-PointerMotionHint XM-Button1Motion XM-Button2Motion
615 XM-Button3Motion XM-Button4Motion XM-Button5Motion
616 XM-ButtonMotion XM-Exposure XM-VisibilityChange XM-StructureNotify
617 XM-ResizeRedirect XM-SubstructureNotify XM-SubstructureRedirect
618 XM-FocusChange XM-PropertyChange XM-ColormapChange XM-KeymapState))
619 (define-X-type POINTEREVENT (list 'enum 4
620 XM-ButtonPress XM-ButtonRelease XM-EnterWindow
621 XM-LeaveWindow XM-PointerMotion XM-PointerMotionHint
622 XM-Button1Motion XM-Button2Motion XM-Button3Motion
623 XM-Button4Motion XM-Button5Motion XM-ButtonMotion XM-KeymapState))
624 (define-X-type DEVICEEVENT (list 'enum 4
625 XM-KeyPress XM-KeyRelease XM-ButtonPress XM-ButtonRelease
626 XM-PointerMotion XM-Button1Motion XM-Button2Motion
627 XM-Button3Motion XM-Button4Motion XM-Button5Motion
629 (define-X-type KEYSYM '(alias INT32))
630 (define-X-type KEYCODE '(alias CARD8))
631 (define-X-type BUTTON '(alias CARD8))
632 (define-X-type KEYMASK (list 'enum 2 X-Shift X-Lock X-Control X-Mod1 X-Mod2 X-Mod3 X-Mod4 X-Mod5))
633 (define-X-type BUTMASK (list 'enum 2 X-Button1 X-Button2 X-Button3 X-Button4 X-Button5))
634 (define-X-type KEYBUTMASK '(or KEYMASK BUTMASK))
636 (defun make-X-Char2B ()
637 (make-string 2 ?\x00))
638 (defun X-Char2B-byte0 (c2b)
640 (defsetf X-Char2B-byte0 (c2b) (b)
642 (defun X-Char2B-byte1 (c2b)
644 (defsetf X-Char2B-byte1 (c2b) (b)
647 (define-X-type CHAR2B '(struct X-Char2B
648 (X-Char2B-byte0 . BYTE)
649 (X-Char2B-byte1 . BYTE)))
650 (define-X-type STRING8 '(listof BYTE))
651 (define-X-type STRING16 '(listof CHAR2B))
653 (define-X-type POINT '(struct X-Point
655 (X-Point-y . INT16)))
656 (define-X-type RECTANGLE '(struct X-Rect
659 (X-Rect-width . CARD16)
660 (X-Rect-height . CARD16)))
661 (define-X-type ARC '(struct X-Arc
664 (X-Arc-width . CARD16)
665 (X-Arc-height . CARD16)
666 (X-Arc-angle1 . INT16)
667 (X-Arc-angle2 . INT16)))
668 (defun make-X-Host ()
670 (defun X-Host-family (h)
672 (defsetf X-Host-family (h) (f)
674 (defun X-Host-address (h)
676 (defsetf X-Host-address (h) (a)
679 (define-X-type HOST `(struct X-Host
680 (X-Host-family . (enum 1 ,X-FamilyInternet ,X-FamilyDECnet ,X-FamilyChaos))
681 (X-Host-address . STRING8)))
683 (defun X-Create-Message (message-s &optional pad-notneed)
684 "Takes the MESSAGE-S structure and builds a net string.
685 MESSAGE-S is a list of vectors and symbols which formulate the message
686 to be sent to the XServer. Each vector is of this form:
688 SIZE is the number of BYTES used by the message.
689 VALUE is the lisp object whose value is to take up SIZE bytes.
690 If VALUE or SIZE is a symbol or list, extract that elements value.
691 If the resulting value is still a list or symbol, extract it's value
692 until it is no longer a symbol or a list.
693 If VALUE is a number, massage it to the correct size.
694 If VALUE is a string, append that string verbatum.
695 If VALUE is nil, fill it with that many NULL characters.
697 When PAD-NOTNEED is non-nil, then do not pad to 4 bytes."
699 (let ((gc-cons-threshold most-positive-fixnum) ;inhibit gc'ing
700 (news "") ; resulting message
701 (padlen 0) ; resulting message padlen (if needed)
706 (if (= (length (car message-s)) 2)
708 ttype (aref (car message-s) 0)
709 tval (aref (car message-s) 1))
710 (setq tlen (aref (car message-s) 0)
711 ttype (aref (car message-s) 1)
712 tval (aref (car message-s) 2)))
714 ;; Check for symbols, or symbols containing symbols.
715 (while (and (not (null tval)) ; nil symbol allowed
716 (not (eq tval t)) ; t symbol allowed
717 (or (listp tval) (symbolp tval)))
718 (setq tval (eval tval)))
722 (setq tval (make-string tlen ?\x00)))
724 (setq tval (concat (make-string (- tlen 1) ?\x00) (make-string 1 ?\x01))))
725 (t (setq tval (X-type-pack nil ttype tval))))
726 (setq news (concat news tval))
728 (setq message-s (cdr message-s)))
731 (if (and (not pad-notneed)
732 (/= (setq padlen (% (length news) 4)) 0))
733 (concat news (make-string (- 4 padlen) ?\x00))
736 (defun X-Parse-Message (dpy message-s)
737 ;; TODO: write me using `X-type-extract'
743 ;;; xlib-xc.el ends here