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