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