2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these libraries and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 //%% (c) Copyright 1993, 1994 Hewlett-Packard Company
24 //%% (c) Copyright 1993, 1994 International Business Machines Corp.
25 //%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
26 //%% (c) Copyright 1993, 1994 Novell, Inc.
27 //%% $TOG: tttkmessage.C /main/5 1998/03/19 18:34:28 mgreess $
29 * @(#)tttkmessage.C 1.3 93/09/07
31 * Copyright 1993 Sun Microsystems, Inc. All rights reserved.
33 #include "api/c/tt_c.h"
34 #include "api/c/api_mp.h"
35 #include "tttk/tttk.h"
36 #include "tttk/tttkpattern.h"
37 #include "tttk/tttkmessage.h"
38 #include "tttk/tttk2free.h"
39 #include "tttk/tttkutils.h"
42 tttk_message_create( // XXX propagate contexts
48 Tt_message_callback callback
51 Tt_message msg = tt_message_create();
52 Tt_status status = tt_ptr_error( msg );
53 if (status != TT_OK) {
56 // fuse msg for automatic destruction if we return before defusing
57 _TttkItem2Free temp = msg;
58 status = tt_message_class_set( msg, theClass );
59 if (status != TT_OK) {
60 return (Tt_message)tt_error_pointer( status );
62 status = tt_message_scope_set( msg, theScope );
63 if (status != TT_OK) {
64 return (Tt_message)tt_error_pointer( status );
66 Tt_address address = TT_PROCEDURE;
68 status = tt_message_handler_set( msg, handler );
69 if (status != TT_OK) {
70 return (Tt_message)tt_error_pointer( status );
74 status = tt_message_address_set( msg, address );
75 if (status != TT_OK) {
76 return (Tt_message)tt_error_pointer( status );
79 status = tt_message_op_set( msg, op );
80 if (status != TT_OK) {
81 return (Tt_message)tt_error_pointer( status );
85 status = tt_message_callback_add( msg, callback );
86 if (status != TT_OK) {
87 return (Tt_message)tt_error_pointer( status );
90 temp = (caddr_t)0; // defuse
94 // extern "C" { extern Tt_status _tt_message_destroy( Tt_message ); }
103 pats1 = (Tt_pattern *)tt_message_user( msg, _TttkContractKey );
104 pats2 = (Tt_pattern *)tt_message_user( msg, _TttkSubContractKey );
105 Tt_status status = _tt_message_destroy( msg );
106 if (status != TT_WRN_STOPPED) {
107 _tttk_patterns_destroy( pats1 );
108 _tttk_patterns_destroy( pats2 );
114 // This is the only message callback we ever use. It retrieves
115 // the clientdata, client callback, and a tttk internal callback.
116 // That internal callback will parse the message and pass the
117 // info (along with the clientdata) to the client callback.
125 _TtDtMessageCB cb = (_TtDtMessageCB)
126 tt_message_user( msg, _TttkCBKey );
127 Tt_status status = tt_ptr_error( cb );
128 if (status != TT_OK) {
129 return TT_CALLBACK_PROCESSED;
132 return TT_CALLBACK_CONTINUE;
134 void *clientCB = tt_message_user( msg, _TttkClientCBKey );
135 status = tt_ptr_error( clientCB );
136 if (status != TT_OK) {
137 return TT_CALLBACK_PROCESSED;
139 // clientCB is allowed to be 0. cf. ttmedia_Deposit()
140 void *clientData = tt_message_user( msg, _TttkClientDataKey );
141 status = tt_ptr_error( clientData );
142 if (status != TT_OK) {
143 return TT_CALLBACK_PROCESSED;
145 msg = (*cb)( msg, pat, clientCB, clientData );
146 return _ttDtCallbackAction( msg );
150 // Create a message and and store on it an internal callback, a
151 // client callback, and a client datum.
165 Tt_message msg = tttk_message_create( context, theClass, theScope,
166 handler, _ttDtOp( op ), _ttDtMessageCB );
167 Tt_status status = tt_ptr_error( msg );
168 if (status != TT_OK) {
171 _TttkItem2Free fuse( msg );
172 status = tt_message_user_set( msg, _TttkCBKey, (void *)cb );
173 if (status != TT_OK) {
174 return (Tt_message)tt_error_pointer( status );
176 status = tt_message_user_set( msg, _TttkClientCBKey, clientCB );
177 if (status != TT_OK) {
178 return (Tt_message)tt_error_pointer( status );
180 status = tt_message_user_set( msg, _TttkClientDataKey, clientData );
181 if (status != TT_OK) {
182 return (Tt_message)tt_error_pointer( status );
189 // Set the status info on a message, fail or reject it, and optionally
196 const char *statusString,
201 tt_message_status_set( msg, status );
202 if (statusString != 0) {
203 tt_message_status_string_set( msg, statusString );
207 ttStatus = tt_message_reject( msg );
209 ttStatus = tt_message_fail( msg );
212 tttk_message_destroy( msg );
221 const char *statusString,
225 return _ttDtMessageGong( msg, status, statusString, 1, destroy );
232 const char *statusString,
236 if (tt_message_class( msg ) == TT_REQUEST) {
237 return _ttDtMessageGong( msg, status, statusString, 0,
239 } else if (destroy) {
240 return tttk_message_destroy( msg );
246 // Set the default procid and call tt_message_receive()
249 _tttk_message_receive(
255 status = tt_default_procid_set( procid );
256 if (status != TT_OK) {
257 return (Tt_message)tt_error_pointer( status );
260 return tt_message_receive();
264 // Used internally to reply to messages that might be edicts (i.e. notices)
271 if (tt_message_class( msg ) == TT_REQUEST) {
272 return tt_message_reply( msg );
278 tttk_message_abandon(
282 if (_tttk_message_am_handling( msg )) {
284 if (tt_message_address( msg ) == TT_HANDLER) {
286 } else if (tt_message_status( msg ) == TT_WRN_START_MESSAGE) {
290 return tttk_message_fail( msg, TT_DESKTOP_ENOTSUP,0,1);
292 return tttk_message_reject(msg, TT_DESKTOP_ENOTSUP,0,1);
295 return tttk_message_destroy( msg );
300 // Returns the sender-set message id if any, otherwise the tt_message_id()
308 int numArgs = tt_message_args_count( msg );
309 Tt_status status = tt_int_error( numArgs );
310 if (status != TT_OK) {
313 for (int i = arg; i < numArgs; i++) {
314 char *type = tt_message_arg_type( msg, i );
315 status = tt_ptr_error( type );
316 if (status != TT_OK) {
322 int miss = strcmp( type, Tttk_message_id );
327 char *msgID = tt_message_arg_val( msg, i );
328 status = tt_ptr_error( type );
329 if (status != TT_OK) {
334 return tt_message_id( msg );
338 _tttk_message_in_final_state(
342 Tt_state theState = tt_message_state( msg );
343 switch (tt_message_class( msg )) {
345 return theState == TT_SENT;
347 return (theState == TT_HANDLED) || (theState == TT_FAILED);
349 return theState == TT_RETURNED;
355 // Can I reply to this message?
358 _tttk_message_am_handling(
362 if (tt_message_class( msg ) != TT_REQUEST) {
365 if (tt_message_state( msg ) != TT_SENT) {
368 char *handler = tt_message_handler( msg );
370 if ((tt_ptr_error( handler ) == TT_OK) && (handler != 0)) {
378 // Get arg value and return default_val on error.
381 _tttk_message_arg_ival(
387 if (! _tttk_message_arg_is_set( msg, n )) {
391 Tt_status status = tt_message_arg_ival( msg, n, &val );
392 if (status != TT_OK) {
399 _tttk_message_arg_val(
402 const char *default_val
405 if (! _tttk_message_arg_is_set( msg, n )) {
406 return (char *)default_val;
408 char *val = tt_message_arg_val( msg, n );
409 Tt_status status = tt_ptr_error( val );
410 if (status != TT_OK) {
411 return (char *)default_val;
417 // Does arg n have a value?
420 _tttk_message_arg_is_set(
426 Tt_status status = tt_message_arg_ival( msg, n, &val );
427 if (status == TT_OK) {
430 if (status != TT_ERR_NUM) {
435 status = tt_message_arg_bval( msg, n, &s, &len );
436 if (status != TT_OK) {
443 // Generic _TtDtMessageCB that sets *clientData to the negated
444 // tt_message_status() of the reply (or failure) of the message.
445 // Useful when sending synchronous requests and you only care to
446 // know the Tt_status of the reply/failure.
449 _ttTkNoteReplyStatus(
456 if (! _tttk_message_in_final_state( msg )) {
459 int *result = (int *)clientData;
460 *result = -TT_DESKTOP_ETIMEDOUT;
461 switch (tt_message_state( msg )) {
466 *result = -tt_message_status( msg );
467 if (*result == -TT_OK) {
469 // The handler did not say why he failed the
470 // request, so we have to make up a reason
471 // to pass back through e.g. ttdt_Save().
473 *result = -TT_DESKTOP_EPROTO;
477 tttk_message_destroy( msg );
478 // Protect against bogus message status causing infinite loop
480 *result = -(*result);