blob: 029a3393802ce269051f9585fa3d17550e79069e [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
3988 * (could be a pipe). */
3989 if (fsync(fd) != 0 && !device)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003990 {
3991 errmsg = (char_u *)_("E667: Fsync failed");
3992 end = 0;
3993 }
3994#endif
3995
3996 if (close(fd) != 0)
3997 {
3998 errmsg = (char_u *)_("E512: Close failed");
3999 end = 0;
4000 }
4001
4002#ifdef UNIX
4003 if (made_writable)
4004 perm &= ~0200; /* reset 'w' bit for security reasons */
4005#endif
4006 if (perm >= 0) /* set perm. of new file same as old file */
4007 (void)mch_setperm(wfname, perm);
4008#ifdef RISCOS
4009 if (!append && !filtering)
4010 /* Set the filetype after writing the file. */
4011 mch_set_filetype(wfname, buf->b_p_oft);
4012#endif
4013#ifdef HAVE_ACL
4014 /* Probably need to set the ACL before changing the user (can't set the
4015 * ACL on a file the user doesn't own). */
4016 if (!backup_copy)
4017 mch_set_acl(wfname, acl);
4018#endif
4019
4020#ifdef UNIX
4021 /* When creating a new file, set its owner/group to that of the original
4022 * file. Get the new device and inode number. */
4023 if (backup != NULL && !backup_copy)
4024 {
4025 struct stat st;
4026
4027 /* don't change the owner when it's already OK, some systems remove
4028 * permission or ACL stuff */
4029 if (mch_stat((char *)wfname, &st) < 0
4030 || st.st_uid != st_old.st_uid
4031 || st.st_gid != st_old.st_gid)
4032 {
4033 chown((char *)wfname, st_old.st_uid, st_old.st_gid);
4034 if (perm >= 0) /* set permission again, may have changed */
4035 (void)mch_setperm(wfname, perm);
4036 }
4037 buf_setino(buf);
4038 }
4039#endif
4040
4041
4042#if defined(FEAT_MBYTE) && defined(FEAT_EVAL)
4043 if (wfname != fname)
4044 {
4045 /*
4046 * The file was written to a temp file, now it needs to be converted
4047 * with 'charconvert' to (overwrite) the output file.
4048 */
4049 if (end != 0)
4050 {
4051 if (eval_charconvert(enc_utf8 ? (char_u *)"utf-8" : p_enc, fenc,
4052 wfname, fname) == FAIL)
4053 {
4054 write_info.bw_conv_error = TRUE;
4055 end = 0;
4056 }
4057 }
4058 mch_remove(wfname);
4059 vim_free(wfname);
4060 }
4061#endif
4062
4063 if (end == 0)
4064 {
4065 if (errmsg == NULL)
4066 {
4067#ifdef FEAT_MBYTE
4068 if (write_info.bw_conv_error)
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00004069 errmsg = (char_u *)_("E513: write error, conversion failed (make 'fenc' empty to override)");
Bram Moolenaar071d4272004-06-13 20:20:40 +00004070 else
4071#endif
4072 if (got_int)
4073 errmsg = (char_u *)_(e_interr);
4074 else
4075 errmsg = (char_u *)_("E514: write error (file system full?)");
4076 }
4077
4078 /*
4079 * If we have a backup file, try to put it in place of the new file,
4080 * because the new file is probably corrupt. This avoids loosing the
4081 * original file when trying to make a backup when writing the file a
4082 * second time.
4083 * When "backup_copy" is set we need to copy the backup over the new
4084 * file. Otherwise rename the backup file.
4085 * If this is OK, don't give the extra warning message.
4086 */
4087 if (backup != NULL)
4088 {
4089 if (backup_copy)
4090 {
4091 /* This may take a while, if we were interrupted let the user
4092 * know we got the message. */
4093 if (got_int)
4094 {
4095 MSG(_(e_interr));
4096 out_flush();
4097 }
4098 if ((fd = mch_open((char *)backup, O_RDONLY | O_EXTRA, 0)) >= 0)
4099 {
4100 if ((write_info.bw_fd = mch_open((char *)fname,
4101 O_WRONLY | O_CREAT | O_TRUNC | O_EXTRA, 0666)) >= 0)
4102 {
4103 /* copy the file. */
4104 write_info.bw_buf = smallbuf;
4105#ifdef HAS_BW_FLAGS
4106 write_info.bw_flags = FIO_NOCONVERT;
4107#endif
4108 while ((write_info.bw_len = vim_read(fd, smallbuf,
4109 SMBUFSIZE)) > 0)
4110 if (buf_write_bytes(&write_info) == FAIL)
4111 break;
4112
4113 if (close(write_info.bw_fd) >= 0
4114 && write_info.bw_len == 0)
4115 end = 1; /* success */
4116 }
4117 close(fd); /* ignore errors for closing read file */
4118 }
4119 }
4120 else
4121 {
4122 if (vim_rename(backup, fname) == 0)
4123 end = 1;
4124 }
4125 }
4126 goto fail;
4127 }
4128
4129 lnum -= start; /* compute number of written lines */
4130 --no_wait_return; /* may wait for return now */
4131
4132#if !(defined(UNIX) || defined(VMS))
4133 fname = sfname; /* use shortname now, for the messages */
4134#endif
4135 if (!filtering)
4136 {
4137 msg_add_fname(buf, fname); /* put fname in IObuff with quotes */
4138 c = FALSE;
4139#ifdef FEAT_MBYTE
4140 if (write_info.bw_conv_error)
4141 {
4142 STRCAT(IObuff, _(" CONVERSION ERROR"));
4143 c = TRUE;
4144 }
4145 else if (notconverted)
4146 {
4147 STRCAT(IObuff, _("[NOT converted]"));
4148 c = TRUE;
4149 }
4150 else if (converted)
4151 {
4152 STRCAT(IObuff, _("[converted]"));
4153 c = TRUE;
4154 }
4155#endif
4156 if (device)
4157 {
4158 STRCAT(IObuff, _("[Device]"));
4159 c = TRUE;
4160 }
4161 else if (newfile)
4162 {
4163 STRCAT(IObuff, shortmess(SHM_NEW) ? _("[New]") : _("[New File]"));
4164 c = TRUE;
4165 }
4166 if (no_eol)
4167 {
4168 msg_add_eol();
4169 c = TRUE;
4170 }
4171 /* may add [unix/dos/mac] */
4172 if (msg_add_fileformat(fileformat))
4173 c = TRUE;
4174#ifdef FEAT_CRYPT
4175 if (wb_flags & FIO_ENCRYPTED)
4176 {
4177 STRCAT(IObuff, _("[crypted]"));
4178 c = TRUE;
4179 }
4180#endif
4181 msg_add_lines(c, (long)lnum, nchars); /* add line/char count */
4182 if (!shortmess(SHM_WRITE))
4183 {
4184 if (append)
4185 STRCAT(IObuff, shortmess(SHM_WRI) ? _(" [a]") : _(" appended"));
4186 else
4187 STRCAT(IObuff, shortmess(SHM_WRI) ? _(" [w]") : _(" written"));
4188 }
4189
4190 set_keep_msg(msg_trunc_attr(IObuff, FALSE, 0));
4191 keep_msg_attr = 0;
4192 }
4193
4194 if (reset_changed && whole
4195#ifdef FEAT_MBYTE
4196 && !write_info.bw_conv_error
4197#endif
4198 ) /* when written everything correctly */
4199 {
4200 unchanged(buf, TRUE);
4201 u_unchanged(buf);
4202 }
4203
4204 /*
4205 * If written to the current file, update the timestamp of the swap file
4206 * and reset the BF_WRITE_MASK flags. Also sets buf->b_mtime.
4207 */
4208 if (overwriting)
4209 {
4210 ml_timestamp(buf);
4211 buf->b_flags &= ~BF_WRITE_MASK;
4212 }
4213
4214 /*
4215 * If we kept a backup until now, and we are in patch mode, then we make
4216 * the backup file our 'original' file.
4217 */
4218 if (*p_pm && dobackup)
4219 {
4220 char *org = (char *)buf_modname(
4221#ifdef SHORT_FNAME
4222 TRUE,
4223#else
4224 (buf->b_p_sn || buf->b_shortname),
4225#endif
4226 fname, p_pm, FALSE);
4227
4228 if (backup != NULL)
4229 {
4230 struct stat st;
4231
4232 /*
4233 * If the original file does not exist yet
4234 * the current backup file becomes the original file
4235 */
4236 if (org == NULL)
4237 EMSG(_("E205: Patchmode: can't save original file"));
4238 else if (mch_stat(org, &st) < 0)
4239 {
4240 vim_rename(backup, (char_u *)org);
4241 vim_free(backup); /* don't delete the file */
4242 backup = NULL;
4243#ifdef UNIX
4244 set_file_time((char_u *)org, st_old.st_atime, st_old.st_mtime);
4245#endif
4246 }
4247 }
4248 /*
4249 * If there is no backup file, remember that a (new) file was
4250 * created.
4251 */
4252 else
4253 {
4254 int empty_fd;
4255
4256 if (org == NULL
4257 || (empty_fd = mch_open(org, O_CREAT | O_EXTRA | O_EXCL,
4258 0666)) < 0)
4259 EMSG(_("E206: patchmode: can't touch empty original file"));
4260 else
4261 close(empty_fd);
4262 }
4263 if (org != NULL)
4264 {
4265 mch_setperm((char_u *)org, mch_getperm(fname) & 0777);
4266 vim_free(org);
4267 }
4268 }
4269
4270 /*
4271 * Remove the backup unless 'backup' option is set
4272 */
4273 if (!p_bk && backup != NULL && mch_remove(backup) != 0)
4274 EMSG(_("E207: Can't delete backup file"));
4275
4276#ifdef FEAT_SUN_WORKSHOP
4277 if (usingSunWorkShop)
4278 workshop_file_saved((char *) ffname);
4279#endif
4280
4281 goto nofail;
4282
4283 /*
4284 * Finish up. We get here either after failure or success.
4285 */
4286fail:
4287 --no_wait_return; /* may wait for return now */
4288nofail:
4289
4290 /* Done saving, we accept changed buffer warnings again */
4291 buf->b_saving = FALSE;
4292
4293 vim_free(backup);
4294 if (buffer != smallbuf)
4295 vim_free(buffer);
4296#ifdef FEAT_MBYTE
4297 vim_free(fenc_tofree);
4298 vim_free(write_info.bw_conv_buf);
4299# ifdef USE_ICONV
4300 if (write_info.bw_iconv_fd != (iconv_t)-1)
4301 {
4302 iconv_close(write_info.bw_iconv_fd);
4303 write_info.bw_iconv_fd = (iconv_t)-1;
4304 }
4305# endif
4306#endif
4307#ifdef HAVE_ACL
4308 mch_free_acl(acl);
4309#endif
4310
4311 if (errmsg != NULL)
4312 {
4313 int numlen = errnum != NULL ? STRLEN(errnum) : 0;
4314
4315 attr = hl_attr(HLF_E); /* set highlight for error messages */
4316 msg_add_fname(buf,
4317#ifndef UNIX
4318 sfname
4319#else
4320 fname
4321#endif
4322 ); /* put file name in IObuff with quotes */
4323 if (STRLEN(IObuff) + STRLEN(errmsg) + numlen >= IOSIZE)
4324 IObuff[IOSIZE - STRLEN(errmsg) - numlen - 1] = NUL;
4325 /* If the error message has the form "is ...", put the error number in
4326 * front of the file name. */
4327 if (errnum != NULL)
4328 {
4329 mch_memmove(IObuff + numlen, IObuff, STRLEN(IObuff) + 1);
4330 mch_memmove(IObuff, errnum, (size_t)numlen);
4331 }
4332 STRCAT(IObuff, errmsg);
4333 emsg(IObuff);
4334
4335 retval = FAIL;
4336 if (end == 0)
4337 {
4338 MSG_PUTS_ATTR(_("\nWARNING: Original file may be lost or damaged\n"),
4339 attr | MSG_HIST);
4340 MSG_PUTS_ATTR(_("don't quit the editor until the file is successfully written!"),
4341 attr | MSG_HIST);
4342
4343 /* Update the timestamp to avoid an "overwrite changed file"
4344 * prompt when writing again. */
4345 if (mch_stat((char *)fname, &st_old) >= 0)
4346 {
4347 buf_store_time(buf, &st_old, fname);
4348 buf->b_mtime_read = buf->b_mtime;
4349 }
4350 }
4351 }
4352 msg_scroll = msg_save;
4353
4354#ifdef FEAT_AUTOCMD
4355#ifdef FEAT_EVAL
4356 if (!should_abort(retval))
4357#else
4358 if (!got_int)
4359#endif
4360 {
4361 aco_save_T aco;
4362
4363 write_no_eol_lnum = 0; /* in case it was set by the previous read */
4364
4365 /*
4366 * Apply POST autocommands.
4367 * Careful: The autocommands may call buf_write() recursively!
4368 */
4369 aucmd_prepbuf(&aco, buf);
4370
4371 if (append)
4372 apply_autocmds_exarg(EVENT_FILEAPPENDPOST, fname, fname,
4373 FALSE, curbuf, eap);
4374 else if (filtering)
4375 apply_autocmds_exarg(EVENT_FILTERWRITEPOST, NULL, fname,
4376 FALSE, curbuf, eap);
4377 else if (reset_changed && whole)
4378 apply_autocmds_exarg(EVENT_BUFWRITEPOST, fname, fname,
4379 FALSE, curbuf, eap);
4380 else
4381 apply_autocmds_exarg(EVENT_FILEWRITEPOST, fname, fname,
4382 FALSE, curbuf, eap);
4383
4384 /* restore curwin/curbuf and a few other things */
4385 aucmd_restbuf(&aco);
4386
4387#ifdef FEAT_EVAL
4388 if (aborting()) /* autocmds may abort script processing */
4389 retval = FALSE;
4390#endif
4391 }
4392#endif
4393
4394 got_int |= prev_got_int;
4395
4396#ifdef MACOS_CLASSIC /* TODO: Is it need for MACOS_X? (Dany) */
4397 /* Update machine specific information. */
4398 mch_post_buffer_write(buf);
4399#endif
4400 return retval;
4401}
4402
4403/*
4404 * Put file name into IObuff with quotes.
4405 */
Bram Moolenaar009b2592004-10-24 19:18:58 +00004406 void
Bram Moolenaar071d4272004-06-13 20:20:40 +00004407msg_add_fname(buf, fname)
4408 buf_T *buf;
4409 char_u *fname;
4410{
4411 if (fname == NULL)
4412 fname = (char_u *)"-stdin-";
4413 home_replace(buf, fname, IObuff + 1, IOSIZE - 4, TRUE);
4414 IObuff[0] = '"';
4415 STRCAT(IObuff, "\" ");
4416}
4417
4418/*
4419 * Append message for text mode to IObuff.
4420 * Return TRUE if something appended.
4421 */
4422 static int
4423msg_add_fileformat(eol_type)
4424 int eol_type;
4425{
4426#ifndef USE_CRNL
4427 if (eol_type == EOL_DOS)
4428 {
4429 STRCAT(IObuff, shortmess(SHM_TEXT) ? _("[dos]") : _("[dos format]"));
4430 return TRUE;
4431 }
4432#endif
4433#ifndef USE_CR
4434 if (eol_type == EOL_MAC)
4435 {
4436 STRCAT(IObuff, shortmess(SHM_TEXT) ? _("[mac]") : _("[mac format]"));
4437 return TRUE;
4438 }
4439#endif
4440#if defined(USE_CRNL) || defined(USE_CR)
4441 if (eol_type == EOL_UNIX)
4442 {
4443 STRCAT(IObuff, shortmess(SHM_TEXT) ? _("[unix]") : _("[unix format]"));
4444 return TRUE;
4445 }
4446#endif
4447 return FALSE;
4448}
4449
4450/*
4451 * Append line and character count to IObuff.
4452 */
Bram Moolenaar009b2592004-10-24 19:18:58 +00004453 void
Bram Moolenaar071d4272004-06-13 20:20:40 +00004454msg_add_lines(insert_space, lnum, nchars)
4455 int insert_space;
4456 long lnum;
4457 long nchars;
4458{
4459 char_u *p;
4460
4461 p = IObuff + STRLEN(IObuff);
4462
4463 if (insert_space)
4464 *p++ = ' ';
4465 if (shortmess(SHM_LINES))
4466 sprintf((char *)p, "%ldL, %ldC", lnum, nchars);
4467 else
4468 {
4469 if (lnum == 1)
4470 STRCPY(p, _("1 line, "));
4471 else
4472 sprintf((char *)p, _("%ld lines, "), lnum);
4473 p += STRLEN(p);
4474 if (nchars == 1)
4475 STRCPY(p, _("1 character"));
4476 else
4477 sprintf((char *)p, _("%ld characters"), nchars);
4478 }
4479}
4480
4481/*
4482 * Append message for missing line separator to IObuff.
4483 */
4484 static void
4485msg_add_eol()
4486{
4487 STRCAT(IObuff, shortmess(SHM_LAST) ? _("[noeol]") : _("[Incomplete last line]"));
4488}
4489
4490/*
4491 * Check modification time of file, before writing to it.
4492 * The size isn't checked, because using a tool like "gzip" takes care of
4493 * using the same timestamp but can't set the size.
4494 */
4495 static int
4496check_mtime(buf, st)
4497 buf_T *buf;
4498 struct stat *st;
4499{
4500 if (buf->b_mtime_read != 0
4501 && time_differs((long)st->st_mtime, buf->b_mtime_read))
4502 {
4503 msg_scroll = TRUE; /* don't overwrite messages here */
4504 msg_silent = 0; /* must give this prompt */
4505 /* don't use emsg() here, don't want to flush the buffers */
4506 MSG_ATTR(_("WARNING: The file has been changed since reading it!!!"),
4507 hl_attr(HLF_E));
4508 if (ask_yesno((char_u *)_("Do you really want to write to it"),
4509 TRUE) == 'n')
4510 return FAIL;
4511 msg_scroll = FALSE; /* always overwrite the file message now */
4512 }
4513 return OK;
4514}
4515
4516 static int
4517time_differs(t1, t2)
4518 long t1, t2;
4519{
4520#if defined(__linux__) || defined(MSDOS) || defined(MSWIN)
4521 /* On a FAT filesystem, esp. under Linux, there are only 5 bits to store
4522 * the seconds. Since the roundoff is done when flushing the inode, the
4523 * time may change unexpectedly by one second!!! */
4524 return (t1 - t2 > 1 || t2 - t1 > 1);
4525#else
4526 return (t1 != t2);
4527#endif
4528}
4529
4530/*
4531 * Call write() to write a number of bytes to the file.
4532 * Also handles encryption and 'encoding' conversion.
4533 *
4534 * Return FAIL for failure, OK otherwise.
4535 */
4536 static int
4537buf_write_bytes(ip)
4538 struct bw_info *ip;
4539{
4540 int wlen;
4541 char_u *buf = ip->bw_buf; /* data to write */
4542 int len = ip->bw_len; /* length of data */
4543#ifdef HAS_BW_FLAGS
4544 int flags = ip->bw_flags; /* extra flags */
4545#endif
4546
4547#ifdef FEAT_MBYTE
4548 /*
4549 * Skip conversion when writing the crypt magic number or the BOM.
4550 */
4551 if (!(flags & FIO_NOCONVERT))
4552 {
4553 char_u *p;
4554 unsigned c;
4555 int n;
4556
4557 if (flags & FIO_UTF8)
4558 {
4559 /*
4560 * Convert latin1 in the buffer to UTF-8 in the file.
4561 */
4562 p = ip->bw_conv_buf; /* translate to buffer */
4563 for (wlen = 0; wlen < len; ++wlen)
4564 p += utf_char2bytes(buf[wlen], p);
4565 buf = ip->bw_conv_buf;
4566 len = (int)(p - ip->bw_conv_buf);
4567 }
4568 else if (flags & (FIO_UCS4 | FIO_UTF16 | FIO_UCS2 | FIO_LATIN1))
4569 {
4570 /*
4571 * Convert UTF-8 bytes in the buffer to UCS-2, UCS-4, UTF-16 or
4572 * Latin1 chars in the file.
4573 */
4574 if (flags & FIO_LATIN1)
4575 p = buf; /* translate in-place (can only get shorter) */
4576 else
4577 p = ip->bw_conv_buf; /* translate to buffer */
4578 for (wlen = 0; wlen < len; wlen += n)
4579 {
4580 if (wlen == 0 && ip->bw_restlen != 0)
4581 {
4582 int l;
4583
4584 /* Use remainder of previous call. Append the start of
4585 * buf[] to get a full sequence. Might still be too
4586 * short! */
4587 l = CONV_RESTLEN - ip->bw_restlen;
4588 if (l > len)
4589 l = len;
4590 mch_memmove(ip->bw_rest + ip->bw_restlen, buf, (size_t)l);
4591 n = utf_ptr2len_check_len(ip->bw_rest, ip->bw_restlen + l);
4592 if (n > ip->bw_restlen + len)
4593 {
4594 /* We have an incomplete byte sequence at the end to
4595 * be written. We can't convert it without the
4596 * remaining bytes. Keep them for the next call. */
4597 if (ip->bw_restlen + len > CONV_RESTLEN)
4598 return FAIL;
4599 ip->bw_restlen += len;
4600 break;
4601 }
4602 if (n > 1)
4603 c = utf_ptr2char(ip->bw_rest);
4604 else
4605 c = ip->bw_rest[0];
4606 if (n >= ip->bw_restlen)
4607 {
4608 n -= ip->bw_restlen;
4609 ip->bw_restlen = 0;
4610 }
4611 else
4612 {
4613 ip->bw_restlen -= n;
4614 mch_memmove(ip->bw_rest, ip->bw_rest + n,
4615 (size_t)ip->bw_restlen);
4616 n = 0;
4617 }
4618 }
4619 else
4620 {
4621 n = utf_ptr2len_check_len(buf + wlen, len - wlen);
4622 if (n > len - wlen)
4623 {
4624 /* We have an incomplete byte sequence at the end to
4625 * be written. We can't convert it without the
4626 * remaining bytes. Keep them for the next call. */
4627 if (len - wlen > CONV_RESTLEN)
4628 return FAIL;
4629 ip->bw_restlen = len - wlen;
4630 mch_memmove(ip->bw_rest, buf + wlen,
4631 (size_t)ip->bw_restlen);
4632 break;
4633 }
4634 if (n > 1)
4635 c = utf_ptr2char(buf + wlen);
4636 else
4637 c = buf[wlen];
4638 }
4639
4640 ip->bw_conv_error |= ucs2bytes(c, &p, flags);
4641 }
4642 if (flags & FIO_LATIN1)
4643 len = (int)(p - buf);
4644 else
4645 {
4646 buf = ip->bw_conv_buf;
4647 len = (int)(p - ip->bw_conv_buf);
4648 }
4649 }
4650
4651# ifdef WIN3264
4652 else if (flags & FIO_CODEPAGE)
4653 {
4654 /*
4655 * Convert UTF-8 or codepage to UCS-2 and then to MS-Windows
4656 * codepage.
4657 */
4658 char_u *from;
4659 size_t fromlen;
4660 char_u *to;
4661 int u8c;
4662 BOOL bad = FALSE;
4663 int needed;
4664
4665 if (ip->bw_restlen > 0)
4666 {
4667 /* Need to concatenate the remainder of the previous call and
4668 * the bytes of the current call. Use the end of the
4669 * conversion buffer for this. */
4670 fromlen = len + ip->bw_restlen;
4671 from = ip->bw_conv_buf + ip->bw_conv_buflen - fromlen;
4672 mch_memmove(from, ip->bw_rest, (size_t)ip->bw_restlen);
4673 mch_memmove(from + ip->bw_restlen, buf, (size_t)len);
4674 }
4675 else
4676 {
4677 from = buf;
4678 fromlen = len;
4679 }
4680
4681 to = ip->bw_conv_buf;
4682 if (enc_utf8)
4683 {
4684 /* Convert from UTF-8 to UCS-2, to the start of the buffer.
4685 * The buffer has been allocated to be big enough. */
4686 while (fromlen > 0)
4687 {
4688 n = utf_ptr2len_check_len(from, fromlen);
4689 if (n > (int)fromlen) /* incomplete byte sequence */
4690 break;
4691 u8c = utf_ptr2char(from);
4692 *to++ = (u8c & 0xff);
4693 *to++ = (u8c >> 8);
4694 fromlen -= n;
4695 from += n;
4696 }
4697
4698 /* Copy remainder to ip->bw_rest[] to be used for the next
4699 * call. */
4700 if (fromlen > CONV_RESTLEN)
4701 {
4702 /* weird overlong sequence */
4703 ip->bw_conv_error = TRUE;
4704 return FAIL;
4705 }
4706 mch_memmove(ip->bw_rest, from, fromlen);
4707 ip->bw_restlen = fromlen;
4708 }
4709 else
4710 {
4711 /* Convert from enc_codepage to UCS-2, to the start of the
4712 * buffer. The buffer has been allocated to be big enough. */
4713 ip->bw_restlen = 0;
4714 needed = MultiByteToWideChar(enc_codepage,
4715 MB_ERR_INVALID_CHARS, (LPCSTR)from, fromlen,
4716 NULL, 0);
4717 if (needed == 0)
4718 {
4719 /* When conversion fails there may be a trailing byte. */
4720 needed = MultiByteToWideChar(enc_codepage,
4721 MB_ERR_INVALID_CHARS, (LPCSTR)from, fromlen - 1,
4722 NULL, 0);
4723 if (needed == 0)
4724 {
4725 /* Conversion doesn't work. */
4726 ip->bw_conv_error = TRUE;
4727 return FAIL;
4728 }
4729 /* Save the trailing byte for the next call. */
4730 ip->bw_rest[0] = from[fromlen - 1];
4731 ip->bw_restlen = 1;
4732 }
4733 needed = MultiByteToWideChar(enc_codepage, MB_ERR_INVALID_CHARS,
4734 (LPCSTR)from, fromlen - ip->bw_restlen,
4735 (LPWSTR)to, needed);
4736 if (needed == 0)
4737 {
4738 /* Safety check: Conversion doesn't work. */
4739 ip->bw_conv_error = TRUE;
4740 return FAIL;
4741 }
4742 to += needed * 2;
4743 }
4744
4745 fromlen = to - ip->bw_conv_buf;
4746 buf = to;
4747# ifdef CP_UTF8 /* VC 4.1 doesn't define CP_UTF8 */
4748 if (FIO_GET_CP(flags) == CP_UTF8)
4749 {
4750 /* Convert from UCS-2 to UTF-8, using the remainder of the
4751 * conversion buffer. Fails when out of space. */
4752 for (from = ip->bw_conv_buf; fromlen > 1; fromlen -= 2)
4753 {
4754 u8c = *from++;
4755 u8c += (*from++ << 8);
4756 to += utf_char2bytes(u8c, to);
4757 if (to + 6 >= ip->bw_conv_buf + ip->bw_conv_buflen)
4758 {
4759 ip->bw_conv_error = TRUE;
4760 return FAIL;
4761 }
4762 }
4763 len = to - buf;
4764 }
4765 else
4766#endif
4767 {
4768 /* Convert from UCS-2 to the codepage, using the remainder of
4769 * the conversion buffer. If the conversion uses the default
4770 * character "0", the data doesn't fit in this encoding, so
4771 * fail. */
4772 len = WideCharToMultiByte(FIO_GET_CP(flags), 0,
4773 (LPCWSTR)ip->bw_conv_buf, (int)fromlen / sizeof(WCHAR),
4774 (LPSTR)to, ip->bw_conv_buflen - fromlen, 0, &bad);
4775 if (bad)
4776 {
4777 ip->bw_conv_error = TRUE;
4778 return FAIL;
4779 }
4780 }
4781 }
4782# endif
4783
4784# ifdef MACOS_X
4785 else if (flags & FIO_MACROMAN)
4786 {
4787 /*
4788 * Convert UTF-8 or latin1 to Apple MacRoman.
4789 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004790 char_u *from;
4791 size_t fromlen;
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00004792 extern int enc2macroman __ARGS((char_u *from, size_t fromlen,
4793 char_u *to, int *tolenp, int maxtolen, char_u *rest,
4794 int *restlenp));
Bram Moolenaar071d4272004-06-13 20:20:40 +00004795
4796 if (ip->bw_restlen > 0)
4797 {
4798 /* Need to concatenate the remainder of the previous call and
4799 * the bytes of the current call. Use the end of the
4800 * conversion buffer for this. */
4801 fromlen = len + ip->bw_restlen;
4802 from = ip->bw_conv_buf + ip->bw_conv_buflen - fromlen;
4803 mch_memmove(from, ip->bw_rest, (size_t)ip->bw_restlen);
4804 mch_memmove(from + ip->bw_restlen, buf, (size_t)len);
4805 }
4806 else
4807 {
4808 from = buf;
4809 fromlen = len;
4810 }
4811
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00004812 if (enc2macroman(from, fromlen,
4813 ip->bw_conv_buf, &len, ip->bw_conv_buflen,
4814 ip->bw_rest, &ip->bw_restlen) == FAIL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004815 {
4816 ip->bw_conv_error = TRUE;
4817 return FAIL;
4818 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004819 buf = ip->bw_conv_buf;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004820 }
4821# endif
4822
4823# ifdef USE_ICONV
4824 if (ip->bw_iconv_fd != (iconv_t)-1)
4825 {
4826 const char *from;
4827 size_t fromlen;
4828 char *to;
4829 size_t tolen;
4830
4831 /* Convert with iconv(). */
4832 if (ip->bw_restlen > 0)
4833 {
4834 /* Need to concatenate the remainder of the previous call and
4835 * the bytes of the current call. Use the end of the
4836 * conversion buffer for this. */
4837 fromlen = len + ip->bw_restlen;
4838 from = (char *)ip->bw_conv_buf + ip->bw_conv_buflen - fromlen;
4839 mch_memmove((void *)from, ip->bw_rest, (size_t)ip->bw_restlen);
4840 mch_memmove((void *)(from + ip->bw_restlen), buf, (size_t)len);
4841 tolen = ip->bw_conv_buflen - fromlen;
4842 }
4843 else
4844 {
4845 from = (const char *)buf;
4846 fromlen = len;
4847 tolen = ip->bw_conv_buflen;
4848 }
4849 to = (char *)ip->bw_conv_buf;
4850
4851 if (ip->bw_first)
4852 {
4853 size_t save_len = tolen;
4854
4855 /* output the initial shift state sequence */
4856 (void)iconv(ip->bw_iconv_fd, NULL, NULL, &to, &tolen);
4857
4858 /* There is a bug in iconv() on Linux (which appears to be
4859 * wide-spread) which sets "to" to NULL and messes up "tolen".
4860 */
4861 if (to == NULL)
4862 {
4863 to = (char *)ip->bw_conv_buf;
4864 tolen = save_len;
4865 }
4866 ip->bw_first = FALSE;
4867 }
4868
4869 /*
4870 * If iconv() has an error or there is not enough room, fail.
4871 */
4872 if ((iconv(ip->bw_iconv_fd, (void *)&from, &fromlen, &to, &tolen)
4873 == (size_t)-1 && ICONV_ERRNO != ICONV_EINVAL)
4874 || fromlen > CONV_RESTLEN)
4875 {
4876 ip->bw_conv_error = TRUE;
4877 return FAIL;
4878 }
4879
4880 /* copy remainder to ip->bw_rest[] to be used for the next call. */
4881 if (fromlen > 0)
4882 mch_memmove(ip->bw_rest, (void *)from, fromlen);
4883 ip->bw_restlen = (int)fromlen;
4884
4885 buf = ip->bw_conv_buf;
4886 len = (int)((char_u *)to - ip->bw_conv_buf);
4887 }
4888# endif
4889 }
4890#endif /* FEAT_MBYTE */
4891
4892#ifdef FEAT_CRYPT
4893 if (flags & FIO_ENCRYPTED) /* encrypt the data */
4894 {
4895 int ztemp, t, i;
4896
4897 for (i = 0; i < len; i++)
4898 {
4899 ztemp = buf[i];
4900 buf[i] = ZENCODE(ztemp, t);
4901 }
4902 }
4903#endif
4904
4905 /* Repeat the write(), it may be interrupted by a signal. */
4906 while (len)
4907 {
4908 wlen = vim_write(ip->bw_fd, buf, len);
4909 if (wlen <= 0) /* error! */
4910 return FAIL;
4911 len -= wlen;
4912 buf += wlen;
4913 }
4914 return OK;
4915}
4916
4917#ifdef FEAT_MBYTE
4918/*
4919 * Convert a Unicode character to bytes.
4920 */
4921 static int
4922ucs2bytes(c, pp, flags)
4923 unsigned c; /* in: character */
4924 char_u **pp; /* in/out: pointer to result */
4925 int flags; /* FIO_ flags */
4926{
4927 char_u *p = *pp;
4928 int error = FALSE;
4929 int cc;
4930
4931
4932 if (flags & FIO_UCS4)
4933 {
4934 if (flags & FIO_ENDIAN_L)
4935 {
4936 *p++ = c;
4937 *p++ = (c >> 8);
4938 *p++ = (c >> 16);
4939 *p++ = (c >> 24);
4940 }
4941 else
4942 {
4943 *p++ = (c >> 24);
4944 *p++ = (c >> 16);
4945 *p++ = (c >> 8);
4946 *p++ = c;
4947 }
4948 }
4949 else if (flags & (FIO_UCS2 | FIO_UTF16))
4950 {
4951 if (c >= 0x10000)
4952 {
4953 if (flags & FIO_UTF16)
4954 {
4955 /* Make two words, ten bits of the character in each. First
4956 * word is 0xd800 - 0xdbff, second one 0xdc00 - 0xdfff */
4957 c -= 0x10000;
4958 if (c >= 0x100000)
4959 error = TRUE;
4960 cc = ((c >> 10) & 0x3ff) + 0xd800;
4961 if (flags & FIO_ENDIAN_L)
4962 {
4963 *p++ = cc;
4964 *p++ = ((unsigned)cc >> 8);
4965 }
4966 else
4967 {
4968 *p++ = ((unsigned)cc >> 8);
4969 *p++ = cc;
4970 }
4971 c = (c & 0x3ff) + 0xdc00;
4972 }
4973 else
4974 error = TRUE;
4975 }
4976 if (flags & FIO_ENDIAN_L)
4977 {
4978 *p++ = c;
4979 *p++ = (c >> 8);
4980 }
4981 else
4982 {
4983 *p++ = (c >> 8);
4984 *p++ = c;
4985 }
4986 }
4987 else /* Latin1 */
4988 {
4989 if (c >= 0x100)
4990 {
4991 error = TRUE;
4992 *p++ = 0xBF;
4993 }
4994 else
4995 *p++ = c;
4996 }
4997
4998 *pp = p;
4999 return error;
5000}
5001
5002/*
5003 * Return TRUE if "a" and "b" are the same 'encoding'.
5004 * Ignores difference between "ansi" and "latin1", "ucs-4" and "ucs-4be", etc.
5005 */
5006 static int
5007same_encoding(a, b)
5008 char_u *a;
5009 char_u *b;
5010{
5011 int f;
5012
5013 if (STRCMP(a, b) == 0)
5014 return TRUE;
5015 f = get_fio_flags(a);
5016 return (f != 0 && get_fio_flags(b) == f);
5017}
5018
5019/*
5020 * Check "ptr" for a unicode encoding and return the FIO_ flags needed for the
5021 * internal conversion.
5022 * if "ptr" is an empty string, use 'encoding'.
5023 */
5024 static int
5025get_fio_flags(ptr)
5026 char_u *ptr;
5027{
5028 int prop;
5029
5030 if (*ptr == NUL)
5031 ptr = p_enc;
5032
5033 prop = enc_canon_props(ptr);
5034 if (prop & ENC_UNICODE)
5035 {
5036 if (prop & ENC_2BYTE)
5037 {
5038 if (prop & ENC_ENDIAN_L)
5039 return FIO_UCS2 | FIO_ENDIAN_L;
5040 return FIO_UCS2;
5041 }
5042 if (prop & ENC_4BYTE)
5043 {
5044 if (prop & ENC_ENDIAN_L)
5045 return FIO_UCS4 | FIO_ENDIAN_L;
5046 return FIO_UCS4;
5047 }
5048 if (prop & ENC_2WORD)
5049 {
5050 if (prop & ENC_ENDIAN_L)
5051 return FIO_UTF16 | FIO_ENDIAN_L;
5052 return FIO_UTF16;
5053 }
5054 return FIO_UTF8;
5055 }
5056 if (prop & ENC_LATIN1)
5057 return FIO_LATIN1;
5058 /* must be ENC_DBCS, requires iconv() */
5059 return 0;
5060}
5061
5062#ifdef WIN3264
5063/*
5064 * Check "ptr" for a MS-Windows codepage name and return the FIO_ flags needed
5065 * for the conversion MS-Windows can do for us. Also accept "utf-8".
5066 * Used for conversion between 'encoding' and 'fileencoding'.
5067 */
5068 static int
5069get_win_fio_flags(ptr)
5070 char_u *ptr;
5071{
5072 int cp;
5073
5074 /* Cannot do this when 'encoding' is not utf-8 and not a codepage. */
5075 if (!enc_utf8 && enc_codepage <= 0)
5076 return 0;
5077
5078 cp = encname2codepage(ptr);
5079 if (cp == 0)
5080 {
5081# ifdef CP_UTF8 /* VC 4.1 doesn't define CP_UTF8 */
5082 if (STRCMP(ptr, "utf-8") == 0)
5083 cp = CP_UTF8;
5084 else
5085# endif
5086 return 0;
5087 }
5088 return FIO_PUT_CP(cp) | FIO_CODEPAGE;
5089}
5090#endif
5091
5092#ifdef MACOS_X
5093/*
5094 * Check "ptr" for a Carbon supported encoding and return the FIO_ flags
5095 * needed for the internal conversion to/from utf-8 or latin1.
5096 */
5097 static int
5098get_mac_fio_flags(ptr)
5099 char_u *ptr;
5100{
5101 if ((enc_utf8 || STRCMP(p_enc, "latin1") == 0)
5102 && (enc_canon_props(ptr) & ENC_MACROMAN))
5103 return FIO_MACROMAN;
5104 return 0;
5105}
5106#endif
5107
5108/*
5109 * Check for a Unicode BOM (Byte Order Mark) at the start of p[size].
5110 * "size" must be at least 2.
5111 * Return the name of the encoding and set "*lenp" to the length.
5112 * Returns NULL when no BOM found.
5113 */
5114 static char_u *
5115check_for_bom(p, size, lenp, flags)
5116 char_u *p;
5117 long size;
5118 int *lenp;
5119 int flags;
5120{
5121 char *name = NULL;
5122 int len = 2;
5123
5124 if (p[0] == 0xef && p[1] == 0xbb && size >= 3 && p[2] == 0xbf
5125 && (flags == FIO_ALL || flags == 0))
5126 {
5127 name = "utf-8"; /* EF BB BF */
5128 len = 3;
5129 }
5130 else if (p[0] == 0xff && p[1] == 0xfe)
5131 {
5132 if (size >= 4 && p[2] == 0 && p[3] == 0
5133 && (flags == FIO_ALL || flags == (FIO_UCS4 | FIO_ENDIAN_L)))
5134 {
5135 name = "ucs-4le"; /* FF FE 00 00 */
5136 len = 4;
5137 }
5138 else if (flags == FIO_ALL || flags == (FIO_UCS2 | FIO_ENDIAN_L))
5139 name = "ucs-2le"; /* FF FE */
5140 else if (flags == (FIO_UTF16 | FIO_ENDIAN_L))
5141 name = "utf-16le"; /* FF FE */
5142 }
5143 else if (p[0] == 0xfe && p[1] == 0xff
5144 && (flags == FIO_ALL || flags == FIO_UCS2 || flags == FIO_UTF16))
5145 {
5146 if (flags == FIO_UTF16)
5147 name = "utf-16"; /* FE FF */
5148 else
5149 name = "ucs-2"; /* FE FF */
5150 }
5151 else if (size >= 4 && p[0] == 0 && p[1] == 0 && p[2] == 0xfe
5152 && p[3] == 0xff && (flags == FIO_ALL || flags == FIO_UCS4))
5153 {
5154 name = "ucs-4"; /* 00 00 FE FF */
5155 len = 4;
5156 }
5157
5158 *lenp = len;
5159 return (char_u *)name;
5160}
5161
5162/*
5163 * Generate a BOM in "buf[4]" for encoding "name".
5164 * Return the length of the BOM (zero when no BOM).
5165 */
5166 static int
5167make_bom(buf, name)
5168 char_u *buf;
5169 char_u *name;
5170{
5171 int flags;
5172 char_u *p;
5173
5174 flags = get_fio_flags(name);
5175
5176 /* Can't put a BOM in a non-Unicode file. */
5177 if (flags == FIO_LATIN1 || flags == 0)
5178 return 0;
5179
5180 if (flags == FIO_UTF8) /* UTF-8 */
5181 {
5182 buf[0] = 0xef;
5183 buf[1] = 0xbb;
5184 buf[2] = 0xbf;
5185 return 3;
5186 }
5187 p = buf;
5188 (void)ucs2bytes(0xfeff, &p, flags);
5189 return (int)(p - buf);
5190}
5191#endif
5192
5193/*
5194 * Try to find a shortname by comparing the fullname with the current
5195 * directory.
5196 * Returns NULL if not shorter name possible, pointer into "full_path"
5197 * otherwise.
5198 */
5199 char_u *
5200shorten_fname(full_path, dir_name)
5201 char_u *full_path;
5202 char_u *dir_name;
5203{
5204 int len;
5205 char_u *p;
5206
5207 if (full_path == NULL)
5208 return NULL;
5209 len = (int)STRLEN(dir_name);
5210 if (fnamencmp(dir_name, full_path, len) == 0)
5211 {
5212 p = full_path + len;
5213#if defined(MSDOS) || defined(MSWIN) || defined(OS2)
5214 /*
5215 * MSDOS: when a file is in the root directory, dir_name will end in a
5216 * slash, since C: by itself does not define a specific dir. In this
5217 * case p may already be correct. <negri>
5218 */
5219 if (!((len > 2) && (*(p - 2) == ':')))
5220#endif
5221 {
5222 if (vim_ispathsep(*p))
5223 ++p;
5224#ifndef VMS /* the path separator is always part of the path */
5225 else
5226 p = NULL;
5227#endif
5228 }
5229 }
5230#if defined(MSDOS) || defined(MSWIN) || defined(OS2)
5231 /*
5232 * When using a file in the current drive, remove the drive name:
5233 * "A:\dir\file" -> "\dir\file". This helps when moving a session file on
5234 * a floppy from "A:\dir" to "B:\dir".
5235 */
5236 else if (len > 3
5237 && TOUPPER_LOC(full_path[0]) == TOUPPER_LOC(dir_name[0])
5238 && full_path[1] == ':'
5239 && vim_ispathsep(full_path[2]))
5240 p = full_path + 2;
5241#endif
5242 else
5243 p = NULL;
5244 return p;
5245}
5246
5247/*
5248 * Shorten filenames for all buffers.
5249 * When "force" is TRUE: Use full path from now on for files currently being
5250 * edited, both for file name and swap file name. Try to shorten the file
5251 * names a bit, if safe to do so.
5252 * When "force" is FALSE: Only try to shorten absolute file names.
5253 * For buffers that have buftype "nofile" or "scratch": never change the file
5254 * name.
5255 */
5256 void
5257shorten_fnames(force)
5258 int force;
5259{
5260 char_u dirname[MAXPATHL];
5261 buf_T *buf;
5262 char_u *p;
5263
5264 mch_dirname(dirname, MAXPATHL);
5265 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
5266 {
5267 if (buf->b_fname != NULL
5268#ifdef FEAT_QUICKFIX
5269 && !bt_nofile(buf)
5270#endif
5271 && !path_with_url(buf->b_fname)
5272 && (force
5273 || buf->b_sfname == NULL
5274 || mch_isFullName(buf->b_sfname)))
5275 {
5276 vim_free(buf->b_sfname);
5277 buf->b_sfname = NULL;
5278 p = shorten_fname(buf->b_ffname, dirname);
5279 if (p != NULL)
5280 {
5281 buf->b_sfname = vim_strsave(p);
5282 buf->b_fname = buf->b_sfname;
5283 }
5284 if (p == NULL || buf->b_fname == NULL)
5285 buf->b_fname = buf->b_ffname;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005286 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005287
5288 /* Always make the swap file name a full path, a "nofile" buffer may
5289 * also have a swap file. */
5290 mf_fullname(buf->b_ml.ml_mfp);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005291 }
5292#ifdef FEAT_WINDOWS
5293 status_redraw_all();
5294#endif
5295}
5296
5297#if (defined(FEAT_DND) && defined(FEAT_GUI_GTK)) \
5298 || defined(FEAT_GUI_MSWIN) \
5299 || defined(FEAT_GUI_MAC) \
5300 || defined(PROTO)
5301/*
5302 * Shorten all filenames in "fnames[count]" by current directory.
5303 */
5304 void
5305shorten_filenames(fnames, count)
5306 char_u **fnames;
5307 int count;
5308{
5309 int i;
5310 char_u dirname[MAXPATHL];
5311 char_u *p;
5312
5313 if (fnames == NULL || count < 1)
5314 return;
5315 mch_dirname(dirname, sizeof(dirname));
5316 for (i = 0; i < count; ++i)
5317 {
5318 if ((p = shorten_fname(fnames[i], dirname)) != NULL)
5319 {
5320 /* shorten_fname() returns pointer in given "fnames[i]". If free
5321 * "fnames[i]" first, "p" becomes invalid. So we need to copy
5322 * "p" first then free fnames[i]. */
5323 p = vim_strsave(p);
5324 vim_free(fnames[i]);
5325 fnames[i] = p;
5326 }
5327 }
5328}
5329#endif
5330
5331/*
5332 * add extention to file name - change path/fo.o.h to path/fo.o.h.ext or
5333 * fo_o_h.ext for MSDOS or when shortname option set.
5334 *
5335 * Assumed that fname is a valid name found in the filesystem we assure that
5336 * the return value is a different name and ends in 'ext'.
5337 * "ext" MUST be at most 4 characters long if it starts with a dot, 3
5338 * characters otherwise.
5339 * Space for the returned name is allocated, must be freed later.
5340 * Returns NULL when out of memory.
5341 */
5342 char_u *
5343modname(fname, ext, prepend_dot)
5344 char_u *fname, *ext;
5345 int prepend_dot; /* may prepend a '.' to file name */
5346{
5347 return buf_modname(
5348#ifdef SHORT_FNAME
5349 TRUE,
5350#else
5351 (curbuf->b_p_sn || curbuf->b_shortname),
5352#endif
5353 fname, ext, prepend_dot);
5354}
5355
5356 char_u *
5357buf_modname(shortname, fname, ext, prepend_dot)
5358 int shortname; /* use 8.3 file name */
5359 char_u *fname, *ext;
5360 int prepend_dot; /* may prepend a '.' to file name */
5361{
5362 char_u *retval;
5363 char_u *s;
5364 char_u *e;
5365 char_u *ptr;
5366 int fnamelen, extlen;
5367
5368 extlen = (int)STRLEN(ext);
5369
5370 /*
5371 * If there is no file name we must get the name of the current directory
5372 * (we need the full path in case :cd is used).
5373 */
5374 if (fname == NULL || *fname == NUL)
5375 {
5376 retval = alloc((unsigned)(MAXPATHL + extlen + 3));
5377 if (retval == NULL)
5378 return NULL;
5379 if (mch_dirname(retval, MAXPATHL) == FAIL ||
5380 (fnamelen = (int)STRLEN(retval)) == 0)
5381 {
5382 vim_free(retval);
5383 return NULL;
5384 }
5385 if (!vim_ispathsep(retval[fnamelen - 1]))
5386 {
5387 retval[fnamelen++] = PATHSEP;
5388 retval[fnamelen] = NUL;
5389 }
5390#ifndef SHORT_FNAME
5391 prepend_dot = FALSE; /* nothing to prepend a dot to */
5392#endif
5393 }
5394 else
5395 {
5396 fnamelen = (int)STRLEN(fname);
5397 retval = alloc((unsigned)(fnamelen + extlen + 3));
5398 if (retval == NULL)
5399 return NULL;
5400 STRCPY(retval, fname);
5401#ifdef VMS
5402 vms_remove_version(retval); /* we do not need versions here */
5403#endif
5404 }
5405
5406 /*
5407 * search backwards until we hit a '/', '\' or ':' replacing all '.'
5408 * by '_' for MSDOS or when shortname option set and ext starts with a dot.
5409 * Then truncate what is after the '/', '\' or ':' to 8 characters for
5410 * MSDOS and 26 characters for AMIGA, a lot more for UNIX.
5411 */
5412 for (ptr = retval + fnamelen; ptr >= retval; ptr--)
5413 {
5414#ifndef RISCOS
5415 if (*ext == '.'
5416#ifdef USE_LONG_FNAME
5417 && (!USE_LONG_FNAME || shortname)
5418#else
5419# ifndef SHORT_FNAME
5420 && shortname
5421# endif
5422#endif
5423 )
5424 if (*ptr == '.') /* replace '.' by '_' */
5425 *ptr = '_';
5426#endif /* RISCOS */
5427 if (vim_ispathsep(*ptr))
5428 break;
5429 }
5430 ptr++;
5431
5432 /* the file name has at most BASENAMELEN characters. */
5433#ifndef SHORT_FNAME
5434 if (STRLEN(ptr) > (unsigned)BASENAMELEN)
5435 ptr[BASENAMELEN] = '\0';
5436#endif
5437
5438 s = ptr + STRLEN(ptr);
5439
5440 /*
5441 * For 8.3 file names we may have to reduce the length.
5442 */
5443#ifdef USE_LONG_FNAME
5444 if (!USE_LONG_FNAME || shortname)
5445#else
5446# ifndef SHORT_FNAME
5447 if (shortname)
5448# endif
5449#endif
5450 {
5451 /*
5452 * If there is no file name, or the file name ends in '/', and the
5453 * extension starts with '.', put a '_' before the dot, because just
5454 * ".ext" is invalid.
5455 */
5456 if (fname == NULL || *fname == NUL
5457 || vim_ispathsep(fname[STRLEN(fname) - 1]))
5458 {
5459#ifdef RISCOS
5460 if (*ext == '/')
5461#else
5462 if (*ext == '.')
5463#endif
5464 *s++ = '_';
5465 }
5466 /*
5467 * If the extension starts with '.', truncate the base name at 8
5468 * characters
5469 */
5470#ifdef RISCOS
5471 /* We normally use '/', but swap files are '_' */
5472 else if (*ext == '/' || *ext == '_')
5473#else
5474 else if (*ext == '.')
5475#endif
5476 {
5477 if (s - ptr > (size_t)8)
5478 {
5479 s = ptr + 8;
5480 *s = '\0';
5481 }
5482 }
5483 /*
5484 * If the extension doesn't start with '.', and the file name
5485 * doesn't have an extension yet, append a '.'
5486 */
5487#ifdef RISCOS
5488 else if ((e = vim_strchr(ptr, '/')) == NULL)
5489 *s++ = '/';
5490#else
5491 else if ((e = vim_strchr(ptr, '.')) == NULL)
5492 *s++ = '.';
5493#endif
5494 /*
5495 * If the extension doesn't start with '.', and there already is an
5496 * extension, it may need to be tructated
5497 */
5498 else if ((int)STRLEN(e) + extlen > 4)
5499 s = e + 4 - extlen;
5500 }
5501#if defined(OS2) || defined(USE_LONG_FNAME) || defined(WIN3264)
5502 /*
5503 * If there is no file name, and the extension starts with '.', put a
5504 * '_' before the dot, because just ".ext" may be invalid if it's on a
5505 * FAT partition, and on HPFS it doesn't matter.
5506 */
5507 else if ((fname == NULL || *fname == NUL) && *ext == '.')
5508 *s++ = '_';
5509#endif
5510
5511 /*
5512 * Append the extention.
5513 * ext can start with '.' and cannot exceed 3 more characters.
5514 */
5515 STRCPY(s, ext);
5516
5517#ifndef SHORT_FNAME
5518 /*
5519 * Prepend the dot.
5520 */
5521 if (prepend_dot && !shortname && *(e = gettail(retval)) !=
5522#ifdef RISCOS
5523 '/'
5524#else
5525 '.'
5526#endif
5527#ifdef USE_LONG_FNAME
5528 && USE_LONG_FNAME
5529#endif
5530 )
5531 {
5532 mch_memmove(e + 1, e, STRLEN(e) + 1);
5533#ifdef RISCOS
5534 *e = '/';
5535#else
5536 *e = '.';
5537#endif
5538 }
5539#endif
5540
5541 /*
5542 * Check that, after appending the extension, the file name is really
5543 * different.
5544 */
5545 if (fname != NULL && STRCMP(fname, retval) == 0)
5546 {
5547 /* we search for a character that can be replaced by '_' */
5548 while (--s >= ptr)
5549 {
5550 if (*s != '_')
5551 {
5552 *s = '_';
5553 break;
5554 }
5555 }
5556 if (s < ptr) /* fname was "________.<ext>", how tricky! */
5557 *ptr = 'v';
5558 }
5559 return retval;
5560}
5561
5562/*
5563 * Like fgets(), but if the file line is too long, it is truncated and the
5564 * rest of the line is thrown away. Returns TRUE for end-of-file.
5565 */
5566 int
5567vim_fgets(buf, size, fp)
5568 char_u *buf;
5569 int size;
5570 FILE *fp;
5571{
5572 char *eof;
5573#define FGETS_SIZE 200
5574 char tbuf[FGETS_SIZE];
5575
5576 buf[size - 2] = NUL;
5577#ifdef USE_CR
5578 eof = fgets_cr((char *)buf, size, fp);
5579#else
5580 eof = fgets((char *)buf, size, fp);
5581#endif
5582 if (buf[size - 2] != NUL && buf[size - 2] != '\n')
5583 {
5584 buf[size - 1] = NUL; /* Truncate the line */
5585
5586 /* Now throw away the rest of the line: */
5587 do
5588 {
5589 tbuf[FGETS_SIZE - 2] = NUL;
5590#ifdef USE_CR
5591 fgets_cr((char *)tbuf, FGETS_SIZE, fp);
5592#else
5593 fgets((char *)tbuf, FGETS_SIZE, fp);
5594#endif
5595 } while (tbuf[FGETS_SIZE - 2] != NUL && tbuf[FGETS_SIZE - 2] != '\n');
5596 }
5597 return (eof == NULL);
5598}
5599
5600#if defined(USE_CR) || defined(PROTO)
5601/*
5602 * Like vim_fgets(), but accept any line terminator: CR, CR-LF or LF.
5603 * Returns TRUE for end-of-file.
5604 * Only used for the Mac, because it's much slower than vim_fgets().
5605 */
5606 int
5607tag_fgets(buf, size, fp)
5608 char_u *buf;
5609 int size;
5610 FILE *fp;
5611{
5612 int i = 0;
5613 int c;
5614 int eof = FALSE;
5615
5616 for (;;)
5617 {
5618 c = fgetc(fp);
5619 if (c == EOF)
5620 {
5621 eof = TRUE;
5622 break;
5623 }
5624 if (c == '\r')
5625 {
5626 /* Always store a NL for end-of-line. */
5627 if (i < size - 1)
5628 buf[i++] = '\n';
5629 c = fgetc(fp);
5630 if (c != '\n') /* Macintosh format: single CR. */
5631 ungetc(c, fp);
5632 break;
5633 }
5634 if (i < size - 1)
5635 buf[i++] = c;
5636 if (c == '\n')
5637 break;
5638 }
5639 buf[i] = NUL;
5640 return eof;
5641}
5642#endif
5643
5644/*
5645 * rename() only works if both files are on the same file system, this
5646 * function will (attempts to?) copy the file across if rename fails -- webb
5647 * Return -1 for failure, 0 for success.
5648 */
5649 int
5650vim_rename(from, to)
5651 char_u *from;
5652 char_u *to;
5653{
5654 int fd_in;
5655 int fd_out;
5656 int n;
5657 char *errmsg = NULL;
5658 char *buffer;
5659#ifdef AMIGA
5660 BPTR flock;
5661#endif
5662 struct stat st;
5663
5664 /*
5665 * When the names are identical, there is nothing to do.
5666 */
5667 if (fnamecmp(from, to) == 0)
5668 return 0;
5669
5670 /*
5671 * Fail if the "from" file doesn't exist. Avoids that "to" is deleted.
5672 */
5673 if (mch_stat((char *)from, &st) < 0)
5674 return -1;
5675
5676 /*
5677 * Delete the "to" file, this is required on some systems to make the
5678 * mch_rename() work, on other systems it makes sure that we don't have
5679 * two files when the mch_rename() fails.
5680 */
5681
5682#ifdef AMIGA
5683 /*
5684 * With MSDOS-compatible filesystems (crossdos, messydos) it is possible
5685 * that the name of the "to" file is the same as the "from" file, even
5686 * though the names are different. To avoid the chance of accidently
5687 * deleting the "from" file (horror!) we lock it during the remove.
5688 *
5689 * When used for making a backup before writing the file: This should not
5690 * happen with ":w", because startscript() should detect this problem and
5691 * set buf->b_shortname, causing modname() to return a correct ".bak" file
5692 * name. This problem does exist with ":w filename", but then the
5693 * original file will be somewhere else so the backup isn't really
5694 * important. If autoscripting is off the rename may fail.
5695 */
5696 flock = Lock((UBYTE *)from, (long)ACCESS_READ);
5697#endif
5698 mch_remove(to);
5699#ifdef AMIGA
5700 if (flock)
5701 UnLock(flock);
5702#endif
5703
5704 /*
5705 * First try a normal rename, return if it works.
5706 */
5707 if (mch_rename((char *)from, (char *)to) == 0)
5708 return 0;
5709
5710 /*
5711 * Rename() failed, try copying the file.
5712 */
5713 fd_in = mch_open((char *)from, O_RDONLY|O_EXTRA, 0);
5714 if (fd_in == -1)
5715 return -1;
5716 fd_out = mch_open((char *)to, O_CREAT|O_EXCL|O_WRONLY|O_EXTRA, 0666);
5717 if (fd_out == -1)
5718 {
5719 close(fd_in);
5720 return -1;
5721 }
5722
5723 buffer = (char *)alloc(BUFSIZE);
5724 if (buffer == NULL)
5725 {
5726 close(fd_in);
5727 close(fd_out);
5728 return -1;
5729 }
5730
5731 while ((n = vim_read(fd_in, buffer, BUFSIZE)) > 0)
5732 if (vim_write(fd_out, buffer, n) != n)
5733 {
5734 errmsg = _("E208: Error writing to \"%s\"");
5735 break;
5736 }
5737
5738 vim_free(buffer);
5739 close(fd_in);
5740 if (close(fd_out) < 0)
5741 errmsg = _("E209: Error closing \"%s\"");
5742 if (n < 0)
5743 {
5744 errmsg = _("E210: Error reading \"%s\"");
5745 to = from;
5746 }
5747 if (errmsg != NULL)
5748 {
5749 EMSG2(errmsg, to);
5750 return -1;
5751 }
5752 mch_remove(from);
5753 return 0;
5754}
5755
5756static int already_warned = FALSE;
5757
5758/*
5759 * Check if any not hidden buffer has been changed.
5760 * Postpone the check if there are characters in the stuff buffer, a global
5761 * command is being executed, a mapping is being executed or an autocommand is
5762 * busy.
5763 * Returns TRUE if some message was written (screen should be redrawn and
5764 * cursor positioned).
5765 */
5766 int
5767check_timestamps(focus)
5768 int focus; /* called for GUI focus event */
5769{
5770 buf_T *buf;
5771 int didit = 0;
5772 int n;
5773
5774 /* Don't check timestamps while system() or another low-level function may
5775 * cause us to lose and gain focus. */
5776 if (no_check_timestamps > 0)
5777 return FALSE;
5778
5779 /* Avoid doing a check twice. The OK/Reload dialog can cause a focus
5780 * event and we would keep on checking if the file is steadily growing.
5781 * Do check again after typing something. */
5782 if (focus && did_check_timestamps)
5783 {
5784 need_check_timestamps = TRUE;
5785 return FALSE;
5786 }
5787
5788 if (!stuff_empty() || global_busy || !typebuf_typed()
5789#ifdef FEAT_AUTOCMD
5790 || autocmd_busy
5791#endif
5792 )
5793 need_check_timestamps = TRUE; /* check later */
5794 else
5795 {
5796 ++no_wait_return;
5797 did_check_timestamps = TRUE;
5798 already_warned = FALSE;
5799 for (buf = firstbuf; buf != NULL; )
5800 {
5801 /* Only check buffers in a window. */
5802 if (buf->b_nwindows > 0)
5803 {
5804 n = buf_check_timestamp(buf, focus);
5805 if (didit < n)
5806 didit = n;
5807 if (n > 0 && !buf_valid(buf))
5808 {
5809 /* Autocommands have removed the buffer, start at the
5810 * first one again. */
5811 buf = firstbuf;
5812 continue;
5813 }
5814 }
5815 buf = buf->b_next;
5816 }
5817 --no_wait_return;
5818 need_check_timestamps = FALSE;
5819 if (need_wait_return && didit == 2)
5820 {
5821 /* make sure msg isn't overwritten */
5822 msg_puts((char_u *)"\n");
5823 out_flush();
5824 }
5825 }
5826 return didit;
5827}
5828
5829/*
5830 * Move all the lines from buffer "frombuf" to buffer "tobuf".
5831 * Return OK or FAIL. When FAIL "tobuf" is incomplete and/or "frombuf" is not
5832 * empty.
5833 */
5834 static int
5835move_lines(frombuf, tobuf)
5836 buf_T *frombuf;
5837 buf_T *tobuf;
5838{
5839 buf_T *tbuf = curbuf;
5840 int retval = OK;
5841 linenr_T lnum;
5842 char_u *p;
5843
5844 /* Copy the lines in "frombuf" to "tobuf". */
5845 curbuf = tobuf;
5846 for (lnum = 1; lnum <= frombuf->b_ml.ml_line_count; ++lnum)
5847 {
5848 p = vim_strsave(ml_get_buf(frombuf, lnum, FALSE));
5849 if (p == NULL || ml_append(lnum - 1, p, 0, FALSE) == FAIL)
5850 {
5851 vim_free(p);
5852 retval = FAIL;
5853 break;
5854 }
5855 vim_free(p);
5856 }
5857
5858 /* Delete all the lines in "frombuf". */
5859 if (retval != FAIL)
5860 {
5861 curbuf = frombuf;
5862 while (!bufempty())
5863 if (ml_delete(curbuf->b_ml.ml_line_count, FALSE) == FAIL)
5864 {
5865 /* Oops! We could try putting back the saved lines, but that
5866 * might fail again... */
5867 retval = FAIL;
5868 break;
5869 }
5870 }
5871
5872 curbuf = tbuf;
5873 return retval;
5874}
5875
5876/*
5877 * Check if buffer "buf" has been changed.
5878 * Also check if the file for a new buffer unexpectedly appeared.
5879 * return 1 if a changed buffer was found.
5880 * return 2 if a message has been displayed.
5881 * return 0 otherwise.
5882 */
5883/*ARGSUSED*/
5884 int
5885buf_check_timestamp(buf, focus)
5886 buf_T *buf;
5887 int focus; /* called for GUI focus event */
5888{
5889 struct stat st;
5890 int stat_res;
5891 int retval = 0;
5892 char_u *path;
5893 char_u *tbuf;
5894 char *mesg = NULL;
5895 char *mesg2;
5896 int helpmesg = FALSE;
5897 int reload = FALSE;
5898#if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
5899 int can_reload = FALSE;
5900#endif
5901 size_t orig_size = buf->b_orig_size;
5902 int orig_mode = buf->b_orig_mode;
5903#ifdef FEAT_GUI
5904 int save_mouse_correct = need_mouse_correct;
5905#endif
5906#ifdef FEAT_AUTOCMD
5907 static int busy = FALSE;
5908#endif
5909
5910 /* If there is no file name, the buffer is not loaded, 'buftype' is
5911 * set, we are in the middle of a save or being called recursively: ignore
5912 * this buffer. */
5913 if (buf->b_ffname == NULL
5914 || buf->b_ml.ml_mfp == NULL
5915#if defined(FEAT_QUICKFIX)
5916 || *buf->b_p_bt != NUL
5917#endif
5918 || buf->b_saving
5919#ifdef FEAT_AUTOCMD
5920 || busy
5921#endif
Bram Moolenaar009b2592004-10-24 19:18:58 +00005922#ifdef FEAT_NETBEANS_INTG
5923 || isNetbeansBuffer(buf)
5924#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005925 )
5926 return 0;
5927
5928 if ( !(buf->b_flags & BF_NOTEDITED)
5929 && buf->b_mtime != 0
5930 && ((stat_res = mch_stat((char *)buf->b_ffname, &st)) < 0
5931 || time_differs((long)st.st_mtime, buf->b_mtime)
5932#ifdef HAVE_ST_MODE
5933 || (int)st.st_mode != buf->b_orig_mode
5934#else
5935 || mch_getperm(buf->b_ffname) != buf->b_orig_mode
5936#endif
5937 ))
5938 {
5939 retval = 1;
5940
5941 /* set b_mtime to stop further warnings */
5942 if (stat_res < 0)
5943 {
5944 buf->b_mtime = 0;
5945 buf->b_orig_size = 0;
5946 buf->b_orig_mode = 0;
5947 }
5948 else
5949 buf_store_time(buf, &st, buf->b_ffname);
5950
5951 /* Don't do anything for a directory. Might contain the file
5952 * explorer. */
5953 if (mch_isdir(buf->b_fname))
5954 ;
5955
5956 /*
5957 * If 'autoread' is set, the buffer has no changes and the file still
5958 * exists, reload the buffer. Use the buffer-local option value if it
5959 * was set, the global option value otherwise.
5960 */
5961 else if ((buf->b_p_ar >= 0 ? buf->b_p_ar : p_ar)
5962 && !bufIsChanged(buf) && stat_res >= 0)
5963 reload = TRUE;
5964 else
5965 {
5966#ifdef FEAT_AUTOCMD
5967 int n;
5968
5969 /*
5970 * Only give the warning if there are no FileChangedShell
5971 * autocommands.
5972 * Avoid being called recursively by setting "busy".
5973 */
5974 busy = TRUE;
5975 n = apply_autocmds(EVENT_FILECHANGEDSHELL,
5976 buf->b_fname, buf->b_fname, FALSE, buf);
5977 busy = FALSE;
5978 if (n)
5979 {
5980 if (!buf_valid(buf))
5981 EMSG(_("E246: FileChangedShell autocommand deleted buffer"));
5982 return 2;
5983 }
5984 else
5985#endif
5986 {
5987 if (stat_res < 0)
5988 mesg = _("E211: Warning: File \"%s\" no longer available");
5989 else
5990 {
5991 helpmesg = TRUE;
5992#if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
5993 can_reload = TRUE;
5994#endif
5995 /*
5996 * Check if the file contents really changed to avoid
5997 * giving a warning when only the timestamp was set (e.g.,
5998 * checked out of CVS). Always warn when the buffer was
5999 * changed.
6000 */
6001 if (bufIsChanged(buf))
6002 mesg = _("W12: Warning: File \"%s\" has changed and the buffer was changed in Vim as well");
6003 else if (orig_size != buf->b_orig_size
6004 || buf_contents_changed(buf))
6005 mesg = _("W11: Warning: File \"%s\" has changed since editing started");
6006 else if (orig_mode != buf->b_orig_mode)
6007 mesg = _("W16: Warning: Mode of file \"%s\" has changed since editing started");
6008 }
6009 }
6010 }
6011
6012 }
6013 else if ((buf->b_flags & BF_NEW) && !(buf->b_flags & BF_NEW_W)
6014 && vim_fexists(buf->b_ffname))
6015 {
6016 retval = 1;
6017 mesg = _("W13: Warning: File \"%s\" has been created after editing started");
6018 buf->b_flags |= BF_NEW_W;
6019#if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
6020 can_reload = TRUE;
6021#endif
6022 }
6023
6024 if (mesg != NULL)
6025 {
6026 path = home_replace_save(buf, buf->b_fname);
6027 if (path != NULL)
6028 {
6029 if (helpmesg)
6030 mesg2 = _("See \":help W11\" for more info.");
6031 else
6032 mesg2 = "";
6033 tbuf = alloc((unsigned)(STRLEN(path) + STRLEN(mesg)
6034 + STRLEN(mesg2) + 2));
6035 sprintf((char *)tbuf, mesg, path);
6036#if defined(FEAT_CON_DIALOG) || defined(FEAT_GUI_DIALOG)
6037 if (can_reload)
6038 {
6039 if (*mesg2 != NUL)
6040 {
6041 STRCAT(tbuf, "\n");
6042 STRCAT(tbuf, mesg2);
6043 }
6044 if (do_dialog(VIM_WARNING, (char_u *)_("Warning"), tbuf,
6045 (char_u *)_("&OK\n&Load File"), 1, NULL) == 2)
6046 reload = TRUE;
6047 }
6048 else
6049#endif
6050 if (State > NORMAL_BUSY || (State & CMDLINE) || already_warned)
6051 {
6052 if (*mesg2 != NUL)
6053 {
6054 STRCAT(tbuf, "; ");
6055 STRCAT(tbuf, mesg2);
6056 }
6057 EMSG(tbuf);
6058 retval = 2;
6059 }
6060 else
6061 {
Bram Moolenaared203462004-06-16 11:19:22 +00006062# ifdef FEAT_AUTOCMD
Bram Moolenaar071d4272004-06-13 20:20:40 +00006063 if (!autocmd_busy)
Bram Moolenaared203462004-06-16 11:19:22 +00006064# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006065 {
6066 msg_start();
6067 msg_puts_attr(tbuf, hl_attr(HLF_E) + MSG_HIST);
6068 if (*mesg2 != NUL)
6069 msg_puts_attr((char_u *)mesg2,
6070 hl_attr(HLF_W) + MSG_HIST);
6071 msg_clr_eos();
6072 (void)msg_end();
6073 if (emsg_silent == 0)
6074 {
6075 out_flush();
Bram Moolenaared203462004-06-16 11:19:22 +00006076# ifdef FEAT_GUI
Bram Moolenaar071d4272004-06-13 20:20:40 +00006077 if (!focus)
Bram Moolenaared203462004-06-16 11:19:22 +00006078# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006079 /* give the user some time to think about it */
6080 ui_delay(1000L, TRUE);
6081
6082 /* don't redraw and erase the message */
6083 redraw_cmdline = FALSE;
6084 }
6085 }
6086 already_warned = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006087 }
6088
6089 vim_free(path);
6090 vim_free(tbuf);
6091 }
6092 }
6093
6094 if (reload)
6095 {
6096 exarg_T ea;
6097 pos_T old_cursor;
6098 linenr_T old_topline;
6099 int old_ro = buf->b_p_ro;
6100 buf_T *savebuf;
6101 int saved = OK;
6102#ifdef FEAT_AUTOCMD
6103 aco_save_T aco;
6104
6105 /* set curwin/curbuf for "buf" and save some things */
6106 aucmd_prepbuf(&aco, buf);
6107#else
6108 buf_T *save_curbuf = curbuf;
6109
6110 curbuf = buf;
6111 curwin->w_buffer = buf;
6112#endif
6113
6114 /* We only want to read the text from the file, not reset the syntax
6115 * highlighting, clear marks, diff status, etc. Force the fileformat
6116 * and encoding to be the same. */
6117 if (prep_exarg(&ea, buf) == OK)
6118 {
6119 old_cursor = curwin->w_cursor;
6120 old_topline = curwin->w_topline;
6121
6122 /*
6123 * To behave like when a new file is edited (matters for
6124 * BufReadPost autocommands) we first need to delete the current
6125 * buffer contents. But if reading the file fails we should keep
6126 * the old contents. Can't use memory only, the file might be
6127 * too big. Use a hidden buffer to move the buffer contents to.
6128 */
6129 if (bufempty())
6130 savebuf = NULL;
6131 else
6132 {
6133 /* Allocate a buffer without putting it in the buffer list. */
6134 savebuf = buflist_new(NULL, NULL, (linenr_T)1, BLN_DUMMY);
6135 if (savebuf != NULL)
6136 {
6137 /* Open the memline. */
6138 curbuf = savebuf;
6139 curwin->w_buffer = savebuf;
6140 saved = ml_open();
6141 curbuf = buf;
6142 curwin->w_buffer = buf;
6143 }
6144 if (savebuf == NULL || saved == FAIL
6145 || move_lines(buf, savebuf) == FAIL)
6146 {
6147 EMSG2(_("E462: Could not prepare for reloading \"%s\""),
6148 buf->b_fname);
6149 saved = FAIL;
6150 }
6151 }
6152
6153 if (saved == OK)
6154 {
6155 curbuf->b_flags |= BF_CHECK_RO; /* check for RO again */
6156#ifdef FEAT_AUTOCMD
6157 keep_filetype = TRUE; /* don't detect 'filetype' */
6158#endif
6159 if (readfile(buf->b_ffname, buf->b_fname, (linenr_T)0,
6160 (linenr_T)0,
6161 (linenr_T)MAXLNUM, &ea, READ_NEW) == FAIL)
6162 {
6163#if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
6164 if (!aborting())
6165#endif
6166 EMSG2(_("E321: Could not reload \"%s\""), buf->b_fname);
6167 if (savebuf != NULL)
6168 {
6169 /* Put the text back from the save buffer. First
6170 * delete any lines that readfile() added. */
6171 while (!bufempty())
6172 if (ml_delete(curbuf->b_ml.ml_line_count, FALSE)
6173 == FAIL)
6174 break;
6175 (void)move_lines(savebuf, buf);
6176 }
6177 }
6178 else
6179 {
6180 /* Mark the buffer as unmodified and free undo info. */
6181 unchanged(buf, TRUE);
6182 u_blockfree(buf);
6183 u_clearall(buf);
6184 }
6185 }
6186 vim_free(ea.cmd);
6187
6188 if (savebuf != NULL)
6189 wipe_buffer(savebuf, FALSE);
6190
6191#ifdef FEAT_DIFF
6192 /* Invalidate diff info if necessary. */
6193 diff_invalidate();
6194#endif
6195
6196 /* Restore the topline and cursor position and check it (lines may
6197 * have been removed). */
6198 if (old_topline > curbuf->b_ml.ml_line_count)
6199 curwin->w_topline = curbuf->b_ml.ml_line_count;
6200 else
6201 curwin->w_topline = old_topline;
6202 curwin->w_cursor = old_cursor;
6203 check_cursor();
6204 update_topline();
6205#ifdef FEAT_AUTOCMD
6206 keep_filetype = FALSE;
6207#endif
6208#ifdef FEAT_FOLDING
6209 {
6210 win_T *wp;
6211
6212 /* Update folds unless they are defined manually. */
6213 FOR_ALL_WINDOWS(wp)
6214 if (wp->w_buffer == curwin->w_buffer
6215 && !foldmethodIsManual(wp))
6216 foldUpdateAll(wp);
6217 }
6218#endif
6219 /* If the mode didn't change and 'readonly' was set, keep the old
6220 * value; the user probably used the ":view" command. But don't
6221 * reset it, might have had a read error. */
6222 if (orig_mode == curbuf->b_orig_mode)
6223 curbuf->b_p_ro |= old_ro;
6224 }
6225
6226#ifdef FEAT_AUTOCMD
6227 /* restore curwin/curbuf and a few other things */
6228 aucmd_restbuf(&aco);
6229 /* Careful: autocommands may have made "buf" invalid! */
6230#else
6231 curwin->w_buffer = save_curbuf;
6232 curbuf = save_curbuf;
6233#endif
6234 }
6235
6236#ifdef FEAT_GUI
6237 /* restore this in case an autocommand has set it; it would break
6238 * 'mousefocus' */
6239 need_mouse_correct = save_mouse_correct;
6240#endif
6241
6242 return retval;
6243}
6244
6245/*ARGSUSED*/
6246 void
6247buf_store_time(buf, st, fname)
6248 buf_T *buf;
6249 struct stat *st;
6250 char_u *fname;
6251{
6252 buf->b_mtime = (long)st->st_mtime;
6253 buf->b_orig_size = (size_t)st->st_size;
6254#ifdef HAVE_ST_MODE
6255 buf->b_orig_mode = (int)st->st_mode;
6256#else
6257 buf->b_orig_mode = mch_getperm(fname);
6258#endif
6259}
6260
6261/*
6262 * Adjust the line with missing eol, used for the next write.
6263 * Used for do_filter(), when the input lines for the filter are deleted.
6264 */
6265 void
6266write_lnum_adjust(offset)
6267 linenr_T offset;
6268{
6269 if (write_no_eol_lnum) /* only if there is a missing eol */
6270 write_no_eol_lnum += offset;
6271}
6272
6273#if defined(TEMPDIRNAMES) || defined(PROTO)
6274static long temp_count = 0; /* Temp filename counter. */
6275
6276/*
6277 * Delete the temp directory and all files it contains.
6278 */
6279 void
6280vim_deltempdir()
6281{
6282 char_u **files;
6283 int file_count;
6284 int i;
6285
6286 if (vim_tempdir != NULL)
6287 {
6288 sprintf((char *)NameBuff, "%s*", vim_tempdir);
6289 if (gen_expand_wildcards(1, &NameBuff, &file_count, &files,
6290 EW_DIR|EW_FILE|EW_SILENT) == OK)
6291 {
6292 for (i = 0; i < file_count; ++i)
6293 mch_remove(files[i]);
6294 FreeWild(file_count, files);
6295 }
6296 gettail(NameBuff)[-1] = NUL;
6297 (void)mch_rmdir(NameBuff);
6298
6299 vim_free(vim_tempdir);
6300 vim_tempdir = NULL;
6301 }
6302}
6303#endif
6304
6305/*
6306 * vim_tempname(): Return a unique name that can be used for a temp file.
6307 *
6308 * The temp file is NOT created.
6309 *
6310 * The returned pointer is to allocated memory.
6311 * The returned pointer is NULL if no valid name was found.
6312 */
6313/*ARGSUSED*/
6314 char_u *
6315vim_tempname(extra_char)
6316 int extra_char; /* character to use in the name instead of '?' */
6317{
6318#ifdef USE_TMPNAM
6319 char_u itmp[L_tmpnam]; /* use tmpnam() */
6320#else
6321 char_u itmp[TEMPNAMELEN];
6322#endif
6323
6324#ifdef TEMPDIRNAMES
6325 static char *(tempdirs[]) = {TEMPDIRNAMES};
6326 int i;
6327 long nr;
6328 long off;
6329# ifndef EEXIST
6330 struct stat st;
6331# endif
6332
6333 /*
6334 * This will create a directory for private use by this instance of Vim.
6335 * This is done once, and the same directory is used for all temp files.
6336 * This method avoids security problems because of symlink attacks et al.
6337 * It's also a bit faster, because we only need to check for an existing
6338 * file when creating the directory and not for each temp file.
6339 */
6340 if (vim_tempdir == NULL)
6341 {
6342 /*
6343 * Try the entries in TEMPDIRNAMES to create the temp directory.
6344 */
6345 for (i = 0; i < sizeof(tempdirs) / sizeof(char *); ++i)
6346 {
6347 /* expand $TMP, leave room for "/v1100000/999999999" */
6348 expand_env((char_u *)tempdirs[i], itmp, TEMPNAMELEN - 20);
6349 if (mch_isdir(itmp)) /* directory exists */
6350 {
6351# ifdef __EMX__
6352 /* If $TMP contains a forward slash (perhaps using bash or
6353 * tcsh), don't add a backslash, use a forward slash!
6354 * Adding 2 backslashes didn't work. */
6355 if (vim_strchr(itmp, '/') != NULL)
6356 STRCAT(itmp, "/");
6357 else
6358# endif
6359 add_pathsep(itmp);
6360
6361 /* Get an arbitrary number of up to 6 digits. When it's
6362 * unlikely that it already exists it will be faster,
6363 * otherwise it doesn't matter. The use of mkdir() avoids any
6364 * security problems because of the predictable number. */
6365 nr = (mch_get_pid() + (long)time(NULL)) % 1000000L;
6366
6367 /* Try up to 10000 different values until we find a name that
6368 * doesn't exist. */
6369 for (off = 0; off < 10000L; ++off)
6370 {
6371 int r;
6372#if defined(UNIX) || defined(VMS)
6373 mode_t umask_save;
6374#endif
6375
6376 sprintf((char *)itmp + STRLEN(itmp), "v%ld", nr + off);
6377# ifndef EEXIST
6378 /* If mkdir() does not set errno to EEXIST, check for
6379 * existing file here. There is a race condition then,
6380 * although it's fail-safe. */
6381 if (mch_stat((char *)itmp, &st) >= 0)
6382 continue;
6383# endif
6384#if defined(UNIX) || defined(VMS)
6385 /* Make sure the umask doesn't remove the executable bit.
6386 * "repl" has been reported to use "177". */
6387 umask_save = umask(077);
6388#endif
6389 r = vim_mkdir(itmp, 0700);
6390#if defined(UNIX) || defined(VMS)
6391 (void)umask(umask_save);
6392#endif
6393 if (r == 0)
6394 {
6395 char_u *buf;
6396
6397 /* Directory was created, use this name.
6398 * Expand to full path; When using the current
6399 * directory a ":cd" would confuse us. */
6400 buf = alloc((unsigned)MAXPATHL + 1);
6401 if (buf != NULL)
6402 {
6403 if (vim_FullName(itmp, buf, MAXPATHL, FALSE)
6404 == FAIL)
6405 STRCPY(buf, itmp);
6406# ifdef __EMX__
6407 if (vim_strchr(buf, '/') != NULL)
6408 STRCAT(buf, "/");
6409 else
6410# endif
6411 add_pathsep(buf);
6412 vim_tempdir = vim_strsave(buf);
6413 vim_free(buf);
6414 }
6415 break;
6416 }
6417# ifdef EEXIST
6418 /* If the mkdir() didn't fail because the file/dir exists,
6419 * we probably can't create any dir here, try another
6420 * place. */
6421 if (errno != EEXIST)
6422# endif
6423 break;
6424 }
6425 if (vim_tempdir != NULL)
6426 break;
6427 }
6428 }
6429 }
6430
6431 if (vim_tempdir != NULL)
6432 {
6433 /* There is no need to check if the file exists, because we own the
6434 * directory and nobody else creates a file in it. */
6435 sprintf((char *)itmp, "%s%ld", vim_tempdir, temp_count++);
6436 return vim_strsave(itmp);
6437 }
6438
6439 return NULL;
6440
6441#else /* TEMPDIRNAMES */
6442
6443# ifdef WIN3264
6444 char szTempFile[_MAX_PATH + 1];
6445 char buf4[4];
6446 char_u *retval;
6447 char_u *p;
6448
6449 STRCPY(itmp, "");
6450 if (GetTempPath(_MAX_PATH, szTempFile) == 0)
6451 szTempFile[0] = NUL; /* GetTempPath() failed, use current dir */
6452 strcpy(buf4, "VIM");
6453 buf4[2] = extra_char; /* make it "VIa", "VIb", etc. */
6454 if (GetTempFileName(szTempFile, buf4, 0, itmp) == 0)
6455 return NULL;
6456 /* GetTempFileName() will create the file, we don't want that */
6457 (void)DeleteFile(itmp);
6458
6459 /* Backslashes in a temp file name cause problems when filtering with
6460 * "sh". NOTE: This also checks 'shellcmdflag' to help those people who
6461 * didn't set 'shellslash'. */
6462 retval = vim_strsave(itmp);
6463 if (*p_shcf == '-' || p_ssl)
6464 for (p = retval; *p; ++p)
6465 if (*p == '\\')
6466 *p = '/';
6467 return retval;
6468
6469# else /* WIN3264 */
6470
6471# ifdef USE_TMPNAM
6472 /* tmpnam() will make its own name */
6473 if (*tmpnam((char *)itmp) == NUL)
6474 return NULL;
6475# else
6476 char_u *p;
6477
6478# ifdef VMS_TEMPNAM
6479 /* mktemp() is not working on VMS. It seems to be
6480 * a do-nothing function. Therefore we use tempnam().
6481 */
6482 sprintf((char *)itmp, "VIM%c", extra_char);
6483 p = (char_u *)tempnam("tmp:", (char *)itmp);
6484 if (p != NULL)
6485 {
6486 /* VMS will use '.LOG' if we don't explicitly specify an extension,
6487 * and VIM will then be unable to find the file later */
6488 STRCPY(itmp, p);
6489 STRCAT(itmp, ".txt");
6490 free(p);
6491 }
6492 else
6493 return NULL;
6494# else
6495 STRCPY(itmp, TEMPNAME);
6496 if ((p = vim_strchr(itmp, '?')) != NULL)
6497 *p = extra_char;
6498 if (mktemp((char *)itmp) == NULL)
6499 return NULL;
6500# endif
6501# endif
6502
6503 return vim_strsave(itmp);
6504# endif /* WIN3264 */
6505#endif /* TEMPDIRNAMES */
6506}
6507
6508#if defined(BACKSLASH_IN_FILENAME) || defined(PROTO)
6509/*
6510 * Convert all backslashes in fname to forward slashes in-place.
6511 */
6512 void
6513forward_slash(fname)
6514 char_u *fname;
6515{
6516 char_u *p;
6517
6518 for (p = fname; *p != NUL; ++p)
6519# ifdef FEAT_MBYTE
6520 /* The Big5 encoding can have '\' in the trail byte. */
6521 if (enc_dbcs != 0 && (*mb_ptr2len_check)(p) > 1)
6522 ++p;
6523 else
6524# endif
6525 if (*p == '\\')
6526 *p = '/';
6527}
6528#endif
6529
6530
6531/*
6532 * Code for automatic commands.
6533 *
6534 * Only included when "FEAT_AUTOCMD" has been defined.
6535 */
6536
6537#if defined(FEAT_AUTOCMD) || defined(PROTO)
6538
6539/*
6540 * The autocommands are stored in a list for each event.
6541 * Autocommands for the same pattern, that are consecutive, are joined
6542 * together, to avoid having to match the pattern too often.
6543 * The result is an array of Autopat lists, which point to AutoCmd lists:
6544 *
6545 * first_autopat[0] --> Autopat.next --> Autopat.next --> NULL
6546 * Autopat.cmds Autopat.cmds
6547 * | |
6548 * V V
6549 * AutoCmd.next AutoCmd.next
6550 * | |
6551 * V V
6552 * AutoCmd.next NULL
6553 * |
6554 * V
6555 * NULL
6556 *
6557 * first_autopat[1] --> Autopat.next --> NULL
6558 * Autopat.cmds
6559 * |
6560 * V
6561 * AutoCmd.next
6562 * |
6563 * V
6564 * NULL
6565 * etc.
6566 *
6567 * The order of AutoCmds is important, this is the order in which they were
6568 * defined and will have to be executed.
6569 */
6570typedef struct AutoCmd
6571{
6572 char_u *cmd; /* The command to be executed (NULL
6573 when command has been removed) */
6574 char nested; /* If autocommands nest here */
6575 char last; /* last command in list */
6576#ifdef FEAT_EVAL
6577 scid_T scriptID; /* script ID where defined */
6578#endif
6579 struct AutoCmd *next; /* Next AutoCmd in list */
6580} AutoCmd;
6581
6582typedef struct AutoPat
6583{
6584 int group; /* group ID */
6585 char_u *pat; /* pattern as typed (NULL when pattern
6586 has been removed) */
6587 int patlen; /* strlen() of pat */
6588 char_u *reg_pat; /* pattern converted to regexp */
6589 char allow_dirs; /* Pattern may match whole path */
6590 char last; /* last pattern for apply_autocmds() */
6591 AutoCmd *cmds; /* list of commands to do */
6592 struct AutoPat *next; /* next AutoPat in AutoPat list */
6593} AutoPat;
6594
6595static struct event_name
6596{
6597 char *name; /* event name */
6598 EVENT_T event; /* event number */
6599} event_names[] =
6600{
6601 {"BufAdd", EVENT_BUFADD},
6602 {"BufCreate", EVENT_BUFADD},
6603 {"BufDelete", EVENT_BUFDELETE},
6604 {"BufEnter", EVENT_BUFENTER},
6605 {"BufFilePost", EVENT_BUFFILEPOST},
6606 {"BufFilePre", EVENT_BUFFILEPRE},
6607 {"BufHidden", EVENT_BUFHIDDEN},
6608 {"BufLeave", EVENT_BUFLEAVE},
6609 {"BufNew", EVENT_BUFNEW},
6610 {"BufNewFile", EVENT_BUFNEWFILE},
6611 {"BufRead", EVENT_BUFREADPOST},
6612 {"BufReadCmd", EVENT_BUFREADCMD},
6613 {"BufReadPost", EVENT_BUFREADPOST},
6614 {"BufReadPre", EVENT_BUFREADPRE},
6615 {"BufUnload", EVENT_BUFUNLOAD},
6616 {"BufWinEnter", EVENT_BUFWINENTER},
6617 {"BufWinLeave", EVENT_BUFWINLEAVE},
6618 {"BufWipeout", EVENT_BUFWIPEOUT},
6619 {"BufWrite", EVENT_BUFWRITEPRE},
6620 {"BufWritePost", EVENT_BUFWRITEPOST},
6621 {"BufWritePre", EVENT_BUFWRITEPRE},
6622 {"BufWriteCmd", EVENT_BUFWRITECMD},
6623 {"CmdwinEnter", EVENT_CMDWINENTER},
6624 {"CmdwinLeave", EVENT_CMDWINLEAVE},
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00006625 {"ColorScheme", EVENT_COLORSCHEME},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006626 {"EncodingChanged", EVENT_ENCODINGCHANGED},
6627 {"FileEncoding", EVENT_ENCODINGCHANGED},
6628 {"CursorHold", EVENT_CURSORHOLD},
6629 {"FileAppendPost", EVENT_FILEAPPENDPOST},
6630 {"FileAppendPre", EVENT_FILEAPPENDPRE},
6631 {"FileAppendCmd", EVENT_FILEAPPENDCMD},
6632 {"FileChangedShell",EVENT_FILECHANGEDSHELL},
6633 {"FileChangedRO", EVENT_FILECHANGEDRO},
6634 {"FileReadPost", EVENT_FILEREADPOST},
6635 {"FileReadPre", EVENT_FILEREADPRE},
6636 {"FileReadCmd", EVENT_FILEREADCMD},
6637 {"FileType", EVENT_FILETYPE},
6638 {"FileWritePost", EVENT_FILEWRITEPOST},
6639 {"FileWritePre", EVENT_FILEWRITEPRE},
6640 {"FileWriteCmd", EVENT_FILEWRITECMD},
6641 {"FilterReadPost", EVENT_FILTERREADPOST},
6642 {"FilterReadPre", EVENT_FILTERREADPRE},
6643 {"FilterWritePost", EVENT_FILTERWRITEPOST},
6644 {"FilterWritePre", EVENT_FILTERWRITEPRE},
6645 {"FocusGained", EVENT_FOCUSGAINED},
6646 {"FocusLost", EVENT_FOCUSLOST},
6647 {"FuncUndefined", EVENT_FUNCUNDEFINED},
6648 {"GUIEnter", EVENT_GUIENTER},
Bram Moolenaar843ee412004-06-30 16:16:41 +00006649 {"InsertChange", EVENT_INSERTCHANGE},
6650 {"InsertEnter", EVENT_INSERTENTER},
6651 {"InsertLeave", EVENT_INSERTLEAVE},
Bram Moolenaar071d4272004-06-13 20:20:40 +00006652 {"RemoteReply", EVENT_REMOTEREPLY},
6653 {"StdinReadPost", EVENT_STDINREADPOST},
6654 {"StdinReadPre", EVENT_STDINREADPRE},
6655 {"Syntax", EVENT_SYNTAX},
6656 {"TermChanged", EVENT_TERMCHANGED},
6657 {"TermResponse", EVENT_TERMRESPONSE},
6658 {"User", EVENT_USER},
6659 {"VimEnter", EVENT_VIMENTER},
6660 {"VimLeave", EVENT_VIMLEAVE},
6661 {"VimLeavePre", EVENT_VIMLEAVEPRE},
6662 {"WinEnter", EVENT_WINENTER},
6663 {"WinLeave", EVENT_WINLEAVE},
6664 {NULL, (EVENT_T)0}
6665};
6666
6667static AutoPat *first_autopat[NUM_EVENTS] =
6668{
6669 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
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,
Bram Moolenaarab79bcb2004-07-18 21:34:53 +00006673 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
6674 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
Bram Moolenaar071d4272004-06-13 20:20:40 +00006675};
6676
6677/*
6678 * struct used to keep status while executing autocommands for an event.
6679 */
6680typedef struct AutoPatCmd
6681{
6682 AutoPat *curpat; /* next AutoPat to examine */
6683 AutoCmd *nextcmd; /* next AutoCmd to execute */
6684 int group; /* group being used */
6685 char_u *fname; /* fname to match with */
6686 char_u *sfname; /* sfname to match with */
6687 char_u *tail; /* tail of fname */
6688 EVENT_T event; /* current event */
6689} AutoPatCmd;
6690
6691/*
6692 * augroups stores a list of autocmd group names.
6693 */
6694garray_T augroups = {0, 0, sizeof(char_u *), 10, NULL};
6695#define AUGROUP_NAME(i) (((char_u **)augroups.ga_data)[i])
6696
6697/*
6698 * The ID of the current group. Group 0 is the default one.
6699 */
6700#define AUGROUP_DEFAULT -1 /* default autocmd group */
6701#define AUGROUP_ERROR -2 /* errornouse autocmd group */
6702#define AUGROUP_ALL -3 /* all autocmd groups */
6703static int current_augroup = AUGROUP_DEFAULT;
6704
6705static int au_need_clean = FALSE; /* need to delete marked patterns */
6706
6707static void show_autocmd __ARGS((AutoPat *ap, EVENT_T event));
6708static void au_remove_pat __ARGS((AutoPat *ap));
6709static void au_remove_cmds __ARGS((AutoPat *ap));
6710static void au_cleanup __ARGS((void));
6711static int au_new_group __ARGS((char_u *name));
6712static void au_del_group __ARGS((char_u *name));
6713static int au_find_group __ARGS((char_u *name));
6714static EVENT_T event_name2nr __ARGS((char_u *start, char_u **end));
6715static char_u *event_nr2name __ARGS((EVENT_T event));
6716static char_u *find_end_event __ARGS((char_u *arg, int have_group));
6717static int event_ignored __ARGS((EVENT_T event));
6718static int au_get_grouparg __ARGS((char_u **argp));
6719static int do_autocmd_event __ARGS((EVENT_T event, char_u *pat, int nested, char_u *cmd, int forceit, int group));
6720static char_u *getnextac __ARGS((int c, void *cookie, int indent));
6721static 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));
6722static void auto_next_pat __ARGS((AutoPatCmd *apc, int stop_at_last));
6723
6724static EVENT_T last_event;
6725static int last_group;
6726
6727/*
6728 * Show the autocommands for one AutoPat.
6729 */
6730 static void
6731show_autocmd(ap, event)
6732 AutoPat *ap;
6733 EVENT_T event;
6734{
6735 AutoCmd *ac;
6736
6737 /* Check for "got_int" (here and at various places below), which is set
6738 * when "q" has been hit for the "--more--" prompt */
6739 if (got_int)
6740 return;
6741 if (ap->pat == NULL) /* pattern has been removed */
6742 return;
6743
6744 msg_putchar('\n');
6745 if (got_int)
6746 return;
6747 if (event != last_event || ap->group != last_group)
6748 {
6749 if (ap->group != AUGROUP_DEFAULT)
6750 {
6751 if (AUGROUP_NAME(ap->group) == NULL)
6752 msg_puts_attr((char_u *)_("--Deleted--"), hl_attr(HLF_E));
6753 else
6754 msg_puts_attr(AUGROUP_NAME(ap->group), hl_attr(HLF_T));
6755 msg_puts((char_u *)" ");
6756 }
6757 msg_puts_attr(event_nr2name(event), hl_attr(HLF_T));
6758 last_event = event;
6759 last_group = ap->group;
6760 msg_putchar('\n');
6761 if (got_int)
6762 return;
6763 }
6764 msg_col = 4;
6765 msg_outtrans(ap->pat);
6766
6767 for (ac = ap->cmds; ac != NULL; ac = ac->next)
6768 {
6769 if (ac->cmd != NULL) /* skip removed commands */
6770 {
6771 if (msg_col >= 14)
6772 msg_putchar('\n');
6773 msg_col = 14;
6774 if (got_int)
6775 return;
6776 msg_outtrans(ac->cmd);
6777 if (got_int)
6778 return;
6779 if (ac->next != NULL)
6780 {
6781 msg_putchar('\n');
6782 if (got_int)
6783 return;
6784 }
6785 }
6786 }
6787}
6788
6789/*
6790 * Mark an autocommand pattern for deletion.
6791 */
6792 static void
6793au_remove_pat(ap)
6794 AutoPat *ap;
6795{
6796 vim_free(ap->pat);
6797 ap->pat = NULL;
6798 au_need_clean = TRUE;
6799}
6800
6801/*
6802 * Mark all commands for a pattern for deletion.
6803 */
6804 static void
6805au_remove_cmds(ap)
6806 AutoPat *ap;
6807{
6808 AutoCmd *ac;
6809
6810 for (ac = ap->cmds; ac != NULL; ac = ac->next)
6811 {
6812 vim_free(ac->cmd);
6813 ac->cmd = NULL;
6814 }
6815 au_need_clean = TRUE;
6816}
6817
6818/*
6819 * Cleanup autocommands and patterns that have been deleted.
6820 * This is only done when not executing autocommands.
6821 */
6822 static void
6823au_cleanup()
6824{
6825 AutoPat *ap, **prev_ap;
6826 AutoCmd *ac, **prev_ac;
6827 EVENT_T event;
6828
6829 if (autocmd_busy || !au_need_clean)
6830 return;
6831
6832 /* loop over all events */
6833 for (event = (EVENT_T)0; (int)event < (int)NUM_EVENTS;
6834 event = (EVENT_T)((int)event + 1))
6835 {
6836 /* loop over all autocommand patterns */
6837 prev_ap = &(first_autopat[(int)event]);
6838 for (ap = *prev_ap; ap != NULL; ap = *prev_ap)
6839 {
6840 /* loop over all commands for this pattern */
6841 prev_ac = &(ap->cmds);
6842 for (ac = *prev_ac; ac != NULL; ac = *prev_ac)
6843 {
6844 /* remove the command if the pattern is to be deleted or when
6845 * the command has been marked for deletion */
6846 if (ap->pat == NULL || ac->cmd == NULL)
6847 {
6848 *prev_ac = ac->next;
6849 vim_free(ac->cmd);
6850 vim_free(ac);
6851 }
6852 else
6853 prev_ac = &(ac->next);
6854 }
6855
6856 /* remove the pattern if it has been marked for deletion */
6857 if (ap->pat == NULL)
6858 {
6859 *prev_ap = ap->next;
6860 vim_free(ap->reg_pat);
6861 vim_free(ap);
6862 }
6863 else
6864 prev_ap = &(ap->next);
6865 }
6866 }
6867
6868 au_need_clean = FALSE;
6869}
6870
6871/*
6872 * Add an autocmd group name.
6873 * Return it's ID. Returns AUGROUP_ERROR (< 0) for error.
6874 */
6875 static int
6876au_new_group(name)
6877 char_u *name;
6878{
6879 int i;
6880
6881 i = au_find_group(name);
6882 if (i == AUGROUP_ERROR) /* the group doesn't exist yet, add it */
6883 {
6884 /* First try using a free entry. */
6885 for (i = 0; i < augroups.ga_len; ++i)
6886 if (AUGROUP_NAME(i) == NULL)
6887 break;
6888 if (i == augroups.ga_len && ga_grow(&augroups, 1) == FAIL)
6889 return AUGROUP_ERROR;
6890
6891 AUGROUP_NAME(i) = vim_strsave(name);
6892 if (AUGROUP_NAME(i) == NULL)
6893 return AUGROUP_ERROR;
6894 if (i == augroups.ga_len)
6895 {
6896 ++augroups.ga_len;
6897 --augroups.ga_room;
6898 }
6899 }
6900
6901 return i;
6902}
6903
6904 static void
6905au_del_group(name)
6906 char_u *name;
6907{
6908 int i;
6909
6910 i = au_find_group(name);
6911 if (i == AUGROUP_ERROR) /* the group doesn't exist */
6912 EMSG2(_("E367: No such group: \"%s\""), name);
6913 else
6914 {
6915 vim_free(AUGROUP_NAME(i));
6916 AUGROUP_NAME(i) = NULL;
6917 }
6918}
6919
6920/*
6921 * Find the ID of an autocmd group name.
6922 * Return it's ID. Returns AUGROUP_ERROR (< 0) for error.
6923 */
6924 static int
6925au_find_group(name)
6926 char_u *name;
6927{
6928 int i;
6929
6930 for (i = 0; i < augroups.ga_len; ++i)
6931 if (AUGROUP_NAME(i) != NULL && STRCMP(AUGROUP_NAME(i), name) == 0)
6932 return i;
6933 return AUGROUP_ERROR;
6934}
6935
6936/*
6937 * ":augroup {name}".
6938 */
6939 void
6940do_augroup(arg, del_group)
6941 char_u *arg;
6942 int del_group;
6943{
6944 int i;
6945
6946 if (del_group)
6947 {
6948 if (*arg == NUL)
6949 EMSG(_(e_argreq));
6950 else
6951 au_del_group(arg);
6952 }
6953 else if (STRICMP(arg, "end") == 0) /* ":aug end": back to group 0 */
6954 current_augroup = AUGROUP_DEFAULT;
6955 else if (*arg) /* ":aug xxx": switch to group xxx */
6956 {
6957 i = au_new_group(arg);
6958 if (i != AUGROUP_ERROR)
6959 current_augroup = i;
6960 }
6961 else /* ":aug": list the group names */
6962 {
6963 msg_start();
6964 for (i = 0; i < augroups.ga_len; ++i)
6965 {
6966 if (AUGROUP_NAME(i) != NULL)
6967 {
6968 msg_puts(AUGROUP_NAME(i));
6969 msg_puts((char_u *)" ");
6970 }
6971 }
6972 msg_clr_eos();
6973 msg_end();
6974 }
6975}
6976
6977/*
6978 * Return the event number for event name "start".
6979 * Return NUM_EVENTS if the event name was not found.
6980 * Return a pointer to the next event name in "end".
6981 */
6982 static EVENT_T
6983event_name2nr(start, end)
6984 char_u *start;
6985 char_u **end;
6986{
6987 char_u *p;
6988 int i;
6989 int len;
6990
6991 /* the event name ends with end of line, a blank or a comma */
6992 for (p = start; *p && !vim_iswhite(*p) && *p != ','; ++p)
6993 ;
6994 for (i = 0; event_names[i].name != NULL; ++i)
6995 {
6996 len = (int)STRLEN(event_names[i].name);
6997 if (len == p - start && STRNICMP(event_names[i].name, start, len) == 0)
6998 break;
6999 }
7000 if (*p == ',')
7001 ++p;
7002 *end = p;
7003 if (event_names[i].name == NULL)
7004 return NUM_EVENTS;
7005 return event_names[i].event;
7006}
7007
7008/*
7009 * Return the name for event "event".
7010 */
7011 static char_u *
7012event_nr2name(event)
7013 EVENT_T event;
7014{
7015 int i;
7016
7017 for (i = 0; event_names[i].name != NULL; ++i)
7018 if (event_names[i].event == event)
7019 return (char_u *)event_names[i].name;
7020 return (char_u *)"Unknown";
7021}
7022
7023/*
7024 * Scan over the events. "*" stands for all events.
7025 */
7026 static char_u *
7027find_end_event(arg, have_group)
7028 char_u *arg;
7029 int have_group; /* TRUE when group name was found */
7030{
7031 char_u *pat;
7032 char_u *p;
7033
7034 if (*arg == '*')
7035 {
7036 if (arg[1] && !vim_iswhite(arg[1]))
7037 {
7038 EMSG2(_("E215: Illegal character after *: %s"), arg);
7039 return NULL;
7040 }
7041 pat = arg + 1;
7042 }
7043 else
7044 {
7045 for (pat = arg; *pat && !vim_iswhite(*pat); pat = p)
7046 {
7047 if ((int)event_name2nr(pat, &p) >= (int)NUM_EVENTS)
7048 {
7049 if (have_group)
7050 EMSG2(_("E216: No such event: %s"), pat);
7051 else
7052 EMSG2(_("E216: No such group or event: %s"), pat);
7053 return NULL;
7054 }
7055 }
7056 }
7057 return pat;
7058}
7059
7060/*
7061 * Return TRUE if "event" is included in 'eventignore'.
7062 */
7063 static int
7064event_ignored(event)
7065 EVENT_T event;
7066{
7067 char_u *p = p_ei;
7068
7069 if (STRICMP(p_ei, "all") == 0)
7070 return TRUE;
7071
7072 while (*p)
7073 if (event_name2nr(p, &p) == event)
7074 return TRUE;
7075
7076 return FALSE;
7077}
7078
7079/*
7080 * Return OK when the contents of p_ei is valid, FAIL otherwise.
7081 */
7082 int
7083check_ei()
7084{
7085 char_u *p = p_ei;
7086
7087 if (STRICMP(p_ei, "all") == 0)
7088 return OK;
7089
7090 while (*p)
7091 if (event_name2nr(p, &p) == NUM_EVENTS)
7092 return FAIL;
7093
7094 return OK;
7095}
7096
7097/*
7098 * do_autocmd() -- implements the :autocmd command. Can be used in the
7099 * following ways:
7100 *
7101 * :autocmd <event> <pat> <cmd> Add <cmd> to the list of commands that
7102 * will be automatically executed for <event>
7103 * when editing a file matching <pat>, in
7104 * the current group.
7105 * :autocmd <event> <pat> Show the auto-commands associated with
7106 * <event> and <pat>.
7107 * :autocmd <event> Show the auto-commands associated with
7108 * <event>.
7109 * :autocmd Show all auto-commands.
7110 * :autocmd! <event> <pat> <cmd> Remove all auto-commands associated with
7111 * <event> and <pat>, and add the command
7112 * <cmd>, for the current group.
7113 * :autocmd! <event> <pat> Remove all auto-commands associated with
7114 * <event> and <pat> for the current group.
7115 * :autocmd! <event> Remove all auto-commands associated with
7116 * <event> for the current group.
7117 * :autocmd! Remove ALL auto-commands for the current
7118 * group.
7119 *
7120 * Multiple events and patterns may be given separated by commas. Here are
7121 * some examples:
7122 * :autocmd bufread,bufenter *.c,*.h set tw=0 smartindent noic
7123 * :autocmd bufleave * set tw=79 nosmartindent ic infercase
7124 *
7125 * :autocmd * *.c show all autocommands for *.c files.
7126 */
7127 void
7128do_autocmd(arg, forceit)
7129 char_u *arg;
7130 int forceit;
7131{
7132 char_u *pat;
7133 char_u *envpat = NULL;
7134 char_u *cmd;
7135 EVENT_T event;
7136 int need_free = FALSE;
7137 int nested = FALSE;
7138 int group;
7139
7140 /*
7141 * Check for a legal group name. If not, use AUGROUP_ALL.
7142 */
7143 group = au_get_grouparg(&arg);
7144 if (arg == NULL) /* out of memory */
7145 return;
7146
7147 /*
7148 * Scan over the events.
7149 * If we find an illegal name, return here, don't do anything.
7150 */
7151 pat = find_end_event(arg, group != AUGROUP_ALL);
7152 if (pat == NULL)
7153 return;
7154
7155 /*
7156 * Scan over the pattern. Put a NUL at the end.
7157 */
7158 pat = skipwhite(pat);
7159 cmd = pat;
7160 while (*cmd && (!vim_iswhite(*cmd) || cmd[-1] == '\\'))
7161 cmd++;
7162 if (*cmd)
7163 *cmd++ = NUL;
7164
7165 /* Expand environment variables in the pattern. Set 'shellslash', we want
7166 * forward slashes here. */
7167 if (vim_strchr(pat, '$') != NULL || vim_strchr(pat, '~') != NULL)
7168 {
7169#ifdef BACKSLASH_IN_FILENAME
7170 int p_ssl_save = p_ssl;
7171
7172 p_ssl = TRUE;
7173#endif
7174 envpat = expand_env_save(pat);
7175#ifdef BACKSLASH_IN_FILENAME
7176 p_ssl = p_ssl_save;
7177#endif
7178 if (envpat != NULL)
7179 pat = envpat;
7180 }
7181
7182 /*
7183 * Check for "nested" flag.
7184 */
7185 cmd = skipwhite(cmd);
7186 if (*cmd != NUL && STRNCMP(cmd, "nested", 6) == 0 && vim_iswhite(cmd[6]))
7187 {
7188 nested = TRUE;
7189 cmd = skipwhite(cmd + 6);
7190 }
7191
7192 /*
7193 * Find the start of the commands.
7194 * Expand <sfile> in it.
7195 */
7196 if (*cmd != NUL)
7197 {
7198 cmd = expand_sfile(cmd);
7199 if (cmd == NULL) /* some error */
7200 return;
7201 need_free = TRUE;
7202 }
7203
7204 /*
7205 * Print header when showing autocommands.
7206 */
7207 if (!forceit && *cmd == NUL)
7208 {
7209 /* Highlight title */
7210 MSG_PUTS_TITLE(_("\n--- Auto-Commands ---"));
7211 }
7212
7213 /*
7214 * Loop over the events.
7215 */
7216 last_event = (EVENT_T)-1; /* for listing the event name */
7217 last_group = AUGROUP_ERROR; /* for listing the group name */
7218 if (*arg == '*' || *arg == NUL)
7219 {
7220 for (event = (EVENT_T)0; (int)event < (int)NUM_EVENTS;
7221 event = (EVENT_T)((int)event + 1))
7222 if (do_autocmd_event(event, pat,
7223 nested, cmd, forceit, group) == FAIL)
7224 break;
7225 }
7226 else
7227 {
7228 while (*arg && !vim_iswhite(*arg))
7229 if (do_autocmd_event(event_name2nr(arg, &arg), pat,
7230 nested, cmd, forceit, group) == FAIL)
7231 break;
7232 }
7233
7234 if (need_free)
7235 vim_free(cmd);
7236 vim_free(envpat);
7237}
7238
7239/*
7240 * Find the group ID in a ":autocmd" or ":doautocmd" argument.
7241 * The "argp" argument is advanced to the following argument.
7242 *
7243 * Returns the group ID, AUGROUP_ERROR for error (out of memory).
7244 */
7245 static int
7246au_get_grouparg(argp)
7247 char_u **argp;
7248{
7249 char_u *group_name;
7250 char_u *p;
7251 char_u *arg = *argp;
7252 int group = AUGROUP_ALL;
7253
7254 p = skiptowhite(arg);
7255 if (p > arg)
7256 {
7257 group_name = vim_strnsave(arg, (int)(p - arg));
7258 if (group_name == NULL) /* out of memory */
7259 return AUGROUP_ERROR;
7260 group = au_find_group(group_name);
7261 if (group == AUGROUP_ERROR)
7262 group = AUGROUP_ALL; /* no match, use all groups */
7263 else
7264 *argp = skipwhite(p); /* match, skip over group name */
7265 vim_free(group_name);
7266 }
7267 return group;
7268}
7269
7270/*
7271 * do_autocmd() for one event.
7272 * If *pat == NUL do for all patterns.
7273 * If *cmd == NUL show entries.
7274 * If forceit == TRUE delete entries.
7275 * If group is not AUGROUP_ALL, only use this group.
7276 */
7277 static int
7278do_autocmd_event(event, pat, nested, cmd, forceit, group)
7279 EVENT_T event;
7280 char_u *pat;
7281 int nested;
7282 char_u *cmd;
7283 int forceit;
7284 int group;
7285{
7286 AutoPat *ap;
7287 AutoPat **prev_ap;
7288 AutoCmd *ac;
7289 AutoCmd **prev_ac;
7290 int brace_level;
7291 char_u *endpat;
7292 int findgroup;
7293 int allgroups;
7294 int patlen;
7295
7296 if (group == AUGROUP_ALL)
7297 findgroup = current_augroup;
7298 else
7299 findgroup = group;
7300 allgroups = (group == AUGROUP_ALL && !forceit && *cmd == NUL);
7301
7302 /*
7303 * Show or delete all patterns for an event.
7304 */
7305 if (*pat == NUL)
7306 {
7307 for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next)
7308 {
7309 if (forceit) /* delete the AutoPat, if it's in the current group */
7310 {
7311 if (ap->group == findgroup)
7312 au_remove_pat(ap);
7313 }
7314 else if (group == AUGROUP_ALL || ap->group == group)
7315 show_autocmd(ap, event);
7316 }
7317 }
7318
7319 /*
7320 * Loop through all the specified patterns.
7321 */
7322 for ( ; *pat; pat = (*endpat == ',' ? endpat + 1 : endpat))
7323 {
7324 /*
7325 * Find end of the pattern.
7326 * Watch out for a comma in braces, like "*.\{obj,o\}".
7327 */
7328 brace_level = 0;
7329 for (endpat = pat; *endpat && (*endpat != ',' || brace_level
7330 || endpat[-1] == '\\'); ++endpat)
7331 {
7332 if (*endpat == '{')
7333 brace_level++;
7334 else if (*endpat == '}')
7335 brace_level--;
7336 }
7337 if (pat == endpat) /* ignore single comma */
7338 continue;
7339 patlen = (int)(endpat - pat);
7340
7341 /*
7342 * Find AutoPat entries with this pattern.
7343 */
7344 prev_ap = &first_autopat[(int)event];
7345 while ((ap = *prev_ap) != NULL)
7346 {
7347 if (ap->pat != NULL)
7348 {
7349 /* Accept a pattern when:
7350 * - a group was specified and it's that group, or a group was
7351 * not specified and it's the current group, or a group was
7352 * not specified and we are listing
7353 * - the length of the pattern matches
7354 * - the pattern matches
7355 */
7356 if ((allgroups || ap->group == findgroup)
7357 && ap->patlen == patlen
7358 && STRNCMP(pat, ap->pat, patlen) == 0)
7359 {
7360 /*
7361 * Remove existing autocommands.
7362 * If adding any new autocmd's for this AutoPat, don't
7363 * delete the pattern from the autopat list, append to
7364 * this list.
7365 */
7366 if (forceit)
7367 {
7368 if (*cmd != NUL && ap->next == NULL)
7369 {
7370 au_remove_cmds(ap);
7371 break;
7372 }
7373 au_remove_pat(ap);
7374 }
7375
7376 /*
7377 * Show autocmd's for this autopat
7378 */
7379 else if (*cmd == NUL)
7380 show_autocmd(ap, event);
7381
7382 /*
7383 * Add autocmd to this autopat, if it's the last one.
7384 */
7385 else if (ap->next == NULL)
7386 break;
7387 }
7388 }
7389 prev_ap = &ap->next;
7390 }
7391
7392 /*
7393 * Add a new command.
7394 */
7395 if (*cmd != NUL)
7396 {
7397 /*
7398 * If the pattern we want to add a command to does appear at the
7399 * end of the list (or not is not in the list at all), add the
7400 * pattern at the end of the list.
7401 */
7402 if (ap == NULL)
7403 {
7404 ap = (AutoPat *)alloc((unsigned)sizeof(AutoPat));
7405 if (ap == NULL)
7406 return FAIL;
7407 ap->pat = vim_strnsave(pat, patlen);
7408 ap->patlen = patlen;
7409 if (ap->pat == NULL)
7410 {
7411 vim_free(ap);
7412 return FAIL;
7413 }
7414 ap->reg_pat = file_pat_to_reg_pat(pat, endpat,
7415 &ap->allow_dirs, TRUE);
7416 if (ap->reg_pat == NULL)
7417 {
7418 vim_free(ap->pat);
7419 vim_free(ap);
7420 return FAIL;
7421 }
7422 ap->cmds = NULL;
7423 *prev_ap = ap;
7424 ap->next = NULL;
7425 if (group == AUGROUP_ALL)
7426 ap->group = current_augroup;
7427 else
7428 ap->group = group;
7429 }
7430
7431 /*
7432 * Add the autocmd at the end of the AutoCmd list.
7433 */
7434 prev_ac = &(ap->cmds);
7435 while ((ac = *prev_ac) != NULL)
7436 prev_ac = &ac->next;
7437 ac = (AutoCmd *)alloc((unsigned)sizeof(AutoCmd));
7438 if (ac == NULL)
7439 return FAIL;
7440 ac->cmd = vim_strsave(cmd);
7441#ifdef FEAT_EVAL
7442 ac->scriptID = current_SID;
7443#endif
7444 if (ac->cmd == NULL)
7445 {
7446 vim_free(ac);
7447 return FAIL;
7448 }
7449 ac->next = NULL;
7450 *prev_ac = ac;
7451 ac->nested = nested;
7452 }
7453 }
7454
7455 au_cleanup(); /* may really delete removed patterns/commands now */
7456 return OK;
7457}
7458
7459/*
7460 * Implementation of ":doautocmd [group] event [fname]".
7461 * Return OK for success, FAIL for failure;
7462 */
7463 int
7464do_doautocmd(arg, do_msg)
7465 char_u *arg;
7466 int do_msg; /* give message for no matching autocmds? */
7467{
7468 char_u *fname;
7469 int nothing_done = TRUE;
7470 int group;
7471
7472 /*
7473 * Check for a legal group name. If not, use AUGROUP_ALL.
7474 */
7475 group = au_get_grouparg(&arg);
7476 if (arg == NULL) /* out of memory */
7477 return FAIL;
7478
7479 if (*arg == '*')
7480 {
7481 EMSG(_("E217: Can't execute autocommands for ALL events"));
7482 return FAIL;
7483 }
7484
7485 /*
7486 * Scan over the events.
7487 * If we find an illegal name, return here, don't do anything.
7488 */
7489 fname = find_end_event(arg, group != AUGROUP_ALL);
7490 if (fname == NULL)
7491 return FAIL;
7492
7493 fname = skipwhite(fname);
7494
7495 /*
7496 * Loop over the events.
7497 */
7498 while (*arg && !vim_iswhite(*arg))
7499 if (apply_autocmds_group(event_name2nr(arg, &arg),
7500 fname, NULL, TRUE, group, curbuf, NULL))
7501 nothing_done = FALSE;
7502
7503 if (nothing_done && do_msg)
7504 MSG(_("No matching autocommands"));
7505
7506#ifdef FEAT_EVAL
7507 return aborting() ? FAIL : OK;
7508#else
7509 return OK;
7510#endif
7511}
7512
7513/*
7514 * ":doautoall": execute autocommands for each loaded buffer.
7515 */
7516 void
7517ex_doautoall(eap)
7518 exarg_T *eap;
7519{
7520 int retval;
7521 aco_save_T aco;
7522 buf_T *buf;
7523
7524 /*
7525 * This is a bit tricky: For some commands curwin->w_buffer needs to be
7526 * equal to curbuf, but for some buffers there may not be a window.
7527 * So we change the buffer for the current window for a moment. This
7528 * gives problems when the autocommands make changes to the list of
7529 * buffers or windows...
7530 */
7531 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
7532 {
7533 if (curbuf->b_ml.ml_mfp != NULL)
7534 {
7535 /* find a window for this buffer and save some values */
7536 aucmd_prepbuf(&aco, buf);
7537
7538 /* execute the autocommands for this buffer */
7539 retval = do_doautocmd(eap->arg, FALSE);
Bram Moolenaar15d0a8c2004-09-06 17:44:46 +00007540 do_modelines(FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00007541
7542 /* restore the current window */
7543 aucmd_restbuf(&aco);
7544
7545 /* stop if there is some error or buffer was deleted */
7546 if (retval == FAIL || !buf_valid(buf))
7547 break;
7548 }
7549 }
7550
7551 check_cursor(); /* just in case lines got deleted */
7552}
7553
7554/*
7555 * Prepare for executing autocommands for (hidden) buffer "buf".
7556 * Search a window for the current buffer. Save the cursor position and
7557 * screen offset.
7558 * Set "curbuf" and "curwin" to match "buf".
7559 */
7560 void
7561aucmd_prepbuf(aco, buf)
7562 aco_save_T *aco; /* structure to save values in */
7563 buf_T *buf; /* new curbuf */
7564{
7565 win_T *win;
7566
7567 aco->new_curbuf = buf;
7568
7569 /* Find a window that is for the new buffer */
7570 if (buf == curbuf) /* be quick when buf is curbuf */
7571 win = curwin;
7572 else
7573#ifdef FEAT_WINDOWS
7574 for (win = firstwin; win != NULL; win = win->w_next)
7575 if (win->w_buffer == buf)
7576 break;
7577#else
7578 win = NULL;
7579#endif
7580
7581 /*
7582 * Prefer to use an existing window for the buffer, it has the least side
7583 * effects (esp. if "buf" is curbuf).
7584 * Otherwise, use curwin for "buf". It might make some items in the
7585 * window invalid. At least save the cursor and topline.
7586 */
7587 if (win != NULL)
7588 {
7589 /* there is a window for "buf", make it the curwin */
7590 aco->save_curwin = curwin;
7591 curwin = win;
7592 aco->save_buf = win->w_buffer;
7593 aco->new_curwin = win;
7594 }
7595 else
7596 {
7597 /* there is no window for "buf", use curwin */
7598 aco->save_curwin = NULL;
7599 aco->save_buf = curbuf;
7600 --curbuf->b_nwindows;
7601 curwin->w_buffer = buf;
7602 ++buf->b_nwindows;
7603
7604 /* save cursor and topline, set them to safe values */
7605 aco->save_cursor = curwin->w_cursor;
7606 curwin->w_cursor.lnum = 1;
7607 curwin->w_cursor.col = 0;
7608 aco->save_topline = curwin->w_topline;
7609 curwin->w_topline = 1;
7610#ifdef FEAT_DIFF
7611 aco->save_topfill = curwin->w_topfill;
7612 curwin->w_topfill = 0;
7613#endif
7614 }
7615
7616 curbuf = buf;
7617}
7618
7619/*
7620 * Cleanup after executing autocommands for a (hidden) buffer.
7621 * Restore the window as it was (if possible).
7622 */
7623 void
7624aucmd_restbuf(aco)
7625 aco_save_T *aco; /* structure holding saved values */
7626{
7627 if (aco->save_curwin != NULL)
7628 {
7629 /* restore curwin */
7630#ifdef FEAT_WINDOWS
7631 if (win_valid(aco->save_curwin))
7632#endif
7633 {
7634 /* restore the buffer which was previously edited by curwin, if
7635 * it's still the same window and it's valid */
7636 if (curwin == aco->new_curwin
7637 && buf_valid(aco->save_buf)
7638 && aco->save_buf->b_ml.ml_mfp != NULL)
7639 {
7640 --curbuf->b_nwindows;
7641 curbuf = aco->save_buf;
7642 curwin->w_buffer = curbuf;
7643 ++curbuf->b_nwindows;
7644 }
7645
7646 curwin = aco->save_curwin;
7647 curbuf = curwin->w_buffer;
7648 }
7649 }
7650 else
7651 {
7652 /* restore buffer for curwin if it still exists and is loaded */
7653 if (buf_valid(aco->save_buf) && aco->save_buf->b_ml.ml_mfp != NULL)
7654 {
7655 --curbuf->b_nwindows;
7656 curbuf = aco->save_buf;
7657 curwin->w_buffer = curbuf;
7658 ++curbuf->b_nwindows;
7659 curwin->w_cursor = aco->save_cursor;
7660 check_cursor();
7661 /* check topline < line_count, in case lines got deleted */
7662 if (aco->save_topline <= curbuf->b_ml.ml_line_count)
7663 {
7664 curwin->w_topline = aco->save_topline;
7665#ifdef FEAT_DIFF
7666 curwin->w_topfill = aco->save_topfill;
7667#endif
7668 }
7669 else
7670 {
7671 curwin->w_topline = curbuf->b_ml.ml_line_count;
7672#ifdef FEAT_DIFF
7673 curwin->w_topfill = 0;
7674#endif
7675 }
7676 }
7677 }
7678}
7679
7680static int autocmd_nested = FALSE;
7681
7682/*
7683 * Execute autocommands for "event" and file name "fname".
7684 * Return TRUE if some commands were executed.
7685 */
7686 int
7687apply_autocmds(event, fname, fname_io, force, buf)
7688 EVENT_T event;
7689 char_u *fname; /* NULL or empty means use actual file name */
7690 char_u *fname_io; /* fname to use for <afile> on cmdline */
7691 int force; /* when TRUE, ignore autocmd_busy */
7692 buf_T *buf; /* buffer for <abuf> */
7693{
7694 return apply_autocmds_group(event, fname, fname_io, force,
7695 AUGROUP_ALL, buf, NULL);
7696}
7697
7698/*
7699 * Like apply_autocmds(), but with extra "eap" argument. This takes care of
7700 * setting v:filearg.
7701 */
7702 static int
7703apply_autocmds_exarg(event, fname, fname_io, force, buf, eap)
7704 EVENT_T event;
7705 char_u *fname;
7706 char_u *fname_io;
7707 int force;
7708 buf_T *buf;
7709 exarg_T *eap;
7710{
7711 return apply_autocmds_group(event, fname, fname_io, force,
7712 AUGROUP_ALL, buf, eap);
7713}
7714
7715/*
7716 * Like apply_autocmds(), but handles the caller's retval. If the script
7717 * processing is being aborted or if retval is FAIL when inside a try
7718 * conditional, no autocommands are executed. If otherwise the autocommands
7719 * cause the script to be aborted, retval is set to FAIL.
7720 */
7721 int
7722apply_autocmds_retval(event, fname, fname_io, force, buf, retval)
7723 EVENT_T event;
7724 char_u *fname; /* NULL or empty means use actual file name */
7725 char_u *fname_io; /* fname to use for <afile> on cmdline */
7726 int force; /* when TRUE, ignore autocmd_busy */
7727 buf_T *buf; /* buffer for <abuf> */
7728 int *retval; /* pointer to caller's retval */
7729{
7730 int did_cmd;
7731
7732 if (should_abort(*retval))
7733 return FALSE;
7734
7735 did_cmd = apply_autocmds_group(event, fname, fname_io, force,
7736 AUGROUP_ALL, buf, NULL);
7737 if (did_cmd && aborting())
7738 *retval = FAIL;
7739 return did_cmd;
7740}
7741
7742#if defined(FEAT_AUTOCMD) || defined(PROTO)
7743 int
7744has_cursorhold()
7745{
7746 return (first_autopat[(int)EVENT_CURSORHOLD] != NULL);
7747}
7748#endif
7749
7750 static int
7751apply_autocmds_group(event, fname, fname_io, force, group, buf, eap)
7752 EVENT_T event;
7753 char_u *fname; /* NULL or empty means use actual file name */
7754 char_u *fname_io; /* fname to use for <afile> on cmdline, NULL means
7755 use fname */
7756 int force; /* when TRUE, ignore autocmd_busy */
7757 int group; /* group ID, or AUGROUP_ALL */
7758 buf_T *buf; /* buffer for <abuf> */
7759 exarg_T *eap; /* command arguments */
7760{
7761 char_u *sfname = NULL; /* short file name */
7762 char_u *tail;
7763 int save_changed;
7764 buf_T *old_curbuf;
7765 int retval = FALSE;
7766 char_u *save_sourcing_name;
7767 linenr_T save_sourcing_lnum;
7768 char_u *save_autocmd_fname;
7769 int save_autocmd_bufnr;
7770 char_u *save_autocmd_match;
7771 int save_autocmd_busy;
7772 int save_autocmd_nested;
7773 static int nesting = 0;
7774 AutoPatCmd patcmd;
7775 AutoPat *ap;
7776#ifdef FEAT_EVAL
7777 scid_T save_current_SID;
7778 void *save_funccalp;
7779 char_u *save_cmdarg;
7780 long save_cmdbang;
7781#endif
7782 static int filechangeshell_busy = FALSE;
7783
7784 /*
7785 * Quickly return if there are no autocommands for this event or
7786 * autocommands are blocked.
7787 */
7788 if (first_autopat[(int)event] == NULL || autocmd_block > 0)
7789 return retval;
7790
7791 /*
7792 * When autocommands are busy, new autocommands are only executed when
7793 * explicitly enabled with the "nested" flag.
7794 */
7795 if (autocmd_busy && !(force || autocmd_nested))
7796 return retval;
7797
7798#ifdef FEAT_EVAL
7799 /*
7800 * Quickly return when immdediately aborting on error, or when an interrupt
7801 * occurred or an exception was thrown but not caught.
7802 */
7803 if (aborting())
7804 return retval;
7805#endif
7806
7807 /*
7808 * FileChangedShell never nests, because it can create an endless loop.
7809 */
7810 if (filechangeshell_busy && event == EVENT_FILECHANGEDSHELL)
7811 return retval;
7812
7813 /*
7814 * Ignore events in 'eventignore'.
7815 */
7816 if (event_ignored(event))
7817 return retval;
7818
7819 /*
7820 * Allow nesting of autocommands, but restrict the depth, because it's
7821 * possible to create an endless loop.
7822 */
7823 if (nesting == 10)
7824 {
7825 EMSG(_("E218: autocommand nesting too deep"));
7826 return retval;
7827 }
7828
7829 /*
7830 * Check if these autocommands are disabled. Used when doing ":all" or
7831 * ":ball".
7832 */
7833 if ( (autocmd_no_enter
7834 && (event == EVENT_WINENTER || event == EVENT_BUFENTER))
7835 || (autocmd_no_leave
7836 && (event == EVENT_WINLEAVE || event == EVENT_BUFLEAVE)))
7837 return retval;
7838
7839 /*
7840 * Save the autocmd_* variables and info about the current buffer.
7841 */
7842 save_autocmd_fname = autocmd_fname;
7843 save_autocmd_bufnr = autocmd_bufnr;
7844 save_autocmd_match = autocmd_match;
7845 save_autocmd_busy = autocmd_busy;
7846 save_autocmd_nested = autocmd_nested;
7847 save_changed = curbuf->b_changed;
7848 old_curbuf = curbuf;
7849
7850 /*
7851 * Set the file name to be used for <afile>.
7852 */
7853 if (fname_io == NULL)
7854 {
7855 if (fname != NULL && *fname != NUL)
7856 autocmd_fname = fname;
7857 else if (buf != NULL)
7858 autocmd_fname = buf->b_fname;
7859 else
7860 autocmd_fname = NULL;
7861 }
7862 else
7863 autocmd_fname = fname_io;
7864
7865 /*
7866 * Set the buffer number to be used for <abuf>.
7867 */
7868 if (buf == NULL)
7869 autocmd_bufnr = 0;
7870 else
7871 autocmd_bufnr = buf->b_fnum;
7872
7873 /*
7874 * When the file name is NULL or empty, use the file name of buffer "buf".
7875 * Always use the full path of the file name to match with, in case
7876 * "allow_dirs" is set.
7877 */
7878 if (fname == NULL || *fname == NUL)
7879 {
7880 if (buf == NULL)
7881 fname = NULL;
7882 else
7883 {
7884#ifdef FEAT_SYN_HL
7885 if (event == EVENT_SYNTAX)
7886 fname = buf->b_p_syn;
7887 else
7888#endif
7889 if (event == EVENT_FILETYPE)
7890 fname = buf->b_p_ft;
7891 else
7892 {
7893 if (buf->b_sfname != NULL)
7894 sfname = vim_strsave(buf->b_sfname);
7895 fname = buf->b_ffname;
7896 }
7897 }
7898 if (fname == NULL)
7899 fname = (char_u *)"";
7900 fname = vim_strsave(fname); /* make a copy, so we can change it */
7901 }
7902 else
7903 {
7904 sfname = vim_strsave(fname);
7905 /* Don't try expanding FileType, Syntax or WindowID. */
7906 if (event == EVENT_FILETYPE || event == EVENT_SYNTAX
7907 || event == EVENT_REMOTEREPLY)
7908 fname = vim_strsave(fname);
7909 else
7910 fname = FullName_save(fname, FALSE);
7911 }
7912 if (fname == NULL) /* out of memory */
7913 {
7914 vim_free(sfname);
7915 return FALSE;
7916 }
7917
7918#ifdef BACKSLASH_IN_FILENAME
7919 /*
7920 * Replace all backslashes with forward slashes. This makes the
7921 * autocommand patterns portable between Unix and MS-DOS.
7922 */
7923 if (sfname != NULL)
7924 forward_slash(sfname);
7925 forward_slash(fname);
7926#endif
7927
7928#ifdef VMS
7929 /* remove version for correct match */
7930 if (sfname != NULL)
7931 vms_remove_version(sfname);
7932 vms_remove_version(fname);
7933#endif
7934
7935 /*
7936 * Set the name to be used for <amatch>.
7937 */
7938 autocmd_match = fname;
7939
7940
7941 /* Don't redraw while doing auto commands. */
7942 ++RedrawingDisabled;
7943 save_sourcing_name = sourcing_name;
7944 sourcing_name = NULL; /* don't free this one */
7945 save_sourcing_lnum = sourcing_lnum;
7946 sourcing_lnum = 0; /* no line number here */
7947
7948#ifdef FEAT_EVAL
7949 save_current_SID = current_SID;
7950
7951 /* Don't use local function variables, if called from a function */
7952 save_funccalp = save_funccal();
7953#endif
7954
7955 /*
7956 * When starting to execute autocommands, save the search patterns.
7957 */
7958 if (!autocmd_busy)
7959 {
7960 save_search_patterns();
7961 saveRedobuff();
7962 did_filetype = keep_filetype;
7963 }
7964
7965 /*
7966 * Note that we are applying autocmds. Some commands need to know.
7967 */
7968 autocmd_busy = TRUE;
7969 filechangeshell_busy = (event == EVENT_FILECHANGEDSHELL);
7970 ++nesting; /* see matching decrement below */
7971
7972 /* Remember that FileType was triggered. Used for did_filetype(). */
7973 if (event == EVENT_FILETYPE)
7974 did_filetype = TRUE;
7975
7976 tail = gettail(fname);
7977
7978 /* Find first autocommand that matches */
7979 patcmd.curpat = first_autopat[(int)event];
7980 patcmd.nextcmd = NULL;
7981 patcmd.group = group;
7982 patcmd.fname = fname;
7983 patcmd.sfname = sfname;
7984 patcmd.tail = tail;
7985 patcmd.event = event;
7986 auto_next_pat(&patcmd, FALSE);
7987
7988 /* found one, start executing the autocommands */
7989 if (patcmd.curpat != NULL)
7990 {
7991#ifdef FEAT_EVAL
7992 /* set v:cmdarg (only when there is a matching pattern) */
7993 save_cmdbang = get_vim_var_nr(VV_CMDBANG);
7994 if (eap != NULL)
7995 {
7996 save_cmdarg = set_cmdarg(eap, NULL);
7997 set_vim_var_nr(VV_CMDBANG, (long)eap->forceit);
7998 }
7999 else
8000 save_cmdarg = NULL; /* avoid gcc warning */
8001#endif
8002 retval = TRUE;
8003 /* mark the last pattern, to avoid an endless loop when more patterns
8004 * are added when executing autocommands */
8005 for (ap = patcmd.curpat; ap->next != NULL; ap = ap->next)
8006 ap->last = FALSE;
8007 ap->last = TRUE;
8008 check_lnums(TRUE); /* make sure cursor and topline are valid */
8009 do_cmdline(NULL, getnextac, (void *)&patcmd,
8010 DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT);
8011#ifdef FEAT_EVAL
8012 if (eap != NULL)
8013 {
8014 (void)set_cmdarg(NULL, save_cmdarg);
8015 set_vim_var_nr(VV_CMDBANG, save_cmdbang);
8016 }
8017#endif
8018 }
8019
8020 --RedrawingDisabled;
8021 autocmd_busy = save_autocmd_busy;
8022 filechangeshell_busy = FALSE;
8023 autocmd_nested = save_autocmd_nested;
8024 vim_free(sourcing_name);
8025 sourcing_name = save_sourcing_name;
8026 sourcing_lnum = save_sourcing_lnum;
8027 autocmd_fname = save_autocmd_fname;
8028 autocmd_bufnr = save_autocmd_bufnr;
8029 autocmd_match = save_autocmd_match;
8030#ifdef FEAT_EVAL
8031 current_SID = save_current_SID;
8032 restore_funccal(save_funccalp);
8033#endif
8034 vim_free(fname);
8035 vim_free(sfname);
8036 --nesting; /* see matching increment above */
8037
8038 /*
8039 * When stopping to execute autocommands, restore the search patterns and
8040 * the redo buffer.
8041 */
8042 if (!autocmd_busy)
8043 {
8044 restore_search_patterns();
8045 restoreRedobuff();
8046 did_filetype = FALSE;
8047 }
8048
8049 /*
8050 * Some events don't set or reset the Changed flag.
8051 * Check if still in the same buffer!
8052 */
8053 if (curbuf == old_curbuf
8054 && (event == EVENT_BUFREADPOST
8055 || event == EVENT_BUFWRITEPOST
8056 || event == EVENT_FILEAPPENDPOST
8057 || event == EVENT_VIMLEAVE
8058 || event == EVENT_VIMLEAVEPRE))
8059 {
8060#ifdef FEAT_TITLE
8061 if (curbuf->b_changed != save_changed)
8062 need_maketitle = TRUE;
8063#endif
8064 curbuf->b_changed = save_changed;
8065 }
8066
8067 au_cleanup(); /* may really delete removed patterns/commands now */
8068 return retval;
8069}
8070
8071/*
8072 * Find next autocommand pattern that matches.
8073 */
8074 static void
8075auto_next_pat(apc, stop_at_last)
8076 AutoPatCmd *apc;
8077 int stop_at_last; /* stop when 'last' flag is set */
8078{
8079 AutoPat *ap;
8080 AutoCmd *cp;
8081 char_u *name;
8082 char *s;
8083
8084 vim_free(sourcing_name);
8085 sourcing_name = NULL;
8086
8087 for (ap = apc->curpat; ap != NULL && !got_int; ap = ap->next)
8088 {
8089 apc->curpat = NULL;
8090
8091 /* only use a pattern when it has not been removed, has commands and
8092 * the group matches */
8093 if (ap->pat != NULL && ap->cmds != NULL
8094 && (apc->group == AUGROUP_ALL || apc->group == ap->group))
8095 {
8096 if (match_file_pat(ap->reg_pat, apc->fname, apc->sfname, apc->tail,
8097 ap->allow_dirs))
8098 {
8099 name = event_nr2name(apc->event);
8100 s = _("%s Auto commands for \"%s\"");
8101 sourcing_name = alloc((unsigned)(STRLEN(s)
8102 + STRLEN(name) + ap->patlen + 1));
8103 if (sourcing_name != NULL)
8104 {
8105 sprintf((char *)sourcing_name, s,
8106 (char *)name, (char *)ap->pat);
8107 if (p_verbose >= 8)
8108 msg_str((char_u *)_("Executing %s"), sourcing_name);
8109 }
8110
8111 apc->curpat = ap;
8112 apc->nextcmd = ap->cmds;
8113 /* mark last command */
8114 for (cp = ap->cmds; cp->next != NULL; cp = cp->next)
8115 cp->last = FALSE;
8116 cp->last = TRUE;
8117 }
8118 line_breakcheck();
8119 if (apc->curpat != NULL) /* found a match */
8120 break;
8121 }
8122 if (stop_at_last && ap->last)
8123 break;
8124 }
8125}
8126
8127/*
8128 * Get next autocommand command.
8129 * Called by do_cmdline() to get the next line for ":if".
8130 * Returns allocated string, or NULL for end of autocommands.
8131 */
8132/* ARGSUSED */
8133 static char_u *
8134getnextac(c, cookie, indent)
8135 int c; /* not used */
8136 void *cookie;
8137 int indent; /* not used */
8138{
8139 AutoPatCmd *acp = (AutoPatCmd *)cookie;
8140 char_u *retval;
8141 AutoCmd *ac;
8142
8143 /* Can be called again after returning the last line. */
8144 if (acp->curpat == NULL)
8145 return NULL;
8146
8147 /* repeat until we find an autocommand to execute */
8148 for (;;)
8149 {
8150 /* skip removed commands */
8151 while (acp->nextcmd != NULL && acp->nextcmd->cmd == NULL)
8152 if (acp->nextcmd->last)
8153 acp->nextcmd = NULL;
8154 else
8155 acp->nextcmd = acp->nextcmd->next;
8156
8157 if (acp->nextcmd != NULL)
8158 break;
8159
8160 /* at end of commands, find next pattern that matches */
8161 if (acp->curpat->last)
8162 acp->curpat = NULL;
8163 else
8164 acp->curpat = acp->curpat->next;
8165 if (acp->curpat != NULL)
8166 auto_next_pat(acp, TRUE);
8167 if (acp->curpat == NULL)
8168 return NULL;
8169 }
8170
8171 ac = acp->nextcmd;
8172
8173 if (p_verbose >= 9)
8174 {
8175 msg_scroll = TRUE; /* always scroll up, don't overwrite */
8176 msg_str((char_u *)_("autocommand %s"), ac->cmd);
8177 msg_puts((char_u *)"\n"); /* don't overwrite this either */
8178 cmdline_row = msg_row;
8179 }
8180 retval = vim_strsave(ac->cmd);
8181 autocmd_nested = ac->nested;
8182#ifdef FEAT_EVAL
8183 current_SID = ac->scriptID;
8184#endif
8185 if (ac->last)
8186 acp->nextcmd = NULL;
8187 else
8188 acp->nextcmd = ac->next;
8189 return retval;
8190}
8191
8192/*
8193 * Return TRUE if there is a matching autocommand for "fname".
8194 */
8195 int
8196has_autocmd(event, sfname)
8197 EVENT_T event;
8198 char_u *sfname;
8199{
8200 AutoPat *ap;
8201 char_u *fname;
8202 char_u *tail = gettail(sfname);
8203 int retval = FALSE;
8204
8205 fname = FullName_save(sfname, FALSE);
8206 if (fname == NULL)
8207 return FALSE;
8208
8209#ifdef BACKSLASH_IN_FILENAME
8210 /*
8211 * Replace all backslashes with forward slashes. This makes the
8212 * autocommand patterns portable between Unix and MS-DOS.
8213 */
8214 sfname = vim_strsave(sfname);
8215 if (sfname != NULL)
8216 forward_slash(sfname);
8217 forward_slash(fname);
8218#endif
8219
8220 for (ap = first_autopat[(int)event]; ap != NULL; ap = ap->next)
8221 if (ap->pat != NULL && ap->cmds != NULL
8222 && match_file_pat(ap->reg_pat, fname, sfname, tail,
8223 ap->allow_dirs))
8224 {
8225 retval = TRUE;
8226 break;
8227 }
8228
8229 vim_free(fname);
8230#ifdef BACKSLASH_IN_FILENAME
8231 vim_free(sfname);
8232#endif
8233
8234 return retval;
8235}
8236
8237#if defined(FEAT_CMDL_COMPL) || defined(PROTO)
8238/*
8239 * Function given to ExpandGeneric() to obtain the list of autocommand group
8240 * names.
8241 */
8242/*ARGSUSED*/
8243 char_u *
8244get_augroup_name(xp, idx)
8245 expand_T *xp;
8246 int idx;
8247{
8248 if (idx == augroups.ga_len) /* add "END" add the end */
8249 return (char_u *)"END";
8250 if (idx >= augroups.ga_len) /* end of list */
8251 return NULL;
8252 if (AUGROUP_NAME(idx) == NULL) /* skip deleted entries */
8253 return (char_u *)"";
8254 return AUGROUP_NAME(idx); /* return a name */
8255}
8256
8257static int include_groups = FALSE;
8258
8259 char_u *
8260set_context_in_autocmd(xp, arg, doautocmd)
8261 expand_T *xp;
8262 char_u *arg;
8263 int doautocmd; /* TRUE for :doautocmd, FALSE for :autocmd */
8264{
8265 char_u *p;
8266 int group;
8267
8268 /* check for a group name, skip it if present */
8269 include_groups = FALSE;
8270 p = arg;
8271 group = au_get_grouparg(&arg);
8272 if (group == AUGROUP_ERROR)
8273 return NULL;
8274 /* If there only is a group name that's what we expand. */
8275 if (*arg == NUL && group != AUGROUP_ALL && !vim_iswhite(arg[-1]))
8276 {
8277 arg = p;
8278 group = AUGROUP_ALL;
8279 }
8280
8281 /* skip over event name */
8282 for (p = arg; *p != NUL && !vim_iswhite(*p); ++p)
8283 if (*p == ',')
8284 arg = p + 1;
8285 if (*p == NUL)
8286 {
8287 if (group == AUGROUP_ALL)
8288 include_groups = TRUE;
8289 xp->xp_context = EXPAND_EVENTS; /* expand event name */
8290 xp->xp_pattern = arg;
8291 return NULL;
8292 }
8293
8294 /* skip over pattern */
8295 arg = skipwhite(p);
8296 while (*arg && (!vim_iswhite(*arg) || arg[-1] == '\\'))
8297 arg++;
8298 if (*arg)
8299 return arg; /* expand (next) command */
8300
8301 if (doautocmd)
8302 xp->xp_context = EXPAND_FILES; /* expand file names */
8303 else
8304 xp->xp_context = EXPAND_NOTHING; /* pattern is not expanded */
8305 return NULL;
8306}
8307
8308/*
8309 * Function given to ExpandGeneric() to obtain the list of event names.
8310 */
8311/*ARGSUSED*/
8312 char_u *
8313get_event_name(xp, idx)
8314 expand_T *xp;
8315 int idx;
8316{
8317 if (idx < augroups.ga_len) /* First list group names, if wanted */
8318 {
8319 if (!include_groups || AUGROUP_NAME(idx) == NULL)
8320 return (char_u *)""; /* skip deleted entries */
8321 return AUGROUP_NAME(idx); /* return a name */
8322 }
8323 return (char_u *)event_names[idx - augroups.ga_len].name;
8324}
8325
8326#endif /* FEAT_CMDL_COMPL */
8327
8328/*
8329 * Return TRUE if an autocommand is defined for "event" and "pattern".
8330 * "pattern" can be NULL to accept any pattern.
8331 */
8332 int
8333au_exists(name, name_end, pattern)
8334 char_u *name;
8335 char_u *name_end;
8336 char_u *pattern;
8337{
8338 char_u *event_name;
8339 char_u *p;
8340 EVENT_T event;
8341 AutoPat *ap;
8342
8343 /* find the index (enum) for the event name */
8344 event_name = vim_strnsave(name, (int)(name_end - name));
8345 if (event_name == NULL)
8346 return FALSE;
8347 event = event_name2nr(event_name, &p);
8348 vim_free(event_name);
8349
8350 /* return FALSE if the event name is not recognized */
8351 if (event == NUM_EVENTS) /* unknown event name */
8352 return FALSE;
8353
8354 /* Find the first autocommand for this event.
8355 * If there isn't any, return FALSE;
8356 * If there is one and no pattern given, return TRUE; */
8357 ap = first_autopat[(int)event];
8358 if (ap == NULL)
8359 return FALSE;
8360 if (pattern == NULL)
8361 return TRUE;
8362
8363 /* Check if there is an autocommand with the given pattern. */
8364 for ( ; ap != NULL; ap = ap->next)
8365 /* only use a pattern when it has not been removed and has commands */
8366 if (ap->pat != NULL && ap->cmds != NULL
8367 && fnamecmp(ap->pat, pattern) == 0)
8368 return TRUE;
8369
8370 return FALSE;
8371}
8372#endif /* FEAT_AUTOCMD */
8373
8374#if defined(FEAT_AUTOCMD) || defined(FEAT_WILDIGN) || defined(PROTO)
8375/*
8376 * Try matching a filename with a pattern.
8377 * Used for autocommands and 'wildignore'.
8378 * Returns TRUE if there is a match, FALSE otherwise.
8379 */
8380 int
8381match_file_pat(pattern, fname, sfname, tail, allow_dirs)
8382 char_u *pattern; /* pattern to match with */
8383 char_u *fname; /* full path of file name */
8384 char_u *sfname; /* short file name or NULL */
8385 char_u *tail; /* tail of path */
8386 int allow_dirs; /* allow matching with dir */
8387{
8388 regmatch_T regmatch;
8389 int result = FALSE;
8390#ifdef FEAT_OSFILETYPE
8391 int no_pattern = FALSE; /* TRUE if check is filetype only */
8392 char_u *type_start;
8393 char_u c;
8394 int match = FALSE;
8395#endif
8396
8397#ifdef CASE_INSENSITIVE_FILENAME
8398 regmatch.rm_ic = TRUE; /* Always ignore case */
8399#else
8400 regmatch.rm_ic = FALSE; /* Don't ever ignore case */
8401#endif
8402#ifdef FEAT_OSFILETYPE
8403 if (*pattern == '<')
8404 {
8405 /* There is a filetype condition specified with this pattern.
8406 * Check the filetype matches first. If not, don't bother with the
8407 * pattern (set regprog to NULL).
8408 * Always use magic for the regexp.
8409 */
8410
8411 for (type_start = pattern + 1; (c = *pattern); pattern++)
8412 {
8413 if ((c == ';' || c == '>') && match == FALSE)
8414 {
8415 *pattern = NUL; /* Terminate the string */
8416 match = mch_check_filetype(fname, type_start);
8417 *pattern = c; /* Restore the terminator */
8418 type_start = pattern + 1;
8419 }
8420 if (c == '>')
8421 break;
8422 }
8423
8424 /* (c should never be NUL, but check anyway) */
8425 if (match == FALSE || c == NUL)
8426 regmatch.regprog = NULL; /* Doesn't match - don't check pat. */
8427 else if (*pattern == NUL)
8428 {
8429 regmatch.regprog = NULL; /* Vim will try to free regprog later */
8430 no_pattern = TRUE; /* Always matches - don't check pat. */
8431 }
8432 else
8433 regmatch.regprog = vim_regcomp(pattern + 1, RE_MAGIC);
8434 }
8435 else
8436#endif
8437 regmatch.regprog = vim_regcomp(pattern, RE_MAGIC);
8438
8439 /*
8440 * Try for a match with the pattern with:
8441 * 1. the full file name, when the pattern has a '/'.
8442 * 2. the short file name, when the pattern has a '/'.
8443 * 3. the tail of the file name, when the pattern has no '/'.
8444 */
8445 if (
8446#ifdef FEAT_OSFILETYPE
8447 /* If the check is for a filetype only and we don't care
8448 * about the path then skip all the regexp stuff.
8449 */
8450 no_pattern ||
8451#endif
8452 (regmatch.regprog != NULL
8453 && ((allow_dirs
8454 && (vim_regexec(&regmatch, fname, (colnr_T)0)
8455 || (sfname != NULL
8456 && vim_regexec(&regmatch, sfname, (colnr_T)0))))
8457 || (!allow_dirs && vim_regexec(&regmatch, tail, (colnr_T)0)))))
8458 result = TRUE;
8459
8460 vim_free(regmatch.regprog);
8461 return result;
8462}
8463#endif
8464
8465#if defined(FEAT_WILDIGN) || defined(PROTO)
8466/*
8467 * Return TRUE if a file matches with a pattern in "list".
8468 * "list" is a comma-separated list of patterns, like 'wildignore'.
8469 * "sfname" is the short file name or NULL, "ffname" the long file name.
8470 */
8471 int
8472match_file_list(list, sfname, ffname)
8473 char_u *list;
8474 char_u *sfname;
8475 char_u *ffname;
8476{
8477 char_u buf[100];
8478 char_u *tail;
8479 char_u *regpat;
8480 char allow_dirs;
8481 int match;
8482 char_u *p;
8483
8484 tail = gettail(sfname);
8485
8486 /* try all patterns in 'wildignore' */
8487 p = list;
8488 while (*p)
8489 {
8490 copy_option_part(&p, buf, 100, ",");
8491 regpat = file_pat_to_reg_pat(buf, NULL, &allow_dirs, FALSE);
8492 if (regpat == NULL)
8493 break;
8494 match = match_file_pat(regpat, ffname, sfname, tail, (int)allow_dirs);
8495 vim_free(regpat);
8496 if (match)
8497 return TRUE;
8498 }
8499 return FALSE;
8500}
8501#endif
8502
8503/*
8504 * Convert the given pattern "pat" which has shell style wildcards in it, into
8505 * a regular expression, and return the result in allocated memory. If there
8506 * is a directory path separator to be matched, then TRUE is put in
8507 * allow_dirs, otherwise FALSE is put there -- webb.
8508 * Handle backslashes before special characters, like "\*" and "\ ".
8509 *
8510 * If FEAT_OSFILETYPE defined then pass initial <type> through unchanged. Eg:
8511 * '<html>myfile' becomes '<html>^myfile$' -- leonard.
8512 *
8513 * Returns NULL when out of memory.
8514 */
8515/*ARGSUSED*/
8516 char_u *
8517file_pat_to_reg_pat(pat, pat_end, allow_dirs, no_bslash)
8518 char_u *pat;
8519 char_u *pat_end; /* first char after pattern or NULL */
8520 char *allow_dirs; /* Result passed back out in here */
8521 int no_bslash; /* Don't use a backward slash as pathsep */
8522{
8523 int size;
8524 char_u *endp;
8525 char_u *reg_pat;
8526 char_u *p;
8527 int i;
8528 int nested = 0;
8529 int add_dollar = TRUE;
8530#ifdef FEAT_OSFILETYPE
8531 int check_length = 0;
8532#endif
8533
8534 if (allow_dirs != NULL)
8535 *allow_dirs = FALSE;
8536 if (pat_end == NULL)
8537 pat_end = pat + STRLEN(pat);
8538
8539#ifdef FEAT_OSFILETYPE
8540 /* Find out how much of the string is the filetype check */
8541 if (*pat == '<')
8542 {
8543 /* Count chars until the next '>' */
8544 for (p = pat + 1; p < pat_end && *p != '>'; p++)
8545 ;
8546 if (p < pat_end)
8547 {
8548 /* Pattern is of the form <.*>.* */
8549 check_length = p - pat + 1;
8550 if (p + 1 >= pat_end)
8551 {
8552 /* The 'pattern' is a filetype check ONLY */
8553 reg_pat = (char_u *)alloc(check_length + 1);
8554 if (reg_pat != NULL)
8555 {
8556 mch_memmove(reg_pat, pat, (size_t)check_length);
8557 reg_pat[check_length] = NUL;
8558 }
8559 return reg_pat;
8560 }
8561 }
8562 /* else: there was no closing '>' - assume it was a normal pattern */
8563
8564 }
8565 pat += check_length;
8566 size = 2 + check_length;
8567#else
8568 size = 2; /* '^' at start, '$' at end */
8569#endif
8570
8571 for (p = pat; p < pat_end; p++)
8572 {
8573 switch (*p)
8574 {
8575 case '*':
8576 case '.':
8577 case ',':
8578 case '{':
8579 case '}':
8580 case '~':
8581 size += 2; /* extra backslash */
8582 break;
8583#ifdef BACKSLASH_IN_FILENAME
8584 case '\\':
8585 case '/':
8586 size += 4; /* could become "[\/]" */
8587 break;
8588#endif
8589 default:
8590 size++;
8591# ifdef FEAT_MBYTE
8592 if (enc_dbcs != 0 && (*mb_ptr2len_check)(p) > 1)
8593 {
8594 ++p;
8595 ++size;
8596 }
8597# endif
8598 break;
8599 }
8600 }
8601 reg_pat = alloc(size + 1);
8602 if (reg_pat == NULL)
8603 return NULL;
8604
8605#ifdef FEAT_OSFILETYPE
8606 /* Copy the type check in to the start. */
8607 if (check_length)
8608 mch_memmove(reg_pat, pat - check_length, (size_t)check_length);
8609 i = check_length;
8610#else
8611 i = 0;
8612#endif
8613
8614 if (pat[0] == '*')
8615 while (pat[0] == '*' && pat < pat_end - 1)
8616 pat++;
8617 else
8618 reg_pat[i++] = '^';
8619 endp = pat_end - 1;
8620 if (*endp == '*')
8621 {
8622 while (endp - pat > 0 && *endp == '*')
8623 endp--;
8624 add_dollar = FALSE;
8625 }
8626 for (p = pat; *p && nested >= 0 && p <= endp; p++)
8627 {
8628 switch (*p)
8629 {
8630 case '*':
8631 reg_pat[i++] = '.';
8632 reg_pat[i++] = '*';
8633 break;
8634 case '.':
8635#ifdef RISCOS
8636 if (allow_dirs != NULL)
8637 *allow_dirs = TRUE;
8638 /* FALLTHROUGH */
8639#endif
8640 case '~':
8641 reg_pat[i++] = '\\';
8642 reg_pat[i++] = *p;
8643 break;
8644 case '?':
8645#ifdef RISCOS
8646 case '#':
8647#endif
8648 reg_pat[i++] = '.';
8649 break;
8650 case '\\':
8651 if (p[1] == NUL)
8652 break;
8653#ifdef BACKSLASH_IN_FILENAME
8654 if (!no_bslash)
8655 {
8656 /* translate:
8657 * "\x" to "\\x" e.g., "dir\file"
8658 * "\*" to "\\.*" e.g., "dir\*.c"
8659 * "\?" to "\\." e.g., "dir\??.c"
8660 * "\+" to "\+" e.g., "fileX\+.c"
8661 */
8662 if ((vim_isfilec(p[1]) || p[1] == '*' || p[1] == '?')
8663 && p[1] != '+')
8664 {
8665 reg_pat[i++] = '[';
8666 reg_pat[i++] = '\\';
8667 reg_pat[i++] = '/';
8668 reg_pat[i++] = ']';
8669 if (allow_dirs != NULL)
8670 *allow_dirs = TRUE;
8671 break;
8672 }
8673 }
8674#endif
8675 if (*++p == '?'
8676#ifdef BACKSLASH_IN_FILENAME
8677 && no_bslash
8678#endif
8679 )
8680 reg_pat[i++] = '?';
8681 else
8682 if (*p == ',')
8683 reg_pat[i++] = ',';
8684 else
8685 {
8686 if (allow_dirs != NULL && vim_ispathsep(*p)
8687#ifdef BACKSLASH_IN_FILENAME
8688 && (!no_bslash || *p != '\\')
8689#endif
8690 )
8691 *allow_dirs = TRUE;
8692 reg_pat[i++] = '\\';
8693 reg_pat[i++] = *p;
8694 }
8695 break;
8696#ifdef BACKSLASH_IN_FILENAME
8697 case '/':
8698 reg_pat[i++] = '[';
8699 reg_pat[i++] = '\\';
8700 reg_pat[i++] = '/';
8701 reg_pat[i++] = ']';
8702 if (allow_dirs != NULL)
8703 *allow_dirs = TRUE;
8704 break;
8705#endif
8706 case '{':
8707 reg_pat[i++] = '\\';
8708 reg_pat[i++] = '(';
8709 nested++;
8710 break;
8711 case '}':
8712 reg_pat[i++] = '\\';
8713 reg_pat[i++] = ')';
8714 --nested;
8715 break;
8716 case ',':
8717 if (nested)
8718 {
8719 reg_pat[i++] = '\\';
8720 reg_pat[i++] = '|';
8721 }
8722 else
8723 reg_pat[i++] = ',';
8724 break;
8725 default:
8726# ifdef FEAT_MBYTE
8727 if (enc_dbcs != 0 && (*mb_ptr2len_check)(p) > 1)
8728 reg_pat[i++] = *p++;
8729 else
8730# endif
8731 if (allow_dirs != NULL && vim_ispathsep(*p))
8732 *allow_dirs = TRUE;
8733 reg_pat[i++] = *p;
8734 break;
8735 }
8736 }
8737 if (add_dollar)
8738 reg_pat[i++] = '$';
8739 reg_pat[i] = NUL;
8740 if (nested != 0)
8741 {
8742 if (nested < 0)
8743 EMSG(_("E219: Missing {."));
8744 else
8745 EMSG(_("E220: Missing }."));
8746 vim_free(reg_pat);
8747 reg_pat = NULL;
8748 }
8749 return reg_pat;
8750}