blob: c925775a9bfde991852d1970a59145e1fa03c2ff [file] [log] [blame]
Bram Moolenaar071d4272004-06-13 20:20:40 +00001/* vi:set ts=8 sts=4 sw=4:
2 *
3 * VIM - Vi IMproved by Bram Moolenaar
4 *
5 * Do ":help uganda" in Vim to read copying and usage conditions.
6 * Do ":help credits" in Vim to see a list of people who contributed.
7 * See README.txt for an overview of the Vim source code.
8 */
9
10/*
11 * fileio.c: read from and write to a file
12 */
13
14#if defined(MSDOS) || defined(WIN16) || defined(WIN32) || defined(_WIN64)
15# include <io.h> /* for lseek(), must be before vim.h */
16#endif
17
18#if defined __EMX__
19# include <io.h> /* for mktemp(), CJW 1997-12-03 */
20#endif
21
22#include "vim.h"
23
24#ifdef HAVE_FCNTL_H
25# include <fcntl.h>
26#endif
27
28#ifdef __TANDEM
29# include <limits.h> /* for SSIZE_MAX */
30#endif
31
32#if defined(HAVE_UTIME) && defined(HAVE_UTIME_H)
33# include <utime.h> /* for struct utimbuf */
34#endif
35
36#define BUFSIZE 8192 /* size of normal write buffer */
37#define SMBUFSIZE 256 /* size of emergency write buffer */
38
39#ifdef FEAT_CRYPT
40# define CRYPT_MAGIC "VimCrypt~01!" /* "01" is the version nr */
41# define CRYPT_MAGIC_LEN 12 /* must be multiple of 4! */
42#endif
43
44/* Is there any system that doesn't have access()? */
45#ifndef MACOS_CLASSIC /* Not available on MacOS 9 */
46# define USE_MCH_ACCESS
47#endif
48
49#ifdef FEAT_MBYTE
50static char_u *next_fenc __ARGS((char_u **pp));
51# ifdef FEAT_EVAL
52static char_u *readfile_charconvert __ARGS((char_u *fname, char_u *fenc, int *fdp));
53# endif
54#endif
55#ifdef FEAT_VIMINFO
56static void check_marks_read __ARGS((void));
57#endif
58#ifdef FEAT_CRYPT
59static char_u *check_for_cryptkey __ARGS((char_u *cryptkey, char_u *ptr, long *sizep, long *filesizep, int newfile));
60#endif
61#ifdef UNIX
62static void set_file_time __ARGS((char_u *fname, time_t atime, time_t mtime));
63#endif
64static void msg_add_fname __ARGS((buf_T *, char_u *));
65static int msg_add_fileformat __ARGS((int eol_type));
66static void msg_add_lines __ARGS((int, long, long));
67static void msg_add_eol __ARGS((void));
68static int check_mtime __ARGS((buf_T *buf, struct stat *s));
69static int time_differs __ARGS((long t1, long t2));
70#ifdef FEAT_AUTOCMD
71static int apply_autocmds_exarg __ARGS((EVENT_T event, char_u *fname, char_u *fname_io, int force, buf_T *buf, exarg_T *eap));
72#endif
73
74#if defined(FEAT_CRYPT) || defined(FEAT_MBYTE)
75# define HAS_BW_FLAGS
76# define FIO_LATIN1 0x01 /* convert Latin1 */
77# define FIO_UTF8 0x02 /* convert UTF-8 */
78# define FIO_UCS2 0x04 /* convert UCS-2 */
79# define FIO_UCS4 0x08 /* convert UCS-4 */
80# define FIO_UTF16 0x10 /* convert UTF-16 */
81# ifdef WIN3264
82# define FIO_CODEPAGE 0x20 /* convert MS-Windows codepage */
83# define FIO_PUT_CP(x) (((x) & 0xffff) << 16) /* put codepage in top word */
84# define FIO_GET_CP(x) (((x)>>16) & 0xffff) /* get codepage from top word */
85# endif
86# ifdef MACOS_X
87# define FIO_MACROMAN 0x20 /* convert MacRoman */
88# endif
89# define FIO_ENDIAN_L 0x80 /* little endian */
90# define FIO_ENCRYPTED 0x1000 /* encrypt written bytes */
91# define FIO_NOCONVERT 0x2000 /* skip encoding conversion */
92# define FIO_UCSBOM 0x4000 /* check for BOM at start of file */
93# define FIO_ALL -1 /* allow all formats */
94#endif
95
96/* When converting, a read() or write() may leave some bytes to be converted
97 * for the next call. The value is guessed... */
98#define CONV_RESTLEN 30
99
100/* We have to guess how much a sequence of bytes may expand when converting
101 * with iconv() to be able to allocate a buffer. */
102#define ICONV_MULT 8
103
104/*
105 * Structure to pass arguments from buf_write() to buf_write_bytes().
106 */
107struct bw_info
108{
109 int bw_fd; /* file descriptor */
110 char_u *bw_buf; /* buffer with data to be written */
111 int bw_len; /* lenght of data */
112#ifdef HAS_BW_FLAGS
113 int bw_flags; /* FIO_ flags */
114#endif
115#ifdef FEAT_MBYTE
116 char_u bw_rest[CONV_RESTLEN]; /* not converted bytes */
117 int bw_restlen; /* nr of bytes in bw_rest[] */
118 int bw_first; /* first write call */
119 char_u *bw_conv_buf; /* buffer for writing converted chars */
120 int bw_conv_buflen; /* size of bw_conv_buf */
121 int bw_conv_error; /* set for conversion error */
122# ifdef USE_ICONV
123 iconv_t bw_iconv_fd; /* descriptor for iconv() or -1 */
124# endif
125#endif
126};
127
128static int buf_write_bytes __ARGS((struct bw_info *ip));
129
130#ifdef FEAT_MBYTE
131static int ucs2bytes __ARGS((unsigned c, char_u **pp, int flags));
132static int same_encoding __ARGS((char_u *a, char_u *b));
133static int get_fio_flags __ARGS((char_u *ptr));
134static char_u *check_for_bom __ARGS((char_u *p, long size, int *lenp, int flags));
135static int make_bom __ARGS((char_u *buf, char_u *name));
136# ifdef WIN3264
137static int get_win_fio_flags __ARGS((char_u *ptr));
138# endif
139# ifdef MACOS_X
140static int get_mac_fio_flags __ARGS((char_u *ptr));
141# endif
142#endif
143static int move_lines __ARGS((buf_T *frombuf, buf_T *tobuf));
144
145static linenr_T write_no_eol_lnum = 0; /* non-zero lnum when last line of
146 next binary write should not have
147 an end-of-line */
148
149 void
150filemess(buf, name, s, attr)
151 buf_T *buf;
152 char_u *name;
153 char_u *s;
154 int attr;
155{
156 int msg_scroll_save;
157
158 if (msg_silent != 0)
159 return;
160 msg_add_fname(buf, name); /* put file name in IObuff with quotes */
161 /* If it's extremely long, truncate it. */
162 if (STRLEN(IObuff) > IOSIZE - 80)
163 IObuff[IOSIZE - 80] = NUL;
164 STRCAT(IObuff, s);
165 /*
166 * For the first message may have to start a new line.
167 * For further ones overwrite the previous one, reset msg_scroll before
168 * calling filemess().
169 */
170 msg_scroll_save = msg_scroll;
171 if (shortmess(SHM_OVERALL) && !exiting && p_verbose == 0)
172 msg_scroll = FALSE;
173 if (!msg_scroll) /* wait a bit when overwriting an error msg */
174 check_for_delay(FALSE);
175 msg_start();
176 msg_scroll = msg_scroll_save;
177 msg_scrolled_ign = TRUE;
178 /* may truncate the message to avoid a hit-return prompt */
179 msg_outtrans_attr(msg_may_trunc(FALSE, IObuff), attr);
180 msg_clr_eos();
181 out_flush();
182 msg_scrolled_ign = FALSE;
183}
184
185/*
186 * Read lines from file "fname" into the buffer after line "from".
187 *
188 * 1. We allocate blocks with lalloc, as big as possible.
189 * 2. Each block is filled with characters from the file with a single read().
190 * 3. The lines are inserted in the buffer with ml_append().
191 *
192 * (caller must check that fname != NULL, unless READ_STDIN is used)
193 *
194 * "lines_to_skip" is the number of lines that must be skipped
195 * "lines_to_read" is the number of lines that are appended
196 * When not recovering lines_to_skip is 0 and lines_to_read MAXLNUM.
197 *
198 * flags:
199 * READ_NEW starting to edit a new buffer
200 * READ_FILTER reading filter output
201 * READ_STDIN read from stdin instead of a file
202 * READ_BUFFER read from curbuf instead of a file (converting after reading
203 * stdin)
204 * READ_DUMMY read into a dummy buffer (to check if file contents changed)
205 *
206 * return FAIL for failure, OK otherwise
207 */
208 int
209readfile(fname, sfname, from, lines_to_skip, lines_to_read, eap, flags)
210 char_u *fname;
211 char_u *sfname;
212 linenr_T from;
213 linenr_T lines_to_skip;
214 linenr_T lines_to_read;
215 exarg_T *eap; /* can be NULL! */
216 int flags;
217{
218 int fd = 0;
219 int newfile = (flags & READ_NEW);
220 int check_readonly;
221 int filtering = (flags & READ_FILTER);
222 int read_stdin = (flags & READ_STDIN);
223 int read_buffer = (flags & READ_BUFFER);
224 linenr_T read_buf_lnum = 1; /* next line to read from curbuf */
225 colnr_T read_buf_col = 0; /* next char to read from this line */
226 char_u c;
227 linenr_T lnum = from;
228 char_u *ptr = NULL; /* pointer into read buffer */
229 char_u *buffer = NULL; /* read buffer */
230 char_u *new_buffer = NULL; /* init to shut up gcc */
231 char_u *line_start = NULL; /* init to shut up gcc */
232 int wasempty; /* buffer was empty before reading */
233 colnr_T len;
234 long size = 0;
235 char_u *p;
236 long filesize = 0;
237 int skip_read = FALSE;
238#ifdef FEAT_CRYPT
239 char_u *cryptkey = NULL;
240#endif
241 int split = 0; /* number of split lines */
242#define UNKNOWN 0x0fffffff /* file size is unknown */
243 linenr_T linecnt;
244 int error = FALSE; /* errors encountered */
245 int ff_error = EOL_UNKNOWN; /* file format with errors */
246 long linerest = 0; /* remaining chars in line */
247#ifdef UNIX
248 int perm = 0;
249 int swap_mode = -1; /* protection bits for swap file */
250#else
251 int perm;
252#endif
253 int fileformat = 0; /* end-of-line format */
254 int keep_fileformat = FALSE;
255 struct stat st;
256 int file_readonly;
257 linenr_T skip_count = 0;
258 linenr_T read_count = 0;
259 int msg_save = msg_scroll;
260 linenr_T read_no_eol_lnum = 0; /* non-zero lnum when last line of
261 * last read was missing the eol */
262 int try_mac = (vim_strchr(p_ffs, 'm') != NULL);
263 int try_dos = (vim_strchr(p_ffs, 'd') != NULL);
264 int try_unix = (vim_strchr(p_ffs, 'x') != NULL);
265 int file_rewind = FALSE;
266#ifdef FEAT_MBYTE
267 int can_retry;
268 int conv_error = FALSE; /* conversion error detected */
269 int keep_dest_enc = FALSE; /* don't retry when char doesn't fit
270 in destination encoding */
271 linenr_T illegal_byte = 0; /* line nr with illegal byte */
272 char_u *tmpname = NULL; /* name of 'charconvert' output file */
273 int fio_flags = 0;
274 char_u *fenc; /* fileencoding to use */
275 int fenc_alloced; /* fenc_next is in allocated memory */
276 char_u *fenc_next = NULL; /* next item in 'fencs' or NULL */
277 int advance_fenc = FALSE;
278 long real_size = 0;
279# ifdef USE_ICONV
280 iconv_t iconv_fd = (iconv_t)-1; /* descriptor for iconv() or -1 */
281# ifdef FEAT_EVAL
282 int did_iconv = FALSE; /* TRUE when iconv() failed and trying
283 'charconvert' next */
284# endif
285# endif
286 int converted = FALSE; /* TRUE if conversion done */
287 int notconverted = FALSE; /* TRUE if conversion wanted but it
288 wasn't possible */
289 char_u conv_rest[CONV_RESTLEN];
290 int conv_restlen = 0; /* nr of bytes in conv_rest[] */
291#endif
292
293#ifdef FEAT_AUTOCMD
294 write_no_eol_lnum = 0; /* in case it was set by the previous read */
295#endif
296
297 /*
298 * If there is no file name yet, use the one for the read file.
299 * BF_NOTEDITED is set to reflect this.
300 * Don't do this for a read from a filter.
301 * Only do this when 'cpoptions' contains the 'f' flag.
302 */
303 if (curbuf->b_ffname == NULL
304 && !filtering
305 && fname != NULL
306 && vim_strchr(p_cpo, CPO_FNAMER) != NULL
307 && !(flags & READ_DUMMY))
308 {
309 if (setfname(curbuf, fname, sfname, FALSE) == OK)
310 curbuf->b_flags |= BF_NOTEDITED;
311 }
312
313 /*
314 * For Unix: Use the short file name whenever possible.
315 * Avoids problems with networks and when directory names are changed.
316 * Don't do this for MS-DOS, a "cd" in a sub-shell may have moved us to
317 * another directory, which we don't detect.
318 */
319 if (sfname == NULL)
320 sfname = fname;
321#if defined(UNIX) || defined(__EMX__)
322 fname = sfname;
323#endif
324
325#ifdef FEAT_AUTOCMD
326 /*
327 * The BufReadCmd and FileReadCmd events intercept the reading process by
328 * executing the associated commands instead.
329 */
330 if (!filtering && !read_stdin && !read_buffer)
331 {
332 pos_T pos;
333
334 pos = curbuf->b_op_start;
335
336 /* Set '[ mark to the line above where the lines go (line 1 if zero). */
337 curbuf->b_op_start.lnum = ((from == 0) ? 1 : from);
338 curbuf->b_op_start.col = 0;
339
340 if (newfile)
341 {
342 if (apply_autocmds_exarg(EVENT_BUFREADCMD, NULL, sfname,
343 FALSE, curbuf, eap))
344#ifdef FEAT_EVAL
345 return aborting() ? FAIL : OK;
346#else
347 return OK;
348#endif
349 }
350 else if (apply_autocmds_exarg(EVENT_FILEREADCMD, sfname, sfname,
351 FALSE, NULL, eap))
352#ifdef FEAT_EVAL
353 return aborting() ? FAIL : OK;
354#else
355 return OK;
356#endif
357
358 curbuf->b_op_start = pos;
359 }
360#endif
361
362 if ((shortmess(SHM_OVER) || curbuf->b_help) && p_verbose == 0)
363 msg_scroll = FALSE; /* overwrite previous file message */
364 else
365 msg_scroll = TRUE; /* don't overwrite previous file message */
366
367 /*
368 * If the name ends in a path separator, we can't open it. Check here,
369 * because reading the file may actually work, but then creating the swap
370 * file may destroy it! Reported on MS-DOS and Win 95.
371 * If the name is too long we might crash further on, quit here.
372 */
Bram Moolenaar15d0a8c2004-09-06 17:44:46 +0000373 if (fname != NULL && *fname != NUL)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000374 {
Bram Moolenaar15d0a8c2004-09-06 17:44:46 +0000375 p = fname + STRLEN(fname) - 1;
376 if ((vim_ispathsep(*p)
377#ifdef FEAT_MBYTE
378 /* Do not use a multi-byte char as path separator. */
379 && (!has_mbyte || (*mb_head_off)(fname, p) == 0)
380#endif
381 ) || STRLEN(fname) >= MAXPATHL)
382 {
383 filemess(curbuf, fname, (char_u *)_("Illegal file name"), 0);
384 msg_end();
385 msg_scroll = msg_save;
386 return FAIL;
387 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000388 }
389
390#ifdef UNIX
391 /*
392 * On Unix it is possible to read a directory, so we have to
393 * check for it before the mch_open().
394 */
395 if (!read_stdin && !read_buffer)
396 {
397 perm = mch_getperm(fname);
398 if (perm >= 0 && !S_ISREG(perm) /* not a regular file ... */
399# ifdef S_ISFIFO
400 && !S_ISFIFO(perm) /* ... or fifo */
401# endif
402# ifdef S_ISSOCK
403 && !S_ISSOCK(perm) /* ... or socket */
404# endif
405 )
406 {
407 if (S_ISDIR(perm))
408 filemess(curbuf, fname, (char_u *)_("is a directory"), 0);
409 else
410 filemess(curbuf, fname, (char_u *)_("is not a file"), 0);
411 msg_end();
412 msg_scroll = msg_save;
413 return FAIL;
414 }
415 }
416#endif
417
418 /* set default 'fileformat' */
419 if (newfile)
420 {
421 if (eap != NULL && eap->force_ff != 0)
422 set_fileformat(get_fileformat_force(curbuf, eap), OPT_LOCAL);
423 else if (*p_ffs != NUL)
424 set_fileformat(default_fileformat(), OPT_LOCAL);
425 }
426
427 /* set or reset 'binary' */
428 if (eap != NULL && eap->force_bin != 0)
429 {
430 int oldval = curbuf->b_p_bin;
431
432 curbuf->b_p_bin = (eap->force_bin == FORCE_BIN);
433 set_options_bin(oldval, curbuf->b_p_bin, OPT_LOCAL);
434 }
435
436 /*
437 * When opening a new file we take the readonly flag from the file.
438 * Default is r/w, can be set to r/o below.
439 * Don't reset it when in readonly mode
440 * Only set/reset b_p_ro when BF_CHECK_RO is set.
441 */
442 check_readonly = (newfile && (curbuf->b_flags & BF_CHECK_RO));
443 if (check_readonly && !readonlymode) /* default: set file not readonly */
444 curbuf->b_p_ro = FALSE;
445
446 if (newfile && !read_stdin && !read_buffer)
447 {
448 /* Remember time of file.
449 * For RISCOS, also remember the filetype.
450 */
451 if (mch_stat((char *)fname, &st) >= 0)
452 {
453 buf_store_time(curbuf, &st, fname);
454 curbuf->b_mtime_read = curbuf->b_mtime;
455
456#if defined(RISCOS) && defined(FEAT_OSFILETYPE)
457 /* Read the filetype into the buffer local filetype option. */
458 mch_read_filetype(fname);
459#endif
460#ifdef UNIX
461 /*
462 * Use the protection bits of the original file for the swap file.
463 * This makes it possible for others to read the name of the
464 * edited file from the swapfile, but only if they can read the
465 * edited file.
466 * Remove the "write" and "execute" bits for group and others
467 * (they must not write the swapfile).
468 * Add the "read" and "write" bits for the user, otherwise we may
469 * not be able to write to the file ourselves.
470 * Setting the bits is done below, after creating the swap file.
471 */
472 swap_mode = (st.st_mode & 0644) | 0600;
473#endif
474#ifdef FEAT_CW_EDITOR
475 /* Get the FSSpec on MacOS
476 * TODO: Update it properly when the buffer name changes
477 */
478 (void)GetFSSpecFromPath(curbuf->b_ffname, &curbuf->b_FSSpec);
479#endif
480#ifdef VMS
481 curbuf->b_fab_rfm = st.st_fab_rfm;
Bram Moolenaard4755bb2004-09-02 19:12:26 +0000482 curbuf->b_fab_rat = st.st_fab_rat;
483 curbuf->b_fab_mrs = st.st_fab_mrs;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000484#endif
485 }
486 else
487 {
488 curbuf->b_mtime = 0;
489 curbuf->b_mtime_read = 0;
490 curbuf->b_orig_size = 0;
491 curbuf->b_orig_mode = 0;
492 }
493
494 /* Reset the "new file" flag. It will be set again below when the
495 * file doesn't exist. */
496 curbuf->b_flags &= ~(BF_NEW | BF_NEW_W);
497 }
498
499/*
500 * for UNIX: check readonly with perm and mch_access()
501 * for RISCOS: same as Unix, otherwise file gets re-datestamped!
502 * for MSDOS and Amiga: check readonly by trying to open the file for writing
503 */
504 file_readonly = FALSE;
505 if (read_stdin)
506 {
507#if defined(MSDOS) || defined(MSWIN) || defined(OS2)
508 /* Force binary I/O on stdin to avoid CR-LF -> LF conversion. */
509 setmode(0, O_BINARY);
510#endif
511 }
512 else if (!read_buffer)
513 {
514#ifdef USE_MCH_ACCESS
515 if (
516# ifdef UNIX
517 !(perm & 0222) ||
518# endif
519 mch_access((char *)fname, W_OK))
520 file_readonly = TRUE;
521 fd = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0);
522#else
523 if (!newfile
524 || readonlymode
525 || (fd = mch_open((char *)fname, O_RDWR | O_EXTRA, 0)) < 0)
526 {
527 file_readonly = TRUE;
528 /* try to open ro */
529 fd = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0);
530 }
531#endif
532 }
533
534 if (fd < 0) /* cannot open at all */
535 {
536#ifndef UNIX
537 int isdir_f;
538#endif
539 msg_scroll = msg_save;
540#ifndef UNIX
541 /*
542 * On MSDOS and Amiga we can't open a directory, check here.
543 */
544 isdir_f = (mch_isdir(fname));
545 perm = mch_getperm(fname); /* check if the file exists */
546 if (isdir_f)
547 {
548 filemess(curbuf, sfname, (char_u *)_("is a directory"), 0);
549 curbuf->b_p_ro = TRUE; /* must use "w!" now */
550 }
551 else
552#endif
553 if (newfile)
554 {
555 if (perm < 0)
556 {
557 /*
558 * Set the 'new-file' flag, so that when the file has
559 * been created by someone else, a ":w" will complain.
560 */
561 curbuf->b_flags |= BF_NEW;
562
563 /* Create a swap file now, so that other Vims are warned
564 * that we are editing this file. Don't do this for a
565 * "nofile" or "nowrite" buffer type. */
566#ifdef FEAT_QUICKFIX
567 if (!bt_dontwrite(curbuf))
568#endif
569 check_need_swap(newfile);
570 filemess(curbuf, sfname, (char_u *)_("[New File]"), 0);
571#ifdef FEAT_VIMINFO
572 /* Even though this is a new file, it might have been
573 * edited before and deleted. Get the old marks. */
574 check_marks_read();
575#endif
576#ifdef FEAT_MBYTE
577 if (eap != NULL && eap->force_enc != 0)
578 {
579 /* set forced 'fileencoding' */
580 fenc = enc_canonize(eap->cmd + eap->force_enc);
581 if (fenc != NULL)
582 set_string_option_direct((char_u *)"fenc", -1,
583 fenc, OPT_FREE|OPT_LOCAL);
584 vim_free(fenc);
585 }
586#endif
587#ifdef FEAT_AUTOCMD
588 apply_autocmds_exarg(EVENT_BUFNEWFILE, sfname, sfname,
589 FALSE, curbuf, eap);
590#endif
591 /* remember the current fileformat */
592 save_file_ff(curbuf);
593
594#if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
595 if (aborting()) /* autocmds may abort script processing */
596 return FAIL;
597#endif
598 return OK; /* a new file is not an error */
599 }
600 else
601 {
602 filemess(curbuf, sfname,
603 (char_u *)_("[Permission Denied]"), 0);
604 curbuf->b_p_ro = TRUE; /* must use "w!" now */
605 }
606 }
607
608 return FAIL;
609 }
610
611 /*
612 * Only set the 'ro' flag for readonly files the first time they are
613 * loaded. Help files always get readonly mode
614 */
615 if ((check_readonly && file_readonly) || curbuf->b_help)
616 curbuf->b_p_ro = TRUE;
617
618 if (newfile)
619 {
620 curbuf->b_p_eol = TRUE;
621 curbuf->b_start_eol = TRUE;
622#ifdef FEAT_MBYTE
623 curbuf->b_p_bomb = FALSE;
624#endif
625 }
626
627 /* Create a swap file now, so that other Vims are warned that we are
628 * editing this file.
629 * Don't do this for a "nofile" or "nowrite" buffer type. */
630#ifdef FEAT_QUICKFIX
631 if (!bt_dontwrite(curbuf))
632#endif
633 {
634 check_need_swap(newfile);
635#ifdef UNIX
636 /* Set swap file protection bits after creating it. */
637 if (swap_mode > 0 && curbuf->b_ml.ml_mfp->mf_fname != NULL)
638 (void)mch_setperm(curbuf->b_ml.ml_mfp->mf_fname, (long)swap_mode);
639#endif
640 }
641
642#if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
643 /* If "Quit" selected at ATTENTION dialog, don't load the file */
644 if (swap_exists_action == SEA_QUIT)
645 {
646 if (!read_buffer && !read_stdin)
647 close(fd);
648 return FAIL;
649 }
650#endif
651
652 ++no_wait_return; /* don't wait for return yet */
653
654 /*
655 * Set '[ mark to the line above where the lines go (line 1 if zero).
656 */
657 curbuf->b_op_start.lnum = ((from == 0) ? 1 : from);
658 curbuf->b_op_start.col = 0;
659
660#ifdef FEAT_AUTOCMD
661 if (!read_buffer)
662 {
663 int m = msg_scroll;
664 int n = msg_scrolled;
665 buf_T *old_curbuf = curbuf;
666
667 /*
668 * The file must be closed again, the autocommands may want to change
669 * the file before reading it.
670 */
671 if (!read_stdin)
672 close(fd); /* ignore errors */
673
674 /*
675 * The output from the autocommands should not overwrite anything and
676 * should not be overwritten: Set msg_scroll, restore its value if no
677 * output was done.
678 */
679 msg_scroll = TRUE;
680 if (filtering)
681 apply_autocmds_exarg(EVENT_FILTERREADPRE, NULL, sfname,
682 FALSE, curbuf, eap);
683 else if (read_stdin)
684 apply_autocmds_exarg(EVENT_STDINREADPRE, NULL, sfname,
685 FALSE, curbuf, eap);
686 else if (newfile)
687 apply_autocmds_exarg(EVENT_BUFREADPRE, NULL, sfname,
688 FALSE, curbuf, eap);
689 else
690 apply_autocmds_exarg(EVENT_FILEREADPRE, sfname, sfname,
691 FALSE, NULL, eap);
692 if (msg_scrolled == n)
693 msg_scroll = m;
694
695#ifdef FEAT_EVAL
696 if (aborting()) /* autocmds may abort script processing */
697 {
698 --no_wait_return;
699 msg_scroll = msg_save;
700 curbuf->b_p_ro = TRUE; /* must use "w!" now */
701 return FAIL;
702 }
703#endif
704 /*
705 * Don't allow the autocommands to change the current buffer.
706 * Try to re-open the file.
707 */
708 if (!read_stdin && (curbuf != old_curbuf
709 || (fd = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0)) < 0))
710 {
711 --no_wait_return;
712 msg_scroll = msg_save;
713 if (fd < 0)
714 EMSG(_("E200: *ReadPre autocommands made the file unreadable"));
715 else
716 EMSG(_("E201: *ReadPre autocommands must not change current buffer"));
717 curbuf->b_p_ro = TRUE; /* must use "w!" now */
718 return FAIL;
719 }
720 }
721#endif /* FEAT_AUTOCMD */
722
723 /* Autocommands may add lines to the file, need to check if it is empty */
724 wasempty = (curbuf->b_ml.ml_flags & ML_EMPTY);
725
726 if (!recoverymode && !filtering && !(flags & READ_DUMMY))
727 {
728 /*
729 * Show the user that we are busy reading the input. Sometimes this
730 * may take a while. When reading from stdin another program may
731 * still be running, don't move the cursor to the last line, unless
732 * always using the GUI.
733 */
734 if (read_stdin)
735 {
736#ifndef ALWAYS_USE_GUI
737 mch_msg(_("Vim: Reading from stdin...\n"));
738#endif
739#ifdef FEAT_GUI
740 /* Also write a message in the GUI window, if there is one. */
741 if (gui.in_use && !gui.dying && !gui.starting)
742 {
743 p = (char_u *)_("Reading from stdin...");
744 gui_write(p, (int)STRLEN(p));
745 }
746#endif
747 }
748 else if (!read_buffer)
749 filemess(curbuf, sfname, (char_u *)"", 0);
750 }
751
752 msg_scroll = FALSE; /* overwrite the file message */
753
754 /*
755 * Set linecnt now, before the "retry" caused by a wrong guess for
756 * fileformat, and after the autocommands, which may change them.
757 */
758 linecnt = curbuf->b_ml.ml_line_count;
759
760#ifdef FEAT_MBYTE
761 /*
762 * Decide which 'encoding' to use first.
763 */
764 if (eap != NULL && eap->force_enc != 0)
765 {
766 fenc = enc_canonize(eap->cmd + eap->force_enc);
767 fenc_alloced = TRUE;
768 }
769 else if (curbuf->b_p_bin)
770 {
771 fenc = (char_u *)""; /* binary: don't convert */
772 fenc_alloced = FALSE;
773 }
774 else if (curbuf->b_help)
775 {
776 char_u firstline[80];
777
778 /* Help files are either utf-8 or latin1. Try utf-8 first, if this
779 * fails it must be latin1.
780 * Always do this when 'encoding' is "utf-8". Otherwise only do
781 * this when needed to avoid [converted] remarks all the time.
782 * It is needed when the first line contains non-ASCII characters.
783 * That is only in *.??x files. */
784 fenc = (char_u *)"latin1";
785 c = enc_utf8;
786 if (!c && !read_stdin && TOLOWER_ASC(fname[STRLEN(fname) - 1]) == 'x')
787 {
788 /* Read the first line (and a bit more). Immediately rewind to
789 * the start of the file. If the read() fails "len" is -1. */
790 len = vim_read(fd, firstline, 80);
791 lseek(fd, (off_t)0L, SEEK_SET);
792 for (p = firstline; p < firstline + len; ++p)
793 if (*p >= 0x80)
794 {
795 c = TRUE;
796 break;
797 }
798 }
799
800 if (c)
801 {
802 fenc_next = fenc;
803 fenc = (char_u *)"utf-8";
804
805 /* When the file is utf-8 but a character doesn't fit in
806 * 'encoding' don't retry. In help text editing utf-8 bytes
807 * doesn't make sense. */
808 keep_dest_enc = TRUE;
809 }
810 fenc_alloced = FALSE;
811 }
812 else if (*p_fencs == NUL)
813 {
814 fenc = curbuf->b_p_fenc; /* use format from buffer */
815 fenc_alloced = FALSE;
816 }
817 else
818 {
819 fenc_next = p_fencs; /* try items in 'fileencodings' */
820 fenc = next_fenc(&fenc_next);
821 fenc_alloced = TRUE;
822 }
823#endif
824
825 /*
826 * Jump back here to retry reading the file in different ways.
827 * Reasons to retry:
828 * - encoding conversion failed: try another one from "fenc_next"
829 * - BOM detected and fenc was set, need to setup conversion
830 * - "fileformat" check failed: try another
831 *
832 * Variables set for special retry actions:
833 * "file_rewind" Rewind the file to start reading it again.
834 * "advance_fenc" Advance "fenc" using "fenc_next".
835 * "skip_read" Re-use already read bytes (BOM detected).
836 * "did_iconv" iconv() conversion failed, try 'charconvert'.
837 * "keep_fileformat" Don't reset "fileformat".
838 *
839 * Other status indicators:
840 * "tmpname" When != NULL did conversion with 'charconvert'.
841 * Output file has to be deleted afterwards.
842 * "iconv_fd" When != -1 did conversion with iconv().
843 */
844retry:
845
846 if (file_rewind)
847 {
848 if (read_buffer)
849 {
850 read_buf_lnum = 1;
851 read_buf_col = 0;
852 }
853 else if (read_stdin || lseek(fd, (off_t)0L, SEEK_SET) != 0)
854 {
855 /* Can't rewind the file, give up. */
856 error = TRUE;
857 goto failed;
858 }
859 /* Delete the previously read lines. */
860 while (lnum > from)
861 ml_delete(lnum--, FALSE);
862 file_rewind = FALSE;
863#ifdef FEAT_MBYTE
864 if (newfile)
865 curbuf->b_p_bomb = FALSE;
866 conv_error = FALSE;
867#endif
868 }
869
870 /*
871 * When retrying with another "fenc" and the first time "fileformat"
872 * will be reset.
873 */
874 if (keep_fileformat)
875 keep_fileformat = FALSE;
876 else
877 {
878 if (eap != NULL && eap->force_ff != 0)
879 fileformat = get_fileformat_force(curbuf, eap);
880 else if (curbuf->b_p_bin)
881 fileformat = EOL_UNIX; /* binary: use Unix format */
882 else if (*p_ffs == NUL)
883 fileformat = get_fileformat(curbuf);/* use format from buffer */
884 else
885 fileformat = EOL_UNKNOWN; /* detect from file */
886 }
887
888#ifdef FEAT_MBYTE
889# ifdef USE_ICONV
890 if (iconv_fd != (iconv_t)-1)
891 {
892 /* aborted conversion with iconv(), close the descriptor */
893 iconv_close(iconv_fd);
894 iconv_fd = (iconv_t)-1;
895 }
896# endif
897
898 if (advance_fenc)
899 {
900 /*
901 * Try the next entry in 'fileencodings'.
902 */
903 advance_fenc = FALSE;
904
905 if (eap != NULL && eap->force_enc != 0)
906 {
907 /* Conversion given with "++cc=" wasn't possible, read
908 * without conversion. */
909 notconverted = TRUE;
910 conv_error = FALSE;
911 if (fenc_alloced)
912 vim_free(fenc);
913 fenc = (char_u *)"";
914 fenc_alloced = FALSE;
915 }
916 else
917 {
918 if (fenc_alloced)
919 vim_free(fenc);
920 if (fenc_next != NULL)
921 {
922 fenc = next_fenc(&fenc_next);
923 fenc_alloced = (fenc_next != NULL);
924 }
925 else
926 {
927 fenc = (char_u *)"";
928 fenc_alloced = FALSE;
929 }
930 }
931 if (tmpname != NULL)
932 {
933 mch_remove(tmpname); /* delete converted file */
934 vim_free(tmpname);
935 tmpname = NULL;
936 }
937 }
938
939 /*
940 * Conversion is required when the encoding of the file is different
941 * from 'encoding' or 'encoding' is UTF-16, UCS-2 or UCS-4 (requires
942 * conversion to UTF-8).
943 */
944 fio_flags = 0;
945 converted = (*fenc != NUL && !same_encoding(p_enc, fenc));
946 if (converted || enc_unicode != 0)
947 {
948
949 /* "ucs-bom" means we need to check the first bytes of the file
950 * for a BOM. */
951 if (STRCMP(fenc, ENC_UCSBOM) == 0)
952 fio_flags = FIO_UCSBOM;
953
954 /*
955 * Check if UCS-2/4 or Latin1 to UTF-8 conversion needs to be
956 * done. This is handled below after read(). Prepare the
957 * fio_flags to avoid having to parse the string each time.
958 * Also check for Unicode to Latin1 conversion, because iconv()
959 * appears not to handle this correctly. This works just like
960 * conversion to UTF-8 except how the resulting character is put in
961 * the buffer.
962 */
963 else if (enc_utf8 || STRCMP(p_enc, "latin1") == 0)
964 fio_flags = get_fio_flags(fenc);
965
966# ifdef WIN3264
967 /*
968 * Conversion from an MS-Windows codepage to UTF-8 or another codepage
969 * is handled with MultiByteToWideChar().
970 */
971 if (fio_flags == 0)
972 fio_flags = get_win_fio_flags(fenc);
973# endif
974
975# ifdef MACOS_X
976 /* Conversion from Apple MacRoman to latin1 or UTF-8 */
977 if (fio_flags == 0)
978 fio_flags = get_mac_fio_flags(fenc);
979# endif
980
981# ifdef USE_ICONV
982 /*
983 * Try using iconv() if we can't convert internally.
984 */
985 if (fio_flags == 0
986# ifdef FEAT_EVAL
987 && !did_iconv
988# endif
989 )
990 iconv_fd = (iconv_t)my_iconv_open(
991 enc_utf8 ? (char_u *)"utf-8" : p_enc, fenc);
992# endif
993
994# ifdef FEAT_EVAL
995 /*
996 * Use the 'charconvert' expression when conversion is required
997 * and we can't do it internally or with iconv().
998 */
999 if (fio_flags == 0 && !read_stdin && !read_buffer && *p_ccv != NUL
1000# ifdef USE_ICONV
1001 && iconv_fd == (iconv_t)-1
1002# endif
1003 )
1004 {
1005# ifdef USE_ICONV
1006 did_iconv = FALSE;
1007# endif
1008 /* Skip conversion when it's already done (retry for wrong
1009 * "fileformat"). */
1010 if (tmpname == NULL)
1011 {
1012 tmpname = readfile_charconvert(fname, fenc, &fd);
1013 if (tmpname == NULL)
1014 {
1015 /* Conversion failed. Try another one. */
1016 advance_fenc = TRUE;
1017 if (fd < 0)
1018 {
1019 /* Re-opening the original file failed! */
1020 EMSG(_("E202: Conversion made file unreadable!"));
1021 error = TRUE;
1022 goto failed;
1023 }
1024 goto retry;
1025 }
1026 }
1027 }
1028 else
1029# endif
1030 {
1031 if (fio_flags == 0
1032# ifdef USE_ICONV
1033 && iconv_fd == (iconv_t)-1
1034# endif
1035 )
1036 {
1037 /* Conversion wanted but we can't.
1038 * Try the next conversion in 'fileencodings' */
1039 advance_fenc = TRUE;
1040 goto retry;
1041 }
1042 }
1043 }
1044
1045 /* Set can_retry when it's possible to rewind the file and try with
1046 * another "fenc" value. It's FALSE when no other "fenc" to try, reading
1047 * stdin or "fenc" was specified with "++enc=". */
1048 can_retry = (*fenc != NUL && !read_stdin
1049 && (eap == NULL || eap->force_enc == 0));
1050#endif
1051
1052 if (!skip_read)
1053 {
1054 linerest = 0;
1055 filesize = 0;
1056 skip_count = lines_to_skip;
1057 read_count = lines_to_read;
1058#ifdef FEAT_MBYTE
1059 conv_restlen = 0;
1060#endif
1061 }
1062
1063 while (!error && !got_int)
1064 {
1065 /*
1066 * We allocate as much space for the file as we can get, plus
1067 * space for the old line plus room for one terminating NUL.
1068 * The amount is limited by the fact that read() only can read
1069 * upto max_unsigned characters (and other things).
1070 */
1071#if SIZEOF_INT <= 2
1072 if (linerest >= 0x7ff0)
1073 {
1074 ++split;
1075 *ptr = NL; /* split line by inserting a NL */
1076 size = 1;
1077 }
1078 else
1079#endif
1080 {
1081 if (!skip_read)
1082 {
1083#if SIZEOF_INT > 2
1084# ifdef __TANDEM
1085 size = SSIZE_MAX; /* use max I/O size, 52K */
1086# else
1087 size = 0x10000L; /* use buffer >= 64K */
1088# endif
1089#else
1090 size = 0x7ff0L - linerest; /* limit buffer to 32K */
1091#endif
1092
1093 for ( ; size >= 10; size = (long_u)size >> 1)
1094 {
1095 if ((new_buffer = lalloc((long_u)(size + linerest + 1),
1096 FALSE)) != NULL)
1097 break;
1098 }
1099 if (new_buffer == NULL)
1100 {
1101 do_outofmem_msg((long_u)(size * 2 + linerest + 1));
1102 error = TRUE;
1103 break;
1104 }
1105 if (linerest) /* copy characters from the previous buffer */
1106 mch_memmove(new_buffer, ptr - linerest, (size_t)linerest);
1107 vim_free(buffer);
1108 buffer = new_buffer;
1109 ptr = buffer + linerest;
1110 line_start = buffer;
1111
1112#ifdef FEAT_MBYTE
1113 /* May need room to translate into.
1114 * For iconv() we don't really know the required space, use a
1115 * factor ICONV_MULT.
1116 * latin1 to utf-8: 1 byte becomes up to 2 bytes
1117 * utf-16 to utf-8: 2 bytes become up to 3 bytes, 4 bytes
1118 * become up to 4 bytes, size must be multiple of 2
1119 * ucs-2 to utf-8: 2 bytes become up to 3 bytes, size must be
1120 * multiple of 2
1121 * ucs-4 to utf-8: 4 bytes become up to 6 bytes, size must be
1122 * multiple of 4 */
1123 real_size = size;
1124# ifdef USE_ICONV
1125 if (iconv_fd != (iconv_t)-1)
1126 size = size / ICONV_MULT;
1127 else
1128# endif
1129 if (fio_flags & FIO_LATIN1)
1130 size = size / 2;
1131 else if (fio_flags & (FIO_UCS2 | FIO_UTF16))
1132 size = (size * 2 / 3) & ~1;
1133 else if (fio_flags & FIO_UCS4)
1134 size = (size * 2 / 3) & ~3;
1135 else if (fio_flags == FIO_UCSBOM)
1136 size = size / ICONV_MULT; /* worst case */
1137# ifdef WIN3264
1138 else if (fio_flags & FIO_CODEPAGE)
1139 size = size / ICONV_MULT; /* also worst case */
1140# endif
1141# ifdef MACOS_X
1142 else if (fio_flags & FIO_MACROMAN)
1143 size = size / ICONV_MULT; /* also worst case */
1144# endif
1145#endif
1146
1147#ifdef FEAT_MBYTE
1148 if (conv_restlen > 0)
1149 {
1150 /* Insert unconverted bytes from previous line. */
1151 mch_memmove(ptr, conv_rest, conv_restlen);
1152 ptr += conv_restlen;
1153 size -= conv_restlen;
1154 }
1155#endif
1156
1157 if (read_buffer)
1158 {
1159 /*
1160 * Read bytes from curbuf. Used for converting text read
1161 * from stdin.
1162 */
1163 if (read_buf_lnum > from)
1164 size = 0;
1165 else
1166 {
1167 int n, ni;
1168 long tlen;
1169
1170 tlen = 0;
1171 for (;;)
1172 {
1173 p = ml_get(read_buf_lnum) + read_buf_col;
1174 n = (int)STRLEN(p);
1175 if ((int)tlen + n + 1 > size)
1176 {
1177 /* Filled up to "size", append partial line.
1178 * Change NL to NUL to reverse the effect done
1179 * below. */
1180 n = size - tlen;
1181 for (ni = 0; ni < n; ++ni)
1182 {
1183 if (p[ni] == NL)
1184 ptr[tlen++] = NUL;
1185 else
1186 ptr[tlen++] = p[ni];
1187 }
1188 read_buf_col += n;
1189 break;
1190 }
1191 else
1192 {
1193 /* Append whole line and new-line. Change NL
1194 * to NUL to reverse the effect done below. */
1195 for (ni = 0; ni < n; ++ni)
1196 {
1197 if (p[ni] == NL)
1198 ptr[tlen++] = NUL;
1199 else
1200 ptr[tlen++] = p[ni];
1201 }
1202 ptr[tlen++] = NL;
1203 read_buf_col = 0;
1204 if (++read_buf_lnum > from)
1205 {
1206 /* When the last line didn't have an
1207 * end-of-line don't add it now either. */
1208 if (!curbuf->b_p_eol)
1209 --tlen;
1210 size = tlen;
1211 break;
1212 }
1213 }
1214 }
1215 }
1216 }
1217 else
1218 {
1219 /*
1220 * Read bytes from the file.
1221 */
1222 size = vim_read(fd, ptr, size);
1223 }
1224
1225 if (size <= 0)
1226 {
1227 if (size < 0) /* read error */
1228 error = TRUE;
1229#ifdef FEAT_MBYTE
1230 else if (conv_restlen > 0)
1231 /* some trailing bytes unconverted */
1232 conv_error = TRUE;
1233#endif
1234 }
1235
1236#ifdef FEAT_CRYPT
1237 /*
1238 * At start of file: Check for magic number of encryption.
1239 */
1240 if (filesize == 0)
1241 cryptkey = check_for_cryptkey(cryptkey, ptr, &size,
1242 &filesize, newfile);
1243 /*
1244 * Decrypt the read bytes.
1245 */
1246 if (cryptkey != NULL && size > 0)
1247 for (p = ptr; p < ptr + size; ++p)
1248 ZDECODE(*p);
1249#endif
1250 }
1251 skip_read = FALSE;
1252
1253#ifdef FEAT_MBYTE
1254 /*
1255 * At start of file (or after crypt magic number): Check for BOM.
1256 * Also check for a BOM for other Unicode encodings, but not after
1257 * converting with 'charconvert' or when a BOM has already been
1258 * found.
1259 */
1260 if ((filesize == 0
1261# ifdef FEAT_CRYPT
1262 || (filesize == CRYPT_MAGIC_LEN && cryptkey != NULL)
1263# endif
1264 )
1265 && (fio_flags == FIO_UCSBOM
1266 || (!curbuf->b_p_bomb
1267 && tmpname == NULL
1268 && (*fenc == 'u' || (*fenc == NUL && enc_utf8)))))
1269 {
1270 char_u *ccname;
1271 int blen;
1272
1273 /* no BOM detection in a short file or in binary mode */
1274 if (size < 2 || curbuf->b_p_bin)
1275 ccname = NULL;
1276 else
1277 ccname = check_for_bom(ptr, size, &blen,
1278 fio_flags == FIO_UCSBOM ? FIO_ALL : get_fio_flags(fenc));
1279 if (ccname != NULL)
1280 {
1281 /* Remove BOM from the text */
1282 filesize += blen;
1283 size -= blen;
1284 mch_memmove(ptr, ptr + blen, (size_t)size);
1285 if (newfile)
1286 curbuf->b_p_bomb = TRUE;
1287 }
1288
1289 if (fio_flags == FIO_UCSBOM)
1290 {
1291 if (ccname == NULL)
1292 {
1293 /* No BOM detected: retry with next encoding. */
1294 advance_fenc = TRUE;
1295 }
1296 else
1297 {
1298 /* BOM detected: set "fenc" and jump back */
1299 if (fenc_alloced)
1300 vim_free(fenc);
1301 fenc = ccname;
1302 fenc_alloced = FALSE;
1303 }
1304 /* retry reading without getting new bytes or rewinding */
1305 skip_read = TRUE;
1306 goto retry;
1307 }
1308 }
1309#endif
1310 /*
1311 * Break here for a read error or end-of-file.
1312 */
1313 if (size <= 0)
1314 break;
1315
1316#ifdef FEAT_MBYTE
1317
1318 /* Include not converted bytes. */
1319 ptr -= conv_restlen;
1320 size += conv_restlen;
1321 conv_restlen = 0;
1322
1323# ifdef USE_ICONV
1324 if (iconv_fd != (iconv_t)-1)
1325 {
1326 /*
1327 * Attempt conversion of the read bytes to 'encoding' using
1328 * iconv().
1329 */
1330 const char *fromp;
1331 char *top;
1332 size_t from_size;
1333 size_t to_size;
1334
1335 fromp = (char *)ptr;
1336 from_size = size;
1337 ptr += size;
1338 top = (char *)ptr;
1339 to_size = real_size - size;
1340
1341 /*
1342 * If there is conversion error or not enough room try using
1343 * another conversion.
1344 */
1345 if ((iconv(iconv_fd, (void *)&fromp, &from_size, &top, &to_size)
1346 == (size_t)-1 && ICONV_ERRNO != ICONV_EINVAL)
1347 || from_size > CONV_RESTLEN)
1348 goto rewind_retry;
1349
1350 if (from_size > 0)
1351 {
1352 /* Some remaining characters, keep them for the next
1353 * round. */
1354 mch_memmove(conv_rest, (char_u *)fromp, from_size);
1355 conv_restlen = (int)from_size;
1356 }
1357
1358 /* move the linerest to before the converted characters */
1359 line_start = ptr - linerest;
1360 mch_memmove(line_start, buffer, (size_t)linerest);
1361 size = (long)((char_u *)top - ptr);
1362 }
1363# endif
1364
1365# ifdef WIN3264
1366 if (fio_flags & FIO_CODEPAGE)
1367 {
1368 /*
1369 * Conversion from an MS-Windows codepage or UTF-8 to UTF-8 or
1370 * a codepage, using standard MS-Windows functions.
1371 * 1. find out how many ucs-2 characters there are.
1372 * 2. convert from 'fileencoding' to ucs-2
1373 * 3. convert from ucs-2 to 'encoding'
1374 */
1375 char_u *ucsp;
1376 size_t from_size = size;
1377 int needed;
1378 char_u *p;
1379 int u8c;
1380
1381 /*
1382 * 1. find out how many ucs-2 characters there are.
1383 */
1384# ifdef CP_UTF8 /* VC 4.1 doesn't define CP_UTF8 */
1385 if (FIO_GET_CP(fio_flags) == CP_UTF8)
1386 {
1387 int l, flen;
1388
1389 /* Handle CP_UTF8 ourselves to be able to handle trailing
1390 * bytes properly. First find out the number of
1391 * characters and check for trailing bytes. */
1392 needed = 0;
1393 p = ptr;
1394 for (flen = from_size; flen > 0; flen -= l)
1395 {
1396 l = utf_ptr2len_check_len(p, flen);
1397 if (l > flen) /* incomplete char */
1398 {
1399 if (l > CONV_RESTLEN)
1400 /* weird overlong byte sequence */
1401 goto rewind_retry;
1402 mch_memmove(conv_rest, p, flen);
1403 conv_restlen = flen;
1404 from_size -= flen;
1405 break;
1406 }
1407 if (l == 1 && *p >= 0x80) /* illegal byte */
1408 goto rewind_retry;
1409 ++needed;
1410 p += l;
1411 }
1412 }
1413 else
1414# endif
1415 {
1416 /* We can't tell if the last byte of an MBCS string is
1417 * valid and MultiByteToWideChar() returns zero if it
1418 * isn't. Try the whole string, and if that fails, bump
1419 * the last byte into conv_rest and try again. */
1420 needed = MultiByteToWideChar(FIO_GET_CP(fio_flags),
1421 MB_ERR_INVALID_CHARS, (LPCSTR)ptr, from_size,
1422 NULL, 0);
1423 if (needed == 0)
1424 {
1425 conv_rest[0] = ptr[from_size - 1];
1426 conv_restlen = 1;
1427 --from_size;
1428 needed = MultiByteToWideChar(FIO_GET_CP(fio_flags),
1429 MB_ERR_INVALID_CHARS, (LPCSTR)ptr, from_size,
1430 NULL, 0);
1431 }
1432
1433 /* If there really is a conversion error, try using another
1434 * conversion. */
1435 if (needed == 0)
1436 goto rewind_retry;
1437 }
1438
1439 /*
1440 * 2. convert from 'fileencoding' to ucs-2
1441 *
1442 * Put the result of conversion to UCS-2 at the end of the
1443 * buffer, then convert from UCS-2 to UTF-8 or "enc_codepage"
1444 * into the start of the buffer. If there is not enough space
1445 * just fail, there is probably something wrong.
1446 */
1447 ucsp = ptr + real_size - (needed * sizeof(WCHAR));
1448 if (ucsp < ptr + size)
1449 goto rewind_retry;
1450
1451# ifdef CP_UTF8 /* VC 4.1 doesn't define CP_UTF8 */
1452 if (FIO_GET_CP(fio_flags) == CP_UTF8)
1453 {
1454 int l, flen;
1455
1456 /* Convert from utf-8 to ucs-2. */
1457 needed = 0;
1458 p = ptr;
1459 for (flen = from_size; flen > 0; flen -= l)
1460 {
1461 l = utf_ptr2len_check_len(p, flen);
1462 u8c = utf_ptr2char(p);
1463 ucsp[needed * 2] = (u8c & 0xff);
1464 ucsp[needed * 2 + 1] = (u8c >> 8);
1465 ++needed;
1466 p += l;
1467 }
1468 }
1469 else
1470# endif
1471 needed = MultiByteToWideChar(FIO_GET_CP(fio_flags),
1472 MB_ERR_INVALID_CHARS, (LPCSTR)ptr,
1473 from_size, (LPWSTR)ucsp, needed);
1474
1475 /*
1476 * 3. convert from ucs-2 to 'encoding'
1477 */
1478 if (enc_utf8)
1479 {
1480 /* From UCS-2 to UTF-8. Cannot fail. */
1481 p = ptr;
1482 for (; needed > 0; --needed)
1483 {
1484 u8c = *ucsp++;
1485 u8c += (*ucsp++ << 8);
1486 p += utf_char2bytes(u8c, p);
1487 }
1488 size = p - ptr;
1489 }
1490 else
1491 {
1492 BOOL bad = FALSE;
1493
1494 /* From UCS-2 to "enc_codepage". If the conversion uses
1495 * the default character "?", the data doesn't fit in this
1496 * encoding, so fail (unless forced). */
1497 size = WideCharToMultiByte(enc_codepage, 0,
1498 (LPCWSTR)ucsp, needed,
1499 (LPSTR)ptr, real_size, "?", &bad);
1500 if (bad && !keep_dest_enc)
1501 goto rewind_retry;
1502 }
1503 }
1504 else
1505# endif
1506# ifdef MACOS_X
1507 if (fio_flags & FIO_MACROMAN)
1508 {
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00001509 extern int macroman2enc __ARGS((char_u *ptr, long *sizep, long
1510 real_size));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001511 /*
1512 * Conversion from Apple MacRoman char encoding to UTF-8 or
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00001513 * latin1. This is in os_mac_conv.c.
Bram Moolenaar071d4272004-06-13 20:20:40 +00001514 */
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00001515 if (macroman2enc(ptr, &size, real_size) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001516 goto rewind_retry;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001517 }
1518 else
1519# endif
1520 if (fio_flags != 0)
1521 {
1522 int u8c;
1523 char_u *dest;
1524 char_u *tail = NULL;
1525
1526 /*
1527 * "enc_utf8" set: Convert Unicode or Latin1 to UTF-8.
1528 * "enc_utf8" not set: Convert Unicode to Latin1.
1529 * Go from end to start through the buffer, because the number
1530 * of bytes may increase.
1531 * "dest" points to after where the UTF-8 bytes go, "p" points
1532 * to after the next character to convert.
1533 */
1534 dest = ptr + real_size;
1535 if (fio_flags == FIO_LATIN1 || fio_flags == FIO_UTF8)
1536 {
1537 p = ptr + size;
1538 if (fio_flags == FIO_UTF8)
1539 {
1540 /* Check for a trailing incomplete UTF-8 sequence */
1541 tail = ptr + size - 1;
1542 while (tail > ptr && (*tail & 0xc0) == 0x80)
1543 --tail;
1544 if (tail + utf_byte2len(*tail) <= ptr + size)
1545 tail = NULL;
1546 else
1547 p = tail;
1548 }
1549 }
1550 else if (fio_flags & (FIO_UCS2 | FIO_UTF16))
1551 {
1552 /* Check for a trailing byte */
1553 p = ptr + (size & ~1);
1554 if (size & 1)
1555 tail = p;
1556 if ((fio_flags & FIO_UTF16) && p > ptr)
1557 {
1558 /* Check for a trailing leading word */
1559 if (fio_flags & FIO_ENDIAN_L)
1560 {
1561 u8c = (*--p << 8);
1562 u8c += *--p;
1563 }
1564 else
1565 {
1566 u8c = *--p;
1567 u8c += (*--p << 8);
1568 }
1569 if (u8c >= 0xd800 && u8c <= 0xdbff)
1570 tail = p;
1571 else
1572 p += 2;
1573 }
1574 }
1575 else /* FIO_UCS4 */
1576 {
1577 /* Check for trailing 1, 2 or 3 bytes */
1578 p = ptr + (size & ~3);
1579 if (size & 3)
1580 tail = p;
1581 }
1582
1583 /* If there is a trailing incomplete sequence move it to
1584 * conv_rest[]. */
1585 if (tail != NULL)
1586 {
1587 conv_restlen = (int)((ptr + size) - tail);
1588 mch_memmove(conv_rest, (char_u *)tail, conv_restlen);
1589 size -= conv_restlen;
1590 }
1591
1592
1593 while (p > ptr)
1594 {
1595 if (fio_flags & FIO_LATIN1)
1596 u8c = *--p;
1597 else if (fio_flags & (FIO_UCS2 | FIO_UTF16))
1598 {
1599 if (fio_flags & FIO_ENDIAN_L)
1600 {
1601 u8c = (*--p << 8);
1602 u8c += *--p;
1603 }
1604 else
1605 {
1606 u8c = *--p;
1607 u8c += (*--p << 8);
1608 }
1609 if ((fio_flags & FIO_UTF16)
1610 && u8c >= 0xdc00 && u8c <= 0xdfff)
1611 {
1612 int u16c;
1613
1614 if (p == ptr)
1615 {
1616 /* Missing leading word. */
1617 if (can_retry)
1618 goto rewind_retry;
1619 conv_error = TRUE;
1620 }
1621
1622 /* found second word of double-word, get the first
1623 * word and compute the resulting character */
1624 if (fio_flags & FIO_ENDIAN_L)
1625 {
1626 u16c = (*--p << 8);
1627 u16c += *--p;
1628 }
1629 else
1630 {
1631 u16c = *--p;
1632 u16c += (*--p << 8);
1633 }
1634 /* Check if the word is indeed a leading word. */
1635 if (u16c < 0xd800 || u16c > 0xdbff)
1636 {
1637 if (can_retry)
1638 goto rewind_retry;
1639 conv_error = TRUE;
1640 }
1641 u8c = 0x10000 + ((u16c & 0x3ff) << 10)
1642 + (u8c & 0x3ff);
1643 }
1644 }
1645 else if (fio_flags & FIO_UCS4)
1646 {
1647 if (fio_flags & FIO_ENDIAN_L)
1648 {
1649 u8c = (*--p << 24);
1650 u8c += (*--p << 16);
1651 u8c += (*--p << 8);
1652 u8c += *--p;
1653 }
1654 else /* big endian */
1655 {
1656 u8c = *--p;
1657 u8c += (*--p << 8);
1658 u8c += (*--p << 16);
1659 u8c += (*--p << 24);
1660 }
1661 }
1662 else /* UTF-8 */
1663 {
1664 if (*--p < 0x80)
1665 u8c = *p;
1666 else
1667 {
1668 len = utf_head_off(ptr, p);
1669 if (len == 0)
1670 {
1671 /* Not a valid UTF-8 character, retry with
1672 * another fenc when possible, otherwise just
1673 * report the error. */
1674 if (can_retry)
1675 goto rewind_retry;
1676 conv_error = TRUE;
1677 }
1678 p -= len;
1679 u8c = utf_ptr2char(p);
1680 }
1681 }
1682 if (enc_utf8) /* produce UTF-8 */
1683 {
1684 dest -= utf_char2len(u8c);
1685 (void)utf_char2bytes(u8c, dest);
1686 }
1687 else /* produce Latin1 */
1688 {
1689 --dest;
1690 if (u8c >= 0x100)
1691 {
1692 /* character doesn't fit in latin1, retry with
1693 * another fenc when possible, otherwise just
1694 * report the error. */
1695 if (can_retry && !keep_dest_enc)
1696 goto rewind_retry;
1697 *dest = 0xBF;
1698 conv_error = TRUE;
1699 }
1700 else
1701 *dest = u8c;
1702 }
1703 }
1704
1705 /* move the linerest to before the converted characters */
1706 line_start = dest - linerest;
1707 mch_memmove(line_start, buffer, (size_t)linerest);
1708 size = (long)((ptr + real_size) - dest);
1709 ptr = dest;
1710 }
1711 else if (enc_utf8 && !conv_error && !curbuf->b_p_bin)
1712 {
1713 /* Reading UTF-8: Check if the bytes are valid UTF-8.
1714 * Need to start before "ptr" when part of the character was
1715 * read in the previous read() call. */
1716 for (p = ptr - utf_head_off(buffer, ptr); p < ptr + size; ++p)
1717 {
1718 if (*p >= 0x80)
1719 {
1720 len = utf_ptr2len_check(p);
1721 /* A length of 1 means it's an illegal byte. Accept
1722 * an incomplete character at the end though, the next
1723 * read() will get the next bytes, we'll check it
1724 * then. */
1725 if (len == 1)
1726 {
1727 p += utf_byte2len(*p) - 1;
1728 break;
1729 }
1730 p += len - 1;
1731 }
1732 }
1733 if (p < ptr + size)
1734 {
1735 /* Detected a UTF-8 error. */
1736 if (can_retry)
1737 {
1738rewind_retry:
1739 /* Retry reading with another conversion. */
1740# if defined(FEAT_EVAL) && defined(USE_ICONV)
1741 if (*p_ccv != NUL && iconv_fd != (iconv_t)-1)
1742 /* iconv() failed, try 'charconvert' */
1743 did_iconv = TRUE;
1744 else
1745# endif
1746 /* use next item from 'fileencodings' */
1747 advance_fenc = TRUE;
1748 file_rewind = TRUE;
1749 goto retry;
1750 }
1751
1752 /* There is no alternative fenc, just report the error. */
1753# ifdef USE_ICONV
1754 if (iconv_fd != (iconv_t)-1)
1755 conv_error = TRUE;
1756 else
1757# endif
1758 {
1759 char_u *s;
1760
1761 /* Estimate the line number. */
1762 illegal_byte = curbuf->b_ml.ml_line_count - linecnt + 1;
1763 for (s = ptr; s < p; ++s)
1764 if (*s == '\n')
1765 ++illegal_byte;
1766 }
1767 }
1768 }
1769#endif
1770
1771 /* count the number of characters (after conversion!) */
1772 filesize += size;
1773
1774 /*
1775 * when reading the first part of a file: guess EOL type
1776 */
1777 if (fileformat == EOL_UNKNOWN)
1778 {
1779 /* First try finding a NL, for Dos and Unix */
1780 if (try_dos || try_unix)
1781 {
1782 for (p = ptr; p < ptr + size; ++p)
1783 {
1784 if (*p == NL)
1785 {
1786 if (!try_unix
1787 || (try_dos && p > ptr && p[-1] == CAR))
1788 fileformat = EOL_DOS;
1789 else
1790 fileformat = EOL_UNIX;
1791 break;
1792 }
1793 }
1794
1795 /* Don't give in to EOL_UNIX if EOL_MAC is more likely */
1796 if (fileformat == EOL_UNIX && try_mac)
1797 {
1798 /* Need to reset the counters when retrying fenc. */
1799 try_mac = 1;
1800 try_unix = 1;
1801 for (; p >= ptr && *p != CAR; p--)
1802 ;
1803 if (p >= ptr)
1804 {
1805 for (p = ptr; p < ptr + size; ++p)
1806 {
1807 if (*p == NL)
1808 try_unix++;
1809 else if (*p == CAR)
1810 try_mac++;
1811 }
1812 if (try_mac > try_unix)
1813 fileformat = EOL_MAC;
1814 }
1815 }
1816 }
1817
1818 /* No NL found: may use Mac format */
1819 if (fileformat == EOL_UNKNOWN && try_mac)
1820 fileformat = EOL_MAC;
1821
1822 /* Still nothing found? Use first format in 'ffs' */
1823 if (fileformat == EOL_UNKNOWN)
1824 fileformat = default_fileformat();
1825
1826 /* if editing a new file: may set p_tx and p_ff */
1827 if (newfile)
1828 set_fileformat(fileformat, OPT_LOCAL);
1829 }
1830 }
1831
1832 /*
1833 * This loop is executed once for every character read.
1834 * Keep it fast!
1835 */
1836 if (fileformat == EOL_MAC)
1837 {
1838 --ptr;
1839 while (++ptr, --size >= 0)
1840 {
1841 /* catch most common case first */
1842 if ((c = *ptr) != NUL && c != CAR && c != NL)
1843 continue;
1844 if (c == NUL)
1845 *ptr = NL; /* NULs are replaced by newlines! */
1846 else if (c == NL)
1847 *ptr = CAR; /* NLs are replaced by CRs! */
1848 else
1849 {
1850 if (skip_count == 0)
1851 {
1852 *ptr = NUL; /* end of line */
1853 len = (colnr_T) (ptr - line_start + 1);
1854 if (ml_append(lnum, line_start, len, newfile) == FAIL)
1855 {
1856 error = TRUE;
1857 break;
1858 }
1859 ++lnum;
1860 if (--read_count == 0)
1861 {
1862 error = TRUE; /* break loop */
1863 line_start = ptr; /* nothing left to write */
1864 break;
1865 }
1866 }
1867 else
1868 --skip_count;
1869 line_start = ptr + 1;
1870 }
1871 }
1872 }
1873 else
1874 {
1875 --ptr;
1876 while (++ptr, --size >= 0)
1877 {
1878 if ((c = *ptr) != NUL && c != NL) /* catch most common case */
1879 continue;
1880 if (c == NUL)
1881 *ptr = NL; /* NULs are replaced by newlines! */
1882 else
1883 {
1884 if (skip_count == 0)
1885 {
1886 *ptr = NUL; /* end of line */
1887 len = (colnr_T)(ptr - line_start + 1);
1888 if (fileformat == EOL_DOS)
1889 {
1890 if (ptr[-1] == CAR) /* remove CR */
1891 {
1892 ptr[-1] = NUL;
1893 --len;
1894 }
1895 /*
1896 * Reading in Dos format, but no CR-LF found!
1897 * When 'fileformats' includes "unix", delete all
1898 * the lines read so far and start all over again.
1899 * Otherwise give an error message later.
1900 */
1901 else if (ff_error != EOL_DOS)
1902 {
1903 if ( try_unix
1904 && !read_stdin
1905 && (read_buffer
1906 || lseek(fd, (off_t)0L, SEEK_SET) == 0))
1907 {
1908 fileformat = EOL_UNIX;
1909 if (newfile)
1910 set_fileformat(EOL_UNIX, OPT_LOCAL);
1911 file_rewind = TRUE;
1912 keep_fileformat = TRUE;
1913 goto retry;
1914 }
1915 ff_error = EOL_DOS;
1916 }
1917 }
1918 if (ml_append(lnum, line_start, len, newfile) == FAIL)
1919 {
1920 error = TRUE;
1921 break;
1922 }
1923 ++lnum;
1924 if (--read_count == 0)
1925 {
1926 error = TRUE; /* break loop */
1927 line_start = ptr; /* nothing left to write */
1928 break;
1929 }
1930 }
1931 else
1932 --skip_count;
1933 line_start = ptr + 1;
1934 }
1935 }
1936 }
1937 linerest = (long)(ptr - line_start);
1938 ui_breakcheck();
1939 }
1940
1941failed:
1942 /* not an error, max. number of lines reached */
1943 if (error && read_count == 0)
1944 error = FALSE;
1945
1946 /*
1947 * If we get EOF in the middle of a line, note the fact and
1948 * complete the line ourselves.
1949 * In Dos format ignore a trailing CTRL-Z, unless 'binary' set.
1950 */
1951 if (!error
1952 && !got_int
1953 && linerest != 0
1954 && !(!curbuf->b_p_bin
1955 && fileformat == EOL_DOS
1956 && *line_start == Ctrl_Z
1957 && ptr == line_start + 1))
1958 {
1959 if (newfile) /* remember for when writing */
1960 curbuf->b_p_eol = FALSE;
1961 *ptr = NUL;
1962 if (ml_append(lnum, line_start,
1963 (colnr_T)(ptr - line_start + 1), newfile) == FAIL)
1964 error = TRUE;
1965 else
1966 read_no_eol_lnum = ++lnum;
1967 }
1968
1969 if (newfile)
1970 save_file_ff(curbuf); /* remember the current file format */
1971
1972#ifdef FEAT_CRYPT
1973 if (cryptkey != curbuf->b_p_key)
1974 vim_free(cryptkey);
1975#endif
1976
1977#ifdef FEAT_MBYTE
1978 /* If editing a new file: set 'fenc' for the current buffer. */
1979 if (newfile)
1980 set_string_option_direct((char_u *)"fenc", -1, fenc,
1981 OPT_FREE|OPT_LOCAL);
1982 if (fenc_alloced)
1983 vim_free(fenc);
1984# ifdef USE_ICONV
1985 if (iconv_fd != (iconv_t)-1)
1986 {
1987 iconv_close(iconv_fd);
1988 iconv_fd = (iconv_t)-1;
1989 }
1990# endif
1991#endif
1992
1993 if (!read_buffer && !read_stdin)
1994 close(fd); /* errors are ignored */
1995 vim_free(buffer);
1996
1997#ifdef HAVE_DUP
1998 if (read_stdin)
1999 {
2000 /* Use stderr for stdin, makes shell commands work. */
2001 close(0);
2002 dup(2);
2003 }
2004#endif
2005
2006#ifdef FEAT_MBYTE
2007 if (tmpname != NULL)
2008 {
2009 mch_remove(tmpname); /* delete converted file */
2010 vim_free(tmpname);
2011 }
2012#endif
2013 --no_wait_return; /* may wait for return now */
2014
2015 /*
2016 * In recovery mode everything but autocommands is skipped.
2017 */
2018 if (!recoverymode)
2019 {
2020 /* need to delete the last line, which comes from the empty buffer */
2021 if (newfile && wasempty && !(curbuf->b_ml.ml_flags & ML_EMPTY))
2022 {
2023#ifdef FEAT_NETBEANS_INTG
2024 netbeansFireChanges = 0;
2025#endif
2026 ml_delete(curbuf->b_ml.ml_line_count, FALSE);
2027#ifdef FEAT_NETBEANS_INTG
2028 netbeansFireChanges = 1;
2029#endif
2030 --linecnt;
2031 }
2032 linecnt = curbuf->b_ml.ml_line_count - linecnt;
2033 if (filesize == 0)
2034 linecnt = 0;
2035 if (newfile || read_buffer)
2036 redraw_curbuf_later(NOT_VALID);
2037 else if (linecnt) /* appended at least one line */
2038 appended_lines_mark(from, linecnt);
2039
2040#ifdef FEAT_DIFF
2041 /* After reading the text into the buffer the diff info needs to be
2042 * updated. */
2043 if ((newfile || read_buffer))
2044 diff_invalidate();
2045#endif
2046#ifndef ALWAYS_USE_GUI
2047 /*
2048 * If we were reading from the same terminal as where messages go,
2049 * the screen will have been messed up.
2050 * Switch on raw mode now and clear the screen.
2051 */
2052 if (read_stdin)
2053 {
2054 settmode(TMODE_RAW); /* set to raw mode */
2055 starttermcap();
2056 screenclear();
2057 }
2058#endif
2059
2060 if (got_int)
2061 {
2062 if (!(flags & READ_DUMMY))
2063 {
2064 filemess(curbuf, sfname, (char_u *)_(e_interr), 0);
2065 if (newfile)
2066 curbuf->b_p_ro = TRUE; /* must use "w!" now */
2067 }
2068 msg_scroll = msg_save;
2069#ifdef FEAT_VIMINFO
2070 check_marks_read();
2071#endif
2072 return OK; /* an interrupt isn't really an error */
2073 }
2074
2075 if (!filtering && !(flags & READ_DUMMY))
2076 {
2077 msg_add_fname(curbuf, sfname); /* fname in IObuff with quotes */
2078 c = FALSE;
2079
2080#ifdef UNIX
2081# ifdef S_ISFIFO
2082 if (S_ISFIFO(perm)) /* fifo or socket */
2083 {
2084 STRCAT(IObuff, _("[fifo/socket]"));
2085 c = TRUE;
2086 }
2087# else
2088# ifdef S_IFIFO
2089 if ((perm & S_IFMT) == S_IFIFO) /* fifo */
2090 {
2091 STRCAT(IObuff, _("[fifo]"));
2092 c = TRUE;
2093 }
2094# endif
2095# ifdef S_IFSOCK
2096 if ((perm & S_IFMT) == S_IFSOCK) /* or socket */
2097 {
2098 STRCAT(IObuff, _("[socket]"));
2099 c = TRUE;
2100 }
2101# endif
2102# endif
2103#endif
2104 if (curbuf->b_p_ro)
2105 {
2106 STRCAT(IObuff, shortmess(SHM_RO) ? _("[RO]") : _("[readonly]"));
2107 c = TRUE;
2108 }
2109 if (read_no_eol_lnum)
2110 {
2111 msg_add_eol();
2112 c = TRUE;
2113 }
2114 if (ff_error == EOL_DOS)
2115 {
2116 STRCAT(IObuff, _("[CR missing]"));
2117 c = TRUE;
2118 }
2119 if (ff_error == EOL_MAC)
2120 {
2121 STRCAT(IObuff, _("[NL found]"));
2122 c = TRUE;
2123 }
2124 if (split)
2125 {
2126 STRCAT(IObuff, _("[long lines split]"));
2127 c = TRUE;
2128 }
2129#ifdef FEAT_MBYTE
2130 if (notconverted)
2131 {
2132 STRCAT(IObuff, _("[NOT converted]"));
2133 c = TRUE;
2134 }
2135 else if (converted)
2136 {
2137 STRCAT(IObuff, _("[converted]"));
2138 c = TRUE;
2139 }
2140#endif
2141#ifdef FEAT_CRYPT
2142 if (cryptkey != NULL)
2143 {
2144 STRCAT(IObuff, _("[crypted]"));
2145 c = TRUE;
2146 }
2147#endif
2148#ifdef FEAT_MBYTE
2149 if (conv_error)
2150 {
2151 STRCAT(IObuff, _("[CONVERSION ERROR]"));
2152 c = TRUE;
2153 }
2154 else if (illegal_byte > 0)
2155 {
2156 sprintf((char *)IObuff + STRLEN(IObuff),
2157 _("[ILLEGAL BYTE in line %ld]"), (long)illegal_byte);
2158 c = TRUE;
2159 }
2160 else
2161#endif
2162 if (error)
2163 {
2164 STRCAT(IObuff, _("[READ ERRORS]"));
2165 c = TRUE;
2166 }
2167 if (msg_add_fileformat(fileformat))
2168 c = TRUE;
2169#ifdef FEAT_CRYPT
2170 if (cryptkey != NULL)
2171 msg_add_lines(c, (long)linecnt, filesize - CRYPT_MAGIC_LEN);
2172 else
2173#endif
2174 msg_add_lines(c, (long)linecnt, filesize);
2175
2176 vim_free(keep_msg);
2177 keep_msg = NULL;
2178 msg_scrolled_ign = TRUE;
2179#ifdef ALWAYS_USE_GUI
2180 /* Don't show the message when reading stdin, it would end up in a
2181 * message box (which might be shown when exiting!) */
2182 if (read_stdin || read_buffer)
2183 p = msg_may_trunc(FALSE, IObuff);
2184 else
2185#endif
2186 p = msg_trunc_attr(IObuff, FALSE, 0);
2187 if (read_stdin || read_buffer || restart_edit != 0
2188 || (msg_scrolled && !need_wait_return))
2189 {
2190 /* Need to repeat the message after redrawing when:
2191 * - When reading from stdin (the screen will be cleared next).
2192 * - When restart_edit is set (otherwise there will be a delay
2193 * before redrawing).
2194 * - When the screen was scrolled but there is no wait-return
2195 * prompt. */
2196 set_keep_msg(p);
2197 keep_msg_attr = 0;
2198 }
2199 msg_scrolled_ign = FALSE;
2200 }
2201
2202 /* with errors writing the file requires ":w!" */
2203 if (newfile && (error
2204#ifdef FEAT_MBYTE
2205 || conv_error
2206#endif
2207 ))
2208 curbuf->b_p_ro = TRUE;
2209
2210 u_clearline(); /* cannot use "U" command after adding lines */
2211
2212 /*
2213 * In Ex mode: cursor at last new line.
2214 * Otherwise: cursor at first new line.
2215 */
2216 if (exmode_active)
2217 curwin->w_cursor.lnum = from + linecnt;
2218 else
2219 curwin->w_cursor.lnum = from + 1;
2220 check_cursor_lnum();
2221 beginline(BL_WHITE | BL_FIX); /* on first non-blank */
2222
2223 /*
2224 * Set '[ and '] marks to the newly read lines.
2225 */
2226 curbuf->b_op_start.lnum = from + 1;
2227 curbuf->b_op_start.col = 0;
2228 curbuf->b_op_end.lnum = from + linecnt;
2229 curbuf->b_op_end.col = 0;
2230 }
2231 msg_scroll = msg_save;
2232
2233#ifdef FEAT_VIMINFO
2234 /*
2235 * Get the marks before executing autocommands, so they can be used there.
2236 */
2237 check_marks_read();
2238#endif
2239
2240#ifdef FEAT_AUTOCMD
2241 /*
2242 * Trick: We remember if the last line of the read didn't have
2243 * an eol for when writing it again. This is required for
2244 * ":autocmd FileReadPost *.gz set bin|'[,']!gunzip" to work.
2245 */
2246 write_no_eol_lnum = read_no_eol_lnum;
2247
2248 if (!read_stdin && !read_buffer)
2249 {
2250 int m = msg_scroll;
2251 int n = msg_scrolled;
2252
2253 /* Save the fileformat now, otherwise the buffer will be considered
2254 * modified if the format/encoding was automatically detected. */
2255 if (newfile)
2256 save_file_ff(curbuf);
2257
2258 /*
2259 * The output from the autocommands should not overwrite anything and
2260 * should not be overwritten: Set msg_scroll, restore its value if no
2261 * output was done.
2262 */
2263 msg_scroll = TRUE;
2264 if (filtering)
2265 apply_autocmds_exarg(EVENT_FILTERREADPOST, NULL, sfname,
2266 FALSE, curbuf, eap);
2267 else if (newfile)
2268 apply_autocmds_exarg(EVENT_BUFREADPOST, NULL, sfname,
2269 FALSE, curbuf, eap);
2270 else
2271 apply_autocmds_exarg(EVENT_FILEREADPOST, sfname, sfname,
2272 FALSE, NULL, eap);
2273 if (msg_scrolled == n)
2274 msg_scroll = m;
2275#ifdef FEAT_EVAL
2276 if (aborting()) /* autocmds may abort script processing */
2277 return FAIL;
2278#endif
2279 }
2280#endif
2281
2282 if (recoverymode && error)
2283 return FAIL;
2284 return OK;
2285}
2286
2287/*
2288 * Fill "*eap" to force the 'fileencoding' and 'fileformat' to be equal to the
2289 * buffer "buf". Used for calling readfile().
2290 * Returns OK or FAIL.
2291 */
2292 int
2293prep_exarg(eap, buf)
2294 exarg_T *eap;
2295 buf_T *buf;
2296{
2297 eap->cmd = alloc((unsigned)(STRLEN(buf->b_p_ff)
2298#ifdef FEAT_MBYTE
2299 + STRLEN(buf->b_p_fenc)
2300#endif
2301 + 15));
2302 if (eap->cmd == NULL)
2303 return FAIL;
2304
2305#ifdef FEAT_MBYTE
2306 sprintf((char *)eap->cmd, "e ++ff=%s ++enc=%s", buf->b_p_ff, buf->b_p_fenc);
2307 eap->force_enc = 14 + (int)STRLEN(buf->b_p_ff);
2308#else
2309 sprintf((char *)eap->cmd, "e ++ff=%s", buf->b_p_ff);
2310#endif
2311 eap->force_ff = 7;
2312 return OK;
2313}
2314
2315#ifdef FEAT_MBYTE
2316/*
2317 * Find next fileencoding to use from 'fileencodings'.
2318 * "pp" points to fenc_next. It's advanced to the next item.
2319 * When there are no more items, an empty string is returned and *pp is set to
2320 * NULL.
2321 * When *pp is not set to NULL, the result is in allocated memory.
2322 */
2323 static char_u *
2324next_fenc(pp)
2325 char_u **pp;
2326{
2327 char_u *p;
2328 char_u *r;
2329
2330 if (**pp == NUL)
2331 {
2332 *pp = NULL;
2333 return (char_u *)"";
2334 }
2335 p = vim_strchr(*pp, ',');
2336 if (p == NULL)
2337 {
2338 r = enc_canonize(*pp);
2339 *pp += STRLEN(*pp);
2340 }
2341 else
2342 {
2343 r = vim_strnsave(*pp, (int)(p - *pp));
2344 *pp = p + 1;
2345 if (r != NULL)
2346 {
2347 p = enc_canonize(r);
2348 vim_free(r);
2349 r = p;
2350 }
2351 }
2352 if (r == NULL) /* out of memory */
2353 {
2354 r = (char_u *)"";
2355 *pp = NULL;
2356 }
2357 return r;
2358}
2359
2360# ifdef FEAT_EVAL
2361/*
2362 * Convert a file with the 'charconvert' expression.
2363 * This closes the file which is to be read, converts it and opens the
2364 * resulting file for reading.
2365 * Returns name of the resulting converted file (the caller should delete it
2366 * after reading it).
2367 * Returns NULL if the conversion failed ("*fdp" is not set) .
2368 */
2369 static char_u *
2370readfile_charconvert(fname, fenc, fdp)
2371 char_u *fname; /* name of input file */
2372 char_u *fenc; /* converted from */
2373 int *fdp; /* in/out: file descriptor of file */
2374{
2375 char_u *tmpname;
2376 char_u *errmsg = NULL;
2377
2378 tmpname = vim_tempname('r');
2379 if (tmpname == NULL)
2380 errmsg = (char_u *)_("Can't find temp file for conversion");
2381 else
2382 {
2383 close(*fdp); /* close the input file, ignore errors */
2384 *fdp = -1;
2385 if (eval_charconvert(fenc, enc_utf8 ? (char_u *)"utf-8" : p_enc,
2386 fname, tmpname) == FAIL)
2387 errmsg = (char_u *)_("Conversion with 'charconvert' failed");
2388 if (errmsg == NULL && (*fdp = mch_open((char *)tmpname,
2389 O_RDONLY | O_EXTRA, 0)) < 0)
2390 errmsg = (char_u *)_("can't read output of 'charconvert'");
2391 }
2392
2393 if (errmsg != NULL)
2394 {
2395 /* Don't use emsg(), it breaks mappings, the retry with
2396 * another type of conversion might still work. */
2397 MSG(errmsg);
2398 if (tmpname != NULL)
2399 {
2400 mch_remove(tmpname); /* delete converted file */
2401 vim_free(tmpname);
2402 tmpname = NULL;
2403 }
2404 }
2405
2406 /* If the input file is closed, open it (caller should check for error). */
2407 if (*fdp < 0)
2408 *fdp = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0);
2409
2410 return tmpname;
2411}
2412# endif
2413
2414#endif
2415
2416#ifdef FEAT_VIMINFO
2417/*
2418 * Read marks for the current buffer from the viminfo file, when we support
2419 * buffer marks and the buffer has a name.
2420 */
2421 static void
2422check_marks_read()
2423{
2424 if (!curbuf->b_marks_read && get_viminfo_parameter('\'') > 0
2425 && curbuf->b_ffname != NULL)
2426 read_viminfo(NULL, FALSE, TRUE, FALSE);
2427
2428 /* Always set b_marks_read; needed when 'viminfo' is changed to include
2429 * the ' parameter after opening a buffer. */
2430 curbuf->b_marks_read = TRUE;
2431}
2432#endif
2433
2434#ifdef FEAT_CRYPT
2435/*
2436 * Check for magic number used for encryption.
2437 * If found, the magic number is removed from ptr[*sizep] and *sizep and
2438 * *filesizep are updated.
2439 * Return the (new) encryption key, NULL for no encryption.
2440 */
2441 static char_u *
2442check_for_cryptkey(cryptkey, ptr, sizep, filesizep, newfile)
2443 char_u *cryptkey; /* previous encryption key or NULL */
2444 char_u *ptr; /* pointer to read bytes */
2445 long *sizep; /* length of read bytes */
2446 long *filesizep; /* nr of bytes used from file */
2447 int newfile; /* editing a new buffer */
2448{
2449 if (*sizep >= CRYPT_MAGIC_LEN
2450 && STRNCMP(ptr, CRYPT_MAGIC, CRYPT_MAGIC_LEN) == 0)
2451 {
2452 if (cryptkey == NULL)
2453 {
2454 if (*curbuf->b_p_key)
2455 cryptkey = curbuf->b_p_key;
2456 else
2457 {
2458 /* When newfile is TRUE, store the typed key
2459 * in the 'key' option and don't free it. */
2460 cryptkey = get_crypt_key(newfile, FALSE);
2461 /* check if empty key entered */
2462 if (cryptkey != NULL && *cryptkey == NUL)
2463 {
2464 if (cryptkey != curbuf->b_p_key)
2465 vim_free(cryptkey);
2466 cryptkey = NULL;
2467 }
2468 }
2469 }
2470
2471 if (cryptkey != NULL)
2472 {
2473 crypt_init_keys(cryptkey);
2474
2475 /* Remove magic number from the text */
2476 *filesizep += CRYPT_MAGIC_LEN;
2477 *sizep -= CRYPT_MAGIC_LEN;
2478 mch_memmove(ptr, ptr + CRYPT_MAGIC_LEN, (size_t)*sizep);
2479 }
2480 }
2481 /* When starting to edit a new file which does not have
2482 * encryption, clear the 'key' option, except when
2483 * starting up (called with -x argument) */
2484 else if (newfile && *curbuf->b_p_key && !starting)
2485 set_option_value((char_u *)"key", 0L, (char_u *)"", OPT_LOCAL);
2486
2487 return cryptkey;
2488}
2489#endif
2490
2491#ifdef UNIX
2492 static void
2493set_file_time(fname, atime, mtime)
2494 char_u *fname;
2495 time_t atime; /* access time */
2496 time_t mtime; /* modification time */
2497{
2498# if defined(HAVE_UTIME) && defined(HAVE_UTIME_H)
2499 struct utimbuf buf;
2500
2501 buf.actime = atime;
2502 buf.modtime = mtime;
2503 (void)utime((char *)fname, &buf);
2504# else
2505# if defined(HAVE_UTIMES)
2506 struct timeval tvp[2];
2507
2508 tvp[0].tv_sec = atime;
2509 tvp[0].tv_usec = 0;
2510 tvp[1].tv_sec = mtime;
2511 tvp[1].tv_usec = 0;
2512# ifdef NeXT
2513 (void)utimes((char *)fname, tvp);
2514# else
2515 (void)utimes((char *)fname, (const struct timeval *)&tvp);
2516# endif
2517# endif
2518# endif
2519}
2520#endif /* UNIX */
2521
Bram Moolenaard4755bb2004-09-02 19:12:26 +00002522#if defined(VMS) && !defined(MIN)
2523/* Older DECC compiler for VAX doesn't define MIN() */
2524# define MIN(a, b) ((a) < (b) ? (a) : (b))
2525#endif
2526
Bram Moolenaar071d4272004-06-13 20:20:40 +00002527/*
2528 * buf_write() - write to file 'fname' lines 'start' through 'end'
2529 *
2530 * We do our own buffering here because fwrite() is so slow.
2531 *
2532 * If forceit is true, we don't care for errors when attempting backups (jw).
2533 * In case of an error everything possible is done to restore the original file.
2534 * But when forceit is TRUE, we risk loosing it.
2535 * When reset_changed is TRUE and start == 1 and end ==
2536 * curbuf->b_ml.ml_line_count, reset curbuf->b_changed.
2537 *
2538 * This function must NOT use NameBuff (because it's called by autowrite()).
2539 *
2540 * return FAIL for failure, OK otherwise
2541 */
2542 int
2543buf_write(buf, fname, sfname, start, end, eap, append, forceit,
2544 reset_changed, filtering)
2545 buf_T *buf;
2546 char_u *fname;
2547 char_u *sfname;
2548 linenr_T start, end;
2549 exarg_T *eap; /* for forced 'ff' and 'fenc', can be
2550 NULL! */
2551 int append;
2552 int forceit;
2553 int reset_changed;
2554 int filtering;
2555{
2556 int fd;
2557 char_u *backup = NULL;
2558 int backup_copy = FALSE; /* copy the original file? */
2559 int dobackup;
2560 char_u *ffname;
2561 char_u *wfname = NULL; /* name of file to write to */
2562 char_u *s;
2563 char_u *ptr;
2564 char_u c;
2565 int len;
2566 linenr_T lnum;
2567 long nchars;
2568 char_u *errmsg = NULL;
2569 char_u *errnum = NULL;
2570 char_u *buffer;
2571 char_u smallbuf[SMBUFSIZE];
2572 char_u *backup_ext;
2573 int bufsize;
2574 long perm; /* file permissions */
2575 int retval = OK;
2576 int newfile = FALSE; /* TRUE if file doesn't exist yet */
2577 int msg_save = msg_scroll;
2578 int overwriting; /* TRUE if writing over original */
2579 int no_eol = FALSE; /* no end-of-line written */
2580 int device = FALSE; /* writing to a device */
2581 struct stat st_old;
2582 int prev_got_int = got_int;
2583 int file_readonly = FALSE; /* overwritten file is read-only */
2584 static char *err_readonly = "is read-only (cannot override: \"W\" in 'cpoptions')";
2585#if defined(UNIX) || defined(__EMX__XX) /*XXX fix me sometime? */
2586 int made_writable = FALSE; /* 'w' bit has been set */
2587#endif
2588 /* writing everything */
2589 int whole = (start == 1 && end == buf->b_ml.ml_line_count);
2590#ifdef FEAT_AUTOCMD
2591 linenr_T old_line_count = buf->b_ml.ml_line_count;
2592#endif
2593 int attr;
2594 int fileformat;
2595 int write_bin;
2596 struct bw_info write_info; /* info for buf_write_bytes() */
2597#ifdef FEAT_MBYTE
2598 int converted = FALSE;
2599 int notconverted = FALSE;
2600 char_u *fenc; /* effective 'fileencoding' */
2601 char_u *fenc_tofree = NULL; /* allocated "fenc" */
2602#endif
2603#ifdef HAS_BW_FLAGS
2604 int wb_flags = 0;
2605#endif
2606#ifdef HAVE_ACL
2607 vim_acl_T acl = NULL; /* ACL copied from original file to
2608 backup or new file */
2609#endif
2610
2611 if (fname == NULL || *fname == NUL) /* safety check */
2612 return FAIL;
2613
2614 /*
2615 * Disallow writing from .exrc and .vimrc in current directory for
2616 * security reasons.
2617 */
2618 if (check_secure())
2619 return FAIL;
2620
2621 /* Avoid a crash for a long name. */
2622 if (STRLEN(fname) >= MAXPATHL)
2623 {
2624 EMSG(_(e_longname));
2625 return FAIL;
2626 }
2627
2628#ifdef FEAT_MBYTE
2629 /* must init bw_conv_buf and bw_iconv_fd before jumping to "fail" */
2630 write_info.bw_conv_buf = NULL;
2631 write_info.bw_conv_error = FALSE;
2632 write_info.bw_restlen = 0;
2633# ifdef USE_ICONV
2634 write_info.bw_iconv_fd = (iconv_t)-1;
2635# endif
2636#endif
2637
2638 /*
2639 * If there is no file name yet, use the one for the written file.
2640 * BF_NOTEDITED is set to reflect this (in case the write fails).
2641 * Don't do this when the write is for a filter command.
2642 * Only do this when 'cpoptions' contains the 'f' flag.
2643 */
2644 if (reset_changed
2645 && whole
2646 && buf == curbuf
2647 && curbuf->b_ffname == NULL
2648 && !filtering
2649 && vim_strchr(p_cpo, CPO_FNAMEW) != NULL)
2650 {
2651#ifdef FEAT_AUTOCMD
2652 /* It's like the unnamed buffer is deleted.... */
2653 if (curbuf->b_p_bl)
2654 apply_autocmds(EVENT_BUFDELETE, NULL, NULL, FALSE, curbuf);
2655 apply_autocmds(EVENT_BUFWIPEOUT, NULL, NULL, FALSE, curbuf);
2656#ifdef FEAT_EVAL
2657 if (aborting()) /* autocmds may abort script processing */
2658 return FAIL;
2659#endif
2660#endif
2661 if (setfname(curbuf, fname, sfname, FALSE) == OK)
2662 curbuf->b_flags |= BF_NOTEDITED;
2663#ifdef FEAT_AUTOCMD
2664 /* ....and a new named one is created */
2665 apply_autocmds(EVENT_BUFNEW, NULL, NULL, FALSE, curbuf);
2666 if (curbuf->b_p_bl)
2667 apply_autocmds(EVENT_BUFADD, NULL, NULL, FALSE, curbuf);
2668#endif
2669 }
2670
2671 if (sfname == NULL)
2672 sfname = fname;
2673 /*
2674 * For Unix: Use the short file name whenever possible.
2675 * Avoids problems with networks and when directory names are changed.
2676 * Don't do this for MS-DOS, a "cd" in a sub-shell may have moved us to
2677 * another directory, which we don't detect
2678 */
2679 ffname = fname; /* remember full fname */
2680#ifdef UNIX
2681 fname = sfname;
2682#endif
2683
2684 if (buf->b_ffname != NULL && fnamecmp(ffname, buf->b_ffname) == 0)
2685 overwriting = TRUE;
2686 else
2687 overwriting = FALSE;
2688
2689 if (exiting)
2690 settmode(TMODE_COOK); /* when exiting allow typahead now */
2691
2692 ++no_wait_return; /* don't wait for return yet */
2693
2694 /*
2695 * Set '[ and '] marks to the lines to be written.
2696 */
2697 buf->b_op_start.lnum = start;
2698 buf->b_op_start.col = 0;
2699 buf->b_op_end.lnum = end;
2700 buf->b_op_end.col = 0;
2701
2702#ifdef FEAT_AUTOCMD
2703 {
2704 aco_save_T aco;
2705 int buf_ffname = FALSE;
2706 int buf_sfname = FALSE;
2707 int buf_fname_f = FALSE;
2708 int buf_fname_s = FALSE;
2709 int did_cmd = FALSE;
Bram Moolenaar21cf8232004-07-16 20:18:37 +00002710 int nofile_err = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002711
2712 /*
2713 * Apply PRE aucocommands.
2714 * Set curbuf to the buffer to be written.
2715 * Careful: The autocommands may call buf_write() recursively!
2716 */
2717 if (ffname == buf->b_ffname)
2718 buf_ffname = TRUE;
2719 if (sfname == buf->b_sfname)
2720 buf_sfname = TRUE;
2721 if (fname == buf->b_ffname)
2722 buf_fname_f = TRUE;
2723 if (fname == buf->b_sfname)
2724 buf_fname_s = TRUE;
2725
2726 /* set curwin/curbuf to buf and save a few things */
2727 aucmd_prepbuf(&aco, buf);
2728
2729 if (append)
2730 {
2731 if (!(did_cmd = apply_autocmds_exarg(EVENT_FILEAPPENDCMD,
2732 sfname, sfname, FALSE, curbuf, eap)))
Bram Moolenaar21cf8232004-07-16 20:18:37 +00002733 {
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00002734 if (overwriting && bt_nofile(curbuf))
Bram Moolenaar21cf8232004-07-16 20:18:37 +00002735 nofile_err = TRUE;
2736 else
2737 apply_autocmds_exarg(EVENT_FILEAPPENDPRE,
Bram Moolenaar071d4272004-06-13 20:20:40 +00002738 sfname, sfname, FALSE, curbuf, eap);
Bram Moolenaar21cf8232004-07-16 20:18:37 +00002739 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002740 }
2741 else if (filtering)
2742 {
2743 apply_autocmds_exarg(EVENT_FILTERWRITEPRE,
2744 NULL, sfname, FALSE, curbuf, eap);
2745 }
2746 else if (reset_changed && whole)
2747 {
2748 if (!(did_cmd = apply_autocmds_exarg(EVENT_BUFWRITECMD,
2749 sfname, sfname, FALSE, curbuf, eap)))
Bram Moolenaar21cf8232004-07-16 20:18:37 +00002750 {
2751 if (bt_nofile(curbuf))
2752 nofile_err = TRUE;
2753 else
2754 apply_autocmds_exarg(EVENT_BUFWRITEPRE,
Bram Moolenaar071d4272004-06-13 20:20:40 +00002755 sfname, sfname, FALSE, curbuf, eap);
Bram Moolenaar21cf8232004-07-16 20:18:37 +00002756 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002757 }
2758 else
2759 {
2760 if (!(did_cmd = apply_autocmds_exarg(EVENT_FILEWRITECMD,
2761 sfname, sfname, FALSE, curbuf, eap)))
Bram Moolenaar21cf8232004-07-16 20:18:37 +00002762 {
2763 if (bt_nofile(curbuf))
2764 nofile_err = TRUE;
2765 else
2766 apply_autocmds_exarg(EVENT_FILEWRITEPRE,
Bram Moolenaar071d4272004-06-13 20:20:40 +00002767 sfname, sfname, FALSE, curbuf, eap);
Bram Moolenaar21cf8232004-07-16 20:18:37 +00002768 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002769 }
2770
2771 /* restore curwin/curbuf and a few other things */
2772 aucmd_restbuf(&aco);
2773
2774 /*
2775 * In three situations we return here and don't write the file:
2776 * 1. the autocommands deleted or unloaded the buffer.
2777 * 2. The autocommands abort script processing.
2778 * 3. If one of the "Cmd" autocommands was executed.
2779 */
2780 if (!buf_valid(buf))
2781 buf = NULL;
Bram Moolenaar21cf8232004-07-16 20:18:37 +00002782 if (buf == NULL || buf->b_ml.ml_mfp == NULL
2783 || did_cmd || nofile_err || aborting())
Bram Moolenaar071d4272004-06-13 20:20:40 +00002784 {
2785 --no_wait_return;
2786 msg_scroll = msg_save;
Bram Moolenaar21cf8232004-07-16 20:18:37 +00002787 if (nofile_err)
2788 EMSG(_("E676: No matching autocommands for acwrite buffer"));
2789
2790 if (aborting() || nofile_err)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002791 /* An aborting error, interrupt or exception in the
2792 * autocommands. */
2793 return FAIL;
2794 if (did_cmd)
2795 {
2796 if (buf == NULL)
2797 /* The buffer was deleted. We assume it was written
2798 * (can't retry anyway). */
2799 return OK;
2800 if (overwriting)
2801 {
2802 /* Assume the buffer was written, update the timestamp. */
2803 ml_timestamp(buf);
2804 buf->b_flags &= ~BF_WRITE_MASK;
2805 }
2806 if (reset_changed && buf->b_changed)
2807 /* Buffer still changed, the autocommands didn't work
2808 * properly. */
2809 return FAIL;
2810 return OK;
2811 }
2812#ifdef FEAT_EVAL
2813 if (!aborting())
2814#endif
2815 EMSG(_("E203: Autocommands deleted or unloaded buffer to be written"));
2816 return FAIL;
2817 }
2818
2819 /*
2820 * The autocommands may have changed the number of lines in the file.
2821 * When writing the whole file, adjust the end.
2822 * When writing part of the file, assume that the autocommands only
2823 * changed the number of lines that are to be written (tricky!).
2824 */
2825 if (buf->b_ml.ml_line_count != old_line_count)
2826 {
2827 if (whole) /* write all */
2828 end = buf->b_ml.ml_line_count;
2829 else if (buf->b_ml.ml_line_count > old_line_count) /* more lines */
2830 end += buf->b_ml.ml_line_count - old_line_count;
2831 else /* less lines */
2832 {
2833 end -= old_line_count - buf->b_ml.ml_line_count;
2834 if (end < start)
2835 {
2836 --no_wait_return;
2837 msg_scroll = msg_save;
2838 EMSG(_("E204: Autocommand changed number of lines in unexpected way"));
2839 return FAIL;
2840 }
2841 }
2842 }
2843
2844 /*
2845 * The autocommands may have changed the name of the buffer, which may
2846 * be kept in fname, ffname and sfname.
2847 */
2848 if (buf_ffname)
2849 ffname = buf->b_ffname;
2850 if (buf_sfname)
2851 sfname = buf->b_sfname;
2852 if (buf_fname_f)
2853 fname = buf->b_ffname;
2854 if (buf_fname_s)
2855 fname = buf->b_sfname;
2856 }
2857#endif
2858
2859#ifdef FEAT_NETBEANS_INTG
2860 if (usingNetbeans && isNetbeansBuffer(buf))
2861 {
2862 if (whole)
2863 {
2864 /*
2865 * b_changed can be 0 after an undo, but we still need to write
2866 * the buffer to NetBeans.
2867 */
2868 if (buf->b_changed || isNetbeansModified(buf))
2869 {
2870 netbeans_save_buffer(buf);
2871 return retval;
2872 }
2873 else
2874 {
2875 errnum = (char_u *)"E656: ";
2876 errmsg = (char_u *)_("NetBeans dissallows writes of unmodified buffers");
2877 buffer = NULL;
2878 goto fail;
2879 }
2880 }
2881 else
2882 {
2883 errnum = (char_u *)"E657: ";
2884 errmsg = (char_u *)_("Partial writes disallowed for NetBeans buffers");
2885 buffer = NULL;
2886 goto fail;
2887 }
2888 }
2889#endif
2890
2891 if (shortmess(SHM_OVER) && !exiting)
2892 msg_scroll = FALSE; /* overwrite previous file message */
2893 else
2894 msg_scroll = TRUE; /* don't overwrite previous file message */
2895 if (!filtering)
2896 filemess(buf,
2897#ifndef UNIX
2898 sfname,
2899#else
2900 fname,
2901#endif
2902 (char_u *)"", 0); /* show that we are busy */
2903 msg_scroll = FALSE; /* always overwrite the file message now */
2904
2905 buffer = alloc(BUFSIZE);
2906 if (buffer == NULL) /* can't allocate big buffer, use small
2907 * one (to be able to write when out of
2908 * memory) */
2909 {
2910 buffer = smallbuf;
2911 bufsize = SMBUFSIZE;
2912 }
2913 else
2914 bufsize = BUFSIZE;
2915
2916 /*
2917 * Get information about original file (if there is one).
2918 */
2919#if defined(UNIX) && !defined(ARCHIE)
2920 st_old.st_dev = st_old.st_ino = 0;
2921 perm = -1;
2922 if (mch_stat((char *)fname, &st_old) < 0)
2923 newfile = TRUE;
2924 else
2925 {
2926 perm = st_old.st_mode;
2927 if (!S_ISREG(st_old.st_mode)) /* not a file */
2928 {
2929 if (S_ISDIR(st_old.st_mode))
2930 {
2931 errnum = (char_u *)"E502: ";
2932 errmsg = (char_u *)_("is a directory");
2933 goto fail;
2934 }
2935 if (mch_nodetype(fname) != NODE_WRITABLE)
2936 {
2937 errnum = (char_u *)"E503: ";
2938 errmsg = (char_u *)_("is not a file or writable device");
2939 goto fail;
2940 }
2941 /* It's a device of some kind (or a fifo) which we can write to
2942 * but for which we can't make a backup. */
2943 device = TRUE;
2944 newfile = TRUE;
2945 perm = -1;
2946 }
2947 }
2948#else /* !UNIX */
2949 /*
2950 * Check for a writable device name.
2951 */
2952 c = mch_nodetype(fname);
2953 if (c == NODE_OTHER)
2954 {
2955 errnum = (char_u *)"E503: ";
2956 errmsg = (char_u *)_("is not a file or writable device");
2957 goto fail;
2958 }
2959 if (c == NODE_WRITABLE)
2960 {
2961 device = TRUE;
2962 newfile = TRUE;
2963 perm = -1;
2964 }
2965 else
2966 {
2967 perm = mch_getperm(fname);
2968 if (perm < 0)
2969 newfile = TRUE;
2970 else if (mch_isdir(fname))
2971 {
2972 errnum = (char_u *)"E502: ";
2973 errmsg = (char_u *)_("is a directory");
2974 goto fail;
2975 }
2976 if (overwriting)
2977 (void)mch_stat((char *)fname, &st_old);
2978 }
2979#endif /* !UNIX */
2980
2981 if (!device && !newfile)
2982 {
2983 /*
2984 * Check if the file is really writable (when renaming the file to
2985 * make a backup we won't discover it later).
2986 */
2987 file_readonly = (
2988# ifdef USE_MCH_ACCESS
2989# ifdef UNIX
2990 (perm & 0222) == 0 ||
2991# endif
2992 mch_access((char *)fname, W_OK)
2993# else
2994 (fd = mch_open((char *)fname, O_RDWR | O_EXTRA, 0)) < 0
2995 ? TRUE : (close(fd), FALSE)
2996# endif
2997 );
2998 if (!forceit && file_readonly)
2999 {
3000 if (vim_strchr(p_cpo, CPO_FWRITE) != NULL)
3001 {
3002 errnum = (char_u *)"E504: ";
3003 errmsg = (char_u *)_(err_readonly);
3004 }
3005 else
3006 {
3007 errnum = (char_u *)"E505: ";
3008 errmsg = (char_u *)_("is read-only (add ! to override)");
3009 }
3010 goto fail;
3011 }
3012
3013 /*
3014 * Check if the timestamp hasn't changed since reading the file.
3015 */
3016 if (overwriting)
3017 {
3018 retval = check_mtime(buf, &st_old);
3019 if (retval == FAIL)
3020 goto fail;
3021 }
3022 }
3023
3024#ifdef HAVE_ACL
3025 /*
3026 * For systems that support ACL: get the ACL from the original file.
3027 */
3028 if (!newfile)
3029 acl = mch_get_acl(fname);
3030#endif
3031
3032 /*
3033 * If 'backupskip' is not empty, don't make a backup for some files.
3034 */
3035 dobackup = (p_wb || p_bk || *p_pm != NUL);
3036#ifdef FEAT_WILDIGN
3037 if (dobackup && *p_bsk != NUL && match_file_list(p_bsk, sfname, ffname))
3038 dobackup = FALSE;
3039#endif
3040
3041 /*
3042 * Save the value of got_int and reset it. We don't want a previous
3043 * interruption cancel writing, only hitting CTRL-C while writing should
3044 * abort it.
3045 */
3046 prev_got_int = got_int;
3047 got_int = FALSE;
3048
3049 /* Mark the buffer as 'being saved' to prevent changed buffer warnings */
3050 buf->b_saving = TRUE;
3051
3052 /*
3053 * If we are not appending or filtering, the file exists, and the
3054 * 'writebackup', 'backup' or 'patchmode' option is set, need a backup.
3055 * When 'patchmode' is set also make a backup when appending.
3056 *
3057 * Do not make any backup, if 'writebackup' and 'backup' are both switched
3058 * off. This helps when editing large files on almost-full disks.
3059 */
3060 if (!(append && *p_pm == NUL) && !filtering && perm >= 0 && dobackup)
3061 {
3062#if defined(UNIX) || defined(WIN32)
3063 struct stat st;
3064#endif
3065
3066 if ((bkc_flags & BKC_YES) || append) /* "yes" */
3067 backup_copy = TRUE;
3068#if defined(UNIX) || defined(WIN32)
3069 else if ((bkc_flags & BKC_AUTO)) /* "auto" */
3070 {
3071 int i;
3072
3073# ifdef UNIX
3074 /*
3075 * Don't rename the file when:
3076 * - it's a hard link
3077 * - it's a symbolic link
3078 * - we don't have write permission in the directory
3079 * - we can't set the owner/group of the new file
3080 */
3081 if (st_old.st_nlink > 1
3082 || mch_lstat((char *)fname, &st) < 0
3083 || st.st_dev != st_old.st_dev
3084 || st.st_ino != st_old.st_ino)
3085 backup_copy = TRUE;
3086 else
3087# endif
3088 {
3089 /*
3090 * Check if we can create a file and set the owner/group to
3091 * the ones from the original file.
3092 * First find a file name that doesn't exist yet (use some
3093 * arbitrary numbers).
3094 */
3095 STRCPY(IObuff, fname);
3096 for (i = 4913; ; i += 123)
3097 {
3098 sprintf((char *)gettail(IObuff), "%d", i);
3099 if (mch_stat((char *)IObuff, &st) < 0)
3100 break;
3101 }
3102 fd = mch_open((char *)IObuff, O_CREAT|O_WRONLY|O_EXCL, perm);
3103 close(fd);
3104 if (fd < 0) /* can't write in directory */
3105 backup_copy = TRUE;
3106 else
3107 {
3108# ifdef UNIX
3109 chown((char *)IObuff, st_old.st_uid, st_old.st_gid);
3110 (void)mch_setperm(IObuff, perm);
3111 if (mch_stat((char *)IObuff, &st) < 0
3112 || st.st_uid != st_old.st_uid
3113 || st.st_gid != st_old.st_gid
3114 || st.st_mode != perm)
3115 backup_copy = TRUE;
3116# endif
3117 mch_remove(IObuff);
3118 }
3119 }
3120 }
3121
3122# ifdef UNIX
3123 /*
3124 * Break symlinks and/or hardlinks if we've been asked to.
3125 */
3126 if ((bkc_flags & BKC_BREAKSYMLINK) || (bkc_flags & BKC_BREAKHARDLINK))
3127 {
3128 int lstat_res;
3129
3130 lstat_res = mch_lstat((char *)fname, &st);
3131
3132 /* Symlinks. */
3133 if ((bkc_flags & BKC_BREAKSYMLINK)
3134 && lstat_res == 0
3135 && st.st_ino != st_old.st_ino)
3136 backup_copy = FALSE;
3137
3138 /* Hardlinks. */
3139 if ((bkc_flags & BKC_BREAKHARDLINK)
3140 && st_old.st_nlink > 1
3141 && (lstat_res != 0 || st.st_ino == st_old.st_ino))
3142 backup_copy = FALSE;
3143 }
3144#endif
3145
3146#endif
3147
3148 /* make sure we have a valid backup extension to use */
3149 if (*p_bex == NUL)
3150 {
3151#ifdef RISCOS
3152 backup_ext = (char_u *)"/bak";
3153#else
3154 backup_ext = (char_u *)".bak";
3155#endif
3156 }
3157 else
3158 backup_ext = p_bex;
3159
3160 if (backup_copy
3161 && (fd = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0)) >= 0)
3162 {
3163 int bfd;
3164 char_u *copybuf, *wp;
3165 int some_error = FALSE;
3166 struct stat st_new;
3167 char_u *dirp;
3168 char_u *rootname;
3169#ifndef SHORT_FNAME
3170 int did_set_shortname;
3171#endif
3172
3173 copybuf = alloc(BUFSIZE + 1);
3174 if (copybuf == NULL)
3175 {
3176 some_error = TRUE; /* out of memory */
3177 goto nobackup;
3178 }
3179
3180 /*
3181 * Try to make the backup in each directory in the 'bdir' option.
3182 *
3183 * Unix semantics has it, that we may have a writable file,
3184 * that cannot be recreated with a simple open(..., O_CREAT, ) e.g:
3185 * - the directory is not writable,
3186 * - the file may be a symbolic link,
3187 * - the file may belong to another user/group, etc.
3188 *
3189 * For these reasons, the existing writable file must be truncated
3190 * and reused. Creation of a backup COPY will be attempted.
3191 */
3192 dirp = p_bdir;
3193 while (*dirp)
3194 {
3195#ifdef UNIX
3196 st_new.st_ino = 0;
3197 st_new.st_dev = 0;
3198 st_new.st_gid = 0;
3199#endif
3200
3201 /*
3202 * Isolate one directory name, using an entry in 'bdir'.
3203 */
3204 (void)copy_option_part(&dirp, copybuf, BUFSIZE, ",");
3205 rootname = get_file_in_dir(fname, copybuf);
3206 if (rootname == NULL)
3207 {
3208 some_error = TRUE; /* out of memory */
3209 goto nobackup;
3210 }
3211
3212#ifndef SHORT_FNAME
3213 did_set_shortname = FALSE;
3214#endif
3215
3216 /*
3217 * May try twice if 'shortname' not set.
3218 */
3219 for (;;)
3220 {
3221 /*
3222 * Make backup file name.
3223 */
3224 backup = buf_modname(
3225#ifdef SHORT_FNAME
3226 TRUE,
3227#else
3228 (buf->b_p_sn || buf->b_shortname),
3229#endif
3230 rootname, backup_ext, FALSE);
3231 if (backup == NULL)
3232 {
3233 vim_free(rootname);
3234 some_error = TRUE; /* out of memory */
3235 goto nobackup;
3236 }
3237
3238 /*
3239 * Check if backup file already exists.
3240 */
3241 if (mch_stat((char *)backup, &st_new) >= 0)
3242 {
3243#ifdef UNIX
3244 /*
3245 * Check if backup file is same as original file.
3246 * May happen when modname() gave the same file back.
3247 * E.g. silly link, or file name-length reached.
3248 * If we don't check here, we either ruin the file
3249 * when copying or erase it after writing. jw.
3250 */
3251 if (st_new.st_dev == st_old.st_dev
3252 && st_new.st_ino == st_old.st_ino)
3253 {
3254 vim_free(backup);
3255 backup = NULL; /* no backup file to delete */
3256# ifndef SHORT_FNAME
3257 /*
3258 * may try again with 'shortname' set
3259 */
3260 if (!(buf->b_shortname || buf->b_p_sn))
3261 {
3262 buf->b_shortname = TRUE;
3263 did_set_shortname = TRUE;
3264 continue;
3265 }
3266 /* setting shortname didn't help */
3267 if (did_set_shortname)
3268 buf->b_shortname = FALSE;
3269# endif
3270 break;
3271 }
3272#endif
3273
3274 /*
3275 * If we are not going to keep the backup file, don't
3276 * delete an existing one, try to use another name.
3277 * Change one character, just before the extension.
3278 */
3279 if (!p_bk)
3280 {
3281 wp = backup + STRLEN(backup) - 1
3282 - STRLEN(backup_ext);
3283 if (wp < backup) /* empty file name ??? */
3284 wp = backup;
3285 *wp = 'z';
3286 while (*wp > 'a'
3287 && mch_stat((char *)backup, &st_new) >= 0)
3288 --*wp;
3289 /* They all exist??? Must be something wrong. */
3290 if (*wp == 'a')
3291 {
3292 vim_free(backup);
3293 backup = NULL;
3294 }
3295 }
3296 }
3297 break;
3298 }
3299 vim_free(rootname);
3300
3301 /*
3302 * Try to create the backup file
3303 */
3304 if (backup != NULL)
3305 {
3306 /* remove old backup, if present */
3307 mch_remove(backup);
3308 /* Open with O_EXCL to avoid the file being created while
3309 * we were sleeping (symlink hacker attack?) */
3310 bfd = mch_open((char *)backup,
3311 O_WRONLY|O_CREAT|O_EXTRA|O_EXCL, 0666);
3312 if (bfd < 0)
3313 {
3314 vim_free(backup);
3315 backup = NULL;
3316 }
3317 else
3318 {
3319 /* set file protection same as original file, but
3320 * strip s-bit */
3321 (void)mch_setperm(backup, perm & 0777);
3322
3323#ifdef UNIX
3324 /*
3325 * Try to set the group of the backup same as the
3326 * original file. If this fails, set the protection
3327 * bits for the group same as the protection bits for
3328 * others.
3329 */
3330 if (st_new.st_gid != st_old.st_gid &&
3331# ifdef HAVE_FCHOWN /* sequent-ptx lacks fchown() */
3332 fchown(bfd, (uid_t)-1, st_old.st_gid) != 0
3333# else
3334 chown((char *)backup, (uid_t)-1, st_old.st_gid) != 0
3335# endif
3336 )
3337 mch_setperm(backup,
3338 (perm & 0707) | ((perm & 07) << 3));
3339#endif
3340
3341 /*
3342 * copy the file.
3343 */
3344 write_info.bw_fd = bfd;
3345 write_info.bw_buf = copybuf;
3346#ifdef HAS_BW_FLAGS
3347 write_info.bw_flags = FIO_NOCONVERT;
3348#endif
3349 while ((write_info.bw_len = vim_read(fd, copybuf,
3350 BUFSIZE)) > 0)
3351 {
3352 if (buf_write_bytes(&write_info) == FAIL)
3353 {
3354 errmsg = (char_u *)_("E506: Can't write to backup file (add ! to override)");
3355 break;
3356 }
3357 ui_breakcheck();
3358 if (got_int)
3359 {
3360 errmsg = (char_u *)_(e_interr);
3361 break;
3362 }
3363 }
3364
3365 if (close(bfd) < 0 && errmsg == NULL)
3366 errmsg = (char_u *)_("E507: Close error for backup file (add ! to override)");
3367 if (write_info.bw_len < 0)
3368 errmsg = (char_u *)_("E508: Can't read file for backup (add ! to override)");
3369#ifdef UNIX
3370 set_file_time(backup, st_old.st_atime, st_old.st_mtime);
3371#endif
3372#ifdef HAVE_ACL
3373 mch_set_acl(backup, acl);
3374#endif
3375 break;
3376 }
3377 }
3378 }
3379 nobackup:
3380 close(fd); /* ignore errors for closing read file */
3381 vim_free(copybuf);
3382
3383 if (backup == NULL && errmsg == NULL)
3384 errmsg = (char_u *)_("E509: Cannot create backup file (add ! to override)");
3385 /* ignore errors when forceit is TRUE */
3386 if ((some_error || errmsg != NULL) && !forceit)
3387 {
3388 retval = FAIL;
3389 goto fail;
3390 }
3391 errmsg = NULL;
3392 }
3393 else
3394 {
3395 char_u *dirp;
3396 char_u *p;
3397 char_u *rootname;
3398
3399 /*
3400 * Make a backup by renaming the original file.
3401 */
3402 /*
3403 * If 'cpoptions' includes the "W" flag, we don't want to
3404 * overwrite a read-only file. But rename may be possible
3405 * anyway, thus we need an extra check here.
3406 */
3407 if (file_readonly && vim_strchr(p_cpo, CPO_FWRITE) != NULL)
3408 {
3409 errnum = (char_u *)"E504: ";
3410 errmsg = (char_u *)_(err_readonly);
3411 goto fail;
3412 }
3413
3414 /*
3415 *
3416 * Form the backup file name - change path/fo.o.h to
3417 * path/fo.o.h.bak Try all directories in 'backupdir', first one
3418 * that works is used.
3419 */
3420 dirp = p_bdir;
3421 while (*dirp)
3422 {
3423 /*
3424 * Isolate one directory name and make the backup file name.
3425 */
3426 (void)copy_option_part(&dirp, IObuff, IOSIZE, ",");
3427 rootname = get_file_in_dir(fname, IObuff);
3428 if (rootname == NULL)
3429 backup = NULL;
3430 else
3431 {
3432 backup = buf_modname(
3433#ifdef SHORT_FNAME
3434 TRUE,
3435#else
3436 (buf->b_p_sn || buf->b_shortname),
3437#endif
3438 rootname, backup_ext, FALSE);
3439 vim_free(rootname);
3440 }
3441
3442 if (backup != NULL)
3443 {
3444 /*
3445 * If we are not going to keep the backup file, don't
3446 * delete an existing one, try to use another name.
3447 * Change one character, just before the extension.
3448 */
3449 if (!p_bk && mch_getperm(backup) >= 0)
3450 {
3451 p = backup + STRLEN(backup) - 1 - STRLEN(backup_ext);
3452 if (p < backup) /* empty file name ??? */
3453 p = backup;
3454 *p = 'z';
3455 while (*p > 'a' && mch_getperm(backup) >= 0)
3456 --*p;
3457 /* They all exist??? Must be something wrong! */
3458 if (*p == 'a')
3459 {
3460 vim_free(backup);
3461 backup = NULL;
3462 }
3463 }
3464 }
3465 if (backup != NULL)
3466 {
3467
3468 /*
3469 * Delete any existing backup and move the current version to
3470 * the backup. For safety, we don't remove the backup until
3471 * the write has finished successfully. And if the 'backup'
3472 * option is set, leave it around.
3473 */
3474 /*
3475 * If the renaming of the original file to the backup file
3476 * works, quit here.
3477 */
3478 if (vim_rename(fname, backup) == 0)
3479 break;
3480
3481 vim_free(backup); /* don't do the rename below */
3482 backup = NULL;
3483 }
3484 }
3485 if (backup == NULL && !forceit)
3486 {
3487 errmsg = (char_u *)_("E510: Can't make backup file (add ! to override)");
3488 goto fail;
3489 }
3490 }
3491 }
3492
3493#if defined(UNIX) && !defined(ARCHIE)
3494 /* When using ":w!" and the file was read-only: make it writable */
3495 if (forceit && perm >= 0 && !(perm & 0200) && st_old.st_uid == getuid()
3496 && vim_strchr(p_cpo, CPO_FWRITE) == NULL)
3497 {
3498 perm |= 0200;
3499 (void)mch_setperm(fname, perm);
3500 made_writable = TRUE;
3501 }
3502#endif
3503
3504 /* When using ":w!" and writing to the current file, readonly makes no
3505 * sense, reset it */
3506 if (forceit && overwriting)
3507 {
3508 buf->b_p_ro = FALSE;
3509#ifdef FEAT_TITLE
3510 need_maketitle = TRUE; /* set window title later */
3511#endif
3512#ifdef FEAT_WINDOWS
3513 status_redraw_all(); /* redraw status lines later */
3514#endif
3515 }
3516
3517 if (end > buf->b_ml.ml_line_count)
3518 end = buf->b_ml.ml_line_count;
3519 if (buf->b_ml.ml_flags & ML_EMPTY)
3520 start = end + 1;
3521
3522 /*
3523 * If the original file is being overwritten, there is a small chance that
3524 * we crash in the middle of writing. Therefore the file is preserved now.
3525 * This makes all block numbers positive so that recovery does not need
3526 * the original file.
3527 * Don't do this if there is a backup file and we are exiting.
3528 */
3529 if (reset_changed && !newfile && !otherfile(ffname)
3530 && !(exiting && backup != NULL))
3531 {
3532 ml_preserve(buf, FALSE);
3533 if (got_int)
3534 {
3535 errmsg = (char_u *)_(e_interr);
3536 goto restore_backup;
3537 }
3538 }
3539
3540#ifdef MACOS_CLASSIC /* TODO: Is it need for MACOS_X? (Dany) */
3541 /*
3542 * Before risking to lose the original file verify if there's
3543 * a resource fork to preserve, and if cannot be done warn
3544 * the users. This happens when overwriting without backups.
3545 */
3546 if (backup == NULL && overwriting && !append)
3547 if (mch_has_resource_fork(fname))
3548 {
3549 errmsg = (char_u *)_("E460: The resource fork would be lost (add ! to override)");
3550 goto restore_backup;
3551 }
3552#endif
3553
3554#ifdef VMS
3555 vms_remove_version(fname); /* remove version */
3556#endif
3557 /* Default: write the the file directly. May write to a temp file for
3558 * multi-byte conversion. */
3559 wfname = fname;
3560
3561#ifdef FEAT_MBYTE
3562 /* Check for forced 'fileencoding' from "++opt=val" argument. */
3563 if (eap != NULL && eap->force_enc != 0)
3564 {
3565 fenc = eap->cmd + eap->force_enc;
3566 fenc = enc_canonize(fenc);
3567 fenc_tofree = fenc;
3568 }
3569 else
3570 fenc = buf->b_p_fenc;
3571
3572 /*
3573 * The file needs to be converted when 'fileencoding' is set and
3574 * 'fileencoding' differs from 'encoding'.
3575 */
3576 converted = (*fenc != NUL && !same_encoding(p_enc, fenc));
3577
3578 /*
3579 * Check if UTF-8 to UCS-2/4 or Latin1 conversion needs to be done. Or
3580 * Latin1 to Unicode conversion. This is handled in buf_write_bytes().
3581 * Prepare the flags for it and allocate bw_conv_buf when needed.
3582 */
3583 if (converted && (enc_utf8 || STRCMP(p_enc, "latin1") == 0))
3584 {
3585 wb_flags = get_fio_flags(fenc);
3586 if (wb_flags & (FIO_UCS2 | FIO_UCS4 | FIO_UTF16 | FIO_UTF8))
3587 {
3588 /* Need to allocate a buffer to translate into. */
3589 if (wb_flags & (FIO_UCS2 | FIO_UTF16 | FIO_UTF8))
3590 write_info.bw_conv_buflen = bufsize * 2;
3591 else /* FIO_UCS4 */
3592 write_info.bw_conv_buflen = bufsize * 4;
3593 write_info.bw_conv_buf
3594 = lalloc((long_u)write_info.bw_conv_buflen, TRUE);
3595 if (write_info.bw_conv_buf == NULL)
3596 end = 0;
3597 }
3598 }
3599
3600# ifdef WIN3264
3601 if (converted && wb_flags == 0 && (wb_flags = get_win_fio_flags(fenc)) != 0)
3602 {
3603 /* Convert UTF-8 -> UCS-2 and UCS-2 -> DBCS. Worst-case * 4: */
3604 write_info.bw_conv_buflen = bufsize * 4;
3605 write_info.bw_conv_buf
3606 = lalloc((long_u)write_info.bw_conv_buflen, TRUE);
3607 if (write_info.bw_conv_buf == NULL)
3608 end = 0;
3609 }
3610# endif
3611
3612# ifdef MACOS_X
3613 if (converted && wb_flags == 0 && (wb_flags = get_mac_fio_flags(fenc)) != 0)
3614 {
3615 write_info.bw_conv_buflen = bufsize * 3;
3616 write_info.bw_conv_buf
3617 = lalloc((long_u)write_info.bw_conv_buflen, TRUE);
3618 if (write_info.bw_conv_buf == NULL)
3619 end = 0;
3620 }
3621# endif
3622
3623# if defined(FEAT_EVAL) || defined(USE_ICONV)
3624 if (converted && wb_flags == 0)
3625 {
3626# ifdef USE_ICONV
3627 /*
3628 * Use iconv() conversion when conversion is needed and it's not done
3629 * internally.
3630 */
3631 write_info.bw_iconv_fd = (iconv_t)my_iconv_open(fenc,
3632 enc_utf8 ? (char_u *)"utf-8" : p_enc);
3633 if (write_info.bw_iconv_fd != (iconv_t)-1)
3634 {
3635 /* We're going to use iconv(), allocate a buffer to convert in. */
3636 write_info.bw_conv_buflen = bufsize * ICONV_MULT;
3637 write_info.bw_conv_buf
3638 = lalloc((long_u)write_info.bw_conv_buflen, TRUE);
3639 if (write_info.bw_conv_buf == NULL)
3640 end = 0;
3641 write_info.bw_first = TRUE;
3642 }
3643# ifdef FEAT_EVAL
3644 else
3645# endif
3646# endif
3647
3648# ifdef FEAT_EVAL
3649 /*
3650 * When the file needs to be converted with 'charconvert' after
3651 * writing, write to a temp file instead and let the conversion
3652 * overwrite the original file.
3653 */
3654 if (*p_ccv != NUL)
3655 {
3656 wfname = vim_tempname('w');
3657 if (wfname == NULL) /* Can't write without a tempfile! */
3658 {
3659 errmsg = (char_u *)_("E214: Can't find temp file for writing");
3660 goto restore_backup;
3661 }
3662 }
3663# endif
3664 }
3665# endif
3666 if (converted && wb_flags == 0
3667# ifdef USE_ICONV
3668 && write_info.bw_iconv_fd == (iconv_t)-1
3669# endif
3670# ifdef FEAT_EVAL
3671 && wfname == fname
3672# endif
3673 )
3674 {
3675 if (!forceit)
3676 {
3677 errmsg = (char_u *)_("E213: Cannot convert (add ! to write without conversion)");
3678 goto restore_backup;
3679 }
3680 notconverted = TRUE;
3681 }
3682#endif
3683
3684 /*
3685 * Open the file "wfname" for writing.
3686 * We may try to open the file twice: If we can't write to the
3687 * file and forceit is TRUE we delete the existing file and try to create
3688 * a new one. If this still fails we may have lost the original file!
3689 * (this may happen when the user reached his quotum for number of files).
3690 * Appending will fail if the file does not exist and forceit is FALSE.
3691 */
3692 while ((fd = mch_open((char *)wfname, O_WRONLY | O_EXTRA | (append
3693 ? (forceit ? (O_APPEND | O_CREAT) : O_APPEND)
3694 : (O_CREAT | O_TRUNC))
3695 , 0666)) < 0)
3696 {
3697 /*
3698 * A forced write will try to create a new file if the old one is
3699 * still readonly. This may also happen when the directory is
3700 * read-only. In that case the mch_remove() will fail.
3701 */
3702 if (errmsg == NULL)
3703 {
3704#ifdef UNIX
3705 struct stat st;
3706
3707 /* Don't delete the file when it's a hard or symbolic link. */
3708 if ((!newfile && st_old.st_nlink > 1)
3709 || (mch_lstat((char *)fname, &st) == 0
3710 && (st.st_dev != st_old.st_dev
3711 || st.st_ino != st_old.st_ino)))
3712 errmsg = (char_u *)_("E166: Can't open linked file for writing");
3713 else
3714#endif
3715 {
3716 errmsg = (char_u *)_("E212: Can't open file for writing");
3717 if (forceit && vim_strchr(p_cpo, CPO_FWRITE) == NULL
3718 && perm >= 0)
3719 {
3720#ifdef UNIX
3721 /* we write to the file, thus it should be marked
3722 writable after all */
3723 if (!(perm & 0200))
3724 made_writable = TRUE;
3725 perm |= 0200;
3726 if (st_old.st_uid != getuid() || st_old.st_gid != getgid())
3727 perm &= 0777;
3728#endif
3729 if (!append) /* don't remove when appending */
3730 mch_remove(wfname);
3731 continue;
3732 }
3733 }
3734 }
3735
3736restore_backup:
3737 {
3738 struct stat st;
3739
3740 /*
3741 * If we failed to open the file, we don't need a backup. Throw it
3742 * away. If we moved or removed the original file try to put the
3743 * backup in its place.
3744 */
3745 if (backup != NULL && wfname == fname)
3746 {
3747 if (backup_copy)
3748 {
3749 /*
3750 * There is a small chance that we removed the original,
3751 * try to move the copy in its place.
3752 * This may not work if the vim_rename() fails.
3753 * In that case we leave the copy around.
3754 */
3755 /* If file does not exist, put the copy in its place */
3756 if (mch_stat((char *)fname, &st) < 0)
3757 vim_rename(backup, fname);
3758 /* if original file does exist throw away the copy */
3759 if (mch_stat((char *)fname, &st) >= 0)
3760 mch_remove(backup);
3761 }
3762 else
3763 {
3764 /* try to put the original file back */
3765 vim_rename(backup, fname);
3766 }
3767 }
3768
3769 /* if original file no longer exists give an extra warning */
3770 if (!newfile && mch_stat((char *)fname, &st) < 0)
3771 end = 0;
3772 }
3773
3774#ifdef FEAT_MBYTE
3775 if (wfname != fname)
3776 vim_free(wfname);
3777#endif
3778 goto fail;
3779 }
3780 errmsg = NULL;
3781
3782#if defined(MACOS_CLASSIC) || defined(WIN3264)
3783 /* TODO: Is it need for MACOS_X? (Dany) */
3784 /*
3785 * On macintosh copy the original files attributes (i.e. the backup)
3786 * This is done in order to preserve the ressource fork and the
3787 * Finder attribute (label, comments, custom icons, file creatore)
3788 */
3789 if (backup != NULL && overwriting && !append)
3790 {
3791 if (backup_copy)
3792 (void)mch_copy_file_attribute(wfname, backup);
3793 else
3794 (void)mch_copy_file_attribute(backup, wfname);
3795 }
3796
3797 if (!overwriting && !append)
3798 {
3799 if (buf->b_ffname != NULL)
3800 (void)mch_copy_file_attribute(buf->b_ffname, wfname);
3801 /* Should copy ressource fork */
3802 }
3803#endif
3804
3805 write_info.bw_fd = fd;
3806
3807#ifdef FEAT_CRYPT
3808 if (*buf->b_p_key && !filtering)
3809 {
3810 crypt_init_keys(buf->b_p_key);
3811 /* Write magic number, so that Vim knows that this file is encrypted
3812 * when reading it again. This also undergoes utf-8 to ucs-2/4
3813 * conversion when needed. */
3814 write_info.bw_buf = (char_u *)CRYPT_MAGIC;
3815 write_info.bw_len = CRYPT_MAGIC_LEN;
3816 write_info.bw_flags = FIO_NOCONVERT;
3817 if (buf_write_bytes(&write_info) == FAIL)
3818 end = 0;
3819 wb_flags |= FIO_ENCRYPTED;
3820 }
3821#endif
3822
3823 write_info.bw_buf = buffer;
3824 nchars = 0;
3825
3826 /* use "++bin", "++nobin" or 'binary' */
3827 if (eap != NULL && eap->force_bin != 0)
3828 write_bin = (eap->force_bin == FORCE_BIN);
3829 else
3830 write_bin = buf->b_p_bin;
3831
3832#ifdef FEAT_MBYTE
3833 /*
3834 * The BOM is written just after the encryption magic number.
Bram Moolenaarc0197e22004-09-13 20:26:32 +00003835 * Skip it when appending and the file already existed, the BOM only makes
3836 * sense at the start of the file.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003837 */
Bram Moolenaarc0197e22004-09-13 20:26:32 +00003838 if (buf->b_p_bomb && !write_bin && (!append || perm < 0))
Bram Moolenaar071d4272004-06-13 20:20:40 +00003839 {
3840 write_info.bw_len = make_bom(buffer, fenc);
3841 if (write_info.bw_len > 0)
3842 {
3843 /* don't convert, do encryption */
3844 write_info.bw_flags = FIO_NOCONVERT | wb_flags;
3845 if (buf_write_bytes(&write_info) == FAIL)
3846 end = 0;
3847 else
3848 nchars += write_info.bw_len;
3849 }
3850 }
3851#endif
3852
3853 write_info.bw_len = bufsize;
3854#ifdef HAS_BW_FLAGS
3855 write_info.bw_flags = wb_flags;
3856#endif
3857 fileformat = get_fileformat_force(buf, eap);
3858 s = buffer;
3859 len = 0;
3860 for (lnum = start; lnum <= end; ++lnum)
3861 {
3862 /*
3863 * The next while loop is done once for each character written.
3864 * Keep it fast!
3865 */
3866 ptr = ml_get_buf(buf, lnum, FALSE) - 1;
3867 while ((c = *++ptr) != NUL)
3868 {
3869 if (c == NL)
3870 *s = NUL; /* replace newlines with NULs */
3871 else if (c == CAR && fileformat == EOL_MAC)
3872 *s = NL; /* Mac: replace CRs with NLs */
3873 else
3874 *s = c;
3875 ++s;
3876 if (++len != bufsize)
3877 continue;
3878 if (buf_write_bytes(&write_info) == FAIL)
3879 {
3880 end = 0; /* write error: break loop */
3881 break;
3882 }
3883 nchars += bufsize;
3884 s = buffer;
3885 len = 0;
3886 }
3887 /* write failed or last line has no EOL: stop here */
3888 if (end == 0
3889 || (lnum == end
3890 && write_bin
3891 && (lnum == write_no_eol_lnum
3892 || (lnum == buf->b_ml.ml_line_count && !buf->b_p_eol))))
3893 {
3894 ++lnum; /* written the line, count it */
3895 no_eol = TRUE;
3896 break;
3897 }
3898 if (fileformat == EOL_UNIX)
3899 *s++ = NL;
3900 else
3901 {
3902 *s++ = CAR; /* EOL_MAC or EOL_DOS: write CR */
3903 if (fileformat == EOL_DOS) /* write CR-NL */
3904 {
3905 if (++len == bufsize)
3906 {
3907 if (buf_write_bytes(&write_info) == FAIL)
3908 {
3909 end = 0; /* write error: break loop */
3910 break;
3911 }
3912 nchars += bufsize;
3913 s = buffer;
3914 len = 0;
3915 }
3916 *s++ = NL;
3917 }
3918 }
3919 if (++len == bufsize && end)
3920 {
3921 if (buf_write_bytes(&write_info) == FAIL)
3922 {
3923 end = 0; /* write error: break loop */
3924 break;
3925 }
3926 nchars += bufsize;
3927 s = buffer;
3928 len = 0;
3929
3930 ui_breakcheck();
3931 if (got_int)
3932 {
3933 end = 0; /* Interrupted, break loop */
3934 break;
3935 }
3936 }
3937#ifdef VMS
3938 /*
3939 * On VMS there is a problem: newlines get added when writing blocks
3940 * at a time. Fix it by writing a line at a time.
3941 * This is much slower!
Bram Moolenaard4755bb2004-09-02 19:12:26 +00003942 * Explanation: VAX/DECC RTL insists that records in some RMS
3943 * structures end with a newline (carriage return) character, and if
3944 * they don't it adds one.
3945 * With other RMS structures it works perfect without this fix.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003946 */
Bram Moolenaard4755bb2004-09-02 19:12:26 +00003947 if ((buf->b_fab_rat & (FAB$M_FTN | FAB$M_CR)) != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003948 {
Bram Moolenaard4755bb2004-09-02 19:12:26 +00003949 int b2write;
3950
3951 buf->b_fab_mrs = (buf->b_fab_mrs == 0
3952 ? MIN(4096, bufsize)
3953 : MIN(buf->b_fab_mrs, bufsize));
3954
3955 b2write = len;
3956 while (b2write > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003957 {
Bram Moolenaard4755bb2004-09-02 19:12:26 +00003958 write_info.bw_len = MIN(b2write, buf->b_fab_mrs);
3959 if (buf_write_bytes(&write_info) == FAIL)
3960 {
3961 end = 0;
3962 break;
3963 }
3964 b2write -= MIN(b2write, buf->b_fab_mrs);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003965 }
3966 write_info.bw_len = bufsize;
3967 nchars += len;
3968 s = buffer;
3969 len = 0;
3970 }
3971#endif
3972 }
3973 if (len > 0 && end > 0)
3974 {
3975 write_info.bw_len = len;
3976 if (buf_write_bytes(&write_info) == FAIL)
3977 end = 0; /* write error */
3978 nchars += len;
3979 }
3980
3981#if defined(UNIX) && defined(HAVE_FSYNC)
3982 /* On many journalling file systems there is a bug that causes both the
3983 * original and the backup file to be lost when halting the system right
3984 * after writing the file. That's because only the meta-data is
3985 * journalled. Syncing the file slows down the system, but assures it has
Bram Moolenaarf4b8e572004-06-24 15:53:16 +00003986 * been written to disk and we don't lose it.
3987 * For a device do try the fsync() but don't complain if it does not work
3988 * (could be a pipe). */
3989 if (fsync(fd) != 0 && !device)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003990 {
3991 errmsg = (char_u *)_("E667: Fsync failed");
3992 end = 0;
3993 }
3994#endif
3995
3996 if (close(fd) != 0)
3997 {
3998 errmsg = (char_u *)_("E512: Close failed");
3999 end = 0;
4000 }
4001
4002#ifdef UNIX
4003 if (made_writable)
4004 perm &= ~0200; /* reset 'w' bit for security reasons */
4005#endif
4006 if (perm >= 0) /* set perm. of new file same as old file */
4007 (void)mch_setperm(wfname, perm);
4008#ifdef RISCOS
4009 if (!append && !filtering)
4010 /* Set the filetype after writing the file. */
4011 mch_set_filetype(wfname, buf->b_p_oft);
4012#endif
4013#ifdef HAVE_ACL
4014 /* Probably need to set the ACL before changing the user (can't set the
4015 * ACL on a file the user doesn't own). */
4016 if (!backup_copy)
4017 mch_set_acl(wfname, acl);
4018#endif
4019
4020#ifdef UNIX
4021 /* When creating a new file, set its owner/group to that of the original
4022 * file. Get the new device and inode number. */
4023 if (backup != NULL && !backup_copy)
4024 {
4025 struct stat st;
4026
4027 /* don't change the owner when it's already OK, some systems remove
4028 * permission or ACL stuff */
4029 if (mch_stat((char *)wfname, &st) < 0
4030 || st.st_uid != st_old.st_uid
4031 || st.st_gid != st_old.st_gid)
4032 {
4033 chown((char *)wfname, st_old.st_uid, st_old.st_gid);
4034 if (perm >= 0) /* set permission again, may have changed */
4035 (void)mch_setperm(wfname, perm);
4036 }
4037 buf_setino(buf);
4038 }
4039#endif
4040
4041
4042#if defined(FEAT_MBYTE) && defined(FEAT_EVAL)
4043 if (wfname != fname)
4044 {
4045 /*
4046 * The file was written to a temp file, now it needs to be converted
4047 * with 'charconvert' to (overwrite) the output file.
4048 */
4049 if (end != 0)
4050 {
4051 if (eval_charconvert(enc_utf8 ? (char_u *)"utf-8" : p_enc, fenc,
4052 wfname, fname) == FAIL)
4053 {
4054 write_info.bw_conv_error = TRUE;
4055 end = 0;
4056 }
4057 }
4058 mch_remove(wfname);
4059 vim_free(wfname);
4060 }
4061#endif
4062
4063 if (end == 0)
4064 {
4065 if (errmsg == NULL)
4066 {
4067#ifdef FEAT_MBYTE
4068 if (write_info.bw_conv_error)
4069 errmsg = (char_u *)_("E513: write error, conversion failed");
4070 else
4071#endif
4072 if (got_int)
4073 errmsg = (char_u *)_(e_interr);
4074 else
4075 errmsg = (char_u *)_("E514: write error (file system full?)");
4076 }
4077
4078 /*
4079 * If we have a backup file, try to put it in place of the new file,
4080 * because the new file is probably corrupt. This avoids loosing the
4081 * original file when trying to make a backup when writing the file a
4082 * second time.
4083 * When "backup_copy" is set we need to copy the backup over the new
4084 * file. Otherwise rename the backup file.
4085 * If this is OK, don't give the extra warning message.
4086 */
4087 if (backup != NULL)
4088 {
4089 if (backup_copy)
4090 {
4091 /* This may take a while, if we were interrupted let the user
4092 * know we got the message. */
4093 if (got_int)
4094 {
4095 MSG(_(e_interr));
4096 out_flush();
4097 }
4098 if ((fd = mch_open((char *)backup, O_RDONLY | O_EXTRA, 0)) >= 0)
4099 {
4100 if ((write_info.bw_fd = mch_open((char *)fname,
4101 O_WRONLY | O_CREAT | O_TRUNC | O_EXTRA, 0666)) >= 0)
4102 {
4103 /* copy the file. */
4104 write_info.bw_buf = smallbuf;
4105#ifdef HAS_BW_FLAGS
4106 write_info.bw_flags = FIO_NOCONVERT;
4107#endif
4108 while ((write_info.bw_len = vim_read(fd, smallbuf,
4109 SMBUFSIZE)) > 0)
4110 if (buf_write_bytes(&write_info) == FAIL)
4111 break;
4112
4113 if (close(write_info.bw_fd) >= 0
4114 && write_info.bw_len == 0)
4115 end = 1; /* success */
4116 }
4117 close(fd); /* ignore errors for closing read file */
4118 }
4119 }
4120 else
4121 {
4122 if (vim_rename(backup, fname) == 0)
4123 end = 1;
4124 }
4125 }
4126 goto fail;
4127 }
4128
4129 lnum -= start; /* compute number of written lines */
4130 --no_wait_return; /* may wait for return now */
4131
4132#if !(defined(UNIX) || defined(VMS))
4133 fname = sfname; /* use shortname now, for the messages */
4134#endif
4135 if (!filtering)
4136 {
4137 msg_add_fname(buf, fname); /* put fname in IObuff with quotes */
4138 c = FALSE;
4139#ifdef FEAT_MBYTE
4140 if (write_info.bw_conv_error)
4141 {
4142 STRCAT(IObuff, _(" CONVERSION ERROR"));
4143 c = TRUE;
4144 }
4145 else if (notconverted)
4146 {
4147 STRCAT(IObuff, _("[NOT converted]"));
4148 c = TRUE;
4149 }
4150 else if (converted)
4151 {
4152 STRCAT(IObuff, _("[converted]"));
4153 c = TRUE;
4154 }
4155#endif
4156 if (device)
4157 {
4158 STRCAT(IObuff, _("[Device]"));
4159 c = TRUE;
4160 }
4161 else if (newfile)
4162 {
4163 STRCAT(IObuff, shortmess(SHM_NEW) ? _("[New]") : _("[New File]"));
4164 c = TRUE;
4165 }
4166 if (no_eol)
4167 {
4168 msg_add_eol();
4169 c = TRUE;
4170 }
4171 /* may add [unix/dos/mac] */
4172 if (msg_add_fileformat(fileformat))
4173 c = TRUE;
4174#ifdef FEAT_CRYPT
4175 if (wb_flags & FIO_ENCRYPTED)
4176 {
4177 STRCAT(IObuff, _("[crypted]"));
4178 c = TRUE;
4179 }
4180#endif
4181 msg_add_lines(c, (long)lnum, nchars); /* add line/char count */
4182 if (!shortmess(SHM_WRITE))
4183 {
4184 if (append)
4185 STRCAT(IObuff, shortmess(SHM_WRI) ? _(" [a]") : _(" appended"));
4186 else
4187 STRCAT(IObuff, shortmess(SHM_WRI) ? _(" [w]") : _(" written"));
4188 }
4189
4190 set_keep_msg(msg_trunc_attr(IObuff, FALSE, 0));
4191 keep_msg_attr = 0;
4192 }
4193
4194 if (reset_changed && whole
4195#ifdef FEAT_MBYTE
4196 && !write_info.bw_conv_error
4197#endif
4198 ) /* when written everything correctly */
4199 {
4200 unchanged(buf, TRUE);
4201 u_unchanged(buf);
4202 }
4203
4204 /*
4205 * If written to the current file, update the timestamp of the swap file
4206 * and reset the BF_WRITE_MASK flags. Also sets buf->b_mtime.
4207 */
4208 if (overwriting)
4209 {
4210 ml_timestamp(buf);
4211 buf->b_flags &= ~BF_WRITE_MASK;
4212 }
4213
4214 /*
4215 * If we kept a backup until now, and we are in patch mode, then we make
4216 * the backup file our 'original' file.
4217 */
4218 if (*p_pm && dobackup)
4219 {
4220 char *org = (char *)buf_modname(
4221#ifdef SHORT_FNAME
4222 TRUE,
4223#else
4224 (buf->b_p_sn || buf->b_shortname),
4225#endif
4226 fname, p_pm, FALSE);
4227
4228 if (backup != NULL)
4229 {
4230 struct stat st;
4231
4232 /*
4233 * If the original file does not exist yet
4234 * the current backup file becomes the original file
4235 */
4236 if (org == NULL)
4237 EMSG(_("E205: Patchmode: can't save original file"));
4238 else if (mch_stat(org, &st) < 0)
4239 {
4240 vim_rename(backup, (char_u *)org);
4241 vim_free(backup); /* don't delete the file */
4242 backup = NULL;
4243#ifdef UNIX
4244 set_file_time((char_u *)org, st_old.st_atime, st_old.st_mtime);
4245#endif
4246 }
4247 }
4248 /*
4249 * If there is no backup file, remember that a (new) file was
4250 * created.
4251 */
4252 else
4253 {
4254 int empty_fd;
4255
4256 if (org == NULL
4257 || (empty_fd = mch_open(org, O_CREAT | O_EXTRA | O_EXCL,
4258 0666)) < 0)
4259 EMSG(_("E206: patchmode: can't touch empty original file"));
4260 else
4261 close(empty_fd);
4262 }
4263 if (org != NULL)
4264 {
4265 mch_setperm((char_u *)org, mch_getperm(fname) & 0777);
4266 vim_free(org);
4267 }
4268 }
4269
4270 /*
4271 * Remove the backup unless 'backup' option is set
4272 */
4273 if (!p_bk && backup != NULL && mch_remove(backup) != 0)
4274 EMSG(_("E207: Can't delete backup file"));
4275
4276#ifdef FEAT_SUN_WORKSHOP
4277 if (usingSunWorkShop)
4278 workshop_file_saved((char *) ffname);
4279#endif
4280
4281 goto nofail;
4282
4283 /*
4284 * Finish up. We get here either after failure or success.
4285 */
4286fail:
4287 --no_wait_return; /* may wait for return now */
4288nofail:
4289
4290 /* Done saving, we accept changed buffer warnings again */
4291 buf->b_saving = FALSE;
4292
4293 vim_free(backup);
4294 if (buffer != smallbuf)
4295 vim_free(buffer);
4296#ifdef FEAT_MBYTE
4297 vim_free(fenc_tofree);
4298 vim_free(write_info.bw_conv_buf);
4299# ifdef USE_ICONV
4300 if (write_info.bw_iconv_fd != (iconv_t)-1)
4301 {
4302 iconv_close(write_info.bw_iconv_fd);
4303 write_info.bw_iconv_fd = (iconv_t)-1;
4304 }
4305# endif
4306#endif
4307#ifdef HAVE_ACL
4308 mch_free_acl(acl);
4309#endif
4310
4311 if (errmsg != NULL)
4312 {
4313 int numlen = errnum != NULL ? STRLEN(errnum) : 0;
4314
4315 attr = hl_attr(HLF_E); /* set highlight for error messages */
4316 msg_add_fname(buf,
4317#ifndef UNIX
4318 sfname
4319#else
4320 fname
4321#endif
4322 ); /* put file name in IObuff with quotes */
4323 if (STRLEN(IObuff) + STRLEN(errmsg) + numlen >= IOSIZE)
4324 IObuff[IOSIZE - STRLEN(errmsg) - numlen - 1] = NUL;
4325 /* If the error message has the form "is ...", put the error number in
4326 * front of the file name. */
4327 if (errnum != NULL)
4328 {
4329 mch_memmove(IObuff + numlen, IObuff, STRLEN(IObuff) + 1);
4330 mch_memmove(IObuff, errnum, (size_t)numlen);
4331 }
4332 STRCAT(IObuff, errmsg);
4333 emsg(IObuff);
4334
4335 retval = FAIL;
4336 if (end == 0)
4337 {
4338 MSG_PUTS_ATTR(_("\nWARNING: Original file may be lost or damaged\n"),
4339 attr | MSG_HIST);
4340 MSG_PUTS_ATTR(_("don't quit the editor until the file is successfully written!"),
4341 attr | MSG_HIST);
4342
4343 /* Update the timestamp to avoid an "overwrite changed file"
4344 * prompt when writing again. */
4345 if (mch_stat((char *)fname, &st_old) >= 0)
4346 {
4347 buf_store_time(buf, &st_old, fname);
4348 buf->b_mtime_read = buf->b_mtime;
4349 }
4350 }
4351 }
4352 msg_scroll = msg_save;
4353
4354#ifdef FEAT_AUTOCMD
4355#ifdef FEAT_EVAL
4356 if (!should_abort(retval))
4357#else
4358 if (!got_int)
4359#endif
4360 {
4361 aco_save_T aco;
4362
4363 write_no_eol_lnum = 0; /* in case it was set by the previous read */
4364
4365 /*
4366 * Apply POST autocommands.
4367 * Careful: The autocommands may call buf_write() recursively!
4368 */
4369 aucmd_prepbuf(&aco, buf);
4370
4371 if (append)
4372 apply_autocmds_exarg(EVENT_FILEAPPENDPOST, fname, fname,
4373 FALSE, curbuf, eap);
4374 else if (filtering)
4375 apply_autocmds_exarg(EVENT_FILTERWRITEPOST, NULL, fname,
4376 FALSE, curbuf, eap);
4377 else if (reset_changed && whole)
4378 apply_autocmds_exarg(EVENT_BUFWRITEPOST, fname, fname,
4379 FALSE, curbuf, eap);
4380 else
4381 apply_autocmds_exarg(EVENT_FILEWRITEPOST, fname, fname,
4382 FALSE, curbuf, eap);
4383
4384 /* restore curwin/curbuf and a few other things */
4385 aucmd_restbuf(&aco);
4386
4387#ifdef FEAT_EVAL
4388 if (aborting()) /* autocmds may abort script processing */
4389 retval = FALSE;
4390#endif
4391 }
4392#endif
4393
4394 got_int |= prev_got_int;
4395
4396#ifdef MACOS_CLASSIC /* TODO: Is it need for MACOS_X? (Dany) */
4397 /* Update machine specific information. */
4398 mch_post_buffer_write(buf);
4399#endif
4400 return retval;
4401}
4402
4403/*
4404 * Put file name into IObuff with quotes.
4405 */
4406 static void
4407msg_add_fname(buf, fname)
4408 buf_T *buf;
4409 char_u *fname;
4410{
4411 if (fname == NULL)
4412 fname = (char_u *)"-stdin-";
4413 home_replace(buf, fname, IObuff + 1, IOSIZE - 4, TRUE);
4414 IObuff[0] = '"';
4415 STRCAT(IObuff, "\" ");
4416}
4417
4418/*
4419 * Append message for text mode to IObuff.
4420 * Return TRUE if something appended.
4421 */
4422 static int
4423msg_add_fileformat(eol_type)
4424 int eol_type;
4425{
4426#ifndef USE_CRNL
4427 if (eol_type == EOL_DOS)
4428 {
4429 STRCAT(IObuff, shortmess(SHM_TEXT) ? _("[dos]") : _("[dos format]"));
4430 return TRUE;
4431 }
4432#endif
4433#ifndef USE_CR
4434 if (eol_type == EOL_MAC)
4435 {
4436 STRCAT(IObuff, shortmess(SHM_TEXT) ? _("[mac]") : _("[mac format]"));
4437 return TRUE;
4438 }
4439#endif
4440#if defined(USE_CRNL) || defined(USE_CR)
4441 if (eol_type == EOL_UNIX)
4442 {
4443 STRCAT(IObuff, shortmess(SHM_TEXT) ? _("[unix]") : _("[unix format]"));
4444 return TRUE;
4445 }
4446#endif
4447 return FALSE;
4448}
4449
4450/*
4451 * Append line and character count to IObuff.
4452 */
4453 static void
4454msg_add_lines(insert_space, lnum, nchars)
4455 int insert_space;
4456 long lnum;
4457 long nchars;
4458{
4459 char_u *p;
4460
4461 p = IObuff + STRLEN(IObuff);
4462
4463 if (insert_space)
4464 *p++ = ' ';
4465 if (shortmess(SHM_LINES))
4466 sprintf((char *)p, "%ldL, %ldC", lnum, nchars);
4467 else
4468 {
4469 if (lnum == 1)
4470 STRCPY(p, _("1 line, "));
4471 else
4472 sprintf((char *)p, _("%ld lines, "), lnum);
4473 p += STRLEN(p);
4474 if (nchars == 1)
4475 STRCPY(p, _("1 character"));
4476 else
4477 sprintf((char *)p, _("%ld characters"), nchars);
4478 }
4479}
4480
4481/*
4482 * Append message for missing line separator to IObuff.
4483 */
4484 static void
4485msg_add_eol()
4486{
4487 STRCAT(IObuff, shortmess(SHM_LAST) ? _("[noeol]") : _("[Incomplete last line]"));
4488}
4489
4490/*
4491 * Check modification time of file, before writing to it.
4492 * The size isn't checked, because using a tool like "gzip" takes care of
4493 * using the same timestamp but can't set the size.
4494 */
4495 static int
4496check_mtime(buf, st)
4497 buf_T *buf;
4498 struct stat *st;
4499{
4500 if (buf->b_mtime_read != 0
4501 && time_differs((long)st->st_mtime, buf->b_mtime_read))
4502 {
4503 msg_scroll = TRUE; /* don't overwrite messages here */
4504 msg_silent = 0; /* must give this prompt */
4505 /* don't use emsg() here, don't want to flush the buffers */
4506 MSG_ATTR(_("WARNING: The file has been changed since reading it!!!"),
4507 hl_attr(HLF_E));
4508 if (ask_yesno((char_u *)_("Do you really want to write to it"),
4509 TRUE) == 'n')
4510 return FAIL;
4511 msg_scroll = FALSE; /* always overwrite the file message now */
4512 }
4513 return OK;
4514}
4515
4516 static int
4517time_differs(t1, t2)
4518 long t1, t2;
4519{
4520#if defined(__linux__) || defined(MSDOS) || defined(MSWIN)
4521 /* On a FAT filesystem, esp. under Linux, there are only 5 bits to store
4522 * the seconds. Since the roundoff is done when flushing the inode, the
4523 * time may change unexpectedly by one second!!! */
4524 return (t1 - t2 > 1 || t2 - t1 > 1);
4525#else
4526 return (t1 != t2);
4527#endif
4528}
4529
4530/*
4531 * Call write() to write a number of bytes to the file.
4532 * Also handles encryption and 'encoding' conversion.
4533 *
4534 * Return FAIL for failure, OK otherwise.
4535 */
4536 static int
4537buf_write_bytes(ip)
4538 struct bw_info *ip;
4539{
4540 int wlen;
4541 char_u *buf = ip->bw_buf; /* data to write */
4542 int len = ip->bw_len; /* length of data */
4543#ifdef HAS_BW_FLAGS
4544 int flags = ip->bw_flags; /* extra flags */
4545#endif
4546
4547#ifdef FEAT_MBYTE
4548 /*
4549 * Skip conversion when writing the crypt magic number or the BOM.
4550 */
4551 if (!(flags & FIO_NOCONVERT))
4552 {
4553 char_u *p;
4554 unsigned c;
4555 int n;
4556
4557 if (flags & FIO_UTF8)
4558 {
4559 /*
4560 * Convert latin1 in the buffer to UTF-8 in the file.
4561 */
4562 p = ip->bw_conv_buf; /* translate to buffer */
4563 for (wlen = 0; wlen < len; ++wlen)
4564 p += utf_char2bytes(buf[wlen], p);
4565 buf = ip->bw_conv_buf;
4566 len = (int)(p - ip->bw_conv_buf);
4567 }
4568 else if (flags & (FIO_UCS4 | FIO_UTF16 | FIO_UCS2 | FIO_LATIN1))
4569 {
4570 /*
4571 * Convert UTF-8 bytes in the buffer to UCS-2, UCS-4, UTF-16 or
4572 * Latin1 chars in the file.
4573 */
4574 if (flags & FIO_LATIN1)
4575 p = buf; /* translate in-place (can only get shorter) */
4576 else
4577 p = ip->bw_conv_buf; /* translate to buffer */
4578 for (wlen = 0; wlen < len; wlen += n)
4579 {
4580 if (wlen == 0 && ip->bw_restlen != 0)
4581 {
4582 int l;
4583
4584 /* Use remainder of previous call. Append the start of
4585 * buf[] to get a full sequence. Might still be too
4586 * short! */
4587 l = CONV_RESTLEN - ip->bw_restlen;
4588 if (l > len)
4589 l = len;
4590 mch_memmove(ip->bw_rest + ip->bw_restlen, buf, (size_t)l);
4591 n = utf_ptr2len_check_len(ip->bw_rest, ip->bw_restlen + l);
4592 if (n > ip->bw_restlen + len)
4593 {
4594 /* We have an incomplete byte sequence at the end to
4595 * be written. We can't convert it without the
4596 * remaining bytes. Keep them for the next call. */
4597 if (ip->bw_restlen + len > CONV_RESTLEN)
4598 return FAIL;
4599 ip->bw_restlen += len;
4600 break;
4601 }
4602 if (n > 1)
4603 c = utf_ptr2char(ip->bw_rest);
4604 else
4605 c = ip->bw_rest[0];
4606 if (n >= ip->bw_restlen)
4607 {
4608 n -= ip->bw_restlen;
4609 ip->bw_restlen = 0;
4610 }
4611 else
4612 {
4613 ip->bw_restlen -= n;
4614 mch_memmove(ip->bw_rest, ip->bw_rest + n,
4615 (size_t)ip->bw_restlen);
4616 n = 0;
4617 }
4618 }
4619 else
4620 {
4621 n = utf_ptr2len_check_len(buf + wlen, len - wlen);
4622 if (n > len - wlen)
4623 {
4624 /* We have an incomplete byte sequence at the end to
4625 * be written. We can't convert it without the
4626 * remaining bytes. Keep them for the next call. */
4627 if (len - wlen > CONV_RESTLEN)
4628 return FAIL;
4629 ip->bw_restlen = len - wlen;
4630 mch_memmove(ip->bw_rest, buf + wlen,
4631 (size_t)ip->bw_restlen);
4632 break;
4633 }
4634 if (n > 1)
4635 c = utf_ptr2char(buf + wlen);
4636 else
4637 c = buf[wlen];
4638 }
4639
4640 ip->bw_conv_error |= ucs2bytes(c, &p, flags);
4641 }
4642 if (flags & FIO_LATIN1)
4643 len = (int)(p - buf);
4644 else
4645 {
4646 buf = ip->bw_conv_buf;
4647 len = (int)(p - ip->bw_conv_buf);
4648 }
4649 }
4650
4651# ifdef WIN3264
4652 else if (flags & FIO_CODEPAGE)
4653 {
4654 /*
4655 * Convert UTF-8 or codepage to UCS-2 and then to MS-Windows
4656 * codepage.
4657 */
4658 char_u *from;
4659 size_t fromlen;
4660 char_u *to;
4661 int u8c;
4662 BOOL bad = FALSE;
4663 int needed;
4664
4665 if (ip->bw_restlen > 0)
4666 {
4667 /* Need to concatenate the remainder of the previous call and
4668 * the bytes of the current call. Use the end of the
4669 * conversion buffer for this. */
4670 fromlen = len + ip->bw_restlen;
4671 from = ip->bw_conv_buf + ip->bw_conv_buflen - fromlen;
4672 mch_memmove(from, ip->bw_rest, (size_t)ip->bw_restlen);
4673 mch_memmove(from + ip->bw_restlen, buf, (size_t)len);
4674 }
4675 else
4676 {
4677 from = buf;
4678 fromlen = len;
4679 }
4680
4681 to = ip->bw_conv_buf;
4682 if (enc_utf8)
4683 {
4684 /* Convert from UTF-8 to UCS-2, to the start of the buffer.
4685 * The buffer has been allocated to be big enough. */
4686 while (fromlen > 0)
4687 {
4688 n = utf_ptr2len_check_len(from, fromlen);
4689 if (n > (int)fromlen) /* incomplete byte sequence */
4690 break;
4691 u8c = utf_ptr2char(from);
4692 *to++ = (u8c & 0xff);
4693 *to++ = (u8c >> 8);
4694 fromlen -= n;
4695 from += n;
4696 }
4697
4698 /* Copy remainder to ip->bw_rest[] to be used for the next
4699 * call. */
4700 if (fromlen > CONV_RESTLEN)
4701 {
4702 /* weird overlong sequence */
4703 ip->bw_conv_error = TRUE;
4704 return FAIL;
4705 }
4706 mch_memmove(ip->bw_rest, from, fromlen);
4707 ip->bw_restlen = fromlen;
4708 }
4709 else
4710 {
4711 /* Convert from enc_codepage to UCS-2, to the start of the
4712 * buffer. The buffer has been allocated to be big enough. */
4713 ip->bw_restlen = 0;
4714 needed = MultiByteToWideChar(enc_codepage,
4715 MB_ERR_INVALID_CHARS, (LPCSTR)from, fromlen,
4716 NULL, 0);
4717 if (needed == 0)
4718 {
4719 /* When conversion fails there may be a trailing byte. */
4720 needed = MultiByteToWideChar(enc_codepage,
4721 MB_ERR_INVALID_CHARS, (LPCSTR)from, fromlen - 1,
4722 NULL, 0);
4723 if (needed == 0)
4724 {
4725 /* Conversion doesn't work. */
4726 ip->bw_conv_error = TRUE;
4727 return FAIL;
4728 }
4729 /* Save the trailing byte for the next call. */
4730 ip->bw_rest[0] = from[fromlen - 1];
4731 ip->bw_restlen = 1;
4732 }
4733 needed = MultiByteToWideChar(enc_codepage, MB_ERR_INVALID_CHARS,
4734 (LPCSTR)from, fromlen - ip->bw_restlen,
4735 (LPWSTR)to, needed);
4736 if (needed == 0)
4737 {
4738 /* Safety check: Conversion doesn't work. */
4739 ip->bw_conv_error = TRUE;
4740 return FAIL;
4741 }
4742 to += needed * 2;
4743 }
4744
4745 fromlen = to - ip->bw_conv_buf;
4746 buf = to;
4747# ifdef CP_UTF8 /* VC 4.1 doesn't define CP_UTF8 */
4748 if (FIO_GET_CP(flags) == CP_UTF8)
4749 {
4750 /* Convert from UCS-2 to UTF-8, using the remainder of the
4751 * conversion buffer. Fails when out of space. */
4752 for (from = ip->bw_conv_buf; fromlen > 1; fromlen -= 2)
4753 {
4754 u8c = *from++;
4755 u8c += (*from++ << 8);
4756 to += utf_char2bytes(u8c, to);
4757 if (to + 6 >= ip->bw_conv_buf + ip->bw_conv_buflen)
4758 {
4759 ip->bw_conv_error = TRUE;
4760 return FAIL;
4761 }
4762 }
4763 len = to - buf;
4764 }
4765 else
4766#endif
4767 {
4768 /* Convert from UCS-2 to the codepage, using the remainder of
4769 * the conversion buffer. If the conversion uses the default
4770 * character "0", the data doesn't fit in this encoding, so
4771 * fail. */
4772 len = WideCharToMultiByte(FIO_GET_CP(flags), 0,
4773 (LPCWSTR)ip->bw_conv_buf, (int)fromlen / sizeof(WCHAR),
4774 (LPSTR)to, ip->bw_conv_buflen - fromlen, 0, &bad);
4775 if (bad)
4776 {
4777 ip->bw_conv_error = TRUE;
4778 return FAIL;
4779 }
4780 }
4781 }
4782# endif
4783
4784# ifdef MACOS_X
4785 else if (flags & FIO_MACROMAN)
4786 {
4787 /*
4788 * Convert UTF-8 or latin1 to Apple MacRoman.
4789 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004790 char_u *from;
4791 size_t fromlen;
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00004792 extern int enc2macroman __ARGS((char_u *from, size_t fromlen,
4793 char_u *to, int *tolenp, int maxtolen, char_u *rest,
4794 int *restlenp));
Bram Moolenaar071d4272004-06-13 20:20:40 +00004795
4796 if (ip->bw_restlen > 0)
4797 {
4798 /* Need to concatenate the remainder of the previous call and
4799 * the bytes of the current call. Use the end of the
4800 * conversion buffer for this. */
4801 fromlen = len + ip->bw_restlen;
4802 from = ip->bw_conv_buf + ip->bw_conv_buflen - fromlen;
4803 mch_memmove(from, ip->bw_rest, (size_t)ip->bw_restlen);
4804 mch_memmove(from + ip->bw_restlen, buf, (size_t)len);
4805 }
4806 else
4807 {
4808 from = buf;
4809 fromlen = len;
4810 }
4811
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00004812 if (enc2macroman(from, fromlen,
4813 ip->bw_conv_buf, &len, ip->bw_conv_buflen,
4814 ip->bw_rest, &ip->bw_restlen) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004815 {
4816 ip->bw_conv_error = TRUE;
4817 return FAIL;
4818 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004819 buf = ip->bw_conv_buf;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004820 }
4821# endif
4822
4823# ifdef USE_ICONV
4824 if (ip->bw_iconv_fd != (iconv_t)-1)
4825 {
4826 const char *from;
4827 size_t fromlen;
4828 char *to;
4829 size_t tolen;
4830
4831 /* Convert with iconv(). */
4832 if (ip->bw_restlen > 0)
4833 {
4834 /* Need to concatenate the remainder of the previous call and
4835 * the bytes of the current call. Use the end of the
4836 * conversion buffer for this. */
4837 fromlen = len + ip->bw_restlen;
4838 from = (char *)ip->bw_conv_buf + ip->bw_conv_buflen - fromlen;
4839 mch_memmove((void *)from, ip->bw_rest, (size_t)ip->bw_restlen);
4840 mch_memmove((void *)(from + ip->bw_restlen), buf, (size_t)len);
4841 tolen = ip->bw_conv_buflen - fromlen;
4842 }
4843 else
4844 {
4845 from = (const char *)buf;
4846 fromlen = len;
4847 tolen = ip->bw_conv_buflen;
4848 }
4849 to = (char *)ip->bw_conv_buf;
4850
4851 if (ip->bw_first)
4852 {
4853 size_t save_len = tolen;
4854
4855 /* output the initial shift state sequence */
4856 (void)iconv(ip->bw_iconv_fd, NULL, NULL, &to, &tolen);
4857
4858 /* There is a bug in iconv() on Linux (which appears to be
4859 * wide-spread) which sets "to" to NULL and messes up "tolen".
4860 */
4861 if (to == NULL)
4862 {
4863 to = (char *)ip->bw_conv_buf;
4864 tolen = save_len;
4865 }
4866 ip->bw_first = FALSE;
4867 }
4868
4869 /*
4870 * If iconv() has an error or there is not enough room, fail.
4871 */
4872 if ((iconv(ip->bw_iconv_fd, (void *)&from, &fromlen, &to, &tolen)
4873 == (size_t)-1 && ICONV_ERRNO != ICONV_EINVAL)
4874 || fromlen > CONV_RESTLEN)
4875 {
4876 ip->bw_conv_error = TRUE;
4877 return FAIL;
4878 }
4879
4880 /* copy remainder to ip->bw_rest[] to be used for the next call. */
4881 if (fromlen > 0)
4882 mch_memmove(ip->bw_rest, (void *)from, fromlen);
4883 ip->bw_restlen = (int)fromlen;
4884
4885 buf = ip->bw_conv_buf;
4886 len = (int)((char_u *)to - ip->bw_conv_buf);
4887 }
4888# endif
4889 }
4890#endif /* FEAT_MBYTE */
4891
4892#ifdef FEAT_CRYPT
4893 if (flags & FIO_ENCRYPTED) /* encrypt the data */
4894 {
4895 int ztemp, t, i;
4896
4897 for (i = 0; i < len; i++)
4898 {
4899 ztemp = buf[i];
4900 buf[i] = ZENCODE(ztemp, t);
4901 }
4902 }
4903#endif
4904
4905 /* Repeat the write(), it may be interrupted by a signal. */
4906 while (len)
4907 {
4908 wlen = vim_write(ip->bw_fd, buf, len);
4909 if (wlen <= 0) /* error! */
4910 return FAIL;
4911 len -= wlen;
4912 buf += wlen;
4913 }
4914 return OK;
4915}
4916
4917#ifdef FEAT_MBYTE
4918/*
4919 * Convert a Unicode character to bytes.
4920 */
4921 static int
4922ucs2bytes(c, pp, flags)
4923 unsigned c; /* in: character */
4924 char_u **pp; /* in/out: pointer to result */
4925 int flags; /* FIO_ flags */
4926{
4927 char_u *p = *pp;
4928 int error = FALSE;
4929 int cc;
4930
4931
4932 if (flags & FIO_UCS4)
4933 {
4934 if (flags & FIO_ENDIAN_L)
4935 {
4936 *p++ = c;
4937 *p++ = (c >> 8);
4938 *p++ = (c >> 16);
4939 *p++ = (c >> 24);
4940 }
4941 else
4942 {
4943 *p++ = (c >> 24);
4944 *p++ = (c >> 16);
4945 *p++ = (c >> 8);
4946 *p++ = c;
4947 }
4948 }
4949 else if (flags & (FIO_UCS2 | FIO_UTF16))
4950 {
4951 if (c >= 0x10000)
4952 {
4953 if (flags & FIO_UTF16)
4954 {
4955 /* Make two words, ten bits of the character in each. First
4956 * word is 0xd800 - 0xdbff, second one 0xdc00 - 0xdfff */
4957 c -= 0x10000;
4958 if (c >= 0x100000)
4959 error = TRUE;
4960 cc = ((c >> 10) & 0x3ff) + 0xd800;
4961 if (flags & FIO_ENDIAN_L)
4962 {
4963 *p++ = cc;
4964 *p++ = ((unsigned)cc >> 8);
4965 }
4966 else
4967 {
4968 *p++ = ((unsigned)cc >> 8);
4969 *p++ = cc;
4970 }
4971 c = (c & 0x3ff) + 0xdc00;
4972 }
4973 else
4974 error = TRUE;
4975 }
4976 if (flags & FIO_ENDIAN_L)
4977 {
4978 *p++ = c;
4979 *p++ = (c >> 8);
4980 }
4981 else
4982 {
4983 *p++ = (c >> 8);
4984 *p++ = c;
4985 }
4986 }
4987 else /* Latin1 */
4988 {
4989 if (c >= 0x100)
4990 {
4991 error = TRUE;
4992 *p++ = 0xBF;
4993 }
4994 else
4995 *p++ = c;
4996 }
4997
4998 *pp = p;
4999 return error;
5000}
5001
5002/*
5003 * Return TRUE if "a" and "b" are the same 'encoding'.
5004 * Ignores difference between "ansi" and "latin1", "ucs-4" and "ucs-4be", etc.
5005 */
5006 static int
5007same_encoding(a, b)
5008 char_u *a;
5009 char_u *b;
5010{
5011 int f;
5012
5013 if (STRCMP(a, b) == 0)
5014 return TRUE;
5015 f = get_fio_flags(a);
5016 return (f != 0 && get_fio_flags(b) == f);
5017}
5018
5019/*
5020 * Check "ptr" for a unicode encoding and return the FIO_ flags needed for the
5021 * internal conversion.
5022 * if "ptr" is an empty string, use 'encoding'.
5023 */
5024 static int
5025get_fio_flags(ptr)
5026 char_u *ptr;
5027{
5028 int prop;
5029
5030 if (*ptr == NUL)
5031 ptr = p_enc;
5032
5033 prop = enc_canon_props(ptr);
5034 if (prop & ENC_UNICODE)
5035 {
5036 if (prop & ENC_2BYTE)
5037 {
5038 if (prop & ENC_ENDIAN_L)
5039 return FIO_UCS2 | FIO_ENDIAN_L;
5040 return FIO_UCS2;
5041 }
5042 if (prop & ENC_4BYTE)
5043 {
5044 if (prop & ENC_ENDIAN_L)
5045 return FIO_UCS4 | FIO_ENDIAN_L;
5046 return FIO_UCS4;
5047 }
5048 if (prop & ENC_2WORD)
5049 {
5050 if (prop & ENC_ENDIAN_L)
5051 return FIO_UTF16 | FIO_ENDIAN_L;
5052 return FIO_UTF16;
5053 }
5054 return FIO_UTF8;
5055 }
5056 if (prop & ENC_LATIN1)
5057 return FIO_LATIN1;
5058 /* must be ENC_DBCS, requires iconv() */
5059 return 0;
5060}
5061
5062#ifdef WIN3264
5063/*
5064 * Check "ptr" for a MS-Windows codepage name and return the FIO_ flags needed
5065 * for the conversion MS-Windows can do for us. Also accept "utf-8".
5066 * Used for conversion between 'encoding' and 'fileencoding'.
5067 */
5068 static int
5069get_win_fio_flags(ptr)
5070 char_u *ptr;
5071{
5072 int cp;
5073
5074 /* Cannot do this when 'encoding' is not utf-8 and not a codepage. */
5075 if (!enc_utf8 && enc_codepage <= 0)
5076 return 0;
5077
5078 cp = encname2codepage(ptr);
5079 if (cp == 0)
5080 {
5081# ifdef CP_UTF8 /* VC 4.1 doesn't define CP_UTF8 */
5082 if (STRCMP(ptr, "utf-8") == 0)
5083 cp = CP_UTF8;
5084 else
5085# endif
5086 return 0;
5087 }
5088 return FIO_PUT_CP(cp) | FIO_CODEPAGE;
5089}
5090#endif
5091
5092#ifdef MACOS_X
5093/*
5094 * Check "ptr" for a Carbon supported encoding and return the FIO_ flags
5095 * needed for the internal conversion to/from utf-8 or latin1.
5096 */
5097 static int
5098get_mac_fio_flags(ptr)
5099 char_u *ptr;
5100{
5101 if ((enc_utf8 || STRCMP(p_enc, "latin1") == 0)
5102 && (enc_canon_props(ptr) & ENC_MACROMAN))
5103 return FIO_MACROMAN;
5104 return 0;
5105}
5106#endif
5107
5108/*
5109 * Check for a Unicode BOM (Byte Order Mark) at the start of p[size].
5110 * "size" must be at least 2.
5111 * Return the name of the encoding and set "*lenp" to the length.
5112 * Returns NULL when no BOM found.
5113 */
5114 static char_u *
5115check_for_bom(p, size, lenp, flags)
5116 char_u *p;
5117 long size;
5118 int *lenp;
5119 int flags;
5120{
5121 char *name = NULL;
5122 int len = 2;
5123
5124 if (p[0] == 0xef && p[1] == 0xbb && size >= 3 && p[2] == 0xbf
5125 && (flags == FIO_ALL || flags == 0))
5126 {
5127 name = "utf-8"; /* EF BB BF */
5128 len = 3;
5129 }
5130 else if (p[0] == 0xff && p[1] == 0xfe)
5131 {
5132 if (size >= 4 && p[2] == 0 && p[3] == 0
5133 && (flags == FIO_ALL || flags == (FIO_UCS4 | FIO_ENDIAN_L)))
5134 {
5135 name = "ucs-4le"; /* FF FE 00 00 */
5136 len = 4;
5137 }
5138 else if (flags == FIO_ALL || flags == (FIO_UCS2 | FIO_ENDIAN_L))
5139 name = "ucs-2le"; /* FF FE */
5140 else if (flags == (FIO_UTF16 | FIO_ENDIAN_L))
5141 name = "utf-16le"; /* FF FE */
5142 }
5143 else if (p[0] == 0xfe && p[1] == 0xff
5144 && (flags == FIO_ALL || flags == FIO_UCS2 || flags == FIO_UTF16))
5145 {
5146 if (flags == FIO_UTF16)
5147 name = "utf-16"; /* FE FF */
5148 else
5149 name = "ucs-2"; /* FE FF */
5150 }
5151 else if (size >= 4 && p[0] == 0 && p[1] == 0 && p[2] == 0xfe
5152 && p[3] == 0xff && (flags == FIO_ALL || flags == FIO_UCS4))
5153 {
5154 name = "ucs-4"; /* 00 00 FE FF */
5155 len = 4;
5156 }
5157
5158 *lenp = len;
5159 return (char_u *)name;
5160}
5161
5162/*
5163 * Generate a BOM in "buf[4]" for encoding "name".
5164 * Return the length of the BOM (zero when no BOM).
5165 */
5166 static int
5167make_bom(buf, name)
5168 char_u *buf;
5169 char_u *name;
5170{
5171 int flags;
5172 char_u *p;
5173
5174 flags = get_fio_flags(name);
5175
5176 /* Can't put a BOM in a non-Unicode file. */
5177 if (flags == FIO_LATIN1 || flags == 0)
5178 return 0;
5179
5180 if (flags == FIO_UTF8) /* UTF-8 */
5181 {
5182 buf[0] = 0xef;
5183 buf[1] = 0xbb;
5184 buf[2] = 0xbf;
5185 return 3;
5186 }
5187 p = buf;
5188 (void)ucs2bytes(0xfeff, &p, flags);
5189 return (int)(p - buf);
5190}
5191#endif
5192
5193/*
5194 * Try to find a shortname by comparing the fullname with the current
5195 * directory.
5196 * Returns NULL if not shorter name possible, pointer into "full_path"
5197 * otherwise.
5198 */
5199 char_u *
5200shorten_fname(full_path, dir_name)
5201 char_u *full_path;
5202 char_u *dir_name;
5203{
5204 int len;
5205 char_u *p;
5206
5207 if (full_path == NULL)
5208 return NULL;
5209 len = (int)STRLEN(dir_name);
5210 if (fnamencmp(dir_name, full_path, len) == 0)
5211 {
5212 p = full_path + len;
5213#if defined(MSDOS) || defined(MSWIN) || defined(OS2)
5214 /*
5215 * MSDOS: when a file is in the root directory, dir_name will end in a
5216 * slash, since C: by itself does not define a specific dir. In this
5217 * case p may already be correct. <negri>
5218 */
5219 if (!((len > 2) && (*(p - 2) == ':')))
5220#endif
5221 {
5222 if (vim_ispathsep(*p))
5223 ++p;
5224#ifndef VMS /* the path separator is always part of the path */
5225 else
5226 p = NULL;
5227#endif
5228 }
5229 }
5230#if defined(MSDOS) || defined(MSWIN) || defined(OS2)
5231 /*
5232 * When using a file in the current drive, remove the drive name:
5233 * "A:\dir\file" -> "\dir\file". This helps when moving a session file on
5234 * a floppy from "A:\dir" to "B:\dir".
5235 */
5236 else if (len > 3
5237 && TOUPPER_LOC(full_path[0]) == TOUPPER_LOC(dir_name[0])
5238 && full_path[1] == ':'
5239 && vim_ispathsep(full_path[2]))
5240 p = full_path + 2;
5241#endif
5242 else
5243 p = NULL;
5244 return p;
5245}
5246
5247/*
5248 * Shorten filenames for all buffers.
5249 * When "force" is TRUE: Use full path from now on for files currently being
5250 * edited, both for file name and swap file name. Try to shorten the file
5251 * names a bit, if safe to do so.
5252 * When "force" is FALSE: Only try to shorten absolute file names.
5253 * For buffers that have buftype "nofile" or "scratch": never change the file
5254 * name.
5255 */
5256 void
5257shorten_fnames(force)
5258 int force;
5259{
5260 char_u dirname[MAXPATHL];
5261 buf_T *buf;
5262 char_u *p;
5263
5264 mch_dirname(dirname, MAXPATHL);
5265 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
5266 {
5267 if (buf->b_fname != NULL
5268#ifdef FEAT_QUICKFIX
5269 && !bt_nofile(buf)
5270#endif
5271 && !path_with_url(buf->b_fname)
5272 && (force
5273 || buf->b_sfname == NULL
5274 || mch_isFullName(buf->b_sfname)))
5275 {
5276 vim_free(buf->b_sfname);
5277 buf->b_sfname = NULL;
5278 p = shorten_fname(buf->b_ffname, dirname);
5279 if (p != NULL)
5280 {
5281 buf->b_sfname = vim_strsave(p);
5282 buf->b_fname = buf->b_sfname;
5283 }
5284 if (p == NULL || buf->b_fname == NULL)
5285 buf->b_fname = buf->b_ffname;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005286 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005287
5288 /* Always make the swap file name a full path, a "nofile" buffer may
5289 * also have a swap file. */
5290 mf_fullname(buf->b_ml.ml_mfp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005291 }
5292#ifdef FEAT_WINDOWS
5293 status_redraw_all();
5294#endif
5295}
5296
5297#if (defined(FEAT_DND) && defined(FEAT_GUI_GTK)) \
5298 || defined(FEAT_GUI_MSWIN) \
5299 || defined(FEAT_GUI_MAC) \
5300 || defined(PROTO)
5301/*
5302 * Shorten all filenames in "fnames[count]" by current directory.
5303 */
5304 void
5305shorten_filenames(fnames, count)
5306 char_u **fnames;
5307 int count;
5308{
5309 int i;
5310 char_u dirname[MAXPATHL];
5311 char_u *p;
5312
5313 if (fnames == NULL || count < 1)
5314 return;
5315 mch_dirname(dirname, sizeof(dirname));
5316 for (i = 0; i < count; ++i)
5317 {
5318 if ((p = shorten_fname(fnames[i], dirname)) != NULL)
5319 {
5320 /* shorten_fname() returns pointer in given "fnames[i]". If free
5321 * "fnames[i]" first, "p" becomes invalid. So we need to copy
5322 * "p" first then free fnames[i]. */
5323 p = vim_strsave(p);
5324 vim_free(fnames[i]);
5325 fnames[i] = p;
5326 }
5327 }
5328}
5329#endif
5330
5331/*
5332 * add extention to file name - change path/fo.o.h to path/fo.o.h.ext or
5333 * fo_o_h.ext for MSDOS or when shortname option set.
5334 *
5335 * Assumed that fname is a valid name found in the filesystem we assure that
5336 * the return value is a different name and ends in 'ext'.
5337 * "ext" MUST be at most 4 characters long if it starts with a dot, 3
5338 * characters otherwise.
5339 * Space for the returned name is allocated, must be freed later.
5340 * Returns NULL when out of memory.
5341 */
5342 char_u *
5343modname(fname, ext, prepend_dot)
5344 char_u *fname, *ext;
5345 int prepend_dot; /* may prepend a '.' to file name */
5346{
5347 return buf_modname(
5348#ifdef SHORT_FNAME
5349 TRUE,
5350#else
5351 (curbuf->b_p_sn || curbuf->b_shortname),
5352#endif
5353 fname, ext, prepend_dot);
5354}
5355
5356 char_u *
5357buf_modname(shortname, fname, ext, prepend_dot)
5358 int shortname; /* use 8.3 file name */
5359 char_u *fname, *ext;
5360 int prepend_dot; /* may prepend a '.' to file name */
5361{
5362 char_u *retval;
5363 char_u *s;
5364 char_u *e;
5365 char_u *ptr;
5366 int fnamelen, extlen;
5367
5368 extlen = (int)STRLEN(ext);
5369
5370 /*
5371 * If there is no file name we must get the name of the current directory
5372 * (we need the full path in case :cd is used).
5373 */
5374 if (fname == NULL || *fname == NUL)
5375 {
5376 retval = alloc((unsigned)(MAXPATHL + extlen + 3));
5377 if (retval == NULL)
5378 return NULL;
5379 if (mch_dirname(retval, MAXPATHL) == FAIL ||
5380 (fnamelen = (int)STRLEN(retval)) == 0)
5381 {
5382 vim_free(retval);
5383 return NULL;
5384 }
5385 if (!vim_ispathsep(retval[fnamelen - 1]))
5386 {
5387 retval[fnamelen++] = PATHSEP;
5388 retval[fnamelen] = NUL;
5389 }
5390#ifndef SHORT_FNAME
5391 prepend_dot = FALSE; /* nothing to prepend a dot to */
5392#endif
5393 }
5394 else
5395 {
5396 fnamelen = (int)STRLEN(fname);
5397 retval = alloc((unsigned)(fnamelen + extlen + 3));
5398 if (retval == NULL)
5399 return NULL;
5400 STRCPY(retval, fname);
5401#ifdef VMS
5402 vms_remove_version(retval); /* we do not need versions here */
5403#endif
5404 }
5405
5406 /*
5407 * search backwards until we hit a '/', '\' or ':' replacing all '.'
5408 * by '_' for MSDOS or when shortname option set and ext starts with a dot.
5409 * Then truncate what is after the '/', '\' or ':' to 8 characters for
5410 * MSDOS and 26 characters for AMIGA, a lot more for UNIX.
5411 */
5412 for (ptr = retval + fnamelen; ptr >= retval; ptr--)
5413 {
5414#ifndef RISCOS
5415 if (*ext == '.'
5416#ifdef USE_LONG_FNAME
5417 && (!USE_LONG_FNAME || shortname)
5418#else
5419# ifndef SHORT_FNAME
5420 && shortname
5421# endif
5422#endif
5423 )
5424 if (*ptr == '.') /* replace '.' by '_' */
5425 *ptr = '_';
5426#endif /* RISCOS */
5427 if (vim_ispathsep(*ptr))
5428 break;
5429 }
5430 ptr++;
5431
5432 /* the file name has at most BASENAMELEN characters. */
5433#ifndef SHORT_FNAME
5434 if (STRLEN(ptr) > (unsigned)BASENAMELEN)
5435 ptr[BASENAMELEN] = '\0';
5436#endif
5437
5438 s = ptr + STRLEN(ptr);
5439
5440 /*
5441 * For 8.3 file names we may have to reduce the length.
5442 */
5443#ifdef USE_LONG_FNAME
5444 if (!USE_LONG_FNAME || shortname)
5445#else
5446# ifndef SHORT_FNAME
5447 if (shortname)
5448# endif
5449#endif
5450 {
5451 /*
5452 * If there is no file name, or the file name ends in '/', and the
5453 * extension starts with '.', put a '_' before the dot, because just
5454 * ".ext" is invalid.
5455 */
5456 if (fname == NULL || *fname == NUL
5457 || vim_ispathsep(fname[STRLEN(fname) - 1]))
5458 {
5459#ifdef RISCOS
5460 if (*ext == '/')
5461#else
5462 if (*ext == '.')
5463#endif
5464 *s++ = '_';
5465 }
5466 /*
5467 * If the extension starts with '.', truncate the base name at 8
5468 * characters
5469 */
5470#ifdef RISCOS
5471 /* We normally use '/', but swap files are '_' */
5472 else if (*ext == '/' || *ext == '_')
5473#else
5474 else if (*ext == '.')
5475#endif
5476 {
5477 if (s - ptr > (size_t)8)
5478 {
5479 s = ptr + 8;
5480 *s = '\0';
5481 }
5482 }
5483 /*
5484 * If the extension doesn't start with '.', and the file name
5485 * doesn't have an extension yet, append a '.'
5486 */
5487#ifdef RISCOS
5488 else if ((e = vim_strchr(ptr, '/')) == NULL)
5489 *s++ = '/';
5490#else
5491 else if ((e = vim_strchr(ptr, '.')) == NULL)
5492 *s++ = '.';
5493#endif
5494 /*
5495 * If the extension doesn't start with '.', and there already is an
5496 * extension, it may need to be tructated
5497 */
5498 else if ((int)STRLEN(e) + extlen > 4)
5499 s = e + 4 - extlen;
5500 }
5501#if defined(OS2) || defined(USE_LONG_FNAME) || defined(WIN3264)
5502 /*
5503 * If there is no file name, and the extension starts with '.', put a
5504 * '_' before the dot, because just ".ext" may be invalid if it's on a
5505 * FAT partition, and on HPFS it doesn't matter.
5506 */
5507 else if ((fname == NULL || *fname == NUL) && *ext == '.')
5508 *s++ = '_';
5509#endif
5510
5511 /*
5512 * Append the extention.
5513 * ext can start with '.' and cannot exceed 3 more characters.
5514 */
5515 STRCPY(s, ext);
5516
5517#ifndef SHORT_FNAME
5518 /*
5519 * Prepend the dot.
5520 */
5521 if (prepend_dot && !shortname && *(e = gettail(retval)) !=
5522#ifdef RISCOS
5523 '/'
5524#else
5525 '.'
5526#endif
5527#ifdef USE_LONG_FNAME
5528 && USE_LONG_FNAME
5529#endif
5530 )
5531 {
5532 mch_memmove(e + 1, e, STRLEN(e) + 1);
5533#ifdef RISCOS
5534 *e = '/';
5535#else
5536 *e = '.';
5537#endif
5538 }
5539#endif
5540
5541 /*
5542 * Check that, after appending the extension, the file name is really
5543 * different.
5544 */
5545 if (fname != NULL && STRCMP(fname, retval) == 0)
5546 {
5547 /* we search for a character that can be replaced by '_' */
5548 while (--s >= ptr)
5549 {
5550 if (*s != '_')
5551 {
5552 *s = '_';
5553 break;
5554 }
5555 }
5556 if (s < ptr) /* fname was "________.<ext>", how tricky! */
5557 *ptr = 'v';
5558 }
5559 return retval;
5560}
5561
5562/*
5563 * Like fgets(), but if the file line is too long, it is truncated and the
5564 * rest of the line is thrown away. Returns TRUE for end-of-file.
5565 */
5566 int
5567vim_fgets(buf, size, fp)
5568 char_u *buf;
5569 int size;
5570 FILE *fp;
5571{
5572 char *eof;
5573#define FGETS_SIZE 200
5574 char tbuf[FGETS_SIZE];
5575
5576 buf[size - 2] = NUL;
5577#ifdef USE_CR
5578 eof = fgets_cr((char *)buf, size, fp);
5579#else
5580 eof = fgets((char *)buf, size, fp);
5581#endif
5582 if (buf[size - 2] != NUL && buf[size - 2] != '\n')
5583 {
5584 buf[size - 1] = NUL; /* Truncate the line */
5585
5586 /* Now throw away the rest of the line: */
5587 do
5588 {
5589 tbuf[FGETS_SIZE - 2] = NUL;
5590#ifdef USE_CR
5591 fgets_cr((char *)tbuf, FGETS_SIZE, fp);
5592#else
5593 fgets((char *)tbuf, FGETS_SIZE, fp);
5594#endif
5595 } while (tbuf[FGETS_SIZE - 2] != NUL && tbuf[FGETS_SIZE - 2] != '\n');
5596 }
5597 return (eof == NULL);
5598}
5599
5600#if defined(USE_CR) || defined(PROTO)
5601/*
5602 * Like vim_fgets(), but accept any line terminator: CR, CR-LF or LF.
5603 * Returns TRUE for end-of-file.
5604 * Only used for the Mac, because it's much slower than vim_fgets().
5605 */
5606 int
5607tag_fgets(buf, size, fp)
5608 char_u *buf;
5609 int size;
5610 FILE *fp;
5611{
5612 int i = 0;
5613 int c;
5614 int eof = FALSE;
5615
5616 for (;;)
5617 {
5618 c = fgetc(fp);
5619 if (c == EOF)
5620 {
5621 eof = TRUE;
5622 break;
5623 }
5624 if (c == '\r')
5625 {
5626 /* Always store a NL for end-of-line. */
5627 if (i < size - 1)
5628 buf[i++] = '\n';
5629 c = fgetc(fp);
5630 if (c != '\n') /* Macintosh format: single CR. */
5631 ungetc(c, fp);
5632 break;
5633 }
5634 if (i < size - 1)
5635 buf[i++] = c;
5636 if (c == '\n')
5637 break;
5638 }
5639 buf[i] = NUL;
5640 return eof;
5641}
5642#endif
5643
5644/*
5645 * rename() only works if both files are on the same file system, this
5646 * function will (attempts to?) copy the file across if rename fails -- webb
5647 * Return -1 for failure, 0 for success.
5648 */
5649 int
5650vim_rename(from, to)
5651 char_u *from;
5652 char_u *to;
5653{
5654 int fd_in;
5655 int fd_out;
5656 int n;
5657 char *errmsg = NULL;
5658 char *buffer;
5659#ifdef AMIGA
5660 BPTR flock;
5661#endif
5662 struct stat st;
5663
5664 /*
5665 * When the names are identical, there is nothing to do.
5666 */
5667 if (fnamecmp(from, to) == 0)
5668 return 0;
5669
5670 /*
5671 * Fail if the "from" file doesn't exist. Avoids that "to" is deleted.
5672 */
5673 if (mch_stat((char *)from, &st) < 0)
5674 return -1;
5675
5676 /*
5677 * Delete the "to" file, this is required on some systems to make the
5678 * mch_rename() work, on other systems it makes sure that we don't have
5679 * two files when the mch_rename() fails.
5680 */
5681
5682#ifdef AMIGA
5683 /*
5684 * With MSDOS-compatible filesystems (crossdos, messydos) it is possible
5685 * that the name of the "to" file is the same as the "from" file, even
5686 * though the names are different. To avoid the chance of accidently
5687 * deleting the "from" file (horror!) we lock it during the remove.
5688 *
5689 * When used for making a backup before writing the file: This should not
5690 * happen with ":w", because startscript() should detect this problem and
5691 * set buf->b_shortname, causing modname() to return a correct ".bak" file
5692 * name. This problem does exist with ":w filename", but then the
5693 * original file will be somewhere else so the backup isn't really
5694 * important. If autoscripting is off the rename may fail.
5695 */
5696 flock = Lock((UBYTE *)from, (long)ACCESS_READ);
5697#endif
5698 mch_remove(to);
5699#ifdef AMIGA
5700 if (flock)
5701 UnLock(flock);
5702#endif
5703
5704 /*
5705 * First try a normal rename, return if it works.
5706 */
5707 if (mch_rename((char *)from, (char *)to) == 0)
5708 return 0;
5709
5710 /*
5711 * Rename() failed, try copying the file.
5712 */
5713 fd_in = mch_open((char *)from, O_RDONLY|O_EXTRA, 0);
5714 if (fd_in == -1)
5715 return -1;
5716 fd_out = mch_open((char *)to, O_CREAT|O_EXCL|O_WRONLY|O_EXTRA, 0666);
5717 if (fd_out == -1)
5718 {
5719 close(fd_in);
5720 return -1;
5721 }
5722
5723 buffer = (char *)alloc(BUFSIZE);
5724 if (buffer == NULL)
5725 {
5726 close(fd_in);
5727 close(fd_out);
5728 return -1;
5729 }
5730
5731 while ((n = vim_read(fd_in, buffer, BUFSIZE)) > 0)
5732 if (vim_write(fd_out, buffer, n) != n)
5733 {
5734 errmsg = _("E208: Error writing to \"%s\"");
5735 break;
5736 }
5737
5738 vim_free(buffer);
5739 close(fd_in);
5740 if (close(fd_out) < 0)
5741 errmsg = _("E209: Error closing \"%s\"");
5742 if (n < 0)
5743 {
5744 errmsg = _("E210: Error reading \"%s\"");
5745 to = from;
5746 }
5747 if (errmsg != NULL)
5748 {
5749 EMSG2(errmsg, to);
5750 return -1;
5751 }
5752 mch_remove(from);
5753 return 0;
5754}
5755
5756static int already_warned = FALSE;
5757
5758/*
5759 * Check if any not hidden buffer has been changed.
5760 * Postpone the check if there are characters in the stuff buffer, a global
5761 * command is being executed, a mapping is being executed or an autocommand is
5762 * busy.
5763 * Returns TRUE if some message was written (screen should be redrawn and
5764 * cursor positioned).
5765 */
5766 int
5767check_timestamps(focus)
5768 int focus; /* called for GUI focus event */
5769{
5770 buf_T *buf;
5771 int didit = 0;
5772 int n;
5773
5774 /* Don't check timestamps while system() or another low-level function may
5775 * cause us to lose and gain focus. */
5776 if (no_check_timestamps > 0)
5777 return FALSE;
5778
5779 /* Avoid doing a check twice. The OK/Reload dialog can cause a focus
5780 * event and we would keep on checking if the file is steadily growing.
5781 * Do check again after typing something. */
5782 if (focus && did_check_timestamps)
5783 {
5784 need_check_timestamps = TRUE;
5785 return FALSE;
5786 }
5787
5788 if (!stuff_empty() || global_busy || !typebuf_typed()
5789#ifdef FEAT_AUTOCMD
5790 || autocmd_busy
5791#endif
5792 )
5793 need_check_timestamps = TRUE; /* check later */
5794 else
5795 {
5796 ++no_wait_return;
5797 did_check_timestamps = TRUE;
5798 already_warned = FALSE;
5799 for (buf = firstbuf; buf != NULL; )
5800 {
5801 /* Only check buffers in a window. */
5802 if (buf->b_nwindows > 0)
5803 {
5804 n = buf_check_timestamp(buf, focus);
5805 if (didit < n)
5806 didit = n;
5807 if (n > 0 && !buf_valid(buf))
5808 {
5809 /* Autocommands have removed the buffer, start at the
5810 * first one again. */
5811 buf = firstbuf;
5812 continue;
5813 }
5814 }
5815 buf = buf->b_next;
5816 }
5817 --no_wait_return;
5818 need_check_timestamps = FALSE;
5819 if (need_wait_return && didit == 2)
5820 {
5821 /* make sure msg isn't overwritten */
5822 msg_puts((char_u *)"\n");
5823 out_flush();
5824 }
5825 }
5826 return didit;
5827}
5828
5829/*
5830 * Move all the lines from buffer "frombuf" to buffer "tobuf".
5831 * Return OK or FAIL. When FAIL "tobuf" is incomplete and/or "frombuf" is not
5832 * empty.
5833 */
5834 static int
5835move_lines(frombuf, tobuf)
5836 buf_T *frombuf;
5837 buf_T *tobuf;
5838{
5839 buf_T *tbuf = curbuf;
5840 int retval = OK;
5841 linenr_T lnum;
5842 char_u *p;
5843
5844 /* Copy the lines in "frombuf" to "tobuf". */
5845 curbuf = tobuf;
5846 for (lnum = 1; lnum <= frombuf->b_ml.ml_line_count; ++lnum)
5847 {
5848 p = vim_strsave(ml_get_buf(frombuf, lnum, FALSE));
5849 if (p == NULL || ml_append(lnum - 1, p, 0, FALSE) == FAIL)
5850 {
5851 vim_free(p);
5852 retval = FAIL;
5853 break;
5854 }
5855 vim_free(p);
5856 }
5857
5858 /* Delete all the lines in "frombuf". */
5859 if (retval != FAIL)
5860 {
5861 curbuf = frombuf;
5862 while (!bufempty())
5863 if (ml_delete(curbuf->b_ml.ml_line_count, FALSE) == FAIL)
5864 {
5865 /* Oops! We could try putting back the saved lines, but that
5866 * might fail again... */
5867 retval = FAIL;
5868 break;
5869 }
5870 }
5871
5872 curbuf = tbuf;
5873 return retval;
5874}
5875
5876/*
5877 * Check if buffer "buf" has been changed.
5878 * Also check if the file for a new buffer unexpectedly appeared.
5879 * return 1 if a changed buffer was found.
5880 * return 2 if a message has been displayed.
5881 * return 0 otherwise.
5882 */
5883/*ARGSUSED*/
5884 int
5885buf_check_timestamp(buf, focus)
5886 buf_T *buf;
5887 int focus; /* called for GUI focus event */
5888{
5889 struct stat st;
5890 int stat_res;
5891 int retval = 0;
5892 char_u *path;
5893 char_u *tbuf;
5894 char *mesg = NULL;
5895 char *mesg2;
5896 int helpmesg = FALSE;
5897 int reload = FALSE;
5898#if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
5899 int can_reload = FALSE;
5900#endif
5901 size_t orig_size = buf->b_orig_size;
5902 int orig_mode = buf->b_orig_mode;
5903#ifdef FEAT_GUI
5904 int save_mouse_correct = need_mouse_correct;
5905#endif
5906#ifdef FEAT_AUTOCMD
5907 static int busy = FALSE;
5908#endif
5909
5910 /* If there is no file name, the buffer is not loaded, 'buftype' is
5911 * set, we are in the middle of a save or being called recursively: ignore
5912 * this buffer. */
5913 if (buf->b_ffname == NULL
5914 || buf->b_ml.ml_mfp == NULL
5915#if defined(FEAT_QUICKFIX)
5916 || *buf->b_p_bt != NUL
5917#endif
5918 || buf->b_saving
5919#ifdef FEAT_AUTOCMD
5920 || busy
5921#endif
5922 )
5923 return 0;
5924
5925 if ( !(buf->b_flags & BF_NOTEDITED)
5926 && buf->b_mtime != 0
5927 && ((stat_res = mch_stat((char *)buf->b_ffname, &st)) < 0
5928 || time_differs((long)st.st_mtime, buf->b_mtime)
5929#ifdef HAVE_ST_MODE
5930 || (int)st.st_mode != buf->b_orig_mode
5931#else
5932 || mch_getperm(buf->b_ffname) != buf->b_orig_mode
5933#endif
5934 ))
5935 {
5936 retval = 1;
5937
5938 /* set b_mtime to stop further warnings */
5939 if (stat_res < 0)
5940 {
5941 buf->b_mtime = 0;
5942 buf->b_orig_size = 0;
5943 buf->b_orig_mode = 0;
5944 }
5945 else
5946 buf_store_time(buf, &st, buf->b_ffname);
5947
5948 /* Don't do anything for a directory. Might contain the file
5949 * explorer. */
5950 if (mch_isdir(buf->b_fname))
5951 ;
5952
5953 /*
5954 * If 'autoread' is set, the buffer has no changes and the file still
5955 * exists, reload the buffer. Use the buffer-local option value if it
5956 * was set, the global option value otherwise.
5957 */
5958 else if ((buf->b_p_ar >= 0 ? buf->b_p_ar : p_ar)
5959 && !bufIsChanged(buf) && stat_res >= 0)
5960 reload = TRUE;
5961 else
5962 {
5963#ifdef FEAT_AUTOCMD
5964 int n;
5965
5966 /*
5967 * Only give the warning if there are no FileChangedShell
5968 * autocommands.
5969 * Avoid being called recursively by setting "busy".
5970 */
5971 busy = TRUE;
5972 n = apply_autocmds(EVENT_FILECHANGEDSHELL,
5973 buf->b_fname, buf->b_fname, FALSE, buf);
5974 busy = FALSE;
5975 if (n)
5976 {
5977 if (!buf_valid(buf))
5978 EMSG(_("E246: FileChangedShell autocommand deleted buffer"));
5979 return 2;
5980 }
5981 else
5982#endif
5983 {
5984 if (stat_res < 0)
5985 mesg = _("E211: Warning: File \"%s\" no longer available");
5986 else
5987 {
5988 helpmesg = TRUE;
5989#if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
5990 can_reload = TRUE;
5991#endif
5992 /*
5993 * Check if the file contents really changed to avoid
5994 * giving a warning when only the timestamp was set (e.g.,
5995 * checked out of CVS). Always warn when the buffer was
5996 * changed.
5997 */
5998 if (bufIsChanged(buf))
5999 mesg = _("W12: Warning: File \"%s\" has changed and the buffer was changed in Vim as well");
6000 else if (orig_size != buf->b_orig_size
6001 || buf_contents_changed(buf))
6002 mesg = _("W11: Warning: File \"%s\" has changed since editing started");
6003 else if (orig_mode != buf->b_orig_mode)
6004 mesg = _("W16: Warning: Mode of file \"%s\" has changed since editing started");
6005 }
6006 }
6007 }
6008
6009 }
6010 else if ((buf->b_flags & BF_NEW) && !(buf->b_flags & BF_NEW_W)
6011 && vim_fexists(buf->b_ffname))
6012 {
6013 retval = 1;
6014 mesg = _("W13: Warning: File \"%s\" has been created after editing started");
6015 buf->b_flags |= BF_NEW_W;
6016#if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
6017 can_reload = TRUE;
6018#endif
6019 }
6020
6021 if (mesg != NULL)
6022 {
6023 path = home_replace_save(buf, buf->b_fname);
6024 if (path != NULL)
6025 {
6026 if (helpmesg)
6027 mesg2 = _("See \":help W11\" for more info.");
6028 else
6029 mesg2 = "";
6030 tbuf = alloc((unsigned)(STRLEN(path) + STRLEN(mesg)
6031 + STRLEN(mesg2) + 2));
6032 sprintf((char *)tbuf, mesg, path);
6033#if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
6034 if (can_reload)
6035 {
6036 if (*mesg2 != NUL)
6037 {
6038 STRCAT(tbuf, "\n");
6039 STRCAT(tbuf, mesg2);
6040 }
6041 if (do_dialog(VIM_WARNING, (char_u *)_("Warning"), tbuf,
6042 (char_u *)_("&OK\n&Load File"), 1, NULL) == 2)
6043 reload = TRUE;
6044 }
6045 else
6046#endif
6047 if (State > NORMAL_BUSY || (State & CMDLINE) || already_warned)
6048 {
6049 if (*mesg2 != NUL)
6050 {
6051 STRCAT(tbuf, "; ");
6052 STRCAT(tbuf, mesg2);
6053 }
6054 EMSG(tbuf);
6055 retval = 2;
6056 }
6057 else
6058 {
Bram Moolenaared203462004-06-16 11:19:22 +00006059# ifdef FEAT_AUTOCMD
Bram Moolenaar071d4272004-06-13 20:20:40 +00006060 if (!autocmd_busy)
Bram Moolenaared203462004-06-16 11:19:22 +00006061# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006062 {
6063 msg_start();
6064 msg_puts_attr(tbuf, hl_attr(HLF_E) + MSG_HIST);
6065 if (*mesg2 != NUL)
6066 msg_puts_attr((char_u *)mesg2,
6067 hl_attr(HLF_W) + MSG_HIST);
6068 msg_clr_eos();
6069 (void)msg_end();
6070 if (emsg_silent == 0)
6071 {
6072 out_flush();
Bram Moolenaared203462004-06-16 11:19:22 +00006073# ifdef FEAT_GUI
Bram Moolenaar071d4272004-06-13 20:20:40 +00006074 if (!focus)
Bram Moolenaared203462004-06-16 11:19:22 +00006075# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006076 /* give the user some time to think about it */
6077 ui_delay(1000L, TRUE);
6078
6079 /* don't redraw and erase the message */
6080 redraw_cmdline = FALSE;
6081 }
6082 }
6083 already_warned = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006084 }
6085
6086 vim_free(path);
6087 vim_free(tbuf);
6088 }
6089 }
6090
6091 if (reload)
6092 {
6093 exarg_T ea;
6094 pos_T old_cursor;
6095 linenr_T old_topline;
6096 int old_ro = buf->b_p_ro;
6097 buf_T *savebuf;
6098 int saved = OK;
6099#ifdef FEAT_AUTOCMD
6100 aco_save_T aco;
6101
6102 /* set curwin/curbuf for "buf" and save some things */
6103 aucmd_prepbuf(&aco, buf);
6104#else
6105 buf_T *save_curbuf = curbuf;
6106
6107 curbuf = buf;
6108 curwin->w_buffer = buf;
6109#endif
6110
6111 /* We only want to read the text from the file, not reset the syntax
6112 * highlighting, clear marks, diff status, etc. Force the fileformat
6113 * and encoding to be the same. */
6114 if (prep_exarg(&ea, buf) == OK)
6115 {
6116 old_cursor = curwin->w_cursor;
6117 old_topline = curwin->w_topline;
6118
6119 /*
6120 * To behave like when a new file is edited (matters for
6121 * BufReadPost autocommands) we first need to delete the current
6122 * buffer contents. But if reading the file fails we should keep
6123 * the old contents. Can't use memory only, the file might be
6124 * too big. Use a hidden buffer to move the buffer contents to.
6125 */
6126 if (bufempty())
6127 savebuf = NULL;
6128 else
6129 {
6130 /* Allocate a buffer without putting it in the buffer list. */
6131 savebuf = buflist_new(NULL, NULL, (linenr_T)1, BLN_DUMMY);
6132 if (savebuf != NULL)
6133 {
6134 /* Open the memline. */
6135 curbuf = savebuf;
6136 curwin->w_buffer = savebuf;
6137 saved = ml_open();
6138 curbuf = buf;
6139 curwin->w_buffer = buf;
6140 }
6141 if (savebuf == NULL || saved == FAIL
6142 || move_lines(buf, savebuf) == FAIL)
6143 {
6144 EMSG2(_("E462: Could not prepare for reloading \"%s\""),
6145 buf->b_fname);
6146 saved = FAIL;
6147 }
6148 }
6149
6150 if (saved == OK)
6151 {
6152 curbuf->b_flags |= BF_CHECK_RO; /* check for RO again */
6153#ifdef FEAT_AUTOCMD
6154 keep_filetype = TRUE; /* don't detect 'filetype' */
6155#endif
6156 if (readfile(buf->b_ffname, buf->b_fname, (linenr_T)0,
6157 (linenr_T)0,
6158 (linenr_T)MAXLNUM, &ea, READ_NEW) == FAIL)
6159 {
6160#if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
6161 if (!aborting())
6162#endif
6163 EMSG2(_("E321: Could not reload \"%s\""), buf->b_fname);
6164 if (savebuf != NULL)
6165 {
6166 /* Put the text back from the save buffer. First
6167 * delete any lines that readfile() added. */
6168 while (!bufempty())
6169 if (ml_delete(curbuf->b_ml.ml_line_count, FALSE)
6170 == FAIL)
6171 break;
6172 (void)move_lines(savebuf, buf);
6173 }
6174 }
6175 else
6176 {
6177 /* Mark the buffer as unmodified and free undo info. */
6178 unchanged(buf, TRUE);
6179 u_blockfree(buf);
6180 u_clearall(buf);
6181 }
6182 }
6183 vim_free(ea.cmd);
6184
6185 if (savebuf != NULL)
6186 wipe_buffer(savebuf, FALSE);
6187
6188#ifdef FEAT_DIFF
6189 /* Invalidate diff info if necessary. */
6190 diff_invalidate();
6191#endif
6192
6193 /* Restore the topline and cursor position and check it (lines may
6194 * have been removed). */
6195 if (old_topline > curbuf->b_ml.ml_line_count)
6196 curwin->w_topline = curbuf->b_ml.ml_line_count;
6197 else
6198 curwin->w_topline = old_topline;
6199 curwin->w_cursor = old_cursor;
6200 check_cursor();
6201 update_topline();
6202#ifdef FEAT_AUTOCMD
6203 keep_filetype = FALSE;
6204#endif
6205#ifdef FEAT_FOLDING
6206 {
6207 win_T *wp;
6208
6209 /* Update folds unless they are defined manually. */
6210 FOR_ALL_WINDOWS(wp)
6211 if (wp->w_buffer == curwin->w_buffer
6212 && !foldmethodIsManual(wp))
6213 foldUpdateAll(wp);
6214 }
6215#endif
6216 /* If the mode didn't change and 'readonly' was set, keep the old
6217 * value; the user probably used the ":view" command. But don't
6218 * reset it, might have had a read error. */
6219 if (orig_mode == curbuf->b_orig_mode)
6220 curbuf->b_p_ro |= old_ro;
6221 }
6222
6223#ifdef FEAT_AUTOCMD
6224 /* restore curwin/curbuf and a few other things */
6225 aucmd_restbuf(&aco);
6226 /* Careful: autocommands may have made "buf" invalid! */
6227#else
6228 curwin->w_buffer = save_curbuf;
6229 curbuf = save_curbuf;
6230#endif
6231 }
6232
6233#ifdef FEAT_GUI
6234 /* restore this in case an autocommand has set it; it would break
6235 * 'mousefocus' */
6236 need_mouse_correct = save_mouse_correct;
6237#endif
6238
6239 return retval;
6240}
6241
6242/*ARGSUSED*/
6243 void
6244buf_store_time(buf, st, fname)
6245 buf_T *buf;
6246 struct stat *st;
6247 char_u *fname;
6248{
6249 buf->b_mtime = (long)st->st_mtime;
6250 buf->b_orig_size = (size_t)st->st_size;
6251#ifdef HAVE_ST_MODE
6252 buf->b_orig_mode = (int)st->st_mode;
6253#else
6254 buf->b_orig_mode = mch_getperm(fname);
6255#endif
6256}
6257
6258/*
6259 * Adjust the line with missing eol, used for the next write.
6260 * Used for do_filter(), when the input lines for the filter are deleted.
6261 */
6262 void
6263write_lnum_adjust(offset)
6264 linenr_T offset;
6265{
6266 if (write_no_eol_lnum) /* only if there is a missing eol */
6267 write_no_eol_lnum += offset;
6268}
6269
6270#if defined(TEMPDIRNAMES) || defined(PROTO)
6271static long temp_count = 0; /* Temp filename counter. */
6272
6273/*
6274 * Delete the temp directory and all files it contains.
6275 */
6276 void
6277vim_deltempdir()
6278{
6279 char_u **files;
6280 int file_count;
6281 int i;
6282
6283 if (vim_tempdir != NULL)
6284 {
6285 sprintf((char *)NameBuff, "%s*", vim_tempdir);
6286 if (gen_expand_wildcards(1, &NameBuff, &file_count, &files,
6287 EW_DIR|EW_FILE|EW_SILENT) == OK)
6288 {
6289 for (i = 0; i < file_count; ++i)
6290 mch_remove(files[i]);
6291 FreeWild(file_count, files);
6292 }
6293 gettail(NameBuff)[-1] = NUL;
6294 (void)mch_rmdir(NameBuff);
6295
6296 vim_free(vim_tempdir);
6297 vim_tempdir = NULL;
6298 }
6299}
6300#endif
6301
6302/*
6303 * vim_tempname(): Return a unique name that can be used for a temp file.
6304 *
6305 * The temp file is NOT created.
6306 *
6307 * The returned pointer is to allocated memory.
6308 * The returned pointer is NULL if no valid name was found.
6309 */
6310/*ARGSUSED*/
6311 char_u *
6312vim_tempname(extra_char)
6313 int extra_char; /* character to use in the name instead of '?' */
6314{
6315#ifdef USE_TMPNAM
6316 char_u itmp[L_tmpnam]; /* use tmpnam() */
6317#else
6318 char_u itmp[TEMPNAMELEN];
6319#endif
6320
6321#ifdef TEMPDIRNAMES
6322 static char *(tempdirs[]) = {TEMPDIRNAMES};
6323 int i;
6324 long nr;
6325 long off;
6326# ifndef EEXIST
6327 struct stat st;
6328# endif
6329
6330 /*
6331 * This will create a directory for private use by this instance of Vim.
6332 * This is done once, and the same directory is used for all temp files.
6333 * This method avoids security problems because of symlink attacks et al.
6334 * It's also a bit faster, because we only need to check for an existing
6335 * file when creating the directory and not for each temp file.
6336 */
6337 if (vim_tempdir == NULL)
6338 {
6339 /*
6340 * Try the entries in TEMPDIRNAMES to create the temp directory.
6341 */
6342 for (i = 0; i < sizeof(tempdirs) / sizeof(char *); ++i)
6343 {
6344 /* expand $TMP, leave room for "/v1100000/999999999" */
6345 expand_env((char_u *)tempdirs[i], itmp, TEMPNAMELEN - 20);
6346 if (mch_isdir(itmp)) /* directory exists */
6347 {
6348# ifdef __EMX__
6349 /* If $TMP contains a forward slash (perhaps using bash or
6350 * tcsh), don't add a backslash, use a forward slash!
6351 * Adding 2 backslashes didn't work. */
6352 if (vim_strchr(itmp, '/') != NULL)
6353 STRCAT(itmp, "/");
6354 else
6355# endif
6356 add_pathsep(itmp);
6357
6358 /* Get an arbitrary number of up to 6 digits. When it's
6359 * unlikely that it already exists it will be faster,
6360 * otherwise it doesn't matter. The use of mkdir() avoids any
6361 * security problems because of the predictable number. */
6362 nr = (mch_get_pid() + (long)time(NULL)) % 1000000L;
6363
6364 /* Try up to 10000 different values until we find a name that
6365 * doesn't exist. */
6366 for (off = 0; off < 10000L; ++off)
6367 {
6368 int r;
6369#if defined(UNIX) || defined(VMS)
6370 mode_t umask_save;
6371#endif
6372
6373 sprintf((char *)itmp + STRLEN(itmp), "v%ld", nr + off);
6374# ifndef EEXIST
6375 /* If mkdir() does not set errno to EEXIST, check for
6376 * existing file here. There is a race condition then,
6377 * although it's fail-safe. */
6378 if (mch_stat((char *)itmp, &st) >= 0)
6379 continue;
6380# endif
6381#if defined(UNIX) || defined(VMS)
6382 /* Make sure the umask doesn't remove the executable bit.
6383 * "repl" has been reported to use "177". */
6384 umask_save = umask(077);
6385#endif
6386 r = vim_mkdir(itmp, 0700);
6387#if defined(UNIX) || defined(VMS)
6388 (void)umask(umask_save);
6389#endif
6390 if (r == 0)
6391 {
6392 char_u *buf;
6393
6394 /* Directory was created, use this name.
6395 * Expand to full path; When using the current
6396 * directory a ":cd" would confuse us. */
6397 buf = alloc((unsigned)MAXPATHL + 1);
6398 if (buf != NULL)
6399 {
6400 if (vim_FullName(itmp, buf, MAXPATHL, FALSE)
6401 == FAIL)
6402 STRCPY(buf, itmp);
6403# ifdef __EMX__
6404 if (vim_strchr(buf, '/') != NULL)
6405 STRCAT(buf, "/");
6406 else
6407# endif
6408 add_pathsep(buf);
6409 vim_tempdir = vim_strsave(buf);
6410 vim_free(buf);
6411 }
6412 break;
6413 }
6414# ifdef EEXIST
6415 /* If the mkdir() didn't fail because the file/dir exists,
6416 * we probably can't create any dir here, try another
6417 * place. */
6418 if (errno != EEXIST)
6419# endif
6420 break;
6421 }
6422 if (vim_tempdir != NULL)
6423 break;
6424 }
6425 }
6426 }
6427
6428 if (vim_tempdir != NULL)
6429 {
6430 /* There is no need to check if the file exists, because we own the
6431 * directory and nobody else creates a file in it. */
6432 sprintf((char *)itmp, "%s%ld", vim_tempdir, temp_count++);
6433 return vim_strsave(itmp);
6434 }
6435
6436 return NULL;
6437
6438#else /* TEMPDIRNAMES */
6439
6440# ifdef WIN3264
6441 char szTempFile[_MAX_PATH + 1];
6442 char buf4[4];
6443 char_u *retval;
6444 char_u *p;
6445
6446 STRCPY(itmp, "");
6447 if (GetTempPath(_MAX_PATH, szTempFile) == 0)
6448 szTempFile[0] = NUL; /* GetTempPath() failed, use current dir */
6449 strcpy(buf4, "VIM");
6450 buf4[2] = extra_char; /* make it "VIa", "VIb", etc. */
6451 if (GetTempFileName(szTempFile, buf4, 0, itmp) == 0)
6452 return NULL;
6453 /* GetTempFileName() will create the file, we don't want that */
6454 (void)DeleteFile(itmp);
6455
6456 /* Backslashes in a temp file name cause problems when filtering with
6457 * "sh". NOTE: This also checks 'shellcmdflag' to help those people who
6458 * didn't set 'shellslash'. */
6459 retval = vim_strsave(itmp);
6460 if (*p_shcf == '-' || p_ssl)
6461 for (p = retval; *p; ++p)
6462 if (*p == '\\')
6463 *p = '/';
6464 return retval;
6465
6466# else /* WIN3264 */
6467
6468# ifdef USE_TMPNAM
6469 /* tmpnam() will make its own name */
6470 if (*tmpnam((char *)itmp) == NUL)
6471 return NULL;
6472# else
6473 char_u *p;
6474
6475# ifdef VMS_TEMPNAM
6476 /* mktemp() is not working on VMS. It seems to be
6477 * a do-nothing function. Therefore we use tempnam().
6478 */
6479 sprintf((char *)itmp, "VIM%c", extra_char);
6480 p = (char_u *)tempnam("tmp:", (char *)itmp);
6481 if (p != NULL)
6482 {
6483 /* VMS will use '.LOG' if we don't explicitly specify an extension,
6484 * and VIM will then be unable to find the file later */
6485 STRCPY(itmp, p);
6486 STRCAT(itmp, ".txt");
6487 free(p);
6488 }
6489 else
6490 return NULL;
6491# else
6492 STRCPY(itmp, TEMPNAME);
6493 if ((p = vim_strchr(itmp, '?')) != NULL)
6494 *p = extra_char;
6495 if (mktemp((char *)itmp) == NULL)
6496 return NULL;
6497# endif
6498# endif
6499
6500 return vim_strsave(itmp);
6501# endif /* WIN3264 */
6502#endif /* TEMPDIRNAMES */
6503}
6504
6505#if defined(BACKSLASH_IN_FILENAME) || defined(PROTO)
6506/*
6507 * Convert all backslashes in fname to forward slashes in-place.
6508 */
6509 void
6510forward_slash(fname)
6511 char_u *fname;
6512{
6513 char_u *p;
6514
6515 for (p = fname; *p != NUL; ++p)
6516# ifdef FEAT_MBYTE
6517 /* The Big5 encoding can have '\' in the trail byte. */
6518 if (enc_dbcs != 0 && (*mb_ptr2len_check)(p) > 1)
6519 ++p;
6520 else
6521# endif
6522 if (*p == '\\')
6523 *p = '/';
6524}
6525#endif
6526
6527
6528/*
6529 * Code for automatic commands.
6530 *
6531 * Only included when "FEAT_AUTOCMD" has been defined.
6532 */
6533
6534#if defined(FEAT_AUTOCMD) || defined(PROTO)
6535
6536/*
6537 * The autocommands are stored in a list for each event.
6538 * Autocommands for the same pattern, that are consecutive, are joined
6539 * together, to avoid having to match the pattern too often.
6540 * The result is an array of Autopat lists, which point to AutoCmd lists:
6541 *
6542 * first_autopat[0] --> Autopat.next --> Autopat.next --> NULL
6543 * Autopat.cmds Autopat.cmds
6544 * | |
6545 * V V
6546 * AutoCmd.next AutoCmd.next
6547 * | |
6548 * V V
6549 * AutoCmd.next NULL
6550 * |
6551 * V
6552 * NULL
6553 *
6554 * first_autopat[1] --> Autopat.next --> NULL
6555 * Autopat.cmds
6556 * |
6557 * V
6558 * AutoCmd.next
6559 * |
6560 * V
6561 * NULL
6562 * etc.
6563 *
6564 * The order of AutoCmds is important, this is the order in which they were
6565 * defined and will have to be executed.
6566 */
6567typedef struct AutoCmd
6568{
6569 char_u *cmd; /* The command to be executed (NULL
6570 when command has been removed) */
6571 char nested; /* If autocommands nest here */
6572 char last; /* last command in list */
6573#ifdef FEAT_EVAL
6574 scid_T scriptID; /* script ID where defined */
6575#endif
6576 struct AutoCmd *next; /* Next AutoCmd in list */
6577} AutoCmd;
6578
6579typedef struct AutoPat
6580{
6581 int group; /* group ID */
6582 char_u *pat; /* pattern as typed (NULL when pattern
6583 has been removed) */
6584 int patlen; /* strlen() of pat */
6585 char_u *reg_pat; /* pattern converted to regexp */
6586 char allow_dirs; /* Pattern may match whole path */
6587 char last; /* last pattern for apply_autocmds() */
6588 AutoCmd *cmds; /* list of commands to do */
6589 struct AutoPat *next; /* next AutoPat in AutoPat list */
6590} AutoPat;
6591
6592static struct event_name
6593{
6594 char *name; /* event name */
6595 EVENT_T event; /* event number */
6596} event_names[] =
6597{
6598 {"BufAdd", EVENT_BUFADD},
6599 {"BufCreate", EVENT_BUFADD},
6600 {"BufDelete", EVENT_BUFDELETE},
6601 {"BufEnter", EVENT_BUFENTER},
6602 {"BufFilePost", EVENT_BUFFILEPOST},
6603 {"BufFilePre", EVENT_BUFFILEPRE},
6604 {"BufHidden", EVENT_BUFHIDDEN},
6605 {"BufLeave", EVENT_BUFLEAVE},
6606 {"BufNew", EVENT_BUFNEW},
6607 {"BufNewFile", EVENT_BUFNEWFILE},
6608 {"BufRead", EVENT_BUFREADPOST},
6609 {"BufReadCmd", EVENT_BUFREADCMD},
6610 {"BufReadPost", EVENT_BUFREADPOST},
6611 {"BufReadPre", EVENT_BUFREADPRE},
6612 {"BufUnload", EVENT_BUFUNLOAD},
6613 {"BufWinEnter", EVENT_BUFWINENTER},
6614 {"BufWinLeave", EVENT_BUFWINLEAVE},
6615 {"BufWipeout", EVENT_BUFWIPEOUT},
6616 {"BufWrite", EVENT_BUFWRITEPRE},
6617 {"BufWritePost", EVENT_BUFWRITEPOST},
6618 {"BufWritePre", EVENT_BUFWRITEPRE},
6619 {"BufWriteCmd", EVENT_BUFWRITECMD},
6620 {"CmdwinEnter", EVENT_CMDWINENTER},
6621 {"CmdwinLeave", EVENT_CMDWINLEAVE},
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00006622 {"ColorScheme", EVENT_COLORSCHEME},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006623 {"EncodingChanged", EVENT_ENCODINGCHANGED},
6624 {"FileEncoding", EVENT_ENCODINGCHANGED},
6625 {"CursorHold", EVENT_CURSORHOLD},
6626 {"FileAppendPost", EVENT_FILEAPPENDPOST},
6627 {"FileAppendPre", EVENT_FILEAPPENDPRE},
6628 {"FileAppendCmd", EVENT_FILEAPPENDCMD},
6629 {"FileChangedShell",EVENT_FILECHANGEDSHELL},
6630 {"FileChangedRO", EVENT_FILECHANGEDRO},
6631 {"FileReadPost", EVENT_FILEREADPOST},
6632 {"FileReadPre", EVENT_FILEREADPRE},
6633 {"FileReadCmd", EVENT_FILEREADCMD},
6634 {"FileType", EVENT_FILETYPE},
6635 {"FileWritePost", EVENT_FILEWRITEPOST},
6636 {"FileWritePre", EVENT_FILEWRITEPRE},
6637 {"FileWriteCmd", EVENT_FILEWRITECMD},
6638 {"FilterReadPost", EVENT_FILTERREADPOST},
6639 {"FilterReadPre", EVENT_FILTERREADPRE},
6640 {"FilterWritePost", EVENT_FILTERWRITEPOST},
6641 {"FilterWritePre", EVENT_FILTERWRITEPRE},
6642 {"FocusGained", EVENT_FOCUSGAINED},
6643 {"FocusLost", EVENT_FOCUSLOST},
6644 {"FuncUndefined", EVENT_FUNCUNDEFINED},
6645 {"GUIEnter", EVENT_GUIENTER},
Bram Moolenaar843ee412004-06-30 16:16:41 +00006646 {"InsertChange", EVENT_INSERTCHANGE},
6647 {"InsertEnter", EVENT_INSERTENTER},
6648 {"InsertLeave", EVENT_INSERTLEAVE},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006649 {"RemoteReply", EVENT_REMOTEREPLY},
6650 {"StdinReadPost", EVENT_STDINREADPOST},
6651 {"StdinReadPre", EVENT_STDINREADPRE},
6652 {"Syntax", EVENT_SYNTAX},
6653 {"TermChanged", EVENT_TERMCHANGED},
6654 {"TermResponse", EVENT_TERMRESPONSE},
6655 {"User", EVENT_USER},
6656 {"VimEnter", EVENT_VIMENTER},
6657 {"VimLeave", EVENT_VIMLEAVE},
6658 {"VimLeavePre", EVENT_VIMLEAVEPRE},
6659 {"WinEnter", EVENT_WINENTER},
6660 {"WinLeave", EVENT_WINLEAVE},
6661 {NULL, (EVENT_T)0}
6662};
6663
6664static AutoPat *first_autopat[NUM_EVENTS] =
6665{
6666 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
6667 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
6668 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
6669 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00006670 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
6671 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
Bram Moolenaar071d4272004-06-13 20:20:40 +00006672};
6673
6674/*
6675 * struct used to keep status while executing autocommands for an event.
6676 */
6677typedef struct AutoPatCmd
6678{
6679 AutoPat *curpat; /* next AutoPat to examine */
6680 AutoCmd *nextcmd; /* next AutoCmd to execute */
6681 int group; /* group being used */
6682 char_u *fname; /* fname to match with */
6683 char_u *sfname; /* sfname to match with */
6684 char_u *tail; /* tail of fname */
6685 EVENT_T event; /* current event */
6686} AutoPatCmd;
6687
6688/*
6689 * augroups stores a list of autocmd group names.
6690 */
6691garray_T augroups = {0, 0, sizeof(char_u *), 10, NULL};
6692#define AUGROUP_NAME(i) (((char_u **)augroups.ga_data)[i])
6693
6694/*
6695 * The ID of the current group. Group 0 is the default one.
6696 */
6697#define AUGROUP_DEFAULT -1 /* default autocmd group */
6698#define AUGROUP_ERROR -2 /* errornouse autocmd group */
6699#define AUGROUP_ALL -3 /* all autocmd groups */
6700static int current_augroup = AUGROUP_DEFAULT;
6701
6702static int au_need_clean = FALSE; /* need to delete marked patterns */
6703
6704static void show_autocmd __ARGS((AutoPat *ap, EVENT_T event));
6705static void au_remove_pat __ARGS((AutoPat *ap));
6706static void au_remove_cmds __ARGS((AutoPat *ap));
6707static void au_cleanup __ARGS((void));
6708static int au_new_group __ARGS((char_u *name));
6709static void au_del_group __ARGS((char_u *name));
6710static int au_find_group __ARGS((char_u *name));
6711static EVENT_T event_name2nr __ARGS((char_u *start, char_u **end));
6712static char_u *event_nr2name __ARGS((EVENT_T event));
6713static char_u *find_end_event __ARGS((char_u *arg, int have_group));
6714static int event_ignored __ARGS((EVENT_T event));
6715static int au_get_grouparg __ARGS((char_u **argp));
6716static int do_autocmd_event __ARGS((EVENT_T event, char_u *pat, int nested, char_u *cmd, int forceit, int group));
6717static char_u *getnextac __ARGS((int c, void *cookie, int indent));
6718static int apply_autocmds_group __ARGS((EVENT_T event, char_u *fname, char_u *fname_io, int force, int group, buf_T *buf, exarg_T *eap));
6719static void auto_next_pat __ARGS((AutoPatCmd *apc, int stop_at_last));
6720
6721static EVENT_T last_event;
6722static int last_group;
6723
6724/*
6725 * Show the autocommands for one AutoPat.
6726 */
6727 static void
6728show_autocmd(ap, event)
6729 AutoPat *ap;
6730 EVENT_T event;
6731{
6732 AutoCmd *ac;
6733
6734 /* Check for "got_int" (here and at various places below), which is set
6735 * when "q" has been hit for the "--more--" prompt */
6736 if (got_int)
6737 return;
6738 if (ap->pat == NULL) /* pattern has been removed */
6739 return;
6740
6741 msg_putchar('\n');
6742 if (got_int)
6743 return;
6744 if (event != last_event || ap->group != last_group)
6745 {
6746 if (ap->group != AUGROUP_DEFAULT)
6747 {
6748 if (AUGROUP_NAME(ap->group) == NULL)
6749 msg_puts_attr((char_u *)_("--Deleted--"), hl_attr(HLF_E));
6750 else
6751 msg_puts_attr(AUGROUP_NAME(ap->group), hl_attr(HLF_T));
6752 msg_puts((char_u *)" ");
6753 }
6754 msg_puts_attr(event_nr2name(event), hl_attr(HLF_T));
6755 last_event = event;
6756 last_group = ap->group;
6757 msg_putchar('\n');
6758 if (got_int)
6759 return;
6760 }
6761 msg_col = 4;
6762 msg_outtrans(ap->pat);
6763
6764 for (ac = ap->cmds; ac != NULL; ac = ac->next)
6765 {
6766 if (ac->cmd != NULL) /* skip removed commands */
6767 {
6768 if (msg_col >= 14)
6769 msg_putchar('\n');
6770 msg_col = 14;
6771 if (got_int)
6772 return;
6773 msg_outtrans(ac->cmd);
6774 if (got_int)
6775 return;
6776 if (ac->next != NULL)
6777 {
6778 msg_putchar('\n');
6779 if (got_int)
6780 return;
6781 }
6782 }
6783 }
6784}
6785
6786/*
6787 * Mark an autocommand pattern for deletion.
6788 */
6789 static void
6790au_remove_pat(ap)
6791 AutoPat *ap;
6792{
6793 vim_free(ap->pat);
6794 ap->pat = NULL;
6795 au_need_clean = TRUE;
6796}
6797
6798/*
6799 * Mark all commands for a pattern for deletion.
6800 */
6801 static void
6802au_remove_cmds(ap)
6803 AutoPat *ap;
6804{
6805 AutoCmd *ac;
6806
6807 for (ac = ap->cmds; ac != NULL; ac = ac->next)
6808 {
6809 vim_free(ac->cmd);
6810 ac->cmd = NULL;
6811 }
6812 au_need_clean = TRUE;
6813}
6814
6815/*
6816 * Cleanup autocommands and patterns that have been deleted.
6817 * This is only done when not executing autocommands.
6818 */
6819 static void
6820au_cleanup()
6821{
6822 AutoPat *ap, **prev_ap;
6823 AutoCmd *ac, **prev_ac;
6824 EVENT_T event;
6825
6826 if (autocmd_busy || !au_need_clean)
6827 return;
6828
6829 /* loop over all events */
6830 for (event = (EVENT_T)0; (int)event < (int)NUM_EVENTS;
6831 event = (EVENT_T)((int)event + 1))
6832 {
6833 /* loop over all autocommand patterns */
6834 prev_ap = &(first_autopat[(int)event]);
6835 for (ap = *prev_ap; ap != NULL; ap = *prev_ap)
6836 {
6837 /* loop over all commands for this pattern */
6838 prev_ac = &(ap->cmds);
6839 for (ac = *prev_ac; ac != NULL; ac = *prev_ac)
6840 {
6841 /* remove the command if the pattern is to be deleted or when
6842 * the command has been marked for deletion */
6843 if (ap->pat == NULL || ac->cmd == NULL)
6844 {
6845 *prev_ac = ac->next;
6846 vim_free(ac->cmd);
6847 vim_free(ac);
6848 }
6849 else
6850 prev_ac = &(ac->next);
6851 }
6852
6853 /* remove the pattern if it has been marked for deletion */
6854 if (ap->pat == NULL)
6855 {
6856 *prev_ap = ap->next;
6857 vim_free(ap->reg_pat);
6858 vim_free(ap);
6859 }
6860 else
6861 prev_ap = &(ap->next);
6862 }
6863 }
6864
6865 au_need_clean = FALSE;
6866}
6867
6868/*
6869 * Add an autocmd group name.
6870 * Return it's ID. Returns AUGROUP_ERROR (< 0) for error.
6871 */
6872 static int
6873au_new_group(name)
6874 char_u *name;
6875{
6876 int i;
6877
6878 i = au_find_group(name);
6879 if (i == AUGROUP_ERROR) /* the group doesn't exist yet, add it */
6880 {
6881 /* First try using a free entry. */
6882 for (i = 0; i < augroups.ga_len; ++i)
6883 if (AUGROUP_NAME(i) == NULL)
6884 break;
6885 if (i == augroups.ga_len && ga_grow(&augroups, 1) == FAIL)
6886 return AUGROUP_ERROR;
6887
6888 AUGROUP_NAME(i) = vim_strsave(name);
6889 if (AUGROUP_NAME(i) == NULL)
6890 return AUGROUP_ERROR;
6891 if (i == augroups.ga_len)
6892 {
6893 ++augroups.ga_len;
6894 --augroups.ga_room;
6895 }
6896 }
6897
6898 return i;
6899}
6900
6901 static void
6902au_del_group(name)
6903 char_u *name;
6904{
6905 int i;
6906
6907 i = au_find_group(name);
6908 if (i == AUGROUP_ERROR) /* the group doesn't exist */
6909 EMSG2(_("E367: No such group: \"%s\""), name);
6910 else
6911 {
6912 vim_free(AUGROUP_NAME(i));
6913 AUGROUP_NAME(i) = NULL;
6914 }
6915}
6916
6917/*
6918 * Find the ID of an autocmd group name.
6919 * Return it's ID. Returns AUGROUP_ERROR (< 0) for error.
6920 */
6921 static int
6922au_find_group(name)
6923 char_u *name;
6924{
6925 int i;
6926
6927 for (i = 0; i < augroups.ga_len; ++i)
6928 if (AUGROUP_NAME(i) != NULL && STRCMP(AUGROUP_NAME(i), name) == 0)
6929 return i;
6930 return AUGROUP_ERROR;
6931}
6932
6933/*
6934 * ":augroup {name}".
6935 */
6936 void
6937do_augroup(arg, del_group)
6938 char_u *arg;
6939 int del_group;
6940{
6941 int i;
6942
6943 if (del_group)
6944 {
6945 if (*arg == NUL)
6946 EMSG(_(e_argreq));
6947 else
6948 au_del_group(arg);
6949 }
6950 else if (STRICMP(arg, "end") == 0) /* ":aug end": back to group 0 */
6951 current_augroup = AUGROUP_DEFAULT;
6952 else if (*arg) /* ":aug xxx": switch to group xxx */
6953 {
6954 i = au_new_group(arg);
6955 if (i != AUGROUP_ERROR)
6956 current_augroup = i;
6957 }
6958 else /* ":aug": list the group names */
6959 {
6960 msg_start();
6961 for (i = 0; i < augroups.ga_len; ++i)
6962 {
6963 if (AUGROUP_NAME(i) != NULL)
6964 {
6965 msg_puts(AUGROUP_NAME(i));
6966 msg_puts((char_u *)" ");
6967 }
6968 }
6969 msg_clr_eos();
6970 msg_end();
6971 }
6972}
6973
6974/*
6975 * Return the event number for event name "start".
6976 * Return NUM_EVENTS if the event name was not found.
6977 * Return a pointer to the next event name in "end".
6978 */
6979 static EVENT_T
6980event_name2nr(start, end)
6981 char_u *start;
6982 char_u **end;
6983{
6984 char_u *p;
6985 int i;
6986 int len;
6987
6988 /* the event name ends with end of line, a blank or a comma */
6989 for (p = start; *p && !vim_iswhite(*p) && *p != ','; ++p)
6990 ;
6991 for (i = 0; event_names[i].name != NULL; ++i)
6992 {
6993 len = (int)STRLEN(event_names[i].name);
6994 if (len == p - start && STRNICMP(event_names[i].name, start, len) == 0)
6995 break;
6996 }
6997 if (*p == ',')
6998 ++p;
6999 *end = p;
7000 if (event_names[i].name == NULL)
7001 return NUM_EVENTS;
7002 return event_names[i].event;
7003}
7004
7005/*
7006 * Return the name for event "event".
7007 */
7008 static char_u *
7009event_nr2name(event)
7010 EVENT_T event;
7011{
7012 int i;
7013
7014 for (i = 0; event_names[i].name != NULL; ++i)
7015 if (event_names[i].event == event)
7016 return (char_u *)event_names[i].name;
7017 return (char_u *)"Unknown";
7018}
7019
7020/*
7021 * Scan over the events. "*" stands for all events.
7022 */
7023 static char_u *
7024find_end_event(arg, have_group)
7025 char_u *arg;
7026 int have_group; /* TRUE when group name was found */
7027{
7028 char_u *pat;
7029 char_u *p;
7030
7031 if (*arg == '*')
7032 {
7033 if (arg[1] && !vim_iswhite(arg[1]))
7034 {
7035 EMSG2(_("E215: Illegal character after *: %s"), arg);
7036 return NULL;
7037 }
7038 pat = arg + 1;
7039 }
7040 else
7041 {
7042 for (pat = arg; *pat && !vim_iswhite(*pat); pat = p)
7043 {
7044 if ((int)event_name2nr(pat, &p) >= (int)NUM_EVENTS)
7045 {
7046 if (have_group)
7047 EMSG2(_("E216: No such event: %s"), pat);
7048 else
7049 EMSG2(_("E216: No such group or event: %s"), pat);
7050 return NULL;
7051 }
7052 }
7053 }
7054 return pat;
7055}
7056
7057/*
7058 * Return TRUE if "event" is included in 'eventignore'.
7059 */
7060 static int
7061event_ignored(event)
7062 EVENT_T event;
7063{
7064 char_u *p = p_ei;
7065
7066 if (STRICMP(p_ei, "all") == 0)
7067 return TRUE;
7068
7069 while (*p)
7070 if (event_name2nr(p, &p) == event)
7071 return TRUE;
7072
7073 return FALSE;
7074}
7075
7076/*
7077 * Return OK when the contents of p_ei is valid, FAIL otherwise.
7078 */
7079 int
7080check_ei()
7081{
7082 char_u *p = p_ei;
7083
7084 if (STRICMP(p_ei, "all") == 0)
7085 return OK;
7086
7087 while (*p)
7088 if (event_name2nr(p, &p) == NUM_EVENTS)
7089 return FAIL;
7090
7091 return OK;
7092}
7093
7094/*
7095 * do_autocmd() -- implements the :autocmd command. Can be used in the
7096 * following ways:
7097 *
7098 * :autocmd <event> <pat> <cmd> Add <cmd> to the list of commands that
7099 * will be automatically executed for <event>
7100 * when editing a file matching <pat>, in
7101 * the current group.
7102 * :autocmd <event> <pat> Show the auto-commands associated with
7103 * <event> and <pat>.
7104 * :autocmd <event> Show the auto-commands associated with
7105 * <event>.
7106 * :autocmd Show all auto-commands.
7107 * :autocmd! <event> <pat> <cmd> Remove all auto-commands associated with
7108 * <event> and <pat>, and add the command
7109 * <cmd>, for the current group.
7110 * :autocmd! <event> <pat> Remove all auto-commands associated with
7111 * <event> and <pat> for the current group.
7112 * :autocmd! <event> Remove all auto-commands associated with
7113 * <event> for the current group.
7114 * :autocmd! Remove ALL auto-commands for the current
7115 * group.
7116 *
7117 * Multiple events and patterns may be given separated by commas. Here are
7118 * some examples:
7119 * :autocmd bufread,bufenter *.c,*.h set tw=0 smartindent noic
7120 * :autocmd bufleave * set tw=79 nosmartindent ic infercase
7121 *
7122 * :autocmd * *.c show all autocommands for *.c files.
7123 */
7124 void
7125do_autocmd(arg, forceit)
7126 char_u *arg;
7127 int forceit;
7128{
7129 char_u *pat;
7130 char_u *envpat = NULL;
7131 char_u *cmd;
7132 EVENT_T event;
7133 int need_free = FALSE;
7134 int nested = FALSE;
7135 int group;
7136
7137 /*
7138 * Check for a legal group name. If not, use AUGROUP_ALL.
7139 */
7140 group = au_get_grouparg(&arg);
7141 if (arg == NULL) /* out of memory */
7142 return;
7143
7144 /*
7145 * Scan over the events.
7146 * If we find an illegal name, return here, don't do anything.
7147 */
7148 pat = find_end_event(arg, group != AUGROUP_ALL);
7149 if (pat == NULL)
7150 return;
7151
7152 /*
7153 * Scan over the pattern. Put a NUL at the end.
7154 */
7155 pat = skipwhite(pat);
7156 cmd = pat;
7157 while (*cmd && (!vim_iswhite(*cmd) || cmd[-1] == '\\'))
7158 cmd++;
7159 if (*cmd)
7160 *cmd++ = NUL;
7161
7162 /* Expand environment variables in the pattern. Set 'shellslash', we want
7163 * forward slashes here. */
7164 if (vim_strchr(pat, '$') != NULL || vim_strchr(pat, '~') != NULL)
7165 {
7166#ifdef BACKSLASH_IN_FILENAME
7167 int p_ssl_save = p_ssl;
7168
7169 p_ssl = TRUE;
7170#endif
7171 envpat = expand_env_save(pat);
7172#ifdef BACKSLASH_IN_FILENAME
7173 p_ssl = p_ssl_save;
7174#endif
7175 if (envpat != NULL)
7176 pat = envpat;
7177 }
7178
7179 /*
7180 * Check for "nested" flag.
7181 */
7182 cmd = skipwhite(cmd);
7183 if (*cmd != NUL && STRNCMP(cmd, "nested", 6) == 0 && vim_iswhite(cmd[6]))
7184 {
7185 nested = TRUE;
7186 cmd = skipwhite(cmd + 6);
7187 }
7188
7189 /*
7190 * Find the start of the commands.
7191 * Expand <sfile> in it.
7192 */
7193 if (*cmd != NUL)
7194 {
7195 cmd = expand_sfile(cmd);
7196 if (cmd == NULL) /* some error */
7197 return;
7198 need_free = TRUE;
7199 }
7200
7201 /*
7202 * Print header when showing autocommands.
7203 */
7204 if (!forceit && *cmd == NUL)
7205 {
7206 /* Highlight title */
7207 MSG_PUTS_TITLE(_("\n--- Auto-Commands ---"));
7208 }
7209
7210 /*
7211 * Loop over the events.
7212 */
7213 last_event = (EVENT_T)-1; /* for listing the event name */
7214 last_group = AUGROUP_ERROR; /* for listing the group name */
7215 if (*arg == '*' || *arg == NUL)
7216 {
7217 for (event = (EVENT_T)0; (int)event < (int)NUM_EVENTS;
7218 event = (EVENT_T)((int)event + 1))
7219 if (do_autocmd_event(event, pat,
7220 nested, cmd, forceit, group) == FAIL)
7221 break;
7222 }
7223 else
7224 {
7225 while (*arg && !vim_iswhite(*arg))
7226 if (do_autocmd_event(event_name2nr(arg, &arg), pat,
7227 nested, cmd, forceit, group) == FAIL)
7228 break;
7229 }
7230
7231 if (need_free)
7232 vim_free(cmd);
7233 vim_free(envpat);
7234}
7235
7236/*
7237 * Find the group ID in a ":autocmd" or ":doautocmd" argument.
7238 * The "argp" argument is advanced to the following argument.
7239 *
7240 * Returns the group ID, AUGROUP_ERROR for error (out of memory).
7241 */
7242 static int
7243au_get_grouparg(argp)
7244 char_u **argp;
7245{
7246 char_u *group_name;
7247 char_u *p;
7248 char_u *arg = *argp;
7249 int group = AUGROUP_ALL;
7250
7251 p = skiptowhite(arg);
7252 if (p > arg)
7253 {
7254 group_name = vim_strnsave(arg, (int)(p - arg));
7255 if (group_name == NULL) /* out of memory */
7256 return AUGROUP_ERROR;
7257 group = au_find_group(group_name);
7258 if (group == AUGROUP_ERROR)
7259 group = AUGROUP_ALL; /* no match, use all groups */
7260 else
7261 *argp = skipwhite(p); /* match, skip over group name */
7262 vim_free(group_name);
7263 }
7264 return group;
7265}
7266
7267/*
7268 * do_autocmd() for one event.
7269 * If *pat == NUL do for all patterns.
7270 * If *cmd == NUL show entries.
7271 * If forceit == TRUE delete entries.
7272 * If group is not AUGROUP_ALL, only use this group.
7273 */
7274 static int
7275do_autocmd_event(event, pat, nested, cmd, forceit, group)
7276 EVENT_T event;
7277 char_u *pat;
7278 int nested;
7279 char_u *cmd;
7280 int forceit;
7281 int group;
7282{
7283 AutoPat *ap;
7284 AutoPat **prev_ap;
7285 AutoCmd *ac;
7286 AutoCmd **prev_ac;
7287 int brace_level;
7288 char_u *endpat;
7289 int findgroup;
7290 int allgroups;
7291 int patlen;
7292
7293 if (group == AUGROUP_ALL)
7294 findgroup = current_augroup;
7295 else
7296 findgroup = group;
7297 allgroups = (group == AUGROUP_ALL && !forceit && *cmd == NUL);
7298
7299 /*
7300 * Show or delete all patterns for an event.
7301 */
7302 if (*pat == NUL)
7303 {
7304 for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next)
7305 {
7306 if (forceit) /* delete the AutoPat, if it's in the current group */
7307 {
7308 if (ap->group == findgroup)
7309 au_remove_pat(ap);
7310 }
7311 else if (group == AUGROUP_ALL || ap->group == group)
7312 show_autocmd(ap, event);
7313 }
7314 }
7315
7316 /*
7317 * Loop through all the specified patterns.
7318 */
7319 for ( ; *pat; pat = (*endpat == ',' ? endpat + 1 : endpat))
7320 {
7321 /*
7322 * Find end of the pattern.
7323 * Watch out for a comma in braces, like "*.\{obj,o\}".
7324 */
7325 brace_level = 0;
7326 for (endpat = pat; *endpat && (*endpat != ',' || brace_level
7327 || endpat[-1] == '\\'); ++endpat)
7328 {
7329 if (*endpat == '{')
7330 brace_level++;
7331 else if (*endpat == '}')
7332 brace_level--;
7333 }
7334 if (pat == endpat) /* ignore single comma */
7335 continue;
7336 patlen = (int)(endpat - pat);
7337
7338 /*
7339 * Find AutoPat entries with this pattern.
7340 */
7341 prev_ap = &first_autopat[(int)event];
7342 while ((ap = *prev_ap) != NULL)
7343 {
7344 if (ap->pat != NULL)
7345 {
7346 /* Accept a pattern when:
7347 * - a group was specified and it's that group, or a group was
7348 * not specified and it's the current group, or a group was
7349 * not specified and we are listing
7350 * - the length of the pattern matches
7351 * - the pattern matches
7352 */
7353 if ((allgroups || ap->group == findgroup)
7354 && ap->patlen == patlen
7355 && STRNCMP(pat, ap->pat, patlen) == 0)
7356 {
7357 /*
7358 * Remove existing autocommands.
7359 * If adding any new autocmd's for this AutoPat, don't
7360 * delete the pattern from the autopat list, append to
7361 * this list.
7362 */
7363 if (forceit)
7364 {
7365 if (*cmd != NUL && ap->next == NULL)
7366 {
7367 au_remove_cmds(ap);
7368 break;
7369 }
7370 au_remove_pat(ap);
7371 }
7372
7373 /*
7374 * Show autocmd's for this autopat
7375 */
7376 else if (*cmd == NUL)
7377 show_autocmd(ap, event);
7378
7379 /*
7380 * Add autocmd to this autopat, if it's the last one.
7381 */
7382 else if (ap->next == NULL)
7383 break;
7384 }
7385 }
7386 prev_ap = &ap->next;
7387 }
7388
7389 /*
7390 * Add a new command.
7391 */
7392 if (*cmd != NUL)
7393 {
7394 /*
7395 * If the pattern we want to add a command to does appear at the
7396 * end of the list (or not is not in the list at all), add the
7397 * pattern at the end of the list.
7398 */
7399 if (ap == NULL)
7400 {
7401 ap = (AutoPat *)alloc((unsigned)sizeof(AutoPat));
7402 if (ap == NULL)
7403 return FAIL;
7404 ap->pat = vim_strnsave(pat, patlen);
7405 ap->patlen = patlen;
7406 if (ap->pat == NULL)
7407 {
7408 vim_free(ap);
7409 return FAIL;
7410 }
7411 ap->reg_pat = file_pat_to_reg_pat(pat, endpat,
7412 &ap->allow_dirs, TRUE);
7413 if (ap->reg_pat == NULL)
7414 {
7415 vim_free(ap->pat);
7416 vim_free(ap);
7417 return FAIL;
7418 }
7419 ap->cmds = NULL;
7420 *prev_ap = ap;
7421 ap->next = NULL;
7422 if (group == AUGROUP_ALL)
7423 ap->group = current_augroup;
7424 else
7425 ap->group = group;
7426 }
7427
7428 /*
7429 * Add the autocmd at the end of the AutoCmd list.
7430 */
7431 prev_ac = &(ap->cmds);
7432 while ((ac = *prev_ac) != NULL)
7433 prev_ac = &ac->next;
7434 ac = (AutoCmd *)alloc((unsigned)sizeof(AutoCmd));
7435 if (ac == NULL)
7436 return FAIL;
7437 ac->cmd = vim_strsave(cmd);
7438#ifdef FEAT_EVAL
7439 ac->scriptID = current_SID;
7440#endif
7441 if (ac->cmd == NULL)
7442 {
7443 vim_free(ac);
7444 return FAIL;
7445 }
7446 ac->next = NULL;
7447 *prev_ac = ac;
7448 ac->nested = nested;
7449 }
7450 }
7451
7452 au_cleanup(); /* may really delete removed patterns/commands now */
7453 return OK;
7454}
7455
7456/*
7457 * Implementation of ":doautocmd [group] event [fname]".
7458 * Return OK for success, FAIL for failure;
7459 */
7460 int
7461do_doautocmd(arg, do_msg)
7462 char_u *arg;
7463 int do_msg; /* give message for no matching autocmds? */
7464{
7465 char_u *fname;
7466 int nothing_done = TRUE;
7467 int group;
7468
7469 /*
7470 * Check for a legal group name. If not, use AUGROUP_ALL.
7471 */
7472 group = au_get_grouparg(&arg);
7473 if (arg == NULL) /* out of memory */
7474 return FAIL;
7475
7476 if (*arg == '*')
7477 {
7478 EMSG(_("E217: Can't execute autocommands for ALL events"));
7479 return FAIL;
7480 }
7481
7482 /*
7483 * Scan over the events.
7484 * If we find an illegal name, return here, don't do anything.
7485 */
7486 fname = find_end_event(arg, group != AUGROUP_ALL);
7487 if (fname == NULL)
7488 return FAIL;
7489
7490 fname = skipwhite(fname);
7491
7492 /*
7493 * Loop over the events.
7494 */
7495 while (*arg && !vim_iswhite(*arg))
7496 if (apply_autocmds_group(event_name2nr(arg, &arg),
7497 fname, NULL, TRUE, group, curbuf, NULL))
7498 nothing_done = FALSE;
7499
7500 if (nothing_done && do_msg)
7501 MSG(_("No matching autocommands"));
7502
7503#ifdef FEAT_EVAL
7504 return aborting() ? FAIL : OK;
7505#else
7506 return OK;
7507#endif
7508}
7509
7510/*
7511 * ":doautoall": execute autocommands for each loaded buffer.
7512 */
7513 void
7514ex_doautoall(eap)
7515 exarg_T *eap;
7516{
7517 int retval;
7518 aco_save_T aco;
7519 buf_T *buf;
7520
7521 /*
7522 * This is a bit tricky: For some commands curwin->w_buffer needs to be
7523 * equal to curbuf, but for some buffers there may not be a window.
7524 * So we change the buffer for the current window for a moment. This
7525 * gives problems when the autocommands make changes to the list of
7526 * buffers or windows...
7527 */
7528 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
7529 {
7530 if (curbuf->b_ml.ml_mfp != NULL)
7531 {
7532 /* find a window for this buffer and save some values */
7533 aucmd_prepbuf(&aco, buf);
7534
7535 /* execute the autocommands for this buffer */
7536 retval = do_doautocmd(eap->arg, FALSE);
Bram Moolenaar15d0a8c2004-09-06 17:44:46 +00007537 do_modelines(FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007538
7539 /* restore the current window */
7540 aucmd_restbuf(&aco);
7541
7542 /* stop if there is some error or buffer was deleted */
7543 if (retval == FAIL || !buf_valid(buf))
7544 break;
7545 }
7546 }
7547
7548 check_cursor(); /* just in case lines got deleted */
7549}
7550
7551/*
7552 * Prepare for executing autocommands for (hidden) buffer "buf".
7553 * Search a window for the current buffer. Save the cursor position and
7554 * screen offset.
7555 * Set "curbuf" and "curwin" to match "buf".
7556 */
7557 void
7558aucmd_prepbuf(aco, buf)
7559 aco_save_T *aco; /* structure to save values in */
7560 buf_T *buf; /* new curbuf */
7561{
7562 win_T *win;
7563
7564 aco->new_curbuf = buf;
7565
7566 /* Find a window that is for the new buffer */
7567 if (buf == curbuf) /* be quick when buf is curbuf */
7568 win = curwin;
7569 else
7570#ifdef FEAT_WINDOWS
7571 for (win = firstwin; win != NULL; win = win->w_next)
7572 if (win->w_buffer == buf)
7573 break;
7574#else
7575 win = NULL;
7576#endif
7577
7578 /*
7579 * Prefer to use an existing window for the buffer, it has the least side
7580 * effects (esp. if "buf" is curbuf).
7581 * Otherwise, use curwin for "buf". It might make some items in the
7582 * window invalid. At least save the cursor and topline.
7583 */
7584 if (win != NULL)
7585 {
7586 /* there is a window for "buf", make it the curwin */
7587 aco->save_curwin = curwin;
7588 curwin = win;
7589 aco->save_buf = win->w_buffer;
7590 aco->new_curwin = win;
7591 }
7592 else
7593 {
7594 /* there is no window for "buf", use curwin */
7595 aco->save_curwin = NULL;
7596 aco->save_buf = curbuf;
7597 --curbuf->b_nwindows;
7598 curwin->w_buffer = buf;
7599 ++buf->b_nwindows;
7600
7601 /* save cursor and topline, set them to safe values */
7602 aco->save_cursor = curwin->w_cursor;
7603 curwin->w_cursor.lnum = 1;
7604 curwin->w_cursor.col = 0;
7605 aco->save_topline = curwin->w_topline;
7606 curwin->w_topline = 1;
7607#ifdef FEAT_DIFF
7608 aco->save_topfill = curwin->w_topfill;
7609 curwin->w_topfill = 0;
7610#endif
7611 }
7612
7613 curbuf = buf;
7614}
7615
7616/*
7617 * Cleanup after executing autocommands for a (hidden) buffer.
7618 * Restore the window as it was (if possible).
7619 */
7620 void
7621aucmd_restbuf(aco)
7622 aco_save_T *aco; /* structure holding saved values */
7623{
7624 if (aco->save_curwin != NULL)
7625 {
7626 /* restore curwin */
7627#ifdef FEAT_WINDOWS
7628 if (win_valid(aco->save_curwin))
7629#endif
7630 {
7631 /* restore the buffer which was previously edited by curwin, if
7632 * it's still the same window and it's valid */
7633 if (curwin == aco->new_curwin
7634 && buf_valid(aco->save_buf)
7635 && aco->save_buf->b_ml.ml_mfp != NULL)
7636 {
7637 --curbuf->b_nwindows;
7638 curbuf = aco->save_buf;
7639 curwin->w_buffer = curbuf;
7640 ++curbuf->b_nwindows;
7641 }
7642
7643 curwin = aco->save_curwin;
7644 curbuf = curwin->w_buffer;
7645 }
7646 }
7647 else
7648 {
7649 /* restore buffer for curwin if it still exists and is loaded */
7650 if (buf_valid(aco->save_buf) && aco->save_buf->b_ml.ml_mfp != NULL)
7651 {
7652 --curbuf->b_nwindows;
7653 curbuf = aco->save_buf;
7654 curwin->w_buffer = curbuf;
7655 ++curbuf->b_nwindows;
7656 curwin->w_cursor = aco->save_cursor;
7657 check_cursor();
7658 /* check topline < line_count, in case lines got deleted */
7659 if (aco->save_topline <= curbuf->b_ml.ml_line_count)
7660 {
7661 curwin->w_topline = aco->save_topline;
7662#ifdef FEAT_DIFF
7663 curwin->w_topfill = aco->save_topfill;
7664#endif
7665 }
7666 else
7667 {
7668 curwin->w_topline = curbuf->b_ml.ml_line_count;
7669#ifdef FEAT_DIFF
7670 curwin->w_topfill = 0;
7671#endif
7672 }
7673 }
7674 }
7675}
7676
7677static int autocmd_nested = FALSE;
7678
7679/*
7680 * Execute autocommands for "event" and file name "fname".
7681 * Return TRUE if some commands were executed.
7682 */
7683 int
7684apply_autocmds(event, fname, fname_io, force, buf)
7685 EVENT_T event;
7686 char_u *fname; /* NULL or empty means use actual file name */
7687 char_u *fname_io; /* fname to use for <afile> on cmdline */
7688 int force; /* when TRUE, ignore autocmd_busy */
7689 buf_T *buf; /* buffer for <abuf> */
7690{
7691 return apply_autocmds_group(event, fname, fname_io, force,
7692 AUGROUP_ALL, buf, NULL);
7693}
7694
7695/*
7696 * Like apply_autocmds(), but with extra "eap" argument. This takes care of
7697 * setting v:filearg.
7698 */
7699 static int
7700apply_autocmds_exarg(event, fname, fname_io, force, buf, eap)
7701 EVENT_T event;
7702 char_u *fname;
7703 char_u *fname_io;
7704 int force;
7705 buf_T *buf;
7706 exarg_T *eap;
7707{
7708 return apply_autocmds_group(event, fname, fname_io, force,
7709 AUGROUP_ALL, buf, eap);
7710}
7711
7712/*
7713 * Like apply_autocmds(), but handles the caller's retval. If the script
7714 * processing is being aborted or if retval is FAIL when inside a try
7715 * conditional, no autocommands are executed. If otherwise the autocommands
7716 * cause the script to be aborted, retval is set to FAIL.
7717 */
7718 int
7719apply_autocmds_retval(event, fname, fname_io, force, buf, retval)
7720 EVENT_T event;
7721 char_u *fname; /* NULL or empty means use actual file name */
7722 char_u *fname_io; /* fname to use for <afile> on cmdline */
7723 int force; /* when TRUE, ignore autocmd_busy */
7724 buf_T *buf; /* buffer for <abuf> */
7725 int *retval; /* pointer to caller's retval */
7726{
7727 int did_cmd;
7728
7729 if (should_abort(*retval))
7730 return FALSE;
7731
7732 did_cmd = apply_autocmds_group(event, fname, fname_io, force,
7733 AUGROUP_ALL, buf, NULL);
7734 if (did_cmd && aborting())
7735 *retval = FAIL;
7736 return did_cmd;
7737}
7738
7739#if defined(FEAT_AUTOCMD) || defined(PROTO)
7740 int
7741has_cursorhold()
7742{
7743 return (first_autopat[(int)EVENT_CURSORHOLD] != NULL);
7744}
7745#endif
7746
7747 static int
7748apply_autocmds_group(event, fname, fname_io, force, group, buf, eap)
7749 EVENT_T event;
7750 char_u *fname; /* NULL or empty means use actual file name */
7751 char_u *fname_io; /* fname to use for <afile> on cmdline, NULL means
7752 use fname */
7753 int force; /* when TRUE, ignore autocmd_busy */
7754 int group; /* group ID, or AUGROUP_ALL */
7755 buf_T *buf; /* buffer for <abuf> */
7756 exarg_T *eap; /* command arguments */
7757{
7758 char_u *sfname = NULL; /* short file name */
7759 char_u *tail;
7760 int save_changed;
7761 buf_T *old_curbuf;
7762 int retval = FALSE;
7763 char_u *save_sourcing_name;
7764 linenr_T save_sourcing_lnum;
7765 char_u *save_autocmd_fname;
7766 int save_autocmd_bufnr;
7767 char_u *save_autocmd_match;
7768 int save_autocmd_busy;
7769 int save_autocmd_nested;
7770 static int nesting = 0;
7771 AutoPatCmd patcmd;
7772 AutoPat *ap;
7773#ifdef FEAT_EVAL
7774 scid_T save_current_SID;
7775 void *save_funccalp;
7776 char_u *save_cmdarg;
7777 long save_cmdbang;
7778#endif
7779 static int filechangeshell_busy = FALSE;
7780
7781 /*
7782 * Quickly return if there are no autocommands for this event or
7783 * autocommands are blocked.
7784 */
7785 if (first_autopat[(int)event] == NULL || autocmd_block > 0)
7786 return retval;
7787
7788 /*
7789 * When autocommands are busy, new autocommands are only executed when
7790 * explicitly enabled with the "nested" flag.
7791 */
7792 if (autocmd_busy && !(force || autocmd_nested))
7793 return retval;
7794
7795#ifdef FEAT_EVAL
7796 /*
7797 * Quickly return when immdediately aborting on error, or when an interrupt
7798 * occurred or an exception was thrown but not caught.
7799 */
7800 if (aborting())
7801 return retval;
7802#endif
7803
7804 /*
7805 * FileChangedShell never nests, because it can create an endless loop.
7806 */
7807 if (filechangeshell_busy && event == EVENT_FILECHANGEDSHELL)
7808 return retval;
7809
7810 /*
7811 * Ignore events in 'eventignore'.
7812 */
7813 if (event_ignored(event))
7814 return retval;
7815
7816 /*
7817 * Allow nesting of autocommands, but restrict the depth, because it's
7818 * possible to create an endless loop.
7819 */
7820 if (nesting == 10)
7821 {
7822 EMSG(_("E218: autocommand nesting too deep"));
7823 return retval;
7824 }
7825
7826 /*
7827 * Check if these autocommands are disabled. Used when doing ":all" or
7828 * ":ball".
7829 */
7830 if ( (autocmd_no_enter
7831 && (event == EVENT_WINENTER || event == EVENT_BUFENTER))
7832 || (autocmd_no_leave
7833 && (event == EVENT_WINLEAVE || event == EVENT_BUFLEAVE)))
7834 return retval;
7835
7836 /*
7837 * Save the autocmd_* variables and info about the current buffer.
7838 */
7839 save_autocmd_fname = autocmd_fname;
7840 save_autocmd_bufnr = autocmd_bufnr;
7841 save_autocmd_match = autocmd_match;
7842 save_autocmd_busy = autocmd_busy;
7843 save_autocmd_nested = autocmd_nested;
7844 save_changed = curbuf->b_changed;
7845 old_curbuf = curbuf;
7846
7847 /*
7848 * Set the file name to be used for <afile>.
7849 */
7850 if (fname_io == NULL)
7851 {
7852 if (fname != NULL && *fname != NUL)
7853 autocmd_fname = fname;
7854 else if (buf != NULL)
7855 autocmd_fname = buf->b_fname;
7856 else
7857 autocmd_fname = NULL;
7858 }
7859 else
7860 autocmd_fname = fname_io;
7861
7862 /*
7863 * Set the buffer number to be used for <abuf>.
7864 */
7865 if (buf == NULL)
7866 autocmd_bufnr = 0;
7867 else
7868 autocmd_bufnr = buf->b_fnum;
7869
7870 /*
7871 * When the file name is NULL or empty, use the file name of buffer "buf".
7872 * Always use the full path of the file name to match with, in case
7873 * "allow_dirs" is set.
7874 */
7875 if (fname == NULL || *fname == NUL)
7876 {
7877 if (buf == NULL)
7878 fname = NULL;
7879 else
7880 {
7881#ifdef FEAT_SYN_HL
7882 if (event == EVENT_SYNTAX)
7883 fname = buf->b_p_syn;
7884 else
7885#endif
7886 if (event == EVENT_FILETYPE)
7887 fname = buf->b_p_ft;
7888 else
7889 {
7890 if (buf->b_sfname != NULL)
7891 sfname = vim_strsave(buf->b_sfname);
7892 fname = buf->b_ffname;
7893 }
7894 }
7895 if (fname == NULL)
7896 fname = (char_u *)"";
7897 fname = vim_strsave(fname); /* make a copy, so we can change it */
7898 }
7899 else
7900 {
7901 sfname = vim_strsave(fname);
7902 /* Don't try expanding FileType, Syntax or WindowID. */
7903 if (event == EVENT_FILETYPE || event == EVENT_SYNTAX
7904 || event == EVENT_REMOTEREPLY)
7905 fname = vim_strsave(fname);
7906 else
7907 fname = FullName_save(fname, FALSE);
7908 }
7909 if (fname == NULL) /* out of memory */
7910 {
7911 vim_free(sfname);
7912 return FALSE;
7913 }
7914
7915#ifdef BACKSLASH_IN_FILENAME
7916 /*
7917 * Replace all backslashes with forward slashes. This makes the
7918 * autocommand patterns portable between Unix and MS-DOS.
7919 */
7920 if (sfname != NULL)
7921 forward_slash(sfname);
7922 forward_slash(fname);
7923#endif
7924
7925#ifdef VMS
7926 /* remove version for correct match */
7927 if (sfname != NULL)
7928 vms_remove_version(sfname);
7929 vms_remove_version(fname);
7930#endif
7931
7932 /*
7933 * Set the name to be used for <amatch>.
7934 */
7935 autocmd_match = fname;
7936
7937
7938 /* Don't redraw while doing auto commands. */
7939 ++RedrawingDisabled;
7940 save_sourcing_name = sourcing_name;
7941 sourcing_name = NULL; /* don't free this one */
7942 save_sourcing_lnum = sourcing_lnum;
7943 sourcing_lnum = 0; /* no line number here */
7944
7945#ifdef FEAT_EVAL
7946 save_current_SID = current_SID;
7947
7948 /* Don't use local function variables, if called from a function */
7949 save_funccalp = save_funccal();
7950#endif
7951
7952 /*
7953 * When starting to execute autocommands, save the search patterns.
7954 */
7955 if (!autocmd_busy)
7956 {
7957 save_search_patterns();
7958 saveRedobuff();
7959 did_filetype = keep_filetype;
7960 }
7961
7962 /*
7963 * Note that we are applying autocmds. Some commands need to know.
7964 */
7965 autocmd_busy = TRUE;
7966 filechangeshell_busy = (event == EVENT_FILECHANGEDSHELL);
7967 ++nesting; /* see matching decrement below */
7968
7969 /* Remember that FileType was triggered. Used for did_filetype(). */
7970 if (event == EVENT_FILETYPE)
7971 did_filetype = TRUE;
7972
7973 tail = gettail(fname);
7974
7975 /* Find first autocommand that matches */
7976 patcmd.curpat = first_autopat[(int)event];
7977 patcmd.nextcmd = NULL;
7978 patcmd.group = group;
7979 patcmd.fname = fname;
7980 patcmd.sfname = sfname;
7981 patcmd.tail = tail;
7982 patcmd.event = event;
7983 auto_next_pat(&patcmd, FALSE);
7984
7985 /* found one, start executing the autocommands */
7986 if (patcmd.curpat != NULL)
7987 {
7988#ifdef FEAT_EVAL
7989 /* set v:cmdarg (only when there is a matching pattern) */
7990 save_cmdbang = get_vim_var_nr(VV_CMDBANG);
7991 if (eap != NULL)
7992 {
7993 save_cmdarg = set_cmdarg(eap, NULL);
7994 set_vim_var_nr(VV_CMDBANG, (long)eap->forceit);
7995 }
7996 else
7997 save_cmdarg = NULL; /* avoid gcc warning */
7998#endif
7999 retval = TRUE;
8000 /* mark the last pattern, to avoid an endless loop when more patterns
8001 * are added when executing autocommands */
8002 for (ap = patcmd.curpat; ap->next != NULL; ap = ap->next)
8003 ap->last = FALSE;
8004 ap->last = TRUE;
8005 check_lnums(TRUE); /* make sure cursor and topline are valid */
8006 do_cmdline(NULL, getnextac, (void *)&patcmd,
8007 DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT);
8008#ifdef FEAT_EVAL
8009 if (eap != NULL)
8010 {
8011 (void)set_cmdarg(NULL, save_cmdarg);
8012 set_vim_var_nr(VV_CMDBANG, save_cmdbang);
8013 }
8014#endif
8015 }
8016
8017 --RedrawingDisabled;
8018 autocmd_busy = save_autocmd_busy;
8019 filechangeshell_busy = FALSE;
8020 autocmd_nested = save_autocmd_nested;
8021 vim_free(sourcing_name);
8022 sourcing_name = save_sourcing_name;
8023 sourcing_lnum = save_sourcing_lnum;
8024 autocmd_fname = save_autocmd_fname;
8025 autocmd_bufnr = save_autocmd_bufnr;
8026 autocmd_match = save_autocmd_match;
8027#ifdef FEAT_EVAL
8028 current_SID = save_current_SID;
8029 restore_funccal(save_funccalp);
8030#endif
8031 vim_free(fname);
8032 vim_free(sfname);
8033 --nesting; /* see matching increment above */
8034
8035 /*
8036 * When stopping to execute autocommands, restore the search patterns and
8037 * the redo buffer.
8038 */
8039 if (!autocmd_busy)
8040 {
8041 restore_search_patterns();
8042 restoreRedobuff();
8043 did_filetype = FALSE;
8044 }
8045
8046 /*
8047 * Some events don't set or reset the Changed flag.
8048 * Check if still in the same buffer!
8049 */
8050 if (curbuf == old_curbuf
8051 && (event == EVENT_BUFREADPOST
8052 || event == EVENT_BUFWRITEPOST
8053 || event == EVENT_FILEAPPENDPOST
8054 || event == EVENT_VIMLEAVE
8055 || event == EVENT_VIMLEAVEPRE))
8056 {
8057#ifdef FEAT_TITLE
8058 if (curbuf->b_changed != save_changed)
8059 need_maketitle = TRUE;
8060#endif
8061 curbuf->b_changed = save_changed;
8062 }
8063
8064 au_cleanup(); /* may really delete removed patterns/commands now */
8065 return retval;
8066}
8067
8068/*
8069 * Find next autocommand pattern that matches.
8070 */
8071 static void
8072auto_next_pat(apc, stop_at_last)
8073 AutoPatCmd *apc;
8074 int stop_at_last; /* stop when 'last' flag is set */
8075{
8076 AutoPat *ap;
8077 AutoCmd *cp;
8078 char_u *name;
8079 char *s;
8080
8081 vim_free(sourcing_name);
8082 sourcing_name = NULL;
8083
8084 for (ap = apc->curpat; ap != NULL && !got_int; ap = ap->next)
8085 {
8086 apc->curpat = NULL;
8087
8088 /* only use a pattern when it has not been removed, has commands and
8089 * the group matches */
8090 if (ap->pat != NULL && ap->cmds != NULL
8091 && (apc->group == AUGROUP_ALL || apc->group == ap->group))
8092 {
8093 if (match_file_pat(ap->reg_pat, apc->fname, apc->sfname, apc->tail,
8094 ap->allow_dirs))
8095 {
8096 name = event_nr2name(apc->event);
8097 s = _("%s Auto commands for \"%s\"");
8098 sourcing_name = alloc((unsigned)(STRLEN(s)
8099 + STRLEN(name) + ap->patlen + 1));
8100 if (sourcing_name != NULL)
8101 {
8102 sprintf((char *)sourcing_name, s,
8103 (char *)name, (char *)ap->pat);
8104 if (p_verbose >= 8)
8105 msg_str((char_u *)_("Executing %s"), sourcing_name);
8106 }
8107
8108 apc->curpat = ap;
8109 apc->nextcmd = ap->cmds;
8110 /* mark last command */
8111 for (cp = ap->cmds; cp->next != NULL; cp = cp->next)
8112 cp->last = FALSE;
8113 cp->last = TRUE;
8114 }
8115 line_breakcheck();
8116 if (apc->curpat != NULL) /* found a match */
8117 break;
8118 }
8119 if (stop_at_last && ap->last)
8120 break;
8121 }
8122}
8123
8124/*
8125 * Get next autocommand command.
8126 * Called by do_cmdline() to get the next line for ":if".
8127 * Returns allocated string, or NULL for end of autocommands.
8128 */
8129/* ARGSUSED */
8130 static char_u *
8131getnextac(c, cookie, indent)
8132 int c; /* not used */
8133 void *cookie;
8134 int indent; /* not used */
8135{
8136 AutoPatCmd *acp = (AutoPatCmd *)cookie;
8137 char_u *retval;
8138 AutoCmd *ac;
8139
8140 /* Can be called again after returning the last line. */
8141 if (acp->curpat == NULL)
8142 return NULL;
8143
8144 /* repeat until we find an autocommand to execute */
8145 for (;;)
8146 {
8147 /* skip removed commands */
8148 while (acp->nextcmd != NULL && acp->nextcmd->cmd == NULL)
8149 if (acp->nextcmd->last)
8150 acp->nextcmd = NULL;
8151 else
8152 acp->nextcmd = acp->nextcmd->next;
8153
8154 if (acp->nextcmd != NULL)
8155 break;
8156
8157 /* at end of commands, find next pattern that matches */
8158 if (acp->curpat->last)
8159 acp->curpat = NULL;
8160 else
8161 acp->curpat = acp->curpat->next;
8162 if (acp->curpat != NULL)
8163 auto_next_pat(acp, TRUE);
8164 if (acp->curpat == NULL)
8165 return NULL;
8166 }
8167
8168 ac = acp->nextcmd;
8169
8170 if (p_verbose >= 9)
8171 {
8172 msg_scroll = TRUE; /* always scroll up, don't overwrite */
8173 msg_str((char_u *)_("autocommand %s"), ac->cmd);
8174 msg_puts((char_u *)"\n"); /* don't overwrite this either */
8175 cmdline_row = msg_row;
8176 }
8177 retval = vim_strsave(ac->cmd);
8178 autocmd_nested = ac->nested;
8179#ifdef FEAT_EVAL
8180 current_SID = ac->scriptID;
8181#endif
8182 if (ac->last)
8183 acp->nextcmd = NULL;
8184 else
8185 acp->nextcmd = ac->next;
8186 return retval;
8187}
8188
8189/*
8190 * Return TRUE if there is a matching autocommand for "fname".
8191 */
8192 int
8193has_autocmd(event, sfname)
8194 EVENT_T event;
8195 char_u *sfname;
8196{
8197 AutoPat *ap;
8198 char_u *fname;
8199 char_u *tail = gettail(sfname);
8200 int retval = FALSE;
8201
8202 fname = FullName_save(sfname, FALSE);
8203 if (fname == NULL)
8204 return FALSE;
8205
8206#ifdef BACKSLASH_IN_FILENAME
8207 /*
8208 * Replace all backslashes with forward slashes. This makes the
8209 * autocommand patterns portable between Unix and MS-DOS.
8210 */
8211 sfname = vim_strsave(sfname);
8212 if (sfname != NULL)
8213 forward_slash(sfname);
8214 forward_slash(fname);
8215#endif
8216
8217 for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next)
8218 if (ap->pat != NULL && ap->cmds != NULL
8219 && match_file_pat(ap->reg_pat, fname, sfname, tail,
8220 ap->allow_dirs))
8221 {
8222 retval = TRUE;
8223 break;
8224 }
8225
8226 vim_free(fname);
8227#ifdef BACKSLASH_IN_FILENAME
8228 vim_free(sfname);
8229#endif
8230
8231 return retval;
8232}
8233
8234#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
8235/*
8236 * Function given to ExpandGeneric() to obtain the list of autocommand group
8237 * names.
8238 */
8239/*ARGSUSED*/
8240 char_u *
8241get_augroup_name(xp, idx)
8242 expand_T *xp;
8243 int idx;
8244{
8245 if (idx == augroups.ga_len) /* add "END" add the end */
8246 return (char_u *)"END";
8247 if (idx >= augroups.ga_len) /* end of list */
8248 return NULL;
8249 if (AUGROUP_NAME(idx) == NULL) /* skip deleted entries */
8250 return (char_u *)"";
8251 return AUGROUP_NAME(idx); /* return a name */
8252}
8253
8254static int include_groups = FALSE;
8255
8256 char_u *
8257set_context_in_autocmd(xp, arg, doautocmd)
8258 expand_T *xp;
8259 char_u *arg;
8260 int doautocmd; /* TRUE for :doautocmd, FALSE for :autocmd */
8261{
8262 char_u *p;
8263 int group;
8264
8265 /* check for a group name, skip it if present */
8266 include_groups = FALSE;
8267 p = arg;
8268 group = au_get_grouparg(&arg);
8269 if (group == AUGROUP_ERROR)
8270 return NULL;
8271 /* If there only is a group name that's what we expand. */
8272 if (*arg == NUL && group != AUGROUP_ALL && !vim_iswhite(arg[-1]))
8273 {
8274 arg = p;
8275 group = AUGROUP_ALL;
8276 }
8277
8278 /* skip over event name */
8279 for (p = arg; *p != NUL && !vim_iswhite(*p); ++p)
8280 if (*p == ',')
8281 arg = p + 1;
8282 if (*p == NUL)
8283 {
8284 if (group == AUGROUP_ALL)
8285 include_groups = TRUE;
8286 xp->xp_context = EXPAND_EVENTS; /* expand event name */
8287 xp->xp_pattern = arg;
8288 return NULL;
8289 }
8290
8291 /* skip over pattern */
8292 arg = skipwhite(p);
8293 while (*arg && (!vim_iswhite(*arg) || arg[-1] == '\\'))
8294 arg++;
8295 if (*arg)
8296 return arg; /* expand (next) command */
8297
8298 if (doautocmd)
8299 xp->xp_context = EXPAND_FILES; /* expand file names */
8300 else
8301 xp->xp_context = EXPAND_NOTHING; /* pattern is not expanded */
8302 return NULL;
8303}
8304
8305/*
8306 * Function given to ExpandGeneric() to obtain the list of event names.
8307 */
8308/*ARGSUSED*/
8309 char_u *
8310get_event_name(xp, idx)
8311 expand_T *xp;
8312 int idx;
8313{
8314 if (idx < augroups.ga_len) /* First list group names, if wanted */
8315 {
8316 if (!include_groups || AUGROUP_NAME(idx) == NULL)
8317 return (char_u *)""; /* skip deleted entries */
8318 return AUGROUP_NAME(idx); /* return a name */
8319 }
8320 return (char_u *)event_names[idx - augroups.ga_len].name;
8321}
8322
8323#endif /* FEAT_CMDL_COMPL */
8324
8325/*
8326 * Return TRUE if an autocommand is defined for "event" and "pattern".
8327 * "pattern" can be NULL to accept any pattern.
8328 */
8329 int
8330au_exists(name, name_end, pattern)
8331 char_u *name;
8332 char_u *name_end;
8333 char_u *pattern;
8334{
8335 char_u *event_name;
8336 char_u *p;
8337 EVENT_T event;
8338 AutoPat *ap;
8339
8340 /* find the index (enum) for the event name */
8341 event_name = vim_strnsave(name, (int)(name_end - name));
8342 if (event_name == NULL)
8343 return FALSE;
8344 event = event_name2nr(event_name, &p);
8345 vim_free(event_name);
8346
8347 /* return FALSE if the event name is not recognized */
8348 if (event == NUM_EVENTS) /* unknown event name */
8349 return FALSE;
8350
8351 /* Find the first autocommand for this event.
8352 * If there isn't any, return FALSE;
8353 * If there is one and no pattern given, return TRUE; */
8354 ap = first_autopat[(int)event];
8355 if (ap == NULL)
8356 return FALSE;
8357 if (pattern == NULL)
8358 return TRUE;
8359
8360 /* Check if there is an autocommand with the given pattern. */
8361 for ( ; ap != NULL; ap = ap->next)
8362 /* only use a pattern when it has not been removed and has commands */
8363 if (ap->pat != NULL && ap->cmds != NULL
8364 && fnamecmp(ap->pat, pattern) == 0)
8365 return TRUE;
8366
8367 return FALSE;
8368}
8369#endif /* FEAT_AUTOCMD */
8370
8371#if defined(FEAT_AUTOCMD) || defined(FEAT_WILDIGN) || defined(PROTO)
8372/*
8373 * Try matching a filename with a pattern.
8374 * Used for autocommands and 'wildignore'.
8375 * Returns TRUE if there is a match, FALSE otherwise.
8376 */
8377 int
8378match_file_pat(pattern, fname, sfname, tail, allow_dirs)
8379 char_u *pattern; /* pattern to match with */
8380 char_u *fname; /* full path of file name */
8381 char_u *sfname; /* short file name or NULL */
8382 char_u *tail; /* tail of path */
8383 int allow_dirs; /* allow matching with dir */
8384{
8385 regmatch_T regmatch;
8386 int result = FALSE;
8387#ifdef FEAT_OSFILETYPE
8388 int no_pattern = FALSE; /* TRUE if check is filetype only */
8389 char_u *type_start;
8390 char_u c;
8391 int match = FALSE;
8392#endif
8393
8394#ifdef CASE_INSENSITIVE_FILENAME
8395 regmatch.rm_ic = TRUE; /* Always ignore case */
8396#else
8397 regmatch.rm_ic = FALSE; /* Don't ever ignore case */
8398#endif
8399#ifdef FEAT_OSFILETYPE
8400 if (*pattern == '<')
8401 {
8402 /* There is a filetype condition specified with this pattern.
8403 * Check the filetype matches first. If not, don't bother with the
8404 * pattern (set regprog to NULL).
8405 * Always use magic for the regexp.
8406 */
8407
8408 for (type_start = pattern + 1; (c = *pattern); pattern++)
8409 {
8410 if ((c == ';' || c == '>') && match == FALSE)
8411 {
8412 *pattern = NUL; /* Terminate the string */
8413 match = mch_check_filetype(fname, type_start);
8414 *pattern = c; /* Restore the terminator */
8415 type_start = pattern + 1;
8416 }
8417 if (c == '>')
8418 break;
8419 }
8420
8421 /* (c should never be NUL, but check anyway) */
8422 if (match == FALSE || c == NUL)
8423 regmatch.regprog = NULL; /* Doesn't match - don't check pat. */
8424 else if (*pattern == NUL)
8425 {
8426 regmatch.regprog = NULL; /* Vim will try to free regprog later */
8427 no_pattern = TRUE; /* Always matches - don't check pat. */
8428 }
8429 else
8430 regmatch.regprog = vim_regcomp(pattern + 1, RE_MAGIC);
8431 }
8432 else
8433#endif
8434 regmatch.regprog = vim_regcomp(pattern, RE_MAGIC);
8435
8436 /*
8437 * Try for a match with the pattern with:
8438 * 1. the full file name, when the pattern has a '/'.
8439 * 2. the short file name, when the pattern has a '/'.
8440 * 3. the tail of the file name, when the pattern has no '/'.
8441 */
8442 if (
8443#ifdef FEAT_OSFILETYPE
8444 /* If the check is for a filetype only and we don't care
8445 * about the path then skip all the regexp stuff.
8446 */
8447 no_pattern ||
8448#endif
8449 (regmatch.regprog != NULL
8450 && ((allow_dirs
8451 && (vim_regexec(&regmatch, fname, (colnr_T)0)
8452 || (sfname != NULL
8453 && vim_regexec(&regmatch, sfname, (colnr_T)0))))
8454 || (!allow_dirs && vim_regexec(&regmatch, tail, (colnr_T)0)))))
8455 result = TRUE;
8456
8457 vim_free(regmatch.regprog);
8458 return result;
8459}
8460#endif
8461
8462#if defined(FEAT_WILDIGN) || defined(PROTO)
8463/*
8464 * Return TRUE if a file matches with a pattern in "list".
8465 * "list" is a comma-separated list of patterns, like 'wildignore'.
8466 * "sfname" is the short file name or NULL, "ffname" the long file name.
8467 */
8468 int
8469match_file_list(list, sfname, ffname)
8470 char_u *list;
8471 char_u *sfname;
8472 char_u *ffname;
8473{
8474 char_u buf[100];
8475 char_u *tail;
8476 char_u *regpat;
8477 char allow_dirs;
8478 int match;
8479 char_u *p;
8480
8481 tail = gettail(sfname);
8482
8483 /* try all patterns in 'wildignore' */
8484 p = list;
8485 while (*p)
8486 {
8487 copy_option_part(&p, buf, 100, ",");
8488 regpat = file_pat_to_reg_pat(buf, NULL, &allow_dirs, FALSE);
8489 if (regpat == NULL)
8490 break;
8491 match = match_file_pat(regpat, ffname, sfname, tail, (int)allow_dirs);
8492 vim_free(regpat);
8493 if (match)
8494 return TRUE;
8495 }
8496 return FALSE;
8497}
8498#endif
8499
8500/*
8501 * Convert the given pattern "pat" which has shell style wildcards in it, into
8502 * a regular expression, and return the result in allocated memory. If there
8503 * is a directory path separator to be matched, then TRUE is put in
8504 * allow_dirs, otherwise FALSE is put there -- webb.
8505 * Handle backslashes before special characters, like "\*" and "\ ".
8506 *
8507 * If FEAT_OSFILETYPE defined then pass initial <type> through unchanged. Eg:
8508 * '<html>myfile' becomes '<html>^myfile$' -- leonard.
8509 *
8510 * Returns NULL when out of memory.
8511 */
8512/*ARGSUSED*/
8513 char_u *
8514file_pat_to_reg_pat(pat, pat_end, allow_dirs, no_bslash)
8515 char_u *pat;
8516 char_u *pat_end; /* first char after pattern or NULL */
8517 char *allow_dirs; /* Result passed back out in here */
8518 int no_bslash; /* Don't use a backward slash as pathsep */
8519{
8520 int size;
8521 char_u *endp;
8522 char_u *reg_pat;
8523 char_u *p;
8524 int i;
8525 int nested = 0;
8526 int add_dollar = TRUE;
8527#ifdef FEAT_OSFILETYPE
8528 int check_length = 0;
8529#endif
8530
8531 if (allow_dirs != NULL)
8532 *allow_dirs = FALSE;
8533 if (pat_end == NULL)
8534 pat_end = pat + STRLEN(pat);
8535
8536#ifdef FEAT_OSFILETYPE
8537 /* Find out how much of the string is the filetype check */
8538 if (*pat == '<')
8539 {
8540 /* Count chars until the next '>' */
8541 for (p = pat + 1; p < pat_end && *p != '>'; p++)
8542 ;
8543 if (p < pat_end)
8544 {
8545 /* Pattern is of the form <.*>.* */
8546 check_length = p - pat + 1;
8547 if (p + 1 >= pat_end)
8548 {
8549 /* The 'pattern' is a filetype check ONLY */
8550 reg_pat = (char_u *)alloc(check_length + 1);
8551 if (reg_pat != NULL)
8552 {
8553 mch_memmove(reg_pat, pat, (size_t)check_length);
8554 reg_pat[check_length] = NUL;
8555 }
8556 return reg_pat;
8557 }
8558 }
8559 /* else: there was no closing '>' - assume it was a normal pattern */
8560
8561 }
8562 pat += check_length;
8563 size = 2 + check_length;
8564#else
8565 size = 2; /* '^' at start, '$' at end */
8566#endif
8567
8568 for (p = pat; p < pat_end; p++)
8569 {
8570 switch (*p)
8571 {
8572 case '*':
8573 case '.':
8574 case ',':
8575 case '{':
8576 case '}':
8577 case '~':
8578 size += 2; /* extra backslash */
8579 break;
8580#ifdef BACKSLASH_IN_FILENAME
8581 case '\\':
8582 case '/':
8583 size += 4; /* could become "[\/]" */
8584 break;
8585#endif
8586 default:
8587 size++;
8588# ifdef FEAT_MBYTE
8589 if (enc_dbcs != 0 && (*mb_ptr2len_check)(p) > 1)
8590 {
8591 ++p;
8592 ++size;
8593 }
8594# endif
8595 break;
8596 }
8597 }
8598 reg_pat = alloc(size + 1);
8599 if (reg_pat == NULL)
8600 return NULL;
8601
8602#ifdef FEAT_OSFILETYPE
8603 /* Copy the type check in to the start. */
8604 if (check_length)
8605 mch_memmove(reg_pat, pat - check_length, (size_t)check_length);
8606 i = check_length;
8607#else
8608 i = 0;
8609#endif
8610
8611 if (pat[0] == '*')
8612 while (pat[0] == '*' && pat < pat_end - 1)
8613 pat++;
8614 else
8615 reg_pat[i++] = '^';
8616 endp = pat_end - 1;
8617 if (*endp == '*')
8618 {
8619 while (endp - pat > 0 && *endp == '*')
8620 endp--;
8621 add_dollar = FALSE;
8622 }
8623 for (p = pat; *p && nested >= 0 && p <= endp; p++)
8624 {
8625 switch (*p)
8626 {
8627 case '*':
8628 reg_pat[i++] = '.';
8629 reg_pat[i++] = '*';
8630 break;
8631 case '.':
8632#ifdef RISCOS
8633 if (allow_dirs != NULL)
8634 *allow_dirs = TRUE;
8635 /* FALLTHROUGH */
8636#endif
8637 case '~':
8638 reg_pat[i++] = '\\';
8639 reg_pat[i++] = *p;
8640 break;
8641 case '?':
8642#ifdef RISCOS
8643 case '#':
8644#endif
8645 reg_pat[i++] = '.';
8646 break;
8647 case '\\':
8648 if (p[1] == NUL)
8649 break;
8650#ifdef BACKSLASH_IN_FILENAME
8651 if (!no_bslash)
8652 {
8653 /* translate:
8654 * "\x" to "\\x" e.g., "dir\file"
8655 * "\*" to "\\.*" e.g., "dir\*.c"
8656 * "\?" to "\\." e.g., "dir\??.c"
8657 * "\+" to "\+" e.g., "fileX\+.c"
8658 */
8659 if ((vim_isfilec(p[1]) || p[1] == '*' || p[1] == '?')
8660 && p[1] != '+')
8661 {
8662 reg_pat[i++] = '[';
8663 reg_pat[i++] = '\\';
8664 reg_pat[i++] = '/';
8665 reg_pat[i++] = ']';
8666 if (allow_dirs != NULL)
8667 *allow_dirs = TRUE;
8668 break;
8669 }
8670 }
8671#endif
8672 if (*++p == '?'
8673#ifdef BACKSLASH_IN_FILENAME
8674 && no_bslash
8675#endif
8676 )
8677 reg_pat[i++] = '?';
8678 else
8679 if (*p == ',')
8680 reg_pat[i++] = ',';
8681 else
8682 {
8683 if (allow_dirs != NULL && vim_ispathsep(*p)
8684#ifdef BACKSLASH_IN_FILENAME
8685 && (!no_bslash || *p != '\\')
8686#endif
8687 )
8688 *allow_dirs = TRUE;
8689 reg_pat[i++] = '\\';
8690 reg_pat[i++] = *p;
8691 }
8692 break;
8693#ifdef BACKSLASH_IN_FILENAME
8694 case '/':
8695 reg_pat[i++] = '[';
8696 reg_pat[i++] = '\\';
8697 reg_pat[i++] = '/';
8698 reg_pat[i++] = ']';
8699 if (allow_dirs != NULL)
8700 *allow_dirs = TRUE;
8701 break;
8702#endif
8703 case '{':
8704 reg_pat[i++] = '\\';
8705 reg_pat[i++] = '(';
8706 nested++;
8707 break;
8708 case '}':
8709 reg_pat[i++] = '\\';
8710 reg_pat[i++] = ')';
8711 --nested;
8712 break;
8713 case ',':
8714 if (nested)
8715 {
8716 reg_pat[i++] = '\\';
8717 reg_pat[i++] = '|';
8718 }
8719 else
8720 reg_pat[i++] = ',';
8721 break;
8722 default:
8723# ifdef FEAT_MBYTE
8724 if (enc_dbcs != 0 && (*mb_ptr2len_check)(p) > 1)
8725 reg_pat[i++] = *p++;
8726 else
8727# endif
8728 if (allow_dirs != NULL && vim_ispathsep(*p))
8729 *allow_dirs = TRUE;
8730 reg_pat[i++] = *p;
8731 break;
8732 }
8733 }
8734 if (add_dollar)
8735 reg_pat[i++] = '$';
8736 reg_pat[i] = NUL;
8737 if (nested != 0)
8738 {
8739 if (nested < 0)
8740 EMSG(_("E219: Missing {."));
8741 else
8742 EMSG(_("E220: Missing }."));
8743 vim_free(reg_pat);
8744 reg_pat = NULL;
8745 }
8746 return reg_pat;
8747}