blob: ea7c924d92d3e8ea5706b04615091d4d792d6a2b [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 Moolenaar7c626922005-02-07 22:01:03 +00002704 int empty_memline = (buf->b_ml.ml_mfp == NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002705
2706 /*
2707 * Apply PRE aucocommands.
2708 * Set curbuf to the buffer to be written.
2709 * Careful: The autocommands may call buf_write() recursively!
2710 */
2711 if (ffname == buf->b_ffname)
2712 buf_ffname = TRUE;
2713 if (sfname == buf->b_sfname)
2714 buf_sfname = TRUE;
2715 if (fname == buf->b_ffname)
2716 buf_fname_f = TRUE;
2717 if (fname == buf->b_sfname)
2718 buf_fname_s = TRUE;
2719
2720 /* set curwin/curbuf to buf and save a few things */
2721 aucmd_prepbuf(&aco, buf);
2722
2723 if (append)
2724 {
2725 if (!(did_cmd = apply_autocmds_exarg(EVENT_FILEAPPENDCMD,
2726 sfname, sfname, FALSE, curbuf, eap)))
Bram Moolenaar21cf8232004-07-16 20:18:37 +00002727 {
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00002728 if (overwriting && bt_nofile(curbuf))
Bram Moolenaar21cf8232004-07-16 20:18:37 +00002729 nofile_err = TRUE;
2730 else
2731 apply_autocmds_exarg(EVENT_FILEAPPENDPRE,
Bram Moolenaar071d4272004-06-13 20:20:40 +00002732 sfname, sfname, FALSE, curbuf, eap);
Bram Moolenaar21cf8232004-07-16 20:18:37 +00002733 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002734 }
2735 else if (filtering)
2736 {
2737 apply_autocmds_exarg(EVENT_FILTERWRITEPRE,
2738 NULL, sfname, FALSE, curbuf, eap);
2739 }
2740 else if (reset_changed && whole)
2741 {
2742 if (!(did_cmd = apply_autocmds_exarg(EVENT_BUFWRITECMD,
2743 sfname, sfname, FALSE, curbuf, eap)))
Bram Moolenaar21cf8232004-07-16 20:18:37 +00002744 {
2745 if (bt_nofile(curbuf))
2746 nofile_err = TRUE;
2747 else
2748 apply_autocmds_exarg(EVENT_BUFWRITEPRE,
Bram Moolenaar071d4272004-06-13 20:20:40 +00002749 sfname, sfname, FALSE, curbuf, eap);
Bram Moolenaar21cf8232004-07-16 20:18:37 +00002750 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002751 }
2752 else
2753 {
2754 if (!(did_cmd = apply_autocmds_exarg(EVENT_FILEWRITECMD,
2755 sfname, sfname, FALSE, curbuf, eap)))
Bram Moolenaar21cf8232004-07-16 20:18:37 +00002756 {
2757 if (bt_nofile(curbuf))
2758 nofile_err = TRUE;
2759 else
2760 apply_autocmds_exarg(EVENT_FILEWRITEPRE,
Bram Moolenaar071d4272004-06-13 20:20:40 +00002761 sfname, sfname, FALSE, curbuf, eap);
Bram Moolenaar21cf8232004-07-16 20:18:37 +00002762 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002763 }
2764
2765 /* restore curwin/curbuf and a few other things */
2766 aucmd_restbuf(&aco);
2767
2768 /*
2769 * In three situations we return here and don't write the file:
2770 * 1. the autocommands deleted or unloaded the buffer.
2771 * 2. The autocommands abort script processing.
2772 * 3. If one of the "Cmd" autocommands was executed.
2773 */
2774 if (!buf_valid(buf))
2775 buf = NULL;
Bram Moolenaar7c626922005-02-07 22:01:03 +00002776 if (buf == NULL || (buf->b_ml.ml_mfp == NULL && !empty_memline)
Bram Moolenaar21cf8232004-07-16 20:18:37 +00002777 || did_cmd || nofile_err || aborting())
Bram Moolenaar071d4272004-06-13 20:20:40 +00002778 {
2779 --no_wait_return;
2780 msg_scroll = msg_save;
Bram Moolenaar21cf8232004-07-16 20:18:37 +00002781 if (nofile_err)
2782 EMSG(_("E676: No matching autocommands for acwrite buffer"));
2783
2784 if (aborting() || nofile_err)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002785 /* An aborting error, interrupt or exception in the
2786 * autocommands. */
2787 return FAIL;
2788 if (did_cmd)
2789 {
2790 if (buf == NULL)
2791 /* The buffer was deleted. We assume it was written
2792 * (can't retry anyway). */
2793 return OK;
2794 if (overwriting)
2795 {
2796 /* Assume the buffer was written, update the timestamp. */
2797 ml_timestamp(buf);
2798 buf->b_flags &= ~BF_WRITE_MASK;
2799 }
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00002800 if (reset_changed && buf->b_changed
2801 && (overwriting || vim_strchr(p_cpo, CPO_PLUS) != NULL))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002802 /* Buffer still changed, the autocommands didn't work
2803 * properly. */
2804 return FAIL;
2805 return OK;
2806 }
2807#ifdef FEAT_EVAL
2808 if (!aborting())
2809#endif
2810 EMSG(_("E203: Autocommands deleted or unloaded buffer to be written"));
2811 return FAIL;
2812 }
2813
2814 /*
2815 * The autocommands may have changed the number of lines in the file.
2816 * When writing the whole file, adjust the end.
2817 * When writing part of the file, assume that the autocommands only
2818 * changed the number of lines that are to be written (tricky!).
2819 */
2820 if (buf->b_ml.ml_line_count != old_line_count)
2821 {
2822 if (whole) /* write all */
2823 end = buf->b_ml.ml_line_count;
2824 else if (buf->b_ml.ml_line_count > old_line_count) /* more lines */
2825 end += buf->b_ml.ml_line_count - old_line_count;
2826 else /* less lines */
2827 {
2828 end -= old_line_count - buf->b_ml.ml_line_count;
2829 if (end < start)
2830 {
2831 --no_wait_return;
2832 msg_scroll = msg_save;
2833 EMSG(_("E204: Autocommand changed number of lines in unexpected way"));
2834 return FAIL;
2835 }
2836 }
2837 }
2838
2839 /*
2840 * The autocommands may have changed the name of the buffer, which may
2841 * be kept in fname, ffname and sfname.
2842 */
2843 if (buf_ffname)
2844 ffname = buf->b_ffname;
2845 if (buf_sfname)
2846 sfname = buf->b_sfname;
2847 if (buf_fname_f)
2848 fname = buf->b_ffname;
2849 if (buf_fname_s)
2850 fname = buf->b_sfname;
2851 }
2852#endif
2853
2854#ifdef FEAT_NETBEANS_INTG
2855 if (usingNetbeans && isNetbeansBuffer(buf))
2856 {
2857 if (whole)
2858 {
2859 /*
2860 * b_changed can be 0 after an undo, but we still need to write
2861 * the buffer to NetBeans.
2862 */
2863 if (buf->b_changed || isNetbeansModified(buf))
2864 {
Bram Moolenaar009b2592004-10-24 19:18:58 +00002865 --no_wait_return; /* may wait for return now */
2866 msg_scroll = msg_save;
2867 netbeans_save_buffer(buf); /* no error checking... */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002868 return retval;
2869 }
2870 else
2871 {
2872 errnum = (char_u *)"E656: ";
2873 errmsg = (char_u *)_("NetBeans dissallows writes of unmodified buffers");
2874 buffer = NULL;
2875 goto fail;
2876 }
2877 }
2878 else
2879 {
2880 errnum = (char_u *)"E657: ";
2881 errmsg = (char_u *)_("Partial writes disallowed for NetBeans buffers");
2882 buffer = NULL;
2883 goto fail;
2884 }
2885 }
2886#endif
2887
2888 if (shortmess(SHM_OVER) && !exiting)
2889 msg_scroll = FALSE; /* overwrite previous file message */
2890 else
2891 msg_scroll = TRUE; /* don't overwrite previous file message */
2892 if (!filtering)
2893 filemess(buf,
2894#ifndef UNIX
2895 sfname,
2896#else
2897 fname,
2898#endif
2899 (char_u *)"", 0); /* show that we are busy */
2900 msg_scroll = FALSE; /* always overwrite the file message now */
2901
2902 buffer = alloc(BUFSIZE);
2903 if (buffer == NULL) /* can't allocate big buffer, use small
2904 * one (to be able to write when out of
2905 * memory) */
2906 {
2907 buffer = smallbuf;
2908 bufsize = SMBUFSIZE;
2909 }
2910 else
2911 bufsize = BUFSIZE;
2912
2913 /*
2914 * Get information about original file (if there is one).
2915 */
2916#if defined(UNIX) && !defined(ARCHIE)
2917 st_old.st_dev = st_old.st_ino = 0;
2918 perm = -1;
2919 if (mch_stat((char *)fname, &st_old) < 0)
2920 newfile = TRUE;
2921 else
2922 {
2923 perm = st_old.st_mode;
2924 if (!S_ISREG(st_old.st_mode)) /* not a file */
2925 {
2926 if (S_ISDIR(st_old.st_mode))
2927 {
2928 errnum = (char_u *)"E502: ";
2929 errmsg = (char_u *)_("is a directory");
2930 goto fail;
2931 }
2932 if (mch_nodetype(fname) != NODE_WRITABLE)
2933 {
2934 errnum = (char_u *)"E503: ";
2935 errmsg = (char_u *)_("is not a file or writable device");
2936 goto fail;
2937 }
2938 /* It's a device of some kind (or a fifo) which we can write to
2939 * but for which we can't make a backup. */
2940 device = TRUE;
2941 newfile = TRUE;
2942 perm = -1;
2943 }
2944 }
2945#else /* !UNIX */
2946 /*
2947 * Check for a writable device name.
2948 */
2949 c = mch_nodetype(fname);
2950 if (c == NODE_OTHER)
2951 {
2952 errnum = (char_u *)"E503: ";
2953 errmsg = (char_u *)_("is not a file or writable device");
2954 goto fail;
2955 }
2956 if (c == NODE_WRITABLE)
2957 {
2958 device = TRUE;
2959 newfile = TRUE;
2960 perm = -1;
2961 }
2962 else
2963 {
2964 perm = mch_getperm(fname);
2965 if (perm < 0)
2966 newfile = TRUE;
2967 else if (mch_isdir(fname))
2968 {
2969 errnum = (char_u *)"E502: ";
2970 errmsg = (char_u *)_("is a directory");
2971 goto fail;
2972 }
2973 if (overwriting)
2974 (void)mch_stat((char *)fname, &st_old);
2975 }
2976#endif /* !UNIX */
2977
2978 if (!device && !newfile)
2979 {
2980 /*
2981 * Check if the file is really writable (when renaming the file to
2982 * make a backup we won't discover it later).
2983 */
2984 file_readonly = (
2985# ifdef USE_MCH_ACCESS
2986# ifdef UNIX
2987 (perm & 0222) == 0 ||
2988# endif
2989 mch_access((char *)fname, W_OK)
2990# else
2991 (fd = mch_open((char *)fname, O_RDWR | O_EXTRA, 0)) < 0
2992 ? TRUE : (close(fd), FALSE)
2993# endif
2994 );
2995 if (!forceit && file_readonly)
2996 {
2997 if (vim_strchr(p_cpo, CPO_FWRITE) != NULL)
2998 {
2999 errnum = (char_u *)"E504: ";
3000 errmsg = (char_u *)_(err_readonly);
3001 }
3002 else
3003 {
3004 errnum = (char_u *)"E505: ";
3005 errmsg = (char_u *)_("is read-only (add ! to override)");
3006 }
3007 goto fail;
3008 }
3009
3010 /*
3011 * Check if the timestamp hasn't changed since reading the file.
3012 */
3013 if (overwriting)
3014 {
3015 retval = check_mtime(buf, &st_old);
3016 if (retval == FAIL)
3017 goto fail;
3018 }
3019 }
3020
3021#ifdef HAVE_ACL
3022 /*
3023 * For systems that support ACL: get the ACL from the original file.
3024 */
3025 if (!newfile)
3026 acl = mch_get_acl(fname);
3027#endif
3028
3029 /*
3030 * If 'backupskip' is not empty, don't make a backup for some files.
3031 */
3032 dobackup = (p_wb || p_bk || *p_pm != NUL);
3033#ifdef FEAT_WILDIGN
3034 if (dobackup && *p_bsk != NUL && match_file_list(p_bsk, sfname, ffname))
3035 dobackup = FALSE;
3036#endif
3037
3038 /*
3039 * Save the value of got_int and reset it. We don't want a previous
3040 * interruption cancel writing, only hitting CTRL-C while writing should
3041 * abort it.
3042 */
3043 prev_got_int = got_int;
3044 got_int = FALSE;
3045
3046 /* Mark the buffer as 'being saved' to prevent changed buffer warnings */
3047 buf->b_saving = TRUE;
3048
3049 /*
3050 * If we are not appending or filtering, the file exists, and the
3051 * 'writebackup', 'backup' or 'patchmode' option is set, need a backup.
3052 * When 'patchmode' is set also make a backup when appending.
3053 *
3054 * Do not make any backup, if 'writebackup' and 'backup' are both switched
3055 * off. This helps when editing large files on almost-full disks.
3056 */
3057 if (!(append && *p_pm == NUL) && !filtering && perm >= 0 && dobackup)
3058 {
3059#if defined(UNIX) || defined(WIN32)
3060 struct stat st;
3061#endif
3062
3063 if ((bkc_flags & BKC_YES) || append) /* "yes" */
3064 backup_copy = TRUE;
3065#if defined(UNIX) || defined(WIN32)
3066 else if ((bkc_flags & BKC_AUTO)) /* "auto" */
3067 {
3068 int i;
3069
3070# ifdef UNIX
3071 /*
3072 * Don't rename the file when:
3073 * - it's a hard link
3074 * - it's a symbolic link
3075 * - we don't have write permission in the directory
3076 * - we can't set the owner/group of the new file
3077 */
3078 if (st_old.st_nlink > 1
3079 || mch_lstat((char *)fname, &st) < 0
3080 || st.st_dev != st_old.st_dev
3081 || st.st_ino != st_old.st_ino)
3082 backup_copy = TRUE;
3083 else
3084# endif
3085 {
3086 /*
3087 * Check if we can create a file and set the owner/group to
3088 * the ones from the original file.
3089 * First find a file name that doesn't exist yet (use some
3090 * arbitrary numbers).
3091 */
3092 STRCPY(IObuff, fname);
3093 for (i = 4913; ; i += 123)
3094 {
3095 sprintf((char *)gettail(IObuff), "%d", i);
3096 if (mch_stat((char *)IObuff, &st) < 0)
3097 break;
3098 }
3099 fd = mch_open((char *)IObuff, O_CREAT|O_WRONLY|O_EXCL, perm);
3100 close(fd);
3101 if (fd < 0) /* can't write in directory */
3102 backup_copy = TRUE;
3103 else
3104 {
3105# ifdef UNIX
3106 chown((char *)IObuff, st_old.st_uid, st_old.st_gid);
3107 (void)mch_setperm(IObuff, perm);
3108 if (mch_stat((char *)IObuff, &st) < 0
3109 || st.st_uid != st_old.st_uid
3110 || st.st_gid != st_old.st_gid
3111 || st.st_mode != perm)
3112 backup_copy = TRUE;
3113# endif
3114 mch_remove(IObuff);
3115 }
3116 }
3117 }
3118
3119# ifdef UNIX
3120 /*
3121 * Break symlinks and/or hardlinks if we've been asked to.
3122 */
3123 if ((bkc_flags & BKC_BREAKSYMLINK) || (bkc_flags & BKC_BREAKHARDLINK))
3124 {
3125 int lstat_res;
3126
3127 lstat_res = mch_lstat((char *)fname, &st);
3128
3129 /* Symlinks. */
3130 if ((bkc_flags & BKC_BREAKSYMLINK)
3131 && lstat_res == 0
3132 && st.st_ino != st_old.st_ino)
3133 backup_copy = FALSE;
3134
3135 /* Hardlinks. */
3136 if ((bkc_flags & BKC_BREAKHARDLINK)
3137 && st_old.st_nlink > 1
3138 && (lstat_res != 0 || st.st_ino == st_old.st_ino))
3139 backup_copy = FALSE;
3140 }
3141#endif
3142
3143#endif
3144
3145 /* make sure we have a valid backup extension to use */
3146 if (*p_bex == NUL)
3147 {
3148#ifdef RISCOS
3149 backup_ext = (char_u *)"/bak";
3150#else
3151 backup_ext = (char_u *)".bak";
3152#endif
3153 }
3154 else
3155 backup_ext = p_bex;
3156
3157 if (backup_copy
3158 && (fd = mch_open((char *)fname, O_RDONLY | O_EXTRA, 0)) >= 0)
3159 {
3160 int bfd;
3161 char_u *copybuf, *wp;
3162 int some_error = FALSE;
3163 struct stat st_new;
3164 char_u *dirp;
3165 char_u *rootname;
3166#ifndef SHORT_FNAME
3167 int did_set_shortname;
3168#endif
3169
3170 copybuf = alloc(BUFSIZE + 1);
3171 if (copybuf == NULL)
3172 {
3173 some_error = TRUE; /* out of memory */
3174 goto nobackup;
3175 }
3176
3177 /*
3178 * Try to make the backup in each directory in the 'bdir' option.
3179 *
3180 * Unix semantics has it, that we may have a writable file,
3181 * that cannot be recreated with a simple open(..., O_CREAT, ) e.g:
3182 * - the directory is not writable,
3183 * - the file may be a symbolic link,
3184 * - the file may belong to another user/group, etc.
3185 *
3186 * For these reasons, the existing writable file must be truncated
3187 * and reused. Creation of a backup COPY will be attempted.
3188 */
3189 dirp = p_bdir;
3190 while (*dirp)
3191 {
3192#ifdef UNIX
3193 st_new.st_ino = 0;
3194 st_new.st_dev = 0;
3195 st_new.st_gid = 0;
3196#endif
3197
3198 /*
3199 * Isolate one directory name, using an entry in 'bdir'.
3200 */
3201 (void)copy_option_part(&dirp, copybuf, BUFSIZE, ",");
3202 rootname = get_file_in_dir(fname, copybuf);
3203 if (rootname == NULL)
3204 {
3205 some_error = TRUE; /* out of memory */
3206 goto nobackup;
3207 }
3208
3209#ifndef SHORT_FNAME
3210 did_set_shortname = FALSE;
3211#endif
3212
3213 /*
3214 * May try twice if 'shortname' not set.
3215 */
3216 for (;;)
3217 {
3218 /*
3219 * Make backup file name.
3220 */
3221 backup = buf_modname(
3222#ifdef SHORT_FNAME
3223 TRUE,
3224#else
3225 (buf->b_p_sn || buf->b_shortname),
3226#endif
3227 rootname, backup_ext, FALSE);
3228 if (backup == NULL)
3229 {
3230 vim_free(rootname);
3231 some_error = TRUE; /* out of memory */
3232 goto nobackup;
3233 }
3234
3235 /*
3236 * Check if backup file already exists.
3237 */
3238 if (mch_stat((char *)backup, &st_new) >= 0)
3239 {
3240#ifdef UNIX
3241 /*
3242 * Check if backup file is same as original file.
3243 * May happen when modname() gave the same file back.
3244 * E.g. silly link, or file name-length reached.
3245 * If we don't check here, we either ruin the file
3246 * when copying or erase it after writing. jw.
3247 */
3248 if (st_new.st_dev == st_old.st_dev
3249 && st_new.st_ino == st_old.st_ino)
3250 {
3251 vim_free(backup);
3252 backup = NULL; /* no backup file to delete */
3253# ifndef SHORT_FNAME
3254 /*
3255 * may try again with 'shortname' set
3256 */
3257 if (!(buf->b_shortname || buf->b_p_sn))
3258 {
3259 buf->b_shortname = TRUE;
3260 did_set_shortname = TRUE;
3261 continue;
3262 }
3263 /* setting shortname didn't help */
3264 if (did_set_shortname)
3265 buf->b_shortname = FALSE;
3266# endif
3267 break;
3268 }
3269#endif
3270
3271 /*
3272 * If we are not going to keep the backup file, don't
3273 * delete an existing one, try to use another name.
3274 * Change one character, just before the extension.
3275 */
3276 if (!p_bk)
3277 {
3278 wp = backup + STRLEN(backup) - 1
3279 - STRLEN(backup_ext);
3280 if (wp < backup) /* empty file name ??? */
3281 wp = backup;
3282 *wp = 'z';
3283 while (*wp > 'a'
3284 && mch_stat((char *)backup, &st_new) >= 0)
3285 --*wp;
3286 /* They all exist??? Must be something wrong. */
3287 if (*wp == 'a')
3288 {
3289 vim_free(backup);
3290 backup = NULL;
3291 }
3292 }
3293 }
3294 break;
3295 }
3296 vim_free(rootname);
3297
3298 /*
3299 * Try to create the backup file
3300 */
3301 if (backup != NULL)
3302 {
3303 /* remove old backup, if present */
3304 mch_remove(backup);
3305 /* Open with O_EXCL to avoid the file being created while
3306 * we were sleeping (symlink hacker attack?) */
3307 bfd = mch_open((char *)backup,
3308 O_WRONLY|O_CREAT|O_EXTRA|O_EXCL, 0666);
3309 if (bfd < 0)
3310 {
3311 vim_free(backup);
3312 backup = NULL;
3313 }
3314 else
3315 {
3316 /* set file protection same as original file, but
3317 * strip s-bit */
3318 (void)mch_setperm(backup, perm & 0777);
3319
3320#ifdef UNIX
3321 /*
3322 * Try to set the group of the backup same as the
3323 * original file. If this fails, set the protection
3324 * bits for the group same as the protection bits for
3325 * others.
3326 */
3327 if (st_new.st_gid != st_old.st_gid &&
3328# ifdef HAVE_FCHOWN /* sequent-ptx lacks fchown() */
3329 fchown(bfd, (uid_t)-1, st_old.st_gid) != 0
3330# else
3331 chown((char *)backup, (uid_t)-1, st_old.st_gid) != 0
3332# endif
3333 )
3334 mch_setperm(backup,
3335 (perm & 0707) | ((perm & 07) << 3));
3336#endif
3337
3338 /*
3339 * copy the file.
3340 */
3341 write_info.bw_fd = bfd;
3342 write_info.bw_buf = copybuf;
3343#ifdef HAS_BW_FLAGS
3344 write_info.bw_flags = FIO_NOCONVERT;
3345#endif
3346 while ((write_info.bw_len = vim_read(fd, copybuf,
3347 BUFSIZE)) > 0)
3348 {
3349 if (buf_write_bytes(&write_info) == FAIL)
3350 {
3351 errmsg = (char_u *)_("E506: Can't write to backup file (add ! to override)");
3352 break;
3353 }
3354 ui_breakcheck();
3355 if (got_int)
3356 {
3357 errmsg = (char_u *)_(e_interr);
3358 break;
3359 }
3360 }
3361
3362 if (close(bfd) < 0 && errmsg == NULL)
3363 errmsg = (char_u *)_("E507: Close error for backup file (add ! to override)");
3364 if (write_info.bw_len < 0)
3365 errmsg = (char_u *)_("E508: Can't read file for backup (add ! to override)");
3366#ifdef UNIX
3367 set_file_time(backup, st_old.st_atime, st_old.st_mtime);
3368#endif
3369#ifdef HAVE_ACL
3370 mch_set_acl(backup, acl);
3371#endif
3372 break;
3373 }
3374 }
3375 }
3376 nobackup:
3377 close(fd); /* ignore errors for closing read file */
3378 vim_free(copybuf);
3379
3380 if (backup == NULL && errmsg == NULL)
3381 errmsg = (char_u *)_("E509: Cannot create backup file (add ! to override)");
3382 /* ignore errors when forceit is TRUE */
3383 if ((some_error || errmsg != NULL) && !forceit)
3384 {
3385 retval = FAIL;
3386 goto fail;
3387 }
3388 errmsg = NULL;
3389 }
3390 else
3391 {
3392 char_u *dirp;
3393 char_u *p;
3394 char_u *rootname;
3395
3396 /*
3397 * Make a backup by renaming the original file.
3398 */
3399 /*
3400 * If 'cpoptions' includes the "W" flag, we don't want to
3401 * overwrite a read-only file. But rename may be possible
3402 * anyway, thus we need an extra check here.
3403 */
3404 if (file_readonly && vim_strchr(p_cpo, CPO_FWRITE) != NULL)
3405 {
3406 errnum = (char_u *)"E504: ";
3407 errmsg = (char_u *)_(err_readonly);
3408 goto fail;
3409 }
3410
3411 /*
3412 *
3413 * Form the backup file name - change path/fo.o.h to
3414 * path/fo.o.h.bak Try all directories in 'backupdir', first one
3415 * that works is used.
3416 */
3417 dirp = p_bdir;
3418 while (*dirp)
3419 {
3420 /*
3421 * Isolate one directory name and make the backup file name.
3422 */
3423 (void)copy_option_part(&dirp, IObuff, IOSIZE, ",");
3424 rootname = get_file_in_dir(fname, IObuff);
3425 if (rootname == NULL)
3426 backup = NULL;
3427 else
3428 {
3429 backup = buf_modname(
3430#ifdef SHORT_FNAME
3431 TRUE,
3432#else
3433 (buf->b_p_sn || buf->b_shortname),
3434#endif
3435 rootname, backup_ext, FALSE);
3436 vim_free(rootname);
3437 }
3438
3439 if (backup != NULL)
3440 {
3441 /*
3442 * If we are not going to keep the backup file, don't
3443 * delete an existing one, try to use another name.
3444 * Change one character, just before the extension.
3445 */
3446 if (!p_bk && mch_getperm(backup) >= 0)
3447 {
3448 p = backup + STRLEN(backup) - 1 - STRLEN(backup_ext);
3449 if (p < backup) /* empty file name ??? */
3450 p = backup;
3451 *p = 'z';
3452 while (*p > 'a' && mch_getperm(backup) >= 0)
3453 --*p;
3454 /* They all exist??? Must be something wrong! */
3455 if (*p == 'a')
3456 {
3457 vim_free(backup);
3458 backup = NULL;
3459 }
3460 }
3461 }
3462 if (backup != NULL)
3463 {
3464
3465 /*
3466 * Delete any existing backup and move the current version to
3467 * the backup. For safety, we don't remove the backup until
3468 * the write has finished successfully. And if the 'backup'
3469 * option is set, leave it around.
3470 */
3471 /*
3472 * If the renaming of the original file to the backup file
3473 * works, quit here.
3474 */
3475 if (vim_rename(fname, backup) == 0)
3476 break;
3477
3478 vim_free(backup); /* don't do the rename below */
3479 backup = NULL;
3480 }
3481 }
3482 if (backup == NULL && !forceit)
3483 {
3484 errmsg = (char_u *)_("E510: Can't make backup file (add ! to override)");
3485 goto fail;
3486 }
3487 }
3488 }
3489
3490#if defined(UNIX) && !defined(ARCHIE)
3491 /* When using ":w!" and the file was read-only: make it writable */
3492 if (forceit && perm >= 0 && !(perm & 0200) && st_old.st_uid == getuid()
3493 && vim_strchr(p_cpo, CPO_FWRITE) == NULL)
3494 {
3495 perm |= 0200;
3496 (void)mch_setperm(fname, perm);
3497 made_writable = TRUE;
3498 }
3499#endif
3500
3501 /* When using ":w!" and writing to the current file, readonly makes no
3502 * sense, reset it */
3503 if (forceit && overwriting)
3504 {
3505 buf->b_p_ro = FALSE;
3506#ifdef FEAT_TITLE
3507 need_maketitle = TRUE; /* set window title later */
3508#endif
3509#ifdef FEAT_WINDOWS
3510 status_redraw_all(); /* redraw status lines later */
3511#endif
3512 }
3513
3514 if (end > buf->b_ml.ml_line_count)
3515 end = buf->b_ml.ml_line_count;
3516 if (buf->b_ml.ml_flags & ML_EMPTY)
3517 start = end + 1;
3518
3519 /*
3520 * If the original file is being overwritten, there is a small chance that
3521 * we crash in the middle of writing. Therefore the file is preserved now.
3522 * This makes all block numbers positive so that recovery does not need
3523 * the original file.
3524 * Don't do this if there is a backup file and we are exiting.
3525 */
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00003526 if (reset_changed && !newfile && overwriting
Bram Moolenaar071d4272004-06-13 20:20:40 +00003527 && !(exiting && backup != NULL))
3528 {
3529 ml_preserve(buf, FALSE);
3530 if (got_int)
3531 {
3532 errmsg = (char_u *)_(e_interr);
3533 goto restore_backup;
3534 }
3535 }
3536
3537#ifdef MACOS_CLASSIC /* TODO: Is it need for MACOS_X? (Dany) */
3538 /*
3539 * Before risking to lose the original file verify if there's
3540 * a resource fork to preserve, and if cannot be done warn
3541 * the users. This happens when overwriting without backups.
3542 */
3543 if (backup == NULL && overwriting && !append)
3544 if (mch_has_resource_fork(fname))
3545 {
3546 errmsg = (char_u *)_("E460: The resource fork would be lost (add ! to override)");
3547 goto restore_backup;
3548 }
3549#endif
3550
3551#ifdef VMS
3552 vms_remove_version(fname); /* remove version */
3553#endif
3554 /* Default: write the the file directly. May write to a temp file for
3555 * multi-byte conversion. */
3556 wfname = fname;
3557
3558#ifdef FEAT_MBYTE
3559 /* Check for forced 'fileencoding' from "++opt=val" argument. */
3560 if (eap != NULL && eap->force_enc != 0)
3561 {
3562 fenc = eap->cmd + eap->force_enc;
3563 fenc = enc_canonize(fenc);
3564 fenc_tofree = fenc;
3565 }
3566 else
3567 fenc = buf->b_p_fenc;
3568
3569 /*
3570 * The file needs to be converted when 'fileencoding' is set and
3571 * 'fileencoding' differs from 'encoding'.
3572 */
3573 converted = (*fenc != NUL && !same_encoding(p_enc, fenc));
3574
3575 /*
3576 * Check if UTF-8 to UCS-2/4 or Latin1 conversion needs to be done. Or
3577 * Latin1 to Unicode conversion. This is handled in buf_write_bytes().
3578 * Prepare the flags for it and allocate bw_conv_buf when needed.
3579 */
3580 if (converted && (enc_utf8 || STRCMP(p_enc, "latin1") == 0))
3581 {
3582 wb_flags = get_fio_flags(fenc);
3583 if (wb_flags & (FIO_UCS2 | FIO_UCS4 | FIO_UTF16 | FIO_UTF8))
3584 {
3585 /* Need to allocate a buffer to translate into. */
3586 if (wb_flags & (FIO_UCS2 | FIO_UTF16 | FIO_UTF8))
3587 write_info.bw_conv_buflen = bufsize * 2;
3588 else /* FIO_UCS4 */
3589 write_info.bw_conv_buflen = bufsize * 4;
3590 write_info.bw_conv_buf
3591 = lalloc((long_u)write_info.bw_conv_buflen, TRUE);
3592 if (write_info.bw_conv_buf == NULL)
3593 end = 0;
3594 }
3595 }
3596
3597# ifdef WIN3264
3598 if (converted && wb_flags == 0 && (wb_flags = get_win_fio_flags(fenc)) != 0)
3599 {
3600 /* Convert UTF-8 -> UCS-2 and UCS-2 -> DBCS. Worst-case * 4: */
3601 write_info.bw_conv_buflen = bufsize * 4;
3602 write_info.bw_conv_buf
3603 = lalloc((long_u)write_info.bw_conv_buflen, TRUE);
3604 if (write_info.bw_conv_buf == NULL)
3605 end = 0;
3606 }
3607# endif
3608
3609# ifdef MACOS_X
3610 if (converted && wb_flags == 0 && (wb_flags = get_mac_fio_flags(fenc)) != 0)
3611 {
3612 write_info.bw_conv_buflen = bufsize * 3;
3613 write_info.bw_conv_buf
3614 = lalloc((long_u)write_info.bw_conv_buflen, TRUE);
3615 if (write_info.bw_conv_buf == NULL)
3616 end = 0;
3617 }
3618# endif
3619
3620# if defined(FEAT_EVAL) || defined(USE_ICONV)
3621 if (converted && wb_flags == 0)
3622 {
3623# ifdef USE_ICONV
3624 /*
3625 * Use iconv() conversion when conversion is needed and it's not done
3626 * internally.
3627 */
3628 write_info.bw_iconv_fd = (iconv_t)my_iconv_open(fenc,
3629 enc_utf8 ? (char_u *)"utf-8" : p_enc);
3630 if (write_info.bw_iconv_fd != (iconv_t)-1)
3631 {
3632 /* We're going to use iconv(), allocate a buffer to convert in. */
3633 write_info.bw_conv_buflen = bufsize * ICONV_MULT;
3634 write_info.bw_conv_buf
3635 = lalloc((long_u)write_info.bw_conv_buflen, TRUE);
3636 if (write_info.bw_conv_buf == NULL)
3637 end = 0;
3638 write_info.bw_first = TRUE;
3639 }
3640# ifdef FEAT_EVAL
3641 else
3642# endif
3643# endif
3644
3645# ifdef FEAT_EVAL
3646 /*
3647 * When the file needs to be converted with 'charconvert' after
3648 * writing, write to a temp file instead and let the conversion
3649 * overwrite the original file.
3650 */
3651 if (*p_ccv != NUL)
3652 {
3653 wfname = vim_tempname('w');
3654 if (wfname == NULL) /* Can't write without a tempfile! */
3655 {
3656 errmsg = (char_u *)_("E214: Can't find temp file for writing");
3657 goto restore_backup;
3658 }
3659 }
3660# endif
3661 }
3662# endif
3663 if (converted && wb_flags == 0
3664# ifdef USE_ICONV
3665 && write_info.bw_iconv_fd == (iconv_t)-1
3666# endif
3667# ifdef FEAT_EVAL
3668 && wfname == fname
3669# endif
3670 )
3671 {
3672 if (!forceit)
3673 {
3674 errmsg = (char_u *)_("E213: Cannot convert (add ! to write without conversion)");
3675 goto restore_backup;
3676 }
3677 notconverted = TRUE;
3678 }
3679#endif
3680
3681 /*
3682 * Open the file "wfname" for writing.
3683 * We may try to open the file twice: If we can't write to the
3684 * file and forceit is TRUE we delete the existing file and try to create
3685 * a new one. If this still fails we may have lost the original file!
3686 * (this may happen when the user reached his quotum for number of files).
3687 * Appending will fail if the file does not exist and forceit is FALSE.
3688 */
3689 while ((fd = mch_open((char *)wfname, O_WRONLY | O_EXTRA | (append
3690 ? (forceit ? (O_APPEND | O_CREAT) : O_APPEND)
3691 : (O_CREAT | O_TRUNC))
3692 , 0666)) < 0)
3693 {
3694 /*
3695 * A forced write will try to create a new file if the old one is
3696 * still readonly. This may also happen when the directory is
3697 * read-only. In that case the mch_remove() will fail.
3698 */
3699 if (errmsg == NULL)
3700 {
3701#ifdef UNIX
3702 struct stat st;
3703
3704 /* Don't delete the file when it's a hard or symbolic link. */
3705 if ((!newfile && st_old.st_nlink > 1)
3706 || (mch_lstat((char *)fname, &st) == 0
3707 && (st.st_dev != st_old.st_dev
3708 || st.st_ino != st_old.st_ino)))
3709 errmsg = (char_u *)_("E166: Can't open linked file for writing");
3710 else
3711#endif
3712 {
3713 errmsg = (char_u *)_("E212: Can't open file for writing");
3714 if (forceit && vim_strchr(p_cpo, CPO_FWRITE) == NULL
3715 && perm >= 0)
3716 {
3717#ifdef UNIX
3718 /* we write to the file, thus it should be marked
3719 writable after all */
3720 if (!(perm & 0200))
3721 made_writable = TRUE;
3722 perm |= 0200;
3723 if (st_old.st_uid != getuid() || st_old.st_gid != getgid())
3724 perm &= 0777;
3725#endif
3726 if (!append) /* don't remove when appending */
3727 mch_remove(wfname);
3728 continue;
3729 }
3730 }
3731 }
3732
3733restore_backup:
3734 {
3735 struct stat st;
3736
3737 /*
3738 * If we failed to open the file, we don't need a backup. Throw it
3739 * away. If we moved or removed the original file try to put the
3740 * backup in its place.
3741 */
3742 if (backup != NULL && wfname == fname)
3743 {
3744 if (backup_copy)
3745 {
3746 /*
3747 * There is a small chance that we removed the original,
3748 * try to move the copy in its place.
3749 * This may not work if the vim_rename() fails.
3750 * In that case we leave the copy around.
3751 */
3752 /* If file does not exist, put the copy in its place */
3753 if (mch_stat((char *)fname, &st) < 0)
3754 vim_rename(backup, fname);
3755 /* if original file does exist throw away the copy */
3756 if (mch_stat((char *)fname, &st) >= 0)
3757 mch_remove(backup);
3758 }
3759 else
3760 {
3761 /* try to put the original file back */
3762 vim_rename(backup, fname);
3763 }
3764 }
3765
3766 /* if original file no longer exists give an extra warning */
3767 if (!newfile && mch_stat((char *)fname, &st) < 0)
3768 end = 0;
3769 }
3770
3771#ifdef FEAT_MBYTE
3772 if (wfname != fname)
3773 vim_free(wfname);
3774#endif
3775 goto fail;
3776 }
3777 errmsg = NULL;
3778
3779#if defined(MACOS_CLASSIC) || defined(WIN3264)
3780 /* TODO: Is it need for MACOS_X? (Dany) */
3781 /*
3782 * On macintosh copy the original files attributes (i.e. the backup)
3783 * This is done in order to preserve the ressource fork and the
3784 * Finder attribute (label, comments, custom icons, file creatore)
3785 */
3786 if (backup != NULL && overwriting && !append)
3787 {
3788 if (backup_copy)
3789 (void)mch_copy_file_attribute(wfname, backup);
3790 else
3791 (void)mch_copy_file_attribute(backup, wfname);
3792 }
3793
3794 if (!overwriting && !append)
3795 {
3796 if (buf->b_ffname != NULL)
3797 (void)mch_copy_file_attribute(buf->b_ffname, wfname);
3798 /* Should copy ressource fork */
3799 }
3800#endif
3801
3802 write_info.bw_fd = fd;
3803
3804#ifdef FEAT_CRYPT
3805 if (*buf->b_p_key && !filtering)
3806 {
3807 crypt_init_keys(buf->b_p_key);
3808 /* Write magic number, so that Vim knows that this file is encrypted
3809 * when reading it again. This also undergoes utf-8 to ucs-2/4
3810 * conversion when needed. */
3811 write_info.bw_buf = (char_u *)CRYPT_MAGIC;
3812 write_info.bw_len = CRYPT_MAGIC_LEN;
3813 write_info.bw_flags = FIO_NOCONVERT;
3814 if (buf_write_bytes(&write_info) == FAIL)
3815 end = 0;
3816 wb_flags |= FIO_ENCRYPTED;
3817 }
3818#endif
3819
3820 write_info.bw_buf = buffer;
3821 nchars = 0;
3822
3823 /* use "++bin", "++nobin" or 'binary' */
3824 if (eap != NULL && eap->force_bin != 0)
3825 write_bin = (eap->force_bin == FORCE_BIN);
3826 else
3827 write_bin = buf->b_p_bin;
3828
3829#ifdef FEAT_MBYTE
3830 /*
3831 * The BOM is written just after the encryption magic number.
Bram Moolenaarc0197e22004-09-13 20:26:32 +00003832 * Skip it when appending and the file already existed, the BOM only makes
3833 * sense at the start of the file.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003834 */
Bram Moolenaarc0197e22004-09-13 20:26:32 +00003835 if (buf->b_p_bomb && !write_bin && (!append || perm < 0))
Bram Moolenaar071d4272004-06-13 20:20:40 +00003836 {
3837 write_info.bw_len = make_bom(buffer, fenc);
3838 if (write_info.bw_len > 0)
3839 {
3840 /* don't convert, do encryption */
3841 write_info.bw_flags = FIO_NOCONVERT | wb_flags;
3842 if (buf_write_bytes(&write_info) == FAIL)
3843 end = 0;
3844 else
3845 nchars += write_info.bw_len;
3846 }
3847 }
3848#endif
3849
3850 write_info.bw_len = bufsize;
3851#ifdef HAS_BW_FLAGS
3852 write_info.bw_flags = wb_flags;
3853#endif
3854 fileformat = get_fileformat_force(buf, eap);
3855 s = buffer;
3856 len = 0;
3857 for (lnum = start; lnum <= end; ++lnum)
3858 {
3859 /*
3860 * The next while loop is done once for each character written.
3861 * Keep it fast!
3862 */
3863 ptr = ml_get_buf(buf, lnum, FALSE) - 1;
3864 while ((c = *++ptr) != NUL)
3865 {
3866 if (c == NL)
3867 *s = NUL; /* replace newlines with NULs */
3868 else if (c == CAR && fileformat == EOL_MAC)
3869 *s = NL; /* Mac: replace CRs with NLs */
3870 else
3871 *s = c;
3872 ++s;
3873 if (++len != bufsize)
3874 continue;
3875 if (buf_write_bytes(&write_info) == FAIL)
3876 {
3877 end = 0; /* write error: break loop */
3878 break;
3879 }
3880 nchars += bufsize;
3881 s = buffer;
3882 len = 0;
3883 }
3884 /* write failed or last line has no EOL: stop here */
3885 if (end == 0
3886 || (lnum == end
3887 && write_bin
3888 && (lnum == write_no_eol_lnum
3889 || (lnum == buf->b_ml.ml_line_count && !buf->b_p_eol))))
3890 {
3891 ++lnum; /* written the line, count it */
3892 no_eol = TRUE;
3893 break;
3894 }
3895 if (fileformat == EOL_UNIX)
3896 *s++ = NL;
3897 else
3898 {
3899 *s++ = CAR; /* EOL_MAC or EOL_DOS: write CR */
3900 if (fileformat == EOL_DOS) /* write CR-NL */
3901 {
3902 if (++len == bufsize)
3903 {
3904 if (buf_write_bytes(&write_info) == FAIL)
3905 {
3906 end = 0; /* write error: break loop */
3907 break;
3908 }
3909 nchars += bufsize;
3910 s = buffer;
3911 len = 0;
3912 }
3913 *s++ = NL;
3914 }
3915 }
3916 if (++len == bufsize && end)
3917 {
3918 if (buf_write_bytes(&write_info) == FAIL)
3919 {
3920 end = 0; /* write error: break loop */
3921 break;
3922 }
3923 nchars += bufsize;
3924 s = buffer;
3925 len = 0;
3926
3927 ui_breakcheck();
3928 if (got_int)
3929 {
3930 end = 0; /* Interrupted, break loop */
3931 break;
3932 }
3933 }
3934#ifdef VMS
3935 /*
3936 * On VMS there is a problem: newlines get added when writing blocks
3937 * at a time. Fix it by writing a line at a time.
3938 * This is much slower!
Bram Moolenaard4755bb2004-09-02 19:12:26 +00003939 * Explanation: VAX/DECC RTL insists that records in some RMS
3940 * structures end with a newline (carriage return) character, and if
3941 * they don't it adds one.
3942 * With other RMS structures it works perfect without this fix.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003943 */
Bram Moolenaard4755bb2004-09-02 19:12:26 +00003944 if ((buf->b_fab_rat & (FAB$M_FTN | FAB$M_CR)) != 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003945 {
Bram Moolenaard4755bb2004-09-02 19:12:26 +00003946 int b2write;
3947
3948 buf->b_fab_mrs = (buf->b_fab_mrs == 0
3949 ? MIN(4096, bufsize)
3950 : MIN(buf->b_fab_mrs, bufsize));
3951
3952 b2write = len;
3953 while (b2write > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003954 {
Bram Moolenaard4755bb2004-09-02 19:12:26 +00003955 write_info.bw_len = MIN(b2write, buf->b_fab_mrs);
3956 if (buf_write_bytes(&write_info) == FAIL)
3957 {
3958 end = 0;
3959 break;
3960 }
3961 b2write -= MIN(b2write, buf->b_fab_mrs);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003962 }
3963 write_info.bw_len = bufsize;
3964 nchars += len;
3965 s = buffer;
3966 len = 0;
3967 }
3968#endif
3969 }
3970 if (len > 0 && end > 0)
3971 {
3972 write_info.bw_len = len;
3973 if (buf_write_bytes(&write_info) == FAIL)
3974 end = 0; /* write error */
3975 nchars += len;
3976 }
3977
3978#if defined(UNIX) && defined(HAVE_FSYNC)
3979 /* On many journalling file systems there is a bug that causes both the
3980 * original and the backup file to be lost when halting the system right
3981 * after writing the file. That's because only the meta-data is
3982 * journalled. Syncing the file slows down the system, but assures it has
Bram Moolenaarf4b8e572004-06-24 15:53:16 +00003983 * been written to disk and we don't lose it.
3984 * For a device do try the fsync() but don't complain if it does not work
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00003985 * (could be a pipe).
3986 * If the 'fsync' option is FALSE, don't fsync(). Useful for laptops. */
3987 if (p_fs && fsync(fd) != 0 && !device)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003988 {
3989 errmsg = (char_u *)_("E667: Fsync failed");
3990 end = 0;
3991 }
3992#endif
3993
3994 if (close(fd) != 0)
3995 {
3996 errmsg = (char_u *)_("E512: Close failed");
3997 end = 0;
3998 }
3999
4000#ifdef UNIX
4001 if (made_writable)
4002 perm &= ~0200; /* reset 'w' bit for security reasons */
4003#endif
4004 if (perm >= 0) /* set perm. of new file same as old file */
4005 (void)mch_setperm(wfname, perm);
4006#ifdef RISCOS
4007 if (!append && !filtering)
4008 /* Set the filetype after writing the file. */
4009 mch_set_filetype(wfname, buf->b_p_oft);
4010#endif
4011#ifdef HAVE_ACL
4012 /* Probably need to set the ACL before changing the user (can't set the
4013 * ACL on a file the user doesn't own). */
4014 if (!backup_copy)
4015 mch_set_acl(wfname, acl);
4016#endif
4017
4018#ifdef UNIX
4019 /* When creating a new file, set its owner/group to that of the original
4020 * file. Get the new device and inode number. */
4021 if (backup != NULL && !backup_copy)
4022 {
4023 struct stat st;
4024
4025 /* don't change the owner when it's already OK, some systems remove
4026 * permission or ACL stuff */
4027 if (mch_stat((char *)wfname, &st) < 0
4028 || st.st_uid != st_old.st_uid
4029 || st.st_gid != st_old.st_gid)
4030 {
4031 chown((char *)wfname, st_old.st_uid, st_old.st_gid);
4032 if (perm >= 0) /* set permission again, may have changed */
4033 (void)mch_setperm(wfname, perm);
4034 }
4035 buf_setino(buf);
4036 }
4037#endif
4038
4039
4040#if defined(FEAT_MBYTE) && defined(FEAT_EVAL)
4041 if (wfname != fname)
4042 {
4043 /*
4044 * The file was written to a temp file, now it needs to be converted
4045 * with 'charconvert' to (overwrite) the output file.
4046 */
4047 if (end != 0)
4048 {
4049 if (eval_charconvert(enc_utf8 ? (char_u *)"utf-8" : p_enc, fenc,
4050 wfname, fname) == FAIL)
4051 {
4052 write_info.bw_conv_error = TRUE;
4053 end = 0;
4054 }
4055 }
4056 mch_remove(wfname);
4057 vim_free(wfname);
4058 }
4059#endif
4060
4061 if (end == 0)
4062 {
4063 if (errmsg == NULL)
4064 {
4065#ifdef FEAT_MBYTE
4066 if (write_info.bw_conv_error)
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00004067 errmsg = (char_u *)_("E513: write error, conversion failed (make 'fenc' empty to override)");
Bram Moolenaar071d4272004-06-13 20:20:40 +00004068 else
4069#endif
4070 if (got_int)
4071 errmsg = (char_u *)_(e_interr);
4072 else
4073 errmsg = (char_u *)_("E514: write error (file system full?)");
4074 }
4075
4076 /*
4077 * If we have a backup file, try to put it in place of the new file,
4078 * because the new file is probably corrupt. This avoids loosing the
4079 * original file when trying to make a backup when writing the file a
4080 * second time.
4081 * When "backup_copy" is set we need to copy the backup over the new
4082 * file. Otherwise rename the backup file.
4083 * If this is OK, don't give the extra warning message.
4084 */
4085 if (backup != NULL)
4086 {
4087 if (backup_copy)
4088 {
4089 /* This may take a while, if we were interrupted let the user
4090 * know we got the message. */
4091 if (got_int)
4092 {
4093 MSG(_(e_interr));
4094 out_flush();
4095 }
4096 if ((fd = mch_open((char *)backup, O_RDONLY | O_EXTRA, 0)) >= 0)
4097 {
4098 if ((write_info.bw_fd = mch_open((char *)fname,
4099 O_WRONLY | O_CREAT | O_TRUNC | O_EXTRA, 0666)) >= 0)
4100 {
4101 /* copy the file. */
4102 write_info.bw_buf = smallbuf;
4103#ifdef HAS_BW_FLAGS
4104 write_info.bw_flags = FIO_NOCONVERT;
4105#endif
4106 while ((write_info.bw_len = vim_read(fd, smallbuf,
4107 SMBUFSIZE)) > 0)
4108 if (buf_write_bytes(&write_info) == FAIL)
4109 break;
4110
4111 if (close(write_info.bw_fd) >= 0
4112 && write_info.bw_len == 0)
4113 end = 1; /* success */
4114 }
4115 close(fd); /* ignore errors for closing read file */
4116 }
4117 }
4118 else
4119 {
4120 if (vim_rename(backup, fname) == 0)
4121 end = 1;
4122 }
4123 }
4124 goto fail;
4125 }
4126
4127 lnum -= start; /* compute number of written lines */
4128 --no_wait_return; /* may wait for return now */
4129
4130#if !(defined(UNIX) || defined(VMS))
4131 fname = sfname; /* use shortname now, for the messages */
4132#endif
4133 if (!filtering)
4134 {
4135 msg_add_fname(buf, fname); /* put fname in IObuff with quotes */
4136 c = FALSE;
4137#ifdef FEAT_MBYTE
4138 if (write_info.bw_conv_error)
4139 {
4140 STRCAT(IObuff, _(" CONVERSION ERROR"));
4141 c = TRUE;
4142 }
4143 else if (notconverted)
4144 {
4145 STRCAT(IObuff, _("[NOT converted]"));
4146 c = TRUE;
4147 }
4148 else if (converted)
4149 {
4150 STRCAT(IObuff, _("[converted]"));
4151 c = TRUE;
4152 }
4153#endif
4154 if (device)
4155 {
4156 STRCAT(IObuff, _("[Device]"));
4157 c = TRUE;
4158 }
4159 else if (newfile)
4160 {
4161 STRCAT(IObuff, shortmess(SHM_NEW) ? _("[New]") : _("[New File]"));
4162 c = TRUE;
4163 }
4164 if (no_eol)
4165 {
4166 msg_add_eol();
4167 c = TRUE;
4168 }
4169 /* may add [unix/dos/mac] */
4170 if (msg_add_fileformat(fileformat))
4171 c = TRUE;
4172#ifdef FEAT_CRYPT
4173 if (wb_flags & FIO_ENCRYPTED)
4174 {
4175 STRCAT(IObuff, _("[crypted]"));
4176 c = TRUE;
4177 }
4178#endif
4179 msg_add_lines(c, (long)lnum, nchars); /* add line/char count */
4180 if (!shortmess(SHM_WRITE))
4181 {
4182 if (append)
4183 STRCAT(IObuff, shortmess(SHM_WRI) ? _(" [a]") : _(" appended"));
4184 else
4185 STRCAT(IObuff, shortmess(SHM_WRI) ? _(" [w]") : _(" written"));
4186 }
4187
4188 set_keep_msg(msg_trunc_attr(IObuff, FALSE, 0));
4189 keep_msg_attr = 0;
4190 }
4191
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00004192 /* When written everything correctly: reset 'modified'. Unless not
4193 * writing to the original file and '+' is not in 'cpoptions'. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004194 if (reset_changed && whole
4195#ifdef FEAT_MBYTE
4196 && !write_info.bw_conv_error
4197#endif
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00004198 && (overwriting || vim_strchr(p_cpo, CPO_PLUS) != NULL)
4199 )
Bram Moolenaar071d4272004-06-13 20:20:40 +00004200 {
4201 unchanged(buf, TRUE);
4202 u_unchanged(buf);
4203 }
4204
4205 /*
4206 * If written to the current file, update the timestamp of the swap file
4207 * and reset the BF_WRITE_MASK flags. Also sets buf->b_mtime.
4208 */
4209 if (overwriting)
4210 {
4211 ml_timestamp(buf);
4212 buf->b_flags &= ~BF_WRITE_MASK;
4213 }
4214
4215 /*
4216 * If we kept a backup until now, and we are in patch mode, then we make
4217 * the backup file our 'original' file.
4218 */
4219 if (*p_pm && dobackup)
4220 {
4221 char *org = (char *)buf_modname(
4222#ifdef SHORT_FNAME
4223 TRUE,
4224#else
4225 (buf->b_p_sn || buf->b_shortname),
4226#endif
4227 fname, p_pm, FALSE);
4228
4229 if (backup != NULL)
4230 {
4231 struct stat st;
4232
4233 /*
4234 * If the original file does not exist yet
4235 * the current backup file becomes the original file
4236 */
4237 if (org == NULL)
4238 EMSG(_("E205: Patchmode: can't save original file"));
4239 else if (mch_stat(org, &st) < 0)
4240 {
4241 vim_rename(backup, (char_u *)org);
4242 vim_free(backup); /* don't delete the file */
4243 backup = NULL;
4244#ifdef UNIX
4245 set_file_time((char_u *)org, st_old.st_atime, st_old.st_mtime);
4246#endif
4247 }
4248 }
4249 /*
4250 * If there is no backup file, remember that a (new) file was
4251 * created.
4252 */
4253 else
4254 {
4255 int empty_fd;
4256
4257 if (org == NULL
4258 || (empty_fd = mch_open(org, O_CREAT | O_EXTRA | O_EXCL,
4259 0666)) < 0)
4260 EMSG(_("E206: patchmode: can't touch empty original file"));
4261 else
4262 close(empty_fd);
4263 }
4264 if (org != NULL)
4265 {
4266 mch_setperm((char_u *)org, mch_getperm(fname) & 0777);
4267 vim_free(org);
4268 }
4269 }
4270
4271 /*
4272 * Remove the backup unless 'backup' option is set
4273 */
4274 if (!p_bk && backup != NULL && mch_remove(backup) != 0)
4275 EMSG(_("E207: Can't delete backup file"));
4276
4277#ifdef FEAT_SUN_WORKSHOP
4278 if (usingSunWorkShop)
4279 workshop_file_saved((char *) ffname);
4280#endif
4281
4282 goto nofail;
4283
4284 /*
4285 * Finish up. We get here either after failure or success.
4286 */
4287fail:
4288 --no_wait_return; /* may wait for return now */
4289nofail:
4290
4291 /* Done saving, we accept changed buffer warnings again */
4292 buf->b_saving = FALSE;
4293
4294 vim_free(backup);
4295 if (buffer != smallbuf)
4296 vim_free(buffer);
4297#ifdef FEAT_MBYTE
4298 vim_free(fenc_tofree);
4299 vim_free(write_info.bw_conv_buf);
4300# ifdef USE_ICONV
4301 if (write_info.bw_iconv_fd != (iconv_t)-1)
4302 {
4303 iconv_close(write_info.bw_iconv_fd);
4304 write_info.bw_iconv_fd = (iconv_t)-1;
4305 }
4306# endif
4307#endif
4308#ifdef HAVE_ACL
4309 mch_free_acl(acl);
4310#endif
4311
4312 if (errmsg != NULL)
4313 {
4314 int numlen = errnum != NULL ? STRLEN(errnum) : 0;
4315
4316 attr = hl_attr(HLF_E); /* set highlight for error messages */
4317 msg_add_fname(buf,
4318#ifndef UNIX
4319 sfname
4320#else
4321 fname
4322#endif
4323 ); /* put file name in IObuff with quotes */
4324 if (STRLEN(IObuff) + STRLEN(errmsg) + numlen >= IOSIZE)
4325 IObuff[IOSIZE - STRLEN(errmsg) - numlen - 1] = NUL;
4326 /* If the error message has the form "is ...", put the error number in
4327 * front of the file name. */
4328 if (errnum != NULL)
4329 {
4330 mch_memmove(IObuff + numlen, IObuff, STRLEN(IObuff) + 1);
4331 mch_memmove(IObuff, errnum, (size_t)numlen);
4332 }
4333 STRCAT(IObuff, errmsg);
4334 emsg(IObuff);
4335
4336 retval = FAIL;
4337 if (end == 0)
4338 {
4339 MSG_PUTS_ATTR(_("\nWARNING: Original file may be lost or damaged\n"),
4340 attr | MSG_HIST);
4341 MSG_PUTS_ATTR(_("don't quit the editor until the file is successfully written!"),
4342 attr | MSG_HIST);
4343
4344 /* Update the timestamp to avoid an "overwrite changed file"
4345 * prompt when writing again. */
4346 if (mch_stat((char *)fname, &st_old) >= 0)
4347 {
4348 buf_store_time(buf, &st_old, fname);
4349 buf->b_mtime_read = buf->b_mtime;
4350 }
4351 }
4352 }
4353 msg_scroll = msg_save;
4354
4355#ifdef FEAT_AUTOCMD
4356#ifdef FEAT_EVAL
4357 if (!should_abort(retval))
4358#else
4359 if (!got_int)
4360#endif
4361 {
4362 aco_save_T aco;
4363
4364 write_no_eol_lnum = 0; /* in case it was set by the previous read */
4365
4366 /*
4367 * Apply POST autocommands.
4368 * Careful: The autocommands may call buf_write() recursively!
4369 */
4370 aucmd_prepbuf(&aco, buf);
4371
4372 if (append)
4373 apply_autocmds_exarg(EVENT_FILEAPPENDPOST, fname, fname,
4374 FALSE, curbuf, eap);
4375 else if (filtering)
4376 apply_autocmds_exarg(EVENT_FILTERWRITEPOST, NULL, fname,
4377 FALSE, curbuf, eap);
4378 else if (reset_changed && whole)
4379 apply_autocmds_exarg(EVENT_BUFWRITEPOST, fname, fname,
4380 FALSE, curbuf, eap);
4381 else
4382 apply_autocmds_exarg(EVENT_FILEWRITEPOST, fname, fname,
4383 FALSE, curbuf, eap);
4384
4385 /* restore curwin/curbuf and a few other things */
4386 aucmd_restbuf(&aco);
4387
4388#ifdef FEAT_EVAL
4389 if (aborting()) /* autocmds may abort script processing */
4390 retval = FALSE;
4391#endif
4392 }
4393#endif
4394
4395 got_int |= prev_got_int;
4396
4397#ifdef MACOS_CLASSIC /* TODO: Is it need for MACOS_X? (Dany) */
4398 /* Update machine specific information. */
4399 mch_post_buffer_write(buf);
4400#endif
4401 return retval;
4402}
4403
4404/*
4405 * Put file name into IObuff with quotes.
4406 */
Bram Moolenaar009b2592004-10-24 19:18:58 +00004407 void
Bram Moolenaar071d4272004-06-13 20:20:40 +00004408msg_add_fname(buf, fname)
4409 buf_T *buf;
4410 char_u *fname;
4411{
4412 if (fname == NULL)
4413 fname = (char_u *)"-stdin-";
4414 home_replace(buf, fname, IObuff + 1, IOSIZE - 4, TRUE);
4415 IObuff[0] = '"';
4416 STRCAT(IObuff, "\" ");
4417}
4418
4419/*
4420 * Append message for text mode to IObuff.
4421 * Return TRUE if something appended.
4422 */
4423 static int
4424msg_add_fileformat(eol_type)
4425 int eol_type;
4426{
4427#ifndef USE_CRNL
4428 if (eol_type == EOL_DOS)
4429 {
4430 STRCAT(IObuff, shortmess(SHM_TEXT) ? _("[dos]") : _("[dos format]"));
4431 return TRUE;
4432 }
4433#endif
4434#ifndef USE_CR
4435 if (eol_type == EOL_MAC)
4436 {
4437 STRCAT(IObuff, shortmess(SHM_TEXT) ? _("[mac]") : _("[mac format]"));
4438 return TRUE;
4439 }
4440#endif
4441#if defined(USE_CRNL) || defined(USE_CR)
4442 if (eol_type == EOL_UNIX)
4443 {
4444 STRCAT(IObuff, shortmess(SHM_TEXT) ? _("[unix]") : _("[unix format]"));
4445 return TRUE;
4446 }
4447#endif
4448 return FALSE;
4449}
4450
4451/*
4452 * Append line and character count to IObuff.
4453 */
Bram Moolenaar009b2592004-10-24 19:18:58 +00004454 void
Bram Moolenaar071d4272004-06-13 20:20:40 +00004455msg_add_lines(insert_space, lnum, nchars)
4456 int insert_space;
4457 long lnum;
4458 long nchars;
4459{
4460 char_u *p;
4461
4462 p = IObuff + STRLEN(IObuff);
4463
4464 if (insert_space)
4465 *p++ = ' ';
4466 if (shortmess(SHM_LINES))
4467 sprintf((char *)p, "%ldL, %ldC", lnum, nchars);
4468 else
4469 {
4470 if (lnum == 1)
4471 STRCPY(p, _("1 line, "));
4472 else
4473 sprintf((char *)p, _("%ld lines, "), lnum);
4474 p += STRLEN(p);
4475 if (nchars == 1)
4476 STRCPY(p, _("1 character"));
4477 else
4478 sprintf((char *)p, _("%ld characters"), nchars);
4479 }
4480}
4481
4482/*
4483 * Append message for missing line separator to IObuff.
4484 */
4485 static void
4486msg_add_eol()
4487{
4488 STRCAT(IObuff, shortmess(SHM_LAST) ? _("[noeol]") : _("[Incomplete last line]"));
4489}
4490
4491/*
4492 * Check modification time of file, before writing to it.
4493 * The size isn't checked, because using a tool like "gzip" takes care of
4494 * using the same timestamp but can't set the size.
4495 */
4496 static int
4497check_mtime(buf, st)
4498 buf_T *buf;
4499 struct stat *st;
4500{
4501 if (buf->b_mtime_read != 0
4502 && time_differs((long)st->st_mtime, buf->b_mtime_read))
4503 {
4504 msg_scroll = TRUE; /* don't overwrite messages here */
4505 msg_silent = 0; /* must give this prompt */
4506 /* don't use emsg() here, don't want to flush the buffers */
4507 MSG_ATTR(_("WARNING: The file has been changed since reading it!!!"),
4508 hl_attr(HLF_E));
4509 if (ask_yesno((char_u *)_("Do you really want to write to it"),
4510 TRUE) == 'n')
4511 return FAIL;
4512 msg_scroll = FALSE; /* always overwrite the file message now */
4513 }
4514 return OK;
4515}
4516
4517 static int
4518time_differs(t1, t2)
4519 long t1, t2;
4520{
4521#if defined(__linux__) || defined(MSDOS) || defined(MSWIN)
4522 /* On a FAT filesystem, esp. under Linux, there are only 5 bits to store
4523 * the seconds. Since the roundoff is done when flushing the inode, the
4524 * time may change unexpectedly by one second!!! */
4525 return (t1 - t2 > 1 || t2 - t1 > 1);
4526#else
4527 return (t1 != t2);
4528#endif
4529}
4530
4531/*
4532 * Call write() to write a number of bytes to the file.
4533 * Also handles encryption and 'encoding' conversion.
4534 *
4535 * Return FAIL for failure, OK otherwise.
4536 */
4537 static int
4538buf_write_bytes(ip)
4539 struct bw_info *ip;
4540{
4541 int wlen;
4542 char_u *buf = ip->bw_buf; /* data to write */
4543 int len = ip->bw_len; /* length of data */
4544#ifdef HAS_BW_FLAGS
4545 int flags = ip->bw_flags; /* extra flags */
4546#endif
4547
4548#ifdef FEAT_MBYTE
4549 /*
4550 * Skip conversion when writing the crypt magic number or the BOM.
4551 */
4552 if (!(flags & FIO_NOCONVERT))
4553 {
4554 char_u *p;
4555 unsigned c;
4556 int n;
4557
4558 if (flags & FIO_UTF8)
4559 {
4560 /*
4561 * Convert latin1 in the buffer to UTF-8 in the file.
4562 */
4563 p = ip->bw_conv_buf; /* translate to buffer */
4564 for (wlen = 0; wlen < len; ++wlen)
4565 p += utf_char2bytes(buf[wlen], p);
4566 buf = ip->bw_conv_buf;
4567 len = (int)(p - ip->bw_conv_buf);
4568 }
4569 else if (flags & (FIO_UCS4 | FIO_UTF16 | FIO_UCS2 | FIO_LATIN1))
4570 {
4571 /*
4572 * Convert UTF-8 bytes in the buffer to UCS-2, UCS-4, UTF-16 or
4573 * Latin1 chars in the file.
4574 */
4575 if (flags & FIO_LATIN1)
4576 p = buf; /* translate in-place (can only get shorter) */
4577 else
4578 p = ip->bw_conv_buf; /* translate to buffer */
4579 for (wlen = 0; wlen < len; wlen += n)
4580 {
4581 if (wlen == 0 && ip->bw_restlen != 0)
4582 {
4583 int l;
4584
4585 /* Use remainder of previous call. Append the start of
4586 * buf[] to get a full sequence. Might still be too
4587 * short! */
4588 l = CONV_RESTLEN - ip->bw_restlen;
4589 if (l > len)
4590 l = len;
4591 mch_memmove(ip->bw_rest + ip->bw_restlen, buf, (size_t)l);
4592 n = utf_ptr2len_check_len(ip->bw_rest, ip->bw_restlen + l);
4593 if (n > ip->bw_restlen + len)
4594 {
4595 /* We have an incomplete byte sequence at the end to
4596 * be written. We can't convert it without the
4597 * remaining bytes. Keep them for the next call. */
4598 if (ip->bw_restlen + len > CONV_RESTLEN)
4599 return FAIL;
4600 ip->bw_restlen += len;
4601 break;
4602 }
4603 if (n > 1)
4604 c = utf_ptr2char(ip->bw_rest);
4605 else
4606 c = ip->bw_rest[0];
4607 if (n >= ip->bw_restlen)
4608 {
4609 n -= ip->bw_restlen;
4610 ip->bw_restlen = 0;
4611 }
4612 else
4613 {
4614 ip->bw_restlen -= n;
4615 mch_memmove(ip->bw_rest, ip->bw_rest + n,
4616 (size_t)ip->bw_restlen);
4617 n = 0;
4618 }
4619 }
4620 else
4621 {
4622 n = utf_ptr2len_check_len(buf + wlen, len - wlen);
4623 if (n > len - wlen)
4624 {
4625 /* We have an incomplete byte sequence at the end to
4626 * be written. We can't convert it without the
4627 * remaining bytes. Keep them for the next call. */
4628 if (len - wlen > CONV_RESTLEN)
4629 return FAIL;
4630 ip->bw_restlen = len - wlen;
4631 mch_memmove(ip->bw_rest, buf + wlen,
4632 (size_t)ip->bw_restlen);
4633 break;
4634 }
4635 if (n > 1)
4636 c = utf_ptr2char(buf + wlen);
4637 else
4638 c = buf[wlen];
4639 }
4640
4641 ip->bw_conv_error |= ucs2bytes(c, &p, flags);
4642 }
4643 if (flags & FIO_LATIN1)
4644 len = (int)(p - buf);
4645 else
4646 {
4647 buf = ip->bw_conv_buf;
4648 len = (int)(p - ip->bw_conv_buf);
4649 }
4650 }
4651
4652# ifdef WIN3264
4653 else if (flags & FIO_CODEPAGE)
4654 {
4655 /*
4656 * Convert UTF-8 or codepage to UCS-2 and then to MS-Windows
4657 * codepage.
4658 */
4659 char_u *from;
4660 size_t fromlen;
4661 char_u *to;
4662 int u8c;
4663 BOOL bad = FALSE;
4664 int needed;
4665
4666 if (ip->bw_restlen > 0)
4667 {
4668 /* Need to concatenate the remainder of the previous call and
4669 * the bytes of the current call. Use the end of the
4670 * conversion buffer for this. */
4671 fromlen = len + ip->bw_restlen;
4672 from = ip->bw_conv_buf + ip->bw_conv_buflen - fromlen;
4673 mch_memmove(from, ip->bw_rest, (size_t)ip->bw_restlen);
4674 mch_memmove(from + ip->bw_restlen, buf, (size_t)len);
4675 }
4676 else
4677 {
4678 from = buf;
4679 fromlen = len;
4680 }
4681
4682 to = ip->bw_conv_buf;
4683 if (enc_utf8)
4684 {
4685 /* Convert from UTF-8 to UCS-2, to the start of the buffer.
4686 * The buffer has been allocated to be big enough. */
4687 while (fromlen > 0)
4688 {
4689 n = utf_ptr2len_check_len(from, fromlen);
4690 if (n > (int)fromlen) /* incomplete byte sequence */
4691 break;
4692 u8c = utf_ptr2char(from);
4693 *to++ = (u8c & 0xff);
4694 *to++ = (u8c >> 8);
4695 fromlen -= n;
4696 from += n;
4697 }
4698
4699 /* Copy remainder to ip->bw_rest[] to be used for the next
4700 * call. */
4701 if (fromlen > CONV_RESTLEN)
4702 {
4703 /* weird overlong sequence */
4704 ip->bw_conv_error = TRUE;
4705 return FAIL;
4706 }
4707 mch_memmove(ip->bw_rest, from, fromlen);
4708 ip->bw_restlen = fromlen;
4709 }
4710 else
4711 {
4712 /* Convert from enc_codepage to UCS-2, to the start of the
4713 * buffer. The buffer has been allocated to be big enough. */
4714 ip->bw_restlen = 0;
4715 needed = MultiByteToWideChar(enc_codepage,
4716 MB_ERR_INVALID_CHARS, (LPCSTR)from, fromlen,
4717 NULL, 0);
4718 if (needed == 0)
4719 {
4720 /* When conversion fails there may be a trailing byte. */
4721 needed = MultiByteToWideChar(enc_codepage,
4722 MB_ERR_INVALID_CHARS, (LPCSTR)from, fromlen - 1,
4723 NULL, 0);
4724 if (needed == 0)
4725 {
4726 /* Conversion doesn't work. */
4727 ip->bw_conv_error = TRUE;
4728 return FAIL;
4729 }
4730 /* Save the trailing byte for the next call. */
4731 ip->bw_rest[0] = from[fromlen - 1];
4732 ip->bw_restlen = 1;
4733 }
4734 needed = MultiByteToWideChar(enc_codepage, MB_ERR_INVALID_CHARS,
4735 (LPCSTR)from, fromlen - ip->bw_restlen,
4736 (LPWSTR)to, needed);
4737 if (needed == 0)
4738 {
4739 /* Safety check: Conversion doesn't work. */
4740 ip->bw_conv_error = TRUE;
4741 return FAIL;
4742 }
4743 to += needed * 2;
4744 }
4745
4746 fromlen = to - ip->bw_conv_buf;
4747 buf = to;
4748# ifdef CP_UTF8 /* VC 4.1 doesn't define CP_UTF8 */
4749 if (FIO_GET_CP(flags) == CP_UTF8)
4750 {
4751 /* Convert from UCS-2 to UTF-8, using the remainder of the
4752 * conversion buffer. Fails when out of space. */
4753 for (from = ip->bw_conv_buf; fromlen > 1; fromlen -= 2)
4754 {
4755 u8c = *from++;
4756 u8c += (*from++ << 8);
4757 to += utf_char2bytes(u8c, to);
4758 if (to + 6 >= ip->bw_conv_buf + ip->bw_conv_buflen)
4759 {
4760 ip->bw_conv_error = TRUE;
4761 return FAIL;
4762 }
4763 }
4764 len = to - buf;
4765 }
4766 else
4767#endif
4768 {
4769 /* Convert from UCS-2 to the codepage, using the remainder of
4770 * the conversion buffer. If the conversion uses the default
4771 * character "0", the data doesn't fit in this encoding, so
4772 * fail. */
4773 len = WideCharToMultiByte(FIO_GET_CP(flags), 0,
4774 (LPCWSTR)ip->bw_conv_buf, (int)fromlen / sizeof(WCHAR),
4775 (LPSTR)to, ip->bw_conv_buflen - fromlen, 0, &bad);
4776 if (bad)
4777 {
4778 ip->bw_conv_error = TRUE;
4779 return FAIL;
4780 }
4781 }
4782 }
4783# endif
4784
4785# ifdef MACOS_X
4786 else if (flags & FIO_MACROMAN)
4787 {
4788 /*
4789 * Convert UTF-8 or latin1 to Apple MacRoman.
4790 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004791 char_u *from;
4792 size_t fromlen;
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00004793 extern int enc2macroman __ARGS((char_u *from, size_t fromlen,
4794 char_u *to, int *tolenp, int maxtolen, char_u *rest,
4795 int *restlenp));
Bram Moolenaar071d4272004-06-13 20:20:40 +00004796
4797 if (ip->bw_restlen > 0)
4798 {
4799 /* Need to concatenate the remainder of the previous call and
4800 * the bytes of the current call. Use the end of the
4801 * conversion buffer for this. */
4802 fromlen = len + ip->bw_restlen;
4803 from = ip->bw_conv_buf + ip->bw_conv_buflen - fromlen;
4804 mch_memmove(from, ip->bw_rest, (size_t)ip->bw_restlen);
4805 mch_memmove(from + ip->bw_restlen, buf, (size_t)len);
4806 }
4807 else
4808 {
4809 from = buf;
4810 fromlen = len;
4811 }
4812
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00004813 if (enc2macroman(from, fromlen,
4814 ip->bw_conv_buf, &len, ip->bw_conv_buflen,
4815 ip->bw_rest, &ip->bw_restlen) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004816 {
4817 ip->bw_conv_error = TRUE;
4818 return FAIL;
4819 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004820 buf = ip->bw_conv_buf;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004821 }
4822# endif
4823
4824# ifdef USE_ICONV
4825 if (ip->bw_iconv_fd != (iconv_t)-1)
4826 {
4827 const char *from;
4828 size_t fromlen;
4829 char *to;
4830 size_t tolen;
4831
4832 /* Convert with iconv(). */
4833 if (ip->bw_restlen > 0)
4834 {
4835 /* Need to concatenate the remainder of the previous call and
4836 * the bytes of the current call. Use the end of the
4837 * conversion buffer for this. */
4838 fromlen = len + ip->bw_restlen;
4839 from = (char *)ip->bw_conv_buf + ip->bw_conv_buflen - fromlen;
4840 mch_memmove((void *)from, ip->bw_rest, (size_t)ip->bw_restlen);
4841 mch_memmove((void *)(from + ip->bw_restlen), buf, (size_t)len);
4842 tolen = ip->bw_conv_buflen - fromlen;
4843 }
4844 else
4845 {
4846 from = (const char *)buf;
4847 fromlen = len;
4848 tolen = ip->bw_conv_buflen;
4849 }
4850 to = (char *)ip->bw_conv_buf;
4851
4852 if (ip->bw_first)
4853 {
4854 size_t save_len = tolen;
4855
4856 /* output the initial shift state sequence */
4857 (void)iconv(ip->bw_iconv_fd, NULL, NULL, &to, &tolen);
4858
4859 /* There is a bug in iconv() on Linux (which appears to be
4860 * wide-spread) which sets "to" to NULL and messes up "tolen".
4861 */
4862 if (to == NULL)
4863 {
4864 to = (char *)ip->bw_conv_buf;
4865 tolen = save_len;
4866 }
4867 ip->bw_first = FALSE;
4868 }
4869
4870 /*
4871 * If iconv() has an error or there is not enough room, fail.
4872 */
4873 if ((iconv(ip->bw_iconv_fd, (void *)&from, &fromlen, &to, &tolen)
4874 == (size_t)-1 && ICONV_ERRNO != ICONV_EINVAL)
4875 || fromlen > CONV_RESTLEN)
4876 {
4877 ip->bw_conv_error = TRUE;
4878 return FAIL;
4879 }
4880
4881 /* copy remainder to ip->bw_rest[] to be used for the next call. */
4882 if (fromlen > 0)
4883 mch_memmove(ip->bw_rest, (void *)from, fromlen);
4884 ip->bw_restlen = (int)fromlen;
4885
4886 buf = ip->bw_conv_buf;
4887 len = (int)((char_u *)to - ip->bw_conv_buf);
4888 }
4889# endif
4890 }
4891#endif /* FEAT_MBYTE */
4892
4893#ifdef FEAT_CRYPT
4894 if (flags & FIO_ENCRYPTED) /* encrypt the data */
4895 {
4896 int ztemp, t, i;
4897
4898 for (i = 0; i < len; i++)
4899 {
4900 ztemp = buf[i];
4901 buf[i] = ZENCODE(ztemp, t);
4902 }
4903 }
4904#endif
4905
4906 /* Repeat the write(), it may be interrupted by a signal. */
4907 while (len)
4908 {
4909 wlen = vim_write(ip->bw_fd, buf, len);
4910 if (wlen <= 0) /* error! */
4911 return FAIL;
4912 len -= wlen;
4913 buf += wlen;
4914 }
4915 return OK;
4916}
4917
4918#ifdef FEAT_MBYTE
4919/*
4920 * Convert a Unicode character to bytes.
4921 */
4922 static int
4923ucs2bytes(c, pp, flags)
4924 unsigned c; /* in: character */
4925 char_u **pp; /* in/out: pointer to result */
4926 int flags; /* FIO_ flags */
4927{
4928 char_u *p = *pp;
4929 int error = FALSE;
4930 int cc;
4931
4932
4933 if (flags & FIO_UCS4)
4934 {
4935 if (flags & FIO_ENDIAN_L)
4936 {
4937 *p++ = c;
4938 *p++ = (c >> 8);
4939 *p++ = (c >> 16);
4940 *p++ = (c >> 24);
4941 }
4942 else
4943 {
4944 *p++ = (c >> 24);
4945 *p++ = (c >> 16);
4946 *p++ = (c >> 8);
4947 *p++ = c;
4948 }
4949 }
4950 else if (flags & (FIO_UCS2 | FIO_UTF16))
4951 {
4952 if (c >= 0x10000)
4953 {
4954 if (flags & FIO_UTF16)
4955 {
4956 /* Make two words, ten bits of the character in each. First
4957 * word is 0xd800 - 0xdbff, second one 0xdc00 - 0xdfff */
4958 c -= 0x10000;
4959 if (c >= 0x100000)
4960 error = TRUE;
4961 cc = ((c >> 10) & 0x3ff) + 0xd800;
4962 if (flags & FIO_ENDIAN_L)
4963 {
4964 *p++ = cc;
4965 *p++ = ((unsigned)cc >> 8);
4966 }
4967 else
4968 {
4969 *p++ = ((unsigned)cc >> 8);
4970 *p++ = cc;
4971 }
4972 c = (c & 0x3ff) + 0xdc00;
4973 }
4974 else
4975 error = TRUE;
4976 }
4977 if (flags & FIO_ENDIAN_L)
4978 {
4979 *p++ = c;
4980 *p++ = (c >> 8);
4981 }
4982 else
4983 {
4984 *p++ = (c >> 8);
4985 *p++ = c;
4986 }
4987 }
4988 else /* Latin1 */
4989 {
4990 if (c >= 0x100)
4991 {
4992 error = TRUE;
4993 *p++ = 0xBF;
4994 }
4995 else
4996 *p++ = c;
4997 }
4998
4999 *pp = p;
5000 return error;
5001}
5002
5003/*
5004 * Return TRUE if "a" and "b" are the same 'encoding'.
5005 * Ignores difference between "ansi" and "latin1", "ucs-4" and "ucs-4be", etc.
5006 */
5007 static int
5008same_encoding(a, b)
5009 char_u *a;
5010 char_u *b;
5011{
5012 int f;
5013
5014 if (STRCMP(a, b) == 0)
5015 return TRUE;
5016 f = get_fio_flags(a);
5017 return (f != 0 && get_fio_flags(b) == f);
5018}
5019
5020/*
5021 * Check "ptr" for a unicode encoding and return the FIO_ flags needed for the
5022 * internal conversion.
5023 * if "ptr" is an empty string, use 'encoding'.
5024 */
5025 static int
5026get_fio_flags(ptr)
5027 char_u *ptr;
5028{
5029 int prop;
5030
5031 if (*ptr == NUL)
5032 ptr = p_enc;
5033
5034 prop = enc_canon_props(ptr);
5035 if (prop & ENC_UNICODE)
5036 {
5037 if (prop & ENC_2BYTE)
5038 {
5039 if (prop & ENC_ENDIAN_L)
5040 return FIO_UCS2 | FIO_ENDIAN_L;
5041 return FIO_UCS2;
5042 }
5043 if (prop & ENC_4BYTE)
5044 {
5045 if (prop & ENC_ENDIAN_L)
5046 return FIO_UCS4 | FIO_ENDIAN_L;
5047 return FIO_UCS4;
5048 }
5049 if (prop & ENC_2WORD)
5050 {
5051 if (prop & ENC_ENDIAN_L)
5052 return FIO_UTF16 | FIO_ENDIAN_L;
5053 return FIO_UTF16;
5054 }
5055 return FIO_UTF8;
5056 }
5057 if (prop & ENC_LATIN1)
5058 return FIO_LATIN1;
5059 /* must be ENC_DBCS, requires iconv() */
5060 return 0;
5061}
5062
5063#ifdef WIN3264
5064/*
5065 * Check "ptr" for a MS-Windows codepage name and return the FIO_ flags needed
5066 * for the conversion MS-Windows can do for us. Also accept "utf-8".
5067 * Used for conversion between 'encoding' and 'fileencoding'.
5068 */
5069 static int
5070get_win_fio_flags(ptr)
5071 char_u *ptr;
5072{
5073 int cp;
5074
5075 /* Cannot do this when 'encoding' is not utf-8 and not a codepage. */
5076 if (!enc_utf8 && enc_codepage <= 0)
5077 return 0;
5078
5079 cp = encname2codepage(ptr);
5080 if (cp == 0)
5081 {
5082# ifdef CP_UTF8 /* VC 4.1 doesn't define CP_UTF8 */
5083 if (STRCMP(ptr, "utf-8") == 0)
5084 cp = CP_UTF8;
5085 else
5086# endif
5087 return 0;
5088 }
5089 return FIO_PUT_CP(cp) | FIO_CODEPAGE;
5090}
5091#endif
5092
5093#ifdef MACOS_X
5094/*
5095 * Check "ptr" for a Carbon supported encoding and return the FIO_ flags
5096 * needed for the internal conversion to/from utf-8 or latin1.
5097 */
5098 static int
5099get_mac_fio_flags(ptr)
5100 char_u *ptr;
5101{
5102 if ((enc_utf8 || STRCMP(p_enc, "latin1") == 0)
5103 && (enc_canon_props(ptr) & ENC_MACROMAN))
5104 return FIO_MACROMAN;
5105 return 0;
5106}
5107#endif
5108
5109/*
5110 * Check for a Unicode BOM (Byte Order Mark) at the start of p[size].
5111 * "size" must be at least 2.
5112 * Return the name of the encoding and set "*lenp" to the length.
5113 * Returns NULL when no BOM found.
5114 */
5115 static char_u *
5116check_for_bom(p, size, lenp, flags)
5117 char_u *p;
5118 long size;
5119 int *lenp;
5120 int flags;
5121{
5122 char *name = NULL;
5123 int len = 2;
5124
5125 if (p[0] == 0xef && p[1] == 0xbb && size >= 3 && p[2] == 0xbf
5126 && (flags == FIO_ALL || flags == 0))
5127 {
5128 name = "utf-8"; /* EF BB BF */
5129 len = 3;
5130 }
5131 else if (p[0] == 0xff && p[1] == 0xfe)
5132 {
5133 if (size >= 4 && p[2] == 0 && p[3] == 0
5134 && (flags == FIO_ALL || flags == (FIO_UCS4 | FIO_ENDIAN_L)))
5135 {
5136 name = "ucs-4le"; /* FF FE 00 00 */
5137 len = 4;
5138 }
5139 else if (flags == FIO_ALL || flags == (FIO_UCS2 | FIO_ENDIAN_L))
5140 name = "ucs-2le"; /* FF FE */
5141 else if (flags == (FIO_UTF16 | FIO_ENDIAN_L))
5142 name = "utf-16le"; /* FF FE */
5143 }
5144 else if (p[0] == 0xfe && p[1] == 0xff
5145 && (flags == FIO_ALL || flags == FIO_UCS2 || flags == FIO_UTF16))
5146 {
5147 if (flags == FIO_UTF16)
5148 name = "utf-16"; /* FE FF */
5149 else
5150 name = "ucs-2"; /* FE FF */
5151 }
5152 else if (size >= 4 && p[0] == 0 && p[1] == 0 && p[2] == 0xfe
5153 && p[3] == 0xff && (flags == FIO_ALL || flags == FIO_UCS4))
5154 {
5155 name = "ucs-4"; /* 00 00 FE FF */
5156 len = 4;
5157 }
5158
5159 *lenp = len;
5160 return (char_u *)name;
5161}
5162
5163/*
5164 * Generate a BOM in "buf[4]" for encoding "name".
5165 * Return the length of the BOM (zero when no BOM).
5166 */
5167 static int
5168make_bom(buf, name)
5169 char_u *buf;
5170 char_u *name;
5171{
5172 int flags;
5173 char_u *p;
5174
5175 flags = get_fio_flags(name);
5176
5177 /* Can't put a BOM in a non-Unicode file. */
5178 if (flags == FIO_LATIN1 || flags == 0)
5179 return 0;
5180
5181 if (flags == FIO_UTF8) /* UTF-8 */
5182 {
5183 buf[0] = 0xef;
5184 buf[1] = 0xbb;
5185 buf[2] = 0xbf;
5186 return 3;
5187 }
5188 p = buf;
5189 (void)ucs2bytes(0xfeff, &p, flags);
5190 return (int)(p - buf);
5191}
5192#endif
5193
5194/*
5195 * Try to find a shortname by comparing the fullname with the current
5196 * directory.
5197 * Returns NULL if not shorter name possible, pointer into "full_path"
5198 * otherwise.
5199 */
5200 char_u *
5201shorten_fname(full_path, dir_name)
5202 char_u *full_path;
5203 char_u *dir_name;
5204{
5205 int len;
5206 char_u *p;
5207
5208 if (full_path == NULL)
5209 return NULL;
5210 len = (int)STRLEN(dir_name);
5211 if (fnamencmp(dir_name, full_path, len) == 0)
5212 {
5213 p = full_path + len;
5214#if defined(MSDOS) || defined(MSWIN) || defined(OS2)
5215 /*
5216 * MSDOS: when a file is in the root directory, dir_name will end in a
5217 * slash, since C: by itself does not define a specific dir. In this
5218 * case p may already be correct. <negri>
5219 */
5220 if (!((len > 2) && (*(p - 2) == ':')))
5221#endif
5222 {
5223 if (vim_ispathsep(*p))
5224 ++p;
5225#ifndef VMS /* the path separator is always part of the path */
5226 else
5227 p = NULL;
5228#endif
5229 }
5230 }
5231#if defined(MSDOS) || defined(MSWIN) || defined(OS2)
5232 /*
5233 * When using a file in the current drive, remove the drive name:
5234 * "A:\dir\file" -> "\dir\file". This helps when moving a session file on
5235 * a floppy from "A:\dir" to "B:\dir".
5236 */
5237 else if (len > 3
5238 && TOUPPER_LOC(full_path[0]) == TOUPPER_LOC(dir_name[0])
5239 && full_path[1] == ':'
5240 && vim_ispathsep(full_path[2]))
5241 p = full_path + 2;
5242#endif
5243 else
5244 p = NULL;
5245 return p;
5246}
5247
5248/*
5249 * Shorten filenames for all buffers.
5250 * When "force" is TRUE: Use full path from now on for files currently being
5251 * edited, both for file name and swap file name. Try to shorten the file
5252 * names a bit, if safe to do so.
5253 * When "force" is FALSE: Only try to shorten absolute file names.
5254 * For buffers that have buftype "nofile" or "scratch": never change the file
5255 * name.
5256 */
5257 void
5258shorten_fnames(force)
5259 int force;
5260{
5261 char_u dirname[MAXPATHL];
5262 buf_T *buf;
5263 char_u *p;
5264
5265 mch_dirname(dirname, MAXPATHL);
5266 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
5267 {
5268 if (buf->b_fname != NULL
5269#ifdef FEAT_QUICKFIX
5270 && !bt_nofile(buf)
5271#endif
5272 && !path_with_url(buf->b_fname)
5273 && (force
5274 || buf->b_sfname == NULL
5275 || mch_isFullName(buf->b_sfname)))
5276 {
5277 vim_free(buf->b_sfname);
5278 buf->b_sfname = NULL;
5279 p = shorten_fname(buf->b_ffname, dirname);
5280 if (p != NULL)
5281 {
5282 buf->b_sfname = vim_strsave(p);
5283 buf->b_fname = buf->b_sfname;
5284 }
5285 if (p == NULL || buf->b_fname == NULL)
5286 buf->b_fname = buf->b_ffname;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005287 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005288
5289 /* Always make the swap file name a full path, a "nofile" buffer may
5290 * also have a swap file. */
5291 mf_fullname(buf->b_ml.ml_mfp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005292 }
5293#ifdef FEAT_WINDOWS
5294 status_redraw_all();
5295#endif
5296}
5297
5298#if (defined(FEAT_DND) && defined(FEAT_GUI_GTK)) \
5299 || defined(FEAT_GUI_MSWIN) \
5300 || defined(FEAT_GUI_MAC) \
5301 || defined(PROTO)
5302/*
5303 * Shorten all filenames in "fnames[count]" by current directory.
5304 */
5305 void
5306shorten_filenames(fnames, count)
5307 char_u **fnames;
5308 int count;
5309{
5310 int i;
5311 char_u dirname[MAXPATHL];
5312 char_u *p;
5313
5314 if (fnames == NULL || count < 1)
5315 return;
5316 mch_dirname(dirname, sizeof(dirname));
5317 for (i = 0; i < count; ++i)
5318 {
5319 if ((p = shorten_fname(fnames[i], dirname)) != NULL)
5320 {
5321 /* shorten_fname() returns pointer in given "fnames[i]". If free
5322 * "fnames[i]" first, "p" becomes invalid. So we need to copy
5323 * "p" first then free fnames[i]. */
5324 p = vim_strsave(p);
5325 vim_free(fnames[i]);
5326 fnames[i] = p;
5327 }
5328 }
5329}
5330#endif
5331
5332/*
5333 * add extention to file name - change path/fo.o.h to path/fo.o.h.ext or
5334 * fo_o_h.ext for MSDOS or when shortname option set.
5335 *
5336 * Assumed that fname is a valid name found in the filesystem we assure that
5337 * the return value is a different name and ends in 'ext'.
5338 * "ext" MUST be at most 4 characters long if it starts with a dot, 3
5339 * characters otherwise.
5340 * Space for the returned name is allocated, must be freed later.
5341 * Returns NULL when out of memory.
5342 */
5343 char_u *
5344modname(fname, ext, prepend_dot)
5345 char_u *fname, *ext;
5346 int prepend_dot; /* may prepend a '.' to file name */
5347{
5348 return buf_modname(
5349#ifdef SHORT_FNAME
5350 TRUE,
5351#else
5352 (curbuf->b_p_sn || curbuf->b_shortname),
5353#endif
5354 fname, ext, prepend_dot);
5355}
5356
5357 char_u *
5358buf_modname(shortname, fname, ext, prepend_dot)
5359 int shortname; /* use 8.3 file name */
5360 char_u *fname, *ext;
5361 int prepend_dot; /* may prepend a '.' to file name */
5362{
5363 char_u *retval;
5364 char_u *s;
5365 char_u *e;
5366 char_u *ptr;
5367 int fnamelen, extlen;
5368
5369 extlen = (int)STRLEN(ext);
5370
5371 /*
5372 * If there is no file name we must get the name of the current directory
5373 * (we need the full path in case :cd is used).
5374 */
5375 if (fname == NULL || *fname == NUL)
5376 {
5377 retval = alloc((unsigned)(MAXPATHL + extlen + 3));
5378 if (retval == NULL)
5379 return NULL;
5380 if (mch_dirname(retval, MAXPATHL) == FAIL ||
5381 (fnamelen = (int)STRLEN(retval)) == 0)
5382 {
5383 vim_free(retval);
5384 return NULL;
5385 }
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00005386 if (!after_pathsep(retval, retval + fnamelen))
Bram Moolenaar071d4272004-06-13 20:20:40 +00005387 {
5388 retval[fnamelen++] = PATHSEP;
5389 retval[fnamelen] = NUL;
5390 }
5391#ifndef SHORT_FNAME
5392 prepend_dot = FALSE; /* nothing to prepend a dot to */
5393#endif
5394 }
5395 else
5396 {
5397 fnamelen = (int)STRLEN(fname);
5398 retval = alloc((unsigned)(fnamelen + extlen + 3));
5399 if (retval == NULL)
5400 return NULL;
5401 STRCPY(retval, fname);
5402#ifdef VMS
5403 vms_remove_version(retval); /* we do not need versions here */
5404#endif
5405 }
5406
5407 /*
5408 * search backwards until we hit a '/', '\' or ':' replacing all '.'
5409 * by '_' for MSDOS or when shortname option set and ext starts with a dot.
5410 * Then truncate what is after the '/', '\' or ':' to 8 characters for
5411 * MSDOS and 26 characters for AMIGA, a lot more for UNIX.
5412 */
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00005413 for (ptr = retval + fnamelen; ptr >= retval; mb_ptr_back(retval, ptr))
Bram Moolenaar071d4272004-06-13 20:20:40 +00005414 {
5415#ifndef RISCOS
5416 if (*ext == '.'
5417#ifdef USE_LONG_FNAME
5418 && (!USE_LONG_FNAME || shortname)
5419#else
5420# ifndef SHORT_FNAME
5421 && shortname
5422# endif
5423#endif
5424 )
5425 if (*ptr == '.') /* replace '.' by '_' */
5426 *ptr = '_';
5427#endif /* RISCOS */
5428 if (vim_ispathsep(*ptr))
5429 break;
5430 }
5431 ptr++;
5432
5433 /* the file name has at most BASENAMELEN characters. */
5434#ifndef SHORT_FNAME
5435 if (STRLEN(ptr) > (unsigned)BASENAMELEN)
5436 ptr[BASENAMELEN] = '\0';
5437#endif
5438
5439 s = ptr + STRLEN(ptr);
5440
5441 /*
5442 * For 8.3 file names we may have to reduce the length.
5443 */
5444#ifdef USE_LONG_FNAME
5445 if (!USE_LONG_FNAME || shortname)
5446#else
5447# ifndef SHORT_FNAME
5448 if (shortname)
5449# endif
5450#endif
5451 {
5452 /*
5453 * If there is no file name, or the file name ends in '/', and the
5454 * extension starts with '.', put a '_' before the dot, because just
5455 * ".ext" is invalid.
5456 */
5457 if (fname == NULL || *fname == NUL
5458 || vim_ispathsep(fname[STRLEN(fname) - 1]))
5459 {
5460#ifdef RISCOS
5461 if (*ext == '/')
5462#else
5463 if (*ext == '.')
5464#endif
5465 *s++ = '_';
5466 }
5467 /*
5468 * If the extension starts with '.', truncate the base name at 8
5469 * characters
5470 */
5471#ifdef RISCOS
5472 /* We normally use '/', but swap files are '_' */
5473 else if (*ext == '/' || *ext == '_')
5474#else
5475 else if (*ext == '.')
5476#endif
5477 {
5478 if (s - ptr > (size_t)8)
5479 {
5480 s = ptr + 8;
5481 *s = '\0';
5482 }
5483 }
5484 /*
5485 * If the extension doesn't start with '.', and the file name
5486 * doesn't have an extension yet, append a '.'
5487 */
5488#ifdef RISCOS
5489 else if ((e = vim_strchr(ptr, '/')) == NULL)
5490 *s++ = '/';
5491#else
5492 else if ((e = vim_strchr(ptr, '.')) == NULL)
5493 *s++ = '.';
5494#endif
5495 /*
5496 * If the extension doesn't start with '.', and there already is an
5497 * extension, it may need to be tructated
5498 */
5499 else if ((int)STRLEN(e) + extlen > 4)
5500 s = e + 4 - extlen;
5501 }
5502#if defined(OS2) || defined(USE_LONG_FNAME) || defined(WIN3264)
5503 /*
5504 * If there is no file name, and the extension starts with '.', put a
5505 * '_' before the dot, because just ".ext" may be invalid if it's on a
5506 * FAT partition, and on HPFS it doesn't matter.
5507 */
5508 else if ((fname == NULL || *fname == NUL) && *ext == '.')
5509 *s++ = '_';
5510#endif
5511
5512 /*
5513 * Append the extention.
5514 * ext can start with '.' and cannot exceed 3 more characters.
5515 */
5516 STRCPY(s, ext);
5517
5518#ifndef SHORT_FNAME
5519 /*
5520 * Prepend the dot.
5521 */
5522 if (prepend_dot && !shortname && *(e = gettail(retval)) !=
5523#ifdef RISCOS
5524 '/'
5525#else
5526 '.'
5527#endif
5528#ifdef USE_LONG_FNAME
5529 && USE_LONG_FNAME
5530#endif
5531 )
5532 {
5533 mch_memmove(e + 1, e, STRLEN(e) + 1);
5534#ifdef RISCOS
5535 *e = '/';
5536#else
5537 *e = '.';
5538#endif
5539 }
5540#endif
5541
5542 /*
5543 * Check that, after appending the extension, the file name is really
5544 * different.
5545 */
5546 if (fname != NULL && STRCMP(fname, retval) == 0)
5547 {
5548 /* we search for a character that can be replaced by '_' */
5549 while (--s >= ptr)
5550 {
5551 if (*s != '_')
5552 {
5553 *s = '_';
5554 break;
5555 }
5556 }
5557 if (s < ptr) /* fname was "________.<ext>", how tricky! */
5558 *ptr = 'v';
5559 }
5560 return retval;
5561}
5562
5563/*
5564 * Like fgets(), but if the file line is too long, it is truncated and the
5565 * rest of the line is thrown away. Returns TRUE for end-of-file.
5566 */
5567 int
5568vim_fgets(buf, size, fp)
5569 char_u *buf;
5570 int size;
5571 FILE *fp;
5572{
5573 char *eof;
5574#define FGETS_SIZE 200
5575 char tbuf[FGETS_SIZE];
5576
5577 buf[size - 2] = NUL;
5578#ifdef USE_CR
5579 eof = fgets_cr((char *)buf, size, fp);
5580#else
5581 eof = fgets((char *)buf, size, fp);
5582#endif
5583 if (buf[size - 2] != NUL && buf[size - 2] != '\n')
5584 {
5585 buf[size - 1] = NUL; /* Truncate the line */
5586
5587 /* Now throw away the rest of the line: */
5588 do
5589 {
5590 tbuf[FGETS_SIZE - 2] = NUL;
5591#ifdef USE_CR
5592 fgets_cr((char *)tbuf, FGETS_SIZE, fp);
5593#else
5594 fgets((char *)tbuf, FGETS_SIZE, fp);
5595#endif
5596 } while (tbuf[FGETS_SIZE - 2] != NUL && tbuf[FGETS_SIZE - 2] != '\n');
5597 }
5598 return (eof == NULL);
5599}
5600
5601#if defined(USE_CR) || defined(PROTO)
5602/*
5603 * Like vim_fgets(), but accept any line terminator: CR, CR-LF or LF.
5604 * Returns TRUE for end-of-file.
5605 * Only used for the Mac, because it's much slower than vim_fgets().
5606 */
5607 int
5608tag_fgets(buf, size, fp)
5609 char_u *buf;
5610 int size;
5611 FILE *fp;
5612{
5613 int i = 0;
5614 int c;
5615 int eof = FALSE;
5616
5617 for (;;)
5618 {
5619 c = fgetc(fp);
5620 if (c == EOF)
5621 {
5622 eof = TRUE;
5623 break;
5624 }
5625 if (c == '\r')
5626 {
5627 /* Always store a NL for end-of-line. */
5628 if (i < size - 1)
5629 buf[i++] = '\n';
5630 c = fgetc(fp);
5631 if (c != '\n') /* Macintosh format: single CR. */
5632 ungetc(c, fp);
5633 break;
5634 }
5635 if (i < size - 1)
5636 buf[i++] = c;
5637 if (c == '\n')
5638 break;
5639 }
5640 buf[i] = NUL;
5641 return eof;
5642}
5643#endif
5644
5645/*
5646 * rename() only works if both files are on the same file system, this
5647 * function will (attempts to?) copy the file across if rename fails -- webb
5648 * Return -1 for failure, 0 for success.
5649 */
5650 int
5651vim_rename(from, to)
5652 char_u *from;
5653 char_u *to;
5654{
5655 int fd_in;
5656 int fd_out;
5657 int n;
5658 char *errmsg = NULL;
5659 char *buffer;
5660#ifdef AMIGA
5661 BPTR flock;
5662#endif
5663 struct stat st;
5664
5665 /*
5666 * When the names are identical, there is nothing to do.
5667 */
5668 if (fnamecmp(from, to) == 0)
5669 return 0;
5670
5671 /*
5672 * Fail if the "from" file doesn't exist. Avoids that "to" is deleted.
5673 */
5674 if (mch_stat((char *)from, &st) < 0)
5675 return -1;
5676
5677 /*
5678 * Delete the "to" file, this is required on some systems to make the
5679 * mch_rename() work, on other systems it makes sure that we don't have
5680 * two files when the mch_rename() fails.
5681 */
5682
5683#ifdef AMIGA
5684 /*
5685 * With MSDOS-compatible filesystems (crossdos, messydos) it is possible
5686 * that the name of the "to" file is the same as the "from" file, even
5687 * though the names are different. To avoid the chance of accidently
5688 * deleting the "from" file (horror!) we lock it during the remove.
5689 *
5690 * When used for making a backup before writing the file: This should not
5691 * happen with ":w", because startscript() should detect this problem and
5692 * set buf->b_shortname, causing modname() to return a correct ".bak" file
5693 * name. This problem does exist with ":w filename", but then the
5694 * original file will be somewhere else so the backup isn't really
5695 * important. If autoscripting is off the rename may fail.
5696 */
5697 flock = Lock((UBYTE *)from, (long)ACCESS_READ);
5698#endif
5699 mch_remove(to);
5700#ifdef AMIGA
5701 if (flock)
5702 UnLock(flock);
5703#endif
5704
5705 /*
5706 * First try a normal rename, return if it works.
5707 */
5708 if (mch_rename((char *)from, (char *)to) == 0)
5709 return 0;
5710
5711 /*
5712 * Rename() failed, try copying the file.
5713 */
5714 fd_in = mch_open((char *)from, O_RDONLY|O_EXTRA, 0);
5715 if (fd_in == -1)
5716 return -1;
5717 fd_out = mch_open((char *)to, O_CREAT|O_EXCL|O_WRONLY|O_EXTRA, 0666);
5718 if (fd_out == -1)
5719 {
5720 close(fd_in);
5721 return -1;
5722 }
5723
5724 buffer = (char *)alloc(BUFSIZE);
5725 if (buffer == NULL)
5726 {
5727 close(fd_in);
5728 close(fd_out);
5729 return -1;
5730 }
5731
5732 while ((n = vim_read(fd_in, buffer, BUFSIZE)) > 0)
5733 if (vim_write(fd_out, buffer, n) != n)
5734 {
5735 errmsg = _("E208: Error writing to \"%s\"");
5736 break;
5737 }
5738
5739 vim_free(buffer);
5740 close(fd_in);
5741 if (close(fd_out) < 0)
5742 errmsg = _("E209: Error closing \"%s\"");
5743 if (n < 0)
5744 {
5745 errmsg = _("E210: Error reading \"%s\"");
5746 to = from;
5747 }
5748 if (errmsg != NULL)
5749 {
5750 EMSG2(errmsg, to);
5751 return -1;
5752 }
5753 mch_remove(from);
5754 return 0;
5755}
5756
5757static int already_warned = FALSE;
5758
5759/*
5760 * Check if any not hidden buffer has been changed.
5761 * Postpone the check if there are characters in the stuff buffer, a global
5762 * command is being executed, a mapping is being executed or an autocommand is
5763 * busy.
5764 * Returns TRUE if some message was written (screen should be redrawn and
5765 * cursor positioned).
5766 */
5767 int
5768check_timestamps(focus)
5769 int focus; /* called for GUI focus event */
5770{
5771 buf_T *buf;
5772 int didit = 0;
5773 int n;
5774
5775 /* Don't check timestamps while system() or another low-level function may
5776 * cause us to lose and gain focus. */
5777 if (no_check_timestamps > 0)
5778 return FALSE;
5779
5780 /* Avoid doing a check twice. The OK/Reload dialog can cause a focus
5781 * event and we would keep on checking if the file is steadily growing.
5782 * Do check again after typing something. */
5783 if (focus && did_check_timestamps)
5784 {
5785 need_check_timestamps = TRUE;
5786 return FALSE;
5787 }
5788
5789 if (!stuff_empty() || global_busy || !typebuf_typed()
5790#ifdef FEAT_AUTOCMD
5791 || autocmd_busy
5792#endif
5793 )
5794 need_check_timestamps = TRUE; /* check later */
5795 else
5796 {
5797 ++no_wait_return;
5798 did_check_timestamps = TRUE;
5799 already_warned = FALSE;
5800 for (buf = firstbuf; buf != NULL; )
5801 {
5802 /* Only check buffers in a window. */
5803 if (buf->b_nwindows > 0)
5804 {
5805 n = buf_check_timestamp(buf, focus);
5806 if (didit < n)
5807 didit = n;
5808 if (n > 0 && !buf_valid(buf))
5809 {
5810 /* Autocommands have removed the buffer, start at the
5811 * first one again. */
5812 buf = firstbuf;
5813 continue;
5814 }
5815 }
5816 buf = buf->b_next;
5817 }
5818 --no_wait_return;
5819 need_check_timestamps = FALSE;
5820 if (need_wait_return && didit == 2)
5821 {
5822 /* make sure msg isn't overwritten */
5823 msg_puts((char_u *)"\n");
5824 out_flush();
5825 }
5826 }
5827 return didit;
5828}
5829
5830/*
5831 * Move all the lines from buffer "frombuf" to buffer "tobuf".
5832 * Return OK or FAIL. When FAIL "tobuf" is incomplete and/or "frombuf" is not
5833 * empty.
5834 */
5835 static int
5836move_lines(frombuf, tobuf)
5837 buf_T *frombuf;
5838 buf_T *tobuf;
5839{
5840 buf_T *tbuf = curbuf;
5841 int retval = OK;
5842 linenr_T lnum;
5843 char_u *p;
5844
5845 /* Copy the lines in "frombuf" to "tobuf". */
5846 curbuf = tobuf;
5847 for (lnum = 1; lnum <= frombuf->b_ml.ml_line_count; ++lnum)
5848 {
5849 p = vim_strsave(ml_get_buf(frombuf, lnum, FALSE));
5850 if (p == NULL || ml_append(lnum - 1, p, 0, FALSE) == FAIL)
5851 {
5852 vim_free(p);
5853 retval = FAIL;
5854 break;
5855 }
5856 vim_free(p);
5857 }
5858
5859 /* Delete all the lines in "frombuf". */
5860 if (retval != FAIL)
5861 {
5862 curbuf = frombuf;
5863 while (!bufempty())
5864 if (ml_delete(curbuf->b_ml.ml_line_count, FALSE) == FAIL)
5865 {
5866 /* Oops! We could try putting back the saved lines, but that
5867 * might fail again... */
5868 retval = FAIL;
5869 break;
5870 }
5871 }
5872
5873 curbuf = tbuf;
5874 return retval;
5875}
5876
5877/*
5878 * Check if buffer "buf" has been changed.
5879 * Also check if the file for a new buffer unexpectedly appeared.
5880 * return 1 if a changed buffer was found.
5881 * return 2 if a message has been displayed.
5882 * return 0 otherwise.
5883 */
5884/*ARGSUSED*/
5885 int
5886buf_check_timestamp(buf, focus)
5887 buf_T *buf;
5888 int focus; /* called for GUI focus event */
5889{
5890 struct stat st;
5891 int stat_res;
5892 int retval = 0;
5893 char_u *path;
5894 char_u *tbuf;
5895 char *mesg = NULL;
5896 char *mesg2;
5897 int helpmesg = FALSE;
5898 int reload = FALSE;
5899#if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
5900 int can_reload = FALSE;
5901#endif
5902 size_t orig_size = buf->b_orig_size;
5903 int orig_mode = buf->b_orig_mode;
5904#ifdef FEAT_GUI
5905 int save_mouse_correct = need_mouse_correct;
5906#endif
5907#ifdef FEAT_AUTOCMD
5908 static int busy = FALSE;
5909#endif
5910
5911 /* If there is no file name, the buffer is not loaded, 'buftype' is
5912 * set, we are in the middle of a save or being called recursively: ignore
5913 * this buffer. */
5914 if (buf->b_ffname == NULL
5915 || buf->b_ml.ml_mfp == NULL
5916#if defined(FEAT_QUICKFIX)
5917 || *buf->b_p_bt != NUL
5918#endif
5919 || buf->b_saving
5920#ifdef FEAT_AUTOCMD
5921 || busy
5922#endif
Bram Moolenaar009b2592004-10-24 19:18:58 +00005923#ifdef FEAT_NETBEANS_INTG
5924 || isNetbeansBuffer(buf)
5925#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005926 )
5927 return 0;
5928
5929 if ( !(buf->b_flags & BF_NOTEDITED)
5930 && buf->b_mtime != 0
5931 && ((stat_res = mch_stat((char *)buf->b_ffname, &st)) < 0
5932 || time_differs((long)st.st_mtime, buf->b_mtime)
5933#ifdef HAVE_ST_MODE
5934 || (int)st.st_mode != buf->b_orig_mode
5935#else
5936 || mch_getperm(buf->b_ffname) != buf->b_orig_mode
5937#endif
5938 ))
5939 {
5940 retval = 1;
5941
5942 /* set b_mtime to stop further warnings */
5943 if (stat_res < 0)
5944 {
5945 buf->b_mtime = 0;
5946 buf->b_orig_size = 0;
5947 buf->b_orig_mode = 0;
5948 }
5949 else
5950 buf_store_time(buf, &st, buf->b_ffname);
5951
5952 /* Don't do anything for a directory. Might contain the file
5953 * explorer. */
5954 if (mch_isdir(buf->b_fname))
5955 ;
5956
5957 /*
5958 * If 'autoread' is set, the buffer has no changes and the file still
5959 * exists, reload the buffer. Use the buffer-local option value if it
5960 * was set, the global option value otherwise.
5961 */
5962 else if ((buf->b_p_ar >= 0 ? buf->b_p_ar : p_ar)
5963 && !bufIsChanged(buf) && stat_res >= 0)
5964 reload = TRUE;
5965 else
5966 {
5967#ifdef FEAT_AUTOCMD
5968 int n;
5969
5970 /*
5971 * Only give the warning if there are no FileChangedShell
5972 * autocommands.
5973 * Avoid being called recursively by setting "busy".
5974 */
5975 busy = TRUE;
5976 n = apply_autocmds(EVENT_FILECHANGEDSHELL,
5977 buf->b_fname, buf->b_fname, FALSE, buf);
5978 busy = FALSE;
5979 if (n)
5980 {
5981 if (!buf_valid(buf))
5982 EMSG(_("E246: FileChangedShell autocommand deleted buffer"));
5983 return 2;
5984 }
5985 else
5986#endif
5987 {
5988 if (stat_res < 0)
5989 mesg = _("E211: Warning: File \"%s\" no longer available");
5990 else
5991 {
5992 helpmesg = TRUE;
5993#if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
5994 can_reload = TRUE;
5995#endif
5996 /*
5997 * Check if the file contents really changed to avoid
5998 * giving a warning when only the timestamp was set (e.g.,
5999 * checked out of CVS). Always warn when the buffer was
6000 * changed.
6001 */
6002 if (bufIsChanged(buf))
6003 mesg = _("W12: Warning: File \"%s\" has changed and the buffer was changed in Vim as well");
6004 else if (orig_size != buf->b_orig_size
6005 || buf_contents_changed(buf))
6006 mesg = _("W11: Warning: File \"%s\" has changed since editing started");
6007 else if (orig_mode != buf->b_orig_mode)
6008 mesg = _("W16: Warning: Mode of file \"%s\" has changed since editing started");
6009 }
6010 }
6011 }
6012
6013 }
6014 else if ((buf->b_flags & BF_NEW) && !(buf->b_flags & BF_NEW_W)
6015 && vim_fexists(buf->b_ffname))
6016 {
6017 retval = 1;
6018 mesg = _("W13: Warning: File \"%s\" has been created after editing started");
6019 buf->b_flags |= BF_NEW_W;
6020#if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
6021 can_reload = TRUE;
6022#endif
6023 }
6024
6025 if (mesg != NULL)
6026 {
6027 path = home_replace_save(buf, buf->b_fname);
6028 if (path != NULL)
6029 {
6030 if (helpmesg)
6031 mesg2 = _("See \":help W11\" for more info.");
6032 else
6033 mesg2 = "";
6034 tbuf = alloc((unsigned)(STRLEN(path) + STRLEN(mesg)
6035 + STRLEN(mesg2) + 2));
6036 sprintf((char *)tbuf, mesg, path);
6037#if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
6038 if (can_reload)
6039 {
6040 if (*mesg2 != NUL)
6041 {
6042 STRCAT(tbuf, "\n");
6043 STRCAT(tbuf, mesg2);
6044 }
6045 if (do_dialog(VIM_WARNING, (char_u *)_("Warning"), tbuf,
6046 (char_u *)_("&OK\n&Load File"), 1, NULL) == 2)
6047 reload = TRUE;
6048 }
6049 else
6050#endif
6051 if (State > NORMAL_BUSY || (State & CMDLINE) || already_warned)
6052 {
6053 if (*mesg2 != NUL)
6054 {
6055 STRCAT(tbuf, "; ");
6056 STRCAT(tbuf, mesg2);
6057 }
6058 EMSG(tbuf);
6059 retval = 2;
6060 }
6061 else
6062 {
Bram Moolenaared203462004-06-16 11:19:22 +00006063# ifdef FEAT_AUTOCMD
Bram Moolenaar071d4272004-06-13 20:20:40 +00006064 if (!autocmd_busy)
Bram Moolenaared203462004-06-16 11:19:22 +00006065# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006066 {
6067 msg_start();
6068 msg_puts_attr(tbuf, hl_attr(HLF_E) + MSG_HIST);
6069 if (*mesg2 != NUL)
6070 msg_puts_attr((char_u *)mesg2,
6071 hl_attr(HLF_W) + MSG_HIST);
6072 msg_clr_eos();
6073 (void)msg_end();
6074 if (emsg_silent == 0)
6075 {
6076 out_flush();
Bram Moolenaared203462004-06-16 11:19:22 +00006077# ifdef FEAT_GUI
Bram Moolenaar071d4272004-06-13 20:20:40 +00006078 if (!focus)
Bram Moolenaared203462004-06-16 11:19:22 +00006079# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006080 /* give the user some time to think about it */
6081 ui_delay(1000L, TRUE);
6082
6083 /* don't redraw and erase the message */
6084 redraw_cmdline = FALSE;
6085 }
6086 }
6087 already_warned = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006088 }
6089
6090 vim_free(path);
6091 vim_free(tbuf);
6092 }
6093 }
6094
6095 if (reload)
6096 {
6097 exarg_T ea;
6098 pos_T old_cursor;
6099 linenr_T old_topline;
6100 int old_ro = buf->b_p_ro;
6101 buf_T *savebuf;
6102 int saved = OK;
6103#ifdef FEAT_AUTOCMD
6104 aco_save_T aco;
6105
6106 /* set curwin/curbuf for "buf" and save some things */
6107 aucmd_prepbuf(&aco, buf);
6108#else
6109 buf_T *save_curbuf = curbuf;
6110
6111 curbuf = buf;
6112 curwin->w_buffer = buf;
6113#endif
6114
6115 /* We only want to read the text from the file, not reset the syntax
6116 * highlighting, clear marks, diff status, etc. Force the fileformat
6117 * and encoding to be the same. */
6118 if (prep_exarg(&ea, buf) == OK)
6119 {
6120 old_cursor = curwin->w_cursor;
6121 old_topline = curwin->w_topline;
6122
6123 /*
6124 * To behave like when a new file is edited (matters for
6125 * BufReadPost autocommands) we first need to delete the current
6126 * buffer contents. But if reading the file fails we should keep
6127 * the old contents. Can't use memory only, the file might be
6128 * too big. Use a hidden buffer to move the buffer contents to.
6129 */
6130 if (bufempty())
6131 savebuf = NULL;
6132 else
6133 {
6134 /* Allocate a buffer without putting it in the buffer list. */
6135 savebuf = buflist_new(NULL, NULL, (linenr_T)1, BLN_DUMMY);
6136 if (savebuf != NULL)
6137 {
6138 /* Open the memline. */
6139 curbuf = savebuf;
6140 curwin->w_buffer = savebuf;
6141 saved = ml_open();
6142 curbuf = buf;
6143 curwin->w_buffer = buf;
6144 }
6145 if (savebuf == NULL || saved == FAIL
6146 || move_lines(buf, savebuf) == FAIL)
6147 {
6148 EMSG2(_("E462: Could not prepare for reloading \"%s\""),
6149 buf->b_fname);
6150 saved = FAIL;
6151 }
6152 }
6153
6154 if (saved == OK)
6155 {
6156 curbuf->b_flags |= BF_CHECK_RO; /* check for RO again */
6157#ifdef FEAT_AUTOCMD
6158 keep_filetype = TRUE; /* don't detect 'filetype' */
6159#endif
6160 if (readfile(buf->b_ffname, buf->b_fname, (linenr_T)0,
6161 (linenr_T)0,
6162 (linenr_T)MAXLNUM, &ea, READ_NEW) == FAIL)
6163 {
6164#if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
6165 if (!aborting())
6166#endif
6167 EMSG2(_("E321: Could not reload \"%s\""), buf->b_fname);
6168 if (savebuf != NULL)
6169 {
6170 /* Put the text back from the save buffer. First
6171 * delete any lines that readfile() added. */
6172 while (!bufempty())
6173 if (ml_delete(curbuf->b_ml.ml_line_count, FALSE)
6174 == FAIL)
6175 break;
6176 (void)move_lines(savebuf, buf);
6177 }
6178 }
6179 else
6180 {
6181 /* Mark the buffer as unmodified and free undo info. */
6182 unchanged(buf, TRUE);
6183 u_blockfree(buf);
6184 u_clearall(buf);
6185 }
6186 }
6187 vim_free(ea.cmd);
6188
6189 if (savebuf != NULL)
6190 wipe_buffer(savebuf, FALSE);
6191
6192#ifdef FEAT_DIFF
6193 /* Invalidate diff info if necessary. */
6194 diff_invalidate();
6195#endif
6196
6197 /* Restore the topline and cursor position and check it (lines may
6198 * have been removed). */
6199 if (old_topline > curbuf->b_ml.ml_line_count)
6200 curwin->w_topline = curbuf->b_ml.ml_line_count;
6201 else
6202 curwin->w_topline = old_topline;
6203 curwin->w_cursor = old_cursor;
6204 check_cursor();
6205 update_topline();
6206#ifdef FEAT_AUTOCMD
6207 keep_filetype = FALSE;
6208#endif
6209#ifdef FEAT_FOLDING
6210 {
6211 win_T *wp;
6212
6213 /* Update folds unless they are defined manually. */
6214 FOR_ALL_WINDOWS(wp)
6215 if (wp->w_buffer == curwin->w_buffer
6216 && !foldmethodIsManual(wp))
6217 foldUpdateAll(wp);
6218 }
6219#endif
6220 /* If the mode didn't change and 'readonly' was set, keep the old
6221 * value; the user probably used the ":view" command. But don't
6222 * reset it, might have had a read error. */
6223 if (orig_mode == curbuf->b_orig_mode)
6224 curbuf->b_p_ro |= old_ro;
6225 }
6226
6227#ifdef FEAT_AUTOCMD
6228 /* restore curwin/curbuf and a few other things */
6229 aucmd_restbuf(&aco);
6230 /* Careful: autocommands may have made "buf" invalid! */
6231#else
6232 curwin->w_buffer = save_curbuf;
6233 curbuf = save_curbuf;
6234#endif
6235 }
6236
6237#ifdef FEAT_GUI
6238 /* restore this in case an autocommand has set it; it would break
6239 * 'mousefocus' */
6240 need_mouse_correct = save_mouse_correct;
6241#endif
6242
6243 return retval;
6244}
6245
6246/*ARGSUSED*/
6247 void
6248buf_store_time(buf, st, fname)
6249 buf_T *buf;
6250 struct stat *st;
6251 char_u *fname;
6252{
6253 buf->b_mtime = (long)st->st_mtime;
6254 buf->b_orig_size = (size_t)st->st_size;
6255#ifdef HAVE_ST_MODE
6256 buf->b_orig_mode = (int)st->st_mode;
6257#else
6258 buf->b_orig_mode = mch_getperm(fname);
6259#endif
6260}
6261
6262/*
6263 * Adjust the line with missing eol, used for the next write.
6264 * Used for do_filter(), when the input lines for the filter are deleted.
6265 */
6266 void
6267write_lnum_adjust(offset)
6268 linenr_T offset;
6269{
6270 if (write_no_eol_lnum) /* only if there is a missing eol */
6271 write_no_eol_lnum += offset;
6272}
6273
6274#if defined(TEMPDIRNAMES) || defined(PROTO)
6275static long temp_count = 0; /* Temp filename counter. */
6276
6277/*
6278 * Delete the temp directory and all files it contains.
6279 */
6280 void
6281vim_deltempdir()
6282{
6283 char_u **files;
6284 int file_count;
6285 int i;
6286
6287 if (vim_tempdir != NULL)
6288 {
6289 sprintf((char *)NameBuff, "%s*", vim_tempdir);
6290 if (gen_expand_wildcards(1, &NameBuff, &file_count, &files,
6291 EW_DIR|EW_FILE|EW_SILENT) == OK)
6292 {
6293 for (i = 0; i < file_count; ++i)
6294 mch_remove(files[i]);
6295 FreeWild(file_count, files);
6296 }
6297 gettail(NameBuff)[-1] = NUL;
6298 (void)mch_rmdir(NameBuff);
6299
6300 vim_free(vim_tempdir);
6301 vim_tempdir = NULL;
6302 }
6303}
6304#endif
6305
6306/*
6307 * vim_tempname(): Return a unique name that can be used for a temp file.
6308 *
6309 * The temp file is NOT created.
6310 *
6311 * The returned pointer is to allocated memory.
6312 * The returned pointer is NULL if no valid name was found.
6313 */
6314/*ARGSUSED*/
6315 char_u *
6316vim_tempname(extra_char)
6317 int extra_char; /* character to use in the name instead of '?' */
6318{
6319#ifdef USE_TMPNAM
6320 char_u itmp[L_tmpnam]; /* use tmpnam() */
6321#else
6322 char_u itmp[TEMPNAMELEN];
6323#endif
6324
6325#ifdef TEMPDIRNAMES
6326 static char *(tempdirs[]) = {TEMPDIRNAMES};
6327 int i;
6328 long nr;
6329 long off;
6330# ifndef EEXIST
6331 struct stat st;
6332# endif
6333
6334 /*
6335 * This will create a directory for private use by this instance of Vim.
6336 * This is done once, and the same directory is used for all temp files.
6337 * This method avoids security problems because of symlink attacks et al.
6338 * It's also a bit faster, because we only need to check for an existing
6339 * file when creating the directory and not for each temp file.
6340 */
6341 if (vim_tempdir == NULL)
6342 {
6343 /*
6344 * Try the entries in TEMPDIRNAMES to create the temp directory.
6345 */
6346 for (i = 0; i < sizeof(tempdirs) / sizeof(char *); ++i)
6347 {
6348 /* expand $TMP, leave room for "/v1100000/999999999" */
6349 expand_env((char_u *)tempdirs[i], itmp, TEMPNAMELEN - 20);
6350 if (mch_isdir(itmp)) /* directory exists */
6351 {
6352# ifdef __EMX__
6353 /* If $TMP contains a forward slash (perhaps using bash or
6354 * tcsh), don't add a backslash, use a forward slash!
6355 * Adding 2 backslashes didn't work. */
6356 if (vim_strchr(itmp, '/') != NULL)
6357 STRCAT(itmp, "/");
6358 else
6359# endif
6360 add_pathsep(itmp);
6361
6362 /* Get an arbitrary number of up to 6 digits. When it's
6363 * unlikely that it already exists it will be faster,
6364 * otherwise it doesn't matter. The use of mkdir() avoids any
6365 * security problems because of the predictable number. */
6366 nr = (mch_get_pid() + (long)time(NULL)) % 1000000L;
6367
6368 /* Try up to 10000 different values until we find a name that
6369 * doesn't exist. */
6370 for (off = 0; off < 10000L; ++off)
6371 {
6372 int r;
6373#if defined(UNIX) || defined(VMS)
6374 mode_t umask_save;
6375#endif
6376
6377 sprintf((char *)itmp + STRLEN(itmp), "v%ld", nr + off);
6378# ifndef EEXIST
6379 /* If mkdir() does not set errno to EEXIST, check for
6380 * existing file here. There is a race condition then,
6381 * although it's fail-safe. */
6382 if (mch_stat((char *)itmp, &st) >= 0)
6383 continue;
6384# endif
6385#if defined(UNIX) || defined(VMS)
6386 /* Make sure the umask doesn't remove the executable bit.
6387 * "repl" has been reported to use "177". */
6388 umask_save = umask(077);
6389#endif
6390 r = vim_mkdir(itmp, 0700);
6391#if defined(UNIX) || defined(VMS)
6392 (void)umask(umask_save);
6393#endif
6394 if (r == 0)
6395 {
6396 char_u *buf;
6397
6398 /* Directory was created, use this name.
6399 * Expand to full path; When using the current
6400 * directory a ":cd" would confuse us. */
6401 buf = alloc((unsigned)MAXPATHL + 1);
6402 if (buf != NULL)
6403 {
6404 if (vim_FullName(itmp, buf, MAXPATHL, FALSE)
6405 == FAIL)
6406 STRCPY(buf, itmp);
6407# ifdef __EMX__
6408 if (vim_strchr(buf, '/') != NULL)
6409 STRCAT(buf, "/");
6410 else
6411# endif
6412 add_pathsep(buf);
6413 vim_tempdir = vim_strsave(buf);
6414 vim_free(buf);
6415 }
6416 break;
6417 }
6418# ifdef EEXIST
6419 /* If the mkdir() didn't fail because the file/dir exists,
6420 * we probably can't create any dir here, try another
6421 * place. */
6422 if (errno != EEXIST)
6423# endif
6424 break;
6425 }
6426 if (vim_tempdir != NULL)
6427 break;
6428 }
6429 }
6430 }
6431
6432 if (vim_tempdir != NULL)
6433 {
6434 /* There is no need to check if the file exists, because we own the
6435 * directory and nobody else creates a file in it. */
6436 sprintf((char *)itmp, "%s%ld", vim_tempdir, temp_count++);
6437 return vim_strsave(itmp);
6438 }
6439
6440 return NULL;
6441
6442#else /* TEMPDIRNAMES */
6443
6444# ifdef WIN3264
6445 char szTempFile[_MAX_PATH + 1];
6446 char buf4[4];
6447 char_u *retval;
6448 char_u *p;
6449
6450 STRCPY(itmp, "");
6451 if (GetTempPath(_MAX_PATH, szTempFile) == 0)
6452 szTempFile[0] = NUL; /* GetTempPath() failed, use current dir */
6453 strcpy(buf4, "VIM");
6454 buf4[2] = extra_char; /* make it "VIa", "VIb", etc. */
6455 if (GetTempFileName(szTempFile, buf4, 0, itmp) == 0)
6456 return NULL;
6457 /* GetTempFileName() will create the file, we don't want that */
6458 (void)DeleteFile(itmp);
6459
6460 /* Backslashes in a temp file name cause problems when filtering with
6461 * "sh". NOTE: This also checks 'shellcmdflag' to help those people who
6462 * didn't set 'shellslash'. */
6463 retval = vim_strsave(itmp);
6464 if (*p_shcf == '-' || p_ssl)
6465 for (p = retval; *p; ++p)
6466 if (*p == '\\')
6467 *p = '/';
6468 return retval;
6469
6470# else /* WIN3264 */
6471
6472# ifdef USE_TMPNAM
6473 /* tmpnam() will make its own name */
6474 if (*tmpnam((char *)itmp) == NUL)
6475 return NULL;
6476# else
6477 char_u *p;
6478
6479# ifdef VMS_TEMPNAM
6480 /* mktemp() is not working on VMS. It seems to be
6481 * a do-nothing function. Therefore we use tempnam().
6482 */
6483 sprintf((char *)itmp, "VIM%c", extra_char);
6484 p = (char_u *)tempnam("tmp:", (char *)itmp);
6485 if (p != NULL)
6486 {
6487 /* VMS will use '.LOG' if we don't explicitly specify an extension,
6488 * and VIM will then be unable to find the file later */
6489 STRCPY(itmp, p);
6490 STRCAT(itmp, ".txt");
6491 free(p);
6492 }
6493 else
6494 return NULL;
6495# else
6496 STRCPY(itmp, TEMPNAME);
6497 if ((p = vim_strchr(itmp, '?')) != NULL)
6498 *p = extra_char;
6499 if (mktemp((char *)itmp) == NULL)
6500 return NULL;
6501# endif
6502# endif
6503
6504 return vim_strsave(itmp);
6505# endif /* WIN3264 */
6506#endif /* TEMPDIRNAMES */
6507}
6508
6509#if defined(BACKSLASH_IN_FILENAME) || defined(PROTO)
6510/*
6511 * Convert all backslashes in fname to forward slashes in-place.
6512 */
6513 void
6514forward_slash(fname)
6515 char_u *fname;
6516{
6517 char_u *p;
6518
6519 for (p = fname; *p != NUL; ++p)
6520# ifdef FEAT_MBYTE
6521 /* The Big5 encoding can have '\' in the trail byte. */
6522 if (enc_dbcs != 0 && (*mb_ptr2len_check)(p) > 1)
6523 ++p;
6524 else
6525# endif
6526 if (*p == '\\')
6527 *p = '/';
6528}
6529#endif
6530
6531
6532/*
6533 * Code for automatic commands.
6534 *
6535 * Only included when "FEAT_AUTOCMD" has been defined.
6536 */
6537
6538#if defined(FEAT_AUTOCMD) || defined(PROTO)
6539
6540/*
6541 * The autocommands are stored in a list for each event.
6542 * Autocommands for the same pattern, that are consecutive, are joined
6543 * together, to avoid having to match the pattern too often.
6544 * The result is an array of Autopat lists, which point to AutoCmd lists:
6545 *
6546 * first_autopat[0] --> Autopat.next --> Autopat.next --> NULL
6547 * Autopat.cmds Autopat.cmds
6548 * | |
6549 * V V
6550 * AutoCmd.next AutoCmd.next
6551 * | |
6552 * V V
6553 * AutoCmd.next NULL
6554 * |
6555 * V
6556 * NULL
6557 *
6558 * first_autopat[1] --> Autopat.next --> NULL
6559 * Autopat.cmds
6560 * |
6561 * V
6562 * AutoCmd.next
6563 * |
6564 * V
6565 * NULL
6566 * etc.
6567 *
6568 * The order of AutoCmds is important, this is the order in which they were
6569 * defined and will have to be executed.
6570 */
6571typedef struct AutoCmd
6572{
6573 char_u *cmd; /* The command to be executed (NULL
6574 when command has been removed) */
6575 char nested; /* If autocommands nest here */
6576 char last; /* last command in list */
6577#ifdef FEAT_EVAL
6578 scid_T scriptID; /* script ID where defined */
6579#endif
6580 struct AutoCmd *next; /* Next AutoCmd in list */
6581} AutoCmd;
6582
6583typedef struct AutoPat
6584{
6585 int group; /* group ID */
6586 char_u *pat; /* pattern as typed (NULL when pattern
6587 has been removed) */
6588 int patlen; /* strlen() of pat */
Bram Moolenaar748bf032005-02-02 23:04:36 +00006589 regprog_T *reg_prog; /* compiled regprog for pattern */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006590 char allow_dirs; /* Pattern may match whole path */
6591 char last; /* last pattern for apply_autocmds() */
6592 AutoCmd *cmds; /* list of commands to do */
6593 struct AutoPat *next; /* next AutoPat in AutoPat list */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00006594 int buflocal_nr; /* !=0 for buffer-local AutoPat */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006595} AutoPat;
6596
6597static struct event_name
6598{
6599 char *name; /* event name */
6600 EVENT_T event; /* event number */
6601} event_names[] =
6602{
6603 {"BufAdd", EVENT_BUFADD},
6604 {"BufCreate", EVENT_BUFADD},
6605 {"BufDelete", EVENT_BUFDELETE},
6606 {"BufEnter", EVENT_BUFENTER},
6607 {"BufFilePost", EVENT_BUFFILEPOST},
6608 {"BufFilePre", EVENT_BUFFILEPRE},
6609 {"BufHidden", EVENT_BUFHIDDEN},
6610 {"BufLeave", EVENT_BUFLEAVE},
6611 {"BufNew", EVENT_BUFNEW},
6612 {"BufNewFile", EVENT_BUFNEWFILE},
6613 {"BufRead", EVENT_BUFREADPOST},
6614 {"BufReadCmd", EVENT_BUFREADCMD},
6615 {"BufReadPost", EVENT_BUFREADPOST},
6616 {"BufReadPre", EVENT_BUFREADPRE},
6617 {"BufUnload", EVENT_BUFUNLOAD},
6618 {"BufWinEnter", EVENT_BUFWINENTER},
6619 {"BufWinLeave", EVENT_BUFWINLEAVE},
6620 {"BufWipeout", EVENT_BUFWIPEOUT},
6621 {"BufWrite", EVENT_BUFWRITEPRE},
6622 {"BufWritePost", EVENT_BUFWRITEPOST},
6623 {"BufWritePre", EVENT_BUFWRITEPRE},
6624 {"BufWriteCmd", EVENT_BUFWRITECMD},
6625 {"CmdwinEnter", EVENT_CMDWINENTER},
6626 {"CmdwinLeave", EVENT_CMDWINLEAVE},
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00006627 {"ColorScheme", EVENT_COLORSCHEME},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006628 {"EncodingChanged", EVENT_ENCODINGCHANGED},
6629 {"FileEncoding", EVENT_ENCODINGCHANGED},
6630 {"CursorHold", EVENT_CURSORHOLD},
6631 {"FileAppendPost", EVENT_FILEAPPENDPOST},
6632 {"FileAppendPre", EVENT_FILEAPPENDPRE},
6633 {"FileAppendCmd", EVENT_FILEAPPENDCMD},
6634 {"FileChangedShell",EVENT_FILECHANGEDSHELL},
6635 {"FileChangedRO", EVENT_FILECHANGEDRO},
6636 {"FileReadPost", EVENT_FILEREADPOST},
6637 {"FileReadPre", EVENT_FILEREADPRE},
6638 {"FileReadCmd", EVENT_FILEREADCMD},
6639 {"FileType", EVENT_FILETYPE},
6640 {"FileWritePost", EVENT_FILEWRITEPOST},
6641 {"FileWritePre", EVENT_FILEWRITEPRE},
6642 {"FileWriteCmd", EVENT_FILEWRITECMD},
6643 {"FilterReadPost", EVENT_FILTERREADPOST},
6644 {"FilterReadPre", EVENT_FILTERREADPRE},
6645 {"FilterWritePost", EVENT_FILTERWRITEPOST},
6646 {"FilterWritePre", EVENT_FILTERWRITEPRE},
6647 {"FocusGained", EVENT_FOCUSGAINED},
6648 {"FocusLost", EVENT_FOCUSLOST},
6649 {"FuncUndefined", EVENT_FUNCUNDEFINED},
6650 {"GUIEnter", EVENT_GUIENTER},
Bram Moolenaar843ee412004-06-30 16:16:41 +00006651 {"InsertChange", EVENT_INSERTCHANGE},
6652 {"InsertEnter", EVENT_INSERTENTER},
6653 {"InsertLeave", EVENT_INSERTLEAVE},
Bram Moolenaar7c626922005-02-07 22:01:03 +00006654 {"QuickFixCmdPost", EVENT_QUICKFIXCMDPOST},
6655 {"QuickFixCmdPre", EVENT_QUICKFIXCMDPRE},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006656 {"RemoteReply", EVENT_REMOTEREPLY},
6657 {"StdinReadPost", EVENT_STDINREADPOST},
6658 {"StdinReadPre", EVENT_STDINREADPRE},
6659 {"Syntax", EVENT_SYNTAX},
6660 {"TermChanged", EVENT_TERMCHANGED},
6661 {"TermResponse", EVENT_TERMRESPONSE},
6662 {"User", EVENT_USER},
6663 {"VimEnter", EVENT_VIMENTER},
6664 {"VimLeave", EVENT_VIMLEAVE},
6665 {"VimLeavePre", EVENT_VIMLEAVEPRE},
6666 {"WinEnter", EVENT_WINENTER},
6667 {"WinLeave", EVENT_WINLEAVE},
6668 {NULL, (EVENT_T)0}
6669};
6670
6671static AutoPat *first_autopat[NUM_EVENTS] =
6672{
6673 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
6674 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
6675 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
6676 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00006677 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
6678 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
Bram Moolenaar071d4272004-06-13 20:20:40 +00006679};
6680
6681/*
6682 * struct used to keep status while executing autocommands for an event.
6683 */
6684typedef struct AutoPatCmd
6685{
6686 AutoPat *curpat; /* next AutoPat to examine */
6687 AutoCmd *nextcmd; /* next AutoCmd to execute */
6688 int group; /* group being used */
6689 char_u *fname; /* fname to match with */
6690 char_u *sfname; /* sfname to match with */
6691 char_u *tail; /* tail of fname */
6692 EVENT_T event; /* current event */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00006693 int arg_bufnr; /* initially equal to <abuf>, set to zero when
6694 buf is deleted */
6695 struct AutoPatCmd *next; /* chain of active apc-s for auto-invalidation*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00006696} AutoPatCmd;
6697
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00006698AutoPatCmd *active_apc_list = NULL; /* stack of active autocommands */
6699
Bram Moolenaar071d4272004-06-13 20:20:40 +00006700/*
6701 * augroups stores a list of autocmd group names.
6702 */
6703garray_T augroups = {0, 0, sizeof(char_u *), 10, NULL};
6704#define AUGROUP_NAME(i) (((char_u **)augroups.ga_data)[i])
6705
6706/*
6707 * The ID of the current group. Group 0 is the default one.
6708 */
6709#define AUGROUP_DEFAULT -1 /* default autocmd group */
6710#define AUGROUP_ERROR -2 /* errornouse autocmd group */
6711#define AUGROUP_ALL -3 /* all autocmd groups */
6712static int current_augroup = AUGROUP_DEFAULT;
6713
6714static int au_need_clean = FALSE; /* need to delete marked patterns */
6715
6716static void show_autocmd __ARGS((AutoPat *ap, EVENT_T event));
6717static void au_remove_pat __ARGS((AutoPat *ap));
6718static void au_remove_cmds __ARGS((AutoPat *ap));
6719static void au_cleanup __ARGS((void));
6720static int au_new_group __ARGS((char_u *name));
6721static void au_del_group __ARGS((char_u *name));
6722static int au_find_group __ARGS((char_u *name));
6723static EVENT_T event_name2nr __ARGS((char_u *start, char_u **end));
6724static char_u *event_nr2name __ARGS((EVENT_T event));
6725static char_u *find_end_event __ARGS((char_u *arg, int have_group));
6726static int event_ignored __ARGS((EVENT_T event));
6727static int au_get_grouparg __ARGS((char_u **argp));
6728static int do_autocmd_event __ARGS((EVENT_T event, char_u *pat, int nested, char_u *cmd, int forceit, int group));
6729static char_u *getnextac __ARGS((int c, void *cookie, int indent));
6730static 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));
6731static void auto_next_pat __ARGS((AutoPatCmd *apc, int stop_at_last));
6732
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00006733
Bram Moolenaar071d4272004-06-13 20:20:40 +00006734static EVENT_T last_event;
6735static int last_group;
6736
6737/*
6738 * Show the autocommands for one AutoPat.
6739 */
6740 static void
6741show_autocmd(ap, event)
6742 AutoPat *ap;
6743 EVENT_T event;
6744{
6745 AutoCmd *ac;
6746
6747 /* Check for "got_int" (here and at various places below), which is set
6748 * when "q" has been hit for the "--more--" prompt */
6749 if (got_int)
6750 return;
6751 if (ap->pat == NULL) /* pattern has been removed */
6752 return;
6753
6754 msg_putchar('\n');
6755 if (got_int)
6756 return;
6757 if (event != last_event || ap->group != last_group)
6758 {
6759 if (ap->group != AUGROUP_DEFAULT)
6760 {
6761 if (AUGROUP_NAME(ap->group) == NULL)
6762 msg_puts_attr((char_u *)_("--Deleted--"), hl_attr(HLF_E));
6763 else
6764 msg_puts_attr(AUGROUP_NAME(ap->group), hl_attr(HLF_T));
6765 msg_puts((char_u *)" ");
6766 }
6767 msg_puts_attr(event_nr2name(event), hl_attr(HLF_T));
6768 last_event = event;
6769 last_group = ap->group;
6770 msg_putchar('\n');
6771 if (got_int)
6772 return;
6773 }
6774 msg_col = 4;
6775 msg_outtrans(ap->pat);
6776
6777 for (ac = ap->cmds; ac != NULL; ac = ac->next)
6778 {
6779 if (ac->cmd != NULL) /* skip removed commands */
6780 {
6781 if (msg_col >= 14)
6782 msg_putchar('\n');
6783 msg_col = 14;
6784 if (got_int)
6785 return;
6786 msg_outtrans(ac->cmd);
6787 if (got_int)
6788 return;
6789 if (ac->next != NULL)
6790 {
6791 msg_putchar('\n');
6792 if (got_int)
6793 return;
6794 }
6795 }
6796 }
6797}
6798
6799/*
6800 * Mark an autocommand pattern for deletion.
6801 */
6802 static void
6803au_remove_pat(ap)
6804 AutoPat *ap;
6805{
6806 vim_free(ap->pat);
6807 ap->pat = NULL;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00006808 ap->buflocal_nr = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006809 au_need_clean = TRUE;
6810}
6811
6812/*
6813 * Mark all commands for a pattern for deletion.
6814 */
6815 static void
6816au_remove_cmds(ap)
6817 AutoPat *ap;
6818{
6819 AutoCmd *ac;
6820
6821 for (ac = ap->cmds; ac != NULL; ac = ac->next)
6822 {
6823 vim_free(ac->cmd);
6824 ac->cmd = NULL;
6825 }
6826 au_need_clean = TRUE;
6827}
6828
6829/*
6830 * Cleanup autocommands and patterns that have been deleted.
6831 * This is only done when not executing autocommands.
6832 */
6833 static void
6834au_cleanup()
6835{
6836 AutoPat *ap, **prev_ap;
6837 AutoCmd *ac, **prev_ac;
6838 EVENT_T event;
6839
6840 if (autocmd_busy || !au_need_clean)
6841 return;
6842
6843 /* loop over all events */
6844 for (event = (EVENT_T)0; (int)event < (int)NUM_EVENTS;
6845 event = (EVENT_T)((int)event + 1))
6846 {
6847 /* loop over all autocommand patterns */
6848 prev_ap = &(first_autopat[(int)event]);
6849 for (ap = *prev_ap; ap != NULL; ap = *prev_ap)
6850 {
6851 /* loop over all commands for this pattern */
6852 prev_ac = &(ap->cmds);
6853 for (ac = *prev_ac; ac != NULL; ac = *prev_ac)
6854 {
6855 /* remove the command if the pattern is to be deleted or when
6856 * the command has been marked for deletion */
6857 if (ap->pat == NULL || ac->cmd == NULL)
6858 {
6859 *prev_ac = ac->next;
6860 vim_free(ac->cmd);
6861 vim_free(ac);
6862 }
6863 else
6864 prev_ac = &(ac->next);
6865 }
6866
6867 /* remove the pattern if it has been marked for deletion */
6868 if (ap->pat == NULL)
6869 {
6870 *prev_ap = ap->next;
Bram Moolenaar748bf032005-02-02 23:04:36 +00006871 vim_free(ap->reg_prog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006872 vim_free(ap);
6873 }
6874 else
6875 prev_ap = &(ap->next);
6876 }
6877 }
6878
6879 au_need_clean = FALSE;
6880}
6881
6882/*
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00006883 * Called when buffer is freed, to remove/invalidate related buffer-local
6884 * autocmds.
6885 */
6886 void
6887aubuflocal_remove(buf)
6888 buf_T *buf;
6889{
6890 AutoPat *ap;
6891 EVENT_T event;
6892 AutoPatCmd *apc;
6893
6894 /* invalidate currently executing autocommands */
6895 for (apc = active_apc_list; apc; apc = apc->next)
6896 if (buf->b_fnum == apc->arg_bufnr)
6897 apc->arg_bufnr = 0;
6898
6899 /* invalidate buflocals looping through events */
6900 for (event = (EVENT_T)0; (int)event < (int)NUM_EVENTS;
6901 event = (EVENT_T)((int)event + 1))
6902 /* loop over all autocommand patterns */
6903 for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next)
6904 if (ap->buflocal_nr == buf->b_fnum)
6905 {
6906 au_remove_pat(ap);
6907 if (p_verbose >= 6)
6908 smsg((char_u *)
6909 _("auto-removing autocommand: %s <buffer=%d>"),
6910 event_nr2name(event), buf->b_fnum);
6911 }
6912 au_cleanup();
6913}
6914
6915/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00006916 * Add an autocmd group name.
6917 * Return it's ID. Returns AUGROUP_ERROR (< 0) for error.
6918 */
6919 static int
6920au_new_group(name)
6921 char_u *name;
6922{
6923 int i;
6924
6925 i = au_find_group(name);
6926 if (i == AUGROUP_ERROR) /* the group doesn't exist yet, add it */
6927 {
6928 /* First try using a free entry. */
6929 for (i = 0; i < augroups.ga_len; ++i)
6930 if (AUGROUP_NAME(i) == NULL)
6931 break;
6932 if (i == augroups.ga_len && ga_grow(&augroups, 1) == FAIL)
6933 return AUGROUP_ERROR;
6934
6935 AUGROUP_NAME(i) = vim_strsave(name);
6936 if (AUGROUP_NAME(i) == NULL)
6937 return AUGROUP_ERROR;
6938 if (i == augroups.ga_len)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006939 ++augroups.ga_len;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006940 }
6941
6942 return i;
6943}
6944
6945 static void
6946au_del_group(name)
6947 char_u *name;
6948{
6949 int i;
6950
6951 i = au_find_group(name);
6952 if (i == AUGROUP_ERROR) /* the group doesn't exist */
6953 EMSG2(_("E367: No such group: \"%s\""), name);
6954 else
6955 {
6956 vim_free(AUGROUP_NAME(i));
6957 AUGROUP_NAME(i) = NULL;
6958 }
6959}
6960
6961/*
6962 * Find the ID of an autocmd group name.
6963 * Return it's ID. Returns AUGROUP_ERROR (< 0) for error.
6964 */
6965 static int
6966au_find_group(name)
6967 char_u *name;
6968{
6969 int i;
6970
6971 for (i = 0; i < augroups.ga_len; ++i)
6972 if (AUGROUP_NAME(i) != NULL && STRCMP(AUGROUP_NAME(i), name) == 0)
6973 return i;
6974 return AUGROUP_ERROR;
6975}
6976
6977/*
6978 * ":augroup {name}".
6979 */
6980 void
6981do_augroup(arg, del_group)
6982 char_u *arg;
6983 int del_group;
6984{
6985 int i;
6986
6987 if (del_group)
6988 {
6989 if (*arg == NUL)
6990 EMSG(_(e_argreq));
6991 else
6992 au_del_group(arg);
6993 }
6994 else if (STRICMP(arg, "end") == 0) /* ":aug end": back to group 0 */
6995 current_augroup = AUGROUP_DEFAULT;
6996 else if (*arg) /* ":aug xxx": switch to group xxx */
6997 {
6998 i = au_new_group(arg);
6999 if (i != AUGROUP_ERROR)
7000 current_augroup = i;
7001 }
7002 else /* ":aug": list the group names */
7003 {
7004 msg_start();
7005 for (i = 0; i < augroups.ga_len; ++i)
7006 {
7007 if (AUGROUP_NAME(i) != NULL)
7008 {
7009 msg_puts(AUGROUP_NAME(i));
7010 msg_puts((char_u *)" ");
7011 }
7012 }
7013 msg_clr_eos();
7014 msg_end();
7015 }
7016}
7017
7018/*
7019 * Return the event number for event name "start".
7020 * Return NUM_EVENTS if the event name was not found.
7021 * Return a pointer to the next event name in "end".
7022 */
7023 static EVENT_T
7024event_name2nr(start, end)
7025 char_u *start;
7026 char_u **end;
7027{
7028 char_u *p;
7029 int i;
7030 int len;
7031
7032 /* the event name ends with end of line, a blank or a comma */
7033 for (p = start; *p && !vim_iswhite(*p) && *p != ','; ++p)
7034 ;
7035 for (i = 0; event_names[i].name != NULL; ++i)
7036 {
7037 len = (int)STRLEN(event_names[i].name);
7038 if (len == p - start && STRNICMP(event_names[i].name, start, len) == 0)
7039 break;
7040 }
7041 if (*p == ',')
7042 ++p;
7043 *end = p;
7044 if (event_names[i].name == NULL)
7045 return NUM_EVENTS;
7046 return event_names[i].event;
7047}
7048
7049/*
7050 * Return the name for event "event".
7051 */
7052 static char_u *
7053event_nr2name(event)
7054 EVENT_T event;
7055{
7056 int i;
7057
7058 for (i = 0; event_names[i].name != NULL; ++i)
7059 if (event_names[i].event == event)
7060 return (char_u *)event_names[i].name;
7061 return (char_u *)"Unknown";
7062}
7063
7064/*
7065 * Scan over the events. "*" stands for all events.
7066 */
7067 static char_u *
7068find_end_event(arg, have_group)
7069 char_u *arg;
7070 int have_group; /* TRUE when group name was found */
7071{
7072 char_u *pat;
7073 char_u *p;
7074
7075 if (*arg == '*')
7076 {
7077 if (arg[1] && !vim_iswhite(arg[1]))
7078 {
7079 EMSG2(_("E215: Illegal character after *: %s"), arg);
7080 return NULL;
7081 }
7082 pat = arg + 1;
7083 }
7084 else
7085 {
7086 for (pat = arg; *pat && !vim_iswhite(*pat); pat = p)
7087 {
7088 if ((int)event_name2nr(pat, &p) >= (int)NUM_EVENTS)
7089 {
7090 if (have_group)
7091 EMSG2(_("E216: No such event: %s"), pat);
7092 else
7093 EMSG2(_("E216: No such group or event: %s"), pat);
7094 return NULL;
7095 }
7096 }
7097 }
7098 return pat;
7099}
7100
7101/*
7102 * Return TRUE if "event" is included in 'eventignore'.
7103 */
7104 static int
7105event_ignored(event)
7106 EVENT_T event;
7107{
7108 char_u *p = p_ei;
7109
7110 if (STRICMP(p_ei, "all") == 0)
7111 return TRUE;
7112
7113 while (*p)
7114 if (event_name2nr(p, &p) == event)
7115 return TRUE;
7116
7117 return FALSE;
7118}
7119
7120/*
7121 * Return OK when the contents of p_ei is valid, FAIL otherwise.
7122 */
7123 int
7124check_ei()
7125{
7126 char_u *p = p_ei;
7127
7128 if (STRICMP(p_ei, "all") == 0)
7129 return OK;
7130
7131 while (*p)
7132 if (event_name2nr(p, &p) == NUM_EVENTS)
7133 return FAIL;
7134
7135 return OK;
7136}
7137
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00007138# if defined(FEAT_SYN_HL) || defined(PROTO)
7139
7140/*
7141 * Add "what" to 'eventignore' to skip loading syntax highlighting for every
7142 * buffer loaded into the window. "what" must start with a comma.
7143 * Returns the old value of 'eventignore' in allocated memory.
7144 */
7145 char_u *
7146au_event_disable(what)
7147 char *what;
7148{
7149 char_u *new_ei;
7150 char_u *save_ei;
7151
7152 save_ei = vim_strsave(p_ei);
7153 if (save_ei != NULL)
7154 {
7155 new_ei = vim_strnsave(p_ei, (int)STRLEN(p_ei) + 8);
7156 if (new_ei != NULL)
7157 {
7158 STRCAT(new_ei, what);
7159 set_string_option_direct((char_u *)"ei", -1, new_ei, OPT_FREE);
7160 vim_free(new_ei);
7161 }
7162 }
7163 return save_ei;
7164}
7165
7166 void
7167au_event_restore(old_ei)
7168 char_u *old_ei;
7169{
7170 if (old_ei != NULL)
7171 {
7172 set_string_option_direct((char_u *)"ei", -1, old_ei, OPT_FREE);
Bram Moolenaardcaf10e2005-01-21 11:55:25 +00007173 vim_free(old_ei);
7174 }
7175}
7176# endif /* FEAT_SYN_HL */
7177
Bram Moolenaar071d4272004-06-13 20:20:40 +00007178/*
7179 * do_autocmd() -- implements the :autocmd command. Can be used in the
7180 * following ways:
7181 *
7182 * :autocmd <event> <pat> <cmd> Add <cmd> to the list of commands that
7183 * will be automatically executed for <event>
7184 * when editing a file matching <pat>, in
7185 * the current group.
7186 * :autocmd <event> <pat> Show the auto-commands associated with
7187 * <event> and <pat>.
7188 * :autocmd <event> Show the auto-commands associated with
7189 * <event>.
7190 * :autocmd Show all auto-commands.
7191 * :autocmd! <event> <pat> <cmd> Remove all auto-commands associated with
7192 * <event> and <pat>, and add the command
7193 * <cmd>, for the current group.
7194 * :autocmd! <event> <pat> Remove all auto-commands associated with
7195 * <event> and <pat> for the current group.
7196 * :autocmd! <event> Remove all auto-commands associated with
7197 * <event> for the current group.
7198 * :autocmd! Remove ALL auto-commands for the current
7199 * group.
7200 *
7201 * Multiple events and patterns may be given separated by commas. Here are
7202 * some examples:
7203 * :autocmd bufread,bufenter *.c,*.h set tw=0 smartindent noic
7204 * :autocmd bufleave * set tw=79 nosmartindent ic infercase
7205 *
7206 * :autocmd * *.c show all autocommands for *.c files.
7207 */
7208 void
7209do_autocmd(arg, forceit)
7210 char_u *arg;
7211 int forceit;
7212{
7213 char_u *pat;
7214 char_u *envpat = NULL;
7215 char_u *cmd;
7216 EVENT_T event;
7217 int need_free = FALSE;
7218 int nested = FALSE;
7219 int group;
7220
7221 /*
7222 * Check for a legal group name. If not, use AUGROUP_ALL.
7223 */
7224 group = au_get_grouparg(&arg);
7225 if (arg == NULL) /* out of memory */
7226 return;
7227
7228 /*
7229 * Scan over the events.
7230 * If we find an illegal name, return here, don't do anything.
7231 */
7232 pat = find_end_event(arg, group != AUGROUP_ALL);
7233 if (pat == NULL)
7234 return;
7235
7236 /*
7237 * Scan over the pattern. Put a NUL at the end.
7238 */
7239 pat = skipwhite(pat);
7240 cmd = pat;
7241 while (*cmd && (!vim_iswhite(*cmd) || cmd[-1] == '\\'))
7242 cmd++;
7243 if (*cmd)
7244 *cmd++ = NUL;
7245
7246 /* Expand environment variables in the pattern. Set 'shellslash', we want
7247 * forward slashes here. */
7248 if (vim_strchr(pat, '$') != NULL || vim_strchr(pat, '~') != NULL)
7249 {
7250#ifdef BACKSLASH_IN_FILENAME
7251 int p_ssl_save = p_ssl;
7252
7253 p_ssl = TRUE;
7254#endif
7255 envpat = expand_env_save(pat);
7256#ifdef BACKSLASH_IN_FILENAME
7257 p_ssl = p_ssl_save;
7258#endif
7259 if (envpat != NULL)
7260 pat = envpat;
7261 }
7262
7263 /*
7264 * Check for "nested" flag.
7265 */
7266 cmd = skipwhite(cmd);
7267 if (*cmd != NUL && STRNCMP(cmd, "nested", 6) == 0 && vim_iswhite(cmd[6]))
7268 {
7269 nested = TRUE;
7270 cmd = skipwhite(cmd + 6);
7271 }
7272
7273 /*
7274 * Find the start of the commands.
7275 * Expand <sfile> in it.
7276 */
7277 if (*cmd != NUL)
7278 {
7279 cmd = expand_sfile(cmd);
7280 if (cmd == NULL) /* some error */
7281 return;
7282 need_free = TRUE;
7283 }
7284
7285 /*
7286 * Print header when showing autocommands.
7287 */
7288 if (!forceit && *cmd == NUL)
7289 {
7290 /* Highlight title */
7291 MSG_PUTS_TITLE(_("\n--- Auto-Commands ---"));
7292 }
7293
7294 /*
7295 * Loop over the events.
7296 */
7297 last_event = (EVENT_T)-1; /* for listing the event name */
7298 last_group = AUGROUP_ERROR; /* for listing the group name */
7299 if (*arg == '*' || *arg == NUL)
7300 {
7301 for (event = (EVENT_T)0; (int)event < (int)NUM_EVENTS;
7302 event = (EVENT_T)((int)event + 1))
7303 if (do_autocmd_event(event, pat,
7304 nested, cmd, forceit, group) == FAIL)
7305 break;
7306 }
7307 else
7308 {
7309 while (*arg && !vim_iswhite(*arg))
7310 if (do_autocmd_event(event_name2nr(arg, &arg), pat,
7311 nested, cmd, forceit, group) == FAIL)
7312 break;
7313 }
7314
7315 if (need_free)
7316 vim_free(cmd);
7317 vim_free(envpat);
7318}
7319
7320/*
7321 * Find the group ID in a ":autocmd" or ":doautocmd" argument.
7322 * The "argp" argument is advanced to the following argument.
7323 *
7324 * Returns the group ID, AUGROUP_ERROR for error (out of memory).
7325 */
7326 static int
7327au_get_grouparg(argp)
7328 char_u **argp;
7329{
7330 char_u *group_name;
7331 char_u *p;
7332 char_u *arg = *argp;
7333 int group = AUGROUP_ALL;
7334
7335 p = skiptowhite(arg);
7336 if (p > arg)
7337 {
7338 group_name = vim_strnsave(arg, (int)(p - arg));
7339 if (group_name == NULL) /* out of memory */
7340 return AUGROUP_ERROR;
7341 group = au_find_group(group_name);
7342 if (group == AUGROUP_ERROR)
7343 group = AUGROUP_ALL; /* no match, use all groups */
7344 else
7345 *argp = skipwhite(p); /* match, skip over group name */
7346 vim_free(group_name);
7347 }
7348 return group;
7349}
7350
7351/*
7352 * do_autocmd() for one event.
7353 * If *pat == NUL do for all patterns.
7354 * If *cmd == NUL show entries.
7355 * If forceit == TRUE delete entries.
7356 * If group is not AUGROUP_ALL, only use this group.
7357 */
7358 static int
7359do_autocmd_event(event, pat, nested, cmd, forceit, group)
7360 EVENT_T event;
7361 char_u *pat;
7362 int nested;
7363 char_u *cmd;
7364 int forceit;
7365 int group;
7366{
7367 AutoPat *ap;
7368 AutoPat **prev_ap;
7369 AutoCmd *ac;
7370 AutoCmd **prev_ac;
7371 int brace_level;
7372 char_u *endpat;
7373 int findgroup;
7374 int allgroups;
7375 int patlen;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007376 int is_buflocal;
7377 int buflocal_nr;
7378 char_u buflocal_pat[25]; /* for "<buffer=X>" */
Bram Moolenaar071d4272004-06-13 20:20:40 +00007379
7380 if (group == AUGROUP_ALL)
7381 findgroup = current_augroup;
7382 else
7383 findgroup = group;
7384 allgroups = (group == AUGROUP_ALL && !forceit && *cmd == NUL);
7385
7386 /*
7387 * Show or delete all patterns for an event.
7388 */
7389 if (*pat == NUL)
7390 {
7391 for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next)
7392 {
7393 if (forceit) /* delete the AutoPat, if it's in the current group */
7394 {
7395 if (ap->group == findgroup)
7396 au_remove_pat(ap);
7397 }
7398 else if (group == AUGROUP_ALL || ap->group == group)
7399 show_autocmd(ap, event);
7400 }
7401 }
7402
7403 /*
7404 * Loop through all the specified patterns.
7405 */
7406 for ( ; *pat; pat = (*endpat == ',' ? endpat + 1 : endpat))
7407 {
7408 /*
7409 * Find end of the pattern.
7410 * Watch out for a comma in braces, like "*.\{obj,o\}".
7411 */
7412 brace_level = 0;
7413 for (endpat = pat; *endpat && (*endpat != ',' || brace_level
7414 || endpat[-1] == '\\'); ++endpat)
7415 {
7416 if (*endpat == '{')
7417 brace_level++;
7418 else if (*endpat == '}')
7419 brace_level--;
7420 }
7421 if (pat == endpat) /* ignore single comma */
7422 continue;
7423 patlen = (int)(endpat - pat);
7424
7425 /*
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007426 * detect special <buflocal[=X]> buffer-local patterns
7427 */
7428 is_buflocal = FALSE;
7429 buflocal_nr = 0;
7430
7431 if (patlen >= 7 && STRNCMP(pat, "<buffer", 7) == 0
7432 && pat[patlen - 1] == '>')
7433 {
7434 /* Error will be printed only for addition. printing and removing
7435 * will proceed silently. */
7436 is_buflocal = TRUE;
7437 if (patlen == 8)
7438 buflocal_nr = curbuf->b_fnum;
7439 else if (patlen > 9 && pat[7] == '=')
7440 {
7441 /* <buffer=abuf> */
7442 if (patlen == 13 && STRNICMP(pat, "<buffer=abuf>", 13))
7443 buflocal_nr = autocmd_bufnr;
7444 /* <buffer=123> */
7445 else if (skipdigits(pat + 8) == pat + patlen - 1)
7446 buflocal_nr = atoi((char *)pat + 8);
7447 }
7448 }
7449
7450 if (is_buflocal)
7451 {
7452 /* normalize pat into standard "<buffer>#N" form */
7453 sprintf((char *)buflocal_pat, "<buffer=%d>", buflocal_nr);
7454 pat = buflocal_pat; /* can modify pat and patlen */
7455 patlen = STRLEN(buflocal_pat); /* but not endpat */
7456 }
7457
7458 /*
Bram Moolenaar071d4272004-06-13 20:20:40 +00007459 * Find AutoPat entries with this pattern.
7460 */
7461 prev_ap = &first_autopat[(int)event];
7462 while ((ap = *prev_ap) != NULL)
7463 {
7464 if (ap->pat != NULL)
7465 {
7466 /* Accept a pattern when:
7467 * - a group was specified and it's that group, or a group was
7468 * not specified and it's the current group, or a group was
7469 * not specified and we are listing
7470 * - the length of the pattern matches
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007471 * - the pattern matches.
7472 * For <buffer[=X]>, this condition works because we normalize
7473 * all buffer-local patterns.
Bram Moolenaar071d4272004-06-13 20:20:40 +00007474 */
7475 if ((allgroups || ap->group == findgroup)
7476 && ap->patlen == patlen
7477 && STRNCMP(pat, ap->pat, patlen) == 0)
7478 {
7479 /*
7480 * Remove existing autocommands.
7481 * If adding any new autocmd's for this AutoPat, don't
7482 * delete the pattern from the autopat list, append to
7483 * this list.
7484 */
7485 if (forceit)
7486 {
7487 if (*cmd != NUL && ap->next == NULL)
7488 {
7489 au_remove_cmds(ap);
7490 break;
7491 }
7492 au_remove_pat(ap);
7493 }
7494
7495 /*
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007496 * Show autocmd's for this autopat, or buflocals <buffer=X>
Bram Moolenaar071d4272004-06-13 20:20:40 +00007497 */
7498 else if (*cmd == NUL)
7499 show_autocmd(ap, event);
7500
7501 /*
7502 * Add autocmd to this autopat, if it's the last one.
7503 */
7504 else if (ap->next == NULL)
7505 break;
7506 }
7507 }
7508 prev_ap = &ap->next;
7509 }
7510
7511 /*
7512 * Add a new command.
7513 */
7514 if (*cmd != NUL)
7515 {
7516 /*
7517 * If the pattern we want to add a command to does appear at the
7518 * end of the list (or not is not in the list at all), add the
7519 * pattern at the end of the list.
7520 */
7521 if (ap == NULL)
7522 {
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007523 /* refuse to add buffer-local ap if buffer number is invalid */
7524 if (is_buflocal && (buflocal_nr == 0
7525 || buflist_findnr(buflocal_nr) == NULL))
7526 {
7527 EMSGN(_("E680: <buffer=%d>: invalid buffer number "),
7528 buflocal_nr);
7529 return FAIL;
7530 }
7531
Bram Moolenaar071d4272004-06-13 20:20:40 +00007532 ap = (AutoPat *)alloc((unsigned)sizeof(AutoPat));
7533 if (ap == NULL)
7534 return FAIL;
7535 ap->pat = vim_strnsave(pat, patlen);
7536 ap->patlen = patlen;
7537 if (ap->pat == NULL)
7538 {
7539 vim_free(ap);
7540 return FAIL;
7541 }
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007542
7543 if (is_buflocal)
Bram Moolenaar071d4272004-06-13 20:20:40 +00007544 {
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007545 ap->buflocal_nr = buflocal_nr;
Bram Moolenaar748bf032005-02-02 23:04:36 +00007546 ap->reg_prog = NULL;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007547 }
7548 else
7549 {
Bram Moolenaar748bf032005-02-02 23:04:36 +00007550 char_u *reg_pat;
7551
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007552 ap->buflocal_nr = 0;
Bram Moolenaar748bf032005-02-02 23:04:36 +00007553 reg_pat = file_pat_to_reg_pat(pat, endpat,
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007554 &ap->allow_dirs, TRUE);
Bram Moolenaar748bf032005-02-02 23:04:36 +00007555 if (reg_pat != NULL)
7556 ap->reg_prog = vim_regcomp(reg_pat, RE_MAGIC);
7557 if (reg_pat == NULL || ap->reg_prog == NULL)
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007558 {
Bram Moolenaar748bf032005-02-02 23:04:36 +00007559 vim_free(reg_pat);
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007560 vim_free(ap->pat);
7561 vim_free(ap);
7562 return FAIL;
7563 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00007564 }
7565 ap->cmds = NULL;
7566 *prev_ap = ap;
7567 ap->next = NULL;
7568 if (group == AUGROUP_ALL)
7569 ap->group = current_augroup;
7570 else
7571 ap->group = group;
7572 }
7573
7574 /*
7575 * Add the autocmd at the end of the AutoCmd list.
7576 */
7577 prev_ac = &(ap->cmds);
7578 while ((ac = *prev_ac) != NULL)
7579 prev_ac = &ac->next;
7580 ac = (AutoCmd *)alloc((unsigned)sizeof(AutoCmd));
7581 if (ac == NULL)
7582 return FAIL;
7583 ac->cmd = vim_strsave(cmd);
7584#ifdef FEAT_EVAL
7585 ac->scriptID = current_SID;
7586#endif
7587 if (ac->cmd == NULL)
7588 {
7589 vim_free(ac);
7590 return FAIL;
7591 }
7592 ac->next = NULL;
7593 *prev_ac = ac;
7594 ac->nested = nested;
7595 }
7596 }
7597
7598 au_cleanup(); /* may really delete removed patterns/commands now */
7599 return OK;
7600}
7601
7602/*
7603 * Implementation of ":doautocmd [group] event [fname]".
7604 * Return OK for success, FAIL for failure;
7605 */
7606 int
7607do_doautocmd(arg, do_msg)
7608 char_u *arg;
7609 int do_msg; /* give message for no matching autocmds? */
7610{
7611 char_u *fname;
7612 int nothing_done = TRUE;
7613 int group;
7614
7615 /*
7616 * Check for a legal group name. If not, use AUGROUP_ALL.
7617 */
7618 group = au_get_grouparg(&arg);
7619 if (arg == NULL) /* out of memory */
7620 return FAIL;
7621
7622 if (*arg == '*')
7623 {
7624 EMSG(_("E217: Can't execute autocommands for ALL events"));
7625 return FAIL;
7626 }
7627
7628 /*
7629 * Scan over the events.
7630 * If we find an illegal name, return here, don't do anything.
7631 */
7632 fname = find_end_event(arg, group != AUGROUP_ALL);
7633 if (fname == NULL)
7634 return FAIL;
7635
7636 fname = skipwhite(fname);
7637
7638 /*
7639 * Loop over the events.
7640 */
7641 while (*arg && !vim_iswhite(*arg))
7642 if (apply_autocmds_group(event_name2nr(arg, &arg),
7643 fname, NULL, TRUE, group, curbuf, NULL))
7644 nothing_done = FALSE;
7645
7646 if (nothing_done && do_msg)
7647 MSG(_("No matching autocommands"));
7648
7649#ifdef FEAT_EVAL
7650 return aborting() ? FAIL : OK;
7651#else
7652 return OK;
7653#endif
7654}
7655
7656/*
7657 * ":doautoall": execute autocommands for each loaded buffer.
7658 */
7659 void
7660ex_doautoall(eap)
7661 exarg_T *eap;
7662{
7663 int retval;
7664 aco_save_T aco;
7665 buf_T *buf;
7666
7667 /*
7668 * This is a bit tricky: For some commands curwin->w_buffer needs to be
7669 * equal to curbuf, but for some buffers there may not be a window.
7670 * So we change the buffer for the current window for a moment. This
7671 * gives problems when the autocommands make changes to the list of
7672 * buffers or windows...
7673 */
7674 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
7675 {
7676 if (curbuf->b_ml.ml_mfp != NULL)
7677 {
7678 /* find a window for this buffer and save some values */
7679 aucmd_prepbuf(&aco, buf);
7680
7681 /* execute the autocommands for this buffer */
7682 retval = do_doautocmd(eap->arg, FALSE);
Bram Moolenaar15d0a8c2004-09-06 17:44:46 +00007683 do_modelines(FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007684
7685 /* restore the current window */
7686 aucmd_restbuf(&aco);
7687
7688 /* stop if there is some error or buffer was deleted */
7689 if (retval == FAIL || !buf_valid(buf))
7690 break;
7691 }
7692 }
7693
7694 check_cursor(); /* just in case lines got deleted */
7695}
7696
7697/*
7698 * Prepare for executing autocommands for (hidden) buffer "buf".
7699 * Search a window for the current buffer. Save the cursor position and
7700 * screen offset.
7701 * Set "curbuf" and "curwin" to match "buf".
7702 */
7703 void
7704aucmd_prepbuf(aco, buf)
7705 aco_save_T *aco; /* structure to save values in */
7706 buf_T *buf; /* new curbuf */
7707{
7708 win_T *win;
7709
7710 aco->new_curbuf = buf;
7711
7712 /* Find a window that is for the new buffer */
7713 if (buf == curbuf) /* be quick when buf is curbuf */
7714 win = curwin;
7715 else
7716#ifdef FEAT_WINDOWS
7717 for (win = firstwin; win != NULL; win = win->w_next)
7718 if (win->w_buffer == buf)
7719 break;
7720#else
7721 win = NULL;
7722#endif
7723
7724 /*
7725 * Prefer to use an existing window for the buffer, it has the least side
7726 * effects (esp. if "buf" is curbuf).
7727 * Otherwise, use curwin for "buf". It might make some items in the
7728 * window invalid. At least save the cursor and topline.
7729 */
7730 if (win != NULL)
7731 {
7732 /* there is a window for "buf", make it the curwin */
7733 aco->save_curwin = curwin;
7734 curwin = win;
7735 aco->save_buf = win->w_buffer;
7736 aco->new_curwin = win;
7737 }
7738 else
7739 {
7740 /* there is no window for "buf", use curwin */
7741 aco->save_curwin = NULL;
7742 aco->save_buf = curbuf;
7743 --curbuf->b_nwindows;
7744 curwin->w_buffer = buf;
7745 ++buf->b_nwindows;
7746
7747 /* save cursor and topline, set them to safe values */
7748 aco->save_cursor = curwin->w_cursor;
7749 curwin->w_cursor.lnum = 1;
7750 curwin->w_cursor.col = 0;
7751 aco->save_topline = curwin->w_topline;
7752 curwin->w_topline = 1;
7753#ifdef FEAT_DIFF
7754 aco->save_topfill = curwin->w_topfill;
7755 curwin->w_topfill = 0;
7756#endif
7757 }
7758
7759 curbuf = buf;
7760}
7761
7762/*
7763 * Cleanup after executing autocommands for a (hidden) buffer.
7764 * Restore the window as it was (if possible).
7765 */
7766 void
7767aucmd_restbuf(aco)
7768 aco_save_T *aco; /* structure holding saved values */
7769{
7770 if (aco->save_curwin != NULL)
7771 {
7772 /* restore curwin */
7773#ifdef FEAT_WINDOWS
7774 if (win_valid(aco->save_curwin))
7775#endif
7776 {
7777 /* restore the buffer which was previously edited by curwin, if
7778 * it's still the same window and it's valid */
7779 if (curwin == aco->new_curwin
7780 && buf_valid(aco->save_buf)
7781 && aco->save_buf->b_ml.ml_mfp != NULL)
7782 {
7783 --curbuf->b_nwindows;
7784 curbuf = aco->save_buf;
7785 curwin->w_buffer = curbuf;
7786 ++curbuf->b_nwindows;
7787 }
7788
7789 curwin = aco->save_curwin;
7790 curbuf = curwin->w_buffer;
7791 }
7792 }
7793 else
7794 {
7795 /* restore buffer for curwin if it still exists and is loaded */
7796 if (buf_valid(aco->save_buf) && aco->save_buf->b_ml.ml_mfp != NULL)
7797 {
7798 --curbuf->b_nwindows;
7799 curbuf = aco->save_buf;
7800 curwin->w_buffer = curbuf;
7801 ++curbuf->b_nwindows;
7802 curwin->w_cursor = aco->save_cursor;
7803 check_cursor();
7804 /* check topline < line_count, in case lines got deleted */
7805 if (aco->save_topline <= curbuf->b_ml.ml_line_count)
7806 {
7807 curwin->w_topline = aco->save_topline;
7808#ifdef FEAT_DIFF
7809 curwin->w_topfill = aco->save_topfill;
7810#endif
7811 }
7812 else
7813 {
7814 curwin->w_topline = curbuf->b_ml.ml_line_count;
7815#ifdef FEAT_DIFF
7816 curwin->w_topfill = 0;
7817#endif
7818 }
7819 }
7820 }
7821}
7822
7823static int autocmd_nested = FALSE;
7824
7825/*
7826 * Execute autocommands for "event" and file name "fname".
7827 * Return TRUE if some commands were executed.
7828 */
7829 int
7830apply_autocmds(event, fname, fname_io, force, buf)
7831 EVENT_T event;
7832 char_u *fname; /* NULL or empty means use actual file name */
7833 char_u *fname_io; /* fname to use for <afile> on cmdline */
7834 int force; /* when TRUE, ignore autocmd_busy */
7835 buf_T *buf; /* buffer for <abuf> */
7836{
7837 return apply_autocmds_group(event, fname, fname_io, force,
7838 AUGROUP_ALL, buf, NULL);
7839}
7840
7841/*
7842 * Like apply_autocmds(), but with extra "eap" argument. This takes care of
7843 * setting v:filearg.
7844 */
7845 static int
7846apply_autocmds_exarg(event, fname, fname_io, force, buf, eap)
7847 EVENT_T event;
7848 char_u *fname;
7849 char_u *fname_io;
7850 int force;
7851 buf_T *buf;
7852 exarg_T *eap;
7853{
7854 return apply_autocmds_group(event, fname, fname_io, force,
7855 AUGROUP_ALL, buf, eap);
7856}
7857
7858/*
7859 * Like apply_autocmds(), but handles the caller's retval. If the script
7860 * processing is being aborted or if retval is FAIL when inside a try
7861 * conditional, no autocommands are executed. If otherwise the autocommands
7862 * cause the script to be aborted, retval is set to FAIL.
7863 */
7864 int
7865apply_autocmds_retval(event, fname, fname_io, force, buf, retval)
7866 EVENT_T event;
7867 char_u *fname; /* NULL or empty means use actual file name */
7868 char_u *fname_io; /* fname to use for <afile> on cmdline */
7869 int force; /* when TRUE, ignore autocmd_busy */
7870 buf_T *buf; /* buffer for <abuf> */
7871 int *retval; /* pointer to caller's retval */
7872{
7873 int did_cmd;
7874
7875 if (should_abort(*retval))
7876 return FALSE;
7877
7878 did_cmd = apply_autocmds_group(event, fname, fname_io, force,
7879 AUGROUP_ALL, buf, NULL);
7880 if (did_cmd && aborting())
7881 *retval = FAIL;
7882 return did_cmd;
7883}
7884
7885#if defined(FEAT_AUTOCMD) || defined(PROTO)
7886 int
7887has_cursorhold()
7888{
7889 return (first_autopat[(int)EVENT_CURSORHOLD] != NULL);
7890}
7891#endif
7892
7893 static int
7894apply_autocmds_group(event, fname, fname_io, force, group, buf, eap)
7895 EVENT_T event;
7896 char_u *fname; /* NULL or empty means use actual file name */
7897 char_u *fname_io; /* fname to use for <afile> on cmdline, NULL means
7898 use fname */
7899 int force; /* when TRUE, ignore autocmd_busy */
7900 int group; /* group ID, or AUGROUP_ALL */
7901 buf_T *buf; /* buffer for <abuf> */
7902 exarg_T *eap; /* command arguments */
7903{
7904 char_u *sfname = NULL; /* short file name */
7905 char_u *tail;
7906 int save_changed;
7907 buf_T *old_curbuf;
7908 int retval = FALSE;
7909 char_u *save_sourcing_name;
7910 linenr_T save_sourcing_lnum;
7911 char_u *save_autocmd_fname;
7912 int save_autocmd_bufnr;
7913 char_u *save_autocmd_match;
7914 int save_autocmd_busy;
7915 int save_autocmd_nested;
7916 static int nesting = 0;
7917 AutoPatCmd patcmd;
7918 AutoPat *ap;
7919#ifdef FEAT_EVAL
7920 scid_T save_current_SID;
7921 void *save_funccalp;
7922 char_u *save_cmdarg;
7923 long save_cmdbang;
7924#endif
7925 static int filechangeshell_busy = FALSE;
7926
7927 /*
7928 * Quickly return if there are no autocommands for this event or
7929 * autocommands are blocked.
7930 */
7931 if (first_autopat[(int)event] == NULL || autocmd_block > 0)
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007932 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007933
7934 /*
7935 * When autocommands are busy, new autocommands are only executed when
7936 * explicitly enabled with the "nested" flag.
7937 */
7938 if (autocmd_busy && !(force || autocmd_nested))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007939 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007940
7941#ifdef FEAT_EVAL
7942 /*
7943 * Quickly return when immdediately aborting on error, or when an interrupt
7944 * occurred or an exception was thrown but not caught.
7945 */
7946 if (aborting())
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007947 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007948#endif
7949
7950 /*
7951 * FileChangedShell never nests, because it can create an endless loop.
7952 */
7953 if (filechangeshell_busy && event == EVENT_FILECHANGEDSHELL)
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007954 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007955
7956 /*
7957 * Ignore events in 'eventignore'.
7958 */
7959 if (event_ignored(event))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007960 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007961
7962 /*
7963 * Allow nesting of autocommands, but restrict the depth, because it's
7964 * possible to create an endless loop.
7965 */
7966 if (nesting == 10)
7967 {
7968 EMSG(_("E218: autocommand nesting too deep"));
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007969 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007970 }
7971
7972 /*
7973 * Check if these autocommands are disabled. Used when doing ":all" or
7974 * ":ball".
7975 */
7976 if ( (autocmd_no_enter
7977 && (event == EVENT_WINENTER || event == EVENT_BUFENTER))
7978 || (autocmd_no_leave
7979 && (event == EVENT_WINLEAVE || event == EVENT_BUFLEAVE)))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00007980 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00007981
7982 /*
7983 * Save the autocmd_* variables and info about the current buffer.
7984 */
7985 save_autocmd_fname = autocmd_fname;
7986 save_autocmd_bufnr = autocmd_bufnr;
7987 save_autocmd_match = autocmd_match;
7988 save_autocmd_busy = autocmd_busy;
7989 save_autocmd_nested = autocmd_nested;
7990 save_changed = curbuf->b_changed;
7991 old_curbuf = curbuf;
7992
7993 /*
7994 * Set the file name to be used for <afile>.
7995 */
7996 if (fname_io == NULL)
7997 {
7998 if (fname != NULL && *fname != NUL)
7999 autocmd_fname = fname;
8000 else if (buf != NULL)
8001 autocmd_fname = buf->b_fname;
8002 else
8003 autocmd_fname = NULL;
8004 }
8005 else
8006 autocmd_fname = fname_io;
8007
8008 /*
8009 * Set the buffer number to be used for <abuf>.
8010 */
8011 if (buf == NULL)
8012 autocmd_bufnr = 0;
8013 else
8014 autocmd_bufnr = buf->b_fnum;
8015
8016 /*
8017 * When the file name is NULL or empty, use the file name of buffer "buf".
8018 * Always use the full path of the file name to match with, in case
8019 * "allow_dirs" is set.
8020 */
8021 if (fname == NULL || *fname == NUL)
8022 {
8023 if (buf == NULL)
8024 fname = NULL;
8025 else
8026 {
8027#ifdef FEAT_SYN_HL
8028 if (event == EVENT_SYNTAX)
8029 fname = buf->b_p_syn;
8030 else
8031#endif
8032 if (event == EVENT_FILETYPE)
8033 fname = buf->b_p_ft;
8034 else
8035 {
8036 if (buf->b_sfname != NULL)
8037 sfname = vim_strsave(buf->b_sfname);
8038 fname = buf->b_ffname;
8039 }
8040 }
8041 if (fname == NULL)
8042 fname = (char_u *)"";
8043 fname = vim_strsave(fname); /* make a copy, so we can change it */
8044 }
8045 else
8046 {
8047 sfname = vim_strsave(fname);
Bram Moolenaar7c626922005-02-07 22:01:03 +00008048 /* Don't try expanding FileType, Syntax, WindowID or QuickFixCmd* */
8049 if (event == EVENT_FILETYPE
8050 || event == EVENT_SYNTAX
8051 || event == EVENT_REMOTEREPLY
8052 || event == EVENT_QUICKFIXCMDPRE
8053 || event == EVENT_QUICKFIXCMDPOST)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008054 fname = vim_strsave(fname);
8055 else
8056 fname = FullName_save(fname, FALSE);
8057 }
8058 if (fname == NULL) /* out of memory */
8059 {
8060 vim_free(sfname);
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008061 retval = FALSE;
8062 goto BYPASS_AU;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008063 }
8064
8065#ifdef BACKSLASH_IN_FILENAME
8066 /*
8067 * Replace all backslashes with forward slashes. This makes the
8068 * autocommand patterns portable between Unix and MS-DOS.
8069 */
8070 if (sfname != NULL)
8071 forward_slash(sfname);
8072 forward_slash(fname);
8073#endif
8074
8075#ifdef VMS
8076 /* remove version for correct match */
8077 if (sfname != NULL)
8078 vms_remove_version(sfname);
8079 vms_remove_version(fname);
8080#endif
8081
8082 /*
8083 * Set the name to be used for <amatch>.
8084 */
8085 autocmd_match = fname;
8086
8087
8088 /* Don't redraw while doing auto commands. */
8089 ++RedrawingDisabled;
8090 save_sourcing_name = sourcing_name;
8091 sourcing_name = NULL; /* don't free this one */
8092 save_sourcing_lnum = sourcing_lnum;
8093 sourcing_lnum = 0; /* no line number here */
8094
8095#ifdef FEAT_EVAL
8096 save_current_SID = current_SID;
8097
8098 /* Don't use local function variables, if called from a function */
8099 save_funccalp = save_funccal();
8100#endif
8101
8102 /*
8103 * When starting to execute autocommands, save the search patterns.
8104 */
8105 if (!autocmd_busy)
8106 {
8107 save_search_patterns();
8108 saveRedobuff();
8109 did_filetype = keep_filetype;
8110 }
8111
8112 /*
8113 * Note that we are applying autocmds. Some commands need to know.
8114 */
8115 autocmd_busy = TRUE;
8116 filechangeshell_busy = (event == EVENT_FILECHANGEDSHELL);
8117 ++nesting; /* see matching decrement below */
8118
8119 /* Remember that FileType was triggered. Used for did_filetype(). */
8120 if (event == EVENT_FILETYPE)
8121 did_filetype = TRUE;
8122
8123 tail = gettail(fname);
8124
8125 /* Find first autocommand that matches */
8126 patcmd.curpat = first_autopat[(int)event];
8127 patcmd.nextcmd = NULL;
8128 patcmd.group = group;
8129 patcmd.fname = fname;
8130 patcmd.sfname = sfname;
8131 patcmd.tail = tail;
8132 patcmd.event = event;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008133 patcmd.arg_bufnr = autocmd_bufnr;
8134 patcmd.next = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008135 auto_next_pat(&patcmd, FALSE);
8136
8137 /* found one, start executing the autocommands */
8138 if (patcmd.curpat != NULL)
8139 {
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008140 /* add to active_apc_list */
8141 patcmd.next = active_apc_list;
8142 active_apc_list = &patcmd;
8143
Bram Moolenaar071d4272004-06-13 20:20:40 +00008144#ifdef FEAT_EVAL
8145 /* set v:cmdarg (only when there is a matching pattern) */
8146 save_cmdbang = get_vim_var_nr(VV_CMDBANG);
8147 if (eap != NULL)
8148 {
8149 save_cmdarg = set_cmdarg(eap, NULL);
8150 set_vim_var_nr(VV_CMDBANG, (long)eap->forceit);
8151 }
8152 else
8153 save_cmdarg = NULL; /* avoid gcc warning */
8154#endif
8155 retval = TRUE;
8156 /* mark the last pattern, to avoid an endless loop when more patterns
8157 * are added when executing autocommands */
8158 for (ap = patcmd.curpat; ap->next != NULL; ap = ap->next)
8159 ap->last = FALSE;
8160 ap->last = TRUE;
8161 check_lnums(TRUE); /* make sure cursor and topline are valid */
8162 do_cmdline(NULL, getnextac, (void *)&patcmd,
8163 DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT);
8164#ifdef FEAT_EVAL
8165 if (eap != NULL)
8166 {
8167 (void)set_cmdarg(NULL, save_cmdarg);
8168 set_vim_var_nr(VV_CMDBANG, save_cmdbang);
8169 }
8170#endif
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008171 /* delete from active_apc_list */
8172 if (active_apc_list == &patcmd) /* just in case */
8173 active_apc_list = patcmd.next;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008174 }
8175
8176 --RedrawingDisabled;
8177 autocmd_busy = save_autocmd_busy;
8178 filechangeshell_busy = FALSE;
8179 autocmd_nested = save_autocmd_nested;
8180 vim_free(sourcing_name);
8181 sourcing_name = save_sourcing_name;
8182 sourcing_lnum = save_sourcing_lnum;
8183 autocmd_fname = save_autocmd_fname;
8184 autocmd_bufnr = save_autocmd_bufnr;
8185 autocmd_match = save_autocmd_match;
8186#ifdef FEAT_EVAL
8187 current_SID = save_current_SID;
8188 restore_funccal(save_funccalp);
8189#endif
8190 vim_free(fname);
8191 vim_free(sfname);
8192 --nesting; /* see matching increment above */
8193
8194 /*
8195 * When stopping to execute autocommands, restore the search patterns and
8196 * the redo buffer.
8197 */
8198 if (!autocmd_busy)
8199 {
8200 restore_search_patterns();
8201 restoreRedobuff();
8202 did_filetype = FALSE;
8203 }
8204
8205 /*
8206 * Some events don't set or reset the Changed flag.
8207 * Check if still in the same buffer!
8208 */
8209 if (curbuf == old_curbuf
8210 && (event == EVENT_BUFREADPOST
8211 || event == EVENT_BUFWRITEPOST
8212 || event == EVENT_FILEAPPENDPOST
8213 || event == EVENT_VIMLEAVE
8214 || event == EVENT_VIMLEAVEPRE))
8215 {
8216#ifdef FEAT_TITLE
8217 if (curbuf->b_changed != save_changed)
8218 need_maketitle = TRUE;
8219#endif
8220 curbuf->b_changed = save_changed;
8221 }
8222
8223 au_cleanup(); /* may really delete removed patterns/commands now */
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008224
8225BYPASS_AU:
8226 /* When wiping out a buffer make sure all its buffer-local autocommands
8227 * are deleted. */
8228 if (event == EVENT_BUFWIPEOUT && buf != NULL)
8229 aubuflocal_remove(buf);
8230
Bram Moolenaar071d4272004-06-13 20:20:40 +00008231 return retval;
8232}
8233
8234/*
8235 * Find next autocommand pattern that matches.
8236 */
8237 static void
8238auto_next_pat(apc, stop_at_last)
8239 AutoPatCmd *apc;
8240 int stop_at_last; /* stop when 'last' flag is set */
8241{
8242 AutoPat *ap;
8243 AutoCmd *cp;
8244 char_u *name;
8245 char *s;
8246
8247 vim_free(sourcing_name);
8248 sourcing_name = NULL;
8249
8250 for (ap = apc->curpat; ap != NULL && !got_int; ap = ap->next)
8251 {
8252 apc->curpat = NULL;
8253
8254 /* only use a pattern when it has not been removed, has commands and
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008255 * the group matches. For buffer-local autocommands only check the
8256 * buffer number. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008257 if (ap->pat != NULL && ap->cmds != NULL
8258 && (apc->group == AUGROUP_ALL || apc->group == ap->group))
8259 {
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008260 /* execution-condition */
8261 if (ap->buflocal_nr == 0
Bram Moolenaar748bf032005-02-02 23:04:36 +00008262 ? (match_file_pat(NULL, ap->reg_prog, apc->fname,
8263 apc->sfname, apc->tail, ap->allow_dirs))
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008264 : ap->buflocal_nr == apc->arg_bufnr)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008265 {
8266 name = event_nr2name(apc->event);
8267 s = _("%s Auto commands for \"%s\"");
8268 sourcing_name = alloc((unsigned)(STRLEN(s)
8269 + STRLEN(name) + ap->patlen + 1));
8270 if (sourcing_name != NULL)
8271 {
8272 sprintf((char *)sourcing_name, s,
8273 (char *)name, (char *)ap->pat);
8274 if (p_verbose >= 8)
8275 msg_str((char_u *)_("Executing %s"), sourcing_name);
8276 }
8277
8278 apc->curpat = ap;
8279 apc->nextcmd = ap->cmds;
8280 /* mark last command */
8281 for (cp = ap->cmds; cp->next != NULL; cp = cp->next)
8282 cp->last = FALSE;
8283 cp->last = TRUE;
8284 }
8285 line_breakcheck();
8286 if (apc->curpat != NULL) /* found a match */
8287 break;
8288 }
8289 if (stop_at_last && ap->last)
8290 break;
8291 }
8292}
8293
8294/*
8295 * Get next autocommand command.
8296 * Called by do_cmdline() to get the next line for ":if".
8297 * Returns allocated string, or NULL for end of autocommands.
8298 */
8299/* ARGSUSED */
8300 static char_u *
8301getnextac(c, cookie, indent)
8302 int c; /* not used */
8303 void *cookie;
8304 int indent; /* not used */
8305{
8306 AutoPatCmd *acp = (AutoPatCmd *)cookie;
8307 char_u *retval;
8308 AutoCmd *ac;
8309
8310 /* Can be called again after returning the last line. */
8311 if (acp->curpat == NULL)
8312 return NULL;
8313
8314 /* repeat until we find an autocommand to execute */
8315 for (;;)
8316 {
8317 /* skip removed commands */
8318 while (acp->nextcmd != NULL && acp->nextcmd->cmd == NULL)
8319 if (acp->nextcmd->last)
8320 acp->nextcmd = NULL;
8321 else
8322 acp->nextcmd = acp->nextcmd->next;
8323
8324 if (acp->nextcmd != NULL)
8325 break;
8326
8327 /* at end of commands, find next pattern that matches */
8328 if (acp->curpat->last)
8329 acp->curpat = NULL;
8330 else
8331 acp->curpat = acp->curpat->next;
8332 if (acp->curpat != NULL)
8333 auto_next_pat(acp, TRUE);
8334 if (acp->curpat == NULL)
8335 return NULL;
8336 }
8337
8338 ac = acp->nextcmd;
8339
8340 if (p_verbose >= 9)
8341 {
8342 msg_scroll = TRUE; /* always scroll up, don't overwrite */
8343 msg_str((char_u *)_("autocommand %s"), ac->cmd);
8344 msg_puts((char_u *)"\n"); /* don't overwrite this either */
8345 cmdline_row = msg_row;
8346 }
8347 retval = vim_strsave(ac->cmd);
8348 autocmd_nested = ac->nested;
8349#ifdef FEAT_EVAL
8350 current_SID = ac->scriptID;
8351#endif
8352 if (ac->last)
8353 acp->nextcmd = NULL;
8354 else
8355 acp->nextcmd = ac->next;
8356 return retval;
8357}
8358
8359/*
8360 * Return TRUE if there is a matching autocommand for "fname".
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008361 * To account for buffer-local autocommands, function needs to know
8362 * in which buffer the file will be opened.
Bram Moolenaar071d4272004-06-13 20:20:40 +00008363 */
8364 int
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008365has_autocmd(event, sfname, buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008366 EVENT_T event;
8367 char_u *sfname;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008368 buf_T *buf;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008369{
8370 AutoPat *ap;
8371 char_u *fname;
8372 char_u *tail = gettail(sfname);
8373 int retval = FALSE;
8374
8375 fname = FullName_save(sfname, FALSE);
8376 if (fname == NULL)
8377 return FALSE;
8378
8379#ifdef BACKSLASH_IN_FILENAME
8380 /*
8381 * Replace all backslashes with forward slashes. This makes the
8382 * autocommand patterns portable between Unix and MS-DOS.
8383 */
8384 sfname = vim_strsave(sfname);
8385 if (sfname != NULL)
8386 forward_slash(sfname);
8387 forward_slash(fname);
8388#endif
8389
8390 for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next)
8391 if (ap->pat != NULL && ap->cmds != NULL
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008392 && (ap->buflocal_nr == 0
Bram Moolenaar748bf032005-02-02 23:04:36 +00008393 ? match_file_pat(NULL, ap->reg_prog,
8394 fname, sfname, tail, ap->allow_dirs)
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008395 : buf != NULL && ap->buflocal_nr == buf->b_fnum
8396 ))
Bram Moolenaar071d4272004-06-13 20:20:40 +00008397 {
8398 retval = TRUE;
8399 break;
8400 }
8401
8402 vim_free(fname);
8403#ifdef BACKSLASH_IN_FILENAME
8404 vim_free(sfname);
8405#endif
8406
8407 return retval;
8408}
8409
8410#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
8411/*
8412 * Function given to ExpandGeneric() to obtain the list of autocommand group
8413 * names.
8414 */
8415/*ARGSUSED*/
8416 char_u *
8417get_augroup_name(xp, idx)
8418 expand_T *xp;
8419 int idx;
8420{
8421 if (idx == augroups.ga_len) /* add "END" add the end */
8422 return (char_u *)"END";
8423 if (idx >= augroups.ga_len) /* end of list */
8424 return NULL;
8425 if (AUGROUP_NAME(idx) == NULL) /* skip deleted entries */
8426 return (char_u *)"";
8427 return AUGROUP_NAME(idx); /* return a name */
8428}
8429
8430static int include_groups = FALSE;
8431
8432 char_u *
8433set_context_in_autocmd(xp, arg, doautocmd)
8434 expand_T *xp;
8435 char_u *arg;
8436 int doautocmd; /* TRUE for :doautocmd, FALSE for :autocmd */
8437{
8438 char_u *p;
8439 int group;
8440
8441 /* check for a group name, skip it if present */
8442 include_groups = FALSE;
8443 p = arg;
8444 group = au_get_grouparg(&arg);
8445 if (group == AUGROUP_ERROR)
8446 return NULL;
8447 /* If there only is a group name that's what we expand. */
8448 if (*arg == NUL && group != AUGROUP_ALL && !vim_iswhite(arg[-1]))
8449 {
8450 arg = p;
8451 group = AUGROUP_ALL;
8452 }
8453
8454 /* skip over event name */
8455 for (p = arg; *p != NUL && !vim_iswhite(*p); ++p)
8456 if (*p == ',')
8457 arg = p + 1;
8458 if (*p == NUL)
8459 {
8460 if (group == AUGROUP_ALL)
8461 include_groups = TRUE;
8462 xp->xp_context = EXPAND_EVENTS; /* expand event name */
8463 xp->xp_pattern = arg;
8464 return NULL;
8465 }
8466
8467 /* skip over pattern */
8468 arg = skipwhite(p);
8469 while (*arg && (!vim_iswhite(*arg) || arg[-1] == '\\'))
8470 arg++;
8471 if (*arg)
8472 return arg; /* expand (next) command */
8473
8474 if (doautocmd)
8475 xp->xp_context = EXPAND_FILES; /* expand file names */
8476 else
8477 xp->xp_context = EXPAND_NOTHING; /* pattern is not expanded */
8478 return NULL;
8479}
8480
8481/*
8482 * Function given to ExpandGeneric() to obtain the list of event names.
8483 */
8484/*ARGSUSED*/
8485 char_u *
8486get_event_name(xp, idx)
8487 expand_T *xp;
8488 int idx;
8489{
8490 if (idx < augroups.ga_len) /* First list group names, if wanted */
8491 {
8492 if (!include_groups || AUGROUP_NAME(idx) == NULL)
8493 return (char_u *)""; /* skip deleted entries */
8494 return AUGROUP_NAME(idx); /* return a name */
8495 }
8496 return (char_u *)event_names[idx - augroups.ga_len].name;
8497}
8498
8499#endif /* FEAT_CMDL_COMPL */
8500
8501/*
8502 * Return TRUE if an autocommand is defined for "event" and "pattern".
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008503 * "pattern" can be NULL to accept any pattern. Buffer-local patterns
8504 * <buffer> or <buffer=N> are accepted.
8505 * Used for exists("#Event#pat")
Bram Moolenaar071d4272004-06-13 20:20:40 +00008506 */
8507 int
8508au_exists(name, name_end, pattern)
8509 char_u *name;
8510 char_u *name_end;
8511 char_u *pattern;
8512{
8513 char_u *event_name;
8514 char_u *p;
8515 EVENT_T event;
8516 AutoPat *ap;
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008517 buf_T *buflocal_buf = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00008518
8519 /* find the index (enum) for the event name */
8520 event_name = vim_strnsave(name, (int)(name_end - name));
8521 if (event_name == NULL)
8522 return FALSE;
8523 event = event_name2nr(event_name, &p);
8524 vim_free(event_name);
8525
8526 /* return FALSE if the event name is not recognized */
8527 if (event == NUM_EVENTS) /* unknown event name */
8528 return FALSE;
8529
8530 /* Find the first autocommand for this event.
8531 * If there isn't any, return FALSE;
8532 * If there is one and no pattern given, return TRUE; */
8533 ap = first_autopat[(int)event];
8534 if (ap == NULL)
8535 return FALSE;
8536 if (pattern == NULL)
8537 return TRUE;
8538
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008539 /* if pattern is "<buffer>", special handling is needed which uses curbuf */
8540 /* for pattern "<buffer=N>, fnamecmp() will work fine */
8541 if (STRICMP(pattern, "<buffer>") == 0)
8542 buflocal_buf = curbuf;
8543
Bram Moolenaar071d4272004-06-13 20:20:40 +00008544 /* Check if there is an autocommand with the given pattern. */
8545 for ( ; ap != NULL; ap = ap->next)
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008546 /* only use a pattern when it has not been removed and has commands. */
8547 /* For buffer-local autocommands, fnamecmp() works fine. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008548 if (ap->pat != NULL && ap->cmds != NULL
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008549 && (buflocal_buf == NULL
8550 ? fnamecmp(ap->pat, pattern) == 0
8551 : ap->buflocal_nr == buflocal_buf->b_fnum))
Bram Moolenaar071d4272004-06-13 20:20:40 +00008552 return TRUE;
8553
8554 return FALSE;
8555}
Bram Moolenaarb5bf5b82004-12-24 14:35:23 +00008556
Bram Moolenaar071d4272004-06-13 20:20:40 +00008557#endif /* FEAT_AUTOCMD */
8558
8559#if defined(FEAT_AUTOCMD) || defined(FEAT_WILDIGN) || defined(PROTO)
8560/*
Bram Moolenaar748bf032005-02-02 23:04:36 +00008561 * Try matching a filename with a "pattern" ("prog" is NULL), or use the
8562 * precompiled regprog "prog" ("pattern" is NULL). That avoids calling
8563 * vim_regcomp() often.
Bram Moolenaar071d4272004-06-13 20:20:40 +00008564 * Used for autocommands and 'wildignore'.
8565 * Returns TRUE if there is a match, FALSE otherwise.
8566 */
8567 int
Bram Moolenaar748bf032005-02-02 23:04:36 +00008568match_file_pat(pattern, prog, fname, sfname, tail, allow_dirs)
Bram Moolenaar071d4272004-06-13 20:20:40 +00008569 char_u *pattern; /* pattern to match with */
Bram Moolenaar748bf032005-02-02 23:04:36 +00008570 regprog_T *prog; /* pre-compiled regprog or NULL */
Bram Moolenaar071d4272004-06-13 20:20:40 +00008571 char_u *fname; /* full path of file name */
8572 char_u *sfname; /* short file name or NULL */
8573 char_u *tail; /* tail of path */
8574 int allow_dirs; /* allow matching with dir */
8575{
8576 regmatch_T regmatch;
8577 int result = FALSE;
8578#ifdef FEAT_OSFILETYPE
8579 int no_pattern = FALSE; /* TRUE if check is filetype only */
8580 char_u *type_start;
8581 char_u c;
8582 int match = FALSE;
8583#endif
8584
8585#ifdef CASE_INSENSITIVE_FILENAME
8586 regmatch.rm_ic = TRUE; /* Always ignore case */
8587#else
8588 regmatch.rm_ic = FALSE; /* Don't ever ignore case */
8589#endif
8590#ifdef FEAT_OSFILETYPE
8591 if (*pattern == '<')
8592 {
8593 /* There is a filetype condition specified with this pattern.
8594 * Check the filetype matches first. If not, don't bother with the
8595 * pattern (set regprog to NULL).
8596 * Always use magic for the regexp.
8597 */
8598
8599 for (type_start = pattern + 1; (c = *pattern); pattern++)
8600 {
8601 if ((c == ';' || c == '>') && match == FALSE)
8602 {
8603 *pattern = NUL; /* Terminate the string */
8604 match = mch_check_filetype(fname, type_start);
8605 *pattern = c; /* Restore the terminator */
8606 type_start = pattern + 1;
8607 }
8608 if (c == '>')
8609 break;
8610 }
8611
8612 /* (c should never be NUL, but check anyway) */
8613 if (match == FALSE || c == NUL)
8614 regmatch.regprog = NULL; /* Doesn't match - don't check pat. */
8615 else if (*pattern == NUL)
8616 {
8617 regmatch.regprog = NULL; /* Vim will try to free regprog later */
8618 no_pattern = TRUE; /* Always matches - don't check pat. */
8619 }
8620 else
8621 regmatch.regprog = vim_regcomp(pattern + 1, RE_MAGIC);
8622 }
8623 else
8624#endif
Bram Moolenaar748bf032005-02-02 23:04:36 +00008625 {
8626 if (prog != NULL)
8627 regmatch.regprog = prog;
8628 else
8629 regmatch.regprog = vim_regcomp(pattern, RE_MAGIC);
8630 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00008631
8632 /*
8633 * Try for a match with the pattern with:
8634 * 1. the full file name, when the pattern has a '/'.
8635 * 2. the short file name, when the pattern has a '/'.
8636 * 3. the tail of the file name, when the pattern has no '/'.
8637 */
8638 if (
8639#ifdef FEAT_OSFILETYPE
8640 /* If the check is for a filetype only and we don't care
8641 * about the path then skip all the regexp stuff.
8642 */
8643 no_pattern ||
8644#endif
8645 (regmatch.regprog != NULL
8646 && ((allow_dirs
8647 && (vim_regexec(&regmatch, fname, (colnr_T)0)
8648 || (sfname != NULL
8649 && vim_regexec(&regmatch, sfname, (colnr_T)0))))
8650 || (!allow_dirs && vim_regexec(&regmatch, tail, (colnr_T)0)))))
8651 result = TRUE;
8652
Bram Moolenaar748bf032005-02-02 23:04:36 +00008653 if (prog == NULL)
8654 vim_free(regmatch.regprog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008655 return result;
8656}
8657#endif
8658
8659#if defined(FEAT_WILDIGN) || defined(PROTO)
8660/*
8661 * Return TRUE if a file matches with a pattern in "list".
8662 * "list" is a comma-separated list of patterns, like 'wildignore'.
8663 * "sfname" is the short file name or NULL, "ffname" the long file name.
8664 */
8665 int
8666match_file_list(list, sfname, ffname)
8667 char_u *list;
8668 char_u *sfname;
8669 char_u *ffname;
8670{
8671 char_u buf[100];
8672 char_u *tail;
8673 char_u *regpat;
8674 char allow_dirs;
8675 int match;
8676 char_u *p;
8677
8678 tail = gettail(sfname);
8679
8680 /* try all patterns in 'wildignore' */
8681 p = list;
8682 while (*p)
8683 {
8684 copy_option_part(&p, buf, 100, ",");
8685 regpat = file_pat_to_reg_pat(buf, NULL, &allow_dirs, FALSE);
8686 if (regpat == NULL)
8687 break;
Bram Moolenaar748bf032005-02-02 23:04:36 +00008688 match = match_file_pat(regpat, NULL, ffname, sfname,
8689 tail, (int)allow_dirs);
Bram Moolenaar071d4272004-06-13 20:20:40 +00008690 vim_free(regpat);
8691 if (match)
8692 return TRUE;
8693 }
8694 return FALSE;
8695}
8696#endif
8697
8698/*
8699 * Convert the given pattern "pat" which has shell style wildcards in it, into
8700 * a regular expression, and return the result in allocated memory. If there
8701 * is a directory path separator to be matched, then TRUE is put in
8702 * allow_dirs, otherwise FALSE is put there -- webb.
8703 * Handle backslashes before special characters, like "\*" and "\ ".
8704 *
8705 * If FEAT_OSFILETYPE defined then pass initial <type> through unchanged. Eg:
8706 * '<html>myfile' becomes '<html>^myfile$' -- leonard.
8707 *
8708 * Returns NULL when out of memory.
8709 */
8710/*ARGSUSED*/
8711 char_u *
8712file_pat_to_reg_pat(pat, pat_end, allow_dirs, no_bslash)
8713 char_u *pat;
8714 char_u *pat_end; /* first char after pattern or NULL */
8715 char *allow_dirs; /* Result passed back out in here */
8716 int no_bslash; /* Don't use a backward slash as pathsep */
8717{
8718 int size;
8719 char_u *endp;
8720 char_u *reg_pat;
8721 char_u *p;
8722 int i;
8723 int nested = 0;
8724 int add_dollar = TRUE;
8725#ifdef FEAT_OSFILETYPE
8726 int check_length = 0;
8727#endif
8728
8729 if (allow_dirs != NULL)
8730 *allow_dirs = FALSE;
8731 if (pat_end == NULL)
8732 pat_end = pat + STRLEN(pat);
8733
8734#ifdef FEAT_OSFILETYPE
8735 /* Find out how much of the string is the filetype check */
8736 if (*pat == '<')
8737 {
8738 /* Count chars until the next '>' */
8739 for (p = pat + 1; p < pat_end && *p != '>'; p++)
8740 ;
8741 if (p < pat_end)
8742 {
8743 /* Pattern is of the form <.*>.* */
8744 check_length = p - pat + 1;
8745 if (p + 1 >= pat_end)
8746 {
8747 /* The 'pattern' is a filetype check ONLY */
8748 reg_pat = (char_u *)alloc(check_length + 1);
8749 if (reg_pat != NULL)
8750 {
8751 mch_memmove(reg_pat, pat, (size_t)check_length);
8752 reg_pat[check_length] = NUL;
8753 }
8754 return reg_pat;
8755 }
8756 }
8757 /* else: there was no closing '>' - assume it was a normal pattern */
8758
8759 }
8760 pat += check_length;
8761 size = 2 + check_length;
8762#else
8763 size = 2; /* '^' at start, '$' at end */
8764#endif
8765
8766 for (p = pat; p < pat_end; p++)
8767 {
8768 switch (*p)
8769 {
8770 case '*':
8771 case '.':
8772 case ',':
8773 case '{':
8774 case '}':
8775 case '~':
8776 size += 2; /* extra backslash */
8777 break;
8778#ifdef BACKSLASH_IN_FILENAME
8779 case '\\':
8780 case '/':
8781 size += 4; /* could become "[\/]" */
8782 break;
8783#endif
8784 default:
8785 size++;
8786# ifdef FEAT_MBYTE
8787 if (enc_dbcs != 0 && (*mb_ptr2len_check)(p) > 1)
8788 {
8789 ++p;
8790 ++size;
8791 }
8792# endif
8793 break;
8794 }
8795 }
8796 reg_pat = alloc(size + 1);
8797 if (reg_pat == NULL)
8798 return NULL;
8799
8800#ifdef FEAT_OSFILETYPE
8801 /* Copy the type check in to the start. */
8802 if (check_length)
8803 mch_memmove(reg_pat, pat - check_length, (size_t)check_length);
8804 i = check_length;
8805#else
8806 i = 0;
8807#endif
8808
8809 if (pat[0] == '*')
8810 while (pat[0] == '*' && pat < pat_end - 1)
8811 pat++;
8812 else
8813 reg_pat[i++] = '^';
8814 endp = pat_end - 1;
8815 if (*endp == '*')
8816 {
8817 while (endp - pat > 0 && *endp == '*')
8818 endp--;
8819 add_dollar = FALSE;
8820 }
8821 for (p = pat; *p && nested >= 0 && p <= endp; p++)
8822 {
8823 switch (*p)
8824 {
8825 case '*':
8826 reg_pat[i++] = '.';
8827 reg_pat[i++] = '*';
8828 break;
8829 case '.':
8830#ifdef RISCOS
8831 if (allow_dirs != NULL)
8832 *allow_dirs = TRUE;
8833 /* FALLTHROUGH */
8834#endif
8835 case '~':
8836 reg_pat[i++] = '\\';
8837 reg_pat[i++] = *p;
8838 break;
8839 case '?':
8840#ifdef RISCOS
8841 case '#':
8842#endif
8843 reg_pat[i++] = '.';
8844 break;
8845 case '\\':
8846 if (p[1] == NUL)
8847 break;
8848#ifdef BACKSLASH_IN_FILENAME
8849 if (!no_bslash)
8850 {
8851 /* translate:
8852 * "\x" to "\\x" e.g., "dir\file"
8853 * "\*" to "\\.*" e.g., "dir\*.c"
8854 * "\?" to "\\." e.g., "dir\??.c"
8855 * "\+" to "\+" e.g., "fileX\+.c"
8856 */
8857 if ((vim_isfilec(p[1]) || p[1] == '*' || p[1] == '?')
8858 && p[1] != '+')
8859 {
8860 reg_pat[i++] = '[';
8861 reg_pat[i++] = '\\';
8862 reg_pat[i++] = '/';
8863 reg_pat[i++] = ']';
8864 if (allow_dirs != NULL)
8865 *allow_dirs = TRUE;
8866 break;
8867 }
8868 }
8869#endif
8870 if (*++p == '?'
8871#ifdef BACKSLASH_IN_FILENAME
8872 && no_bslash
8873#endif
8874 )
8875 reg_pat[i++] = '?';
8876 else
8877 if (*p == ',')
8878 reg_pat[i++] = ',';
8879 else
8880 {
8881 if (allow_dirs != NULL && vim_ispathsep(*p)
8882#ifdef BACKSLASH_IN_FILENAME
8883 && (!no_bslash || *p != '\\')
8884#endif
8885 )
8886 *allow_dirs = TRUE;
8887 reg_pat[i++] = '\\';
8888 reg_pat[i++] = *p;
8889 }
8890 break;
8891#ifdef BACKSLASH_IN_FILENAME
8892 case '/':
8893 reg_pat[i++] = '[';
8894 reg_pat[i++] = '\\';
8895 reg_pat[i++] = '/';
8896 reg_pat[i++] = ']';
8897 if (allow_dirs != NULL)
8898 *allow_dirs = TRUE;
8899 break;
8900#endif
8901 case '{':
8902 reg_pat[i++] = '\\';
8903 reg_pat[i++] = '(';
8904 nested++;
8905 break;
8906 case '}':
8907 reg_pat[i++] = '\\';
8908 reg_pat[i++] = ')';
8909 --nested;
8910 break;
8911 case ',':
8912 if (nested)
8913 {
8914 reg_pat[i++] = '\\';
8915 reg_pat[i++] = '|';
8916 }
8917 else
8918 reg_pat[i++] = ',';
8919 break;
8920 default:
8921# ifdef FEAT_MBYTE
8922 if (enc_dbcs != 0 && (*mb_ptr2len_check)(p) > 1)
8923 reg_pat[i++] = *p++;
8924 else
8925# endif
8926 if (allow_dirs != NULL && vim_ispathsep(*p))
8927 *allow_dirs = TRUE;
8928 reg_pat[i++] = *p;
8929 break;
8930 }
8931 }
8932 if (add_dollar)
8933 reg_pat[i++] = '$';
8934 reg_pat[i] = NUL;
8935 if (nested != 0)
8936 {
8937 if (nested < 0)
8938 EMSG(_("E219: Missing {."));
8939 else
8940 EMSG(_("E220: Missing }."));
8941 vim_free(reg_pat);
8942 reg_pat = NULL;
8943 }
8944 return reg_pat;
8945}