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