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