Some files were trying to access the global includes directy in the build area with things like #include <api/c/tt_c.h>, which is now wrong. Se we fix all of those up. tt_c.h and tttk.h are now global, so we no longer need to root around various build dirs to find them. TT builds again.
484 lines
11 KiB
C
484 lines
11 KiB
C
/*
|
|
* CDE - Common Desktop Environment
|
|
*
|
|
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
|
*
|
|
* These libraries and programs are free software; you can
|
|
* redistribute them and/or modify them under the terms of the GNU
|
|
* Lesser General Public License as published by the Free Software
|
|
* Foundation; either version 2 of the License, or (at your option)
|
|
* any later version.
|
|
*
|
|
* These libraries and programs are distributed in the hope that
|
|
* they will be useful, but WITHOUT ANY WARRANTY; without even the
|
|
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
* PURPOSE. See the GNU Lesser General Public License for more
|
|
* details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with these libraries and programs; if not, write
|
|
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
* Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
//%% (c) Copyright 1993, 1994 Hewlett-Packard Company
|
|
//%% (c) Copyright 1993, 1994 International Business Machines Corp.
|
|
//%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
|
|
//%% (c) Copyright 1993, 1994 Novell, Inc.
|
|
//%% $TOG: tttkmessage.C /main/5 1998/03/19 18:34:28 mgreess $
|
|
/*
|
|
* @(#)tttkmessage.C 1.3 93/09/07
|
|
*
|
|
* Copyright 1993 Sun Microsystems, Inc. All rights reserved.
|
|
*/
|
|
#include "Tt/tt_c.h"
|
|
#include "api/c/api_mp.h"
|
|
#include "Tt/tttk.h"
|
|
#include "tttk/tttkpattern.h"
|
|
#include "tttk/tttkmessage.h"
|
|
#include "tttk/tttk2free.h"
|
|
#include "tttk/tttkutils.h"
|
|
|
|
Tt_message
|
|
tttk_message_create( // XXX propagate contexts
|
|
Tt_message ,
|
|
Tt_class theClass,
|
|
Tt_scope theScope,
|
|
const char *handler,
|
|
const char *op,
|
|
Tt_message_callback callback
|
|
)
|
|
{
|
|
Tt_message msg = tt_message_create();
|
|
Tt_status status = tt_ptr_error( msg );
|
|
if (status != TT_OK) {
|
|
return msg;
|
|
}
|
|
// fuse msg for automatic destruction if we return before defusing
|
|
_TttkItem2Free temp = msg;
|
|
status = tt_message_class_set( msg, theClass );
|
|
if (status != TT_OK) {
|
|
return (Tt_message)tt_error_pointer( status );
|
|
}
|
|
status = tt_message_scope_set( msg, theScope );
|
|
if (status != TT_OK) {
|
|
return (Tt_message)tt_error_pointer( status );
|
|
}
|
|
Tt_address address = TT_PROCEDURE;
|
|
if (handler != 0) {
|
|
status = tt_message_handler_set( msg, handler );
|
|
if (status != TT_OK) {
|
|
return (Tt_message)tt_error_pointer( status );
|
|
}
|
|
address = TT_HANDLER;
|
|
}
|
|
status = tt_message_address_set( msg, address );
|
|
if (status != TT_OK) {
|
|
return (Tt_message)tt_error_pointer( status );
|
|
}
|
|
if (op != 0) {
|
|
status = tt_message_op_set( msg, op );
|
|
if (status != TT_OK) {
|
|
return (Tt_message)tt_error_pointer( status );
|
|
}
|
|
}
|
|
if (callback != 0) {
|
|
status = tt_message_callback_add( msg, callback );
|
|
if (status != TT_OK) {
|
|
return (Tt_message)tt_error_pointer( status );
|
|
}
|
|
}
|
|
temp = (caddr_t)0; // defuse
|
|
return msg;
|
|
}
|
|
|
|
// extern "C" { extern Tt_status _tt_message_destroy( Tt_message ); }
|
|
|
|
Tt_status
|
|
tttk_message_destroy(
|
|
Tt_message msg
|
|
)
|
|
{
|
|
Tt_pattern *pats1;
|
|
Tt_pattern *pats2;
|
|
pats1 = (Tt_pattern *)tt_message_user( msg, _TttkContractKey );
|
|
pats2 = (Tt_pattern *)tt_message_user( msg, _TttkSubContractKey );
|
|
Tt_status status = _tt_message_destroy( msg );
|
|
if (status != TT_WRN_STOPPED) {
|
|
_tttk_patterns_destroy( pats1 );
|
|
_tttk_patterns_destroy( pats2 );
|
|
}
|
|
return status;
|
|
}
|
|
|
|
//
|
|
// This is the only message callback we ever use. It retrieves
|
|
// the clientdata, client callback, and a tttk internal callback.
|
|
// That internal callback will parse the message and pass the
|
|
// info (along with the clientdata) to the client callback.
|
|
//
|
|
Tt_callback_action
|
|
_ttDtMessageCB(
|
|
Tt_message msg,
|
|
Tt_pattern pat
|
|
)
|
|
{
|
|
_TtDtMessageCB cb = (_TtDtMessageCB)
|
|
tt_message_user( msg, _TttkCBKey );
|
|
Tt_status status = tt_ptr_error( cb );
|
|
if (status != TT_OK) {
|
|
return TT_CALLBACK_PROCESSED;
|
|
}
|
|
if (cb == 0) {
|
|
return TT_CALLBACK_CONTINUE;
|
|
}
|
|
void *clientCB = tt_message_user( msg, _TttkClientCBKey );
|
|
status = tt_ptr_error( clientCB );
|
|
if (status != TT_OK) {
|
|
return TT_CALLBACK_PROCESSED;
|
|
}
|
|
// clientCB is allowed to be 0. cf. ttmedia_Deposit()
|
|
void *clientData = tt_message_user( msg, _TttkClientDataKey );
|
|
status = tt_ptr_error( clientData );
|
|
if (status != TT_OK) {
|
|
return TT_CALLBACK_PROCESSED;
|
|
}
|
|
msg = (*cb)( msg, pat, clientCB, clientData );
|
|
return _ttDtCallbackAction( msg );
|
|
}
|
|
|
|
//
|
|
// Create a message and and store on it an internal callback, a
|
|
// client callback, and a client datum.
|
|
//
|
|
Tt_message
|
|
_ttDtPMessageCreate(
|
|
Tt_message context,
|
|
Tt_class theClass,
|
|
Tt_scope theScope,
|
|
const char *handler,
|
|
Tttk_op op,
|
|
_TtDtMessageCB cb,
|
|
void *clientCB,
|
|
void *clientData
|
|
)
|
|
{
|
|
Tt_message msg = tttk_message_create( context, theClass, theScope,
|
|
handler, _ttDtOp( op ), _ttDtMessageCB );
|
|
Tt_status status = tt_ptr_error( msg );
|
|
if (status != TT_OK) {
|
|
return msg;
|
|
}
|
|
_TttkItem2Free fuse( msg );
|
|
status = tt_message_user_set( msg, _TttkCBKey, (void *)cb );
|
|
if (status != TT_OK) {
|
|
return (Tt_message)tt_error_pointer( status );
|
|
}
|
|
status = tt_message_user_set( msg, _TttkClientCBKey, clientCB );
|
|
if (status != TT_OK) {
|
|
return (Tt_message)tt_error_pointer( status );
|
|
}
|
|
status = tt_message_user_set( msg, _TttkClientDataKey, clientData );
|
|
if (status != TT_OK) {
|
|
return (Tt_message)tt_error_pointer( status );
|
|
}
|
|
fuse = (caddr_t)0;
|
|
return msg;
|
|
}
|
|
|
|
//
|
|
// Set the status info on a message, fail or reject it, and optionally
|
|
// destroy it.
|
|
//
|
|
Tt_status
|
|
_ttDtMessageGong(
|
|
Tt_message msg,
|
|
Tt_status status,
|
|
const char *statusString,
|
|
int reject,
|
|
int destroy
|
|
)
|
|
{
|
|
tt_message_status_set( msg, status );
|
|
if (statusString != 0) {
|
|
tt_message_status_string_set( msg, statusString );
|
|
}
|
|
Tt_status ttStatus;
|
|
if (reject) {
|
|
ttStatus = tt_message_reject( msg );
|
|
} else {
|
|
ttStatus = tt_message_fail( msg );
|
|
}
|
|
if (destroy) {
|
|
tttk_message_destroy( msg );
|
|
}
|
|
return ttStatus;
|
|
}
|
|
|
|
Tt_status
|
|
tttk_message_reject(
|
|
Tt_message msg,
|
|
Tt_status status,
|
|
const char *statusString,
|
|
int destroy
|
|
)
|
|
{
|
|
return _ttDtMessageGong( msg, status, statusString, 1, destroy );
|
|
}
|
|
|
|
Tt_status
|
|
tttk_message_fail(
|
|
Tt_message msg,
|
|
Tt_status status,
|
|
const char *statusString,
|
|
int destroy
|
|
)
|
|
{
|
|
if (tt_message_class( msg ) == TT_REQUEST) {
|
|
return _ttDtMessageGong( msg, status, statusString, 0,
|
|
destroy );
|
|
} else if (destroy) {
|
|
return tttk_message_destroy( msg );
|
|
}
|
|
return TT_OK;
|
|
}
|
|
|
|
//
|
|
// Set the default procid and call tt_message_receive()
|
|
//
|
|
Tt_message
|
|
_tttk_message_receive(
|
|
const char *procid
|
|
)
|
|
{
|
|
Tt_status status;
|
|
if (procid != 0) {
|
|
status = tt_default_procid_set( procid );
|
|
if (status != TT_OK) {
|
|
return (Tt_message)tt_error_pointer( status );
|
|
}
|
|
}
|
|
return tt_message_receive();
|
|
}
|
|
|
|
//
|
|
// Used internally to reply to messages that might be edicts (i.e. notices)
|
|
//
|
|
Tt_status
|
|
_tttk_message_reply(
|
|
Tt_message msg
|
|
)
|
|
{
|
|
if (tt_message_class( msg ) == TT_REQUEST) {
|
|
return tt_message_reply( msg );
|
|
}
|
|
return TT_OK;
|
|
}
|
|
|
|
Tt_status
|
|
tttk_message_abandon(
|
|
Tt_message msg
|
|
)
|
|
{
|
|
if (_tttk_message_am_handling( msg )) {
|
|
int fail = 0;
|
|
if (tt_message_address( msg ) == TT_HANDLER) {
|
|
fail = 1;
|
|
} else if (tt_message_status( msg ) == TT_WRN_START_MESSAGE) {
|
|
fail = 1;
|
|
}
|
|
if (fail) {
|
|
return tttk_message_fail( msg, TT_DESKTOP_ENOTSUP,0,1);
|
|
} else {
|
|
return tttk_message_reject(msg, TT_DESKTOP_ENOTSUP,0,1);
|
|
}
|
|
} else {
|
|
return tttk_message_destroy( msg );
|
|
}
|
|
}
|
|
|
|
//
|
|
// Returns the sender-set message id if any, otherwise the tt_message_id()
|
|
//
|
|
char *
|
|
_tttk_message_id(
|
|
Tt_message msg,
|
|
int arg
|
|
)
|
|
{
|
|
int numArgs = tt_message_args_count( msg );
|
|
Tt_status status = tt_int_error( numArgs );
|
|
if (status != TT_OK) {
|
|
return 0;
|
|
}
|
|
for (int i = arg; i < numArgs; i++) {
|
|
char *type = tt_message_arg_type( msg, i );
|
|
status = tt_ptr_error( type );
|
|
if (status != TT_OK) {
|
|
return 0;
|
|
}
|
|
if (type == 0) {
|
|
continue;
|
|
}
|
|
int miss = strcmp( type, Tttk_message_id );
|
|
tt_free( type );
|
|
if (miss) {
|
|
continue;
|
|
}
|
|
char *msgID = tt_message_arg_val( msg, i );
|
|
status = tt_ptr_error( type );
|
|
if (status != TT_OK) {
|
|
return 0;
|
|
}
|
|
return msgID;
|
|
}
|
|
return tt_message_id( msg );
|
|
}
|
|
|
|
int
|
|
_tttk_message_in_final_state(
|
|
Tt_message msg
|
|
)
|
|
{
|
|
Tt_state theState = tt_message_state( msg );
|
|
switch (tt_message_class( msg )) {
|
|
case TT_NOTICE:
|
|
return theState == TT_SENT;
|
|
case TT_REQUEST:
|
|
return (theState == TT_HANDLED) || (theState == TT_FAILED);
|
|
case TT_OFFER:
|
|
return theState == TT_RETURNED;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
//
|
|
// Can I reply to this message?
|
|
//
|
|
int
|
|
_tttk_message_am_handling(
|
|
Tt_message msg
|
|
)
|
|
{
|
|
if (tt_message_class( msg ) != TT_REQUEST) {
|
|
return 0;
|
|
}
|
|
if (tt_message_state( msg ) != TT_SENT) {
|
|
return 0;
|
|
}
|
|
char *handler = tt_message_handler( msg );
|
|
int am_handling = 0;
|
|
if ((tt_ptr_error( handler ) == TT_OK) && (handler != 0)) {
|
|
am_handling = 1;
|
|
}
|
|
tt_free( handler );
|
|
return am_handling;
|
|
}
|
|
|
|
//
|
|
// Get arg value and return default_val on error.
|
|
//
|
|
int
|
|
_tttk_message_arg_ival(
|
|
Tt_message msg,
|
|
unsigned int n,
|
|
int default_val
|
|
)
|
|
{
|
|
if (! _tttk_message_arg_is_set( msg, n )) {
|
|
return default_val;
|
|
}
|
|
int val;
|
|
Tt_status status = tt_message_arg_ival( msg, n, &val );
|
|
if (status != TT_OK) {
|
|
return default_val;
|
|
}
|
|
return val;
|
|
}
|
|
|
|
char *
|
|
_tttk_message_arg_val(
|
|
Tt_message msg,
|
|
unsigned int n,
|
|
const char *default_val
|
|
)
|
|
{
|
|
if (! _tttk_message_arg_is_set( msg, n )) {
|
|
return (char *)default_val;
|
|
}
|
|
char *val = tt_message_arg_val( msg, n );
|
|
Tt_status status = tt_ptr_error( val );
|
|
if (status != TT_OK) {
|
|
return (char *)default_val;
|
|
}
|
|
return val;
|
|
}
|
|
|
|
//
|
|
// Does arg n have a value?
|
|
//
|
|
int
|
|
_tttk_message_arg_is_set(
|
|
Tt_message msg,
|
|
unsigned int n
|
|
)
|
|
{
|
|
int val;
|
|
Tt_status status = tt_message_arg_ival( msg, n, &val );
|
|
if (status == TT_OK) {
|
|
return 1;
|
|
}
|
|
if (status != TT_ERR_NUM) {
|
|
return 0;
|
|
}
|
|
unsigned char *s;
|
|
int len;
|
|
status = tt_message_arg_bval( msg, n, &s, &len );
|
|
if (status != TT_OK) {
|
|
return 0;
|
|
}
|
|
return (s != 0);
|
|
}
|
|
|
|
//
|
|
// Generic _TtDtMessageCB that sets *clientData to the negated
|
|
// tt_message_status() of the reply (or failure) of the message.
|
|
// Useful when sending synchronous requests and you only care to
|
|
// know the Tt_status of the reply/failure.
|
|
//
|
|
Tt_message
|
|
_ttTkNoteReplyStatus(
|
|
Tt_message msg,
|
|
Tt_pattern ,
|
|
void *,
|
|
void *clientData
|
|
)
|
|
{
|
|
if (! _tttk_message_in_final_state( msg )) {
|
|
return msg;
|
|
}
|
|
int *result = (int *)clientData;
|
|
*result = -TT_DESKTOP_ETIMEDOUT;
|
|
switch (tt_message_state( msg )) {
|
|
case TT_HANDLED:
|
|
*result = -TT_OK;
|
|
break;
|
|
case TT_FAILED:
|
|
*result = -tt_message_status( msg );
|
|
if (*result == -TT_OK) {
|
|
//
|
|
// The handler did not say why he failed the
|
|
// request, so we have to make up a reason
|
|
// to pass back through e.g. ttdt_Save().
|
|
//
|
|
*result = -TT_DESKTOP_EPROTO;
|
|
}
|
|
break;
|
|
}
|
|
tttk_message_destroy( msg );
|
|
// Protect against bogus message status causing infinite loop
|
|
if (*result > 0) {
|
|
*result = -(*result);
|
|
}
|
|
return 0;
|
|
}
|