ttMsgSupport.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937
  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. /* $TOG: ttMsgSupport.c /main/7 1999/09/15 14:23:02 mgreess $ */
  24. /**********************************<+>*************************************
  25. ***************************************************************************
  26. **
  27. ** File: ttMsgSupport.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 Tool Talk "Desktop" and "Document and Media
  36. ** Exchange" message sets.
  37. **
  38. ** XXX - Need to use message catalogs for error messages and not write to
  39. ** stdout or stderr.
  40. **
  41. *******************************************************************
  42. ** (c) Copyright Hewlett-Packard Company, 1990, 1991, 1992, 1993.
  43. ** All rights are
  44. ** reserved. Copying or other reproduction of this program
  45. ** except for archival purposes is prohibited without prior
  46. ** written consent of Hewlett-Packard Company.
  47. ********************************************************************
  48. **
  49. ********************************************************************
  50. ** (c) Copyright 1993, 1994 Hewlett-Packard Company
  51. ** (c) Copyright 1993, 1994 International Business Machines Corp.
  52. ** (c) Copyright 1993, 1994 Sun Microsystems, Inc.
  53. ** (c) Copyright 1993, 1994 Novell, Inc.
  54. ********************************************************************
  55. **
  56. **
  57. **************************************************************************
  58. **********************************<+>*************************************/
  59. /* for asprintf */
  60. #if defined(__linux__) || defined(CSRG_BASED)
  61. # define _GNU_SOURCE
  62. #endif
  63. #include "dtpad.h"
  64. #include <dirent.h>
  65. #include <Dt/DtpadM.h>
  66. #include <Dt/HourGlass.h>
  67. #define TIMEOUT_FACTOR 1000
  68. XtInputId ProcessToolTalkInputId = 0;
  69. extern Editor *pPadList; /* list of Editor instances - declared in main.c */
  70. extern char *initialServerGeometry; /* declared in main.c */
  71. extern Tt_message TTSaveContractCB( /* declared in ttSaveSupport.c */
  72. Tt_message m,
  73. void * clientData,
  74. Tt_message contract);
  75. extern Tt_pattern TTCreateSavePattern( /* declared in ttSaveSupport.c */
  76. Tt_message contract,
  77. Ttdt_contract_cb clientCB,
  78. void * clientData,
  79. int register_it);
  80. /************************************************************************
  81. * TTdisplayError - posts a ToolTalk error dialog containing the specified
  82. * error message followed by the related ToolTalk status message.
  83. ************************************************************************/
  84. void
  85. TTdisplayError(
  86. Editor *pPad,
  87. char *errorMsg,
  88. Tt_status status)
  89. {
  90. char *statusMsg = tt_status_message(status);
  91. char buf[1024];
  92. if (errorMsg != (char *) NULL) {
  93. sprintf(buf, "%s\n(%d: %s)", errorMsg, status, statusMsg);
  94. } else {
  95. sprintf(buf, "(%d: %s)", status, statusMsg);
  96. }
  97. tt_free(statusMsg);
  98. Warning(pPad, buf, XmDIALOG_ERROR);
  99. }
  100. /******************************************************************************
  101. * TTdt_session_joinCB - Callback passed to ttdt_session_join() to handle
  102. * standard "Desktop" messages.
  103. *
  104. * In our case, this only deals with the standard Desktop Quit message with
  105. * signature:
  106. *
  107. * Quit(in boolean silent, in boolean force, in messageID operation2Quit)
  108. *
  109. * XXX - This routine was setup by SUN but currently does nothing since:
  110. * Requests to quit a specific Media Edit/Display request are handled in
  111. * TTdt_message_acceptCB() (which is registered in TTmedia_ptype_declareCB()
  112. * when the Media Edit/Display request is first accepted).
  113. ******************************************************************************/
  114. Tt_message
  115. TTdt_session_joinCB(
  116. Tt_message m,
  117. void * client_data,
  118. Tt_message contract)
  119. {
  120. /* should never get here, if we do, notify sender with a fail */
  121. tttk_message_fail(m,
  122. TT_DESKTOP_ENOTSUP, /* status */
  123. (char *) NULL, /* status str */
  124. 1); /* destroy request */
  125. return((Tt_message) 0); /* we handled this message */
  126. }
  127. /******************************************************************************
  128. * TTdt_message_acceptCB - callback (setup in ttdt_message_accept()) to handle
  129. * TT_HANDLER-addressed messages. Currently this routine handles:
  130. *
  131. * Quit(4) request which can contain the following arguments:
  132. *
  133. * silent - controls whether or not the user is notified
  134. * when there are unsaved changes
  135. * force - controls whether or not the Quit is aborted
  136. * when there are unsaved changes
  137. * operation2Quit - controls whether all edit window(s) are closed or
  138. * whether a specific edit window is closed
  139. *
  140. * This routine is analogous to TTSaveContractCB() which handles
  141. * Save requests. Patterns to handle Quit requests are automatically
  142. * registered via ttdt_message_accept() whereas patterns to handle Save
  143. * requests must be explicitly registered (see TTCreateSavePattern()).
  144. *
  145. * See dtpad(1) for more details.
  146. *
  147. ******************************************************************************/
  148. Tt_message
  149. TTdt_message_acceptCB(
  150. Tt_message m,
  151. void * client_data,
  152. Tt_message contract)
  153. {
  154. Editor *pPad;
  155. int silent, force;
  156. Tt_status status;
  157. char *operation2Quit;
  158. int mark = tt_mark();
  159. char *opString = tt_message_op(m);
  160. Tttk_op op = tttk_string_op(opString);
  161. if (op == TTDT_QUIT) {
  162. /* Search the list of Editor instances for one with a TT media
  163. * msg id matching the originating media msg id supplied as the
  164. * 'operation2Quit' (3rd) argument of the TTDT_QUIT msg */
  165. if (operation2Quit = tt_message_arg_val(m, 2)) {
  166. for (pPad = pPadList; pPad != (Editor *)NULL; pPad = pPad->pNextPad) {
  167. if (pPad->inUse == True && pPad->ttEditReq.msg_id &&
  168. strcmp(pPad->ttEditReq.msg_id, operation2Quit) == 0) {
  169. pPad->ttQuitReq.contract = m; /* process Quit msg */
  170. status = tt_message_arg_ival(m, 0, &silent);
  171. status = tt_message_arg_ival(m, 1, &force);
  172. pPad->ttQuitReq.silent = (Boolean) silent;
  173. pPad->ttQuitReq.force = (Boolean) force;
  174. pPad->ttQuitReq.operation2Quit = strdup(operation2Quit);
  175. FileExitCB( (Widget) NULL, (caddr_t) pPad, (caddr_t) NULL);
  176. tt_release(mark);
  177. return((Tt_message) 0); /* handling Quit */
  178. }
  179. }
  180. /* no Edit window matching the operation2Quit */
  181. tttk_message_fail(m,
  182. TT_DESKTOP_ENOMSG, /* status */
  183. (char *) NULL, /* status str */
  184. 1); /* destroy request */
  185. } else { /* no operation2Quit - quit all Edit windows */
  186. /* XXX - not currently processing this type of Quit */
  187. tttk_message_fail(m,
  188. TT_DESKTOP_ENOTSUP, /* status */
  189. (char *) NULL, /* status str */
  190. 1); /* destroy request */
  191. }
  192. /* We're handling all Quit requests. If the request has not been
  193. * failed already, pPad->ttQuitReq.contract will be non-NULL and
  194. * the Quit message will be responded to or failed later. */
  195. tt_release(mark);
  196. return((Tt_message) 0); /* handling Quit */
  197. } else { /* unsupported message type */
  198. tt_release(mark);
  199. return(m); /* didn't handle message */
  200. }
  201. }
  202. /******************************************************************************
  203. * TTmedia_ptype_declareCB - callback (set up in ttmedia_ptype_declare()) to
  204. * handle the standard ToolTalk Instantiate/Edit/Display media messages
  205. * from a "requestor" dtpad or from other applications.
  206. *
  207. * It sets up TTdt_message_acceptCB() when it "accepts" the message which
  208. * handles Quit messages relating to the accepted Instantiate/Edit/Display
  209. * message.
  210. *
  211. * Returns: 0 if the message is handled; otherwise, returns Tt_message.
  212. ******************************************************************************/
  213. Tt_message
  214. TTmedia_ptype_declareCB(
  215. Tt_message m,
  216. void * client_data,
  217. Tttk_op op,
  218. Tt_status diag,
  219. unsigned char * contents,
  220. int len,
  221. char * file,
  222. char * docname)
  223. {
  224. Editor *pPad;
  225. char *filename;
  226. Tt_message TTdt_message_acceptCB(), incoming;
  227. Tt_pattern *ttrc;
  228. DtEditorContentRec contentRec;
  229. DtEditorErrorCode errorCode;
  230. Boolean foundPad = False;
  231. char *context = (char *)NULL;
  232. Boolean isCurrentlyVisible = False;
  233. int mark = tt_mark();
  234. char *localPath = tt_message_file(m);
  235. if (diag != TT_OK
  236. && !(op == TTME_INSTANTIATE && diag == TT_DESKTOP_ENODATA)) { /* TTT - workaround for tttk bug */
  237. fprintf(stderr,
  238. "Ignored Media request with ToolTalk detected error: %s\n",
  239. tt_status_message(diag));
  240. return(m);
  241. }
  242. if (op != TTME_EDIT && op != TTME_DISPLAY && op != TTME_INSTANTIATE) {
  243. return(m); /* Message not handled by this routine. */
  244. }
  245. /* if editing a file, make sure we can read it first,
  246. * if not, fail the request immediately
  247. */
  248. if (file) {
  249. char *pathEnd;
  250. if (MbStrrchr(localPath, '/') != (char *)NULL) {
  251. char *dir; DIR *pDir;
  252. dir = (char *) XtMalloc(strlen(localPath) + 1);
  253. strcpy(dir, localPath);
  254. pathEnd = MbStrrchr(dir, '/');
  255. if (pathEnd == dir) {
  256. /* file is in the root directory
  257. */
  258. pathEnd++;
  259. }
  260. *pathEnd = (char)'\0';
  261. if ((pDir = opendir(dir)) != (DIR *)NULL) {
  262. closedir(pDir);
  263. XtFree(dir);
  264. } else {
  265. tt_free(localPath);
  266. localPath = (char *) NULL;
  267. XtFree(dir);
  268. tttk_message_fail(m,
  269. TT_DESKTOP_ENOENT, /* status */
  270. (char *) NULL, /* status str */
  271. 1); /* destroy request */
  272. tt_release(mark);
  273. return((Tt_message) 0); /* Message handled by this routine. */
  274. }
  275. }
  276. }
  277. /*
  278. * Create an Editor "instance" and manage/realize it.
  279. * This involves creating its GUI components, setting it resources,
  280. * mapping its windows and, if specified, loading the file to be edited.
  281. */
  282. if (foundPad == False)
  283. foundPad = FindOrCreatePad(&pPad); /* returns new Editor in pPad */
  284. /*
  285. * If this message is from a dtpad requestor then replace selective
  286. * server resources with requestor resources shipped to the dtpad server
  287. * in the message context fields
  288. */
  289. if (tt_message_contexts_count(m)) {
  290. /*----> a session file, want to restore a session */
  291. if (*(context = tt_message_context_val(m, "SESSION"))) {
  292. pPad->xrdb.session = strdup(context);
  293. }
  294. else {
  295. /* -----> non text editor specific resource */
  296. if (*(context = tt_message_context_val(m, "GEOMETRY"))) {
  297. pPad->geometry = strdup(context);
  298. }
  299. /* -----> basic options */
  300. if (context = tt_message_context_val(m, "STATUSLINE")) {
  301. if (*context == 't')
  302. pPad->xrdb.statusLine = True;
  303. else
  304. pPad->xrdb.statusLine = False;
  305. }
  306. if (context = tt_message_context_val(m, "WINDOWWORDWRAP")) {
  307. if (*context == 't')
  308. pPad->xrdb.wordWrap = True;
  309. else
  310. pPad->xrdb.wordWrap = False;
  311. }
  312. if (context = tt_message_context_val(m, "OVERSTRIKE")) {
  313. if (*context == 't')
  314. pPad->xrdb.overstrike = True;
  315. else
  316. pPad->xrdb.overstrike = False;
  317. }
  318. if (context = tt_message_context_val(m, "SAVEONCLOSE")) {
  319. if (*context == 't')
  320. pPad->xrdb.saveOnClose = True;
  321. else
  322. pPad->xrdb.saveOnClose = False;
  323. }
  324. if (context = tt_message_context_val(m, "MISSINGFILEWARNING")) {
  325. if (*context == 't')
  326. pPad->xrdb.missingFileWarning = True;
  327. else
  328. pPad->xrdb.missingFileWarning = False;
  329. }
  330. if (context = tt_message_context_val(m, "NOREADONLYWARNING")) {
  331. if (*context == 't')
  332. pPad->xrdb.readOnlyWarning = True;
  333. else
  334. pPad->xrdb.readOnlyWarning = False;
  335. }
  336. if (context = tt_message_context_val(m, "NONAMECHANGE")) {
  337. if (*context == 't')
  338. pPad->xrdb.nameChange = True;
  339. else
  340. pPad->xrdb.nameChange = False;
  341. }
  342. if (context = tt_message_context_val(m, "VIEWONLY")) {
  343. if (*context == 't')
  344. pPad->xrdb.viewOnly = True;
  345. else
  346. pPad->xrdb.viewOnly = False;
  347. }
  348. if (context = tt_message_context_val(m, "WORKSPACELIST")) {
  349. pPad->xrdb.workspaceList = strdup(context);
  350. }
  351. /* -----> client/server control options */
  352. if (*(context = tt_message_context_val(m, "BLOCKING"))) {
  353. pPad->xrdb.blocking = True;
  354. pPad->blockChannel = strdup(context);
  355. }
  356. }
  357. }
  358. pPad->ttEditReq.contract = m;
  359. pPad->ttEditReq.msg_id = strdup(tt_message_id(m));
  360. pPad->ttEditReq.op = op;
  361. if (op == TTME_INSTANTIATE) {
  362. pPad->ttEditReq.contents = False;
  363. pPad->ttEditReq.returnBufContents = False;
  364. } else { /* TTME_EDIT or TTME_DISPLAY */
  365. if (file) {
  366. /* the mediaType of the first arg (contents) applies to either
  367. * contents or a file */
  368. pPad->ttEditReq.vtype = strdup(tt_message_arg_type(m, 0));
  369. pPad->ttEditReq.contents = False; /* editing a file */
  370. pPad->ttEditReq.fileName = strdup(localPath);
  371. pPad->fileStuff.fileName = XtNewString(pPad->ttEditReq.fileName);
  372. } else {
  373. pPad->ttEditReq.contents = True; /* editing a buffer */
  374. pPad->xrdb.nameChange = False; /* disallow switching to another
  375. file */
  376. pPad->ttEditReq.returnBufContents = True;
  377. }
  378. if (docname) {
  379. pPad->ttEditReq.docName = strdup(docname);
  380. } else {
  381. pPad->ttEditReq.docName = (char *) NULL;
  382. }
  383. if (op == TTME_DISPLAY)
  384. pPad->xrdb.viewOnly = True;
  385. }
  386. /* -----> Create GUI components of Editor instance, set resouces,
  387. * map window and load file (if specified). */
  388. if (!foundPad) {
  389. RealizeNewPad(pPad); /* pPad->mainWindow is created here */
  390. } else {
  391. ManageOldPad(pPad, isCurrentlyVisible);
  392. }
  393. /* -----> Accept the message.
  394. *
  395. * Registers patterns in the default session to handle TT_HANDLER-addressed
  396. * requests (created by specifying the "handler" argument in
  397. * tttk_message_create) in the following manner (based on the shell and
  398. * Ttdt_contract_cb args):
  399. *
  400. * type requests handled notes
  401. * ---- -------------------- ---------------------------- -----
  402. * (1) Get|Set_Geometry, transparently (a)
  403. * Get|Set_Iconified,
  404. * Get|Set_Mapped,
  405. * Get|Set_XInfo,
  406. * Raise, Lower
  407. * (2) Pause, Resume passed to Ttdt_contract_cb (b)
  408. * (3) Quit, Get_Status passed to Ttdt_contract_cb (c)
  409. *
  410. * NOTES:
  411. * (a) type (1) requests are handled transparently because the shell
  412. * arg is specified (that is, a pattern is registered to handle
  413. * these requests via an internal TT callback)
  414. * (b) type (2) requests are handled like type (3) because
  415. * Ttdt_contract_cb is specified; otherwise they would be
  416. * handled transparently
  417. * (c) type (3) request are handled in Ttdt_contract_cb because it
  418. * was specified; otherwise they fail with TT_DESKTOP_ENOTSUP
  419. * (that is, Ttdt_contract_cb is the pattern callback registered
  420. * in the pattern to handle these requests).
  421. */
  422. ttrc = ttdt_message_accept(
  423. m, /* Tt_message */
  424. TTdt_message_acceptCB, /* Ttdt_contract_cb */
  425. pPad->app_shell, /* shell widget */
  426. pPad->mainWindow, /* client data */
  427. 1, /* call tt_message_accept() */
  428. 1); /* send STATUS notice to requestor */
  429. if (tt_ptr_error((void *) ttrc) != TT_OK) {
  430. fprintf(stderr,
  431. "Could not ttdt_message_accept the edit request: %s\n",
  432. tt_status_message((tt_ptr_error((void *) ttrc))));
  433. }
  434. /* -----> Create pattern to handle "Save" requests in a manner analogous
  435. * to "Quit" requests.
  436. * NOTE: This pattern (unlike the Quit pattern automatically registered
  437. * via ttdt_message_accept()) is *not* automatically destroyed
  438. * when the original Edit request is destroyed. */
  439. pPad->ttEditReq.savePattern = TTCreateSavePattern(
  440. m, /* Tt_message */
  441. TTSaveContractCB, /* Ttdt_contract_cb */
  442. pPad->mainWindow, /* client data - not currently used */
  443. 1); /* register it */
  444. /* -----> Set the DtEditor widget contents. */
  445. if (pPad->ttEditReq.contents) {
  446. contentRec.type = DtEDITOR_TEXT;
  447. contentRec.value.string = (char *) contents;
  448. errorCode = DtEditorSetContents(pPad->editor, &contentRec);
  449. /* [SuG 5/18/95] Done
  450. The NOT_SAMPLE warnings/errors need to be added to the message
  451. catalog. Removed ifdefs.*/
  452. switch (errorCode) {
  453. case DtEDITOR_NO_ERRORS:
  454. break;
  455. case DtEDITOR_NULLS_REMOVED:
  456. Warning(pPad, (char *) GETMESSAGE(6, 6,
  457. "Embedded Nulls stripped from file."),
  458. XmDIALOG_WARNING);
  459. break;
  460. case DtEDITOR_INSUFFICIENT_MEMORY:
  461. Warning(pPad, (char*) GETMESSAGE(6, 7,
  462. "Unable to load file (insufficient memory)."),
  463. XmDIALOG_ERROR);
  464. break;
  465. default:
  466. Warning(pPad, (char *) GETMESSAGE(6, 12,
  467. "Unable to read from the file (unknown reason)."),
  468. XmDIALOG_ERROR);
  469. break;
  470. }
  471. }
  472. tt_release(mark);
  473. return((Tt_message) 0); /* Message handled by this routine. */
  474. }
  475. /********************** Exported Functions (via dtpad.h) **********************/
  476. /******************************************************************************
  477. * TTstartDesktopMediaExchange - Initializes Took Talk for handling the
  478. * "Desktop" and "Document & Media Exchange" message sets.
  479. *
  480. * Returns: True if successful; 0 if failure.
  481. ******************************************************************************/
  482. Tt_status
  483. TTstartDesktopMediaExchange(
  484. Widget topLevelWithWmCommand,
  485. Editor * pPad)
  486. {
  487. char *my_procid = NULL;
  488. int my_ttfd = 0;
  489. Tt_pattern *tt_pat = NULL;
  490. Tt_status status = TT_OK;
  491. int mark = tt_mark();
  492. char *sess = NULL;
  493. /*
  494. * Open a connection to the ToolTalk service
  495. * and send a Started notice so other applications know we're up.
  496. */
  497. sess = (char *)getenv("TT_SESSION");
  498. if (!sess || (*sess == '\0')) {
  499. sess = getenv("_SUN_TT_SESSION");
  500. }
  501. if (!sess || (*sess == '\0')) {
  502. tt_default_session_set(
  503. tt_X_session(XDisplayString(XtDisplay(topLevelWithWmCommand))) );
  504. }
  505. status = TTdesktopOpen( &my_ttfd, pPad, (int) pPad->xrdb.server);
  506. if (TT_OK != status)
  507. return(status);
  508. if (pPad->xrdb.server == True) {
  509. /*
  510. * Declare we will handle messages defined under our ptype
  511. * which in this case currently consist of the Instantialte, Display
  512. * and Edit messages from the Media set, as defined in dtpad.ptypes.
  513. * This will enable auto start of dtpad if any of the messages in the
  514. * ptype are received.
  515. */
  516. if ((status = ttmedia_ptype_declare(
  517. DTPAD_TOOL_CLASS, /* ptype */
  518. 0, /* base opnum */
  519. TTmedia_ptype_declareCB,/* Ttmedia_load_pat_cb */
  520. (void *) pPadList, /* client data */
  521. 1)) /* call tt_ptype_declare() */
  522. != TT_OK) {
  523. fprintf(stderr,
  524. "Could not register as %s tool class handler: %s\n",
  525. DTPAD_TOOL_CLASS,
  526. tt_status_message(status)) ;
  527. return(status);
  528. }
  529. /*
  530. * Join the default session,
  531. * and register to deal with standard Desktop requests in the following
  532. * manner (controlled by the Ttdt_contract_cb and shell arguments):
  533. *
  534. * type requests handled notes
  535. * ---- -------------------- ---------------------------- -----
  536. * (1) Get|Set_Environment, transparently
  537. * Get|Set_Locale,
  538. * Get|Set_Situation,
  539. * Signal, Get_Sysinfo
  540. * (2) Get|Set_Geometry, fail with TT_DESKTOP_ENOTSUP (b)
  541. * Get|Set_Iconified,
  542. * Get|Set_Mapped,
  543. * Raise, Lower,
  544. * Set_Xinfo,
  545. * Get_Xinfo transparently
  546. * (3) Pause, Resume, Quit passed to Ttdt_contract_cb (c)
  547. * (4) Get_Status, Do_Command passed to Ttdt_contract_cb
  548. *
  549. * NOTES:
  550. * (b) type (2) requests (except Get_Xinfo) fail because the shell
  551. * arg is not a "realized mappedWhenManaged applicationShellWidget"
  552. * (c) type (3) requests are not handled transparently because
  553. * Ttdt_contract_cb is specified
  554. */
  555. tt_pat = ttdt_session_join(
  556. (const char *) 0, /* join default session */
  557. TTdt_session_joinCB, /* Ttdt_contract_cb */
  558. topLevelWithWmCommand, /* shell widget */
  559. (void *) 0, /* client data */
  560. 1); /* really join the session */
  561. if ((status = tt_ptr_error(tt_pat)) != TT_OK) {
  562. fprintf(stderr,
  563. "Could not join default ToolTalk session: %s\n",
  564. tt_status_message(tt_ptr_error(tt_pat)));
  565. ttdt_close(0, 0, 1);
  566. return(status);
  567. }
  568. }
  569. /*
  570. * Have Xt monitor the connection to the ToolTalk service.
  571. * tttk_Xt_input_handler() will ultimately call tt_message_receive(),
  572. * which will invoke the callbacks we've registered.
  573. */
  574. XtAppAddInput(XtWidgetToApplicationContext(topLevelWithWmCommand),
  575. my_ttfd, (XtPointer) XtInputReadMask, tttk_Xt_input_handler,
  576. my_procid);
  577. return(status);
  578. }
  579. /************************************************************************
  580. * TTmediaDepositContents - sends a ToolTalk Deposit request (containing
  581. * the current contents of the DtEditor widget) directly to the
  582. * sender of the original media request.
  583. *
  584. * Returns: 0 if successful; !0 if failure.
  585. ************************************************************************/
  586. Boolean
  587. TTmediaDepositContents(
  588. Editor *pPad)
  589. {
  590. DtEditorErrorCode errorCode;
  591. DtEditorContentRec contentRec;
  592. Boolean addNewlines = pPad->xrdb.wordWrap == True &&
  593. pPad->fileStuff.saveWithNewlines == True;
  594. Tt_status status;
  595. _DtTurnOnHourGlass(pPad->app_shell);
  596. contentRec.type = DtEDITOR_TEXT;
  597. errorCode = DtEditorGetContents(
  598. pPad->editor,
  599. &contentRec,
  600. addNewlines,
  601. False); /* don't mark contents as saved yet */
  602. if (errorCode != DtEDITOR_NO_ERRORS) {
  603. Warning(pPad,
  604. "Internal Error: Unable to get contents from Editor Widget.",
  605. XmDIALOG_ERROR);
  606. return(1);
  607. }
  608. status = ttmedia_Deposit(
  609. pPad->ttEditReq.contract, /* original request */
  610. (char *) NULL, /* send directly to requestor */
  611. pPad->ttEditReq.vtype, /* media type */
  612. (unsigned char *) contentRec.value.string, /*new contents */
  613. strlen(contentRec.value.string),
  614. (char *) NULL, /* don't use temp file for xfer */
  615. pPad->app_context, /* we're the blocking application */
  616. 10 * TIMEOUT_FACTOR); /* milliseconds to block for reply */
  617. if (status == TT_OK) {
  618. /* XXX - an inefficient way of marking contents as saved -
  619. * need to use a global to keep track of unsaved changes
  620. * and replace DtEditorCheckForUnsavedChanges() */
  621. errorCode = DtEditorGetContents(
  622. pPad->editor,
  623. &contentRec,
  624. addNewlines,
  625. True); /* mark contents as saved */
  626. _DtTurnOffHourGlass(pPad->app_shell);
  627. } else {
  628. _DtTurnOffHourGlass(pPad->app_shell);
  629. TTdisplayError(pPad,
  630. (char *) GETMESSAGE(13, 1, "Checkpoint save failed."),
  631. status);
  632. return(1);
  633. }
  634. return(0);
  635. }
  636. /************************************************************************
  637. * TTmediaReply - replies to (and closes) a ToolTalk media request.
  638. *
  639. * If a file is being edited, it is assumed at this point that it
  640. * has already been updated with the current contents.
  641. *
  642. * If a buffer is being edited, the current text is included in the
  643. * reply only if pPad->ttEditReq.returnBufContents is True.
  644. *
  645. * Returns: 0 if successful; !0 if failure.
  646. ************************************************************************/
  647. Boolean
  648. TTmediaReply(
  649. Editor *pPad)
  650. {
  651. DtEditorErrorCode errorCode;
  652. DtEditorContentRec contentRec;
  653. Tt_status status;
  654. Boolean addNewlines = pPad->xrdb.wordWrap == True &&
  655. pPad->fileStuff.saveWithNewlines == True;
  656. _DtTurnOnHourGlass(pPad->app_shell);
  657. if (! pPad->ttEditReq.contract) {
  658. return 0;
  659. }
  660. /* ----> Not editing a buffer */
  661. if (! pPad->ttEditReq.contents) {
  662. status = ttmedia_load_reply(
  663. pPad->ttEditReq.contract, /* original request */
  664. (unsigned char *) 0, /* new contents */
  665. 0, /* contents length */
  666. True); /* destroy message after reply */
  667. _DtTurnOffHourGlass(pPad->app_shell);
  668. if (status == TT_OK) {
  669. pPad->ttEditReq.contract = 0; /* request has been closed */
  670. return(0);
  671. } else {
  672. TTdisplayError(pPad,
  673. (char *) GETMESSAGE(13, 2, "Checkpoint reply failed."),
  674. status);
  675. return(1);
  676. }
  677. }
  678. /* ----> Editing a buffer */
  679. if (pPad->ttEditReq.returnBufContents) {
  680. /* -----> Include the contents in the reply */
  681. contentRec.type = DtEDITOR_TEXT;
  682. errorCode = DtEditorGetContents(
  683. pPad->editor,
  684. &contentRec,
  685. addNewlines,
  686. False); /* don't mark contents as saved yet */
  687. if (errorCode != DtEDITOR_NO_ERRORS) {
  688. Warning(pPad,
  689. "Internal Error: Unable to get contents from Editor Widget.",
  690. XmDIALOG_ERROR);
  691. tttk_message_fail(pPad->ttEditReq.contract,
  692. TT_DESKTOP_ENODATA, /* status */
  693. (char *) NULL, /* status str */
  694. 1); /* destroy request */
  695. return(1);
  696. }
  697. status = ttmedia_load_reply(
  698. pPad->ttEditReq.contract, /* original request */
  699. (unsigned char *) contentRec.value.string, /* new contents */
  700. strlen(contentRec.value.string),
  701. True); /* destroy message after reply */
  702. if (status == TT_OK) {
  703. /* XXX - an inefficient way of marking contents as saved -
  704. * need to use a global to keep track of unsaved changes
  705. * and replace DtEditorCheckForUnsavedChanges() */
  706. errorCode = DtEditorGetContents(
  707. pPad->editor,
  708. &contentRec,
  709. addNewlines,
  710. True); /* mark contents as saved */
  711. _DtTurnOffHourGlass(pPad->app_shell);
  712. pPad->ttEditReq.contract = NULL; /* request has been closed */
  713. } else {
  714. _DtTurnOffHourGlass(pPad->app_shell);
  715. TTdisplayError(pPad,
  716. (char *) GETMESSAGE(13, 2, "Checkpoint reply failed."),
  717. status);
  718. return(1);
  719. }
  720. } else {
  721. /* -----> Don't include anything in the buffer reply (e.g.
  722. * when the user responds "no" to saving unsaved contents).
  723. *
  724. * NOTE: TT_DESKTOP_ECANCELED changes the "failure" into a "reply".
  725. */
  726. status = tttk_message_fail(
  727. pPad->ttEditReq.contract, /* original request */
  728. TT_DESKTOP_ECANCELED, /* status */
  729. (char *) NULL, /* status str */
  730. 1); /* destroy request */
  731. _DtTurnOffHourGlass(pPad->app_shell);
  732. if (status == TT_OK) {
  733. pPad->ttEditReq.contract = NULL; /* request has been closed */
  734. } else {
  735. TTdisplayError(pPad,
  736. (char *) GETMESSAGE(13, 2, "Checkpoint reply failed."),
  737. status);
  738. return(1);
  739. }
  740. }
  741. return(0);
  742. }
  743. /************************************************************************
  744. * TTresetQuitArgs - resets TTDT_QUIT arguments set in TTdt_message_acceptCB()
  745. ************************************************************************/
  746. void
  747. TTresetQuitArgs(
  748. Editor *pPad)
  749. {
  750. if (!pPad->ttQuitReq.contract)
  751. return;
  752. pPad->ttQuitReq.contract = NULL;
  753. if (pPad->ttQuitReq.operation2Quit != (char *) NULL) {
  754. XtFree(pPad->ttQuitReq.operation2Quit);
  755. pPad->ttQuitReq.operation2Quit = (char *) NULL;
  756. }
  757. pPad->ttQuitReq.silent = 0;
  758. pPad->ttQuitReq.force = 0;
  759. }
  760. /************************************************************************
  761. * TTfailPendingQuit - fails any pending Quit request - even if 'force' is
  762. * specified
  763. ************************************************************************/
  764. void
  765. TTfailPendingQuit(
  766. Editor *pPad)
  767. {
  768. if (pPad->ttQuitReq.contract) {
  769. tttk_message_fail(pPad->ttQuitReq.contract, /* original Quit req */
  770. TT_DESKTOP_ECANCELED, /* status */
  771. (char *) NULL, /* status string */
  772. 1); /* destroy request */
  773. TTresetQuitArgs(pPad);
  774. }
  775. }
  776. /************************************************************************
  777. * TTdesktopOpen - This procedure just opens a connection to
  778. * ToolTalk so a simple message can be sent.
  779. ************************************************************************/
  780. Tt_status
  781. TTdesktopOpen( int *ttFd, Editor *pPad, Boolean sendStarted )
  782. {
  783. char * procId;
  784. Tt_status status;
  785. char *vendor;
  786. #ifdef sun
  787. vendor = "Sun Microsystems";
  788. #elif defined(_AIX)
  789. vendor = "IBM";
  790. #else
  791. vendor = "Unknown";
  792. #endif /* _AIX */
  793. procId = ttdt_open( ttFd, "dtpad", vendor, "2.1", sendStarted );
  794. if ( (status = tt_ptr_error( procId )) != TT_OK )
  795. {
  796. ttdt_close( NULL, NULL, sendStarted );
  797. return( status );
  798. }
  799. ProcessToolTalkInputId =
  800. XtAppAddInput( pPad->app_context,
  801. *ttFd, (XtPointer)XtInputReadMask,
  802. tttk_Xt_input_handler, procId );
  803. return( TT_OK );
  804. }
  805. /************************************************************************
  806. * TTwarning - This procedure displays a message dialog and exits.
  807. ************************************************************************/
  808. /* ARGSUSED */
  809. static void
  810. okCB(Widget w, XtPointer clientData, XtPointer callData)
  811. {
  812. *((int*) clientData) = 1;
  813. }
  814. void
  815. TTwarning( Editor *pPad, Tt_status status, char *errsuff )
  816. {
  817. FileWidgets *pFileWidgets;
  818. char *errfmt;
  819. char *errmsg;
  820. char *statmsg;
  821. int done = 0;
  822. if (TT_OK == status || NULL == pPad) return;
  823. errfmt =
  824. GETMESSAGE(7, 13, "Could not connect to ToolTalk service:\n%s\n%s\n");
  825. statmsg = tt_status_message(status);
  826. errmsg = XtMalloc(strlen(errfmt) + strlen(statmsg) + strlen(errsuff) + 2);
  827. if (NULL == errsuff) errsuff = "";
  828. fprintf(stderr, errfmt, statmsg, errsuff);
  829. sprintf(errmsg, errfmt, statmsg, errsuff);
  830. Warning(pPad, errmsg, XmDIALOG_ERROR);
  831. pFileWidgets = &pPad->fileStuff.fileWidgets;
  832. XtAddCallback(pFileWidgets->gen_warning, XmNokCallback,
  833. (XtCallbackProc) okCB, (XtPointer) &done);
  834. XFlush(pPad->display);
  835. XSync(pPad->display, False);
  836. while ( !done )
  837. {
  838. XtAppProcessEvent(
  839. XtWidgetToApplicationContext(pFileWidgets->gen_warning),
  840. XtIMAll);
  841. }
  842. }