comparison src/tooltalk.c @ 428:3ecd8885ac67 r21-2-22

Import from CVS: tag r21-2-22
author cvs
date Mon, 13 Aug 2007 11:28:15 +0200
parents
children 8de8e3f6228a
comparison
equal deleted inserted replaced
427:0a0253eac470 428:3ecd8885ac67
1 /* Tooltalk support for Emacs.
2 Copyright (C) 1993, 1994 Sun Microsystems, Inc.
3 Copyright (C) 1995 Free Software Foundation, Inc.
4
5 This file is part of XEmacs.
6
7 XEmacs is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 2, or (at your option) any
10 later version.
11
12 XEmacs is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with XEmacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
21
22 /* Synched up with: Not in FSF. */
23
24 /* Written by John Rose <john.rose@eng.sun.com>.
25 Heavily modified and cleaned up by Ben Wing <ben@xemacs.org>. */
26
27 #include <config.h>
28 #include "lisp.h"
29
30 #include <X11/Xlib.h>
31
32 #include "buffer.h"
33 #include "elhash.h"
34 #include "process.h"
35 #include "tooltalk.h"
36
37 Lisp_Object Vtooltalk_fd;
38
39 #ifdef TT_DEBUG
40 static FILE *tooltalk_log_file;
41 #endif
42
43 static Lisp_Object
44 Vtooltalk_message_handler_hook,
45 Vtooltalk_pattern_handler_hook,
46 Vtooltalk_unprocessed_message_hook;
47
48 static Lisp_Object
49 Qtooltalk_message_handler_hook,
50 Qtooltalk_pattern_handler_hook,
51 Qtooltalk_unprocessed_message_hook;
52
53 static Lisp_Object
54 Qreceive_tooltalk_message,
55 Qtt_address,
56 Qtt_args_count,
57 Qtt_arg_bval,
58 Qtt_arg_ival,
59 Qtt_arg_mode,
60 Qtt_arg_type,
61 Qtt_arg_val,
62 Qtt_class,
63 Qtt_category,
64 Qtt_disposition,
65 Qtt_file,
66 Qtt_gid,
67 Qtt_handler,
68 Qtt_handler_ptype,
69 Qtt_object,
70 Qtt_op,
71 Qtt_opnum,
72 Qtt_otype,
73 Qtt_scope,
74 Qtt_sender,
75 Qtt_sender_ptype,
76 Qtt_session,
77 Qtt_state,
78 Qtt_status,
79 Qtt_status_string,
80 Qtt_uid,
81 Qtt_callback,
82 Qtt_plist,
83 Qtt_prop,
84
85 Qtt_reject, /* return-tooltalk-message */
86 Qtt_reply,
87 Qtt_fail,
88
89 Q_TT_MODE_UNDEFINED, /* enum Tt_mode */
90 Q_TT_IN,
91 Q_TT_OUT,
92 Q_TT_INOUT,
93 Q_TT_MODE_LAST,
94
95 Q_TT_SCOPE_NONE, /* enum Tt_scope */
96 Q_TT_SESSION,
97 Q_TT_FILE,
98 Q_TT_BOTH,
99 Q_TT_FILE_IN_SESSION,
100
101 Q_TT_CLASS_UNDEFINED, /* enum Tt_class */
102 Q_TT_NOTICE,
103 Q_TT_REQUEST,
104 Q_TT_CLASS_LAST,
105
106 Q_TT_CATEGORY_UNDEFINED, /* enum Tt_category */
107 Q_TT_OBSERVE,
108 Q_TT_HANDLE,
109 Q_TT_CATEGORY_LAST,
110
111 Q_TT_PROCEDURE, /* typedef enum Tt_address */
112 Q_TT_OBJECT,
113 Q_TT_HANDLER,
114 Q_TT_OTYPE,
115 Q_TT_ADDRESS_LAST,
116
117 Q_TT_CREATED, /* enum Tt_state */
118 Q_TT_SENT,
119 Q_TT_HANDLED,
120 Q_TT_FAILED,
121 Q_TT_QUEUED,
122 Q_TT_STARTED,
123 Q_TT_REJECTED,
124 Q_TT_STATE_LAST,
125
126 Q_TT_DISCARD, /* enum Tt_disposition */
127 Q_TT_QUEUE,
128 Q_TT_START;
129
130 static Lisp_Object Tooltalk_Message_plist_str, Tooltalk_Pattern_plist_str;
131
132 Lisp_Object Qtooltalk_error;
133
134 /* Used to GCPRO tooltalk message and pattern objects while
135 they're sitting inside of some active tooltalk message or pattern.
136 There may not be any other pointers to these objects. */
137 Lisp_Object Vtooltalk_message_gcpro, Vtooltalk_pattern_gcpro;
138
139
140 /* */
141 /* machinery for tooltalk-message type */
142 /* */
143
144 Lisp_Object Qtooltalk_messagep;
145
146 struct Lisp_Tooltalk_Message
147 {
148 struct lcrecord_header header;
149 Lisp_Object plist_sym, callback;
150 Tt_message m;
151 };
152
153 static Lisp_Object
154 mark_tooltalk_message (Lisp_Object obj)
155 {
156 mark_object (XTOOLTALK_MESSAGE (obj)->callback);
157 return XTOOLTALK_MESSAGE (obj)->plist_sym;
158 }
159
160 static void
161 print_tooltalk_message (Lisp_Object obj, Lisp_Object printcharfun,
162 int escapeflag)
163 {
164 struct Lisp_Tooltalk_Message *p = XTOOLTALK_MESSAGE (obj);
165
166 char buf[200];
167
168 if (print_readably)
169 error ("printing unreadable object #<tooltalk_message 0x%x>",
170 p->header.uid);
171
172 sprintf (buf, "#<tooltalk_message id:0x%lx 0x%x>", (long) (p->m), p->header.uid);
173 write_c_string (buf, printcharfun);
174 }
175
176 DEFINE_LRECORD_IMPLEMENTATION ("tooltalk-message", tooltalk_message,
177 mark_tooltalk_message, print_tooltalk_message,
178 0, 0, 0, 0,
179 struct Lisp_Tooltalk_Message);
180
181 static Lisp_Object
182 make_tooltalk_message (Tt_message m)
183 {
184 Lisp_Object val;
185 struct Lisp_Tooltalk_Message *msg =
186 alloc_lcrecord_type (struct Lisp_Tooltalk_Message,
187 &lrecord_tooltalk_message);
188
189 msg->m = m;
190 msg->callback = Qnil;
191 msg->plist_sym = Fmake_symbol (Tooltalk_Message_plist_str);
192 XSETTOOLTALK_MESSAGE (val, msg);
193 return val;
194 }
195
196 Tt_message
197 unbox_tooltalk_message (Lisp_Object msg)
198 {
199 CHECK_TOOLTALK_MESSAGE (msg);
200 return XTOOLTALK_MESSAGE (msg)->m;
201 }
202
203 DEFUN ("tooltalk-message-p", Ftooltalk_message_p, 1, 1, 0, /*
204 Return non-nil if OBJECT is a tooltalk message.
205 */
206 (object))
207 {
208 return TOOLTALK_MESSAGEP (object) ? Qt : Qnil;
209 }
210
211
212
213
214 /* */
215 /* machinery for tooltalk-pattern type */
216 /* */
217
218 Lisp_Object Qtooltalk_patternp;
219
220 struct Lisp_Tooltalk_Pattern
221 {
222 struct lcrecord_header header;
223 Lisp_Object plist_sym, callback;
224 Tt_pattern p;
225 };
226
227 static Lisp_Object
228 mark_tooltalk_pattern (Lisp_Object obj)
229 {
230 mark_object (XTOOLTALK_PATTERN (obj)->callback);
231 return XTOOLTALK_PATTERN (obj)->plist_sym;
232 }
233
234 static void
235 print_tooltalk_pattern (Lisp_Object obj, Lisp_Object printcharfun,
236 int escapeflag)
237 {
238 struct Lisp_Tooltalk_Pattern *p = XTOOLTALK_PATTERN (obj);
239
240 char buf[200];
241
242 if (print_readably)
243 error ("printing unreadable object #<tooltalk_pattern 0x%x>",
244 p->header.uid);
245
246 sprintf (buf, "#<tooltalk_pattern id:0x%lx 0x%x>", (long) (p->p), p->header.uid);
247 write_c_string (buf, printcharfun);
248 }
249
250 DEFINE_LRECORD_IMPLEMENTATION ("tooltalk-pattern", tooltalk_pattern,
251 mark_tooltalk_pattern, print_tooltalk_pattern,
252 0, 0, 0, 0,
253 struct Lisp_Tooltalk_Pattern);
254
255 static Lisp_Object
256 make_tooltalk_pattern (Tt_pattern p)
257 {
258 struct Lisp_Tooltalk_Pattern *pat =
259 alloc_lcrecord_type (struct Lisp_Tooltalk_Pattern,
260 &lrecord_tooltalk_pattern);
261 Lisp_Object val;
262
263 pat->p = p;
264 pat->callback = Qnil;
265 pat->plist_sym = Fmake_symbol (Tooltalk_Pattern_plist_str);
266
267 XSETTOOLTALK_PATTERN (val, pat);
268 return val;
269 }
270
271 static Tt_pattern
272 unbox_tooltalk_pattern (Lisp_Object pattern)
273 {
274 CHECK_TOOLTALK_PATTERN (pattern);
275 return XTOOLTALK_PATTERN (pattern)->p;
276 }
277
278 DEFUN ("tooltalk-pattern-p", Ftooltalk_pattern_p, 1, 1, 0, /*
279 Return non-nil if OBJECT is a tooltalk pattern.
280 */
281 (object))
282 {
283 return TOOLTALK_PATTERNP (object) ? Qt : Qnil;
284 }
285
286
287
288
289 static int
290 tooltalk_constant_value (Lisp_Object s)
291 {
292 if (INTP (s))
293 return XINT (s);
294 else if (SYMBOLP (s))
295 return XINT (XSYMBOL (s)->value);
296 else
297 return 0; /* should never occur */
298 }
299
300 static void
301 check_status (Tt_status st)
302 {
303 if (tt_is_err (st))
304 signal_error (Qtooltalk_error,
305 Fcons (build_string (tt_status_message (st)), Qnil));
306 }
307
308 DEFUN ("receive-tooltalk-message", Freceive_tooltalk_message, 0, 2, 0, /*
309 Run tt_message_receive().
310 This function is the process handler for the ToolTalk connection process.
311 */
312 (ignore1, ignore2))
313 {
314 /* This function can GC */
315 Tt_message mess = tt_message_receive ();
316 Lisp_Object message_ = make_tooltalk_message (mess);
317 struct gcpro gcpro1;
318
319 GCPRO1 (message_);
320 if (mess != NULL && !NILP (Vtooltalk_unprocessed_message_hook))
321 va_run_hook_with_args (Qtooltalk_unprocessed_message_hook, 1, message_);
322 UNGCPRO;
323
324 /* see comment in event-stream.c about this return value. */
325 return Qzero;
326 }
327
328 static Tt_callback_action
329 tooltalk_message_callback (Tt_message m, Tt_pattern p)
330 {
331 /* This function can GC */
332 Lisp_Object cb;
333 Lisp_Object message_;
334 Lisp_Object pattern;
335 struct gcpro gcpro1, gcpro2;
336
337 #ifdef TT_DEBUG
338 int i, j;
339
340 fprintf (tooltalk_log_file, "message_cb: %d\n", m);
341 fprintf (tooltalk_log_file, "op: %s (", tt_message_op (m));
342 for (j = tt_message_args_count (m), i = 0; i < j; i++) {
343 fprintf (tooltalk_log_file, "%s \"%s\"", tt_message_arg_type (m, i),
344 tt_message_arg_val (m, i));
345 fprintf (tooltalk_log_file, "%s", i == j-1 ? ")" : ", ");
346 }
347 fprintf (tooltalk_log_file, "\n\n");
348 fflush (tooltalk_log_file);
349 #endif
350
351 VOID_TO_LISP (message_, tt_message_user (m, TOOLTALK_MESSAGE_KEY));
352 pattern = make_tooltalk_pattern (p);
353 cb = XTOOLTALK_MESSAGE (message_)->callback;
354 GCPRO2 (message_, pattern);
355 if (!NILP (Vtooltalk_message_handler_hook))
356 va_run_hook_with_args (Qtooltalk_message_handler_hook, 2,
357 message_, pattern);
358
359 if ((SYMBOLP (cb) && EQ (Qt, Ffboundp (cb))) ||
360 (CONSP (cb) && EQ (Qlambda, Fcar (cb)) &&
361 !NILP (Flistp (Fcar (Fcdr (cb))))))
362 call2 (cb, message_, pattern);
363 UNGCPRO;
364
365 tt_message_destroy (m);
366 Fremhash (message_, Vtooltalk_message_gcpro);
367
368 return TT_CALLBACK_PROCESSED;
369 }
370
371 static Tt_callback_action
372 tooltalk_pattern_callback (Tt_message m, Tt_pattern p)
373 {
374 /* This function can GC */
375 Lisp_Object cb;
376 Lisp_Object message_;
377 Lisp_Object pattern;
378 struct gcpro gcpro1, gcpro2;
379
380 #ifdef TT_DEBUG
381 int i, j;
382
383 fprintf (tooltalk_log_file, "pattern_cb: %d\n", m);
384 fprintf (tooltalk_log_file, "op: %s (", tt_message_op (m));
385 for (j = tt_message_args_count (m), i = 0; i < j; i++) {
386 fprintf (tooltalk_log_file, "%s \"%s\"", tt_message_arg_type (m, i),
387 tt_message_arg_val (m, i));
388 fprintf (tooltalk_log_file, "%s", i == j-1 ? ")" : ", ");
389 }
390 fprintf (tooltalk_log_file, "\n\n");
391 fflush (tooltalk_log_file);
392 #endif
393
394 message_ = make_tooltalk_message (m);
395 VOID_TO_LISP (pattern, tt_pattern_user (p, TOOLTALK_PATTERN_KEY));
396 cb = XTOOLTALK_PATTERN (pattern)->callback;
397 GCPRO2 (message_, pattern);
398 if (!NILP (Vtooltalk_pattern_handler_hook))
399 va_run_hook_with_args (Qtooltalk_pattern_handler_hook, 2,
400 message_, pattern);
401
402 if (SYMBOLP (cb) && EQ (Qt, Ffboundp (cb)))
403 call2 (cb, message_, pattern);
404 UNGCPRO;
405
406 tt_message_destroy (m);
407 return TT_CALLBACK_PROCESSED;
408 }
409
410 static Lisp_Object
411 tt_mode_symbol (Tt_mode n)
412 {
413 switch (n)
414 {
415 case TT_MODE_UNDEFINED: return Q_TT_MODE_UNDEFINED;
416 case TT_IN: return Q_TT_IN;
417 case TT_OUT: return Q_TT_OUT;
418 case TT_INOUT: return Q_TT_INOUT;
419 case TT_MODE_LAST: return Q_TT_MODE_LAST;
420 default: return Qnil;
421 }
422 }
423
424 static Lisp_Object
425 tt_scope_symbol (Tt_scope n)
426 {
427 switch (n)
428 {
429 case TT_SCOPE_NONE: return Q_TT_SCOPE_NONE;
430 case TT_SESSION: return Q_TT_SESSION;
431 case TT_FILE: return Q_TT_FILE;
432 case TT_BOTH: return Q_TT_BOTH;
433 case TT_FILE_IN_SESSION: return Q_TT_FILE_IN_SESSION;
434 default: return Qnil;
435 }
436 }
437
438
439 static Lisp_Object
440 tt_class_symbol (Tt_class n)
441 {
442 switch (n)
443 {
444 case TT_CLASS_UNDEFINED: return Q_TT_CLASS_UNDEFINED;
445 case TT_NOTICE: return Q_TT_NOTICE;
446 case TT_REQUEST: return Q_TT_REQUEST;
447 case TT_CLASS_LAST: return Q_TT_CLASS_LAST;
448 default: return Qnil;
449 }
450 }
451
452 /*
453 * This is not being used. Is that a mistake or is this function
454 * simply not necessary?
455 */
456 #if 0
457 static Lisp_Object
458 tt_category_symbol (Tt_category n)
459 {
460 switch (n)
461 {
462 case TT_CATEGORY_UNDEFINED: return Q_TT_CATEGORY_UNDEFINED;
463 case TT_OBSERVE: return Q_TT_OBSERVE;
464 case TT_HANDLE: return Q_TT_HANDLE;
465 case TT_CATEGORY_LAST: return Q_TT_CATEGORY_LAST;
466 default: return Qnil;
467 }
468 }
469 #endif /* 0 */
470
471 static Lisp_Object
472 tt_address_symbol (Tt_address n)
473 {
474 switch (n)
475 {
476 case TT_PROCEDURE: return Q_TT_PROCEDURE;
477 case TT_OBJECT: return Q_TT_OBJECT;
478 case TT_HANDLER: return Q_TT_HANDLER;
479 case TT_OTYPE: return Q_TT_OTYPE;
480 case TT_ADDRESS_LAST: return Q_TT_ADDRESS_LAST;
481 default: return Qnil;
482 }
483 }
484
485 static Lisp_Object
486 tt_state_symbol (Tt_state n)
487 {
488 switch (n)
489 {
490 case TT_CREATED: return Q_TT_CREATED;
491 case TT_SENT: return Q_TT_SENT;
492 case TT_HANDLED: return Q_TT_HANDLED;
493 case TT_FAILED: return Q_TT_FAILED;
494 case TT_QUEUED: return Q_TT_QUEUED;
495 case TT_STARTED: return Q_TT_STARTED;
496 case TT_REJECTED: return Q_TT_REJECTED;
497 case TT_STATE_LAST: return Q_TT_STATE_LAST;
498 default: return Qnil;
499 }
500 }
501
502 static Lisp_Object
503 tt_build_string (char *s)
504 {
505 return build_string (s ? s : "");
506 }
507
508 static Lisp_Object
509 tt_opnum_string (int n)
510 {
511 char buf[32];
512
513 sprintf (buf, "%u", n);
514 return build_string (buf);
515 }
516
517 static Lisp_Object
518 tt_message_arg_ival_string (Tt_message m, int n)
519 {
520 char buf[32];
521 int value;
522
523 check_status (tt_message_arg_ival (m, n, &value));
524 long_to_string (buf, value);
525 return build_string (buf);
526 }
527
528 static Lisp_Object
529 tt_message_arg_bval_vector (Tt_message m, int n)
530 {
531 /* !!#### This function has not been Mule-ized */
532 Bufbyte *value;
533 int len = 0;
534
535 check_status (tt_message_arg_bval (m, n, &value, &len));
536
537 return make_string (value, len);
538 }
539
540 DEFUN ("get-tooltalk-message-attribute", Fget_tooltalk_message_attribute,
541 2, 3, 0, /*
542 Return the indicated Tooltalk message attribute. Attributes are
543 identified by symbols with the same name (underscores and all) as the
544 suffix of the Tooltalk tt_message_<attribute> function that extracts the value.
545 String attribute values are copied, enumerated type values (except disposition)
546 are converted to symbols - e.g. TT_HANDLER is 'TT_HANDLER, uid and gid are
547 represented by fixnums (small integers), opnum is converted to a string,
548 and disposition is converted to a fixnum. We convert opnum (a C int) to a
549 string, e.g. 123 => "123" because there's no guarantee that opnums will fit
550 within the range of Lisp integers.
551
552 Use the 'plist attribute instead of the C API 'user attribute
553 for user defined message data. To retrieve the value of a message property
554 specify the indicator for argn. For example to get the value of a property
555 called 'rflag, use
556 (get-tooltalk-message-attribute message 'plist 'rflag)
557
558 To get the value of a message argument use one of the 'arg_val (strings),
559 'arg_ival (integers), or 'arg_bval (strings with embedded nulls), attributes.
560 For example to get the integer value of the third argument:
561
562 (get-tooltalk-message-attribute message 'arg_ival 2)
563
564 As you can see, argument numbers are zero based. The type of each argument
565 can be retrieved with the 'arg_type attribute; however, Tooltalk doesn't
566 define any semantics for the string value of 'arg_type. Conventionally
567 "string" is used for strings and "int" for 32 bit integers. Note that
568 Emacs Lisp stores the lengths of strings explicitly (unlike C) so treating the
569 value returned by 'arg_bval like a string is fine.
570 */
571 (message_, attribute, argn))
572 {
573 Tt_message m = unbox_tooltalk_message (message_);
574 int n = 0;
575
576 CHECK_SYMBOL (attribute);
577 if (EQ (attribute, (Qtt_arg_bval)) ||
578 EQ (attribute, (Qtt_arg_ival)) ||
579 EQ (attribute, (Qtt_arg_mode)) ||
580 EQ (attribute, (Qtt_arg_type)) ||
581 EQ (attribute, (Qtt_arg_val)))
582 {
583 CHECK_INT (argn);
584 n = XINT (argn);
585 }
586
587 if (!VALID_TOOLTALK_MESSAGEP (m))
588 return Qnil;
589
590 else if (EQ (attribute, Qtt_arg_bval))
591 return tt_message_arg_bval_vector (m, n);
592
593 else if (EQ (attribute, Qtt_arg_ival))
594 return tt_message_arg_ival_string (m, n);
595
596 else if (EQ (attribute, Qtt_arg_mode))
597 return tt_mode_symbol (tt_message_arg_mode (m, n));
598
599 else if (EQ (attribute, Qtt_arg_type))
600 return tt_build_string (tt_message_arg_type (m, n));
601
602 else if (EQ (attribute, Qtt_arg_val))
603 return tt_message_arg_bval_vector (m, n);
604
605 else if (EQ (attribute, Qtt_args_count))
606 return make_int (tt_message_args_count (m));
607
608 else if (EQ (attribute, Qtt_address))
609 return tt_address_symbol (tt_message_address (m));
610
611 else if (EQ (attribute, Qtt_class))
612 return tt_class_symbol (tt_message_class (m));
613
614 else if (EQ (attribute, Qtt_disposition))
615 return make_int (tt_message_disposition (m));
616
617 else if (EQ (attribute, Qtt_file))
618 return tt_build_string (tt_message_file (m));
619
620 else if (EQ (attribute, Qtt_gid))
621 return make_int (tt_message_gid (m));
622
623 else if (EQ (attribute, Qtt_handler))
624 return tt_build_string (tt_message_handler (m));
625
626 else if (EQ (attribute, Qtt_handler_ptype))
627 return tt_build_string (tt_message_handler_ptype (m));
628
629 else if (EQ (attribute, Qtt_object))
630 return tt_build_string (tt_message_object (m));
631
632 else if (EQ (attribute, Qtt_op))
633 return tt_build_string (tt_message_op (m));
634
635 else if (EQ (attribute, Qtt_opnum))
636 return tt_opnum_string (tt_message_opnum (m));
637
638 else if (EQ (attribute, Qtt_otype))
639 return tt_build_string (tt_message_otype (m));
640
641 else if (EQ (attribute, Qtt_scope))
642 return tt_scope_symbol (tt_message_scope (m));
643
644 else if (EQ (attribute, Qtt_sender))
645 return tt_build_string (tt_message_sender (m));
646
647 else if (EQ (attribute, Qtt_sender_ptype))
648 return tt_build_string (tt_message_sender_ptype (m));
649
650 else if (EQ (attribute, Qtt_session))
651 return tt_build_string (tt_message_session (m));
652
653 else if (EQ (attribute, Qtt_state))
654 return tt_state_symbol (tt_message_state (m));
655
656 else if (EQ (attribute, Qtt_status))
657 return make_int (tt_message_status (m));
658
659 else if (EQ (attribute, Qtt_status_string))
660 return tt_build_string (tt_message_status_string (m));
661
662 else if (EQ (attribute, Qtt_uid))
663 return make_int (tt_message_uid (m));
664
665 else if (EQ (attribute, Qtt_callback))
666 return XTOOLTALK_MESSAGE (message_)->callback;
667
668 else if (EQ (attribute, Qtt_prop))
669 return Fget (XTOOLTALK_MESSAGE (message_)->plist_sym, argn, Qnil);
670
671 else if (EQ (attribute, Qtt_plist))
672 return Fcopy_sequence (Fsymbol_plist
673 (XTOOLTALK_MESSAGE (message_)->plist_sym));
674
675 else
676 signal_simple_error ("Invalid value for `get-tooltalk-message-attribute'",
677 attribute);
678
679 return Qnil;
680 }
681
682 DEFUN ("set-tooltalk-message-attribute", Fset_tooltalk_message_attribute,
683 3, 4, 0, /*
684 Initialize one Tooltalk message attribute.
685
686 Attribute names and values are the same as for
687 `get-tooltalk-message-attribute'. A property list is provided for user
688 data (instead of the 'user message attribute); see
689 `get-tooltalk-message-attribute'.
690
691 The value of callback should be the name of a function of one argument.
692 It will be applied to the message and matching pattern each time the state of the
693 message changes. This is usually used to notice when the messages state has
694 changed to TT_HANDLED (or TT_FAILED), so that reply argument values
695 can be used.
696
697 If one of the argument attributes is specified, 'arg_val, 'arg_ival, or
698 'arg_bval then argn must be the number of an already created argument.
699 New arguments can be added to a message with add-tooltalk-message-arg.
700 */
701 (value, message_, attribute, argn))
702 {
703 Tt_message m = unbox_tooltalk_message (message_);
704 int n = 0;
705
706 CHECK_SYMBOL (attribute);
707 if (EQ (attribute, (Qtt_arg_bval)) ||
708 EQ (attribute, (Qtt_arg_ival)) ||
709 EQ (attribute, (Qtt_arg_val)))
710 {
711 CHECK_INT (argn);
712 n = XINT (argn);
713 }
714
715 if (!VALID_TOOLTALK_MESSAGEP (m))
716 return Qnil;
717
718 else if (EQ (attribute, Qtt_address))
719 {
720 CHECK_TOOLTALK_CONSTANT (value);
721 tt_message_address_set (m, (Tt_address) tooltalk_constant_value (value));
722 }
723 else if (EQ (attribute, Qtt_class))
724 {
725 CHECK_TOOLTALK_CONSTANT (value);
726 tt_message_class_set (m, (Tt_class) tooltalk_constant_value (value));
727 }
728 else if (EQ (attribute, Qtt_disposition))
729 {
730 CHECK_TOOLTALK_CONSTANT (value);
731 tt_message_disposition_set (m, ((Tt_disposition)
732 tooltalk_constant_value (value)));
733 }
734 else if (EQ (attribute, Qtt_file))
735 {
736 CONST char *value_ext;
737 CHECK_STRING (value);
738 GET_C_STRING_OS_DATA_ALLOCA (value, value_ext);
739 tt_message_file_set (m, value_ext);
740 }
741 else if (EQ (attribute, Qtt_handler_ptype))
742 {
743 CONST char *value_ext;
744 CHECK_STRING (value);
745 GET_C_STRING_OS_DATA_ALLOCA (value, value_ext);
746 tt_message_handler_ptype_set (m, value_ext);
747 }
748 else if (EQ (attribute, Qtt_handler))
749 {
750 CONST char *value_ext;
751 CHECK_STRING (value);
752 GET_C_STRING_OS_DATA_ALLOCA (value, value_ext);
753 tt_message_handler_set (m, value_ext);
754 }
755 else if (EQ (attribute, Qtt_object))
756 {
757 CONST char *value_ext;
758 CHECK_STRING (value);
759 GET_C_STRING_OS_DATA_ALLOCA (value, value_ext);
760 tt_message_object_set (m, value_ext);
761 }
762 else if (EQ (attribute, Qtt_op))
763 {
764 CONST char *value_ext;
765 CHECK_STRING (value);
766 GET_C_STRING_OS_DATA_ALLOCA (value, value_ext);
767 tt_message_op_set (m, value_ext);
768 }
769 else if (EQ (attribute, Qtt_otype))
770 {
771 CONST char *value_ext;
772 CHECK_STRING (value);
773 GET_C_STRING_OS_DATA_ALLOCA (value, value_ext);
774 tt_message_otype_set (m, value_ext);
775 }
776 else if (EQ (attribute, Qtt_scope))
777 {
778 CHECK_TOOLTALK_CONSTANT (value);
779 tt_message_scope_set (m, (Tt_scope) tooltalk_constant_value (value));
780 }
781 else if (EQ (attribute, Qtt_sender_ptype))
782 {
783 CONST char *value_ext;
784 CHECK_STRING (value);
785 GET_C_STRING_OS_DATA_ALLOCA (value, value_ext);
786 tt_message_sender_ptype_set (m, value_ext);
787 }
788 else if (EQ (attribute, Qtt_session))
789 {
790 CONST char *value_ext;
791 CHECK_STRING (value);
792 GET_C_STRING_OS_DATA_ALLOCA (value, value_ext);
793 tt_message_session_set (m, value_ext);
794 }
795 else if (EQ (attribute, Qtt_arg_bval))
796 {
797 Extbyte *value_ext;
798 Extcount value_ext_len;
799 CHECK_STRING (value);
800 GET_STRING_OS_DATA_ALLOCA (value, value_ext, value_ext_len);
801 tt_message_arg_bval_set (m, n, value_ext, value_ext_len);
802 }
803 else if (EQ (attribute, Qtt_arg_ival))
804 {
805 CHECK_INT (value);
806 tt_message_arg_ival_set (m, n, XINT (value));
807 }
808 else if (EQ (attribute, Qtt_arg_val))
809 {
810 CONST char *value_ext;
811 CHECK_STRING (value);
812 GET_C_STRING_OS_DATA_ALLOCA (value, value_ext);
813 tt_message_arg_val_set (m, n, value_ext);
814 }
815 else if (EQ (attribute, Qtt_status))
816 {
817 CHECK_INT (value);
818 tt_message_status_set (m, XINT (value));
819 }
820 else if (EQ (attribute, Qtt_status_string))
821 {
822 CONST char *value_ext;
823 CHECK_STRING (value);
824 GET_C_STRING_OS_DATA_ALLOCA (value, value_ext);
825 tt_message_status_string_set (m, value_ext);
826 }
827 else if (EQ (attribute, Qtt_callback))
828 {
829 CHECK_SYMBOL (value);
830 XTOOLTALK_MESSAGE (message_)->callback = value;
831 }
832 else if (EQ (attribute, Qtt_prop))
833 {
834 return Fput (XTOOLTALK_MESSAGE (message_)->plist_sym, argn, value);
835 }
836 else
837 signal_simple_error ("Invalid value for `set-tooltalk-message-attribute'",
838 attribute);
839 return Qnil;
840 }
841
842 DEFUN ("return-tooltalk-message", Freturn_tooltalk_message, 1, 2, 0, /*
843 Send a reply to this message. The second argument can be
844 'reply, 'reject or 'fail; the default is 'reply. Before sending
845 a reply all message arguments whose mode is TT_INOUT or TT_OUT should
846 have been filled in - see set-tooltalk-message-attribute.
847 */
848 (message_, mode))
849 {
850 Tt_message m = unbox_tooltalk_message (message_);
851
852 if (NILP (mode))
853 mode = Qtt_reply;
854 else
855 CHECK_SYMBOL (mode);
856
857 if (!VALID_TOOLTALK_MESSAGEP (m))
858 return Qnil;
859 else if (EQ (mode, Qtt_reply))
860 tt_message_reply (m);
861 else if (EQ (mode, Qtt_reject))
862 tt_message_reject (m);
863 else if (EQ (mode, Qtt_fail))
864 tt_message_fail (m);
865
866 return Qnil;
867 }
868
869 DEFUN ("create-tooltalk-message", Fcreate_tooltalk_message, 0, 1, 0, /*
870 Create a new tooltalk message.
871 The messages session attribute is initialized to the default session.
872 Other attributes can be initialized with `set-tooltalk-message-attribute'.
873 `make-tooltalk-message' is the preferred to create and initialize a message.
874
875 Optional arg NO-CALLBACK says don't add a C-level callback at all.
876 Normally don't do that; just don't specify the Lisp callback when
877 calling `make-tooltalk-message'.
878 */
879 (no_callback))
880 {
881 Tt_message m = tt_message_create ();
882 Lisp_Object message_ = make_tooltalk_message (m);
883 if (NILP (no_callback))
884 {
885 tt_message_callback_add (m, tooltalk_message_callback);
886 }
887 tt_message_session_set (m, tt_default_session ());
888 tt_message_user_set (m, TOOLTALK_MESSAGE_KEY, LISP_TO_VOID (message_));
889 return message_;
890 }
891
892 DEFUN ("destroy-tooltalk-message", Fdestroy_tooltalk_message, 1, 1, 0, /*
893 Apply tt_message_destroy() to the message.
894 It's not necessary to destroy messages after they've been processed by
895 a message or pattern callback; the Lisp/Tooltalk callback machinery does
896 this for you.
897 */
898 (message_))
899 {
900 Tt_message m = unbox_tooltalk_message (message_);
901
902 if (VALID_TOOLTALK_MESSAGEP (m))
903 /* #### Should we call Fremhash() here? It seems that
904 a common paradigm is
905
906 (send-tooltalk-message)
907 (destroy-tooltalk-message)
908
909 which would imply that destroying a sent ToolTalk message
910 doesn't actually destroy it; when a response is sent back,
911 the callback for the message will still be called.
912
913 But then maybe not: Maybe it really does destroy it,
914 and the reason for that paradigm is that the author
915 of `send-tooltalk-message' didn't really know what he
916 was talking about when he said that it's a good idea
917 to call `destroy-tooltalk-message' after sending it. */
918 tt_message_destroy (m);
919
920 return Qnil;
921 }
922
923
924 DEFUN ("add-tooltalk-message-arg", Fadd_tooltalk_message_arg, 3, 4, 0, /*
925 Append one new argument to the message.
926 MODE must be one of TT_IN, TT_INOUT, or TT_OUT; VTYPE must be a string;
927 and VALUE can be a string or an integer. Tooltalk doesn't
928 define any semantics for VTYPE, so only the participants in the
929 protocol you're using need to agree what types mean (if anything).
930 Conventionally "string" is used for strings and "int" for 32 bit integers.
931 Arguments can initialized by providing a value or with
932 `set-tooltalk-message-attribute'. The latter is necessary if you
933 want to initialize the argument with a string that can contain
934 embedded nulls (use 'arg_bval).
935 */
936 (message_, mode, vtype, value))
937 {
938 Tt_message m = unbox_tooltalk_message (message_);
939 Tt_mode n;
940
941 CHECK_STRING (vtype);
942 CHECK_TOOLTALK_CONSTANT (mode);
943
944 n = (Tt_mode) tooltalk_constant_value (mode);
945
946 if (!VALID_TOOLTALK_MESSAGEP (m))
947 return Qnil;
948 {
949 CONST char *vtype_ext;
950
951 GET_C_STRING_OS_DATA_ALLOCA (vtype, vtype_ext);
952 if (NILP (value))
953 tt_message_arg_add (m, n, vtype_ext, NULL);
954 else if (STRINGP (value))
955 {
956 CONST char *value_ext;
957 GET_C_STRING_OS_DATA_ALLOCA (value, value_ext);
958 tt_message_arg_add (m, n, vtype_ext, value_ext);
959 }
960 else if (INTP (value))
961 tt_message_iarg_add (m, n, vtype_ext, XINT (value));
962 }
963
964 return Qnil;
965 }
966
967 DEFUN ("send-tooltalk-message", Fsend_tooltalk_message, 1, 1, 0, /*
968 Send the message on its way.
969 Once the message has been sent it's almost always a good idea to get rid of
970 it with `destroy-tooltalk-message'.
971 */
972 (message_))
973 {
974 Tt_message m = unbox_tooltalk_message (message_);
975
976 if (VALID_TOOLTALK_MESSAGEP (m))
977 {
978 tt_message_send (m);
979 Fputhash (message_, Qnil, Vtooltalk_message_gcpro);
980 }
981
982 return Qnil;
983 }
984
985 DEFUN ("create-tooltalk-pattern", Fcreate_tooltalk_pattern, 0, 0, 0, /*
986 Create a new Tooltalk pattern.
987 Its session attribute is initialized to be the default session.
988 */
989 ())
990 {
991 Tt_pattern p = tt_pattern_create ();
992 Lisp_Object pattern = make_tooltalk_pattern (p);
993
994 tt_pattern_callback_add (p, tooltalk_pattern_callback);
995 tt_pattern_session_add (p, tt_default_session ());
996 tt_pattern_user_set (p, TOOLTALK_PATTERN_KEY, LISP_TO_VOID (pattern));
997
998 return pattern;
999 }
1000
1001
1002 DEFUN ("destroy-tooltalk-pattern", Fdestroy_tooltalk_pattern, 1, 1, 0, /*
1003 Apply tt_pattern_destroy() to the pattern.
1004 This effectively unregisters the pattern.
1005 */
1006 (pattern))
1007 {
1008 Tt_pattern p = unbox_tooltalk_pattern (pattern);
1009
1010 if (VALID_TOOLTALK_PATTERNP (p))
1011 {
1012 tt_pattern_destroy (p);
1013 Fremhash (pattern, Vtooltalk_pattern_gcpro);
1014 }
1015
1016 return Qnil;
1017 }
1018
1019
1020 DEFUN ("add-tooltalk-pattern-attribute", Fadd_tooltalk_pattern_attribute, 3, 3, 0, /*
1021 Add one value to the indicated pattern attribute.
1022 All Tooltalk pattern attributes are supported except 'user. The names
1023 of attributes are the same as the Tooltalk accessors used to set them
1024 less the "tooltalk_pattern_" prefix and the "_add" ...
1025 */
1026 (value, pattern, attribute))
1027 {
1028 Tt_pattern p = unbox_tooltalk_pattern (pattern);
1029
1030 CHECK_SYMBOL (attribute);
1031
1032 if (!VALID_TOOLTALK_PATTERNP (p))
1033 return Qnil;
1034
1035 else if (EQ (attribute, Qtt_category))
1036 {
1037 CHECK_TOOLTALK_CONSTANT (value);
1038 tt_pattern_category_set (p, ((Tt_category)
1039 tooltalk_constant_value (value)));
1040 }
1041 else if (EQ (attribute, Qtt_address))
1042 {
1043 CHECK_TOOLTALK_CONSTANT (value);
1044 tt_pattern_address_add (p, ((Tt_address)
1045 tooltalk_constant_value (value)));
1046 }
1047 else if (EQ (attribute, Qtt_class))
1048 {
1049 CHECK_TOOLTALK_CONSTANT (value);
1050 tt_pattern_class_add (p, (Tt_class) tooltalk_constant_value (value));
1051 }
1052 else if (EQ (attribute, Qtt_disposition))
1053 {
1054 CHECK_TOOLTALK_CONSTANT (value);
1055 tt_pattern_disposition_add (p, ((Tt_disposition)
1056 tooltalk_constant_value (value)));
1057 }
1058 else if (EQ (attribute, Qtt_file))
1059 {
1060 CONST char *value_ext;
1061 CHECK_STRING (value);
1062 GET_C_STRING_OS_DATA_ALLOCA (value, value_ext);
1063 tt_pattern_file_add (p, value_ext);
1064 }
1065 else if (EQ (attribute, Qtt_object))
1066 {
1067 CONST char *value_ext;
1068 CHECK_STRING (value);
1069 GET_C_STRING_OS_DATA_ALLOCA (value, value_ext);
1070 tt_pattern_object_add (p, value_ext);
1071 }
1072 else if (EQ (attribute, Qtt_op))
1073 {
1074 CONST char *value_ext;
1075 CHECK_STRING (value);
1076 GET_C_STRING_OS_DATA_ALLOCA (value, value_ext);
1077 tt_pattern_op_add (p, value_ext);
1078 }
1079 else if (EQ (attribute, Qtt_otype))
1080 {
1081 CONST char *value_ext;
1082 CHECK_STRING (value);
1083 GET_C_STRING_OS_DATA_ALLOCA (value, value_ext);
1084 tt_pattern_otype_add (p, value_ext);
1085 }
1086 else if (EQ (attribute, Qtt_scope))
1087 {
1088 CHECK_TOOLTALK_CONSTANT (value);
1089 tt_pattern_scope_add (p, (Tt_scope) tooltalk_constant_value (value));
1090 }
1091 else if (EQ (attribute, Qtt_sender))
1092 {
1093 CONST char *value_ext;
1094 CHECK_STRING (value);
1095 GET_C_STRING_OS_DATA_ALLOCA (value, value_ext);
1096 tt_pattern_sender_add (p, value_ext);
1097 }
1098 else if (EQ (attribute, Qtt_sender_ptype))
1099 {
1100 CONST char *value_ext;
1101 CHECK_STRING (value);
1102 GET_C_STRING_OS_DATA_ALLOCA (value, value_ext);
1103 tt_pattern_sender_ptype_add (p, value_ext);
1104 }
1105 else if (EQ (attribute, Qtt_session))
1106 {
1107 CONST char *value_ext;
1108 CHECK_STRING (value);
1109 GET_C_STRING_OS_DATA_ALLOCA (value, value_ext);
1110 tt_pattern_session_add (p, value_ext);
1111 }
1112 else if (EQ (attribute, Qtt_state))
1113 {
1114 CHECK_TOOLTALK_CONSTANT (value);
1115 tt_pattern_state_add (p, (Tt_state) tooltalk_constant_value (value));
1116 }
1117 else if (EQ (attribute, Qtt_callback))
1118 {
1119 CHECK_SYMBOL (value);
1120 XTOOLTALK_PATTERN (pattern)->callback = value;
1121 }
1122
1123 return Qnil;
1124 }
1125
1126
1127 DEFUN ("add-tooltalk-pattern-arg", Fadd_tooltalk_pattern_arg, 3, 4, 0, /*
1128 Add one fully specified argument to a tooltalk pattern.
1129 Mode must be one of TT_IN, TT_INOUT, or TT_OUT, type must be a string.
1130 Value can be an integer, string or nil. If value is an integer then
1131 an integer argument (tt_pattern_iarg_add) added otherwise a string argument
1132 is added. At present there's no way to add a binary data argument.
1133 */
1134 (pattern, mode, vtype, value))
1135 {
1136 Tt_pattern p = unbox_tooltalk_pattern (pattern);
1137 Tt_mode n;
1138
1139 CHECK_STRING (vtype);
1140 CHECK_TOOLTALK_CONSTANT (mode);
1141
1142 n = (Tt_mode) tooltalk_constant_value (mode);
1143
1144 if (!VALID_TOOLTALK_PATTERNP (p))
1145 return Qnil;
1146
1147 {
1148 CONST char *vtype_ext;
1149
1150 GET_C_STRING_OS_DATA_ALLOCA (vtype, vtype_ext);
1151 if (NILP (value))
1152 tt_pattern_arg_add (p, n, vtype_ext, NULL);
1153 else if (STRINGP (value))
1154 {
1155 CONST char *value_ext;
1156 GET_C_STRING_OS_DATA_ALLOCA (value, value_ext);
1157 tt_pattern_arg_add (p, n, vtype_ext, value_ext);
1158 }
1159 else if (INTP (value))
1160 tt_pattern_iarg_add (p, n, vtype_ext, XINT (value));
1161 }
1162
1163 return Qnil;
1164 }
1165
1166
1167 DEFUN ("register-tooltalk-pattern", Fregister_tooltalk_pattern, 1, 1, 0, /*
1168 Emacs will begin receiving messages that match this pattern.
1169 */
1170 (pattern))
1171 {
1172 Tt_pattern p = unbox_tooltalk_pattern (pattern);
1173
1174 if (VALID_TOOLTALK_PATTERNP (p) && tt_pattern_register (p) == TT_OK)
1175 {
1176 Fputhash (pattern, Qnil, Vtooltalk_pattern_gcpro);
1177 return Qt;
1178 }
1179 else
1180 return Qnil;
1181 }
1182
1183
1184 DEFUN ("unregister-tooltalk-pattern", Funregister_tooltalk_pattern, 1, 1, 0, /*
1185 Emacs will stop receiving messages that match this pattern.
1186 */
1187 (pattern))
1188 {
1189 Tt_pattern p = unbox_tooltalk_pattern (pattern);
1190
1191 if (VALID_TOOLTALK_PATTERNP (p))
1192 {
1193 tt_pattern_unregister (p);
1194 Fremhash (pattern, Vtooltalk_pattern_gcpro);
1195 }
1196
1197 return Qnil;
1198 }
1199
1200
1201 DEFUN ("tooltalk-pattern-prop-get", Ftooltalk_pattern_prop_get, 2, 2, 0, /*
1202 Return the value of PROPERTY in tooltalk pattern PATTERN.
1203 This is the last value set with `tooltalk-pattern-prop-set'.
1204 */
1205 (pattern, property))
1206 {
1207 CHECK_TOOLTALK_PATTERN (pattern);
1208 return Fget (XTOOLTALK_PATTERN (pattern)->plist_sym, property, Qnil);
1209 }
1210
1211
1212 DEFUN ("tooltalk-pattern-prop-set", Ftooltalk_pattern_prop_set, 3, 3, 0, /*
1213 Set the value of PROPERTY to VALUE in tooltalk pattern PATTERN.
1214 It can be retrieved with `tooltalk-pattern-prop-get'.
1215 */
1216 (pattern, property, value))
1217 {
1218 CHECK_TOOLTALK_PATTERN (pattern);
1219 return Fput (XTOOLTALK_PATTERN (pattern)->plist_sym, property, value);
1220 }
1221
1222
1223 DEFUN ("tooltalk-pattern-plist-get", Ftooltalk_pattern_plist_get, 1, 1, 0, /*
1224 Return the a list of all the properties currently set in PATTERN.
1225 */
1226 (pattern))
1227 {
1228 CHECK_TOOLTALK_PATTERN (pattern);
1229 return
1230 Fcopy_sequence (Fsymbol_plist (XTOOLTALK_PATTERN (pattern)->plist_sym));
1231 }
1232
1233 DEFUN ("tooltalk-default-procid", Ftooltalk_default_procid, 0, 0, 0, /*
1234 Return current default process identifier for your process.
1235 */
1236 ())
1237 {
1238 char *procid = tt_default_procid ();
1239 return procid ? build_string (procid) : Qnil;
1240 }
1241
1242 DEFUN ("tooltalk-default-session", Ftooltalk_default_session, 0, 0, 0, /*
1243 Return current default session identifier for the current default procid.
1244 */
1245 ())
1246 {
1247 char *session = tt_default_session ();
1248 return session ? build_string (session) : Qnil;
1249 }
1250
1251 static void
1252 init_tooltalk (void)
1253 {
1254 /* This function can GC */
1255 char *retval;
1256 Lisp_Object lp;
1257 Lisp_Object fil;
1258
1259
1260 /* tt_open() messes with our signal handler flags (at least when no
1261 ttsessions is running on the machine), therefore we save the
1262 actions and restore them after the call */
1263 #ifdef HAVE_SIGPROCMASK
1264 {
1265 struct sigaction ActSIGQUIT;
1266 struct sigaction ActSIGINT;
1267 struct sigaction ActSIGCHLD;
1268 sigaction (SIGQUIT, NULL, &ActSIGQUIT);
1269 sigaction (SIGINT, NULL, &ActSIGINT);
1270 sigaction (SIGCHLD, NULL, &ActSIGCHLD);
1271 #endif
1272 retval = tt_open ();
1273 #ifdef HAVE_SIGPROCMASK
1274 sigaction (SIGQUIT, &ActSIGQUIT, NULL);
1275 sigaction (SIGINT, &ActSIGINT, NULL);
1276 sigaction (SIGCHLD, &ActSIGCHLD, NULL);
1277 }
1278 #endif
1279
1280
1281 if (tt_ptr_error (retval) != TT_OK)
1282 return;
1283
1284 Vtooltalk_fd = make_int (tt_fd ());
1285
1286 tt_session_join (tt_default_session ());
1287
1288 lp = connect_to_file_descriptor (build_string ("tooltalk"), Qnil,
1289 Vtooltalk_fd, Vtooltalk_fd);
1290 if (!NILP (lp))
1291 {
1292 /* Don't ask the user for confirmation when exiting Emacs */
1293 Fprocess_kill_without_query (lp, Qnil);
1294 XSETSUBR (fil, &SFreceive_tooltalk_message);
1295 set_process_filter (lp, fil, 1);
1296 }
1297 else
1298 {
1299 tt_close ();
1300 Vtooltalk_fd = Qnil;
1301 return;
1302 }
1303
1304 #if defined (SOLARIS2)
1305 /* Apparently the tt_message_send_on_exit() function does not exist
1306 under SunOS 4.x or IRIX 5 or various other non-Solaris-2 systems.
1307 No big deal if we don't do the following under those systems. */
1308 {
1309 Tt_message exit_msg = tt_message_create ();
1310
1311 tt_message_op_set (exit_msg, "emacs-aborted");
1312 tt_message_scope_set (exit_msg, TT_SESSION);
1313 tt_message_class_set (exit_msg, TT_NOTICE);
1314 tt_message_send_on_exit (exit_msg);
1315 tt_message_destroy (exit_msg);
1316 }
1317 #endif
1318 }
1319
1320 DEFUN ("tooltalk-open-connection", Ftooltalk_open_connection, 0, 0, 0, /*
1321 Opens a connection to the ToolTalk server.
1322 Returns t if successful, nil otherwise.
1323 */
1324 ())
1325 {
1326 if (!NILP (Vtooltalk_fd))
1327 error ("Already connected to ToolTalk.");
1328 if (noninteractive)
1329 error ("Can't connect to ToolTalk in batch mode.");
1330 init_tooltalk ();
1331 return NILP (Vtooltalk_fd) ? Qnil : Qt;
1332 }
1333
1334
1335 void
1336 syms_of_tooltalk (void)
1337 {
1338 defsymbol (&Qtooltalk_messagep, "tooltalk-message-p");
1339 DEFSUBR (Ftooltalk_message_p);
1340 defsymbol (&Qtooltalk_patternp, "tooltalk-pattern-p");
1341 DEFSUBR (Ftooltalk_pattern_p);
1342 defsymbol (&Qtooltalk_message_handler_hook, "tooltalk-message-handler-hook");
1343 defsymbol (&Qtooltalk_pattern_handler_hook, "tooltalk-pattern-handler-hook");
1344 defsymbol (&Qtooltalk_unprocessed_message_hook,
1345 "tooltalk-unprocessed-message-hook");
1346
1347 DEFSUBR (Freceive_tooltalk_message);
1348 DEFSUBR (Fcreate_tooltalk_message);
1349 DEFSUBR (Fdestroy_tooltalk_message);
1350 DEFSUBR (Fadd_tooltalk_message_arg);
1351 DEFSUBR (Fget_tooltalk_message_attribute);
1352 DEFSUBR (Fset_tooltalk_message_attribute);
1353 DEFSUBR (Fsend_tooltalk_message);
1354 DEFSUBR (Freturn_tooltalk_message);
1355 DEFSUBR (Fcreate_tooltalk_pattern);
1356 DEFSUBR (Fdestroy_tooltalk_pattern);
1357 DEFSUBR (Fadd_tooltalk_pattern_attribute);
1358 DEFSUBR (Fadd_tooltalk_pattern_arg);
1359 DEFSUBR (Fregister_tooltalk_pattern);
1360 DEFSUBR (Funregister_tooltalk_pattern);
1361 DEFSUBR (Ftooltalk_pattern_plist_get);
1362 DEFSUBR (Ftooltalk_pattern_prop_set);
1363 DEFSUBR (Ftooltalk_pattern_prop_get);
1364 DEFSUBR (Ftooltalk_default_procid);
1365 DEFSUBR (Ftooltalk_default_session);
1366 DEFSUBR (Ftooltalk_open_connection);
1367
1368 defsymbol (&Qreceive_tooltalk_message, "receive-tooltalk-message");
1369 defsymbol (&Qtt_address, "address");
1370 defsymbol (&Qtt_args_count, "args_count");
1371 defsymbol (&Qtt_arg_bval, "arg_bval");
1372 defsymbol (&Qtt_arg_ival, "arg_ival");
1373 defsymbol (&Qtt_arg_mode, "arg_mode");
1374 defsymbol (&Qtt_arg_type, "arg_type");
1375 defsymbol (&Qtt_arg_val, "arg_val");
1376 defsymbol (&Qtt_class, "class");
1377 defsymbol (&Qtt_category, "category");
1378 defsymbol (&Qtt_disposition, "disposition");
1379 defsymbol (&Qtt_file, "file");
1380 defsymbol (&Qtt_gid, "gid");
1381 defsymbol (&Qtt_handler, "handler");
1382 defsymbol (&Qtt_handler_ptype, "handler_ptype");
1383 defsymbol (&Qtt_object, "object");
1384 defsymbol (&Qtt_op, "op");
1385 defsymbol (&Qtt_opnum, "opnum");
1386 defsymbol (&Qtt_otype, "otype");
1387 defsymbol (&Qtt_scope, "scope");
1388 defsymbol (&Qtt_sender, "sender");
1389 defsymbol (&Qtt_sender_ptype, "sender_ptype");
1390 defsymbol (&Qtt_session, "session");
1391 defsymbol (&Qtt_state, "state");
1392 defsymbol (&Qtt_status, "status");
1393 defsymbol (&Qtt_status_string, "status_string");
1394 defsymbol (&Qtt_uid, "uid");
1395 defsymbol (&Qtt_callback, "callback");
1396 defsymbol (&Qtt_prop, "prop");
1397 defsymbol (&Qtt_plist, "plist");
1398 defsymbol (&Qtt_reject, "reject");
1399 defsymbol (&Qtt_reply, "reply");
1400 defsymbol (&Qtt_fail, "fail");
1401
1402 deferror (&Qtooltalk_error, "tooltalk-error", "ToolTalk error", Qio_error);
1403 }
1404
1405 void
1406 vars_of_tooltalk (void)
1407 {
1408 Fprovide (intern ("tooltalk"));
1409
1410 DEFVAR_LISP ("tooltalk-fd", &Vtooltalk_fd /*
1411 File descriptor returned by tt_initialize; nil if not connected to ToolTalk.
1412 */ );
1413 Vtooltalk_fd = Qnil;
1414
1415 DEFVAR_LISP ("tooltalk-message-handler-hook",
1416 &Vtooltalk_message_handler_hook /*
1417 List of functions to be applied to each ToolTalk message reply received.
1418 This will always occur as a result of our sending a request message.
1419 Functions will be called with two arguments, the message and the
1420 corresponding pattern. This hook will not be called if the request
1421 message was created without a C-level callback function (see
1422 `tooltalk-unprocessed-message-hook').
1423 */ );
1424 Vtooltalk_message_handler_hook = Qnil;
1425
1426 DEFVAR_LISP ("tooltalk-pattern-handler-hook",
1427 &Vtooltalk_pattern_handler_hook /*
1428 List of functions to be applied to each pattern-matching ToolTalk message.
1429 This is all messages except those handled by `tooltalk-message-handler-hook'.
1430 Functions will be called with two arguments, the message and the
1431 corresponding pattern.
1432 */ );
1433 Vtooltalk_pattern_handler_hook = Qnil;
1434
1435 DEFVAR_LISP ("tooltalk-unprocessed-message-hook",
1436 &Vtooltalk_unprocessed_message_hook /*
1437 List of functions to be applied to each unprocessed ToolTalk message.
1438 Unprocessed messages are messages that didn't match any patterns.
1439 */ );
1440 Vtooltalk_unprocessed_message_hook = Qnil;
1441
1442 Tooltalk_Message_plist_str = build_string ("Tooltalk Message plist");
1443 Tooltalk_Pattern_plist_str = build_string ("Tooltalk Pattern p plist");
1444
1445 staticpro(&Tooltalk_Message_plist_str);
1446 staticpro(&Tooltalk_Pattern_plist_str);
1447
1448 #define MAKE_CONSTANT(name) do { \
1449 defsymbol (&Q_ ## name, #name); \
1450 Fset (Q_ ## name, make_int (name)); \
1451 } while (0)
1452
1453 MAKE_CONSTANT (TT_MODE_UNDEFINED);
1454 MAKE_CONSTANT (TT_IN);
1455 MAKE_CONSTANT (TT_OUT);
1456 MAKE_CONSTANT (TT_INOUT);
1457 MAKE_CONSTANT (TT_MODE_LAST);
1458
1459 MAKE_CONSTANT (TT_SCOPE_NONE);
1460 MAKE_CONSTANT (TT_SESSION);
1461 MAKE_CONSTANT (TT_FILE);
1462 MAKE_CONSTANT (TT_BOTH);
1463 MAKE_CONSTANT (TT_FILE_IN_SESSION);
1464
1465 MAKE_CONSTANT (TT_CLASS_UNDEFINED);
1466 MAKE_CONSTANT (TT_NOTICE);
1467 MAKE_CONSTANT (TT_REQUEST);
1468 MAKE_CONSTANT (TT_CLASS_LAST);
1469
1470 MAKE_CONSTANT (TT_CATEGORY_UNDEFINED);
1471 MAKE_CONSTANT (TT_OBSERVE);
1472 MAKE_CONSTANT (TT_HANDLE);
1473 MAKE_CONSTANT (TT_CATEGORY_LAST);
1474
1475 MAKE_CONSTANT (TT_PROCEDURE);
1476 MAKE_CONSTANT (TT_OBJECT);
1477 MAKE_CONSTANT (TT_HANDLER);
1478 MAKE_CONSTANT (TT_OTYPE);
1479 MAKE_CONSTANT (TT_ADDRESS_LAST);
1480
1481 MAKE_CONSTANT (TT_CREATED);
1482 MAKE_CONSTANT (TT_SENT);
1483 MAKE_CONSTANT (TT_HANDLED);
1484 MAKE_CONSTANT (TT_FAILED);
1485 MAKE_CONSTANT (TT_QUEUED);
1486 MAKE_CONSTANT (TT_STARTED);
1487 MAKE_CONSTANT (TT_REJECTED);
1488 MAKE_CONSTANT (TT_STATE_LAST);
1489
1490 MAKE_CONSTANT (TT_DISCARD);
1491 MAKE_CONSTANT (TT_QUEUE);
1492 MAKE_CONSTANT (TT_START);
1493
1494 #undef MAKE_CONSTANT
1495
1496 staticpro (&Vtooltalk_message_gcpro);
1497 staticpro (&Vtooltalk_pattern_gcpro);
1498 Vtooltalk_message_gcpro =
1499 make_lisp_hash_table (10, HASH_TABLE_NON_WEAK, HASH_TABLE_EQ);
1500 Vtooltalk_pattern_gcpro =
1501 make_lisp_hash_table (10, HASH_TABLE_NON_WEAK, HASH_TABLE_EQ);
1502 }