dtwm: basic multihead(xinerama only) support
[oweals/cde.git] / cde / programs / dtcreate / fileio.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 #include <stdio.h>
24 #include <string.h>
25 #include <sys/stat.h>
26 #include <sys/types.h>
27 #include <fcntl.h>
28 #include <unistd.h>
29
30 #include <Dt/Icon.h>
31
32 #include <stdlib.h>
33 #include "dtcreate.h"
34 #include "cmnrtns.h"
35 #include "fileio.h"
36 #include "parser.h"
37 #include "ErrorDialog.h"
38
39 #define COMMENT_CHAR      '#'
40 #define MAX_KEY           10000
41 #define MAX_KEY_SIZE      5
42 #define MAX_HEADER_LINES  13
43
44 /*****************************************************************************/
45 /*                                                                           */
46 /*  CalculateMagicCookie                                                     */
47 /*                                                                           */
48 /*   description: Calculates a integer (the "key" value) which reflects the  */
49 /*                contents of the given file from the current file-offset    */
50 /*                to the end of file.                                        */
51 /*                Comment lines (those starting with '!' or '#') are ignored */
52 /*                in calculating the key value.                              */
53 /*                                                                           */
54 /*    input: pointer to FILE                                                 */
55 /*    output: integer - magic cookie                                         */
56 /*                                                                           */
57 /*****************************************************************************/
58 int CalculateMagicCookie(FILE *fp)
59 {
60
61 #define PRIME1  2999
62 #define PRIME2  353
63 #define PRIME3  113
64
65   long  save_offset, file_id;
66   int   c, prev_c, char_sum, nline, nword, nchar, inword;
67
68   /**************************************************************************/
69   /* Since we will be traversing the file, we save the file-offset          */
70   /* so that we can restore it before returning                             */
71   /**************************************************************************/
72   save_offset = ftell( fp );
73
74   inword = FALSE;
75   char_sum = nline = nword = nchar = 0;
76   prev_c = '0';   /* This is arbitrary, but '0' not '\0' IS intended */
77
78   while ( (c = fgetc( fp )) != EOF ) {
79     if ( c == COMMENT_CHAR ) {
80        while ( (c = fgetc( fp )) != EOF && c != '\n' )
81                ; /* skip characters to end of line */
82     } else {
83        char_sum += (c * (prev_c%10));
84        prev_c = c;
85        ++nchar;
86
87        if (c == '\n') {
88           ++nline;
89        }
90        if ( c == ' ' || c == '\n' || c == '\t' ) {
91           inword = FALSE;
92        } else if ( inword == FALSE ) {
93           inword = TRUE;
94           ++nword;
95        }
96     }
97   }
98
99   file_id = PRIME1 * nline + PRIME2 * nword + PRIME3 * nchar + char_sum;
100
101 #ifdef DEBUG
102   printf( "nline = %d nword = %d nchar = %d char_sum = %d\n",
103           nline, nword, nchar, char_sum );
104   printf( "file_id = %ld\n", file_id );
105 #endif
106
107   /**************************************************************************/
108   /* We restore the file-offset to its previous value                       */
109   /**************************************************************************/
110   (void) fseek( fp, save_offset, 0 );
111   return ( file_id % MAX_KEY );
112 }
113
114 /****************************************************************************/
115 /*                                                                          */
116 /*  SetCookie   - find the location in the file to write the magic cookie   */
117 /*                and update the file with the magic cookie.                */
118 /*                                                                          */
119 /*  input   - file pointer                                                  */
120 /*  output  - none                                                          */
121 /*                                                                          */
122 /****************************************************************************/
123 void SetCookie(FILE *fp)
124 {
125   int     iCookie;
126   long    lSave_offset;
127   char    buffer[256];
128   char    *keystr;
129   char    *retbuf;
130   fpos_t  filepos;
131   char    *mc_pos;
132   char    *mc_clrpos;
133   int     i;
134   int     size;
135
136   /**************************************************************************/
137   /* Save file pointer initial setting                                      */
138   /**************************************************************************/
139   lSave_offset = ftell (fp);
140
141   /**************************************************************************/
142   /* Set file pointer to beginning of file                                  */
143   /**************************************************************************/
144   fseek(fp, 0, SEEK_SET);
145
146   /**************************************************************************/
147   /* Calculate magic cookie                                                 */
148   /**************************************************************************/
149   iCookie = CalculateMagicCookie(fp);
150 #ifdef DEBUG
151   printf("Magic Cookie: %d\n", iCookie);
152 #endif
153
154   /**************************************************************************/
155   /* Find location in header and store cookie                               */
156   /**************************************************************************/
157   keystr = (char *)NULL;
158   retbuf = buffer;
159   i = 0;
160   while ( !keystr && retbuf && (i < MAX_HEADER_LINES) ) {
161     fgetpos(fp, &filepos);
162     retbuf = fgets(buffer, 80, fp);
163     keystr = strstr (buffer, "$KEY:");
164     i++;
165   }
166
167   if (!keystr) {
168 #ifdef DEBUG
169      printf("No '$KEY' keyword in file. Magic Cookie not written to file.\n");
170 #endif
171      return;
172   }
173   mc_pos = strchr(keystr, ':');
174   if (mc_pos) {
175      mc_pos += 2;
176      sprintf(mc_pos, "%i", iCookie);
177      size = strlen(mc_pos);
178      if (size < MAX_KEY_SIZE) {
179         mc_clrpos = mc_pos + size;
180         for (i=size; i < MAX_KEY_SIZE; i++) {
181             *mc_clrpos = ' ';
182             mc_clrpos++;
183         }
184      }
185   }
186   fsetpos (fp, &filepos);
187   fputs (buffer, fp);
188
189   /**************************************************************************/
190   /* Set file pointer back to initial setting                               */
191   /**************************************************************************/
192   fseek (fp, lSave_offset, SEEK_SET);
193   return;
194 }
195
196 /****************************************************************************/
197 /*                                                                          */
198 /*  CheckCookie  - check if the magic cookie exists in the file and is the  */
199 /*                 correct value.                                           */
200 /*                                                                          */
201 /*  input    - file pointer                                                 */
202 /*  output   - boolean indicating if correct value or not, TRUE = good      */
203 /*                                                                          */
204 /****************************************************************************/
205 Boolean CheckCookie(FILE *fp)
206 {
207   int     iNewCookie, iOldCookie;
208   long    lSave_offset;
209   char    buffer[256];
210   char    *msgPtr, *errPtr;
211   char    *keystr;
212   char    *retbuf;
213   fpos_t  filepos;
214   char    *mc_pos;
215   int     i;
216   Boolean bGoodCookie = TRUE;
217
218   /**************************************************************************/
219   /* Save file pointer initial setting                                      */
220   /**************************************************************************/
221   lSave_offset = ftell (fp);
222
223   /**************************************************************************/
224   /* Set file pointer to beginning of file                                  */
225   /**************************************************************************/
226   fseek (fp, 0, SEEK_SET);
227
228   /**************************************************************************/
229   /* Calculate magic cookie                                                 */
230   /**************************************************************************/
231   iNewCookie = CalculateMagicCookie(fp);
232 #ifdef DEBUG
233   printf("New Magic Cookie: %d\n", iNewCookie);
234 #endif
235
236   /**************************************************************************/
237   /* Find location in header of old cookie and retrieve it.                 */
238   /**************************************************************************/
239   keystr = (char *)NULL;
240   retbuf = buffer;
241   i = 0;
242   while ( !keystr && retbuf && (i < MAX_HEADER_LINES) ) {
243     fgetpos(fp, &filepos);
244     retbuf = fgets(buffer, 80, fp);
245     keystr = strstr (buffer, "$KEY:");
246     i++;
247   }
248
249   if (!keystr) {
250 #ifdef DEBUG
251      printf("No '$KEY' keyword in file header. File is invalid.\n");
252 #endif
253      msgPtr = GETMESSAGE(5, 67,
254          "Create Action can only edit files that were created\n\
255 and edited by Create Action.");
256      errPtr = XtNewString(msgPtr);
257      display_error_message(CreateActionAppShell, errPtr);
258      XtFree(errPtr);
259      bGoodCookie = FALSE;
260      fseek (fp, lSave_offset, SEEK_SET);
261      return(bGoodCookie);
262   }
263
264   mc_pos = strchr(keystr, ':');
265   mc_pos += 2;
266
267   sscanf(mc_pos, "%i", &iOldCookie);
268 #ifdef DEBUG
269   printf("Old Magic Cookie: %d\n", iOldCookie);
270 #endif
271
272
273   /**************************************************************************/
274   /* Check if cookies are the same.                                         */
275   /**************************************************************************/
276 #ifdef DEBUG
277   if (iOldCookie == iNewCookie) {
278      printf("Cookies are good = %i\n", iNewCookie);
279   }
280 #endif
281
282   if (iOldCookie != iNewCookie) {
283
284 #ifdef DEBUG
285      printf("Cookies are bad; n=%i, o=%i\n", iNewCookie, iOldCookie);
286 #endif
287
288      msgPtr = GETMESSAGE(5, 66,
289          "Could not load the file because it has been altered by some\n\
290 other means other than Create Action.  This could have been caused\n\
291 by modifying the file with a text editor or some other tool.");
292      errPtr = XtNewString(msgPtr);
293      display_error_message(CreateActionAppShell, errPtr);
294      XtFree(errPtr);
295      bGoodCookie = FALSE;
296   }
297
298   /**************************************************************************/
299   /* Set file pointer back to initial setting                               */
300   /**************************************************************************/
301   fseek (fp, lSave_offset, SEEK_SET);
302   return(bGoodCookie);
303 }
304
305 /*****************************************************************************/
306 /*                                                                           */
307 /*  MakeExecString                                                           */
308 /*                                                                           */
309 /*    return codes:                                                          */
310 /*                                                                           */
311 /*      ptr  good                                                            */
312 /*      0    bad                                                             */
313 /*                                                                           */
314 /*****************************************************************************/
315 char * MakeExecString(char *pszCmd, char *pszPrompt)
316
317 {
318   char    *pszExecString;
319   char    *pArgSrc = (char *)NULL;
320   char    *pArgDst = (char *)NULL;
321   char    *pTmp;
322   char    pszArgStr[10];
323   int     size = 0;
324   int     cArgs = 0;
325   int     val;
326   Boolean bDidPrompt = FALSE;
327 #define   ARGSIZE  7    /* sizeof "%Arg_n%" */
328
329   pArgSrc = pszCmd;
330   while (pArgSrc = strchr(pArgSrc, '$')) {
331 #ifdef DEBUG
332     printf("%d  pArgSrc = %s\n", cArgs, pArgSrc);
333 #endif
334     pArgSrc++;
335     val = *pArgSrc;
336     switch (val) {
337       case '1': case '2': case '3': case '4': case '5':
338       case '6': case '7': case '8': case '9': case '*':
339                 cArgs++;
340                 break;
341     }
342   }
343
344 #ifdef DEBUG
345   printf("Args found = %d\n", cArgs);
346 #endif
347
348   size = 1;
349   size += cArgs * ARGSIZE;
350   size += strlen(pszCmd);
351   if (pszPrompt) {
352      size += strlen(pszPrompt) + 2;
353   }
354   pszExecString = (char *)XtMalloc(size);
355
356   strcpy(pszExecString, pszCmd);
357   pArgSrc = pszCmd;
358   pTmp = pszExecString;
359   while (pArgSrc = strchr(pArgSrc, '$')) {
360     pArgDst = strchr(pTmp, '$');
361     pTmp = pArgDst;
362     *pArgDst = '\0';
363     pTmp++;
364     val = *pTmp;
365     switch (val) {
366       case '1': case '2': case '3': case '4': case '5':
367       case '6': case '7': case '8': case '9': case '*':
368                 pArgSrc+=2;
369                 if (*pTmp == '*') {
370                    strcat(pszExecString, "%Args");
371                 } else {
372                    sprintf(pszArgStr, "%%Arg_%c", *pTmp);
373                    strcat(pszExecString, pszArgStr);
374                 }
375                 if ((pszPrompt) && (!bDidPrompt)) {
376                    strcat(pszExecString, "\"");
377                    strcat(pszExecString, pszPrompt);
378                    strcat(pszExecString, "\"");
379                    bDidPrompt = TRUE;
380                 }
381                 strcat(pszExecString, "%");
382                 break;
383     }
384     if (*pArgSrc) {
385        strcat(pszExecString, pArgSrc);
386        pArgSrc++;
387     }
388   }
389 #ifdef DEBUG
390   printf("EXEC_STRING = '%s'\n", pszExecString);
391 #endif
392   return(pszExecString);
393 }
394
395 /*****************************************************************************/
396 /*                                                                           */
397 /*  WriteDefinitionFile                                                      */
398 /*                                                                           */
399 /*    return codes:                                                          */
400 /*                                                                           */
401 /*      0    successful                                                      */
402 /*      1    could not open file                                             */
403 /*                                                                           */
404 /*****************************************************************************/
405 ushort WriteDefinitionFile(char *pszFile, ActionData *pAD)
406
407 {
408   FILE            *fp = (FILE *)NULL;
409   int             i;
410   FiletypeData    *pFtD;
411   char            buffer[MAXBUFSIZE];
412   char            *ptr;
413   char            *msgPtr, *fmtPtr, *errPtr;
414
415   /***************************************************************************/
416   /* Open action and filetypes definition file for writing.                  */
417   /***************************************************************************/
418   if ((fp = fopen(pszFile, "w+")) == NULL) {
419 #ifdef DEBUG
420     printf("Can not open file.\n"); /* debug */
421 #endif
422     msgPtr = GETMESSAGE(5, 55, "Could not create the following file:");
423     fmtPtr = "%s\n   %s";
424     errPtr = XtMalloc((strlen(msgPtr) + strlen(fmtPtr) +
425                        strlen(pszFile) + 1) * sizeof(char));
426     sprintf(errPtr, fmtPtr, msgPtr, pszFile);
427     display_error_message(CreateActionAppShell, errPtr);
428     XtFree(errPtr);
429     return(1);
430   }
431 #ifdef DEBUG
432   printf("database file = %s\n", pszFile); /* debug */
433 #endif
434
435   /***************************************************************************/
436   /* Write comment area of action and filetype definition file, including    */
437   /* revision number and magic cookie.                                       */
438   /***************************************************************************/
439   fprintf(fp, "######################################################################\n");
440   fprintf(fp, "#\n");
441   fprintf(fp, "#    Common Desktop Environment (CDE)\n");
442   fprintf(fp, "#\n");
443   fprintf(fp, "#    Action and DataType Definition File\n");
444   fprintf(fp, "#\n");
445   fprintf(fp, "#      Generated by the CreateAction tool\n");
446   fprintf(fp, "#\n");
447   fprintf(fp, "#      $Revision: 1.0\n");
448   fprintf(fp, "#\n");
449   fprintf(fp, "#      $KEY: nnnnn \n");
450   fprintf(fp, "#\n");
451   fprintf(fp, "######################################################################\n");
452   fprintf(fp, "#\n");
453   fprintf(fp, "#    WARNING:\n");
454   fprintf(fp, "#\n");
455   fprintf(fp, "#    This file was generated by the CDE CreateAction tool.\n");
456   fprintf(fp, "#    If this file is modified by some other tool, such as vi,\n");
457   fprintf(fp, "#    the CreateAction tool will no longer be able to load and\n");
458   fprintf(fp, "#    update this file.  For this reason, changes to this file\n");
459   fprintf(fp, "#    should be handled through CreateAction whenever possible.\n");
460   fprintf(fp, "#\n");
461   fprintf(fp, "######################################################################\n");
462   fprintf(fp, "\n");
463
464   /***************************************************************************/
465   /* Write the main Action definition.                                       */
466   /***************************************************************************/
467   ptr = GetCoreName(pszFile);
468   fprintf(fp, "ACTION %s\n", ptr);
469   free(ptr);
470   fprintf(fp, "{\n");
471   fprintf(fp, "     LABEL         %s\n", pAD->pszName);
472   fprintf(fp, "     TYPE          COMMAND\n");
473   ptr = MakeExecString(AD.pszCmd, AD.pszPrompt);
474   if (ptr) {
475      fprintf(fp, "     EXEC_STRING   %s\n", ptr);
476      XtFree(ptr);
477   }
478   if (pAD->pszIcon) {
479 #ifdef OLDICON
480     fprintf(fp, "     LARGE_ICON    %s.m\n", pAD->pszIcon);
481     fprintf(fp, "     SMALL_ICON    %s.t\n", pAD->pszIcon);
482 #else
483     if (ActionHasIcon()) {
484        fprintf(fp, "     ICON          %s\n", pAD->pszName);
485     } else {
486        fprintf(fp, "     ICON          %s\n", pAD->pszIcon);
487     }
488 #endif
489   }
490 #ifdef DEBUG
491   printf("CA flags = %X\n", pAD->fsFlags);
492 #endif
493   if (pAD->fsFlags & CA_WT_TERM) fprintf(fp, "     WINDOW_TYPE   TERMINAL\n");
494   else if (pAD->fsFlags & CA_WT_PERMTERM) fprintf(fp, "     WINDOW_TYPE   PERM_TERMINAL\n");
495   else if (pAD->fsFlags & CA_WT_SHELLTERM) fprintf(fp, "     WINDOW_TYPE   SHELL_TERMINAL\n");
496   else fprintf(fp, "     WINDOW_TYPE   NO_STDIO\n");
497
498   if ((pAD->papFiletypes) && (pAD->fsFlags & CA_DF_ONLYFTFILES)) {
499     fprintf(fp, "     ARG_TYPE      %s", (pAD->papFiletypes[0])->pszName);
500     for (i=1; i < pAD->cFiletypes; i++) {
501       pFtD = pAD->papFiletypes[i];
502       fprintf(fp, ",%s", pFtD->pszName);
503     }
504     fprintf(fp, "\n");
505   }
506
507   if (pAD->pszHelp) {
508     fprintf(fp, "     DESCRIPTION   %s\n", pAD->pszHelp);
509   }
510   fprintf(fp, "}\n");
511   fprintf(fp, "\n");
512
513   /***************************************************************************/
514   /* Write the filetype definitions.                                         */
515   /***************************************************************************/
516   if (pAD->papFiletypes) {
517     for (i=0; i < pAD->cFiletypes; i++) {
518       pFtD = pAD->papFiletypes[i];
519       /***********************************************************************/
520       /* Write the data attributes declaration.                              */
521       /***********************************************************************/
522       fprintf(fp, "DATA_ATTRIBUTES %s\n", pFtD->pszName);
523       fprintf(fp, "{\n");
524       fprintf(fp, "     ACTIONS       Open");
525       if (pFtD->pszPrintCmd) {
526         fprintf(fp, ",Print");
527       }
528       fprintf(fp, "\n");
529       if (pFtD->pszIcon) {
530 #ifdef OLDICON
531         fprintf(fp, "     LARGE_ICON    %s.m\n", pFtD->pszIcon);
532         fprintf(fp, "     SMALL_ICON    %s.t\n", pFtD->pszIcon);
533 #else
534         if (FiletypeHasIcon(pFtD)) {
535            fprintf(fp, "     ICON          %s\n", pFtD->pszName);
536         } else {
537            fprintf(fp, "     ICON          %s\n", pFtD->pszIcon);
538         }
539 #endif
540       }
541       if (pFtD->pszHelp) {
542         fprintf(fp, "     DESCRIPTION   %s\n", pFtD->pszHelp);
543       }
544       fprintf(fp, "}\n");
545       fprintf(fp, "\n");
546       /***********************************************************************/
547       /* Write the data criteria   declaration.                              */
548       /***********************************************************************/
549       fprintf(fp, "DATA_CRITERIA %sA\n", pFtD->pszName);
550       fprintf(fp, "{\n");
551       fprintf(fp, "     DATA_ATTRIBUTES_NAME %s\n", pFtD->pszName);
552       if (pFtD->pszPermissions) {
553         fprintf(fp, "     MODE          %s\n", pFtD->pszPermissions);
554       }
555       if (pFtD->pszPattern) {
556         fprintf(fp, "     PATH_PATTERN  %s\n", pFtD->pszPattern);
557       }
558       if (pFtD->pszContents) {
559          if (pFtD->fsFlags & CA_FT_CNTSTRING)
560             strcpy(buffer, "string");
561          else if (pFtD->fsFlags & CA_FT_CNTBYTE)
562             strcpy(buffer, "byte");
563          else if (pFtD->fsFlags & CA_FT_CNTSHORT)
564             strcpy(buffer, "short");
565          else if (pFtD->fsFlags & CA_FT_CNTLONG)
566             strcpy(buffer, "long");
567          fprintf(fp, "     CONTENT       %d %s %s\n", pFtD->sStart, buffer, pFtD->pszContents);
568       }
569       fprintf(fp, "}\n");
570       fprintf(fp, "\n");
571       /***********************************************************************/
572       /* Write the Open MAP action.                                          */
573       /***********************************************************************/
574       fprintf(fp, "ACTION Open\n");
575       fprintf(fp, "{\n");
576       fprintf(fp, "     ARG_TYPE      %s\n", pFtD->pszName);
577       fprintf(fp, "     TYPE          MAP\n");
578       fprintf(fp, "     MAP_ACTION    %s\n", pAD->pszName);
579       fprintf(fp, "     LABEL         %s\n", GETMESSAGE(7, 30, "Open"));
580       fprintf(fp, "}\n");
581       fprintf(fp, "\n");
582       /***********************************************************************/
583       /* Write the Print filetype action and MAP action.                     */
584       /***********************************************************************/
585       if (pFtD->pszPrintCmd) {
586         /*********************************************************************/
587         /* First write the print filetype action.                            */
588         /*********************************************************************/
589         fprintf(fp, "ACTION %s_PRINT\n", pFtD->pszName);
590         fprintf(fp, "{\n");
591         fprintf(fp, "     TYPE          COMMAND\n");
592         ptr = MakeExecString(pFtD->pszPrintCmd, NULL);
593         if (ptr) {
594            fprintf(fp, "     EXEC_STRING   %s\n", ptr);
595          /*fprintf(fp, "     EXEC_STRING   %s\n", pFtD->pszPrintCmd);*/
596            XtFree(ptr);
597         }
598         fprintf(fp, "     WINDOW_TYPE   NO_STDIO\n");
599         fprintf(fp, "}\n");
600         fprintf(fp, "\n");
601         /*********************************************************************/
602         /* Now writhe the Print MAP action.                                  */
603         /*********************************************************************/
604         fprintf(fp, "ACTION Print\n");
605         fprintf(fp, "{\n");
606         fprintf(fp, "     ARG_TYPE      %s\n", pFtD->pszName);
607         fprintf(fp, "     TYPE          MAP\n");
608         fprintf(fp, "     MAP_ACTION    %s_PRINT\n", pFtD->pszName);
609         fprintf(fp, "     LABEL         %s\n", GETMESSAGE(7, 31, "Print"));
610         fprintf(fp, "}\n");
611         fprintf(fp, "\n");
612       }
613     }
614   }
615   SetCookie(fp);
616   if (fp) fclose(fp);
617   chmod(pszFile, 0644);
618   return(0);
619 }
620
621 /*****************************************************************************/
622 /*                                                                           */
623 /*  WriteActionFile                                                          */
624 /*                                                                           */
625 /*    return codes:                                                          */
626 /*                                                                           */
627 /*      0    successful                                                      */
628 /*      1    could not open file                                             */
629 /*                                                                           */
630 /*****************************************************************************/
631 ushort WriteActionFile(ActionData *pAD)
632
633 {
634   FILE            *fp = (FILE *)NULL;
635   char            *pszFile;
636   char            *newName;
637   char            *pszEnvVar;
638   char            *msgPtr, *fmtPtr, *errPtr;
639
640   /***************************************************************************/
641   /* Open action file for writing.                                           */
642   /***************************************************************************/
643   newName = ReplaceSpaces(AD.pszName);
644   pszEnvVar = getenv("HOME");
645   pszFile = NULL;
646   if ( pszEnvVar && strlen(pszEnvVar) ) {
647      pszFile = XtMalloc(strlen(pszEnvVar) + strlen(newName) + 10);
648      if (pszFile) sprintf(pszFile, "%s/%s", pszEnvVar, newName);
649   } else {
650      pszFile = XtMalloc(strlen(newName) + 10);
651      if (pszFile) sprintf(pszFile, "/tmp/%s", newName);
652   }
653   free(newName);
654
655   /***************************************************************************/
656   /* Open action file for writing.                                           */
657   /***************************************************************************/
658   if (pszFile && (fp = fopen(pszFile, "w")) == NULL) {
659 #ifdef DEBUG
660     printf("Can not open file.\n"); /* debug */
661 #endif
662     msgPtr = GETMESSAGE(5, 55, "Could not create the following file:");
663     fmtPtr = "%s\n   %s";
664     errPtr = XtMalloc((strlen(msgPtr) + strlen(fmtPtr) +
665                        strlen(pszFile) + 1) * sizeof(char));
666     sprintf(errPtr, fmtPtr, msgPtr, pszFile);
667     display_error_message(CreateActionAppShell, errPtr);
668     XtFree(errPtr);
669     XtFree(pszFile);
670     return(1);
671   }
672 #ifdef DEBUG
673   printf("action file = %s\n", pszFile); /* debug */
674 #endif
675   /***************************************************************************/
676   /* Write action file contents.                                             */
677   /***************************************************************************/
678   fprintf(fp, "################################################\n");
679   fprintf(fp, "#\n");
680   fprintf(fp, "#  action\n");
681   fprintf(fp, "#\n");
682   fprintf(fp, "#  Common Desktop Environment (CDE)\n");
683   fprintf(fp, "#\n");
684   fprintf(fp, "#  $TOG: fileio.c /main/9 1998/10/26 17:18:19 mgreess $\n");
685   fprintf(fp, "#\n");
686   fprintf(fp, "################################################\n");
687   fprintf(fp, "\n");
688   fprintf(fp, "# This file represents a CDE Dt action.  The contents of the file do\n");
689   fprintf(fp, "# not matter; however, the file must have executable permission and the\n");
690   fprintf(fp, "# name of the file must match an entry in the action database (*.dt files).\n");
691   fprintf(fp, "#\n");
692   fprintf(fp, "# For more information on Dt actions, see the CDE Dt manuals.\n");
693   fprintf(fp, "\n");
694   fprintf(fp, "echo \"Common Desktop Environment Dt action\"\n");
695   fprintf(fp, "\n");
696
697   if (fp) fclose(fp);
698   chmod(pszFile, 0755);
699   return(0);
700 }
701
702 /******************************************************************************/
703 /* check_file_exists - check if the file exists that is passed in, if not     */
704 /*                     display error dialog.                                  */
705 /*                                                                            */
706 /* INPUT:   filename      - name of file to check if it exists or not.        */
707 /*                                                                            */
708 /* OUTPUT:  TRUE          - file exists                                       */
709 /*          FALSE         - file does not exist                               */
710 /*                                                                            */
711 /******************************************************************************/
712 Boolean check_file_exists (char *pszFileName)
713 {
714   FILE *exists;
715
716   /***************************************/
717   /* see if file exists                  */
718   /***************************************/
719   exists = fopen (pszFileName, "r");
720
721   /***************************************/
722   /* if exists, return good return code  */
723   /***************************************/
724   if (exists) {
725     fclose (exists);
726     return(TRUE);
727   } else {
728 #ifdef DEBUG
729     printf("File '%s' does not exist!\n", pszFileName);
730 #endif
731     return(FALSE);
732   }
733 }
734
735 /*****************************************************************************/
736 /*                                                                           */
737 /*  OpenDefinitionFile                                                       */
738 /*                                                                           */
739 /*    return codes:                                                          */
740 /*                                                                           */
741 /*      0    successful                                                      */
742 /*      1    error                                                           */
743 /*                                                                           */
744 /*****************************************************************************/
745 int OpenDefinitionFile(char *pszFile, ActionData *pAD)
746
747 {
748   FILE       *fp = (FILE *)NULL;
749   int        rc;
750   char       *msgPtr, *fmtPtr, *errPtr;
751
752   /***************************************************************************/
753   /* Open action and filetypes definition file for reading.                  */
754   /***************************************************************************/
755   if ((fp = fopen(pszFile, "r+")) == NULL) {
756 #ifdef DEBUG
757     printf("Can not open file.\n"); /* debug */
758 #endif
759     msgPtr = GETMESSAGE(5, 60, "Could not open the following file:");
760     fmtPtr = "%s\n   %s";
761     errPtr = XtMalloc((strlen(msgPtr) + strlen(fmtPtr) +
762                        strlen(pszFile) + 1) * sizeof(char));
763     sprintf(errPtr, fmtPtr, msgPtr, pszFile);
764     display_error_message(CreateActionAppShell, errPtr);
765     XtFree(errPtr);
766     return(1);
767   }
768 #ifdef DEBUG
769   printf("Opened database file = %s\n", pszFile); /* debug */
770 #endif
771
772   /***************************************************************************/
773   /* If magic cookie is good, then parse the file.                           */
774   /***************************************************************************/
775   if (CheckCookie(fp)) {
776 #ifdef DEBUG
777      printf("Cookie good, call parse code\n");
778 #endif
779      rc = GetActionData(fp, pAD);
780
781      /************************************************************************/
782      /* If error, display error message.                                     */
783      /************************************************************************/
784      if (rc) {
785         msgPtr = GETMESSAGE(5, 90, "Could not parse the following file:");
786         fmtPtr = "%s\n   %s";
787         errPtr = XtMalloc((strlen(msgPtr) + strlen(fmtPtr) +
788                            strlen(pszFile) + 1) * sizeof(char));
789         sprintf(errPtr, fmtPtr, msgPtr, pszFile);
790         display_error_message(CreateActionAppShell, errPtr);
791         XtFree(errPtr);
792         return(1);
793      }
794   }
795   if (fp) fclose(fp);
796   return(rc);
797 }
798
799 /******************************************************************************/
800 /* CheckDirtyIcon - check if icon has a DirtyBit set                          */
801 /*                                                                            */
802 /* INPUT:   Icon Widget   - widget id of icon gadget to check                 */
803 /*                                                                            */
804 /* OUTPUT:  TRUE          - dirty bit is set                                  */
805 /*          FALSE         - dirty bit is not set                              */
806 /*                                                                            */
807 /******************************************************************************/
808 Boolean CheckDirtyIcon (Widget wid)
809 {
810   IconData  *pIconData;
811
812   pIconData = GetIconDataFromWid(wid);
813   if (pIconData) {
814      if ( (pIconData->pmDirtyBit) || (pIconData->bmDirtyBit) ) {
815         return(True);
816      }
817   }
818   return(False);
819 }
820
821 /*****************************************************************************/
822 /*                                                                           */
823 /*  CreateIconName                                                           */
824 /*                                                                           */
825 /*    return codes:                                                          */
826 /*                                                                           */
827 /*      0    successful                                                      */
828 /*      1    could not open file                                             */
829 /*                                                                           */
830 /*****************************************************************************/
831 char * CreateIconName(char *pszDirName, char *pszBaseName, enum icon_size_range enumSize, char *pszType, Boolean bIsMask)
832 {
833   char  *pszName;
834   char  pszSize[MAX_EXT_SIZE];
835
836   switch (enumSize) {
837     case Large_Icon :
838                strcpy(pszSize, LARGE_EXT);
839                break;
840     case Medium_Icon :
841                strcpy(pszSize, MEDIUM_EXT);
842                break;
843     case Small_Icon :
844                strcpy(pszSize, SMALL_EXT);
845                break;
846     case Tiny_Icon :
847                strcpy(pszSize, TINY_EXT);
848                break;
849     case None_Selected :
850                pszSize[0] = 0;
851   }
852   if (bIsMask) {
853      strcat(pszSize, "_m");
854   }
855   if (pszDirName) {
856      pszName = XtMalloc(strlen(pszDirName) + strlen(pszBaseName) + strlen(pszSize) + strlen(pszType) + 1);
857      if (pszName) {
858         sprintf(pszName, "%s%s%s%s", pszDirName, pszBaseName, pszSize, pszType);
859      }
860   } else {
861      pszName = XtMalloc(strlen(pszBaseName) + strlen(pszSize) + strlen(pszType) + 1);
862      if (pszName) {
863         sprintf(pszName, "%s%s%s", pszBaseName, pszSize, pszType);
864      }
865   }
866   return(pszName);
867 }
868
869 /*****************************************************************************/
870 /*                                                                           */
871 /*  CopyFile                                                                 */
872 /*                                                                           */
873 /*    return codes:                                                          */
874 /*                                                                           */
875 /*      0    successful                                                      */
876 /*      1    could not open file                                             */
877 /*                                                                           */
878 /*****************************************************************************/
879 ushort CopyFile(char *pszSource, char *pszDest)
880
881 {
882   int            fdSource;
883   int            fdDest;
884   int            len;
885   int            rlen;
886   ushort         usRc = 0;
887   char           *buffer;
888   char           *msgPtr, *fmtPtr, *errPtr;
889
890   fdSource = open(pszSource, O_RDONLY);
891   if (fdSource == -1) {
892      msgPtr = GETMESSAGE(5, 60, "Could not open the following file:");
893      fmtPtr = "%s\n   %s";
894      errPtr = XtMalloc((strlen(msgPtr) + strlen(fmtPtr) +
895                         strlen(pszSource) + 1) * sizeof(char));
896      sprintf(errPtr, fmtPtr, msgPtr, pszSource);
897      display_error_message(CreateActionAppShell, errPtr);
898      XtFree(errPtr);
899      usRc = 1;
900   } else {
901      /************************************************************/
902      /* Find out how big a buffer is needed                      */
903      /************************************************************/
904      len = lseek(fdSource, 0, SEEK_END);
905      (void) lseek(fdSource, 0, SEEK_SET);
906      buffer = XtMalloc((Cardinal) (len + 1));
907      if ((rlen = read(fdSource, buffer, len)) != len) {
908         /*********************************************************/
909         /* Didn't read whole file!                               */
910         /*********************************************************/
911      } else {
912         fdDest = creat(pszDest, 0644);
913         /*fdDest = open(pszDest, O_WRONLY);*/
914         if (fdDest == -1) {
915            msgPtr = GETMESSAGE(5, 55, "Could not create the following file:");
916            fmtPtr = "%s\n   %s";
917            errPtr = XtMalloc((strlen(msgPtr) + strlen(fmtPtr) +
918                               strlen(pszDest) + 1) * sizeof(char));
919            sprintf(errPtr, fmtPtr, msgPtr, pszDest);
920            display_error_message(CreateActionAppShell, errPtr);
921            XtFree(errPtr);
922            usRc = 1;
923         } else {
924            if ((rlen = write(fdDest, buffer, len)) != len) {
925               /***************************************************/
926               /* Didn't write the whole file!                    */
927               /***************************************************/
928            }
929
930            close(fdDest);
931         }
932      }
933
934      XtFree(buffer);
935      close(fdSource);
936   }
937   return(usRc);
938 }
939
940 /*****************************************************************************/
941 /*                                                                           */
942 /*  CreateDirName                                                            */
943 /*                                                                           */
944 /*    return codes:                                                          */
945 /*                                                                           */
946 /*      NULL        error has occurred                                       */
947 /*      not NULL    name of directory to store icons                         */
948 /*                                                                           */
949 /*****************************************************************************/
950 char * CreateDirName(void)
951 {
952   char  *pszNewName = (char *)NULL;
953   char  *pszDirName = (char *)NULL;
954   char  *pszEnvVar;
955   char  *msgPtr, *errPtr;
956
957   pszEnvVar = getenv("HOME");
958   if ( pszEnvVar && strlen(pszEnvVar) ) {
959      pszDirName = XtMalloc(strlen(pszEnvVar) + strlen("/.dt/icons/") + 1);
960      sprintf(pszDirName, "%s/.dt/icons/", pszEnvVar);
961   } else {
962      msgPtr = GETMESSAGE(5, 170, "The HOME environment variable is not set.\n\
963 The HOME environment variable must be set in order\n\
964 for this action to be saved.");
965      errPtr = XtNewString(msgPtr);
966      display_error_message(CreateActionAppShell, errPtr);
967      XtFree(errPtr);
968   }
969   return(pszDirName);
970 }
971
972 /*****************************************************************************/
973 /*                                                                           */
974 /*  CopyFilesFromWid                                                         */
975 /*                                                                           */
976 /*    return codes:                                                          */
977 /*                                                                           */
978 /*      0    successful                                                      */
979 /*      1    could not open file                                             */
980 /*                                                                           */
981 /*****************************************************************************/
982 ushort CopyFilesFromWid(ActionData *pAD, Widget wid)
983
984 {
985   IconData      *pIconData;
986   char          *pszDirName = (char *)NULL;
987   Boolean       bHaveError = FALSE;
988   char          *pszIconName = (char *)NULL;
989   char          *pszNewName = (char *)NULL;
990   char          *pszMaskName = (char *)NULL;
991
992   pszDirName = CreateDirName();
993   if (!pszDirName) bHaveError = True;
994
995   pIconData = GetIconDataFromWid(wid);
996   pszNewName = ReplaceSpaces(pAD->pszName);
997
998   if ((!bHaveError) && (pIconData)) {
999      pszIconName = CreateIconName(pszDirName, pszNewName, pIconData->size, PIXMAP_EXT, FALSE);
1000      if ((!pszIconName) || (CopyFile(pIconData->pmFileName, pszIconName))) {
1001         bHaveError = True;
1002      }
1003      if (pszIconName) XtFree(pszIconName);
1004   }
1005
1006   if ((!bHaveError) && (pIconData)) {
1007      pszIconName = CreateIconName(pszDirName, pszNewName, pIconData->size, BITMAP_EXT, FALSE);
1008      if ((!pszIconName) || (CopyFile(pIconData->bmFileName, pszIconName))) {
1009         bHaveError = True;
1010      }
1011      if (pszIconName) XtFree(pszIconName);
1012
1013      /**********************************************/
1014      /* Now see if it has a mask file.             */
1015      /**********************************************/
1016      if (!bHaveError) {
1017         pszMaskName = CreateMaskName(pIconData->bmFileName);
1018         if ((pszMaskName) && (check_file_exists(pszMaskName))) {
1019 #ifdef DEBUG
1020            printf("Mask file exists = %s\n", pszMaskName); /* debug */
1021 #endif
1022            pszIconName = CreateIconName(pszDirName, pszNewName, pIconData->size, BITMAP_EXT, TRUE);
1023            if ((!pszIconName) || (CopyFile(pszMaskName, pszIconName))) {
1024               bHaveError = True;
1025            }
1026            if (pszIconName) XtFree(pszIconName);
1027            XtFree(pszMaskName);
1028         }
1029      }
1030   }
1031
1032   if (pszNewName) XtFree(pszNewName);
1033   if (pszDirName) XtFree(pszDirName);
1034
1035   if (bHaveError) {
1036      return(1);
1037   } else {
1038      return(0);
1039   }
1040 }
1041 /******************************************************************************/
1042 /* ActionHasIcon - check if any of the main action's icons have dirty bit set */
1043 /*                                                                            */
1044 /* INPUT:   none                                                              */
1045 /*                                                                            */
1046 /* OUTPUT:  TRUE          - action has icon                                   */
1047 /*          FALSE         - no icon for this action                           */
1048 /*                                                                            */
1049 /******************************************************************************/
1050 Boolean ActionHasIcon (void)
1051 {
1052   if ( CheckDirtyIcon(CA_LRG_IconGadget) ||
1053        CheckDirtyIcon(CA_MED_IconGadget) ||
1054        CheckDirtyIcon(CA_TINY_IconGadget) ) {
1055      return(True);
1056   } else {
1057      return(False);
1058   }
1059
1060 }
1061
1062 /******************************************************************************/
1063 /* FiletypeHasIcon - check if the filetype has modified icons.                */
1064 /*                                                                            */
1065 /* INPUT:   Filetype data structure pointer                                   */
1066 /*                                                                            */
1067 /* OUTPUT:  TRUE          - action has icon                                   */
1068 /*          FALSE         - no icon for this action                           */
1069 /*                                                                            */
1070 /******************************************************************************/
1071 Boolean FiletypeHasIcon (FiletypeData *pFtD)
1072 {
1073   if ( (pFtD->pszMedPmIcon) ||
1074        (pFtD->pszMedBmIcon) ||
1075        (pFtD->pszTinyPmIcon) ||
1076        (pFtD->pszTinyBmIcon) ) {
1077      return(True);
1078   } else {
1079      return(False);
1080   }
1081
1082 }
1083
1084 /*****************************************************************************/
1085 /*                                                                           */
1086 /*  CopyIconFiles                                                            */
1087 /*                                                                           */
1088 /*    return codes:                                                          */
1089 /*                                                                           */
1090 /*      0    successful                                                      */
1091 /*      1    could not open file                                             */
1092 /*                                                                           */
1093 /*****************************************************************************/
1094 ushort CopyIconFiles(ActionData *pAD)
1095
1096 {
1097   Boolean       bHaveError = FALSE;
1098   FiletypeData  *pFtD;
1099   int           i;
1100   char          *pszDirName = (char *)NULL;
1101   char          *pszNewIconName;
1102   char          *pszNewIconMask;
1103   char          *pszOldIconName;
1104   char          *ptr;
1105   char          buffer[MAXFILENAME];
1106
1107 #define  CIF_ERROR    1
1108 #define  CIF_SUCCESS  0
1109
1110   if (ActionHasIcon()) {
1111      if ( !bHaveError && (CopyFilesFromWid(pAD, CA_LRG_IconGadget) != 0) ) {
1112         bHaveError = TRUE;
1113      }
1114      if ( !bHaveError && (CopyFilesFromWid(pAD, CA_MED_IconGadget) != 0) ) {
1115         bHaveError = TRUE;
1116      }
1117      if ( !bHaveError && (CopyFilesFromWid(pAD, CA_TINY_IconGadget) != 0) ) {
1118         bHaveError = TRUE;
1119      }
1120   }
1121
1122   if (!bHaveError && (pAD->papFiletypes)) {
1123      pszDirName = CreateDirName();
1124      for (i=0; i < pAD->cFiletypes; i++) {
1125        pFtD = pAD->papFiletypes[i];
1126        if (FiletypeHasIcon(pFtD)) {
1127           FIND_ICONGADGET_ICON(pFtD->pszIcon, pszOldIconName, DtMEDIUM);
1128           if (pszOldIconName) {
1129              ptr = strstr(pszOldIconName, MEDIUM_EXT);
1130              if (ptr) *ptr = '\0';
1131           }
1132
1133           /*****************************************************************/
1134           /* Medium Pixmap                                                 */
1135           /*****************************************************************/
1136           pszNewIconName = CreateIconName(pszDirName, pFtD->pszName, Medium_Icon, PIXMAP_EXT, FALSE);
1137           if (pszNewIconName) {
1138              if (pFtD->pszMedPmIcon) {
1139                 CopyFile(pFtD->pszMedPmIcon, pszNewIconName);
1140              } else {
1141                 ptr = CreateIconName((char *)NULL, pszOldIconName, Medium_Icon, PIXMAP_EXT, FALSE);
1142                 if (ptr) {
1143                    CopyFile(ptr, pszNewIconName);
1144                    XtFree(ptr);
1145                 }
1146              }
1147              if (pszNewIconName) XtFree(pszNewIconName);
1148           }
1149
1150           /*****************************************************************/
1151           /* Medium Bitmap                                                 */
1152           /*****************************************************************/
1153           pszNewIconName = CreateIconName(pszDirName, pFtD->pszName, Medium_Icon, BITMAP_EXT, FALSE);
1154           pszNewIconMask = CreateIconName(pszDirName, pFtD->pszName, Medium_Icon, BITMAP_EXT, TRUE);
1155           if (pszNewIconName) {
1156              if (pFtD->pszMedBmIcon) {
1157                 CopyFile(pFtD->pszMedBmIcon, pszNewIconName);
1158                 /****************************/
1159                 /* Now do the mask file.    */
1160                 /****************************/
1161                 sprintf(buffer, "%s_m", pFtD->pszMedBmIcon);
1162                 if (pszNewIconMask && check_file_exists(buffer)) {
1163                    CopyFile(buffer, pszNewIconMask);
1164                 }
1165              } else {
1166                 ptr = CreateIconName((char *)NULL, pszOldIconName, Medium_Icon, BITMAP_EXT, FALSE);
1167                 if (ptr) {
1168                    CopyFile(ptr, pszNewIconName);
1169                    XtFree(ptr);
1170                 }
1171                 /****************************/
1172                 /* Now do the mask file.    */
1173                 /****************************/
1174                 ptr = CreateIconName((char *)NULL, pszOldIconName, Medium_Icon, BITMAP_EXT, TRUE);
1175                 if (ptr && check_file_exists(ptr) && pszNewIconMask) {
1176                    CopyFile(ptr, pszNewIconMask);
1177                    XtFree(ptr);
1178                 }
1179              }
1180              if (pszNewIconName) XtFree(pszNewIconName);
1181              if (pszNewIconMask) XtFree(pszNewIconMask);
1182           }
1183
1184           /*****************************************************************/
1185           /* Tiny Pixmap                                                   */
1186           /*****************************************************************/
1187           pszNewIconName = CreateIconName(pszDirName, pFtD->pszName, Tiny_Icon, PIXMAP_EXT, FALSE);
1188           if (pszNewIconName) {
1189              if (pFtD->pszTinyPmIcon) {
1190                 CopyFile(pFtD->pszTinyPmIcon, pszNewIconName);
1191              } else {
1192                 ptr = CreateIconName((char *)NULL, pszOldIconName, Tiny_Icon, PIXMAP_EXT, FALSE);
1193                 if (ptr) {
1194                    CopyFile(ptr, pszNewIconName);
1195                    XtFree(ptr);
1196                 }
1197              }
1198              if (pszNewIconName) XtFree(pszNewIconName);
1199           }
1200
1201           /*****************************************************************/
1202           /* Tiny Bitmap                                                   */
1203           /*****************************************************************/
1204           pszNewIconName = CreateIconName(pszDirName, pFtD->pszName, Tiny_Icon, BITMAP_EXT, FALSE);
1205           pszNewIconMask = CreateIconName(pszDirName, pFtD->pszName, Tiny_Icon, BITMAP_EXT, TRUE);
1206           if (pszNewIconName) {
1207              if (pFtD->pszTinyBmIcon) {
1208                 CopyFile(pFtD->pszTinyBmIcon, pszNewIconName);
1209                 /****************************/
1210                 /* Now do the mask file.    */
1211                 /****************************/
1212                 sprintf(buffer, "%s_m", pFtD->pszTinyBmIcon);
1213                 if (pszNewIconMask && check_file_exists(buffer)) {
1214                    CopyFile(buffer, pszNewIconMask);
1215                 }
1216              } else {
1217                 ptr = CreateIconName((char *)NULL, pszOldIconName, Tiny_Icon, BITMAP_EXT, FALSE);
1218                 if (ptr) {
1219                    CopyFile(ptr, pszNewIconName);
1220                    XtFree(ptr);
1221                 }
1222                 /****************************/
1223                 /* Now do the mask file.    */
1224                 /****************************/
1225                 ptr = CreateIconName((char *)NULL, pszOldIconName, Tiny_Icon, BITMAP_EXT, TRUE);
1226                 if (ptr && check_file_exists(ptr) && pszNewIconMask) {
1227                    CopyFile(ptr, pszNewIconMask);
1228                    XtFree(ptr);
1229                 }
1230              }
1231              if (pszNewIconName) XtFree(pszNewIconName);
1232              if (pszNewIconMask) XtFree(pszNewIconMask);
1233           }
1234        }
1235      }
1236   }
1237
1238   return(CIF_SUCCESS);
1239 }