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