432 lines
13 KiB
C
432 lines
13 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
|
|
*/
|
|
/* $XConsortium: ttSaveSupport.c /main/4 1996/05/08 20:09:07 drk $ */
|
|
/**********************************<+>*************************************
|
|
***************************************************************************
|
|
**
|
|
** File: ttSaveSupport.c
|
|
**
|
|
** Project: DT dtpad, a memo maker type editor based on the Dt Editor
|
|
** widget.
|
|
**
|
|
** Description:
|
|
** -----------
|
|
**
|
|
** Provides support for the ToolTalk "Save" message in a manner analogous
|
|
** to "Quit" message support provided by the ttdt_message_accept() function.
|
|
**
|
|
*******************************************************************
|
|
** (c) Copyright Hewlett-Packard Company, 1990, 1991, 1992, 1993.
|
|
** All rights are
|
|
** reserved. Copying or other reproduction of this program
|
|
** except for archival purposes is prohibited without prior
|
|
** written consent of Hewlett-Packard Company.
|
|
********************************************************************
|
|
**
|
|
********************************************************************
|
|
** (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.
|
|
********************************************************************
|
|
**
|
|
**
|
|
**************************************************************************
|
|
**********************************<+>*************************************/
|
|
#include "dtpad.h"
|
|
|
|
/* definitions from tttk/tttkutils.h */
|
|
char _TTKeys[7];
|
|
#define _TTCBKey ((int)(intptr_t)&_TTKeys[0])
|
|
#define _TTClientCBKey ((int)(intptr_t)&_TTKeys[1])
|
|
#define _TTClientDataKey ((int)(intptr_t)&_TTKeys[2])
|
|
#define _TTDepositPatKey ((int)(intptr_t)&_TTKeys[3])
|
|
#define _TTJoinInfoKey ((int)(intptr_t)&_TTKeys[4])
|
|
#define _TTContractKey ((int)(intptr_t)&_TTKeys[5])
|
|
#define _TTSubContractKey ((int)(intptr_t)&_TTKeys[6])
|
|
|
|
extern Editor *pPadList; /* list of Editor instances - declared in main.c */
|
|
|
|
/******************************************************************************
|
|
* TTSaveContractCB - callback (setup in ttdt_message_accept()) to handle
|
|
* Save(4) requests. Currently this routine handles one argument:
|
|
*
|
|
* messageID - This must be the message ID the originating Edit
|
|
* request whose contents are to that is to be saved
|
|
* (or deposited if a buffer is being edited).
|
|
*
|
|
* This routine is analogous to TTdt_message_acceptCB() which handles
|
|
* Quit requests. Patterns to handle Quit requests are automatically
|
|
* registered via ttdt_message_accept() whereas patterns to handle Save
|
|
* requests must be explicitly registered (see TTCreateSavePattern()).
|
|
*
|
|
* See dtpad(1) for more details.
|
|
*
|
|
******************************************************************************/
|
|
Tt_message
|
|
TTSaveContractCB(
|
|
Tt_message m,
|
|
void * clientData,
|
|
Tt_message contract)
|
|
{
|
|
Editor *pPad;
|
|
int silent, force;
|
|
Tt_status status;
|
|
char *messageID;
|
|
int mark = tt_mark();
|
|
|
|
char *opString = tt_message_op(m);
|
|
Tttk_op op = tttk_string_op(opString);
|
|
|
|
if (op == TTDT_SAVE) {
|
|
|
|
/* Search the list of Editor instances for one with a TT media
|
|
* msg id matching the originating media msg id supplied as the
|
|
* 'messageID' (1st) argument of the TTDT_SAVE msg */
|
|
if (messageID = tt_message_arg_val(m, 0)) {
|
|
for (pPad = pPadList; pPad != (Editor *)NULL; pPad = pPad->pNextPad) {
|
|
if (pPad->inUse == True && pPad->ttEditReq.msg_id &&
|
|
strcmp(pPad->ttEditReq.msg_id, messageID) == 0) {
|
|
pPad->ttSaveReq.contract = m; /* process Save msg */
|
|
pPad->ttSaveReq.messageID = strdup(messageID);
|
|
FileSaveCB((Widget) NULL, (caddr_t) pPad, (caddr_t) NULL);
|
|
tt_release(mark);
|
|
return((Tt_message) 0); /* handling Save */
|
|
}
|
|
}
|
|
/* no Edit window matching the messageID */
|
|
tttk_message_fail(m,
|
|
TT_DESKTOP_ECANCELED, /* status */
|
|
(char *) NULL, /* status str */
|
|
1); /* destroy request */
|
|
|
|
} else { /* no messageID - which is required */
|
|
tttk_message_fail(m,
|
|
TT_DESKTOP_ECANCELED, /* status */
|
|
(char *) NULL, /* status str */
|
|
1); /* destroy request */
|
|
}
|
|
|
|
/* We're handling all Save requests. If the request has not been
|
|
* failed already, pPad->ttSaveReq.contract will be non-NULL and
|
|
* the Save message will be responded to or failed later. */
|
|
tt_release(mark);
|
|
return((Tt_message) 0); /* handling Quit */
|
|
|
|
} else { /* unsupported message type */
|
|
|
|
tt_release(mark);
|
|
return(m); /* didn't handle message */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
* _TT_pattern_contract - obtains the contracting message from the pattern
|
|
******************************************************************************/
|
|
Tt_message
|
|
_TT_pattern_contract(
|
|
Tt_pattern pat)
|
|
{
|
|
void *contract = tt_pattern_user(pat, _TTContractKey);
|
|
Tt_status status = tt_ptr_error(contract);
|
|
if (status != TT_OK) {
|
|
return 0;
|
|
}
|
|
return (Tt_message) contract;
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
* _TTpatternCB - Retrieves the client callback and callback arguments from
|
|
* the pattern and calls it (ala tttkpattern.C:_ttDtPatternCB()).
|
|
******************************************************************************/
|
|
static Tt_callback_action
|
|
_TTpatternCB(
|
|
Tt_message msg,
|
|
Tt_pattern pat)
|
|
{
|
|
Ttdt_contract_cb clientCB;
|
|
void * clientData;
|
|
Tt_status status;
|
|
|
|
/* ----> Obtain client callback */
|
|
clientCB = (Ttdt_contract_cb) tt_pattern_user(pat, _TTClientCBKey);
|
|
status = tt_ptr_error(clientCB);
|
|
if (status != TT_OK) {
|
|
return TT_CALLBACK_PROCESSED;
|
|
}
|
|
if (clientCB == 0) {
|
|
return TT_CALLBACK_CONTINUE;
|
|
}
|
|
|
|
/* ----> Obtain client data */
|
|
clientData = tt_pattern_user(pat, _TTClientDataKey);
|
|
status = tt_ptr_error(clientData);
|
|
if (status != TT_OK) {
|
|
return TT_CALLBACK_PROCESSED;
|
|
}
|
|
|
|
/* -----> Call client callback */
|
|
msg = (*clientCB)(msg, clientData, _TT_pattern_contract(pat));
|
|
|
|
status = tt_ptr_error(msg);
|
|
if ((status != TT_OK) || (msg == 0)) {
|
|
return TT_CALLBACK_PROCESSED;
|
|
} else {
|
|
return TT_CALLBACK_CONTINUE;
|
|
}
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
* _TTCreatePattern - creates a pattern for a desktop message
|
|
* (ala cdesrc/lib/tt/lib/tttk/tttkpattern.C:_ttDtPatternCreate())
|
|
******************************************************************************/
|
|
Tt_pattern
|
|
_TTCreatePattern(
|
|
Tt_category category,
|
|
Tt_scope theScope,
|
|
int addDefaultSess,
|
|
const char * file,
|
|
const char * op_string,
|
|
Ttdt_contract_cb clientCB,
|
|
void * clientData)
|
|
{
|
|
|
|
Tt_pattern pat = tt_pattern_create();
|
|
Tt_status status = tt_ptr_error(pat);
|
|
if (status != TT_OK) {
|
|
return pat;
|
|
}
|
|
|
|
status = tt_pattern_category_set(pat, category);
|
|
if (status != TT_OK) {
|
|
tt_pattern_destroy(pat);
|
|
return (Tt_pattern)tt_error_pointer(status);
|
|
}
|
|
|
|
/* we only observe notices and only handle requests */
|
|
if (category == TT_HANDLE) {
|
|
status = tt_pattern_class_add(pat, TT_REQUEST);
|
|
}
|
|
if (category == TT_OBSERVE) {
|
|
status = tt_pattern_class_add(pat, TT_NOTICE);
|
|
}
|
|
if (status != TT_OK) {
|
|
tt_pattern_destroy(pat);
|
|
return (Tt_pattern)tt_error_pointer(status);
|
|
}
|
|
|
|
status = tt_pattern_scope_add(pat, theScope);
|
|
if (status != TT_OK) {
|
|
tt_pattern_destroy(pat);
|
|
return (Tt_pattern)tt_error_pointer(status);
|
|
}
|
|
|
|
if (addDefaultSess) {
|
|
char *sess = tt_default_session();
|
|
status = tt_pattern_session_add(pat, sess);
|
|
tt_free(sess);
|
|
if (status != TT_OK) {
|
|
tt_pattern_destroy(pat);
|
|
return (Tt_pattern)tt_error_pointer(status);
|
|
}
|
|
}
|
|
|
|
if (file != 0) {
|
|
status = tt_pattern_file_add(pat, file);
|
|
if (status != TT_OK) {
|
|
tt_pattern_destroy(pat);
|
|
return (Tt_pattern)tt_error_pointer(status);
|
|
}
|
|
}
|
|
|
|
if (op_string) {
|
|
status = tt_pattern_op_add(pat, op_string);
|
|
if (status != TT_OK) {
|
|
tt_pattern_destroy(pat);
|
|
return (Tt_pattern)tt_error_pointer(status);
|
|
}
|
|
}
|
|
|
|
/* -----> Add the general purpose pattern callback (as well as the
|
|
* client callback and client data) as fields to the pattern.
|
|
* When the general purpose pattern callback is called, it
|
|
* obtains the client callback and client data from the pattern
|
|
* and calls the client callback with the appropriate arguments. */
|
|
status = tt_pattern_callback_add( pat, _TTpatternCB );
|
|
if (status != TT_OK) {
|
|
tt_pattern_destroy(pat);
|
|
return (Tt_pattern)tt_error_pointer(status);
|
|
}
|
|
status = tt_pattern_user_set(pat, _TTClientCBKey, (void *) clientCB);
|
|
if (status != TT_OK) {
|
|
tt_pattern_destroy(pat);
|
|
return (Tt_pattern)tt_error_pointer(status);
|
|
}
|
|
status = tt_pattern_user_set(pat, _TTClientDataKey, clientData);
|
|
if (status != TT_OK) {
|
|
tt_pattern_destroy(pat);
|
|
return (Tt_pattern)tt_error_pointer(status);
|
|
}
|
|
|
|
return pat;
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
* _TTmessage_id - Returns sender-set message id if any, otherwise the
|
|
* tt_message_id() (ala lib/tt/lib/tttk/tttkmessage.C:_tttk_message_id())
|
|
******************************************************************************/
|
|
char *
|
|
_TTmessage_id(
|
|
Tt_message msg)
|
|
{
|
|
int i, miss, numArgs = tt_message_args_count( msg );
|
|
Tt_status status = tt_int_error( numArgs );
|
|
char *msgID;
|
|
|
|
if (status != TT_OK) {
|
|
return 0;
|
|
}
|
|
|
|
for (i = 0; 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;
|
|
}
|
|
miss = strcmp(type, Tttk_message_id);
|
|
tt_free(type);
|
|
if (miss) {
|
|
continue;
|
|
}
|
|
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);
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
* TTCreateSavePattern - Creates and (optionally) registers a pattern to handle
|
|
* Save requests (ala cdesrc/lib/tt/lib/tttk/ttdesktop.C:_ttdt_pat() and
|
|
* _ttDesktopPatternFinish())
|
|
******************************************************************************/
|
|
Tt_pattern
|
|
TTCreateSavePattern(
|
|
Tt_message contract,
|
|
Ttdt_contract_cb clientCB,
|
|
void * clientData,
|
|
int register_it)
|
|
{
|
|
char *msgID;
|
|
|
|
/* -----> Create pattern */
|
|
Tt_pattern pat = _TTCreatePattern(
|
|
TT_HANDLE, /* catagory */
|
|
TT_SESSION, /* scope */
|
|
1, /* add default session to pat */
|
|
0, /* don't add file to pat */
|
|
"Save", /* desktop message (op) type */
|
|
clientCB,
|
|
clientData);
|
|
|
|
Tt_status status = tt_ptr_error( pat );
|
|
if (status != TT_OK) {
|
|
return pat;
|
|
}
|
|
|
|
/* -----> Add message id and contracting message to pattern */
|
|
if (contract != 0) {
|
|
char *msgID = _TTmessage_id(contract);
|
|
status = tt_pattern_arg_add(pat, TT_IN, Tttk_message_id, msgID);
|
|
tt_free(msgID);
|
|
if (status != TT_OK) {
|
|
tt_pattern_destroy(pat);
|
|
return (Tt_pattern) tt_error_pointer(status);
|
|
}
|
|
tt_pattern_user_set(pat, _TTContractKey, contract);
|
|
}
|
|
|
|
/* -----> Register pattern */
|
|
if (register_it) {
|
|
status = tt_pattern_register(pat);
|
|
if (status != TT_OK) {
|
|
tt_pattern_destroy(pat);
|
|
return (Tt_pattern) tt_error_pointer(status);
|
|
}
|
|
}
|
|
|
|
return pat;
|
|
}
|
|
|
|
|
|
/************************************************************************
|
|
* TTresetSaveArgs - resets TTDT_SAVE arguments set in TTSaveContractCB()
|
|
************************************************************************/
|
|
void
|
|
TTresetSaveArgs(
|
|
Editor *pPad)
|
|
{
|
|
if (!pPad->ttSaveReq.contract)
|
|
return;
|
|
pPad->ttSaveReq.contract = NULL;
|
|
if (pPad->ttSaveReq.messageID != (char *) NULL) {
|
|
XtFree(pPad->ttSaveReq.messageID);
|
|
pPad->ttSaveReq.messageID = (char *) NULL;
|
|
}
|
|
}
|
|
|
|
|
|
/************************************************************************
|
|
* TTfailPendingSave - fails any pending Save request
|
|
************************************************************************/
|
|
void
|
|
TTfailPendingSave(
|
|
Editor *pPad)
|
|
{
|
|
if (pPad->ttSaveReq.contract) {
|
|
tttk_message_fail(pPad->ttSaveReq.contract, /* original Save req */
|
|
TT_DESKTOP_ECANCELED, /* status */
|
|
(char *) NULL, /* status string */
|
|
1); /* destroy request */
|
|
TTresetSaveArgs(pPad);
|
|
}
|
|
}
|