1 /* $XConsortium: ttSaveSupport.c /main/4 1996/05/08 20:09:07 drk $ */
2 /**********************************<+>*************************************
3 ***************************************************************************
5 ** File: ttSaveSupport.c
7 ** Project: DT dtpad, a memo maker type editor based on the Dt Editor
13 ** Provides support for the ToolTalk "Save" message in a manner analogous
14 ** to "Quit" message support provided by the ttdt_message_accept() function.
16 *******************************************************************
17 ** (c) Copyright Hewlett-Packard Company, 1990, 1991, 1992, 1993.
19 ** reserved. Copying or other reproduction of this program
20 ** except for archival purposes is prohibited without prior
21 ** written consent of Hewlett-Packard Company.
22 ********************************************************************
24 ********************************************************************
25 ** (c) Copyright 1993, 1994 Hewlett-Packard Company
26 ** (c) Copyright 1993, 1994 International Business Machines Corp.
27 ** (c) Copyright 1993, 1994 Sun Microsystems, Inc.
28 ** (c) Copyright 1993, 1994 Novell, Inc.
29 ********************************************************************
32 **************************************************************************
33 **********************************<+>*************************************/
36 /* definitions from tttk/tttkutils.h */
38 #define _TTCBKey ((int)&_TTKeys[0])
39 #define _TTClientCBKey ((int)&_TTKeys[1])
40 #define _TTClientDataKey ((int)&_TTKeys[2])
41 #define _TTDepositPatKey ((int)&_TTKeys[3])
42 #define _TTJoinInfoKey ((int)&_TTKeys[4])
43 #define _TTContractKey ((int)&_TTKeys[5])
44 #define _TTSubContractKey ((int)&_TTKeys[6])
46 extern Editor *pPadList; /* list of Editor instances - declared in main.c */
48 /******************************************************************************
49 * TTSaveContractCB - callback (setup in ttdt_message_accept()) to handle
50 * Save(4) requests. Currently this routine handles one argument:
52 * messageID - This must be the message ID the originating Edit
53 * request whose contents are to that is to be saved
54 * (or deposited if a buffer is being edited).
56 * This routine is analogous to TTdt_message_acceptCB() which handles
57 * Quit requests. Patterns to handle Quit requests are automatically
58 * registered via ttdt_message_accept() whereas patterns to handle Save
59 * requests must be explicitly registered (see TTCreateSavePattern()).
61 * See dtpad(1) for more details.
63 ******************************************************************************/
76 char *opString = tt_message_op(m);
77 Tttk_op op = tttk_string_op(opString);
79 if (op == TTDT_SAVE) {
81 /* Search the list of Editor instances for one with a TT media
82 * msg id matching the originating media msg id supplied as the
83 * 'messageID' (1st) argument of the TTDT_SAVE msg */
84 if (messageID = tt_message_arg_val(m, 0)) {
85 for (pPad = pPadList; pPad != (Editor *)NULL; pPad = pPad->pNextPad) {
86 if (pPad->inUse == True && pPad->ttEditReq.msg_id &&
87 strcmp(pPad->ttEditReq.msg_id, messageID) == 0) {
88 pPad->ttSaveReq.contract = m; /* process Save msg */
89 pPad->ttSaveReq.messageID = strdup(messageID);
90 FileSaveCB((Widget) NULL, (caddr_t) pPad, (caddr_t) NULL);
92 return((Tt_message) 0); /* handling Save */
95 /* no Edit window matching the messageID */
97 TT_DESKTOP_ECANCELED, /* status */
98 (char *) NULL, /* status str */
99 1); /* destroy request */
101 } else { /* no messageID - which is required */
103 TT_DESKTOP_ECANCELED, /* status */
104 (char *) NULL, /* status str */
105 1); /* destroy request */
108 /* We're handling all Save requests. If the request has not been
109 * failed already, pPad->ttSaveReq.contract will be non-NULL and
110 * the Save message will be responded to or failed later. */
112 return((Tt_message) 0); /* handling Quit */
114 } else { /* unsupported message type */
117 return(m); /* didn't handle message */
125 /******************************************************************************
126 * _TT_pattern_contract - obtains the contracting message from the pattern
127 ******************************************************************************/
129 _TT_pattern_contract(
132 void *contract = tt_pattern_user(pat, _TTContractKey);
133 Tt_status status = tt_ptr_error(contract);
134 if (status != TT_OK) {
137 return (Tt_message) contract;
142 /******************************************************************************
143 * _TTpatternCB - Retrieves the client callback and callback arguments from
144 * the pattern and calls it (ala tttkpattern.C:_ttDtPatternCB()).
145 ******************************************************************************/
146 static Tt_callback_action
151 Ttdt_contract_cb clientCB;
155 /* ----> Obtain client callback */
156 clientCB = (Ttdt_contract_cb) tt_pattern_user(pat, _TTClientCBKey);
157 status = tt_ptr_error(clientCB);
158 if (status != TT_OK) {
159 return TT_CALLBACK_PROCESSED;
162 return TT_CALLBACK_CONTINUE;
165 /* ----> Obtain client data */
166 clientData = tt_pattern_user(pat, _TTClientDataKey);
167 status = tt_ptr_error(clientData);
168 if (status != TT_OK) {
169 return TT_CALLBACK_PROCESSED;
172 /* -----> Call client callback */
173 msg = (*clientCB)(msg, clientData, _TT_pattern_contract(pat));
175 status = tt_ptr_error(msg);
176 if ((status != TT_OK) || (msg == 0)) {
177 return TT_CALLBACK_PROCESSED;
179 return TT_CALLBACK_CONTINUE;
184 /******************************************************************************
185 * _TTCreatePattern - creates a pattern for a desktop message
186 * (ala cdesrc/lib/tt/lib/tttk/tttkpattern.C:_ttDtPatternCreate())
187 ******************************************************************************/
190 Tt_category category,
194 const char * op_string,
195 Ttdt_contract_cb clientCB,
199 Tt_pattern pat = tt_pattern_create();
200 Tt_status status = tt_ptr_error(pat);
201 if (status != TT_OK) {
205 status = tt_pattern_category_set(pat, category);
206 if (status != TT_OK) {
207 tt_pattern_destroy(pat);
208 return (Tt_pattern)tt_error_pointer(status);
211 /* we only observe notices and only handle requests */
212 if (category == TT_HANDLE) {
213 status = tt_pattern_class_add(pat, TT_REQUEST);
215 if (category == TT_OBSERVE) {
216 status = tt_pattern_class_add(pat, TT_NOTICE);
218 if (status != TT_OK) {
219 tt_pattern_destroy(pat);
220 return (Tt_pattern)tt_error_pointer(status);
223 status = tt_pattern_scope_add(pat, theScope);
224 if (status != TT_OK) {
225 tt_pattern_destroy(pat);
226 return (Tt_pattern)tt_error_pointer(status);
229 if (addDefaultSess) {
230 char *sess = tt_default_session();
231 status = tt_pattern_session_add(pat, sess);
233 if (status != TT_OK) {
234 tt_pattern_destroy(pat);
235 return (Tt_pattern)tt_error_pointer(status);
240 status = tt_pattern_file_add(pat, file);
241 if (status != TT_OK) {
242 tt_pattern_destroy(pat);
243 return (Tt_pattern)tt_error_pointer(status);
248 status = tt_pattern_op_add(pat, op_string);
249 if (status != TT_OK) {
250 tt_pattern_destroy(pat);
251 return (Tt_pattern)tt_error_pointer(status);
255 /* -----> Add the general purpose pattern callback (as well as the
256 * client callback and client data) as fields to the pattern.
257 * When the general purpose pattern callback is called, it
258 * obtains the client callback and client data from the pattern
259 * and calls the client callback with the appropriate arguments. */
260 status = tt_pattern_callback_add( pat, _TTpatternCB );
261 if (status != TT_OK) {
262 tt_pattern_destroy(pat);
263 return (Tt_pattern)tt_error_pointer(status);
265 status = tt_pattern_user_set(pat, _TTClientCBKey, (void *) clientCB);
266 if (status != TT_OK) {
267 tt_pattern_destroy(pat);
268 return (Tt_pattern)tt_error_pointer(status);
270 status = tt_pattern_user_set(pat, _TTClientDataKey, clientData);
271 if (status != TT_OK) {
272 tt_pattern_destroy(pat);
273 return (Tt_pattern)tt_error_pointer(status);
281 /******************************************************************************
282 * _TTmessage_id - Returns sender-set message id if any, otherwise the
283 * tt_message_id() (ala lib/tt/lib/tttk/tttkmessage.C:_tttk_message_id())
284 ******************************************************************************/
289 int i, miss, numArgs = tt_message_args_count( msg );
290 Tt_status status = tt_int_error( numArgs );
293 if (status != TT_OK) {
297 for (i = 0; i < numArgs; i++) {
298 char *type = tt_message_arg_type(msg, i);
299 status = tt_ptr_error(type);
300 if (status != TT_OK) {
306 miss = strcmp(type, Tttk_message_id);
311 msgID = tt_message_arg_val(msg, i);
312 status = tt_ptr_error(type);
313 if (status != TT_OK) {
319 return tt_message_id(msg);
324 /******************************************************************************
325 * TTCreateSavePattern - Creates and (optionally) registers a pattern to handle
326 * Save requests (ala cdesrc/lib/tt/lib/tttk/ttdesktop.C:_ttdt_pat() and
327 * _ttDesktopPatternFinish())
328 ******************************************************************************/
332 Ttdt_contract_cb clientCB,
338 /* -----> Create pattern */
339 Tt_pattern pat = _TTCreatePattern(
340 TT_HANDLE, /* catagory */
341 TT_SESSION, /* scope */
342 1, /* add default session to pat */
343 0, /* don't add file to pat */
344 "Save", /* desktop message (op) type */
348 Tt_status status = tt_ptr_error( pat );
349 if (status != TT_OK) {
353 /* -----> Add message id and contracting message to pattern */
355 char *msgID = _TTmessage_id(contract);
356 status = tt_pattern_arg_add(pat, TT_IN, Tttk_message_id, msgID);
358 if (status != TT_OK) {
359 tt_pattern_destroy(pat);
360 return (Tt_pattern) tt_error_pointer(status);
362 tt_pattern_user_set(pat, _TTContractKey, contract);
365 /* -----> Register pattern */
367 status = tt_pattern_register(pat);
368 if (status != TT_OK) {
369 tt_pattern_destroy(pat);
370 return (Tt_pattern) tt_error_pointer(status);
378 /************************************************************************
379 * TTresetSaveArgs - resets TTDT_SAVE argments set in TTSaveContractCB()
380 ************************************************************************/
385 if (!pPad->ttSaveReq.contract)
387 pPad->ttSaveReq.contract = NULL;
388 if (pPad->ttSaveReq.messageID != (char *) NULL) {
389 XtFree(pPad->ttSaveReq.messageID);
390 pPad->ttSaveReq.messageID = (char *) NULL;
395 /************************************************************************
396 * TTfailPendingSave - fails any pending Save request
397 ************************************************************************/
402 if (pPad->ttSaveReq.contract) {
403 tttk_message_fail(pPad->ttSaveReq.contract, /* original Save req */
404 TT_DESKTOP_ECANCELED, /* status */
405 (char *) NULL, /* status string */
406 1); /* destroy request */
407 TTresetSaveArgs(pPad);