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 librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $XConsortium: ttSaveSupport.c /main/4 1996/05/08 20:09:07 drk $ */
24 /**********************************<+>*************************************
25 ***************************************************************************
27 ** File: ttSaveSupport.c
29 ** Project: DT dtpad, a memo maker type editor based on the Dt Editor
35 ** Provides support for the ToolTalk "Save" message in a manner analogous
36 ** to "Quit" message support provided by the ttdt_message_accept() function.
38 *******************************************************************
39 ** (c) Copyright Hewlett-Packard Company, 1990, 1991, 1992, 1993.
41 ** reserved. Copying or other reproduction of this program
42 ** except for archival purposes is prohibited without prior
43 ** written consent of Hewlett-Packard Company.
44 ********************************************************************
46 ********************************************************************
47 ** (c) Copyright 1993, 1994 Hewlett-Packard Company
48 ** (c) Copyright 1993, 1994 International Business Machines Corp.
49 ** (c) Copyright 1993, 1994 Sun Microsystems, Inc.
50 ** (c) Copyright 1993, 1994 Novell, Inc.
51 ********************************************************************
54 **************************************************************************
55 **********************************<+>*************************************/
58 /* definitions from tttk/tttkutils.h */
60 #define _TTCBKey ((int)&_TTKeys[0])
61 #define _TTClientCBKey ((int)&_TTKeys[1])
62 #define _TTClientDataKey ((int)&_TTKeys[2])
63 #define _TTDepositPatKey ((int)&_TTKeys[3])
64 #define _TTJoinInfoKey ((int)&_TTKeys[4])
65 #define _TTContractKey ((int)&_TTKeys[5])
66 #define _TTSubContractKey ((int)&_TTKeys[6])
68 extern Editor *pPadList; /* list of Editor instances - declared in main.c */
70 /******************************************************************************
71 * TTSaveContractCB - callback (setup in ttdt_message_accept()) to handle
72 * Save(4) requests. Currently this routine handles one argument:
74 * messageID - This must be the message ID the originating Edit
75 * request whose contents are to that is to be saved
76 * (or deposited if a buffer is being edited).
78 * This routine is analogous to TTdt_message_acceptCB() which handles
79 * Quit requests. Patterns to handle Quit requests are automatically
80 * registered via ttdt_message_accept() whereas patterns to handle Save
81 * requests must be explicitly registered (see TTCreateSavePattern()).
83 * See dtpad(1) for more details.
85 ******************************************************************************/
98 char *opString = tt_message_op(m);
99 Tttk_op op = tttk_string_op(opString);
101 if (op == TTDT_SAVE) {
103 /* Search the list of Editor instances for one with a TT media
104 * msg id matching the originating media msg id supplied as the
105 * 'messageID' (1st) argument of the TTDT_SAVE msg */
106 if (messageID = tt_message_arg_val(m, 0)) {
107 for (pPad = pPadList; pPad != (Editor *)NULL; pPad = pPad->pNextPad) {
108 if (pPad->inUse == True && pPad->ttEditReq.msg_id &&
109 strcmp(pPad->ttEditReq.msg_id, messageID) == 0) {
110 pPad->ttSaveReq.contract = m; /* process Save msg */
111 pPad->ttSaveReq.messageID = strdup(messageID);
112 FileSaveCB((Widget) NULL, (caddr_t) pPad, (caddr_t) NULL);
114 return((Tt_message) 0); /* handling Save */
117 /* no Edit window matching the messageID */
119 TT_DESKTOP_ECANCELED, /* status */
120 (char *) NULL, /* status str */
121 1); /* destroy request */
123 } else { /* no messageID - which is required */
125 TT_DESKTOP_ECANCELED, /* status */
126 (char *) NULL, /* status str */
127 1); /* destroy request */
130 /* We're handling all Save requests. If the request has not been
131 * failed already, pPad->ttSaveReq.contract will be non-NULL and
132 * the Save message will be responded to or failed later. */
134 return((Tt_message) 0); /* handling Quit */
136 } else { /* unsupported message type */
139 return(m); /* didn't handle message */
147 /******************************************************************************
148 * _TT_pattern_contract - obtains the contracting message from the pattern
149 ******************************************************************************/
151 _TT_pattern_contract(
154 void *contract = tt_pattern_user(pat, _TTContractKey);
155 Tt_status status = tt_ptr_error(contract);
156 if (status != TT_OK) {
159 return (Tt_message) contract;
164 /******************************************************************************
165 * _TTpatternCB - Retrieves the client callback and callback arguments from
166 * the pattern and calls it (ala tttkpattern.C:_ttDtPatternCB()).
167 ******************************************************************************/
168 static Tt_callback_action
173 Ttdt_contract_cb clientCB;
177 /* ----> Obtain client callback */
178 clientCB = (Ttdt_contract_cb) tt_pattern_user(pat, _TTClientCBKey);
179 status = tt_ptr_error(clientCB);
180 if (status != TT_OK) {
181 return TT_CALLBACK_PROCESSED;
184 return TT_CALLBACK_CONTINUE;
187 /* ----> Obtain client data */
188 clientData = tt_pattern_user(pat, _TTClientDataKey);
189 status = tt_ptr_error(clientData);
190 if (status != TT_OK) {
191 return TT_CALLBACK_PROCESSED;
194 /* -----> Call client callback */
195 msg = (*clientCB)(msg, clientData, _TT_pattern_contract(pat));
197 status = tt_ptr_error(msg);
198 if ((status != TT_OK) || (msg == 0)) {
199 return TT_CALLBACK_PROCESSED;
201 return TT_CALLBACK_CONTINUE;
206 /******************************************************************************
207 * _TTCreatePattern - creates a pattern for a desktop message
208 * (ala cdesrc/lib/tt/lib/tttk/tttkpattern.C:_ttDtPatternCreate())
209 ******************************************************************************/
212 Tt_category category,
216 const char * op_string,
217 Ttdt_contract_cb clientCB,
221 Tt_pattern pat = tt_pattern_create();
222 Tt_status status = tt_ptr_error(pat);
223 if (status != TT_OK) {
227 status = tt_pattern_category_set(pat, category);
228 if (status != TT_OK) {
229 tt_pattern_destroy(pat);
230 return (Tt_pattern)tt_error_pointer(status);
233 /* we only observe notices and only handle requests */
234 if (category == TT_HANDLE) {
235 status = tt_pattern_class_add(pat, TT_REQUEST);
237 if (category == TT_OBSERVE) {
238 status = tt_pattern_class_add(pat, TT_NOTICE);
240 if (status != TT_OK) {
241 tt_pattern_destroy(pat);
242 return (Tt_pattern)tt_error_pointer(status);
245 status = tt_pattern_scope_add(pat, theScope);
246 if (status != TT_OK) {
247 tt_pattern_destroy(pat);
248 return (Tt_pattern)tt_error_pointer(status);
251 if (addDefaultSess) {
252 char *sess = tt_default_session();
253 status = tt_pattern_session_add(pat, sess);
255 if (status != TT_OK) {
256 tt_pattern_destroy(pat);
257 return (Tt_pattern)tt_error_pointer(status);
262 status = tt_pattern_file_add(pat, file);
263 if (status != TT_OK) {
264 tt_pattern_destroy(pat);
265 return (Tt_pattern)tt_error_pointer(status);
270 status = tt_pattern_op_add(pat, op_string);
271 if (status != TT_OK) {
272 tt_pattern_destroy(pat);
273 return (Tt_pattern)tt_error_pointer(status);
277 /* -----> Add the general purpose pattern callback (as well as the
278 * client callback and client data) as fields to the pattern.
279 * When the general purpose pattern callback is called, it
280 * obtains the client callback and client data from the pattern
281 * and calls the client callback with the appropriate arguments. */
282 status = tt_pattern_callback_add( pat, _TTpatternCB );
283 if (status != TT_OK) {
284 tt_pattern_destroy(pat);
285 return (Tt_pattern)tt_error_pointer(status);
287 status = tt_pattern_user_set(pat, _TTClientCBKey, (void *) clientCB);
288 if (status != TT_OK) {
289 tt_pattern_destroy(pat);
290 return (Tt_pattern)tt_error_pointer(status);
292 status = tt_pattern_user_set(pat, _TTClientDataKey, clientData);
293 if (status != TT_OK) {
294 tt_pattern_destroy(pat);
295 return (Tt_pattern)tt_error_pointer(status);
303 /******************************************************************************
304 * _TTmessage_id - Returns sender-set message id if any, otherwise the
305 * tt_message_id() (ala lib/tt/lib/tttk/tttkmessage.C:_tttk_message_id())
306 ******************************************************************************/
311 int i, miss, numArgs = tt_message_args_count( msg );
312 Tt_status status = tt_int_error( numArgs );
315 if (status != TT_OK) {
319 for (i = 0; i < numArgs; i++) {
320 char *type = tt_message_arg_type(msg, i);
321 status = tt_ptr_error(type);
322 if (status != TT_OK) {
328 miss = strcmp(type, Tttk_message_id);
333 msgID = tt_message_arg_val(msg, i);
334 status = tt_ptr_error(type);
335 if (status != TT_OK) {
341 return tt_message_id(msg);
346 /******************************************************************************
347 * TTCreateSavePattern - Creates and (optionally) registers a pattern to handle
348 * Save requests (ala cdesrc/lib/tt/lib/tttk/ttdesktop.C:_ttdt_pat() and
349 * _ttDesktopPatternFinish())
350 ******************************************************************************/
354 Ttdt_contract_cb clientCB,
360 /* -----> Create pattern */
361 Tt_pattern pat = _TTCreatePattern(
362 TT_HANDLE, /* catagory */
363 TT_SESSION, /* scope */
364 1, /* add default session to pat */
365 0, /* don't add file to pat */
366 "Save", /* desktop message (op) type */
370 Tt_status status = tt_ptr_error( pat );
371 if (status != TT_OK) {
375 /* -----> Add message id and contracting message to pattern */
377 char *msgID = _TTmessage_id(contract);
378 status = tt_pattern_arg_add(pat, TT_IN, Tttk_message_id, msgID);
380 if (status != TT_OK) {
381 tt_pattern_destroy(pat);
382 return (Tt_pattern) tt_error_pointer(status);
384 tt_pattern_user_set(pat, _TTContractKey, contract);
387 /* -----> Register pattern */
389 status = tt_pattern_register(pat);
390 if (status != TT_OK) {
391 tt_pattern_destroy(pat);
392 return (Tt_pattern) tt_error_pointer(status);
400 /************************************************************************
401 * TTresetSaveArgs - resets TTDT_SAVE argments set in TTSaveContractCB()
402 ************************************************************************/
407 if (!pPad->ttSaveReq.contract)
409 pPad->ttSaveReq.contract = NULL;
410 if (pPad->ttSaveReq.messageID != (char *) NULL) {
411 XtFree(pPad->ttSaveReq.messageID);
412 pPad->ttSaveReq.messageID = (char *) NULL;
417 /************************************************************************
418 * TTfailPendingSave - fails any pending Save request
419 ************************************************************************/
424 if (pPad->ttSaveReq.contract) {
425 tttk_message_fail(pPad->ttSaveReq.contract, /* original Save req */
426 TT_DESKTOP_ECANCELED, /* status */
427 (char *) NULL, /* status string */
428 1); /* destroy request */
429 TTresetSaveArgs(pPad);