comparison src/tooltalk.c @ 0:376386a54a3c r19-14

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