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