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