1 
2 /* file_act.c - part of asedit program */
3 /*
4  * Copyright 1991 - 1994,  Andrzej Stochniol, London, UK
5  *
6  * ASEDIT text editor, both binary and source (hereafter, Software) is
7  * copyrighted by Andrzej Stochniol (hereafter, AS) and ownership remains
8  * with AS.
9  *
10  * AS grants you (hereafter, Licensee) a license to use the Software
11  * for academic, research and internal business purposes only, without a
12  * fee.  Licensee may distribute the binary and source code (if released)
13  * to third parties provided that the copyright notice and this statement
14  * appears on all copies and that no charge is associated with such copies.
15  *
16  * Licensee may make derivative works.  However, if Licensee distributes
17  * any derivative work based on or derived from the Software, then
18  * Licensee will:
19  * (1) notify AS regarding its distribution of the derivative work, and
20  * (2) clearly notify users that such derivative work is a modified version
21  *      and not the original ASEDIT distributed by AS.
22  *
23  * Any Licensee wishing to make commercial use of the Software should
24  * contact AS to negotiate an appropriate license for such commercial use.
25  * Commercial use includes:
26  * (1) integration of all or part of the source code into a product for sale
27  *     or license by or on behalf of Licensee to third parties, or
28  * (2) distribution of the binary code or source code to third parties that
29  *     need it to utilize a commercial product sold or licensed by or on
30  *     behalf of Licensee.
31  *
32  * A. STOCHNIOL MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS
33  * SOFTWARE FOR ANY PURPOSE.  IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR
34  * IMPLIED WARRANTY.  IN NO EVENT SHALL A. STOCHNIOL BE LIABLE FOR ANY
35  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
36  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
37  * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
38  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
39  *
40  * By using or copying this Software, Licensee agrees to abide by the
41  * copyright law and all other applicable laws, and the terms of this
42  * license.
43  * AS shall have the right to terminate this license immediately by
44  * written notice upon Licensee's breach of, or non-compliance with, any
45  * of its terms.  Licensee may be held legally responsible for any
46  * copyright infringement that is caused or encouraged by Licensee's
47  * failure to abide by the terms of this license.
48  *
49  *
50  * 	Andrzej Stochniol	(A.Stochniol@ic.ac.uk)
51  * 	30 Hatch Road
52  * 	London SW16 4PN
53  * 	UK
54  */
55 
56 #include <stdio.h>
57 #include <string.h>
58 #include <sys/types.h>
59 #include <sys/stat.h>
60 
61 #include <Xm/Text.h>
62 
63 #include "asedit.h"
64 
65 
66 #ifdef _NO_PROTO
open_file_in_last_window(filename)67 void open_file_in_last_window(filename)
68     char *filename;
69 #else  /* ! _NO_PROTO */
70 
71 void open_file_in_last_window(char *filename)
72 #endif
73 {
74     /* opens the specified file in the asedit last window or the default
75        file (when filename is NULL)
76     */
77     char            *work;          /* work string */
78     char            *error_open;
79     int len;
80     static int      as_def_names_count = 0;	/* counter for default names */
81 
82     if(filename != NULL && (len=strlen(filename)) )
83     {
84 	 asedit_last_window->filename = XtMalloc(len+1);
85 	 strcpy(asedit_last_window->filename, filename);
86     }
87     else
88     {
89 	 /* use the default name .... */
90 	 char *NoName = (char *)lstr.noname;
91 	 if(aseditWinCount == 1) as_def_names_count = 0;	/* reset the counter
92 							when all windows were closed */
93 	 as_def_names_count ++;		/* increase the counter */
94 	 len = strlen(NoName) + 5;
95 	 asedit_last_window->filename = XtMalloc(len);
96 	 sprintf(asedit_last_window->filename,"%s%d", NoName ,as_def_names_count);
97 
98     }
99     /* open file; if file can't be opened or created (e.g. irregular)
100        show message and set name to NULL;  if file exists
101        open it, if does not but can be created  set the empty text */
102     if (!OpenFile(asedit_last_window, False))   /* OpenFile is called with
103 					only_existing_files = False */
104     {
105 	error_open = (char *)lstr.fm_unable_to_open;
106 	work = XtMalloc(strlen(error_open) + strlen(asedit_last_window->filename) +1);
107 	/***** pre 1.3 version (did not care for German syntax)
108 	    strcpy(work, error_open);
109 	    strcat(work, asedit_last_window->filename);
110 	***** pre 1.3 version */
111 	sprintf(work, error_open, asedit_last_window->filename);
112 	show_error_message(asedit_last_window, work);
113 	XtFree(asedit_last_window->filename);   asedit_last_window->filename = NULL;
114 	XtFree(work);
115     }
116 
117 }   /* open_file_in_last_window */
118 
119 
120 
121 /*****************************	OpenFile  ************************************
122 **
123 **	Calls ReadFile to read the file. Returns true if file
124 ** 	exists and open is sucessful (for only_existing_files).
125 **	Parameter only_existing_files gives a way of using this
126 **	procedure for both file options: Load (only_existing_files=True)
127 **	and New (only_existing_files parameter should be False).
128 **	Adds file contents to the
129 **	appropriate widget, makes appropriate items sensitive etc.
130 **	Calls a procedure to set the title ot the main window (toplevel widget)
131 **      and the icon name.
132 */
133 #ifdef _NO_PROTO
OpenFile(win,only_existing_files)134 Boolean OpenFile(win, only_existing_files)
135    aseditWindowStruct *win;
136    Boolean only_existing_files;
137 #else  /* ! _NO_PROTO */
138 
139 Boolean OpenFile(aseditWindowStruct *win, Boolean only_existing_files)
140 #endif
141 {
142    char * file_string=NULL;	/* Contents of file. 	  */
143    Boolean         read_only;		/* shows the file read only status */
144    register int ac;			/* arg count		    */
145    Arg al[10];				/* widget arg list	    */
146    int i;
147 
148    /* make sure the file is a regular text file (if not return False
149       immediately)*/
150    if(!isFileRegular(win->filename))
151    {
152 	/* first set the read only colour (we do that here to avoid flashing the background colour
153 	   in a healthy situation*/
154 	ac = 0;
155 	XtSetArg(al[ac], XmNbackground, text_read_only_background); ac++;/* set the read only colour */
156 	XtSetValues(win->edit_text1, al, ac);
157 
158 	return(False);
159    }
160 
161    if( (file_string = ReadFile(win->filename, &read_only)) != NULL  ||
162 		!only_existing_files)
163    {
164 	   /***win->file_read_only = read_only; SEPT */
165 	   if(read_only) win->file_read_only = read_only;	/* 30 SEPT late change */
166 
167 	   /**** SEPT version
168 	   if(!read_only)
169 	   {
170 	       |* file was read/write; check if the user hasn't requested
171 		  only view mode; if so set it to read only mode
172 	       *|
173 	       if(win->view_only_toggle!= NULL)		|* safety check *|
174 	       {
175 		   if(XmToggleButtonGetState(win->view_only_toggle))
176 				win->file_read_only = True;
177 	       }
178 	   }
179 	   ***** SEPT version ***/
180 
181 
182 	   ac = 0;
183 	   XtSetArg(al[ac], XmNeditable, !win->file_read_only); ac++; /* if file is read only
184 						editable is set to False & vice versa */
185 	   /* set appropriate colour for the text widget to distinguish between
186 	      editable and read-only files */
187 	   if(win->file_read_only) XtSetArg(al[ac], XmNbackground, text_read_only_background);
188 	   else		      XtSetArg(al[ac], XmNbackground, text_edit_background);
189 	   ac++;
190 	   XtSetArg(al[ac], XmNsensitive, True);	ac++;	/* make text sensitive */
191 	   XtSetValues(win->edit_text1, al, ac);
192 
193 	   /* hack for Motif 1.2: when the string for the text widget is NULL text modify callback
194 	      is not generated; in that case we don't set the flag file_just_loaded;
195 	      if we do we lose the first action during editing !!!!
196 	   */
197 	   if(file_string != NULL && strlen(file_string))
198 					win->file_just_loaded = True;	/* reset the just loaded flag */
199 	   else				win->file_just_loaded = False;
200 
201 
202 
203 	   /* we have to use XmTextSetString to set the string; when I use
204 	      XtSetArg(al[ac], XmNvalue, (char *) file_string); etc... it does not
205 	      work properly when file_string was empty and the rest was the same
206 	      probably;  it does not work occasionally during loading of a file (comments
207 	      from Kennan (i.e. the there is an inconsistent behaviour );
208 	   ****/
209 	   XmTextSetString(win->edit_text, (char *)file_string);  /* add the file string to the text widget */
210 
211 
212 	   /* free the memory associated with the file_string */
213 	   if(file_string != NULL) XtFree(file_string);
214 
215 	   /* reinitialize the changes counter, reset undo/redo stacks */
216 	   win->changes_counter = 0L;
217 	   reset_undo_redo(win);
218 	   /* write appropriate info into changes_status widget */
219 	   if(!win->file_read_only)   write_ls(win->changes_status, charset, "%s", " ");
220 	   else 		 write_ls(win->changes_status, charset, "%s",
221 						(char *)lstr.read_only_marker);
222 
223 	   /* make undo/redo buttons insensitive */
224 	   XtSetSensitive(win->menu_undo_button,  False);
225 	   XtSetSensitive(win->menu_redo_button,  False);
226 	   XFlush(display);		/* make sure that these buttons are
227 					   insensitive before processing any keyboard
228 					   actions (for very busy systems)*/
229 
230 
231 
232 	   /* make appropriate items sensitive */
233 	   XtSetSensitive(win->menu_copy_button, True);
234 	   /* set the sensitivity of tools buttons */
235 	   for (i=0; i < win->nToolsSelNeeded; i++)
236 		XtSetSensitive(win->toolsSelNeeded[i], True);
237 
238 	   /* set the sensitivity of buttons dependend only on read_only
239 	      status of the file (cut button, clear button, replace button)
240 	   */
241 	   if(!win->file_read_only)
242 	   {
243 		XtSetSensitive(win->menu_cut_button, 	True);
244 		XtSetSensitive(win->menu_clear_button, 	True);
245 		XtSetSensitive(win->menu_replace_button, 	True);
246 		XtSetSensitive(win->menu_insert_button, 	True);
247 	   }
248 	   else
249 	   {
250 		XtSetSensitive(win->menu_cut_button, 	False);
251 		XtSetSensitive(win->menu_clear_button, 	False);
252 		XtSetSensitive(win->menu_replace_button, 	False);
253 		XtSetSensitive(win->menu_insert_button, 	False);
254 	   }
255 	   /* set the sensitivity of the paste buttons */
256 	   if(!win->file_read_only && clipboard_filled)
257 	   {
258 		XtSetSensitive(win->menu_paste_button, True);
259 		XtSetSensitive(win->popup_paste_button, True);
260 	   }
261 	   else
262 	   {
263 	   	XtSetSensitive(win->menu_paste_button, False);
264 	   	XtSetSensitive(win->popup_paste_button, False);
265 	   }
266 
267 
268 
269 	   /* set appropriate file buttons to sensitive */
270 	   XtSetSensitive(win->menu_close_button,	True);
271 	   XtSetSensitive(win->menu_save_as_button, 	True);
272 	   XtSetSensitive(win->menu_print_button,	True);
273 	   /* menu_save_button will be insensitive for read only files .... */
274 	   if(!win->file_read_only)
275 	   {
276 		XtSetSensitive(win->menu_save_button,  True);
277 		XtSetSensitive(win->popup_save_button, True);
278 	   }
279 	   else
280 	   {
281 		XtSetSensitive(win->menu_save_button,  False);
282 		XtSetSensitive(win->popup_save_button, False);
283 	   }
284 
285 
286 	   /* set appropriate search buttons to sensitive */
287 	   XtSetSensitive(win->menu_find_button,         True);
288 	   XtSetSensitive(win->menu_gotoline_button,     True);
289 	   XtSetSensitive(win->menu_mark_button,         True);
290 	   XtSetSensitive(win->menu_match_button,        True);
291 
292 	   XtSetSensitive(win->menu_find_again_button,   True);
293 
294 	   XtSetSensitive(win->menu_spell_button,        True);
295 	   XtSetSensitive(win->menu_commands_button,     True);
296 
297 	   /* setting a new title of the main window and the icon name.
298 	       They include the name of the file just opened */
299 	   set_titles_mwindow_icon(win, win->filename, NULL);
300 	   return(True);
301    }
302    else
303    {
304 	   /* setting a new title (name of the program only) */
305 	   set_titles_mwindow_icon(win, NULL, NULL);
306 	   return(False);
307    }
308 
309 }  /* OpenFile */
310 
311 
312 
313 
314 /*****************************  SaveFile  ************************************
315 **  	Save the currently edited file.
316 */
317 #ifdef _NO_PROTO
SaveFile(win)318 Boolean SaveFile(win)
319 aseditWindowStruct *win;
320 #else  /* ! _NO_PROTO */
321 
322 Boolean SaveFile(aseditWindowStruct *win)
323 #endif
324 {
325     char * file_string = NULL;	   /* Contents of file.		      */
326     Boolean	    result;
327 
328 
329     /* get the text string */
330     file_string = XmTextGetString(win->edit_text);
331 
332 
333     result = WriteFile(win->filename, file_string);
334 
335     if (file_string != NULL)  XtFree(file_string); /* free the text string */
336 
337     if(result)
338     {
339 	win->changes_counter = 0L;
340 	write_ls(win->changes_status, charset, "%s", " ");
341 	set_titles_mwindow_icon(win, win->filename, NULL);
342 	return(True);
343     }
344     else return(False);
345 
346 }   /* SaveFile */
347 
348 
349 /*****************************  ResetAllMarks  ***********************************
350 **
351 **  	Reset all bookmarks and set the appropriate buttons to insensitive
352 */
353 #ifdef _NO_PROTO
ResetAllMarks(win)354 void ResetAllMarks(win)
355 aseditWindowStruct *win;
356 #else  /* ! _NO_PROTO */
357 
358 void ResetAllMarks(aseditWindowStruct *win)
359 #endif
360 {
361     int i, nmarks = TOTAL_MARKS;
362     /* we should really get the number of marks from the size of the appropriate
363        pulldown !!
364     */
365 
366     for(i=0; i<nmarks; i++)
367     {
368 	win->marks_used  = False;
369 	win->mark_set[i] = False;
370 	win->mark_pos[i] = 0;
371 	XtSetSensitive(win->menu_mark_go_button[i], False);
372     }
373 
374 }   /*  ResetAllMarks */
375 
376 
377 /*****************************  CloseFile  ***********************************
378 **
379 **  	Close the present file. Set sensitivity of appropriate menu items.
380 */
381 #ifdef _NO_PROTO
CloseFile(win)382 void CloseFile(win)
383 aseditWindowStruct *win;
384 #else  /* ! _NO_PROTO */
385 
386 void CloseFile(aseditWindowStruct *win)
387 #endif
388 {
389     /* zero out the text string in the text widget.
390        Warning: it causes a value changed callback. */
391     Arg al[5];
392     register int ac;
393     int i;
394 
395     /* check if it is not called for a file already closed  */
396     if (win->filename == NULL) return;		/* probable sequence was: File|Close, File|Exit */
397 
398 
399     /* we use Motif convenience function  to zero out the text instead of setting the resources in one
400        go  i.e. using additionally XtSetArg(al[ac], XmNvalue , "");  ac++; because we have some problems
401        with the other method in the ReadFile procedure; so to be on a safe side .... */
402     /* to avoid getting the flashing title (Changed) set the following */
403     win->file_just_loaded = True;
404     XmTextSetString(win->edit_text1, "");
405 
406 
407     ac = 0;
408     XtSetArg(al[ac], XmNsensitive, False);	ac++;	/* set text to insensitive */
409     /* set the colour of the text background to read only colour */
410     XtSetArg(al[ac], XmNbackground, text_read_only_background);	ac++;
411     XtSetValues(win->edit_text1, al, ac);
412 
413 
414     /* reinitialize the changes counter, reset redo/undo stacks */
415     win->changes_counter = 0L;  write_ls(win->changes_status, charset, "%s", " ");
416     reset_undo_redo(win);
417 
418 
419     /* free the file name */
420     if (win->filename != NULL) { XtFree(win->filename);	win->filename = NULL; }
421 
422     /* blank the line & column number display  */
423     write_ls(win->line_number,   charset, "%s", "     ");
424     write_ls(win->column_number, charset, "%s", "    ");
425 
426     /* unmanage replace_dialog & save_as_dialog if they are active (they
427        may be on the screen and they do not make any sense when no file is open) */
428     if(win->replace_dialog != NULL) XtUnmanageChild( win->replace_dialog );
429     if(win->save_as_dialog != NULL) XtUnmanageChild( win->save_as_dialog );
430 
431 
432     /* set appropriate file buttons to insensitive */
433     XtSetSensitive(win->menu_close_button,   False);
434     XtSetSensitive(win->menu_save_button,    False);
435     XtSetSensitive(win->menu_save_as_button, False);
436     XtSetSensitive(win->menu_insert_button,  False);
437     XtSetSensitive(win->menu_print_button,   False);
438 
439     XtSetSensitive(win->menu_undo_button,  False);
440     XtSetSensitive(win->menu_redo_button,  False);
441     XtSetSensitive(win->menu_cut_button,   False);
442     XtSetSensitive(win->menu_copy_button,  False);
443     XtSetSensitive(win->menu_paste_button, False);
444     XtSetSensitive(win->menu_clear_button, False);
445 
446     XtSetSensitive(win->menu_find_button,         False);
447     XtSetSensitive(win->menu_replace_button,      False);
448     XtSetSensitive(win->menu_find_again_button,   False);
449     XtSetSensitive(win->menu_gotoline_button,     False);
450     XtSetSensitive(win->menu_mark_button,     False);
451     XtSetSensitive(win->menu_match_button,    False);
452 
453     XtSetSensitive(win->popup_undo_button,   False);
454     XtSetSensitive(win->popup_cut_button,    False);
455     XtSetSensitive(win->popup_copy_button,   False);
456     XtSetSensitive(win->popup_paste_button,  False);
457     XtSetSensitive(win->popup_save_button,   False);
458 
459     /* set the sensitivity of tools buttons */
460     for (i=0; i < win->nToolsSelNeeded; i++)
461 	XtSetSensitive(win->toolsSelNeeded[i], False);
462 
463     XtSetSensitive(win->menu_spell_button,    False);
464     XtSetSensitive(win->menu_commands_button, False);
465 
466 
467     /* setting a new title of the main window (name of the program only) */
468     set_titles_mwindow_icon(win, NULL, NULL);
469 
470     /* reset all bookmarks */
471     ResetAllMarks(win);
472 
473 }   /* CloseFile */
474 
475 
476 /*****************************  InsertFile  ************************************
477 **
478 **      Inserts the specified file into the current edit_text widget.
479 **      Calls ReadFile to read the file. Returns true if file
480 **      exists and insert is sucessful.
481 */
482 #ifdef _NO_PROTO
InsertFile(win,filename)483 Boolean InsertFile(win, filename)
484    aseditWindowStruct *win;
485    char *filename;
486 #else  /* ! _NO_PROTO */
487 
488 Boolean InsertFile(aseditWindowStruct *win, char *filename)
489 #endif
490 {
491    char * file_string=NULL;     /* Contents of file.      */
492    Boolean         read_only;           /* shows the file read only status */
493    register int ac;                     /* arg count                */
494    Arg al[10];                          /* widget arg list          */
495 
496    if( (file_string = ReadFile(filename, &read_only)) != NULL)
497    {
498 	return(True);
499    }
500    else
501    {
502 	   return(False);
503    }
504 
505 }  /* InsertFile */
506 
507 
508 
509 /*** old: #ifdef M_LANG_STD ***/
510 
511 /****************************  PrintString  **********************************
512         PrintString  - prints a text pointed to by *text_string using *print_command
513         (If successful returns True.)
514 */
515 #ifdef _NO_PROTO
PrintString(text_string,print_command)516 Boolean PrintString(text_string, print_command)
517     char *text_string;
518     char *print_command;
519 #else  /* _NO_PROTO */
520 
521 Boolean PrintString(char *text_string, char *print_command)
522 #endif
523 {
524     FILE *tfp;                          /* Pointer to a temporary file. */
525     char work[256];
526     Boolean result=True;
527     int status;
528     char system_call_buf[BUFSIZ];
529     char *tempname;     /* Temporary file name .*/
530 
531     /* Note: errors here related to file operations shouldn't really happen, so
532        just to simplify we leave them in English and write them out on stderr
533        (they might happen when the temp dir is full, tmpDir (X) or TEMPDIR is set
534         incorrectly etc.)
535     */
536 
537     if(text_string == NULL || print_command == NULL) return(False);
538 
539     tempname = make_tmpnam();   /* use tmpnam function and consider tmpDir X resource
540                                    or TMPDIR environmental variable (if set) */
541 
542     if ((tfp = fopen(tempname, "w")) == NULL) {
543        fprintf(stderr, (char *)lstr.open_tmp_print_err, tempname);
544        XtFree(tempname);
545        return(False);
546     }
547     /* write to a temp file */
548     fwrite(text_string, sizeof(char), strlen(text_string) , tfp);
549 
550     /* flush and close the file (note that if we are unlucky we use in both
551        cases the same error message saying we are unable to close the file;
552        the flush error is very unlikely here) */
553 
554     if (fflush(tfp))
555         { result=False;  fprintf(stderr,(char *)lstr.close_tmp_err,tempname); }
556 
557     if (fclose(tfp))
558         { result=False;  fprintf(stderr,(char *)lstr.close_tmp_err,tempname); }
559 
560 
561     if(!result) { unlink(tempname); XtFree(tempname); return(result); }
562 
563 
564 #ifndef vax11c
565     sprintf(work, "cat %s | %s", tempname, print_command);
566 #else
567     /* VMS doesn't allow for I/O redirection at all (It's one major handicap).
568        So let's setup the print command to just print the file.
569     */
570     sprintf(work, "%s %s", print_command, tempname);
571 #endif /* !vax11c */
572 
573 #if defined(vax11c) || defined(__DECC)
574     if (!(system(work)&1))  result=False;
575 #else
576     if (system(work))  result=False;
577 #endif /* vax11c */
578 
579     unlink (tempname);
580     XtFree (tempname);
581 
582     return(result);
583 
584 }   /* PrintString */
585 
586 
587