ttSaveSupport.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431
  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 libraries 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. /* definitions from tttk/tttkutils.h */
  58. char _TTKeys[7];
  59. #define _TTCBKey ((int)(intptr_t)&_TTKeys[0])
  60. #define _TTClientCBKey ((int)(intptr_t)&_TTKeys[1])
  61. #define _TTClientDataKey ((int)(intptr_t)&_TTKeys[2])
  62. #define _TTDepositPatKey ((int)(intptr_t)&_TTKeys[3])
  63. #define _TTJoinInfoKey ((int)(intptr_t)&_TTKeys[4])
  64. #define _TTContractKey ((int)(intptr_t)&_TTKeys[5])
  65. #define _TTSubContractKey ((int)(intptr_t)&_TTKeys[6])
  66. extern Editor *pPadList; /* list of Editor instances - declared in main.c */
  67. /******************************************************************************
  68. * TTSaveContractCB - callback (setup in ttdt_message_accept()) to handle
  69. * Save(4) requests. Currently this routine handles one argument:
  70. *
  71. * messageID - This must be the message ID the originating Edit
  72. * request whose contents are to that is to be saved
  73. * (or deposited if a buffer is being edited).
  74. *
  75. * This routine is analogous to TTdt_message_acceptCB() which handles
  76. * Quit requests. Patterns to handle Quit requests are automatically
  77. * registered via ttdt_message_accept() whereas patterns to handle Save
  78. * requests must be explicitly registered (see TTCreateSavePattern()).
  79. *
  80. * See dtpad(1) for more details.
  81. *
  82. ******************************************************************************/
  83. Tt_message
  84. TTSaveContractCB(
  85. Tt_message m,
  86. void * clientData,
  87. Tt_message contract)
  88. {
  89. Editor *pPad;
  90. int silent, force;
  91. Tt_status status;
  92. char *messageID;
  93. int mark = tt_mark();
  94. char *opString = tt_message_op(m);
  95. Tttk_op op = tttk_string_op(opString);
  96. if (op == TTDT_SAVE) {
  97. /* Search the list of Editor instances for one with a TT media
  98. * msg id matching the originating media msg id supplied as the
  99. * 'messageID' (1st) argument of the TTDT_SAVE msg */
  100. if (messageID = tt_message_arg_val(m, 0)) {
  101. for (pPad = pPadList; pPad != (Editor *)NULL; pPad = pPad->pNextPad) {
  102. if (pPad->inUse == True && pPad->ttEditReq.msg_id &&
  103. strcmp(pPad->ttEditReq.msg_id, messageID) == 0) {
  104. pPad->ttSaveReq.contract = m; /* process Save msg */
  105. pPad->ttSaveReq.messageID = strdup(messageID);
  106. FileSaveCB((Widget) NULL, (caddr_t) pPad, (caddr_t) NULL);
  107. tt_release(mark);
  108. return((Tt_message) 0); /* handling Save */
  109. }
  110. }
  111. /* no Edit window matching the messageID */
  112. tttk_message_fail(m,
  113. TT_DESKTOP_ECANCELED, /* status */
  114. (char *) NULL, /* status str */
  115. 1); /* destroy request */
  116. } else { /* no messageID - which is required */
  117. tttk_message_fail(m,
  118. TT_DESKTOP_ECANCELED, /* status */
  119. (char *) NULL, /* status str */
  120. 1); /* destroy request */
  121. }
  122. /* We're handling all Save requests. If the request has not been
  123. * failed already, pPad->ttSaveReq.contract will be non-NULL and
  124. * the Save message will be responded to or failed later. */
  125. tt_release(mark);
  126. return((Tt_message) 0); /* handling Quit */
  127. } else { /* unsupported message type */
  128. tt_release(mark);
  129. return(m); /* didn't handle message */
  130. }
  131. }
  132. /******************************************************************************
  133. * _TT_pattern_contract - obtains the contracting message from the pattern
  134. ******************************************************************************/
  135. Tt_message
  136. _TT_pattern_contract(
  137. Tt_pattern pat)
  138. {
  139. void *contract = tt_pattern_user(pat, _TTContractKey);
  140. Tt_status status = tt_ptr_error(contract);
  141. if (status != TT_OK) {
  142. return 0;
  143. }
  144. return (Tt_message) contract;
  145. }
  146. /******************************************************************************
  147. * _TTpatternCB - Retrieves the client callback and callback arguments from
  148. * the pattern and calls it (ala tttkpattern.C:_ttDtPatternCB()).
  149. ******************************************************************************/
  150. static Tt_callback_action
  151. _TTpatternCB(
  152. Tt_message msg,
  153. Tt_pattern pat)
  154. {
  155. Ttdt_contract_cb clientCB;
  156. void * clientData;
  157. Tt_status status;
  158. /* ----> Obtain client callback */
  159. clientCB = (Ttdt_contract_cb) tt_pattern_user(pat, _TTClientCBKey);
  160. status = tt_ptr_error(clientCB);
  161. if (status != TT_OK) {
  162. return TT_CALLBACK_PROCESSED;
  163. }
  164. if (clientCB == 0) {
  165. return TT_CALLBACK_CONTINUE;
  166. }
  167. /* ----> Obtain client data */
  168. clientData = tt_pattern_user(pat, _TTClientDataKey);
  169. status = tt_ptr_error(clientData);
  170. if (status != TT_OK) {
  171. return TT_CALLBACK_PROCESSED;
  172. }
  173. /* -----> Call client callback */
  174. 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;
  178. } else {
  179. return TT_CALLBACK_CONTINUE;
  180. }
  181. }
  182. /******************************************************************************
  183. * _TTCreatePattern - creates a pattern for a desktop message
  184. * (ala cdesrc/lib/tt/lib/tttk/tttkpattern.C:_ttDtPatternCreate())
  185. ******************************************************************************/
  186. Tt_pattern
  187. _TTCreatePattern(
  188. Tt_category category,
  189. Tt_scope theScope,
  190. int addDefaultSess,
  191. const char * file,
  192. const char * op_string,
  193. Ttdt_contract_cb clientCB,
  194. void * clientData)
  195. {
  196. Tt_pattern pat = tt_pattern_create();
  197. Tt_status status = tt_ptr_error(pat);
  198. if (status != TT_OK) {
  199. return pat;
  200. }
  201. status = tt_pattern_category_set(pat, category);
  202. if (status != TT_OK) {
  203. tt_pattern_destroy(pat);
  204. return (Tt_pattern)tt_error_pointer(status);
  205. }
  206. /* we only observe notices and only handle requests */
  207. if (category == TT_HANDLE) {
  208. status = tt_pattern_class_add(pat, TT_REQUEST);
  209. }
  210. if (category == TT_OBSERVE) {
  211. status = tt_pattern_class_add(pat, TT_NOTICE);
  212. }
  213. if (status != TT_OK) {
  214. tt_pattern_destroy(pat);
  215. return (Tt_pattern)tt_error_pointer(status);
  216. }
  217. status = tt_pattern_scope_add(pat, theScope);
  218. if (status != TT_OK) {
  219. tt_pattern_destroy(pat);
  220. return (Tt_pattern)tt_error_pointer(status);
  221. }
  222. if (addDefaultSess) {
  223. char *sess = tt_default_session();
  224. status = tt_pattern_session_add(pat, sess);
  225. tt_free(sess);
  226. if (status != TT_OK) {
  227. tt_pattern_destroy(pat);
  228. return (Tt_pattern)tt_error_pointer(status);
  229. }
  230. }
  231. if (file != 0) {
  232. status = tt_pattern_file_add(pat, file);
  233. if (status != TT_OK) {
  234. tt_pattern_destroy(pat);
  235. return (Tt_pattern)tt_error_pointer(status);
  236. }
  237. }
  238. if (op_string) {
  239. status = tt_pattern_op_add(pat, op_string);
  240. if (status != TT_OK) {
  241. tt_pattern_destroy(pat);
  242. return (Tt_pattern)tt_error_pointer(status);
  243. }
  244. }
  245. /* -----> Add the general purpose pattern callback (as well as the
  246. * client callback and client data) as fields to the pattern.
  247. * When the general purpose pattern callback is called, it
  248. * obtains the client callback and client data from the pattern
  249. * and calls the client callback with the appropriate arguments. */
  250. status = tt_pattern_callback_add( pat, _TTpatternCB );
  251. if (status != TT_OK) {
  252. tt_pattern_destroy(pat);
  253. return (Tt_pattern)tt_error_pointer(status);
  254. }
  255. status = tt_pattern_user_set(pat, _TTClientCBKey, (void *) clientCB);
  256. if (status != TT_OK) {
  257. tt_pattern_destroy(pat);
  258. return (Tt_pattern)tt_error_pointer(status);
  259. }
  260. status = tt_pattern_user_set(pat, _TTClientDataKey, clientData);
  261. if (status != TT_OK) {
  262. tt_pattern_destroy(pat);
  263. return (Tt_pattern)tt_error_pointer(status);
  264. }
  265. return pat;
  266. }
  267. /******************************************************************************
  268. * _TTmessage_id - Returns sender-set message id if any, otherwise the
  269. * tt_message_id() (ala lib/tt/lib/tttk/tttkmessage.C:_tttk_message_id())
  270. ******************************************************************************/
  271. char *
  272. _TTmessage_id(
  273. Tt_message msg)
  274. {
  275. int i, miss, numArgs = tt_message_args_count( msg );
  276. Tt_status status = tt_int_error( numArgs );
  277. char *msgID;
  278. if (status != TT_OK) {
  279. return 0;
  280. }
  281. for (i = 0; i < numArgs; i++) {
  282. char *type = tt_message_arg_type(msg, i);
  283. status = tt_ptr_error(type);
  284. if (status != TT_OK) {
  285. return 0;
  286. }
  287. if (type == 0) {
  288. continue;
  289. }
  290. miss = strcmp(type, Tttk_message_id);
  291. tt_free(type);
  292. if (miss) {
  293. continue;
  294. }
  295. msgID = tt_message_arg_val(msg, i);
  296. status = tt_ptr_error(type);
  297. if (status != TT_OK) {
  298. return 0;
  299. }
  300. return msgID;
  301. }
  302. return tt_message_id(msg);
  303. }
  304. /******************************************************************************
  305. * TTCreateSavePattern - Creates and (optionally) registers a pattern to handle
  306. * Save requests (ala cdesrc/lib/tt/lib/tttk/ttdesktop.C:_ttdt_pat() and
  307. * _ttDesktopPatternFinish())
  308. ******************************************************************************/
  309. Tt_pattern
  310. TTCreateSavePattern(
  311. Tt_message contract,
  312. Ttdt_contract_cb clientCB,
  313. void * clientData,
  314. int register_it)
  315. {
  316. char *msgID;
  317. /* -----> Create pattern */
  318. Tt_pattern pat = _TTCreatePattern(
  319. TT_HANDLE, /* catagory */
  320. TT_SESSION, /* scope */
  321. 1, /* add default session to pat */
  322. 0, /* don't add file to pat */
  323. "Save", /* desktop message (op) type */
  324. clientCB,
  325. clientData);
  326. Tt_status status = tt_ptr_error( pat );
  327. if (status != TT_OK) {
  328. return pat;
  329. }
  330. /* -----> Add message id and contracting message to pattern */
  331. if (contract != 0) {
  332. char *msgID = _TTmessage_id(contract);
  333. status = tt_pattern_arg_add(pat, TT_IN, Tttk_message_id, msgID);
  334. tt_free(msgID);
  335. if (status != TT_OK) {
  336. tt_pattern_destroy(pat);
  337. return (Tt_pattern) tt_error_pointer(status);
  338. }
  339. tt_pattern_user_set(pat, _TTContractKey, contract);
  340. }
  341. /* -----> Register pattern */
  342. if (register_it) {
  343. status = tt_pattern_register(pat);
  344. if (status != TT_OK) {
  345. tt_pattern_destroy(pat);
  346. return (Tt_pattern) tt_error_pointer(status);
  347. }
  348. }
  349. return pat;
  350. }
  351. /************************************************************************
  352. * TTresetSaveArgs - resets TTDT_SAVE arguments set in TTSaveContractCB()
  353. ************************************************************************/
  354. void
  355. TTresetSaveArgs(
  356. Editor *pPad)
  357. {
  358. if (!pPad->ttSaveReq.contract)
  359. return;
  360. pPad->ttSaveReq.contract = NULL;
  361. if (pPad->ttSaveReq.messageID != (char *) NULL) {
  362. XtFree(pPad->ttSaveReq.messageID);
  363. pPad->ttSaveReq.messageID = (char *) NULL;
  364. }
  365. }
  366. /************************************************************************
  367. * TTfailPendingSave - fails any pending Save request
  368. ************************************************************************/
  369. void
  370. TTfailPendingSave(
  371. Editor *pPad)
  372. {
  373. if (pPad->ttSaveReq.contract) {
  374. tttk_message_fail(pPad->ttSaveReq.contract, /* original Save req */
  375. TT_DESKTOP_ECANCELED, /* status */
  376. (char *) NULL, /* status string */
  377. 1); /* destroy request */
  378. TTresetSaveArgs(pPad);
  379. }
  380. }