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