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: process.c /main/7 1999/08/16 11:03:31 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 /******************************************************************************
34 ** Description: X11-based multi-color icon editor
36 ** File: process.c, which contains the following subroutines or
44 ** Process_Query_Cancel()
47 ** Process_Size_Cancel()
48 ** Process_StdErr_OK()
55 ** Process_AddHotspot()
56 ** Process_DeleteHotspot()
58 ** Process_RotateLeft()
59 ** Process_RotateRight()
62 ** Process_GridState()
63 ** Process_DropCheckOp()
69 ******************************************************************************
71 ** Copyright Hewlett-Packard Company, 1990, 1991, 1992.
72 ** All rights are reserved. Copying or reproduction of this program,
73 ** except for archival purposes, is prohibited without prior written
74 ** consent of Hewlett-Packard Company.
76 ** Hewlett-Packard makes no representations about the suitibility of this
77 ** software for any purpose. It is provided "as is" without express or
80 *****************************************************************************
85 #include "externals.h"
91 #include <Dt/HelpDialog.h>
96 extern void ReplyToMessage( );
97 extern Tt_message replyMsg;
100 static void Do_DropCheckOp(DtDndTransferCallback);
101 static void Do_DropOp(void);
103 extern Widget optionsMenu_grid;
104 Widget editMenu_paste_pb;
105 Widget editMenu_cut_pb;
106 Widget editMenu_copy_pb;
107 Widget editMenu_rotate_pb;
108 Widget editMenu_flip_pb;
109 Widget editMenu_scale_pb;
110 Widget editMenu_undo_pb;
111 extern Widget newWidthText, newHeightText;
113 extern GC scratch_gc;
116 Boolean Write_File( char * );
117 Boolean Read_File( char * );
119 extern void Process_SaveAs(void);
120 extern void Eval_NewSize(int, int);
121 extern void Process_Copy(XImage **, XImage **);
122 extern void Process_Resize(void);
124 /*-----------------------------------------------------------*/
125 /* Insert application global declarations here */
126 /*-----------------------------------------------------------*/
127 static char undo_file[MAX_FNAME]; /* save the file name after new */
128 char dropFileName[MAX_FNAME];
129 int SaveMeNot = TRUE; /* used to flag a save as for existing file */
130 int SavedOnce = False;
131 int NewFlag = False; /* use for undo after new */
133 /***************************************************************************
135 * Routine: Process_New *
137 * Purpose: Process the selection of the NEW button in the 'File' *
138 * pulldown menu. If the 'Dirty' flag is set, changes have *
139 * been made to the drawing tablet since the last save, which *
140 * would be lost by quitting. Notify the user of this and *
141 * allow them the chance to change their minds. If they do *
142 * not, pop-up the NewIconDialog for the user to select new *
143 * dimensions (if desired) for the new icon. *
145 ***************************************************************************/
151 DoQueryDialog( GETSTR(16,16, "The current icon has not been saved.\n\nYour changes will be lost.") );
157 /***************************************************************************
159 * Routine: Process_Open *
161 * Purpose: Process the selection of the OPEN button in the 'File' *
162 * pulldown menu. If the 'Dirty' flag is set, changes have *
163 * been made to the drawing tablet since the last save, which *
164 * would be lost by quitting. Notify the user of this and *
165 * allow them the chance to change their minds. If they do *
166 * not, pop-up the FileSelectionDialog for the user to select *
167 * the new file to be loaded. *
169 ***************************************************************************/
175 fileIOMode = FILE_READ;
177 DoQueryDialog( GETSTR(16,16, "The current icon has not been saved.\nYour changes will be lost.") );
180 XtManageChild(fileIODialog);
181 SetFileIODialogInfo();
186 /***************************************************************************
188 * Routine: Process_Save *
190 * Purpose: Process the selection of the SAVE button in the 'File' *
191 * pulldown menu. This automatically saves the current icon *
192 * to the same file it was loaded from, or saved to the last *
193 * time. If this file was created 'from scratch' and no *
194 * previous save operation has taken place, selecting this *
195 * operation behaves the same way that the SAVE_AS operation *
198 ***************************************************************************/
203 static char *untitledStr = NULL;
204 static char newName[MAX_FNAME];
210 fileIOMode = FILE_WRITE;
212 untitledStr = GETSTR(2,20, "UNTITLED");
213 tmp1= strrchr(last_fname, '/');
216 tmp2 = strchr(tmp1, c);
217 strcpy(newName, tmp2);
219 if (strncmp(newName, untitledStr, 8) == 0 || last_fname[0] == NULL) Process_SaveAs();
222 if (SavedOnce == True)
224 if (!Write_File(last_fname))
225 DoErrorDialog( GETSTR(16,4, "Unable to write data to file") );
235 /***************************************************************************
237 * Routine: Process_SaveAs *
239 * Purpose: Process the selection of the SAVE_AS button in the 'File' *
240 * pulldown menu. This pops-up the FileSelectionDialog which *
241 * prompts the user to select the file in which to save the *
244 ***************************************************************************/
247 Process_SaveAs( void )
249 DialogFlag = SAVE_AS;
250 fileIOMode = FILE_WRITE;
251 XtManageChild(fileIODialog);
252 SetFileIODialogInfo();
256 /***************************************************************************
258 * Routine: Process_Quit *
260 * Purpose: Process the selection of the QUIT button in the 'File' *
261 * pulldown menu. If the 'Dirty' flag is set, changes have *
262 * been made to the drawing tablet since the last save, which *
263 * would be lost by quitting. Notify the user of this and *
264 * allow them the chance to change their minds. *
266 ***************************************************************************/
272 extern int tt_tmpfile_fd;
276 DoQueryDialog( GETSTR(16,16, "The current icon has not been saved.\nYour changes will be lost.") );
279 edit_notifier(NULL, 0, 1);
280 ttdt_session_quit( 0, 0, 1 );
281 ttdt_close( 0, 0, 1 );
282 tt_release( ttMark );
283 if (tt_tmpfile_fd != -1) {
285 if (fileFormat != FORMAT_XPM ) {
294 /*****************************************************************************/
297 Process_Query_OK( void )
300 extern int tt_tmpfile_fd;
302 switch (DialogFlag) {
305 edit_notifier(NULL, 0, 1);
306 ttdt_session_quit( 0, 0, 1 );
307 ttdt_close( 0, 0, 1 );
308 tt_release( ttMark );
309 if (tt_tmpfile_fd != -1) {
311 if (fileFormat != FORMAT_XPM ) {
317 case NEW : Process_Resize();
320 case OPEN : XtManageChild(fileIODialog);
321 SetFileIODialogInfo();
323 case SAVE_AS : SaveMeNot = False;
324 Do_FileIO(NULL, NULL, NULL);
326 case GRAB : Do_GrabOp();
328 case DROP : Do_DropOp();
335 Process_Query_Cancel( void )
341 Process_Size_OK( void )
343 char *widthStr, *heightStr;
344 int new_width, new_height;
346 XtUnmanageChild(newIconDialog);
347 widthStr = XmTextFieldGetString(newWidthText);
348 heightStr = XmTextFieldGetString(newHeightText);
349 new_width = atoi(widthStr);
350 new_height = atoi(heightStr);
351 Eval_NewSize(new_width, new_height);
360 char old_width[10], old_height[10];
363 if ((width < 1) || (width > xrdb.maxIconWidth) ||
364 (height < 1) || (height > xrdb.maxIconHeight)) {
365 sprintf(old_width, "%d", icon_width);
366 XmTextFieldSetString(newWidthText, old_width);
367 sprintf(old_height, "%d", icon_height);
368 XmTextFieldSetString(newHeightText, old_height);
369 DoErrorDialog(GETSTR(16,10,"Invalid width and/or\nheight specified"));
373 if (DialogFlag == NEW)
378 Backup_Icons(); /* for undo */
379 Init_Icons(width, height, flag);
385 Process_Size_Cancel( void )
388 XtUnmanageChild(newIconDialog);
392 Process_StdErr_OK( void )
395 XtUnmanageChild(stdErrDialog);
399 /***************************************************************************
401 * Routine: Process_Undo *
403 * Purpose: Process the selection of the 'Undo' button in the 'Edit' *
404 * pulldown menu. If no previous icon state is available, *
405 * notify the user via a pop-up error dialog. Otherwise, *
406 * reverse the Backup_Icon() function behavior, update the *
407 * tablet to reflect the change, and set the UndoFlag to *
408 * False (indicating that no further undo ops. are possible). *
410 ***************************************************************************/
416 if ((icon_width != backup_width) || (icon_height != backup_height))
417 Init_Icons(backup_width, backup_height, DO_NOT_SAVE);
418 XCopyArea(dpy, prev_color_icon, color_icon,
419 Color_gc, 0, 0, icon_width, icon_height, 0, 0);
420 XCopyArea(dpy, prev_mono_icon, mono_icon,
421 Mono_gc, 0, 0, icon_width, icon_height, 0, 0);
422 if (XtWindow(iconImage))
423 XCopyArea(dpy, color_icon, XtWindow(iconImage), Color_gc,
424 0, 0, icon_width, icon_height, 0, 0);
425 if (XtWindow(monoImage))
426 XCopyArea(dpy, mono_icon, XtWindow(monoImage), Mono_gc,
427 0, 0, icon_width, icon_height, 0, 0);
428 Repaint_Exposed_Tablet();
431 XtSetSensitive( editMenu_undo_pb, False);
433 if ( NewFlag == TRUE ){
435 strcpy(last_fname, undo_file);
436 last_fname[strlen(last_fname)] = '\0';
440 DoErrorDialog( GETSTR(16,8,"There is no previous\nimage available") );
446 Process_Copy(&CutCopy, &CutCopy_mono);
449 XSetForeground(dpy, scratch_gc, Transparent);
450 XFillRectangle(dpy, color_icon, scratch_gc, select_box.x, select_box.y,
451 select_box.width, select_box.height);
452 XFillRectangle(dpy, mono_icon, scratch_gc, select_box.x, select_box.y,
453 select_box.width, select_box.height);
454 XFillRectangle(dpy, XtWindow(iconImage), scratch_gc,
455 select_box.x, select_box.y, select_box.width, select_box.height);
456 XFillRectangle(dpy, XtWindow(monoImage), scratch_gc,
457 select_box.x, select_box.y, select_box.width, select_box.height);
458 Transfer_Back_Image(select_box.x, select_box.y,
459 (select_box.x+select_box.width),
460 (select_box.y+select_box.height), FILL);
461 XtSetSensitive( editMenu_paste_pb, True);
471 *img = XGetImage(dpy, color_icon, select_box.x, select_box.y,
472 select_box.width, select_box.height, AllPlanes, format);
473 *img_mono = XGetImage(dpy, mono_icon, select_box.x, select_box.y,
474 select_box.width, select_box.height, AllPlanes, format);
475 XtSetSensitive( editMenu_paste_pb, True);
478 DoErrorDialog( GETSTR(16,12, "No area has been selected") );
482 Process_Paste( void )
486 Backup_G_Op = GraphicsOp;
487 GraphicsOp = S_PASTE;
489 /* grayout unusable stuff */
490 XtSetSensitive( editMenu_cut_pb, False);
491 XtSetSensitive( editMenu_copy_pb, False);
492 XtSetSensitive(editMenu_rotate_pb, False);
493 XtSetSensitive(editMenu_flip_pb, False);
494 XtSetSensitive(editMenu_scale_pb, False);
498 DoErrorDialog(GETSTR(16,14, "No area was previously\ncut or copied"));
502 Process_Scale( void )
506 Backup_G_Op = GraphicsOp;
507 GraphicsOp = S_SCALE_1;
511 DoErrorDialog( GETSTR(16,12, "No area has been selected") );
515 Process_Resize( void )
518 char old_width[10], old_height[10];
519 static char *untitledStr = NULL;
521 if ( DialogFlag == NEW ) {
522 strcpy(undo_file, last_fname);
523 last_fname[0] = '\0';
525 Backup_Icons(); /* for undo */
527 Init_Icons(icon_width, icon_height, flag);
529 untitledStr = GETSTR(2,20, "UNTITLED");
530 strcpy(last_fname, untitledStr);
531 strcat(last_fname, ".m.pm");
532 last_fname[strlen(last_fname)] = '\0';
534 Repaint_Exposed_Tablet();
539 sprintf(old_width, "%d", icon_width);
540 XmTextFieldSetString(newWidthText, old_width);
541 sprintf(old_height, "%d", icon_height);
542 XmTextFieldSetString(newHeightText, old_height);
543 XtManageChild(newIconDialog);
544 XmProcessTraversal(newWidthText, XmTRAVERSE_CURRENT);
545 XmTextFieldSetSelection(newWidthText, 0, 3, CurrentTime); }
548 /***************************************************************************
550 * Routine: Process_Clear *
552 * Purpose: Process the selection of the 'Clear' button in the 'Edit' *
553 * pulldown menu. This should be undo'able, just like a normal *
554 * graphics ops., so back up the icons before wiping out their *
555 * contents. After painting them to transparent, copy the *
556 * contents of the color icon back onto the tablet. *
558 ***************************************************************************/
561 Process_Clear( void )
564 XSetForeground(dpy, scratch_gc, Transparent);
565 XFillRectangle(dpy, color_icon, scratch_gc, 0, 0, icon_width, icon_height);
566 XFillRectangle(dpy, mono_icon, scratch_gc, 0, 0, icon_width, icon_height);
567 if (XtWindow(iconImage))
568 XCopyArea(dpy, color_icon, XtWindow(iconImage), scratch_gc,
569 0, 0, icon_width, icon_height, 0, 0);
570 if (XtWindow(monoImage))
571 XCopyArea(dpy, mono_icon, XtWindow(monoImage), scratch_gc,
572 0, 0, icon_width, icon_height, 0, 0);
573 Repaint_Exposed_Tablet();
576 /***************************************************************************
578 * Routine: Process_GrabImage *
580 * Purpose: You're a computer programmer. *YOU* figure out what it does.*
582 ***************************************************************************/
585 Process_GrabImage( void )
589 DoQueryDialog( GETSTR(16,16, "The current icon has not been saved.\nYour changes will be lost.") );
595 /***************************************************************************
597 * Routine: Process_AddHotspot *
599 * Purpose: Process the selection of the 'Add Hotspot' button in the *
600 * 'Edit' pulldown menu. Save the current graphics ops. flag *
601 * and set the flag to S_HOTSPOT. The actual [x,y] location *
602 * selection for the hotspot will occur in the event processing *
603 * loop for the tablet. *
605 ***************************************************************************/
608 Process_AddHotspot( void )
610 Backup_G_Op = GraphicsOp;
611 GraphicsOp = S_HOTSPOT;
615 /***************************************************************************
617 * Routine: Process_DeleteHotspot *
619 * Purpose: Process the selection of the 'Delete Hotspot' button in the *
620 * 'Edit' pulldown menu. Set the X and Y hot values to -1, set *
621 * the hotSpot flag to FALSE, and repaint the exposed portion *
622 * of the tablet (to remove the visible hotspot indicator). *
624 ***************************************************************************/
627 Process_DeleteHotspot( void )
632 Repaint_Exposed_Tablet();
636 Process_RotateLeft( void )
638 XImage *color_img, *mono_img;
640 Process_Copy(&color_img, &mono_img);
641 /* Turn off Paste since no area is available to Paste */
642 XtSetSensitive( editMenu_paste_pb, False);
645 Rotate = XGetImage(dpy, root, 0, 0, color_img->height, color_img->width,
647 Rotate_mono = XGetImage(dpy, root, 0, 0, mono_img->height, mono_img->width,
649 Block_Rotate(color_img, Rotate, ROTATE_L);
650 Block_Rotate(mono_img, Rotate_mono, ROTATE_L);
651 XDestroyImage(color_img);
652 XDestroyImage(mono_img);
653 Backup_G_Op = GraphicsOp;
654 GraphicsOp = S_ROTATE;
660 Process_RotateRight( void )
662 XImage *color_img, *mono_img;
664 Process_Copy(&color_img, &mono_img);
665 /* Turn off Paste since no area is available to Paste */
666 XtSetSensitive( editMenu_paste_pb, False);
669 Rotate = XGetImage(dpy, root, 0, 0, color_img->height, color_img->width,
671 Rotate_mono = XGetImage(dpy, root, 0, 0, mono_img->height, mono_img->width,
673 Block_Rotate(color_img, Rotate, ROTATE_R);
674 Block_Rotate(mono_img, Rotate_mono, ROTATE_R);
675 XDestroyImage(color_img);
676 XDestroyImage(mono_img);
677 Backup_G_Op = GraphicsOp;
678 GraphicsOp = S_ROTATE;
684 /***************************************************************************
686 * Routine: Process_FlipV *
688 * Purpose: Process the selection of the 'Vertical' button in the 'Edit' *
689 * ->'Flip Area' pulldown menu. This should be undo'able, *
690 * just like a normal graphics ops., so back up the icons *
691 * first, then call Mirror_Image(), with the flag VERTICAL. *
692 * If no area is SELECTED, map the error dialog with the *
693 * appropriate message. *
695 ***************************************************************************/
698 Process_FlipV( void )
702 Mirror_Image(VERTICAL);
705 DoErrorDialog( GETSTR(16,12, "No area has been selected") );
709 /***************************************************************************
711 * Routine: Process_FlipH *
713 * Purpose: Process the selection of the 'Horizontal' button in the *
714 * 'Edit'->'Flip Area' pulldown menu. This should be undo'able,*
715 * just like a normal graphics ops., so back up the icons *
716 * first, then call Mirror_Image(), with the flag HORIZONTAL. *
717 * If no area is SELECTED, map the error dialog with the *
718 * appropriate message. *
720 ***************************************************************************/
723 Process_FlipH( void )
727 Mirror_Image(HORIZONTAL);
730 DoErrorDialog( GETSTR(16,12, "No area has been selected") );
734 /***************************************************************************
736 * Routine: Process_GridState *
738 * Purpose: Process the selection of the 'Visible Grid' button in the *
739 * 'Options' pulldown menu. Set the GridEnabled internal flag *
740 * to reflect the current state of the toggle. If the value is *
741 * different from the previous value, repaint the tablet. *
743 ***************************************************************************/
746 Process_GridState( void )
753 XtSetArg(args[i], XmNset, &new_val); i++;
754 XtGetValues(optionsMenu_grid, args, i);
757 stat_out("Toggling tablet grid ");
759 case True : stat_out("ON\n");
761 case False : stat_out("OFF\n");
766 if (new_val != GridEnabled) {
767 GridEnabled = new_val;
768 Repaint_Exposed_Tablet();
771 /***************************************************************************
773 * Routine: ConvertDropName *
775 * Purpose: Convert the "object" received from bms to a full path name *
776 * note: I am making BIG assumptions about the format of the *
777 * file I am getting from dtfile. "<host> - <path>" *
778 * WARNING: I have used an Xe function directly (XeIsLocalHostP), rather *
779 * than include Dt/Connect.h, which was causing bad things to *
780 * happen at build time, probably because dticon is not ansi- *
781 * clean (it tried to get c++ version of /usr/include/stdlib.h?) *
782 * It's simply too late to clean up the ansi... (the bell tolls) *
784 ***************************************************************************/
786 ConvertDropName( char *objects)
795 tmp = strchr(objects,' ');
796 if (tmp==NULL) /* shouldn't happen */
797 return (strdup(strchr(objects, '/')));
799 /* check if same host */
801 if ((Boolean)XeIsLocalHostP(host))
804 return (strdup(strchr(objects, '/')));
807 /* different host... get full path name */
808 path = tmp+3; /* skip past the " - " */
810 /* Convert to a valid name on the local host. */
811 netfile = tt_host_file_netfile(host, path);
812 fullName = tt_netfile_file(netfile);
815 tmp[0] = ' '; /* put back the " " after host name */
820 /***************************************************************************
822 * Routine: Process_DropCheckOp *
824 * Purpose: Validate the drag-n-drop operation that just occured on the *
827 ***************************************************************************/
832 XtPointer client_data,
835 DtDndTransferCallback transferInfo = (DtDndTransferCallback) call_data;
837 /* save name in global array for later (Do_DropOp function) */
839 * REMIND: Need to address case of multiple file names - here and
840 * elsewhere in the code. This continues with the assumption
841 * that there is only one file name transfered.
843 if (transferInfo->dropData->numItems > 0)
845 strncpy (dropFileName, transferInfo->dropData->data.files[0],
849 dropFileName[0] = '\0';
851 Do_DropCheckOp(transferInfo);
855 stat_out(" file-name = %s\n", dropFileName);
861 extern Widget formatMenu_xpm_tb, formatMenu_xbm_tb;
862 extern int successFormat, x_hot, y_hot;
863 extern unsigned int width_ret, height_ret;
865 /***************************************************************************
867 * Routine: Do_DropCheckOp *
869 * Purpose: Verify the drag-n-drop operation that just occured on the *
872 ***************************************************************************/
876 DtDndTransferCallback transferInfo)
881 stat_out(" Doing DROP OPERATION :\n");
882 stat_out(" name is = %s\n", dropFileName);
886 if (dropFileName[0] != '\0')
888 if (!Read_File(dropFileName))
890 DoErrorDialog( GETSTR(16,2,
891 "The file cannot be accessed\nor contains invalid data") );
892 transferInfo->status = DtDND_FAILURE;
896 transferInfo->status = DtDND_SUCCESS;
904 XtPointer client_data,
910 DoQueryDialog( GETSTR(16,16, "The current icon has not been saved.\n\nYour changes will be lost.") );
918 if (successFormat == FORMAT_XPM)
920 X_Hot = xpm_ReadAttribs.x_hotspot;
921 Y_Hot = xpm_ReadAttribs.y_hotspot;
922 Display_XPMFile(xpm_ReadAttribs.width, xpm_ReadAttribs.height);
924 else if (successFormat == FORMAT_XBM)
928 Display_XBMFile(width_ret, height_ret);
934 /***************************************************************************
936 * Routine: Do_Paste *
938 * Purpose: Paste the CutCopy image at the tablet location specified by *
939 * the [x,y] parameters in the call. *
941 ***************************************************************************/
948 XImage *color_img, *mono_img;
950 if (GraphicsOp == S_PASTE) {
952 mono_img = CutCopy_mono;
954 else if (GraphicsOp == S_ROTATE) {
956 mono_img = Rotate_mono;
960 mono_img = Scale_mono;
963 if (GraphicsOp == S_PASTE)
965 GraphicsOp = S_WAIT_RELEASE;
969 GraphicsOp = Backup_G_Op;
970 if (Backup_G_Op == SELECT)
971 Start_HotBox(CONTINUE);
975 XPutImage(dpy, color_icon, Color_gc, color_img, 0, 0, x, y,
976 color_img->width, color_img->height);
977 XPutImage(dpy, mono_icon, Mono_gc, mono_img, 0, 0, x, y,
978 mono_img->width, mono_img->height);
979 XCopyArea(dpy, color_icon, XtWindow(iconImage), Color_gc,
980 x, y, color_img->width, color_img->height, x, y);
981 XCopyArea(dpy, mono_icon, XtWindow(monoImage), Mono_gc,
982 x, y, mono_img->width, mono_img->height, x, y);
983 Transfer_Back_Image(x, y, x+color_img->width, y+color_img->height, FILL);