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