1 /* $TOG: process.c /main/7 1999/08/16 11:03:31 mgreess $ */
2 /********************************************************************
3 * (c) Copyright 1993, 1994 Hewlett-Packard Company
4 * (c) Copyright 1993, 1994 International Business Machines Corp.
5 * (c) Copyright 1993, 1994 Sun Microsystems, Inc.
6 * (c) Copyright 1993, 1994 Unix System Labs, Inc., a subsidiary of
8 **********************************************************************/
9 /******************************************************************************
12 ** Description: X11-based multi-color icon editor
14 ** File: process.c, which contains the following subroutines or
22 ** Process_Query_Cancel()
25 ** Process_Size_Cancel()
26 ** Process_StdErr_OK()
33 ** Process_AddHotspot()
34 ** Process_DeleteHotspot()
36 ** Process_RotateLeft()
37 ** Process_RotateRight()
40 ** Process_GridState()
41 ** Process_DropCheckOp()
47 ******************************************************************************
49 ** Copyright Hewlett-Packard Company, 1990, 1991, 1992.
50 ** All rights are reserved. Copying or reproduction of this program,
51 ** except for archival purposes, is prohibited without prior written
52 ** consent of Hewlett-Packard Company.
54 ** Hewlett-Packard makes no representations about the suitibility of this
55 ** software for any purpose. It is provided "as is" without express or
58 *****************************************************************************
63 #include "externals.h"
69 #include <Dt/HelpDialog.h>
74 extern void ReplyToMessage( );
75 extern Tt_message replyMsg;
78 static void Do_DropCheckOp(DtDndTransferCallback);
79 static void Do_DropOp(void);
81 extern Widget optionsMenu_grid;
82 Widget editMenu_paste_pb;
83 Widget editMenu_cut_pb;
84 Widget editMenu_copy_pb;
85 Widget editMenu_rotate_pb;
86 Widget editMenu_flip_pb;
87 Widget editMenu_scale_pb;
88 Widget editMenu_undo_pb;
89 extern Widget newWidthText, newHeightText;
94 Boolean Write_File( char * );
95 Boolean Read_File( char * );
97 extern void Process_SaveAs(void);
98 extern void Eval_NewSize(int, int);
99 extern void Process_Copy(XImage **, XImage **);
100 extern void Process_Resize(void);
102 /*-----------------------------------------------------------*/
103 /* Insert application global declarations here */
104 /*-----------------------------------------------------------*/
105 static char undo_file[MAX_FNAME]; /* save the file name after new */
106 char dropFileName[MAX_FNAME];
107 int SaveMeNot = TRUE; /* used to flag a save as for existing file */
108 int SavedOnce = False;
109 int NewFlag = False; /* use for undo after new */
111 /***************************************************************************
113 * Routine: Process_New *
115 * Purpose: Process the selection of the NEW button in the 'File' *
116 * pulldown menu. If the 'Dirty' flag is set, changes have *
117 * been made to the drawing tablet since the last save, which *
118 * would be lost by quitting. Notify the user of this and *
119 * allow them the chance to change their minds. If they do *
120 * not, pop-up the NewIconDialog for the user to select new *
121 * dimensions (if desired) for the new icon. *
123 ***************************************************************************/
129 DoQueryDialog( GETSTR(16,16, "The current icon has not been saved.\n\nYour changes will be lost.") );
135 /***************************************************************************
137 * Routine: Process_Open *
139 * Purpose: Process the selection of the OPEN button in the 'File' *
140 * pulldown menu. If the 'Dirty' flag is set, changes have *
141 * been made to the drawing tablet since the last save, which *
142 * would be lost by quitting. Notify the user of this and *
143 * allow them the chance to change their minds. If they do *
144 * not, pop-up the FileSelectionDialog for the user to select *
145 * the new file to be loaded. *
147 ***************************************************************************/
153 fileIOMode = FILE_READ;
155 DoQueryDialog( GETSTR(16,16, "The current icon has not been saved.\nYour changes will be lost.") );
158 XtManageChild(fileIODialog);
159 SetFileIODialogInfo();
164 /***************************************************************************
166 * Routine: Process_Save *
168 * Purpose: Process the selection of the SAVE button in the 'File' *
169 * pulldown menu. This automatically saves the current icon *
170 * to the same file it was loaded from, or saved to the last *
171 * time. If this file was created 'from scratch' and no *
172 * previous save operation has taken place, selecting this *
173 * operation behaves the same way that the SAVE_AS operation *
176 ***************************************************************************/
181 static char *untitledStr = NULL;
182 static char newName[MAX_FNAME];
188 fileIOMode = FILE_WRITE;
190 untitledStr = GETSTR(2,20, "UNTITLED");
191 tmp1= strrchr(last_fname, '/');
194 tmp2 = strchr(tmp1, c);
195 strcpy(newName, tmp2);
197 if (strncmp(newName, untitledStr, 8) == 0 || last_fname[0] == NULL) Process_SaveAs();
200 if (SavedOnce == True)
202 if (!Write_File(last_fname))
203 DoErrorDialog( GETSTR(16,4, "Unable to write data to file") );
213 /***************************************************************************
215 * Routine: Process_SaveAs *
217 * Purpose: Process the selection of the SAVE_AS button in the 'File' *
218 * pulldown menu. This pops-up the FileSelectionDialog which *
219 * prompts the user to select the file in which to save the *
222 ***************************************************************************/
225 Process_SaveAs( void )
227 DialogFlag = SAVE_AS;
228 fileIOMode = FILE_WRITE;
229 XtManageChild(fileIODialog);
230 SetFileIODialogInfo();
234 /***************************************************************************
236 * Routine: Process_Quit *
238 * Purpose: Process the selection of the QUIT button in the 'File' *
239 * pulldown menu. If the 'Dirty' flag is set, changes have *
240 * been made to the drawing tablet since the last save, which *
241 * would be lost by quitting. Notify the user of this and *
242 * allow them the chance to change their minds. *
244 ***************************************************************************/
250 extern int tt_tmpfile_fd;
254 DoQueryDialog( GETSTR(16,16, "The current icon has not been saved.\nYour changes will be lost.") );
257 edit_notifier(NULL, 0, 1);
258 ttdt_session_quit( 0, 0, 1 );
259 ttdt_close( 0, 0, 1 );
260 tt_release( ttMark );
261 if (tt_tmpfile_fd != -1) {
263 if (fileFormat != FORMAT_XPM ) {
272 /*****************************************************************************/
275 Process_Query_OK( void )
278 extern int tt_tmpfile_fd;
280 switch (DialogFlag) {
283 edit_notifier(NULL, 0, 1);
284 ttdt_session_quit( 0, 0, 1 );
285 ttdt_close( 0, 0, 1 );
286 tt_release( ttMark );
287 if (tt_tmpfile_fd != -1) {
289 if (fileFormat != FORMAT_XPM ) {
295 case NEW : Process_Resize();
298 case OPEN : XtManageChild(fileIODialog);
299 SetFileIODialogInfo();
301 case SAVE_AS : SaveMeNot = False;
302 Do_FileIO(NULL, NULL, NULL);
304 case GRAB : Do_GrabOp();
306 case DROP : Do_DropOp();
313 Process_Query_Cancel( void )
319 Process_Size_OK( void )
321 char *widthStr, *heightStr;
322 int new_width, new_height;
324 XtUnmanageChild(newIconDialog);
325 widthStr = XmTextFieldGetString(newWidthText);
326 heightStr = XmTextFieldGetString(newHeightText);
327 new_width = atoi(widthStr);
328 new_height = atoi(heightStr);
329 Eval_NewSize(new_width, new_height);
338 char old_width[10], old_height[10];
341 if ((width < 1) || (width > xrdb.maxIconWidth) ||
342 (height < 1) || (height > xrdb.maxIconHeight)) {
343 sprintf(old_width, "%d", icon_width);
344 XmTextFieldSetString(newWidthText, old_width);
345 sprintf(old_height, "%d", icon_height);
346 XmTextFieldSetString(newHeightText, old_height);
347 DoErrorDialog(GETSTR(16,10,"Invalid width and/or\nheight specified"));
351 if (DialogFlag == NEW)
356 Backup_Icons(); /* for undo */
357 Init_Icons(width, height, flag);
363 Process_Size_Cancel( void )
366 XtUnmanageChild(newIconDialog);
370 Process_StdErr_OK( void )
373 XtUnmanageChild(stdErrDialog);
377 /***************************************************************************
379 * Routine: Process_Undo *
381 * Purpose: Process the selection of the 'Undo' button in the 'Edit' *
382 * pulldown menu. If no previous icon state is available, *
383 * notify the user via a pop-up error dialog. Otherwise, *
384 * reverse the Backup_Icon() function behavior, update the *
385 * tablet to reflect the change, and set the UndoFlag to *
386 * False (indicating that no further undo ops. are possible). *
388 ***************************************************************************/
394 if ((icon_width != backup_width) || (icon_height != backup_height))
395 Init_Icons(backup_width, backup_height, DO_NOT_SAVE);
396 XCopyArea(dpy, prev_color_icon, color_icon,
397 Color_gc, 0, 0, icon_width, icon_height, 0, 0);
398 XCopyArea(dpy, prev_mono_icon, mono_icon,
399 Mono_gc, 0, 0, icon_width, icon_height, 0, 0);
400 if (XtWindow(iconImage))
401 XCopyArea(dpy, color_icon, XtWindow(iconImage), Color_gc,
402 0, 0, icon_width, icon_height, 0, 0);
403 if (XtWindow(monoImage))
404 XCopyArea(dpy, mono_icon, XtWindow(monoImage), Mono_gc,
405 0, 0, icon_width, icon_height, 0, 0);
406 Repaint_Exposed_Tablet();
409 XtSetSensitive( editMenu_undo_pb, False);
411 if ( NewFlag == TRUE ){
413 strcpy(last_fname, undo_file);
414 last_fname[strlen(last_fname)] = '\0';
418 DoErrorDialog( GETSTR(16,8,"There is no previous\nimage available") );
424 Process_Copy(&CutCopy, &CutCopy_mono);
427 XSetForeground(dpy, scratch_gc, Transparent);
428 XFillRectangle(dpy, color_icon, scratch_gc, select_box.x, select_box.y,
429 select_box.width, select_box.height);
430 XFillRectangle(dpy, mono_icon, scratch_gc, select_box.x, select_box.y,
431 select_box.width, select_box.height);
432 XFillRectangle(dpy, XtWindow(iconImage), scratch_gc,
433 select_box.x, select_box.y, select_box.width, select_box.height);
434 XFillRectangle(dpy, XtWindow(monoImage), scratch_gc,
435 select_box.x, select_box.y, select_box.width, select_box.height);
436 Transfer_Back_Image(select_box.x, select_box.y,
437 (select_box.x+select_box.width),
438 (select_box.y+select_box.height), FILL);
439 XtSetSensitive( editMenu_paste_pb, True);
449 *img = XGetImage(dpy, color_icon, select_box.x, select_box.y,
450 select_box.width, select_box.height, AllPlanes, format);
451 *img_mono = XGetImage(dpy, mono_icon, select_box.x, select_box.y,
452 select_box.width, select_box.height, AllPlanes, format);
453 XtSetSensitive( editMenu_paste_pb, True);
456 DoErrorDialog( GETSTR(16,12, "No area has been selected") );
460 Process_Paste( void )
464 Backup_G_Op = GraphicsOp;
465 GraphicsOp = S_PASTE;
467 /* grayout unusable stuff */
468 XtSetSensitive( editMenu_cut_pb, False);
469 XtSetSensitive( editMenu_copy_pb, False);
470 XtSetSensitive(editMenu_rotate_pb, False);
471 XtSetSensitive(editMenu_flip_pb, False);
472 XtSetSensitive(editMenu_scale_pb, False);
476 DoErrorDialog(GETSTR(16,14, "No area was previously\ncut or copied"));
480 Process_Scale( void )
484 Backup_G_Op = GraphicsOp;
485 GraphicsOp = S_SCALE_1;
489 DoErrorDialog( GETSTR(16,12, "No area has been selected") );
493 Process_Resize( void )
496 char old_width[10], old_height[10];
497 static char *untitledStr = NULL;
499 if ( DialogFlag == NEW ) {
500 strcpy(undo_file, last_fname);
501 last_fname[0] = '\0';
503 Backup_Icons(); /* for undo */
505 Init_Icons(icon_width, icon_height, flag);
507 untitledStr = GETSTR(2,20, "UNTITLED");
508 strcpy(last_fname, untitledStr);
509 strcat(last_fname, ".m.pm");
510 last_fname[strlen(last_fname)] = '\0';
512 Repaint_Exposed_Tablet();
517 sprintf(old_width, "%d", icon_width);
518 XmTextFieldSetString(newWidthText, old_width);
519 sprintf(old_height, "%d", icon_height);
520 XmTextFieldSetString(newHeightText, old_height);
521 XtManageChild(newIconDialog);
522 XmProcessTraversal(newWidthText, XmTRAVERSE_CURRENT);
523 XmTextFieldSetSelection(newWidthText, 0, 3, CurrentTime); }
526 /***************************************************************************
528 * Routine: Process_Clear *
530 * Purpose: Process the selection of the 'Clear' button in the 'Edit' *
531 * pulldown menu. This should be undo'able, just like a normal *
532 * graphics ops., so back up the icons before wiping out their *
533 * contents. After painting them to transparent, copy the *
534 * contents of the color icon back onto the tablet. *
536 ***************************************************************************/
539 Process_Clear( void )
542 XSetForeground(dpy, scratch_gc, Transparent);
543 XFillRectangle(dpy, color_icon, scratch_gc, 0, 0, icon_width, icon_height);
544 XFillRectangle(dpy, mono_icon, scratch_gc, 0, 0, icon_width, icon_height);
545 if (XtWindow(iconImage))
546 XCopyArea(dpy, color_icon, XtWindow(iconImage), scratch_gc,
547 0, 0, icon_width, icon_height, 0, 0);
548 if (XtWindow(monoImage))
549 XCopyArea(dpy, mono_icon, XtWindow(monoImage), scratch_gc,
550 0, 0, icon_width, icon_height, 0, 0);
551 Repaint_Exposed_Tablet();
554 /***************************************************************************
556 * Routine: Process_GrabImage *
558 * Purpose: You're a computer programmer. *YOU* figure out what it does.*
560 ***************************************************************************/
563 Process_GrabImage( void )
567 DoQueryDialog( GETSTR(16,16, "The current icon has not been saved.\nYour changes will be lost.") );
573 /***************************************************************************
575 * Routine: Process_AddHotspot *
577 * Purpose: Process the selection of the 'Add Hotspot' button in the *
578 * 'Edit' pulldown menu. Save the current graphics ops. flag *
579 * and set the flag to S_HOTSPOT. The actual [x,y] location *
580 * selection for the hotspot will occur in the event processing *
581 * loop for the tablet. *
583 ***************************************************************************/
586 Process_AddHotspot( void )
588 Backup_G_Op = GraphicsOp;
589 GraphicsOp = S_HOTSPOT;
593 /***************************************************************************
595 * Routine: Process_DeleteHotspot *
597 * Purpose: Process the selection of the 'Delete Hotspot' button in the *
598 * 'Edit' pulldown menu. Set the X and Y hot values to -1, set *
599 * the hotSpot flag to FALSE, and repaint the exposed portion *
600 * of the tablet (to remove the visible hotspot indicator). *
602 ***************************************************************************/
605 Process_DeleteHotspot( void )
610 Repaint_Exposed_Tablet();
614 Process_RotateLeft( void )
616 XImage *color_img, *mono_img;
618 Process_Copy(&color_img, &mono_img);
619 /* Turn off Paste since no area is available to Paste */
620 XtSetSensitive( editMenu_paste_pb, False);
623 Rotate = XGetImage(dpy, root, 0, 0, color_img->height, color_img->width,
625 Rotate_mono = XGetImage(dpy, root, 0, 0, mono_img->height, mono_img->width,
627 Block_Rotate(color_img, Rotate, ROTATE_L);
628 Block_Rotate(mono_img, Rotate_mono, ROTATE_L);
629 XDestroyImage(color_img);
630 XDestroyImage(mono_img);
631 Backup_G_Op = GraphicsOp;
632 GraphicsOp = S_ROTATE;
638 Process_RotateRight( void )
640 XImage *color_img, *mono_img;
642 Process_Copy(&color_img, &mono_img);
643 /* Turn off Paste since no area is available to Paste */
644 XtSetSensitive( editMenu_paste_pb, False);
647 Rotate = XGetImage(dpy, root, 0, 0, color_img->height, color_img->width,
649 Rotate_mono = XGetImage(dpy, root, 0, 0, mono_img->height, mono_img->width,
651 Block_Rotate(color_img, Rotate, ROTATE_R);
652 Block_Rotate(mono_img, Rotate_mono, ROTATE_R);
653 XDestroyImage(color_img);
654 XDestroyImage(mono_img);
655 Backup_G_Op = GraphicsOp;
656 GraphicsOp = S_ROTATE;
662 /***************************************************************************
664 * Routine: Process_FlipV *
666 * Purpose: Process the selection of the 'Vertical' button in the 'Edit' *
667 * ->'Flip Area' pulldown menu. This should be undo'able, *
668 * just like a normal graphics ops., so back up the icons *
669 * first, then call Mirror_Image(), with the flag VERTICAL. *
670 * If no area is SELECTED, map the error dialog with the *
671 * appropriate message. *
673 ***************************************************************************/
676 Process_FlipV( void )
680 Mirror_Image(VERTICAL);
683 DoErrorDialog( GETSTR(16,12, "No area has been selected") );
687 /***************************************************************************
689 * Routine: Process_FlipH *
691 * Purpose: Process the selection of the 'Horizontal' button in the *
692 * 'Edit'->'Flip Area' pulldown menu. This should be undo'able,*
693 * just like a normal graphics ops., so back up the icons *
694 * first, then call Mirror_Image(), with the flag HORIZONTAL. *
695 * If no area is SELECTED, map the error dialog with the *
696 * appropriate message. *
698 ***************************************************************************/
701 Process_FlipH( void )
705 Mirror_Image(HORIZONTAL);
708 DoErrorDialog( GETSTR(16,12, "No area has been selected") );
712 /***************************************************************************
714 * Routine: Process_GridState *
716 * Purpose: Process the selection of the 'Visible Grid' button in the *
717 * 'Options' pulldown menu. Set the GridEnabled internal flag *
718 * to reflect the current state of the toggle. If the value is *
719 * different from the previous value, repaint the tablet. *
721 ***************************************************************************/
724 Process_GridState( void )
731 XtSetArg(args[i], XmNset, &new_val); i++;
732 XtGetValues(optionsMenu_grid, args, i);
735 stat_out("Toggling tablet grid ");
737 case True : stat_out("ON\n");
739 case False : stat_out("OFF\n");
744 if (new_val != GridEnabled) {
745 GridEnabled = new_val;
746 Repaint_Exposed_Tablet();
749 /***************************************************************************
751 * Routine: ConvertDropName *
753 * Purpose: Convert the "object" received from bms to a full path name *
754 * note: I am making BIG assumptions about the format of the *
755 * file I am getting from dtfile. "<host> - <path>" *
756 * WARNING: I have used an Xe function directly (XeIsLocalHostP), rather *
757 * than include Dt/Connect.h, which was causing bad things to *
758 * happen at build time, probably because dticon is not ansi- *
759 * clean (it tried to get c++ version of /usr/include/stdlib.h?) *
760 * It's simply too late to clean up the ansi... (the bell tolls) *
762 ***************************************************************************/
764 ConvertDropName( char *objects)
773 tmp = strchr(objects,' ');
774 if (tmp==NULL) /* shouldn't happen */
775 return (strdup(strchr(objects, '/')));
777 /* check if same host */
779 if ((Boolean)XeIsLocalHostP(host))
782 return (strdup(strchr(objects, '/')));
785 /* different host... get full path name */
786 path = tmp+3; /* skip past the " - " */
788 /* Convert to a valid name on the local host. */
789 netfile = tt_host_file_netfile(host, path);
790 fullName = tt_netfile_file(netfile);
793 tmp[0] = ' '; /* put back the " " after host name */
798 /***************************************************************************
800 * Routine: Process_DropCheckOp *
802 * Purpose: Validate the drag-n-drop operation that just occured on the *
805 ***************************************************************************/
810 XtPointer client_data,
813 DtDndTransferCallback transferInfo = (DtDndTransferCallback) call_data;
815 /* save name in global array for later (Do_DropOp function) */
817 * REMIND: Need to address case of multiple file names - here and
818 * elsewhere in the code. This continues with the assumption
819 * that there is only one file name transfered.
821 if (transferInfo->dropData->numItems > 0)
823 strncpy (dropFileName, transferInfo->dropData->data.files[0],
827 dropFileName[0] = '\0';
829 Do_DropCheckOp(transferInfo);
833 stat_out(" file-name = %s\n", dropFileName);
839 extern Widget formatMenu_xpm_tb, formatMenu_xbm_tb;
840 extern int successFormat, x_hot, y_hot;
841 extern unsigned int width_ret, height_ret;
843 /***************************************************************************
845 * Routine: Do_DropCheckOp *
847 * Purpose: Verify the drag-n-drop operation that just occured on the *
850 ***************************************************************************/
854 DtDndTransferCallback transferInfo)
859 stat_out(" Doing DROP OPERATION :\n");
860 stat_out(" name is = %s\n", dropFileName);
864 if (dropFileName[0] != '\0')
866 if (!Read_File(dropFileName))
868 DoErrorDialog( GETSTR(16,2,
869 "The file cannot be accessed\nor contains invalid data") );
870 transferInfo->status = DtDND_FAILURE;
874 transferInfo->status = DtDND_SUCCESS;
882 XtPointer client_data,
888 DoQueryDialog( GETSTR(16,16, "The current icon has not been saved.\n\nYour changes will be lost.") );
896 if (successFormat == FORMAT_XPM)
898 X_Hot = xpm_ReadAttribs.x_hotspot;
899 Y_Hot = xpm_ReadAttribs.y_hotspot;
900 Display_XPMFile(xpm_ReadAttribs.width, xpm_ReadAttribs.height);
902 else if (successFormat == FORMAT_XBM)
906 Display_XBMFile(width_ret, height_ret);
912 /***************************************************************************
914 * Routine: Do_Paste *
916 * Purpose: Paste the CutCopy image at the tablet location specified by *
917 * the [x,y] parameters in the call. *
919 ***************************************************************************/
926 XImage *color_img, *mono_img;
928 if (GraphicsOp == S_PASTE) {
930 mono_img = CutCopy_mono;
932 else if (GraphicsOp == S_ROTATE) {
934 mono_img = Rotate_mono;
938 mono_img = Scale_mono;
941 if (GraphicsOp == S_PASTE)
943 GraphicsOp = S_WAIT_RELEASE;
947 GraphicsOp = Backup_G_Op;
948 if (Backup_G_Op == SELECT)
949 Start_HotBox(CONTINUE);
953 XPutImage(dpy, color_icon, Color_gc, color_img, 0, 0, x, y,
954 color_img->width, color_img->height);
955 XPutImage(dpy, mono_icon, Mono_gc, mono_img, 0, 0, x, y,
956 mono_img->width, mono_img->height);
957 XCopyArea(dpy, color_icon, XtWindow(iconImage), Color_gc,
958 x, y, color_img->width, color_img->height, x, y);
959 XCopyArea(dpy, mono_icon, XtWindow(monoImage), Mono_gc,
960 x, y, mono_img->width, mono_img->height, x, y);
961 Transfer_Back_Image(x, y, x+color_img->width, y+color_img->height, FILL);