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