2 * ========================================================================
3 * Copyright 2006-2007 University of Washington
4 * Copyright 2013-2022 Eduardo Chappa
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * ========================================================================
14 * Program: High level file input and output routines
19 * The routines in this file
20 * handle the reading and writing of
21 * disk files. All of details about the
22 * reading and writing of the disk are
26 #include "../pith/charconv/filesys.h"
29 void init_insmsgchar_cbuf(void);
31 char *file_split(char *, size_t, char *, int);
34 * Read a file into the current
35 * buffer. This is really easy; all you do it
36 * find the name of the file, and call the standard
37 * "read a file into the current buffer" code.
41 fileread(int f
, int n
)
47 if ((s
=mlreply_utf8(_("Read file: "), fname
, NFILEN
, QNORML
, NULL
)) != TRUE
)
51 emlwrite(_("File reading disabled in secure mode"),NULL
);
55 if (strlen(fname
) == 0) {
56 emlwrite(_("No file name entered"),NULL
);
60 if((gmode
& MDTREE
) && !in_oper_tree(fname
)){
62 emlwrite(_("Can't read file from outside of %s"), &eml
);
66 return(readin(fname
, TRUE
, TRUE
));
71 static char *inshelptext
[] = {
72 /* TRANSLATORS: several lines of help text */
73 N_("Insert File Help Text"),
75 N_(" Type in a file name to have it inserted into your editing"),
76 N_(" buffer between the line that the cursor is currently on"),
77 N_(" and the line directly below it. You may abort this by "),
78 N_("~ typing the ~F~2 (~^~C) key after exiting help."),
80 N_("End of Insert File Help"),
85 static char *writehelp
[] = {
86 /* TRANSLATORS: several lines of help text */
87 N_("Write File Help Text"),
89 N_(" Type in a file name to have it written out, thus saving"),
90 N_(" your buffer, to a file. You can abort this by typing "),
91 N_("~ the ~F~2 (~^~C) key after exiting help."),
93 N_("End of Write File Help"),
101 * Insert a file into the current
102 * buffer. This is really easy; all you do it
103 * find the name of the file, and call the standard
104 * "insert a file into the current buffer" code.
105 * Bound to "C-X C-I".
108 insfile(int f
, int n
)
111 char fname
[NLINE
], dir
[NLINE
];
112 int retval
= 0, bye
= 0, msg
= 0;
113 char prompt
[64], *infile
;
114 EXTRAKEYS menu_ins
[10];
117 if (curbp
->b_mode
&MDVIEW
) /* don't allow this command if */
118 return(rdonly()); /* we are in read only mode */
120 memset(&menu_ins
, 0, 10*sizeof(EXTRAKEYS
));
121 fname
[0] = dir
[0] = '\0';
123 /* set up keymenu stuff */
127 menu_ins
[last_menu
].name
= "^T";
128 menu_ins
[last_menu
].key
= (CTRL
|'T');
129 menu_ins
[last_menu
].label
= N_("To Files");
130 KS_OSDATASET(&menu_ins
[last_menu
], KS_NONE
);
132 if(Pmaster
&& Pmaster
->msgntext
){
133 menu_ins
[++last_menu
].name
= "^W";
134 menu_ins
[last_menu
].key
= (CTRL
|'W');
135 /* TRANSLATORS: Insert File is a key label for a command
136 that inserts a file into a message being composed.
137 InsertMsg means Insert Message and it inserts a different
138 message into the message being composed. */
139 menu_ins
[last_menu
].label
= msg
? N_("InsertFile") : N_("InsertMsg");
140 KS_OSDATASET(&menu_ins
[last_menu
], KS_NONE
);
143 #if !defined(DOS) && !defined(MAC)
144 if(Pmaster
&& Pmaster
->upload
){
145 menu_ins
[++last_menu
].name
= "^Y";
146 menu_ins
[last_menu
].key
= (CTRL
|'Y');
147 menu_ins
[last_menu
].label
= "RcvUpload";
148 KS_OSDATASET(&menu_ins
[last_menu
], KS_NONE
);
150 #endif /* !(DOS || MAC) */
153 menu_ins
[++last_menu
].name
= msg
? "" : "TAB";
154 menu_ins
[last_menu
].key
= (CTRL
|'I');
155 menu_ins
[last_menu
].label
= msg
? "" : N_("Complete");
156 KS_OSDATASET(&menu_ins
[last_menu
], KS_NONE
);
159 menu_ins
[++last_menu
].name
= NULL
;
162 snprintf(prompt
, sizeof(prompt
), "%s to insert from %s %s: ",
163 msg
? "Number of message" : "File",
164 (msg
|| (gmode
&MDCURDIR
))
166 : ((gmode
& MDTREE
) || opertree
[0]) ? opertree
: "home",
167 msg
? "folder" : "directory");
168 s
= mlreplyd_utf8(prompt
, fname
, NLINE
, QDEFLT
, msg
? NULL
: menu_ins
);
169 /* something to read and it was edited or the default accepted */
170 if(fname
[0] && (s
== TRUE
|| s
== FALSE
)){
173 init_insmsgchar_cbuf();
174 if((*Pmaster
->msgntext
)(atol(fname
), insmsgchar
)){
176 emlwrite(_("Message %s included"), &eml
);
182 emlwrite(_("Can't insert file in restricted mode"),NULL
);
186 && !compresspath(opertree
, fname
, sizeof(fname
))){
189 _("Can't insert file from outside of %s: too many ..'s"), &eml
);
192 fixpath(fname
, sizeof(fname
));
194 if((gmode
& MDTREE
) && !in_oper_tree(fname
)){
196 emlwrite(_("Can't insert file from outside of %s"), &eml
);
199 retval
= ifile(fname
);
211 fn
= file_split(dir
, sizeof(dir
), fname
, 0);
213 if(!pico_fncomplete(dir
, fn
, sizeof(fname
)-(fn
-fname
)))
219 msg
= !msg
; /* toggle what to insert */
223 emlwrite(_("Can't select messages yet!"), NULL
);
228 fn
= file_split(dir
, sizeof(dir
), fname
, 1);
229 if(!isdir(dir
, NULL
, NULL
)){
230 strncpy(dir
, (gmode
&MDCURDIR
)
231 ? (browse_dir
[0] ? browse_dir
: ".")
232 : ((gmode
& MDTREE
) || opertree
[0])
234 : (browse_dir
[0] ? browse_dir
235 :gethomedir(NULL
)), sizeof(dir
));
236 dir
[sizeof(dir
)-1] = '\0';
242 dirlen
= strlen(dir
);
243 if(dirlen
&& dir
[dirlen
- 1] != C_FILESEP
){
244 strncat(dir
, S_FILESEP
, sizeof(dir
)-strlen(dir
)-1);
245 dir
[sizeof(dir
)-1] = '\0';
248 strncat(dir
, fn
, sizeof(dir
)-strlen(dir
)-1);
249 dir
[sizeof(dir
)-1] = '\0';
250 if(!isdir(dir
, NULL
, NULL
))
251 dir
[MIN(dirlen
,sizeof(dir
)-1)] = '\0';
256 if((s
= FileBrowse(dir
, sizeof(dir
), fname
, sizeof(fname
),
257 NULL
, 0, FB_READ
, NULL
)) == 1){
259 emlwrite(_("Can't insert in restricted mode"),
266 len
= strlen(dir
)+strlen(S_FILESEP
)+strlen(fname
);
267 if ((infile
= (char *)malloc((len
+1)*sizeof(char))) != NULL
){
268 strncpy(infile
, dir
, len
);
270 strncat(infile
, S_FILESEP
, len
+1-1-strlen(infile
));
272 strncat(infile
, fname
, len
+1-1-strlen(infile
));
274 retval
= ifile(infile
);
275 free((char *) infile
);
278 emlwrite("Trouble allocating space for insert!"
288 pico_refresh(FALSE
, 1);
290 update(); /* redraw on return */
297 #if !defined(DOS) && !defined(MAC)
299 if(Pmaster
&& Pmaster
->upload
){
304 _("Restricted mode disallows uploaded command"),
310 retval
= (*Pmaster
->upload
)(tfname
, sizeof(tfname
), NULL
);
312 pico_refresh(FALSE
, 1);
316 retval
= ifile(tfname
);
320 sleep(3); /* problem, show error! */
322 if(tfname
[0]) /* clean up temp file */
326 (*term
.t_beep
)(); /* what? */
329 #endif /* !(DOS || MAC) */
332 VARS_TO_SAVE
*saved_state
;
334 saved_state
= save_pico_state();
335 (*Pmaster
->helper
)(msg
? Pmaster
->ins_m_help
337 _("Help for Insert File"), 1);
339 restore_pico_state(saved_state
);
340 free_pico_state(saved_state
);
344 pico_help(inshelptext
, _("Help for Insert File"), 1);
346 pico_refresh(FALSE
, 1);
356 curwp
->w_flag
|= WFMODE
|WFHARD
;
362 * split out the file name from the path.
363 * Copy path into dirbuf, return filename,
364 * which is a pointer into orig_fname.
365 * is_for_browse - use browse dir if possible
366 * don't want to use it for TAB-completion
369 file_split(char *dirbuf
, size_t dirbuflen
, char *orig_fname
, int is_for_browse
)
374 if(*orig_fname
&& (p
= strrchr(orig_fname
, C_FILESEP
))){
376 dirlen
= p
- orig_fname
;
378 strncpy(dirbuf
, S_FILESEP
, dirbuflen
);
379 dirbuf
[dirbuflen
-1] = '\0';
382 else if(orig_fname
[0] == C_FILESEP
383 || (isalpha((unsigned char)orig_fname
[0])
384 && orig_fname
[1] == ':')){
385 if(orig_fname
[1] == ':' && p
== orig_fname
+2)
386 dirlen
= fn
- orig_fname
;
388 dirlen
= MIN(dirlen
, dirbuflen
-1);
389 strncpy(dirbuf
, orig_fname
, dirlen
);
390 dirbuf
[dirlen
] = '\0';
393 else if (orig_fname
[0] == C_FILESEP
|| orig_fname
[0] == '~'){
394 dirlen
= MIN(dirlen
, dirbuflen
-1);
395 strncpy(dirbuf
, orig_fname
, dirlen
);
396 dirbuf
[dirlen
] = '\0';
400 snprintf(dirbuf
, dirbuflen
, "%s%c%.*s",
402 ? ((is_for_browse
&& browse_dir
[0]) ? browse_dir
: ".")
403 : ((gmode
& MDTREE
) || opertree
[0])
405 : ((is_for_browse
&& browse_dir
[0])
406 ? browse_dir
: gethomedir(NULL
)),
407 C_FILESEP
, (int) (p
- orig_fname
), orig_fname
);
411 strncpy(dirbuf
, (gmode
& MDCURDIR
)
412 ? ((is_for_browse
&& browse_dir
[0]) ? browse_dir
: ".")
413 : ((gmode
& MDTREE
) || opertree
[0])
415 : ((is_for_browse
&& browse_dir
[0])
416 ? browse_dir
: gethomedir(NULL
)), dirbuflen
);
417 dirbuf
[dirbuflen
-1] = '\0';
424 static CBUF_S insmsgchar_cb
;
427 init_insmsgchar_cbuf(void)
429 insmsgchar_cb
.cbuf
[0] = '\0';
430 insmsgchar_cb
.cbufp
= insmsgchar_cb
.cbuf
;
431 insmsgchar_cb
.cbufend
= insmsgchar_cb
.cbuf
;
436 * This is called with a stream of UTF-8 characters.
437 * We change that stream into UCS characters and insert
447 for(u
= glo_quote_str
; u
&& *u
; u
++)
451 else if(c
!= '\r'){ /* ignore CR (likely CR of CRLF) */
455 if((outchars
= utf8_to_ucs4_oneatatime(c
, &insmsgchar_cb
, &ucs
, NULL
)) != 0)
465 * Read file "fname" into the current
466 * buffer, blowing away any text found there. Called
467 * by both the read and find commands. Return the final
468 * status of the read. Also called by the mainline,
469 * to read in a file specified on the command line as
473 readin(char fname
[], /* name of file to read */
474 int lockfl
, /* check for file locks? */
475 int rename
) /* don't rename if reading from, say, alt speller */
477 UCS line
[NLINE
], *linep
;
479 int s
, done
, newline
;
481 curbp
->b_linecnt
= -1; /* Must be recalculated */
482 if ((s
= bclear(curbp
)) != TRUE
) /* Might be old. */
486 strncpy(curbp
->b_fname
, fname
, sizeof(curbp
->b_fname
));
487 curbp
->b_fname
[sizeof(curbp
->b_fname
)-1] = '\0';
490 if ((s
=ffropen(fname
)) != FIOSUC
){ /* Hard file open. */
491 if(s
== FIOFNF
) /* File not found. */
492 emlwrite(_("New file"), NULL
);
497 size_t charsread
= 0;
499 emlwrite(_("Reading file"), NULL
);
503 if((s
= ffgetline(line
, NLINE
, &charsread
, 1)) == FIOEOF
){
506 curbp
->b_flag
&= ~(BFTEMP
|BFCHG
);
509 snprintf(b
, sizeof(b
), _("Read %ld lines"), nline
);
511 snprintf(b
, sizeof(b
), _("Read 1 line"));
519 if(lnewline() == FALSE
){
532 for(linep
= line
; charsread
-- > 0; linep
++)
533 if(linsert(1, *linep
) == FALSE
) done
++;
543 ffclose(); /* Ignore errors. */
546 return(s
!= FIOERR
&& s
!= FIOFNF
); /* true if success */
551 * Ask for a file name, and write the
552 * contents of the current buffer to that file.
553 * Update the remembered file name and clear the
554 * buffer changed flag. This handling of file names
555 * is different from the earlier versions, and
556 * is more compatible with Gosling EMACS than
557 * with ITS EMACS. Bound to "C-X C-W".
560 filewrite(int f
, int n
)
565 char shows
[NLINE
], origshows
[NLINE
], *bufp
;
566 EXTRAKEYS menu_write
[10];
569 memset(&menu_write
, 0, 10*sizeof(EXTRAKEYS
));
570 if(curbp
->b_fname
[0] != 0){
571 strncpy(fname
, curbp
->b_fname
, sizeof(curbp
->b_fname
));
572 curbp
->b_fname
[sizeof(curbp
->b_fname
)-1] = '\0';
577 menu_write
[0].name
= "^T";
578 menu_write
[0].label
= N_("To Files");
579 menu_write
[0].key
= (CTRL
|'T');
580 menu_write
[1].name
= "TAB";
581 menu_write
[1].label
= N_("Complete");
582 menu_write
[1].key
= (CTRL
|'I');
583 menu_write
[2].name
= NULL
;
584 for(;!(gmode
& MDTOOL
);){
585 /* TRANSLATORS: Asking for name of file to write data into */
586 s
= mlreplyd_utf8(_("File Name to write : "), fname
, NFILEN
,
587 QDEFLT
|QFFILE
, menu_write
);
591 if(!fname
[0]){ /* no file name to write to */
596 if((gmode
& MDTREE
) && !compresspath(opertree
, fname
, sizeof(fname
))){
598 emlwrite(_("Can't write outside of %s: too many ..'s"), &eml
);
603 fixpath(fname
, sizeof(fname
)); /* fixup ~ in file name */
604 if((gmode
& MDTREE
) && !in_oper_tree(fname
)){
606 emlwrite(_("Can't write outside of %s"), &eml
);
616 char *fn
, *p
, dir
[NFILEN
];
620 if(*fname
&& (p
= strrchr(fname
, C_FILESEP
))){
624 strncpy(dir
, S_FILESEP
, sizeof(dir
));
625 dir
[sizeof(dir
)-1] = '\0';
628 else if(fname
[0] == C_FILESEP
629 || (isalpha((unsigned char)fname
[0])
632 else if (fname
[0] == C_FILESEP
|| fname
[0] == '~')
635 strncpy(dir
, fname
, MIN(p
- fname
, sizeof(dir
)-1));
636 dir
[MIN(p
-fname
, sizeof(dir
)-1)] = '\0';
639 snprintf(dir
, sizeof(dir
), "%s%c%.*s",
642 : ((gmode
& MDTREE
) || opertree
[0])
643 ? opertree
: gethomedir(NULL
),
644 C_FILESEP
, (int) (p
- fname
), fname
);
648 strncpy(dir
, (gmode
& MDCURDIR
)
650 : ((gmode
& MDTREE
) || opertree
[0])
651 ? opertree
: gethomedir(NULL
), sizeof(dir
));
652 dir
[sizeof(dir
)-1] = '\0';
655 if(!pico_fncomplete(dir
, fn
, sizeof(fname
)-(fn
-fname
)))
662 /* If we have a file name, break up into path and file name.*/
665 if(isdir(fname
, NULL
, NULL
)) {
666 /* fname is a directory. */
667 strncpy(shows
, fname
, sizeof(shows
));
668 shows
[sizeof(shows
)-1] = '\0';
672 /* Find right most separator. */
673 bufp
= strrchr (fname
, C_FILESEP
);
675 /* Copy directory part to 'shows', and file
676 * name part to front of 'fname'. */
678 strncpy(shows
, fname
, sizeof(shows
));
679 shows
[sizeof(shows
)-1] = '\0';
680 strncpy(fname
, bufp
+1, MIN(strlen(bufp
+1)+1, sizeof(fname
)));
681 fname
[sizeof(fname
)-1] = '\0';
686 /* If we did not end up with a valid directory, use home. */
687 if (!*shows
|| !isdir (shows
, NULL
, NULL
)){
688 strncpy(shows
, ((gmode
& MDTREE
) || opertree
[0])
690 : (browse_dir
[0] ? browse_dir
691 : gethomedir(NULL
)), sizeof(shows
));
692 shows
[sizeof(shows
)-1] = '\0';
695 strncpy(origshows
, shows
, sizeof(origshows
));
696 origshows
[sizeof(origshows
)-1] = '\0';
697 if ((s
= FileBrowse(shows
, sizeof(shows
), fname
, sizeof(fname
), NULL
, 0,
698 FB_SAVE
, NULL
)) == 1) {
699 if (strlen(shows
)+strlen(S_FILESEP
)+strlen(fname
) < NLINE
){
700 strncat(shows
, S_FILESEP
, sizeof(shows
)-strlen(shows
)-1);
701 shows
[sizeof(shows
)-1] = '\0';
702 strncat(shows
, fname
, sizeof(shows
)-strlen(shows
)-1);
703 shows
[sizeof(shows
)-1] = '\0';
704 strncpy(fname
, shows
, sizeof(fname
));
705 fname
[sizeof(fname
)-1] = '\0';
708 emlwrite("Cannot write. File name too long!!",NULL
);
712 else if (s
== 0 && strcmp(shows
, origshows
)){
713 strncat(shows
, S_FILESEP
, sizeof(shows
)-strlen(shows
)-1);
714 shows
[sizeof(shows
)-1] = '\0';
715 strncat(shows
, fname
, sizeof(shows
)-strlen(shows
)-1);
716 shows
[sizeof(shows
)-1] = '\0';
717 strncpy(fname
, shows
, sizeof(fname
));
718 fname
[sizeof(fname
)-1] = '\0';
721 emlwrite("Cannot write. File name too long!!",NULL
);
725 pico_refresh(FALSE
, 1);
733 pico_help(writehelp
, "", 1);
735 pico_refresh(FALSE
, 1);
744 if(strcmp(fname
, curbp
->b_fname
) == 0)
747 if((s
=fexist(fname
, "w", (off_t
*)NULL
)) == FIOSUC
){
748 /*exists overwrite? */
750 snprintf(shows
, sizeof(shows
), _("File \"%s\" exists, OVERWRITE"), fname
);
751 if((s
=mlyesno_utf8(shows
, FALSE
)) == TRUE
)
754 else if(s
== FIOFNF
){
755 break; /* go write it */
757 else{ /* some error, can't write */
763 emlwrite("Writing...", NULL
);
765 if ((s
=writeout(fname
, 0)) != -1) {
767 strncpy(curbp
->b_fname
, fname
, sizeof(curbp
->b_fname
));
768 curbp
->b_fname
[sizeof(curbp
->b_fname
)-1] = '\0';
769 curbp
->b_flag
&= ~BFCHG
;
771 wp
= wheadp
; /* Update mode lines. */
773 if (wp
->w_bufp
== curbp
)
774 if((Pmaster
&& s
== TRUE
) || Pmaster
== NULL
)
775 wp
->w_flag
|= WFMODE
;
782 emlwrite(_("Wrote %s lines"), &eml
);
785 emlwrite(_("Wrote 1 line"), NULL
);
788 return ((s
== -1) ? FALSE
: TRUE
);
793 * Save the contents of the current
794 * buffer in its associated file. No nothing
795 * if nothing has changed (this may be a bug, not a
796 * feature). Error if there is no remembered file
797 * name for the buffer. Bound to "C-X C-S". May
798 * get called by "C-Z".
801 filesave(int f
, int n
)
807 if (curbp
->b_mode
&MDVIEW
) /* don't allow this command if */
808 return(rdonly()); /* we are in read only mode */
809 if ((curbp
->b_flag
&BFCHG
) == 0) /* Return, no changes. */
811 if (curbp
->b_fname
[0] == 0) { /* Must have a name. */
812 emlwrite(_("No file name"), NULL
);
817 emlwrite("Writing...", NULL
);
818 if ((s
=writeout(curbp
->b_fname
, 0)) != -1) {
819 curbp
->b_flag
&= ~BFCHG
;
820 wp
= wheadp
; /* Update mode lines. */
822 if (wp
->w_bufp
== curbp
)
824 wp
->w_flag
|= WFMODE
;
829 emlwrite(_("Wrote %s lines"), &eml
);
832 emlwrite(_("Wrote 1 line"), NULL
);
839 * This function performs the details of file
840 * writing. Uses the file management routines in the
841 * "fileio.c" package. The number of lines written is
842 * displayed. Sadly, it looks inside a LINE; provide
843 * a macro for this. Most of the grief is error
844 * checking of some sort.
846 * If the argument readonly is set, the file is created with user read
847 * and write permission only if it doesn't already exist. Note that the
848 * word readonly is misleading. It is user r/w permission only.
850 * CHANGES: 1 Aug 91: returns number of lines written or -1 on error, MSS
853 writeout(char *fn
, int readonly
)
860 if (!((s
= ffwopen(fn
, readonly
)) == FIOSUC
&& ffelbowroom()))
861 return (-1); /* Open writes message. */
863 lp
= lforw(curbp
->b_linep
); /* First line. */
864 nline
= 0; /* Number of lines. */
865 while (lp
!= curbp
->b_linep
) {
866 if ((s
=ffputline(&lp
->l_text
[0], llength(lp
))) != FIOSUC
)
872 t
= ffclose(); /* ffclose complains if error */
875 s
= t
; /* report worst case */
877 return ((s
== FIOSUC
) ? nline
: -1);
882 * writetmp - write a temporary file for message text, mindful of
883 * access restrictions and included text. If n is true, include
884 * lines that indicated included message text, otw forget them
885 * If dir is non-null, put the temp file in that directory.
888 writetmp(int n
, char *dir
)
890 static char fn
[NFILEN
];
898 /* Open writes message */
899 if (!fn
[0] || (s
=ffwopen(fn
, TRUE
)) != FIOSUC
){
906 lp
= lforw(curbp
->b_linep
); /* First line. */
907 nline
= 0; /* Number of lines. */
908 while (lp
!= curbp
->b_linep
) {
909 if(n
|| (!n
&& lp
->l_text
[0].c
!= '>'))
910 if ((s
=ffputline(&lp
->l_text
[0], llength(lp
))) != FIOSUC
)
917 t
= ffclose(); /* ffclose complains if error */
920 s
= t
; /* remember worst case */
922 if (s
!= FIOSUC
){ /* Some sort of error. */
932 * Insert file "fname" into the current
933 * buffer, Called by insert file command. Return the final
934 * status of the read.
939 UCS line
[NLINE
], *linep
;
941 int s
, done
, newline
;
942 size_t charsread
= 0;
945 if ((s
=ffropen(fname
)) != FIOSUC
){ /* Hard file open. */
952 curbp
->b_flag
|= BFCHG
; /* we have changed */
953 curbp
->b_flag
&= ~BFTEMP
; /* and are not temporary*/
954 curbp
->b_linecnt
= -1; /* must be recalculated */
957 emlwrite(_("Inserting %s."), &eml
);
961 if((s
= ffgetline(line
, NLINE
, &charsread
, 1)) == FIOEOF
){
964 if(llength(curwp
->w_dotp
) > curwp
->w_doto
)
970 snprintf(b
, sizeof(b
), _("Inserted %ld lines"), nline
);
972 snprintf(b
, sizeof(b
), _("Inserted 1 line"));
979 if(lnewline() == FALSE
){
987 case FIOSUC
: /* copy line into buf */
992 for(linep
= line
; charsread
-- > 0; linep
++)
993 if(linsert(1, *linep
) == FALSE
) done
++;
1002 ffclose(); /* Ignore errors. */
1004 return(s
!= FIOERR
);
1009 * pico_fncomplete - pico's function to complete the given file name
1012 pico_fncomplete(char *dirarg
, char *fn
, size_t fnlen
)
1014 char *p
, *dlist
, tmp
[NLINE
], dir
[NLINE
];
1015 int n
, i
, match
= -1, orign
= 0;
1017 #define FILECMP(x, y) (toupper((unsigned char)(x))\
1018 == toupper((unsigned char)(y)))
1020 #define FILECMP(x, y) ((x) == (y))
1023 strncpy(dir
, dirarg
, sizeof(dir
));
1024 dir
[sizeof(dir
)-1] = '\0';
1025 pfnexpand(dir
, sizeof(dir
));
1026 if((dlist
= p
= getfnames(dir
, fn
, &n
, NULL
, 0))){
1028 memset(tmp
, 0, sizeof(tmp
));
1029 while(n
--){ /* any names in it */
1030 if(strcmp(p
, ".") == 0 || strcmp(p
, "..") == 0){
1036 for(i
= 0; i
< sizeof(tmp
)-1 && fn
[i
] && FILECMP(p
[i
], fn
[i
]); i
++)
1039 if(!fn
[i
]){ /* match or more? */
1041 for(; p
[i
] && FILECMP(p
[i
], tmp
[i
]); i
++)
1044 match
= !p
[i
] && !tmp
[i
];
1045 tmp
[i
] = '\0'; /* longest common string */
1048 match
= 1; /* may be it!?! */
1049 strncpy(tmp
, p
, sizeof(tmp
));
1050 tmp
[sizeof(tmp
)-1] = '\0';
1060 if(fn
[0] == '\0' && orign
!= 1)
1064 strncpy(fn
, tmp
, fnlen
);
1067 if ((strlen(dir
)+strlen(S_FILESEP
)+strlen(fn
)) < sizeof(dir
)){
1068 strncat(dir
, S_FILESEP
, sizeof(dir
)-strlen(dir
)-1);
1069 dir
[sizeof(dir
)-1] = '\0';
1070 strncat(dir
, fn
, sizeof(dir
)-strlen(dir
)-1);
1071 dir
[sizeof(dir
)-1] = '\0';
1072 if(isdir(dir
, NULL
, NULL
)){
1073 strncat(fn
, S_FILESEP
, fnlen
-strlen(fn
)-1);
1078 emlwrite("File name too BIG!!",0);
1091 * in_oper_tree - returns true if file "f" does reside in opertree
1094 in_oper_tree(char *f
)
1096 int end
= strlen(opertree
);
1098 return(!strncmp(opertree
, f
, end
)
1099 && (opertree
[end
-1] == '/'
1100 || opertree
[end
-1] == '\\'
1103 || f
[end
] == '\\'));