ttMsgSupport.c 30 KB

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