dtwm: basic multihead(xinerama only) support
[oweals/cde.git] / cde / programs / dticon / main.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* $TOG: main.c /main/11 1999/09/17 13:25:57 mgreess $ */
24 /*********************************************************************
25 *  (c) Copyright 1993, 1994 Hewlett-Packard Company
26 *  (c) Copyright 1993, 1994 International Business Machines Corp.
27 *  (c) Copyright 1993, 1994 Sun Microsystems, Inc.
28 *  (c) Copyright 1993, 1994 Unix System Labs, Inc., a subsidiary of
29 *      Novell, Inc.
30 **********************************************************************/
31 /*-----------------------------------------------------------*/
32 /* This is the project main program file.                    */
33 /* You may add application dependent source code             */
34 /* at the appropriate places.                                */
35 /*-----------------------------------------------------------*/
36 #include <stdio.h>
37 #include <stdint.h>
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #include <fcntl.h>
41 #include <locale.h>
42 #include <sys/param.h>
43
44 #include <X11/Intrinsic.h>
45 #include <Xm/Protocols.h>
46 #include <Xm/DialogS.h>
47 #include <Xm/MessageB.h>
48 #include <Xm/MwmUtil.h>
49 #include <Dt/EnvControlP.h>
50 #include <Dt/UserMsg.h>
51 #include "externals.h"
52 #include "main.h"
53
54 #ifdef __TOOLTALK
55 #include <Tt/tttk.h>
56 int ttMark;
57 int tt_tmpfile_fd = -1;
58 static int undeclared = 0;
59 static Tt_message local_msg = (Tt_message) 0;
60 void DieFromToolTalkError( );
61 Tt_message ProcessToolTalkMessage( );
62 Tt_message ProcessToolTalkMediaMessage( );
63 extern void ProcessAppArgs();
64 void send_tt_saved();
65 #define dticon_ptype "DT_Icon_Editor"
66 #endif
67
68 #define ERROR           -1
69 #define NO_ERROR        0
70
71 static XtResource resources[] = {
72   {"useMessaging", "UseMessaging", XmRBoolean, sizeof (Boolean),
73     XtOffset (ApplicationDataPtr, useBMS), XmRImmediate, (XtPointer)False,
74   },
75   {"session", "Session", XmRString, sizeof (char *),
76     XtOffset (ApplicationDataPtr, session), XmRImmediate, (XtPointer)NULL,
77   },
78   {"bmSuffix", "BmSuffix", XmRString, sizeof (char *),
79     XtOffset (ApplicationDataPtr, bmSuffix), XmRImmediate, (XtPointer)".bm",
80   },
81   {"pmSuffix", "PmSuffix", XmRString, sizeof (char *),
82     XtOffset (ApplicationDataPtr, pmSuffix), XmRImmediate, (XtPointer)".pm",
83   },
84   {"maxIconWidth", "MaxIconWidth", XmRInt, sizeof (int),
85     XtOffset (ApplicationDataPtr, maxIconWidth), XmRImmediate,
86     (caddr_t)MAX_ICON_WIDTH,
87   },
88   {"maxIconHeight", "MaxIconHeight", XmRInt, sizeof (int),
89     XtOffset (ApplicationDataPtr, maxIconHeight), XmRImmediate,
90     (caddr_t)MAX_ICON_HEIGHT,
91   },
92   {"useFileFilter", "UseFileFilter", XmRBoolean, sizeof (Boolean),
93     XtOffset (ApplicationDataPtr, useFileFilter), XmRImmediate, (XtPointer)True,
94   },
95   {"useFileLists", "UseFileLists", XmRBoolean, sizeof (Boolean),
96     XtOffset (ApplicationDataPtr, useFileLists), XmRImmediate, (XtPointer)True,
97   },
98 };
99
100 static XrmOptionDescRec option_list[] =
101 {
102    {"-noMessaging", "useMessaging", XrmoptionNoArg, (caddr_t)"FALSE"},
103    {"-session", "session", XrmoptionSepArg, NULL},
104    {"-bmSuffix", "bmSuffix", XrmoptionSepArg, NULL},
105    {"-pmSuffix", "pmSuffix", XrmoptionSepArg, NULL},
106    {"-maxIconWidth", "maxIconWidth", XrmoptionSepArg, (caddr_t)MAX_ICON_WIDTH},
107    {"-maxIconHeight", "maxIconHeight",XrmoptionSepArg,(caddr_t)MAX_ICON_HEIGHT},
108    {"-noFileFilter", "useFileFilter", XrmoptionNoArg, (caddr_t)"FALSE"},
109    {"-noFileLists", "useFileLists", XrmoptionNoArg, (caddr_t)"FALSE"},
110    {"-useFileFilter", "useFileFilter", XrmoptionNoArg, (caddr_t)"TRUE"},
111    {"-useFileLists", "useFileLists", XrmoptionNoArg, (caddr_t)"TRUE"},
112 };
113
114
115 extern Widget mainForm, iconForm, fileMenu_quit_pb;
116 extern void GetSessionInfo();
117 extern char start_file[];
118 extern char dummy[];
119
120
121 /*-----------------------------------------------------------*/
122 /* Insert application global declarations here               */
123 /*-----------------------------------------------------------*/
124
125 XtAppContext AppContext;
126 Widget       TopLevel;
127 Widget       dticonShell;
128 char        *execName, *progName;
129 char msgID[120];
130
131
132
133
134 /*-----------------------------------------------------------*/
135 /* User has selected window manager close button... verify   */
136 /* close desired if data has not been saved.                 */
137 /*-----------------------------------------------------------*/
138 static void
139 CloseCB (
140         Widget w,
141         XtPointer clientData,
142         XtPointer callbackArg )
143 {
144     DialogFlag = QUIT;
145     XtCallCallbacks (fileMenu_quit_pb, XmNactivateCallback, NULL);
146 }
147
148
149 /*-----------------------------------------------------------*/
150 /* Session is ending, save session information               */
151 /*-----------------------------------------------------------*/
152 static void
153 SaveSessionCB (
154         Widget w,
155         XtPointer clientData,
156         XtPointer callbackArg )
157 {
158 #ifdef DEBUG
159   if (debug)
160     stat_out("SaveSessionCB\n");
161 #endif
162
163     SaveSession();
164 }
165
166
167
168 /*-----------------------------------------------------------*/
169 /*-----------------------------------------------------------*/
170 /* main                                                      */
171 /*-----------------------------------------------------------*/
172 /*-----------------------------------------------------------*/
173 int
174 main(
175         int argc,
176         char *argv[] )
177 {
178         /*-----------------------------------------------------------*/
179         /* Declarations.                                             */
180         /*-----------------------------------------------------------*/
181         Widget  w, d;
182         int n;
183         Arg args[20];
184         Atom xa_WM_DELETE_WINDOW, xa_WM_SAVE_YOURSELF;
185         char *tmpPtr=NULL;
186         static char *untitledStr = NULL;
187         char *p=NULL;
188         char *tmpp=NULL;
189
190 #ifdef __TOOLTALK
191     int ttFd;
192     char * procId;
193     Tt_status ttRc;
194     char * sessionString;
195 #endif
196
197         /*-----------------------------------------------------------*/
198         /* Interface function declaration                            */
199         /*-----------------------------------------------------------*/
200         Widget  create_dtIconShell();
201         Widget  create_newIconDialog();
202         Widget  create_queryDialog();
203         Widget  create_stdErrDialog();
204         Widget  create_fileIODialog();
205         void    GetMarginData();
206
207
208         /* ------------------------*/
209         /*      Initialize program      */
210         /*------------------------------*/
211         _DtEnvControl(DT_ENV_SET); /* set up environment variables */
212
213         XtSetLanguageProc(NULL, NULL, NULL);
214
215         execName = argv[0];
216         if (progName=strrchr(argv[0], '/'))
217             progName++;
218         else
219             progName = argv[0];
220
221
222         TopLevel = XtAppInitialize(&AppContext, CLASS_NAME,
223                                 option_list, XtNumber(option_list),
224                                 &argc, argv, NULL, NULL, 0);
225
226         XtGetApplicationResources(TopLevel, &xrdb, resources,
227                                       XtNumber(resources), NULL, 0);
228
229         GetSessionInfo();
230
231
232
233         /*------------------------------------------------------------*/
234         /*    Insert initialization code for your application here    */
235         /*------------------------------------------------------------*/
236
237
238         /*------------------------------------------------------------------*/
239         /*  Create and popup the first window of the interface.  The        */
240         /*  return value can be used in the popdown or destroy functions.   */
241         /*------------------------------------------------------------------*/
242         w = create_dtIconShell();
243         dticonShell = w;
244         d = create_fileIODialog();
245         d = create_newIconDialog();
246         d = create_queryDialog();
247         d = create_stdErrDialog();
248         Create_Gfx_Labels(Foreground, Background);
249         AssignHelpCallbacks();
250
251         XtRealizeWidget (TopLevel);
252         XtMapWidget (TopLevel);
253
254         GetMarginData();
255
256         /* */
257         /*  Since I can't change the .msg files I'll have to force
258             it here.
259         */
260     last_fname[0] = '\0';
261     if (!untitledStr)
262       untitledStr = GETSTR(2,20, "UNTITLED");
263     strcpy(last_fname, untitledStr);
264     strcat(last_fname, ".m.pm");
265     ChangeTitle();
266         /* */
267
268         ParseAppArgs(argc, argv);
269         if (start_file[0] != '\0')
270         {
271            /* strip off path portion of name if there is one */
272            tmpPtr = strrchr(start_file,'/');
273            if (tmpPtr != NULL)
274                XtSetArg(args[0], XmNiconName, tmpPtr+1);
275            else
276                XtSetArg(args[0], XmNiconName, start_file);
277            XtSetValues(dtIconShell, args, 1);
278         }
279         n = 0;
280         XtSetArg(args[n], XmNresizePolicy, XmRESIZE_NONE); n++;
281         XtSetValues(mainForm, args, n);
282         XtSetValues(iconForm, args, n);
283
284         /*------------------------------------------------------------------*/
285         /*   Catch window close event and call "File...Exit" callback.      */
286         /*------------------------------------------------------------------*/
287         xa_WM_DELETE_WINDOW = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
288         XmAddWMProtocolCallback(dtIconShell, xa_WM_DELETE_WINDOW, CloseCB,
289                                 NULL);
290
291         /*------------------------------------------------------------------*/
292         /*   Register for save and restore.                                 */
293         /*------------------------------------------------------------------*/
294         xa_WM_SAVE_YOURSELF = XInternAtom(dpy, "WM_SAVE_YOURSELF", False);
295         XmAddWMProtocolCallback(dtIconShell, xa_WM_SAVE_YOURSELF,
296                                 SaveSessionCB, NULL);
297
298 #ifdef __TOOLTALK
299     ttMark = tt_mark( );
300     p = (char *)getenv("TT_SESSION");
301     if (!p || strlen(p)==0) {
302     tt_default_session_set( tt_X_session( XDisplayString( dpy )));}
303
304     procId = ttdt_open( &ttFd, "dticon", "CDE", "1.0", 1 );
305     ttRc = tt_ptr_error(procId);
306     tmpPtr = GETSTR(8, 8, "Could not connect to ToolTalk:\n%s\nExiting ...");
307     DieFromToolTalkError( dticonShell, tmpPtr, ttRc );
308
309     ttRc = ttmedia_ptype_declare( dticon_ptype, 0,
310                                   ProcessToolTalkMediaMessage, NULL, 0);
311     DieFromToolTalkError( dticonShell, "ttmedia_ptype_declare: %s", ttRc );
312
313     ttRc = ttmedia_ptype_declare( dticon_ptype, 1000,
314                                   ProcessToolTalkMediaMessage, NULL, 0);
315     DieFromToolTalkError( dticonShell, "ttmedia_ptype_declare: %s", ttRc );
316
317     ttRc = ttmedia_ptype_declare( dticon_ptype, 2000,
318                                   ProcessToolTalkMediaMessage, NULL, 1);
319     DieFromToolTalkError( dticonShell, "ttmedia_ptype_declare: %s", ttRc );
320
321     tttk_Xt_input_handler(NULL, 0, 0);
322
323     ttRc = tt_ptr_error(ttdt_session_join( tt_default_session( ),
324                                           ProcessToolTalkMessage,
325                                           (Widget) 0, NULL, 1));
326     DieFromToolTalkError( dticonShell, "ttdt_session_join: %s", ttRc );
327
328     XtAppAddInput( AppContext, ttFd, (XtPointer)XtInputReadMask,
329                         tttk_Xt_input_handler, 0 );
330     if (!undeclared) tt_ptype_undeclare(dticon_ptype);
331     tt_release(ttMark);
332 #endif
333
334
335         /*-------------------------*/
336         /*   Enter the event loop  */
337         /*-------------------------*/
338         {
339             XEvent event;
340
341             for (;;) {
342                 XtAppNextEvent(AppContext, &event);
343                 if ((GraphicsOp == S_GRAB) &&
344                     ((event.type == ButtonPress)  ||
345                      (event.type == MotionNotify) ||
346                      (event.type == ButtonRelease)))
347                   Do_ButtonOp(&event);
348                 else
349                 {
350                     if ((GraphicsOp == POLYGON || GraphicsOp == POLYLINE) &&
351                           (event.type == ButtonPress))
352                     {
353                         if (event.xbutton.window != tablet_win)
354                             EndPolyOp();
355                     }
356                     XtDispatchEvent(&event);
357                 }
358             }
359         }
360 }
361
362 #ifdef __TOOLTALK
363
364 static void
365 ExitCB (Widget dialog, XtPointer client_data, XtPointer call_data)
366 {
367     exit((int) (intptr_t) client_data);
368 }
369
370 void
371 DieFromToolTalkError(Widget parent, char *errfmt, Tt_status status)
372 {
373     Arg          args[10];
374     Widget       dialog, dialogShell;
375     char        *errmsg, *statmsg, *title;
376     XmString     xms_errmsg, xms_ok, xms_title;
377     int          n;
378
379     if (! tt_is_err(status)) return;
380
381     statmsg = tt_status_message(status);
382     errmsg = XtMalloc(strlen(errfmt) + strlen(statmsg) + 2);
383     sprintf(errmsg, errfmt, statmsg);
384
385     xms_ok = GETXMSTR(8,6, "OK");
386     xms_errmsg = XmStringCreateLocalized(errmsg);
387     xms_title = GETXMSTR(8,2, "Icon Editor - Error");
388
389     n = 0;
390     XtSetArg(args[n], XmNautoUnmanage, False); n++;
391     XtSetArg(args[n], XmNokLabelString, xms_ok); n++;
392     XtSetArg(args[n], XmNdialogTitle, xms_title); n++;
393     XtSetArg(args[n], XmNmessageString, xms_errmsg); n++;
394     XtSetArg(args[n], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL); n++;
395
396     dialog = XmCreateErrorDialog(parent, "IconEditorError", args, n);
397     XtAddCallback(dialog, XmNokCallback, ExitCB, (XtPointer) status);
398     XtUnmanageChild(XmMessageBoxGetChild(dialog, XmDIALOG_CANCEL_BUTTON));
399     XtUnmanageChild(XmMessageBoxGetChild(dialog, XmDIALOG_HELP_BUTTON));
400
401     /*
402      * Disable the frame menu from dialog since we don't want the user
403      * to be able to close dialogs with the frame menu
404      */
405     dialogShell = XtParent(dialog);
406     n = 0;
407     XtSetArg(args[n], XmNmwmDecorations, MWM_DECOR_ALL | MWM_DECOR_MENU); n++;
408     XtSetValues(dialogShell, args, n);
409     XtManageChild(dialog);
410     XtRealizeWidget(dialogShell);
411
412     _DtSimpleError(CLASS_NAME, DtFatalError, NULL, errmsg);
413
414     XtFree(errmsg);
415     XmStringFree(xms_ok);
416     XmStringFree(xms_errmsg);
417     XmStringFree(xms_title);
418
419     while (TRUE)
420       XtAppProcessEvent(XtWidgetToApplicationContext(dialog), XtIMAll);
421 }
422
423
424 Tt_message ProcessToolTalkMediaMessage( Tt_message      msg,
425                                         void*           cdata,
426                                         Tttk_op         op,
427                                         Tt_status       diag,
428                                         unsigned char*  contents,
429                                         int             len,
430                                         char*           file,
431                                         char*           doc)
432 {
433 int mark = tt_mark();
434 int tmplen=0;
435 int tt_tmpMaskfile_fd = -1;
436 char mask_file[MAX_FNAME];
437 char *tmp = NULL;
438 char *tmp1 = NULL;
439
440 if (tt_message_status(msg) == TT_WRN_START_MESSAGE) tt_message_reply(msg);
441
442
443   switch(op) {
444     case TTME_COMPOSE:
445         /*
446          * At this time, we don't handle composing new icons.
447          * Fail any such requests.
448          */
449         tt_message_fail(msg);
450         break;
451     case TTME_DISPLAY:
452         /*
453          * At this time, we don't handle displaying icons
454          * without editing them.
455          * Fail any such requests.
456          */
457         tt_message_fail(msg);
458         break;
459     case TTME_EDIT:
460
461         /*
462          * Undeclare the ptype so that this process will
463          * not service any more TT requests.
464          */
465
466         tt_ptype_undeclare(dticon_ptype);
467         undeclared = 1;
468
469         if (tt_message_status(msg) != TT_WRN_START_MESSAGE)
470         {
471           /*
472            * A message came in while we were already up
473            * and running -- reject it so that another dticon
474            * process will be started up to service this
475            * request.
476            */
477
478           tt_message_reject(msg);
479         }
480         else if (edit_notifier(NULL, msg, 0))
481         {
482            strcpy( msgID, tt_message_arg_val(msg, 1) );
483
484            if (file)
485            {
486                    /*
487                     * Icon data is in a file
488                    */
489                    strcpy(start_file, file);
490            }
491            else
492            {
493              /*
494               * Icon data is in a buffer -- write it
495               * to a /tmp file.
496              */
497              unsigned char* buf;
498              int blen;
499              int wlen;
500
501              if (tt_message_arg_bval(msg, 0,
502                                      &buf, &blen) != TT_OK)
503              {
504                 tt_message_fail(msg);
505                 edit_notifier(NULL, 0, 1);
506              }
507              else
508              {
509                 (void) tmpnam(start_file);
510                 if( (buf) && (!strncmp((char *)buf, "/* XPM */", 9)) )
511                 {
512                    /* Format XPM */
513                    tt_tmpfile_fd =
514                            open(start_file,
515                                 O_CREAT | O_WRONLY | O_NDELAY,
516                                 0666);
517                    if (tt_tmpfile_fd && (wlen =
518                                  write(tt_tmpfile_fd,
519                                        buf, blen)) == blen)
520                    {
521                       (void) close(tt_tmpfile_fd);
522                       param_flag[AUTO_FILE] = True;
523                       argsNeedProcessed = True;
524                    }
525                    else {
526                            tt_message_fail(msg);
527                            edit_notifier(NULL, 0, 1);
528                         }
529                 }
530                 else
531                 {
532                    /* Format XBM */
533                    /* assume two buffers.... */
534                    tmp = strchr((char *)buf, ';');
535                    tmp ++;
536                    tmplen=blen - strlen(tmp);
537
538                      /* read XBM file first*/
539                      /* Grab the first buffer. */
540                      tt_tmpfile_fd =
541                              open(start_file,
542                                   O_CREAT | O_WRONLY | O_NDELAY,
543                                   0666);
544
545                      if (tt_tmpfile_fd && (wlen =
546                                    write(tt_tmpfile_fd,
547                                          buf, tmplen)) == tmplen)
548                      {
549                         (void) close(tt_tmpfile_fd);
550                         param_flag[AUTO_FILE] = True;
551                         argsNeedProcessed = True;
552                      }
553                      else
554                      {
555                              tt_message_fail(msg);
556                             edit_notifier(NULL, 0, 1);
557                      }
558
559                    /* Try to find the second buffer. */
560                    tmp ++;
561                    if(tmp) tmp1=strchr(tmp, ';');
562
563                    if (tmp1)
564                    {
565                       /* we have a mask */
566                       /* construct the name of the mask file */
567                       strcpy(mask_file, start_file);
568                       strcat(mask_file, "_m\0");
569                       tt_tmpMaskfile_fd =
570                             open(mask_file,
571                             O_CREAT | O_WRONLY | O_NDELAY,
572                             0666);
573                       /* Read the mask fro the seconf buffer. */
574                       if (tt_tmpMaskfile_fd && (wlen =
575                       write(tt_tmpMaskfile_fd,
576                             tmp, strlen(tmp))) == strlen(tmp))
577                       {
578                          (void) close(tt_tmpMaskfile_fd);
579                          param_flag[AUTO_FILE] = True;
580                          argsNeedProcessed = True;
581                       }
582                       else {
583                               tt_message_fail(msg);
584                               edit_notifier(NULL, 0, 1);
585                            }
586                    }
587                 } /* else XBM Format */
588              }
589            }
590         }
591     break;
592   }
593
594   tt_release(mark);
595   return (Tt_message) 0;
596 }
597
598 int
599 edit_notifier(char* fname, Tt_message msg, int clear)
600 {
601         /*
602          * Triple-mode function that either (1) saves the message
603          * so it can be replied to later, (2) replies to a
604          * previously-saved message, or (3) clears its state.
605          */
606
607         if (clear) {
608                 if (local_msg != (Tt_message) 0) {
609                         tt_message_reply(local_msg);
610                         tt_message_destroy(local_msg);
611                 }
612                 local_msg = (Tt_message) 0;
613
614                 return 1;
615         }
616
617         if (fname && !msg) {
618
619                 /*
620                  * Not currently used, DELETE THIS COMMENT if it
621                  * is ever needed.
622                  */
623
624                 if (local_msg != (Tt_message) 0) {
625                         /*
626                          * Set the filename arg to the new, passed-in
627                          * file name, and reply to the message.
628                          */
629                         tt_message_arg_val_set(local_msg, 0, fname);
630                         tt_message_reply(local_msg);
631                         local_msg = (Tt_message) 0;
632                 }
633                 return 1;
634         }
635         else if (!fname && msg) {
636                 /*
637                  * Just store the message for a later reply.  If
638                  * we already have a stored message, return a failure
639                  * status (0) and reject the incoming message.
640                  */
641                 if (local_msg != (Tt_message) 0) {
642                         tt_message_reject(msg);
643                         return 0;
644                 }
645                 else {
646                         local_msg = msg;
647                         return 1;
648                 }
649         }
650         else {
651                 /*
652                  * The caller is confused.
653                  */
654                 tt_message_reject(msg);
655                 return 0;
656         }
657 }
658
659
660 void
661 send_tt_saved()
662 {
663         int mark;
664         int fd;
665         int fdm;
666         int len=0;
667         int Mlen=0;
668         int rlen=0;
669         char* buffer=NULL;
670         char* Fbuffer=NULL;
671         char* Mbuffer=NULL;
672         struct stat statbuf;        /* Information on a file. */
673         Tt_status ttstat;
674         Tt_message msg;
675
676         mark = tt_mark();
677         msg = tt_message_create();
678         tt_message_address_set(msg, TT_HANDLER);
679         tt_message_handler_set(msg, tt_message_sender(local_msg));
680         tt_message_class_set(msg, TT_NOTICE);
681         tt_message_scope_set(msg, TT_SESSION);
682         tt_message_session_set(msg, tt_default_session());
683         tt_message_op_set(msg, "Saved");
684
685         /* Read the base file regardless of format */
686         fd = open(last_fname, O_RDONLY | O_NDELAY);
687         len = lseek(fd, 0, SEEK_END);
688         (void) lseek(fd, 0, SEEK_SET);
689         Fbuffer = XtMalloc(len + 1);
690         if ((rlen = read(fd, Fbuffer, len)) != len)
691         {
692         /* didn't read whole file! */
693         printf("dtcreate: Only read %d of %d bytes of icon file!\n", rlen, len);
694         }
695         (void) close(fd);
696         Fbuffer[len]='\0';
697
698         rlen = 0;
699         /* Handle the XBM format */
700         if( (fileFormat != FORMAT_XPM) && (stat(dummy, &statbuf) == 0) )
701         {
702            /* Read the mask file if one exists */
703            fdm = open(dummy, O_RDONLY | O_NDELAY);
704            Mlen = lseek(fdm, 0, SEEK_END);
705            (void) lseek(fdm, 0, SEEK_SET);
706            Mbuffer = XtMalloc(Mlen + 1);
707            if ((rlen = read(fdm, Mbuffer, Mlen)) != Mlen)
708            {
709                /* didn't read whole file! */
710                printf(
711                 "dtcreate: Only read %d of %d bytes of icon file!\n",
712                 rlen, Mlen);
713            }
714            (void) close(fdm);
715            Mbuffer[Mlen] ='\0';
716
717            /* Double buffer the base and mask */
718            buffer = XtMalloc(strlen(Fbuffer)+strlen(Mbuffer)+1);
719            strcpy(buffer, Fbuffer);
720            buffer[strlen(Fbuffer)] ='\0';
721            strcat(buffer, Mbuffer);
722            buffer[strlen(Fbuffer)+strlen(Mbuffer)+1] ='\0';
723            XtFree(Mbuffer);
724         }
725         else
726         {
727            /* No mask/bm just pass the pm file */
728              buffer = XtMalloc(len + 1);
729              strcpy(buffer, Fbuffer);
730              buffer[len+1] ='\0';
731         }
732
733         tt_message_barg_add(msg, TT_IN, tt_message_arg_type(local_msg, 0),
734                             (void *) buffer, Mlen+len+1);
735         tt_message_arg_add(msg, TT_IN, "string", msgID);
736
737         ttstat = tt_message_send(msg);
738         tt_message_destroy(msg);
739         tt_release(mark);
740
741         XtFree(Fbuffer);
742         XtFree(buffer);
743 }
744
745
746 Tt_message ProcessToolTalkMessage(Tt_message msg,
747                                   void* cdata,
748                                   Tt_message contract)
749 {
750         int mark = tt_mark();
751         char* op = tt_message_op(msg);
752
753         if (!strcmp(op, "Quit")) {
754                 /*
755                  * Do any necessary cleanup here, call
756                  * tt_message_reply(), and quit.
757                  * Since this is not currently implemented here,
758                  * the message will just be failed for now.
759                  */
760                 tt_message_fail(msg);
761         }
762         /*
763          * The messages that must interact with the X environment
764          * are not supported currently.  If a realized,
765          * mappedWhenManaged top-level widget were passed to
766          * ttdt_session_join(), they would be handled automatically.
767          * Since that is not the case, they are passed to this
768          * callback, and could be implemented here if desired
769          * (if so, be sure to change tt_message_reject to
770          * tt_message_reply!).
771          */
772         else {
773                 tt_message_reject(msg);
774         }
775
776         tt_release(mark);
777         return (Tt_message) 0;
778 }
779
780 #endif
781
782
783 /******************************************************************************
784 NAME:           handle_dialog_child( wgt, manage_func )
785
786 INPUT:          Widget  wgt                     - the dialogShellWidget
787                 void    (*manage_func)()        - either XtManageChild
788                                                   or XtUnmanageChild
789
790 RETURN:         int                             - NO_ERROR if successfull
791                                                   ERROR otherwise
792
793 DESCRIPTION:    Handles the popping up or popping down of dialog shells
794                 by managing or unmanaging their children.
795
796 CREATION:       Visual Edge Software            Sept 19/91
797 -----------------------------------------------------------------------------*/
798 static  int     handle_dialog_child( Widget wgt, void (*manage_func)() )
799 {
800         int      i;
801         XtArgVal num_children;
802         Widget  *children;
803
804         XtVaGetValues( wgt,
805                        XmNnumChildren, &num_children,
806                        XmNchildren, &children,
807                        NULL );
808
809         /* We manage/unmanage the first rectObj child in the list.
810          * Note that the check for rectObjClass is necessary since some
811          * implementations of Motif add protocol children to the dialogShell.
812          */
813
814         for (i = 0; i < (int)num_children; i++)
815         {
816                 if ( XtIsSubclass( children[i], rectObjClass ) )
817                 {
818                         (*manage_func)(children[i]);
819                         return ( NO_ERROR );
820                 }
821         }
822
823         return ( ERROR );
824 }
825
826 /******************************************************************************
827 NAME:           PopupInterface( wgt, grab_flag )
828
829 INPUT:          Widget          wgt             - Widget to popup
830                 XtGrabKind      grab_flag       - grab flag
831
832 RETURN:         int                     ERROR or NO_ERROR
833
834 DESCRIPTION:    Popups up an interface. The widget should be a toplevel widget.
835                 Note that special handling is required for dialogShells since
836                 those are popped up by managing their children if they have
837                 some.
838                 The grab_flag could be any of:
839                                 no_grab (XtGrabNone)
840                                 nonexclusive_grab (XtGrabNonexclusive)
841                                 exclusive_grab (XtGrabExclusive)
842
843 CREATION:       Visual Edge Software            April 6 1991
844 -----------------------------------------------------------------------------*/
845 int     PopupInterface( Widget wgt, XtGrabKind grab_flag )
846 {
847
848         if ( XtIsSubclass( wgt, xmDialogShellWidgetClass ) )
849         {
850                 if ( handle_dialog_child( wgt, XtManageChild ) == ERROR )
851                         XtPopup( wgt, grab_flag );
852         }
853         else
854         {
855                 XtPopup( wgt, grab_flag );
856         }
857
858         return ( NO_ERROR );
859 }