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