2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
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)
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
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
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
30 **********************************************************************/
31 /*-----------------------------------------------------------*/
32 /* This is the project main program file. */
33 /* You may add application dependent source code */
34 /* at the appropriate places. */
35 /*-----------------------------------------------------------*/
38 #include <sys/types.h>
42 #include <sys/param.h>
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"
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();
65 #define dticon_ptype "DT_Icon_Editor"
71 static XtResource resources[] = {
72 {"useMessaging", "UseMessaging", XmRBoolean, sizeof (Boolean),
73 XtOffset (ApplicationDataPtr, useBMS), XmRImmediate, (XtPointer)False,
75 {"session", "Session", XmRString, sizeof (char *),
76 XtOffset (ApplicationDataPtr, session), XmRImmediate, (XtPointer)NULL,
78 {"bmSuffix", "BmSuffix", XmRString, sizeof (char *),
79 XtOffset (ApplicationDataPtr, bmSuffix), XmRImmediate, (XtPointer)".bm",
81 {"pmSuffix", "PmSuffix", XmRString, sizeof (char *),
82 XtOffset (ApplicationDataPtr, pmSuffix), XmRImmediate, (XtPointer)".pm",
84 {"maxIconWidth", "MaxIconWidth", XmRInt, sizeof (int),
85 XtOffset (ApplicationDataPtr, maxIconWidth), XmRImmediate,
86 (caddr_t)MAX_ICON_WIDTH,
88 {"maxIconHeight", "MaxIconHeight", XmRInt, sizeof (int),
89 XtOffset (ApplicationDataPtr, maxIconHeight), XmRImmediate,
90 (caddr_t)MAX_ICON_HEIGHT,
92 {"useFileFilter", "UseFileFilter", XmRBoolean, sizeof (Boolean),
93 XtOffset (ApplicationDataPtr, useFileFilter), XmRImmediate, (XtPointer)True,
95 {"useFileLists", "UseFileLists", XmRBoolean, sizeof (Boolean),
96 XtOffset (ApplicationDataPtr, useFileLists), XmRImmediate, (XtPointer)True,
100 static XrmOptionDescRec option_list[] =
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"},
115 extern Widget mainForm, iconForm, fileMenu_quit_pb;
116 extern void GetSessionInfo();
117 extern char start_file[];
121 /*-----------------------------------------------------------*/
122 /* Insert application global declarations here */
123 /*-----------------------------------------------------------*/
125 XtAppContext AppContext;
128 char *execName, *progName;
134 /*-----------------------------------------------------------*/
135 /* User has selected window manager close button... verify */
136 /* close desired if data has not been saved. */
137 /*-----------------------------------------------------------*/
141 XtPointer clientData,
142 XtPointer callbackArg )
145 XtCallCallbacks (fileMenu_quit_pb, XmNactivateCallback, NULL);
149 /*-----------------------------------------------------------*/
150 /* Session is ending, save session information */
151 /*-----------------------------------------------------------*/
155 XtPointer clientData,
156 XtPointer callbackArg )
160 stat_out("SaveSessionCB\n");
168 /*-----------------------------------------------------------*/
169 /*-----------------------------------------------------------*/
171 /*-----------------------------------------------------------*/
172 /*-----------------------------------------------------------*/
178 /*-----------------------------------------------------------*/
180 /*-----------------------------------------------------------*/
184 Atom xa_WM_DELETE_WINDOW, xa_WM_SAVE_YOURSELF;
186 static char *untitledStr = NULL;
194 char * sessionString;
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();
208 /* ------------------------*/
209 /* Initialize program */
210 /*------------------------------*/
211 _DtEnvControl(DT_ENV_SET); /* set up environment variables */
213 XtSetLanguageProc(NULL, NULL, NULL);
216 if (progName=strrchr(argv[0], '/'))
222 TopLevel = XtAppInitialize(&AppContext, CLASS_NAME,
223 option_list, XtNumber(option_list),
224 &argc, argv, NULL, NULL, 0);
226 XtGetApplicationResources(TopLevel, &xrdb, resources,
227 XtNumber(resources), NULL, 0);
233 /*------------------------------------------------------------*/
234 /* Insert initialization code for your application here */
235 /*------------------------------------------------------------*/
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();
244 d = create_fileIODialog();
245 d = create_newIconDialog();
246 d = create_queryDialog();
247 d = create_stdErrDialog();
248 Create_Gfx_Labels(Foreground, Background);
249 AssignHelpCallbacks();
251 XtRealizeWidget (TopLevel);
252 XtMapWidget (TopLevel);
257 /* Since I can't change the .msg files I'll have to force
260 last_fname[0] = '\0';
262 untitledStr = GETSTR(2,20, "UNTITLED");
263 strcpy(last_fname, untitledStr);
264 strcat(last_fname, ".m.pm");
268 ParseAppArgs(argc, argv);
269 if (start_file[0] != '\0')
271 /* strip off path portion of name if there is one */
272 tmpPtr = strrchr(start_file,'/');
274 XtSetArg(args[0], XmNiconName, tmpPtr+1);
276 XtSetArg(args[0], XmNiconName, start_file);
277 XtSetValues(dtIconShell, args, 1);
280 XtSetArg(args[n], XmNresizePolicy, XmRESIZE_NONE); n++;
281 XtSetValues(mainForm, args, n);
282 XtSetValues(iconForm, args, n);
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,
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);
300 p = (char *)getenv("TT_SESSION");
301 if (!p || strlen(p)==0) {
302 tt_default_session_set( tt_X_session( XDisplayString( dpy )));}
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 );
309 ttRc = ttmedia_ptype_declare( dticon_ptype, 0,
310 ProcessToolTalkMediaMessage, NULL, 0);
311 DieFromToolTalkError( dticonShell, "ttmedia_ptype_declare: %s", ttRc );
313 ttRc = ttmedia_ptype_declare( dticon_ptype, 1000,
314 ProcessToolTalkMediaMessage, NULL, 0);
315 DieFromToolTalkError( dticonShell, "ttmedia_ptype_declare: %s", ttRc );
317 ttRc = ttmedia_ptype_declare( dticon_ptype, 2000,
318 ProcessToolTalkMediaMessage, NULL, 1);
319 DieFromToolTalkError( dticonShell, "ttmedia_ptype_declare: %s", ttRc );
321 tttk_Xt_input_handler(NULL, 0, 0);
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 );
328 XtAppAddInput( AppContext, ttFd, (XtPointer)XtInputReadMask,
329 tttk_Xt_input_handler, 0 );
330 if (!undeclared) tt_ptype_undeclare(dticon_ptype);
335 /*-------------------------*/
336 /* Enter the event loop */
337 /*-------------------------*/
342 XtAppNextEvent(AppContext, &event);
343 if ((GraphicsOp == S_GRAB) &&
344 ((event.type == ButtonPress) ||
345 (event.type == MotionNotify) ||
346 (event.type == ButtonRelease)))
350 if ((GraphicsOp == POLYGON || GraphicsOp == POLYLINE) &&
351 (event.type == ButtonPress))
353 if (event.xbutton.window != tablet_win)
356 XtDispatchEvent(&event);
365 ExitCB (Widget dialog, XtPointer client_data, XtPointer call_data)
367 exit((int) (intptr_t) client_data);
371 DieFromToolTalkError(Widget parent, char *errfmt, Tt_status status)
374 Widget dialog, dialogShell;
375 char *errmsg, *statmsg, *title;
376 XmString xms_errmsg, xms_ok, xms_title;
379 if (! tt_is_err(status)) return;
381 statmsg = tt_status_message(status);
382 errmsg = XtMalloc(strlen(errfmt) + strlen(statmsg) + 2);
383 sprintf(errmsg, errfmt, statmsg);
385 xms_ok = GETXMSTR(8,6, "OK");
386 xms_errmsg = XmStringCreateLocalized(errmsg);
387 xms_title = GETXMSTR(8,2, "Icon Editor - Error");
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++;
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));
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
405 dialogShell = XtParent(dialog);
407 XtSetArg(args[n], XmNmwmDecorations, MWM_DECOR_ALL | MWM_DECOR_MENU); n++;
408 XtSetValues(dialogShell, args, n);
409 XtManageChild(dialog);
410 XtRealizeWidget(dialogShell);
412 _DtSimpleError(CLASS_NAME, DtFatalError, NULL, errmsg);
415 XmStringFree(xms_ok);
416 XmStringFree(xms_errmsg);
417 XmStringFree(xms_title);
420 XtAppProcessEvent(XtWidgetToApplicationContext(dialog), XtIMAll);
424 Tt_message ProcessToolTalkMediaMessage( Tt_message msg,
428 unsigned char* contents,
433 int mark = tt_mark();
435 int tt_tmpMaskfile_fd = -1;
436 char mask_file[MAX_FNAME];
440 if (tt_message_status(msg) == TT_WRN_START_MESSAGE) tt_message_reply(msg);
446 * At this time, we don't handle composing new icons.
447 * Fail any such requests.
449 tt_message_fail(msg);
453 * At this time, we don't handle displaying icons
454 * without editing them.
455 * Fail any such requests.
457 tt_message_fail(msg);
462 * Undeclare the ptype so that this process will
463 * not service any more TT requests.
466 tt_ptype_undeclare(dticon_ptype);
469 if (tt_message_status(msg) != TT_WRN_START_MESSAGE)
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
478 tt_message_reject(msg);
480 else if (edit_notifier(NULL, msg, 0))
482 strcpy( msgID, tt_message_arg_val(msg, 1) );
487 * Icon data is in a file
489 strcpy(start_file, file);
494 * Icon data is in a buffer -- write it
501 if (tt_message_arg_bval(msg, 0,
502 &buf, &blen) != TT_OK)
504 tt_message_fail(msg);
505 edit_notifier(NULL, 0, 1);
509 (void) tmpnam(start_file);
510 if( (buf) && (!strncmp((char *)buf, "/* XPM */", 9)) )
515 O_CREAT | O_WRONLY | O_NDELAY,
517 if (tt_tmpfile_fd && (wlen =
521 (void) close(tt_tmpfile_fd);
522 param_flag[AUTO_FILE] = True;
523 argsNeedProcessed = True;
526 tt_message_fail(msg);
527 edit_notifier(NULL, 0, 1);
533 /* assume two buffers.... */
534 tmp = strchr((char *)buf, ';');
536 tmplen=blen - strlen(tmp);
538 /* read XBM file first*/
539 /* Grab the first buffer. */
542 O_CREAT | O_WRONLY | O_NDELAY,
545 if (tt_tmpfile_fd && (wlen =
547 buf, tmplen)) == tmplen)
549 (void) close(tt_tmpfile_fd);
550 param_flag[AUTO_FILE] = True;
551 argsNeedProcessed = True;
555 tt_message_fail(msg);
556 edit_notifier(NULL, 0, 1);
559 /* Try to find the second buffer. */
561 if(tmp) tmp1=strchr(tmp, ';');
566 /* construct the name of the mask file */
567 strcpy(mask_file, start_file);
568 strcat(mask_file, "_m\0");
571 O_CREAT | O_WRONLY | O_NDELAY,
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))
578 (void) close(tt_tmpMaskfile_fd);
579 param_flag[AUTO_FILE] = True;
580 argsNeedProcessed = True;
583 tt_message_fail(msg);
584 edit_notifier(NULL, 0, 1);
587 } /* else XBM Format */
595 return (Tt_message) 0;
599 edit_notifier(char* fname, Tt_message msg, int clear)
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.
608 if (local_msg != (Tt_message) 0) {
609 tt_message_reply(local_msg);
610 tt_message_destroy(local_msg);
612 local_msg = (Tt_message) 0;
620 * Not currently used, DELETE THIS COMMENT if it
624 if (local_msg != (Tt_message) 0) {
626 * Set the filename arg to the new, passed-in
627 * file name, and reply to the message.
629 tt_message_arg_val_set(local_msg, 0, fname);
630 tt_message_reply(local_msg);
631 local_msg = (Tt_message) 0;
635 else if (!fname && msg) {
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.
641 if (local_msg != (Tt_message) 0) {
642 tt_message_reject(msg);
652 * The caller is confused.
654 tt_message_reject(msg);
672 struct stat statbuf; /* Information on a file. */
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");
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)
692 /* didn't read whole file! */
693 printf("dtcreate: Only read %d of %d bytes of icon file!\n", rlen, len);
699 /* Handle the XBM format */
700 if( (fileFormat != FORMAT_XPM) && (stat(dummy, &statbuf) == 0) )
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)
709 /* didn't read whole file! */
711 "dtcreate: Only read %d of %d bytes of icon file!\n",
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';
727 /* No mask/bm just pass the pm file */
728 buffer = XtMalloc(len + 1);
729 strcpy(buffer, Fbuffer);
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);
737 ttstat = tt_message_send(msg);
738 tt_message_destroy(msg);
746 Tt_message ProcessToolTalkMessage(Tt_message msg,
750 int mark = tt_mark();
751 char* op = tt_message_op(msg);
753 if (!strcmp(op, "Quit")) {
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.
760 tt_message_fail(msg);
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!).
773 tt_message_reject(msg);
777 return (Tt_message) 0;
783 /******************************************************************************
784 NAME: handle_dialog_child( wgt, manage_func )
786 INPUT: Widget wgt - the dialogShellWidget
787 void (*manage_func)() - either XtManageChild
790 RETURN: int - NO_ERROR if successfull
793 DESCRIPTION: Handles the popping up or popping down of dialog shells
794 by managing or unmanaging their children.
796 CREATION: Visual Edge Software Sept 19/91
797 -----------------------------------------------------------------------------*/
798 static int handle_dialog_child( Widget wgt, void (*manage_func)() )
801 XtArgVal num_children;
805 XmNnumChildren, &num_children,
806 XmNchildren, &children,
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.
814 for (i = 0; i < (int)num_children; i++)
816 if ( XtIsSubclass( children[i], rectObjClass ) )
818 (*manage_func)(children[i]);
826 /******************************************************************************
827 NAME: PopupInterface( wgt, grab_flag )
829 INPUT: Widget wgt - Widget to popup
830 XtGrabKind grab_flag - grab flag
832 RETURN: int ERROR or NO_ERROR
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
838 The grab_flag could be any of:
840 nonexclusive_grab (XtGrabNonexclusive)
841 exclusive_grab (XtGrabExclusive)
843 CREATION: Visual Edge Software April 6 1991
844 -----------------------------------------------------------------------------*/
845 int PopupInterface( Widget wgt, XtGrabKind grab_flag )
848 if ( XtIsSubclass( wgt, xmDialogShellWidgetClass ) )
850 if ( handle_dialog_child( wgt, XtManageChild ) == ERROR )
851 XtPopup( wgt, grab_flag );
855 XtPopup( wgt, grab_flag );