Exceptionally hacky linux fix. gnu gencat is returning != 0 even when it's
[oweals/cde.git] / cde / programs / dtpad / ttSaveSupport.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
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)
10  * any later version.
11  *
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
16  * details.
17  *
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
22  */
23 /* $XConsortium: ttSaveSupport.c /main/4 1996/05/08 20:09:07 drk $ */
24 /**********************************<+>*************************************
25 ***************************************************************************
26 **
27 **  File:        ttSaveSupport.c
28 **
29 **  Project:     DT dtpad, a memo maker type editor based on the Dt Editor
30 **               widget.
31 **
32 **  Description:
33 **  -----------
34 **
35 **  Provides support for the ToolTalk "Save" message in a manner analogous
36 **  to "Quit" message support provided by the ttdt_message_accept() function.
37 **
38 *******************************************************************
39 **  (c) Copyright Hewlett-Packard Company, 1990, 1991, 1992, 1993.
40 **  All rights are
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 ********************************************************************
45 **
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 ********************************************************************
52 **
53 **
54 **************************************************************************
55 **********************************<+>*************************************/
56 #include "dtpad.h"
57
58 /* definitions from tttk/tttkutils.h */
59 char _TTKeys[7];
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])
67
68 extern Editor *pPadList;  /*  list of Editor instances - declared in main.c */
69
70 /******************************************************************************
71  *  TTSaveContractCB - callback (setup in ttdt_message_accept()) to handle
72  *      Save(4) requests.  Currently this routine handles one argument:
73  *
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).
77  *
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()).
82  *
83  *      See dtpad(1) for more details.
84  *
85  ******************************************************************************/
86 Tt_message
87 TTSaveContractCB(
88         Tt_message      m,
89         void *          clientData,
90         Tt_message      contract)
91 {
92     Editor *pPad;
93     int silent, force;
94     Tt_status status;
95     char *messageID;
96     int mark = tt_mark();
97
98     char *opString = tt_message_op(m);
99     Tttk_op op = tttk_string_op(opString);
100
101     if (op == TTDT_SAVE) {
102
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);
113                     tt_release(mark);
114                     return((Tt_message) 0);     /* handling Save */
115                 }
116             }
117             /* no Edit window matching the messageID */
118             tttk_message_fail(m,
119                         TT_DESKTOP_ECANCELED,           /* status */
120                         (char *) NULL,                  /* status str */
121                         1);                             /* destroy request */
122
123         } else {        /* no messageID - which is required */
124             tttk_message_fail(m,
125                         TT_DESKTOP_ECANCELED,           /* status */
126                         (char *) NULL,                  /* status str */
127                         1);                             /* destroy request */
128         }
129
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. */
133         tt_release(mark);
134         return((Tt_message) 0); /* handling Quit */
135
136     } else {    /* unsupported message type */
137
138         tt_release(mark);
139         return(m);      /* didn't handle message */
140
141     }
142
143 }
144
145
146
147 /******************************************************************************
148  * _TT_pattern_contract - obtains the contracting message from the pattern
149  ******************************************************************************/
150 Tt_message
151 _TT_pattern_contract(
152         Tt_pattern      pat)
153 {
154     void *contract = tt_pattern_user(pat, _TTContractKey);
155     Tt_status status = tt_ptr_error(contract);
156     if (status != TT_OK) {
157         return 0;
158     }
159     return (Tt_message) contract;
160 }
161
162
163
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
169 _TTpatternCB(
170         Tt_message      msg,
171         Tt_pattern      pat)
172 {
173     Ttdt_contract_cb    clientCB;
174     void *              clientData;
175     Tt_status           status;
176
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;
182     }
183     if (clientCB == 0) {
184         return TT_CALLBACK_CONTINUE;
185     }
186
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;
192     }
193
194     /* -----> Call client callback */
195     msg = (*clientCB)(msg, clientData, _TT_pattern_contract(pat));
196
197     status = tt_ptr_error(msg);
198     if ((status != TT_OK) || (msg == 0)) {
199         return TT_CALLBACK_PROCESSED;
200     } else {
201         return TT_CALLBACK_CONTINUE;
202     }
203 }
204
205
206 /******************************************************************************
207  * _TTCreatePattern - creates a pattern for a desktop message
208  *      (ala cdesrc/lib/tt/lib/tttk/tttkpattern.C:_ttDtPatternCreate())
209  ******************************************************************************/
210 Tt_pattern
211 _TTCreatePattern(
212         Tt_category             category,
213         Tt_scope                theScope,
214         int                     addDefaultSess,
215         const char *            file,
216         const char *            op_string,
217         Ttdt_contract_cb        clientCB,
218         void *                  clientData)
219 {
220
221     Tt_pattern pat = tt_pattern_create();
222     Tt_status status = tt_ptr_error(pat);
223     if (status != TT_OK) {
224         return pat;
225     }
226
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);
231     }
232
233     /* we only observe notices and only handle requests */
234     if (category == TT_HANDLE) {
235         status = tt_pattern_class_add(pat, TT_REQUEST);
236     }
237     if (category == TT_OBSERVE) {
238         status = tt_pattern_class_add(pat, TT_NOTICE);
239     }
240     if (status != TT_OK) {
241         tt_pattern_destroy(pat);
242         return (Tt_pattern)tt_error_pointer(status);
243     }
244
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);
249     }
250
251     if (addDefaultSess) {
252         char *sess = tt_default_session();
253         status = tt_pattern_session_add(pat, sess);
254         tt_free(sess);
255         if (status != TT_OK) {
256             tt_pattern_destroy(pat);
257             return (Tt_pattern)tt_error_pointer(status);
258         }
259     }
260
261     if (file != 0) {
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);
266         }
267     }
268
269     if (op_string) {
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);
274         }
275     }
276
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);
286     }
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);
291     }
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);
296     }
297
298     return pat;
299 }
300
301
302
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  ******************************************************************************/
307 char *
308 _TTmessage_id(
309         Tt_message      msg)
310 {
311     int i, miss, numArgs = tt_message_args_count( msg );
312     Tt_status status = tt_int_error( numArgs );
313     char *msgID;
314
315     if (status != TT_OK) {
316         return 0;
317     }
318
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) {
323             return 0;
324         }
325         if (type == 0) {
326             continue;
327         }
328         miss = strcmp(type, Tttk_message_id);
329         tt_free(type);
330         if (miss) {
331             continue;
332         }
333         msgID = tt_message_arg_val(msg, i);
334         status = tt_ptr_error(type);
335         if (status != TT_OK) {
336             return 0;
337         }
338         return msgID;
339     }
340
341     return tt_message_id(msg);
342 }
343
344
345
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  ******************************************************************************/
351 Tt_pattern
352 TTCreateSavePattern(
353         Tt_message              contract,
354         Ttdt_contract_cb        clientCB,
355         void *                  clientData,
356         int                     register_it)
357 {
358     char *msgID;
359
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 */
367                         clientCB,
368                         clientData);
369
370     Tt_status status = tt_ptr_error( pat );
371     if (status != TT_OK) {
372                 return pat;
373     }
374
375     /* -----> Add message id and contracting message to pattern */
376     if (contract != 0) {
377         char *msgID = _TTmessage_id(contract);
378         status = tt_pattern_arg_add(pat, TT_IN, Tttk_message_id, msgID);
379         tt_free(msgID);
380         if (status != TT_OK) {
381             tt_pattern_destroy(pat);
382             return (Tt_pattern) tt_error_pointer(status);
383         }
384         tt_pattern_user_set(pat, _TTContractKey, contract);
385     }
386
387     /* -----> Register pattern */
388     if (register_it) {
389         status = tt_pattern_register(pat);
390         if (status != TT_OK) {
391             tt_pattern_destroy(pat);
392             return (Tt_pattern) tt_error_pointer(status);
393         }
394     }
395
396     return pat;
397 }
398
399
400 /************************************************************************
401  * TTresetSaveArgs - resets TTDT_SAVE argments set in TTSaveContractCB()
402  ************************************************************************/
403 void
404 TTresetSaveArgs(
405         Editor *pPad)
406 {
407     if (!pPad->ttSaveReq.contract)
408         return;
409     pPad->ttSaveReq.contract = NULL;
410     if (pPad->ttSaveReq.messageID != (char *) NULL) {
411         XtFree(pPad->ttSaveReq.messageID);
412         pPad->ttSaveReq.messageID = (char *) NULL;
413     }
414 }
415
416
417 /************************************************************************
418  * TTfailPendingSave - fails any pending Save request
419  ************************************************************************/
420 void
421 TTfailPendingSave(
422         Editor *pPad)
423 {
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);
430     }
431 }