version 1.1, 1996/09/07 21:40:26 |
version 1.2, 1996/09/21 06:22:54 |
|
|
*/ |
*/ |
static int overstrike = FALSE; /* typing mode */ |
static int overstrike = FALSE; /* typing mode */ |
|
|
/* |
|
* The next two variables contain the bounds of any range given in a command. |
|
* They are set by do_cmdline(). |
|
*/ |
|
static linenr_t line1, line2; |
|
|
|
static int forceit; |
|
static int regname; |
|
static int quitmore = 0; |
static int quitmore = 0; |
static int cmd_numfiles = -1; /* number of files found by |
static int cmd_numfiles = -1; /* number of files found by |
filename completion */ |
filename completion */ |
|
|
static int ccheck_abbr __ARGS((int)); |
static int ccheck_abbr __ARGS((int)); |
static char_u *do_one_cmd __ARGS((char_u **, int *, int)); |
static char_u *do_one_cmd __ARGS((char_u **, int *, int)); |
static int buf_write_all __ARGS((BUF *)); |
static int buf_write_all __ARGS((BUF *)); |
static int do_write __ARGS((char_u *, int)); |
static int do_write __ARGS((char_u *, linenr_t, linenr_t, int, int)); |
static char_u *getargcmd __ARGS((char_u **)); |
static char_u *getargcmd __ARGS((char_u **)); |
static void backslash_halve __ARGS((char_u *p, int expand_wildcards)); |
static void backslash_halve __ARGS((char_u *p, int expand_wildcards)); |
static void do_make __ARGS((char_u *)); |
static void do_make __ARGS((char_u *)); |
static int do_arglist __ARGS((char_u *)); |
static int do_arglist __ARGS((char_u *)); |
static int is_backslash __ARGS((char_u *str)); |
static int is_backslash __ARGS((char_u *str)); |
static int check_readonly __ARGS((void)); |
static int check_readonly __ARGS((int)); |
static int check_changed __ARGS((BUF *, int, int)); |
static int check_changed __ARGS((BUF *, int, int, int)); |
static int check_changed_any __ARGS((void)); |
static int check_changed_any __ARGS((void)); |
static int check_more __ARGS((int)); |
static int check_more __ARGS((int, int)); |
static void vim_strncpy __ARGS((char_u *, char_u *, int)); |
static void vim_strncpy __ARGS((char_u *, char_u *, int)); |
static int nextwild __ARGS((int)); |
static int nextwild __ARGS((int)); |
static int showmatches __ARGS((char_u *)); |
static int showmatches __ARGS((char_u *)); |
|
|
if (lookfor && c != K_S_DOWN && c != K_S_UP && |
if (lookfor && c != K_S_DOWN && c != K_S_UP && |
c != K_DOWN && c != K_UP && |
c != K_DOWN && c != K_UP && |
c != K_PAGEDOWN && c != K_PAGEUP && |
c != K_PAGEDOWN && c != K_PAGEUP && |
|
c != K_KPAGEDOWN && c != K_KPAGEUP && |
(cmd_numfiles > 0 || (c != Ctrl('P') && c != Ctrl('N')))) |
(cmd_numfiles > 0 || (c != Ctrl('P') && c != Ctrl('N')))) |
{ |
{ |
vim_free(lookfor); |
vim_free(lookfor); |
|
|
|
|
case Ctrl('B'): /* begin of command line */ |
case Ctrl('B'): /* begin of command line */ |
case K_HOME: |
case K_HOME: |
|
case K_KHOME: |
cmdpos = 0; |
cmdpos = 0; |
cmdspos = 1; |
cmdspos = 1; |
goto cmdline_not_changed; |
goto cmdline_not_changed; |
|
|
case Ctrl('E'): /* end of command line */ |
case Ctrl('E'): /* end of command line */ |
case K_END: |
case K_END: |
|
case K_KEND: |
cmdpos = cmdlen; |
cmdpos = cmdlen; |
cmdbuff[cmdlen] = NUL; |
cmdbuff[cmdlen] = NUL; |
cmdspos = strsize(cmdbuff) + 1; |
cmdspos = strsize(cmdbuff) + 1; |
|
|
case K_S_UP: |
case K_S_UP: |
case K_S_DOWN: |
case K_S_DOWN: |
case K_PAGEUP: |
case K_PAGEUP: |
|
case K_KPAGEUP: |
case K_PAGEDOWN: |
case K_PAGEDOWN: |
|
case K_KPAGEDOWN: |
if (hislen == 0) /* no history */ |
if (hislen == 0) /* no history */ |
goto cmdline_not_changed; |
goto cmdline_not_changed; |
|
|
|
|
{ |
{ |
/* one step backwards */ |
/* one step backwards */ |
if (c == K_UP || c == K_S_UP || c == Ctrl('P') || |
if (c == K_UP || c == K_S_UP || c == Ctrl('P') || |
c == K_PAGEUP) |
c == K_PAGEUP || c == K_KPAGEUP) |
{ |
{ |
if (hiscnt == hislen) /* first time */ |
if (hiscnt == hislen) /* first time */ |
hiscnt = hisidx[histype]; |
hiscnt = hisidx[histype]; |
|
|
long argt; |
long argt; |
register linenr_t lnum; |
register linenr_t lnum; |
long n = 0; /* init to shut up gcc */ |
long n = 0; /* init to shut up gcc */ |
|
linenr_t line1 = 1, line2 = 1; /* the command range */ |
int addr_count; /* number of address specs */ |
int addr_count; /* number of address specs */ |
|
int forceit = FALSE; /* '!' after command */ |
FPOS pos; |
FPOS pos; |
int append = FALSE; /* write with append */ |
int append = FALSE; /* write with append */ |
int usefilter = FALSE; /* no read/write but filter */ |
int usefilter = FALSE; /* no read/write but filter */ |
|
int regname = 0; /* register name flag */ |
char_u *nextcomm = NULL; /* no next command yet */ |
char_u *nextcomm = NULL; /* no next command yet */ |
int amount = 0; /* for ":>"; init for gcc */ |
int amount = 0; /* for ":>"; init for gcc */ |
char_u *errormsg = NULL; /* error message */ |
char_u *errormsg = NULL; /* error message */ |
WIN *old_curwin = NULL; /* init for GCC */ |
WIN *old_curwin = NULL; /* init for GCC */ |
|
static int if_level = 0; /* depth in :if */ |
|
|
/* when not editing the last file :q has to be typed twice */ |
/* when not editing the last file :q has to be typed twice */ |
if (quitmore) |
if (quitmore) |
|
|
*/ |
*/ |
|
|
addr_count = 0; |
addr_count = 0; |
|
if (if_level) |
|
goto skip_address; |
|
|
--cmd; |
--cmd; |
do |
do |
{ |
{ |
|
|
if (lnum == MAXLNUM) |
if (lnum == MAXLNUM) |
addr_count = 0; |
addr_count = 0; |
} |
} |
|
skip_address: |
|
|
/* |
/* |
* 4. parse command |
* 4. parse command |
|
|
* ":3|..." prints line 3 |
* ":3|..." prints line 3 |
* ":|" prints current line |
* ":|" prints current line |
*/ |
*/ |
|
if (if_level) /* skip this if inside :if */ |
|
goto doend; |
if (*cmd == '|') |
if (*cmd == '|') |
{ |
{ |
cmdidx = CMD_print; |
cmdidx = CMD_print; |
|
|
break; |
break; |
if (i == 0 || cmdidx == CMD_SIZE) |
if (i == 0 || cmdidx == CMD_SIZE) |
{ |
{ |
STRCPY(IObuff, "Not an editor command"); |
if (if_level == 0) |
if (!sourcing) |
|
{ |
{ |
STRCAT(IObuff, ": "); |
STRCPY(IObuff, "Not an editor command"); |
STRNCAT(IObuff, *cmdlinep, 40); |
if (!sourcing) |
|
{ |
|
STRCAT(IObuff, ": "); |
|
STRNCAT(IObuff, *cmdlinep, 40); |
|
} |
|
errormsg = IObuff; |
} |
} |
errormsg = IObuff; |
|
goto doend; |
goto doend; |
} |
} |
} |
} |
|
|
|
/* |
|
* Handle the future ":if" command. |
|
* For version 4 everything between ":if" and ":endif" is ignored. |
|
*/ |
|
if (cmdidx == CMD_if) |
|
++if_level; |
|
if (if_level) |
|
{ |
|
if (cmdidx == CMD_endif) |
|
--if_level; |
|
goto doend; |
|
} |
|
|
if (*p == '!') /* forced commands */ |
if (*p == '!') /* forced commands */ |
{ |
{ |
++p; |
++p; |
|
|
line2 = curbuf->b_ml.ml_line_count; |
line2 = curbuf->b_ml.ml_line_count; |
} |
} |
|
|
regname = 0; |
|
/* accept numbered register only when no count allowed (:put) */ |
/* accept numbered register only when no count allowed (:put) */ |
if ((argt & REGSTR) && *arg != NUL && is_yank_buffer(*arg, FALSE) && |
if ((argt & REGSTR) && *arg != NUL && is_yank_buffer(*arg, FALSE) && |
!((argt & COUNT) && isdigit(*arg))) |
!((argt & COUNT) && isdigit(*arg))) |
|
|
#define SPEC_CCWORD 3 |
#define SPEC_CCWORD 3 |
"<cfile>", /* cursor path name */ |
"<cfile>", /* cursor path name */ |
#define SPEC_CFILE 4 |
#define SPEC_CFILE 4 |
|
#ifdef AUTOCMD |
"<afile>" /* autocommand file name */ |
"<afile>" /* autocommand file name */ |
#define SPEC_AFILE 5 |
# define SPEC_AFILE 5 |
|
#endif |
}; |
}; |
#define SPEC_COUNT 6 |
#define SPEC_COUNT (sizeof(spec_str) / sizeof(char *)) |
|
|
/* |
/* |
* Decide to expand wildcards *before* replacing '%', '#', etc. If |
* Decide to expand wildcards *before* replacing '%', '#', etc. If |
|
|
for (p = arg; *p; ++p) |
for (p = arg; *p; ++p) |
{ |
{ |
/* |
/* |
|
* Quick check if this cannot be the start of a special string. |
|
*/ |
|
if (vim_strchr((char_u *)"%#<", *p) == NULL) |
|
continue; |
|
|
|
/* |
* Check if there is something to do. |
* Check if there is something to do. |
*/ |
*/ |
for (spec_idx = 0; spec_idx < SPEC_COUNT; ++spec_idx) |
for (spec_idx = 0; spec_idx < SPEC_COUNT; ++spec_idx) |
|
|
buf = q; |
buf = q; |
break; |
break; |
|
|
|
#ifdef AUTOCMD |
case SPEC_AFILE: /* file name for autocommand */ |
case SPEC_AFILE: /* file name for autocommand */ |
q = autocmd_fname; |
q = autocmd_fname; |
if (q == NULL) |
if (q == NULL) |
|
|
goto doend; |
goto doend; |
} |
} |
break; |
break; |
|
#endif |
} |
} |
|
|
len = STRLEN(q); /* length of new string */ |
len = STRLEN(q); /* length of new string */ |
|
|
|
|
/* ":h" - head, remove "/filename" */ |
/* ":h" - head, remove "/filename" */ |
/* ":h" can be repeated */ |
/* ":h" can be repeated */ |
|
/* Don't remove the first "/" or "c:\" */ |
while (p[n] == ':' && p[n + 1] == 'h') |
while (p[n] == ':' && p[n + 1] == 'h') |
{ |
{ |
n += 2; |
n += 2; |
while (tail > q && ispathsep(tail[-1])) |
s = get_past_head(q); |
|
while (tail > s && ispathsep(tail[-1])) |
--tail; |
--tail; |
len = tail - q; |
len = tail - q; |
while (tail > q && !ispathsep(tail[-1])) |
while (tail > s && !ispathsep(tail[-1])) |
--tail; |
--tail; |
} |
} |
|
|
|
|
*/ |
*/ |
case CMD_quit: |
case CMD_quit: |
/* if more files or windows we won't exit */ |
/* if more files or windows we won't exit */ |
if (check_more(FALSE) == OK && only_one_window()) |
if (check_more(FALSE, forceit) == OK && only_one_window()) |
exiting = TRUE; |
exiting = TRUE; |
if (check_changed(curbuf, FALSE, FALSE) || |
if (check_changed(curbuf, FALSE, FALSE, forceit) || |
check_more(TRUE) == FAIL || |
check_more(TRUE, forceit) == FAIL || |
(only_one_window() && check_changed_any())) |
(only_one_window() && !forceit && check_changed_any())) |
{ |
{ |
exiting = FALSE; |
exiting = FALSE; |
settmode(1); |
settmode(1); |
|
|
*/ |
*/ |
case CMD_qall: |
case CMD_qall: |
exiting = TRUE; |
exiting = TRUE; |
if (!check_changed_any()) |
if (forceit || !check_changed_any()) |
getout(0); |
getout(0); |
exiting = FALSE; |
exiting = FALSE; |
settmode(1); |
settmode(1); |
|
|
case CMD_xit: |
case CMD_xit: |
case CMD_wq: |
case CMD_wq: |
/* if more files or windows we won't exit */ |
/* if more files or windows we won't exit */ |
if (check_more(FALSE) == OK && only_one_window()) |
if (check_more(FALSE, forceit) == OK && only_one_window()) |
exiting = TRUE; |
exiting = TRUE; |
if (((cmdidx == CMD_wq || curbuf->b_changed) && |
if (((cmdidx == CMD_wq || curbuf->b_changed) && |
do_write(arg, FALSE) == FAIL) || |
do_write(arg, line1, line2, FALSE, forceit) == FAIL) || |
check_more(TRUE) == FAIL || |
check_more(TRUE, forceit) == FAIL || |
(only_one_window() && check_changed_any())) |
(only_one_window() && !forceit && check_changed_any())) |
{ |
{ |
exiting = FALSE; |
exiting = FALSE; |
settmode(1); |
settmode(1); |
|
|
EMSG2("\"%s\" is readonly, use ! to write anyway", buf->b_xfilename); |
EMSG2("\"%s\" is readonly, use ! to write anyway", buf->b_xfilename); |
++error; |
++error; |
} |
} |
else if (buf_write_all(buf) == FAIL) |
else |
++error; |
{ |
|
if (buf_write_all(buf) == FAIL) |
|
++error; |
|
#ifdef AUTOCMD |
|
/* an autocommand may have deleted the buffer */ |
|
if (!buf_valid(buf)) |
|
buf = firstbuf; |
|
#endif |
|
} |
} |
} |
} |
} |
if (exiting) |
if (exiting) |
|
|
|
|
case CMD_recover: /* recover file */ |
case CMD_recover: /* recover file */ |
recoverymode = TRUE; |
recoverymode = TRUE; |
if (!check_changed(curbuf, FALSE, TRUE) && |
if (!check_changed(curbuf, FALSE, TRUE, forceit) && |
(*arg == NUL || setfname(arg, NULL, TRUE) == OK)) |
(*arg == NUL || setfname(arg, NULL, TRUE) == OK)) |
ml_recover(); |
ml_recover(); |
recoverymode = FALSE; |
recoverymode = FALSE; |
|
|
i = curwin->w_arg_idx - (int)line2; |
i = curwin->w_arg_idx - (int)line2; |
line1 = 1; |
line1 = 1; |
line2 = curbuf->b_ml.ml_line_count; |
line2 = curbuf->b_ml.ml_line_count; |
if (do_write(arg, FALSE) == FAIL) |
if (do_write(arg, line1, line2, FALSE, forceit) == FAIL) |
break; |
break; |
goto donextfile; |
goto donextfile; |
|
|
|
|
* argument list is not redefined. |
* argument list is not redefined. |
*/ |
*/ |
if (!(p_hid || cmdidx == CMD_snext) && |
if (!(p_hid || cmdidx == CMD_snext) && |
check_changed(curbuf, TRUE, FALSE)) |
check_changed(curbuf, TRUE, FALSE, forceit)) |
break; |
break; |
|
|
if (*arg != NUL) /* redefine file list */ |
if (*arg != NUL) /* redefine file list */ |
|
|
if (p_hid) |
if (p_hid) |
other = otherfile(fix_fname(arg_files[i])); |
other = otherfile(fix_fname(arg_files[i])); |
if ((!p_hid || !other) && |
if ((!p_hid || !other) && |
check_changed(curbuf, TRUE, !other)) |
check_changed(curbuf, TRUE, !other, forceit)) |
break; |
break; |
} |
} |
curwin->w_arg_idx = i; |
curwin->w_arg_idx = i; |
if (i == arg_count - 1) |
if (i == arg_count - 1) |
arg_had_last = TRUE; |
arg_had_last = TRUE; |
(void)do_ecmd(0, arg_files[curwin->w_arg_idx], |
(void)do_ecmd(0, arg_files[curwin->w_arg_idx], |
NULL, do_ecmd_cmd, p_hid, do_ecmd_lnum, FALSE); |
NULL, do_ecmd_cmd, do_ecmd_lnum, |
|
(p_hid ? ECMD_HIDE : 0) + |
|
(forceit ? ECMD_FORCEIT : 0)); |
break; |
break; |
|
|
case CMD_previous: |
case CMD_previous: |
|
|
if (usefilter) /* input lines to shell command */ |
if (usefilter) /* input lines to shell command */ |
do_bang(1, line1, line2, FALSE, arg, TRUE, FALSE); |
do_bang(1, line1, line2, FALSE, arg, TRUE, FALSE); |
else |
else |
(void)do_write(arg, append); |
(void)do_write(arg, line1, line2, append, forceit); |
break; |
break; |
|
|
/* |
/* |
|
|
if ((cmdidx == CMD_new) && *arg == NUL) |
if ((cmdidx == CMD_new) && *arg == NUL) |
{ |
{ |
setpcmark(); |
setpcmark(); |
(void)do_ecmd(0, NULL, NULL, do_ecmd_cmd, TRUE, |
(void)do_ecmd(0, NULL, NULL, do_ecmd_cmd, (linenr_t)1, |
(linenr_t)1, FALSE); |
ECMD_HIDE + (forceit ? ECMD_FORCEIT : 0)); |
} |
} |
else if (cmdidx != CMD_split || *arg != NUL) |
else if (cmdidx != CMD_split || *arg != NUL) |
{ |
{ |
|
|
if (cmdidx == CMD_view || cmdidx == CMD_sview) |
if (cmdidx == CMD_view || cmdidx == CMD_sview) |
readonlymode = TRUE; |
readonlymode = TRUE; |
setpcmark(); |
setpcmark(); |
(void)do_ecmd(0, arg, NULL, do_ecmd_cmd, p_hid, |
(void)do_ecmd(0, arg, NULL, do_ecmd_cmd, do_ecmd_lnum, |
do_ecmd_lnum, FALSE); |
(p_hid ? ECMD_HIDE : 0) + |
|
(forceit ? ECMD_FORCEIT : 0)); |
readonlymode = n; |
readonlymode = n; |
} |
} |
else |
else |
|
|
* old window to new file */ |
* old window to new file */ |
if ((cmdidx == CMD_new || cmdidx == CMD_split) && |
if ((cmdidx == CMD_new || cmdidx == CMD_split) && |
*arg != NUL && curwin != old_curwin && |
*arg != NUL && curwin != old_curwin && |
|
win_valid(old_curwin) && |
old_curwin->w_buffer != curbuf) |
old_curwin->w_buffer != curbuf) |
old_curwin->w_alt_fnum = curbuf->b_fnum; |
old_curwin->w_alt_fnum = curbuf->b_fnum; |
break; |
break; |
|
|
postponed_split = TRUE; |
postponed_split = TRUE; |
/*FALLTHROUGH*/ |
/*FALLTHROUGH*/ |
case CMD_tag: |
case CMD_tag: |
do_tag(arg, 0, addr_count ? (int)line2 : 1); |
do_tag(arg, 0, addr_count ? (int)line2 : 1, forceit); |
break; |
break; |
|
|
case CMD_pop: |
case CMD_pop: |
do_tag((char_u *)"", 1, addr_count ? (int)line2 : 1); |
do_tag((char_u *)"", 1, addr_count ? (int)line2 : 1, forceit); |
break; |
break; |
|
|
case CMD_tags: |
case CMD_tags: |
|
|
|
|
case CMD_put: |
case CMD_put: |
yankbuffer = regname; |
yankbuffer = regname; |
|
/* |
|
* ":0put" works like ":1put!". |
|
*/ |
|
if (line2 == 0) |
|
{ |
|
line2 = 1; |
|
forceit = TRUE; |
|
} |
curwin->w_cursor.lnum = line2; |
curwin->w_cursor.lnum = line2; |
do_put(forceit ? BACKWARD : FORWARD, -1L, FALSE); |
do_put(forceit ? BACKWARD : FORWARD, -1L, FALSE); |
break; |
break; |
|
|
} |
} |
|
|
case CMD_cc: |
case CMD_cc: |
qf_jump(0, addr_count ? (int)line2 : 0); |
qf_jump(0, addr_count ? (int)line2 : 0, forceit); |
break; |
break; |
|
|
case CMD_cfile: |
case CMD_cfile: |
|
|
(void)do_set(arg); |
(void)do_set(arg); |
} |
} |
if (qf_init() == OK) |
if (qf_init() == OK) |
qf_jump(0, 0); /* display first error */ |
qf_jump(0, 0, forceit); /* display first error */ |
break; |
break; |
|
|
case CMD_clist: |
case CMD_clist: |
|
|
break; |
break; |
|
|
case CMD_cnext: |
case CMD_cnext: |
qf_jump(FORWARD, addr_count ? (int)line2 : 1); |
qf_jump(FORWARD, addr_count ? (int)line2 : 1, forceit); |
break; |
break; |
|
|
case CMD_cNext: |
case CMD_cNext: |
case CMD_cprevious: |
case CMD_cprevious: |
qf_jump(BACKWARD, addr_count ? (int)line2 : 1); |
qf_jump(BACKWARD, addr_count ? (int)line2 : 1, forceit); |
break; |
break; |
|
|
case CMD_cquit: |
case CMD_cquit: |
getout(1); /* this does not always work. why? */ |
getout(1); /* this does not always pass on the exit |
|
code to the Manx compiler. why? */ |
|
|
case CMD_mark: |
case CMD_mark: |
case CMD_k: |
case CMD_k: |
|
|
} |
} |
if (did_emsg) |
if (did_emsg) |
nextcomm = NULL; /* cancel nextcomm at an error */ |
nextcomm = NULL; /* cancel nextcomm at an error */ |
forceit = FALSE; /* reset now so it can be used in getfile() */ |
|
if (nextcomm && *nextcomm == NUL) /* not really a next command */ |
if (nextcomm && *nextcomm == NUL) /* not really a next command */ |
nextcomm = NULL; |
nextcomm = NULL; |
return nextcomm; |
return nextcomm; |
|
|
* return FAIL for failure, OK otherwise |
* return FAIL for failure, OK otherwise |
*/ |
*/ |
int |
int |
autowrite(buf) |
autowrite(buf, forceit) |
BUF *buf; |
BUF *buf; |
|
int forceit; |
{ |
{ |
if (!p_aw || (!forceit && buf->b_p_ro) || buf->b_filename == NULL) |
if (!p_aw || (!forceit && buf->b_p_ro) || buf->b_filename == NULL) |
return FAIL; |
return FAIL; |
|
|
return; |
return; |
for (buf = firstbuf; buf; buf = buf->b_next) |
for (buf = firstbuf; buf; buf = buf->b_next) |
if (buf->b_changed && !buf->b_p_ro) |
if (buf->b_changed && !buf->b_p_ro) |
|
{ |
(void)buf_write_all(buf); |
(void)buf_write_all(buf); |
|
#ifdef AUTOCMD |
|
/* an autocommand may have deleted the buffer */ |
|
if (!buf_valid(buf)) |
|
buf = firstbuf; |
|
#endif |
|
} |
} |
} |
|
|
/* |
/* |
|
|
buf_write_all(buf) |
buf_write_all(buf) |
BUF *buf; |
BUF *buf; |
{ |
{ |
return (buf_write(buf, buf->b_filename, buf->b_sfilename, |
int retval; |
(linenr_t)1, buf->b_ml.ml_line_count, 0, 0, TRUE, FALSE)); |
#ifdef AUTOCMD |
|
BUF *old_curbuf = curbuf; |
|
#endif |
|
|
|
retval = (buf_write(buf, buf->b_filename, buf->b_sfilename, |
|
(linenr_t)1, buf->b_ml.ml_line_count, |
|
FALSE, FALSE, TRUE, FALSE)); |
|
#ifdef AUTOCMD |
|
if (curbuf != old_curbuf) |
|
MSG("Warning: Entered other buffer unexpectedly (check autocommands)"); |
|
#endif |
|
return retval; |
} |
} |
|
|
/* |
/* |
|
|
* return FAIL for failure, OK otherwise |
* return FAIL for failure, OK otherwise |
*/ |
*/ |
static int |
static int |
do_write(fname, append) |
do_write(fname, line1, line2, append, forceit) |
char_u *fname; |
char_u *fname; |
int append; |
linenr_t line1, line2; |
|
int append; |
|
int forceit; |
{ |
{ |
int other; |
int other; |
char_u *sfname = NULL; /* init to shut up gcc */ |
char_u *sfname = NULL; /* init to shut up gcc */ |
|
|
* writing to the current file is not allowed in readonly mode |
* writing to the current file is not allowed in readonly mode |
* and need a file name |
* and need a file name |
*/ |
*/ |
if (!other && (check_readonly() || check_fname() == FAIL)) |
if (!other && (check_readonly(forceit) || check_fname() == FAIL)) |
return FAIL; |
return FAIL; |
|
|
if (!other) |
if (!other) |
|
|
* - NULL to start an empty buffer |
* - NULL to start an empty buffer |
* sfname: the short file name (or NULL) |
* sfname: the short file name (or NULL) |
* command: the command to be executed after loading the file |
* command: the command to be executed after loading the file |
* hide: if TRUE don't free the current buffer |
|
* newlnum: put cursor on this line number (if possible) |
* newlnum: put cursor on this line number (if possible) |
* set_help: set b_help flag of (new) buffer before opening file |
* flags: |
|
* ECMD_HIDE: if TRUE don't free the current buffer |
|
* ECMD_SET_HELP: set b_help flag of (new) buffer before opening file |
|
* ECMD_OLDBUF: use existing buffer if it exists |
|
* ECMD_FORCEIT: ! used for Ex command |
* |
* |
* return FAIL for failure, OK otherwise |
* return FAIL for failure, OK otherwise |
*/ |
*/ |
int |
int |
do_ecmd(fnum, fname, sfname, command, hide, newlnum, set_help) |
do_ecmd(fnum, fname, sfname, command, newlnum, flags) |
int fnum; |
int fnum; |
char_u *fname; |
char_u *fname; |
char_u *sfname; |
char_u *sfname; |
char_u *command; |
char_u *command; |
int hide; |
|
linenr_t newlnum; |
linenr_t newlnum; |
int set_help; |
int flags; |
{ |
{ |
int other_file; /* TRUE if editing another file */ |
int other_file; /* TRUE if editing another file */ |
int oldbuf = FALSE; /* TRUE if using existing buffer */ |
int oldbuf; /* TRUE if using existing buffer */ |
|
#ifdef AUTOCMD |
|
int auto_buf = FALSE; /* TRUE if autocommands brought us |
|
into the buffer unexpectedly */ |
|
#endif |
BUF *buf; |
BUF *buf; |
|
|
if (fnum != 0) |
if (fnum != 0) |
|
|
/* |
/* |
* if the file was changed we may not be allowed to abandon it |
* if the file was changed we may not be allowed to abandon it |
* - if we are going to re-edit the same file |
* - if we are going to re-edit the same file |
* - or if we are the only window on this file and if hide is FALSE |
* - or if we are the only window on this file and if ECMD_HIDE is FALSE |
*/ |
*/ |
if ((!other_file || (curbuf->b_nwindows == 1 && !hide)) && |
if (((!other_file && !(flags & ECMD_OLDBUF)) || |
check_changed(curbuf, FALSE, !other_file)) |
(curbuf->b_nwindows == 1 && !(flags & ECMD_HIDE))) && |
|
check_changed(curbuf, FALSE, !other_file, (flags & ECMD_FORCEIT))) |
{ |
{ |
if (fnum == 0 && other_file && fname != NULL) |
if (fnum == 0 && other_file && fname != NULL) |
setaltfname(fname, sfname, (linenr_t)1); |
setaltfname(fname, sfname, (linenr_t)1); |
|
|
if (buf->b_ml.ml_mfp == NULL) /* no memfile yet */ |
if (buf->b_ml.ml_mfp == NULL) /* no memfile yet */ |
{ |
{ |
oldbuf = FALSE; |
oldbuf = FALSE; |
buf->b_nwindows = 1; |
buf->b_nwindows = 0; |
} |
} |
else /* existing memfile */ |
else /* existing memfile */ |
{ |
{ |
oldbuf = TRUE; |
oldbuf = TRUE; |
++buf->b_nwindows; |
|
buf_check_timestamp(buf); |
buf_check_timestamp(buf); |
} |
} |
|
|
/* |
/* |
* make the (new) buffer the one used by the current window |
* Make the (new) buffer the one used by the current window. |
* if the old buffer becomes unused, free it if hide is FALSE |
* If the old buffer becomes unused, free it if ECMD_HIDE is FALSE. |
* If the current buffer was empty and has no file name, curbuf |
* If the current buffer was empty and has no file name, curbuf |
* is returned by buflist_new(). |
* is returned by buflist_new(). |
*/ |
*/ |
if (buf != curbuf) |
if (buf != curbuf) |
{ |
{ |
#ifdef AUTOCMD |
#ifdef AUTOCMD |
|
BUF *old_curbuf; |
|
char_u *new_name = NULL; |
|
|
|
/* |
|
* Be careful: The autocommands may delete any buffer and change |
|
* the current buffer. |
|
* - If the buffer we are going to edit is deleted, give up. |
|
* - If we ended up in the new buffer already, need to skip a few |
|
* things, set auto_buf. |
|
*/ |
|
old_curbuf = curbuf; |
|
if (buf->b_xfilename != NULL) |
|
new_name = strsave(buf->b_xfilename); |
apply_autocmds(EVENT_BUFLEAVE, NULL, NULL); |
apply_autocmds(EVENT_BUFLEAVE, NULL, NULL); |
|
if (!buf_valid(buf)) /* new buffer has been deleted */ |
|
{ |
|
EMSG2("Autocommands unexpectedly deleted new buffer %s", |
|
new_name == NULL ? (char_u *)"" : new_name); |
|
vim_free(new_name); |
|
return FAIL; |
|
} |
|
vim_free(new_name); |
|
if (buf == curbuf) /* already in new buffer */ |
|
auto_buf = TRUE; |
|
else |
|
{ |
|
if (curbuf == old_curbuf) |
#endif |
#endif |
|
{ |
#ifdef VIMINFO |
#ifdef VIMINFO |
curbuf->b_last_cursor = curwin->w_cursor; |
curbuf->b_last_cursor = curwin->w_cursor; |
#endif |
#endif |
buf_copy_options(curbuf, buf, TRUE); |
buf_copy_options(curbuf, buf, TRUE, FALSE); |
close_buffer(curwin, curbuf, !hide, FALSE); |
} |
curwin->w_buffer = buf; |
close_buffer(curwin, curbuf, !(flags & ECMD_HIDE), FALSE); |
curbuf = buf; |
curwin->w_buffer = buf; |
|
curbuf = buf; |
|
++curbuf->b_nwindows; |
|
#ifdef AUTOCMD |
|
} |
|
#endif |
} |
} |
|
else |
|
++curbuf->b_nwindows; |
|
|
curwin->w_pcmark.lnum = 1; |
curwin->w_pcmark.lnum = 1; |
curwin->w_pcmark.col = 0; |
curwin->w_pcmark.col = 0; |
} |
} |
else if (check_fname() == FAIL) |
else |
return FAIL; |
{ |
|
if (check_fname() == FAIL) |
|
return FAIL; |
|
oldbuf = (flags & ECMD_OLDBUF); |
|
} |
|
|
/* |
/* |
* If we get here we are sure to start editing |
* If we get here we are sure to start editing |
*/ |
*/ |
/* don't redraw until the cursor is in the right line */ |
/* don't redraw until the cursor is in the right line */ |
++RedrawingDisabled; |
++RedrawingDisabled; |
if (set_help) |
if (flags & ECMD_SET_HELP) |
curbuf->b_help = TRUE; |
curbuf->b_help = TRUE; |
|
|
/* |
/* |
* other_file oldbuf |
* other_file oldbuf |
* FALSE FALSE re-edit same file, buffer is re-used |
* FALSE FALSE re-edit same file, buffer is re-used |
* FALSE TRUE not posible |
* FALSE TRUE re-edit same file, nothing changes |
* TRUE FALSE start editing new file, new buffer |
* TRUE FALSE start editing new file, new buffer |
* TRUE TRUE start editing in existing buffer (nothing to do) |
* TRUE TRUE start editing in existing buffer (nothing to do) |
*/ |
*/ |
if (!other_file) /* re-use the buffer */ |
if (!other_file && !oldbuf) /* re-use the buffer */ |
{ |
{ |
if (newlnum == 0) |
if (newlnum == 0) |
newlnum = curwin->w_cursor.lnum; |
newlnum = curwin->w_cursor.lnum; |
|
|
} |
} |
|
|
/* |
/* |
|
* Reset cursor position, could be used by autocommands. |
|
*/ |
|
adjust_cursor(); |
|
|
|
/* |
* Check if we are editing the w_arg_idx file in the argument list. |
* Check if we are editing the w_arg_idx file in the argument list. |
*/ |
*/ |
check_arg_idx(); |
check_arg_idx(); |
|
|
if (!oldbuf) /* need to read the file */ |
|
(void)open_buffer(); |
|
#ifdef AUTOCMD |
#ifdef AUTOCMD |
else |
if (!auto_buf) |
apply_autocmds(EVENT_BUFENTER, NULL, NULL); |
|
#endif |
#endif |
win_init(curwin); |
{ |
maketitle(); |
/* |
|
* Careful: open_buffer() and apply_autocmds() may change the current |
|
* buffer and window. |
|
*/ |
|
if (!oldbuf) /* need to read the file */ |
|
(void)open_buffer(); |
|
#ifdef AUTOCMD |
|
else |
|
apply_autocmds(EVENT_BUFENTER, NULL, NULL); |
|
check_arg_idx(); |
|
#endif |
|
win_init(curwin); |
|
maketitle(); |
|
} |
|
|
if (command == NULL) |
if (command == NULL) |
{ |
{ |
|
|
* Did not read the file, need to show some info about the file. |
* Did not read the file, need to show some info about the file. |
* Do this after setting the cursor. |
* Do this after setting the cursor. |
*/ |
*/ |
if (oldbuf) |
if (oldbuf |
|
#ifdef AUTOCMD |
|
&& !auto_buf |
|
#endif |
|
) |
fileinfo(did_cd, TRUE, FALSE); |
fileinfo(did_cd, TRUE, FALSE); |
|
|
if (command != NULL) |
if (command != NULL) |
|
|
{ |
{ |
for ( ; *p; ++p) |
for ( ; *p; ++p) |
if (is_backslash(p) |
if (is_backslash(p) |
#if defined(MSDOS) || defined(WIN32) |
|
&& p[1] != '*' && p[1] != '?' |
|
#endif |
|
#if defined(UNIX) || defined(OS2) |
#if defined(UNIX) || defined(OS2) |
&& !(expand_wildcards && |
&& !(expand_wildcards && |
vim_strchr((char_u *)" *?[{`$\\", p[1])) |
vim_strchr((char_u *)" *?[{`$\\", p[1])) |
|
|
autowrite_all(); |
autowrite_all(); |
vim_remove(p_ef); |
vim_remove(p_ef); |
|
|
sprintf((char *)IObuff, "%s %s %s", arg, p_sp, p_ef); |
sprintf((char *)IObuff, "%s%s%s %s %s", p_shq, arg, p_shq, p_sp, p_ef); |
MSG_OUTSTR(":!"); |
MSG_OUTSTR(":!"); |
msg_outtrans(IObuff); /* show what we are doing */ |
msg_outtrans(IObuff); /* show what we are doing */ |
do_shell(IObuff); |
do_shell(IObuff); |
|
|
#endif |
#endif |
|
|
if (qf_init() == OK) |
if (qf_init() == OK) |
qf_jump(0, 0); /* display first error */ |
qf_jump(0, 0, FALSE); /* display first error */ |
|
|
vim_remove(p_ef); |
vim_remove(p_ef); |
} |
} |
|
|
char_u *str; |
char_u *str; |
{ |
{ |
#ifdef BACKSLASH_IN_FILENAME |
#ifdef BACKSLASH_IN_FILENAME |
return (str[0] == '\\' && str[1] != NUL && |
return (str[0] == '\\' && str[1] != NUL && str[1] != '*' && str[1] != '?' |
!(isfilechar(str[1]) && str[1] != '\\')); |
&& !(isfilechar(str[1]) && str[1] != '\\')); |
#else |
#else |
return (str[0] == '\\' && str[1] != NUL); |
return (str[0] == '\\' && str[1] != NUL); |
#endif |
#endif |
|
|
} |
} |
|
|
static int |
static int |
check_readonly() |
check_readonly(forceit) |
|
int forceit; |
{ |
{ |
if (!forceit && curbuf->b_p_ro) |
if (!forceit && curbuf->b_p_ro) |
{ |
{ |
|
|
* return TRUE if buffer was changed and cannot be abandoned. |
* return TRUE if buffer was changed and cannot be abandoned. |
*/ |
*/ |
static int |
static int |
check_changed(buf, checkaw, mult_win) |
check_changed(buf, checkaw, mult_win, forceit) |
BUF *buf; |
BUF *buf; |
int checkaw; /* do autowrite if buffer was changed */ |
int checkaw; /* do autowrite if buffer was changed */ |
int mult_win; /* check also when several windows for the buffer */ |
int mult_win; /* check also when several windows for the buffer */ |
|
int forceit; |
{ |
{ |
if ( !forceit && |
if ( !forceit && |
buf->b_changed && (mult_win || buf->b_nwindows <= 1) && |
buf->b_changed && (mult_win || buf->b_nwindows <= 1) && |
(!checkaw || autowrite(buf) == FAIL)) |
(!checkaw || autowrite(buf, forceit) == FAIL)) |
{ |
{ |
emsg(e_nowrtmsg); |
emsg(e_nowrtmsg); |
return TRUE; |
return TRUE; |
|
|
BUF *buf; |
BUF *buf; |
int save; |
int save; |
|
|
if (!forceit) |
for (buf = firstbuf; buf != NULL; buf = buf->b_next) |
{ |
{ |
for (buf = firstbuf; buf != NULL; buf = buf->b_next) |
if (buf->b_changed) |
{ |
{ |
if (buf->b_changed) |
/* There must be a wait_return for this message, do_buffer |
|
* will cause a redraw */ |
|
exiting = FALSE; |
|
if (EMSG2("No write since last change for buffer \"%s\"", |
|
buf->b_xfilename == NULL ? (char_u *)"No File" : |
|
buf->b_xfilename)) |
{ |
{ |
/* There must be a wait_return for this message, do_buffer |
save = no_wait_return; |
* will cause a redraw */ |
no_wait_return = FALSE; |
exiting = FALSE; |
wait_return(FALSE); |
if (EMSG2("No write since last change for buffer \"%s\"", |
no_wait_return = save; |
buf->b_xfilename == NULL ? (char_u *)"No File" : |
|
buf->b_xfilename)) |
|
{ |
|
save = no_wait_return; |
|
no_wait_return = FALSE; |
|
wait_return(FALSE); |
|
no_wait_return = save; |
|
} |
|
(void)do_buffer(DOBUF_GOTO, DOBUF_FIRST, FORWARD, |
|
buf->b_fnum, 0); |
|
return TRUE; |
|
} |
} |
|
(void)do_buffer(DOBUF_GOTO, DOBUF_FIRST, FORWARD, buf->b_fnum, 0); |
|
return TRUE; |
} |
} |
} |
} |
return FALSE; |
return FALSE; |
|
|
* return OK otherwise |
* return OK otherwise |
*/ |
*/ |
static int |
static int |
check_more(message) |
check_more(message, forceit) |
int message; /* when FALSE check only, no messages */ |
int message; /* when FALSE check only, no messages */ |
|
int forceit; |
{ |
{ |
if (!forceit && only_one_window() && arg_count > 1 && !arg_had_last && |
if (!forceit && only_one_window() && arg_count > 1 && !arg_had_last && |
quitmore == 0) |
quitmore == 0) |
|
|
* 'lnum' is the line number for the cursor in the new file (if non-zero). |
* 'lnum' is the line number for the cursor in the new file (if non-zero). |
*/ |
*/ |
int |
int |
getfile(fnum, fname, sfname, setpm, lnum) |
getfile(fnum, fname, sfname, setpm, lnum, forceit) |
int fnum; |
int fnum; |
char_u *fname; |
char_u *fname; |
char_u *sfname; |
char_u *sfname; |
int setpm; |
int setpm; |
linenr_t lnum; |
linenr_t lnum; |
|
int forceit; |
{ |
{ |
int other; |
int other; |
|
|
|
|
if (other) |
if (other) |
++no_wait_return; /* don't wait for autowrite message */ |
++no_wait_return; /* don't wait for autowrite message */ |
if (other && !forceit && curbuf->b_nwindows == 1 && |
if (other && !forceit && curbuf->b_nwindows == 1 && |
!p_hid && curbuf->b_changed && autowrite(curbuf) == FAIL) |
!p_hid && curbuf->b_changed && autowrite(curbuf, forceit) == FAIL) |
{ |
{ |
if (other) |
if (other) |
--no_wait_return; |
--no_wait_return; |
|
|
|
|
return 0; /* it's in the same file */ |
return 0; /* it's in the same file */ |
} |
} |
if (do_ecmd(fnum, fname, sfname, NULL, p_hid, lnum, FALSE) == OK) |
if (do_ecmd(fnum, fname, sfname, NULL, lnum, |
|
(p_hid ? ECMD_HIDE : 0) + (forceit ? ECMD_FORCEIT : 0)) == OK) |
return -1; /* opened another file */ |
return -1; /* opened another file */ |
return 1; /* error encountered */ |
return 1; /* error encountered */ |
} |
} |
|
|
static char_u **cmd_files = NULL; /* list of input files */ |
static char_u **cmd_files = NULL; /* list of input files */ |
static int findex; |
static int findex; |
static char_u *orig_save = NULL; /* kept value of orig */ |
static char_u *orig_save = NULL; /* kept value of orig */ |
int i, found = 0; |
int i, j; |
int multmatch = FALSE; |
int non_suf_match; /* number without matching suffix */ |
long_u len; |
long_u len; |
char_u *setsuf; |
char_u *setsuf; |
int fnamelen, setsuflen; |
int fnamelen, setsuflen; |
|
|
else |
else |
{ |
{ |
/* |
/* |
* If the pattern starts with a '~', replace the home diretory |
* May change home directory back to "~" |
* with '~' again. |
|
*/ |
*/ |
if (*str == '~' && (options & WILD_HOME_REPLACE)) |
if (options & WILD_HOME_REPLACE) |
{ |
tilde_replace(str, cmd_numfiles, cmd_files); |
for (i = 0; i < cmd_numfiles; ++i) |
|
{ |
|
p = home_replace_save(NULL, cmd_files[i]); |
|
if (p != NULL) |
|
{ |
|
vim_free(cmd_files[i]); |
|
cmd_files[i] = p; |
|
} |
|
} |
|
} |
|
|
|
/* |
/* |
* Insert backslashes into a file name before a space, \, %, # and |
* Insert backslashes into a file name before a space, \, %, # and |
|
|
|
|
if (mode != WILD_ALL && mode != WILD_LONGEST) |
if (mode != WILD_ALL && mode != WILD_LONGEST) |
{ |
{ |
|
non_suf_match = 1; |
if (cmd_numfiles > 1) /* more than one match; check suffix */ |
if (cmd_numfiles > 1) /* more than one match; check suffix */ |
{ |
{ |
found = -2; |
non_suf_match = 0; |
for (i = 0; i < cmd_numfiles; ++i) |
for (i = 0; i < cmd_numfiles; ++i) |
{ |
{ |
fnamelen = STRLEN(cmd_files[i]); |
fnamelen = STRLEN(cmd_files[i]); |
|
|
} |
} |
if (setsuflen) /* suffix matched: ignore file */ |
if (setsuflen) /* suffix matched: ignore file */ |
continue; |
continue; |
if (found >= 0) |
/* |
{ |
* Move the name without matching suffix to the front |
multmatch = TRUE; |
* of the list. This makes CTRL-N work nice. |
break; |
*/ |
} |
p = cmd_files[i]; |
found = i; |
for (j = i; j > non_suf_match; --j) |
|
cmd_files[j] = cmd_files[j - 1]; |
|
cmd_files[non_suf_match++] = p; |
} |
} |
} |
} |
if (multmatch || found < 0) |
if (non_suf_match != 1) |
{ |
{ |
/* Can we ever get here unless it's while expanding |
/* Can we ever get here unless it's while expanding |
* interactively? If not, we can get rid of this all |
* interactively? If not, we can get rid of this all |
|
|
emsg(e_toomany); |
emsg(e_toomany); |
else |
else |
beep_flush(); |
beep_flush(); |
found = 0; /* return first one */ |
|
multmatch = TRUE; /* for found < 0 */ |
|
} |
} |
if (found >= 0 && !(multmatch && mode == WILD_EXPAND_FREE)) |
if (!(non_suf_match != 1 && mode == WILD_EXPAND_FREE)) |
ss = strsave(cmd_files[found]); |
ss = strsave(cmd_files[0]); |
} |
} |
} |
} |
} |
} |
|
|
} |
} |
|
|
/* |
/* |
|
* For each file name in files[num_files]: |
|
* If 'orig_pat' starts with "~/", replace the home directory with "~". |
|
*/ |
|
void |
|
tilde_replace(orig_pat, num_files, files) |
|
char_u *orig_pat; |
|
int num_files; |
|
char_u **files; |
|
{ |
|
int i; |
|
char_u *p; |
|
|
|
if (orig_pat[0] == '~' && ispathsep(orig_pat[1])) |
|
{ |
|
for (i = 0; i < num_files; ++i) |
|
{ |
|
p = home_replace_save(NULL, files[i]); |
|
if (p != NULL) |
|
{ |
|
vim_free(files[i]); |
|
files[i] = p; |
|
} |
|
} |
|
} |
|
} |
|
|
|
/* |
* show all matches for completion on the command line |
* show all matches for completion on the command line |
*/ |
*/ |
static int |
static int |
|
|
int cmdidx; |
int cmdidx; |
long argt; |
long argt; |
char_u delim; |
char_u delim; |
int forced = FALSE; |
int forceit = FALSE; |
int usefilter = FALSE; /* filter instead of file name */ |
int usefilter = FALSE; /* filter instead of file name */ |
|
|
expand_pattern = buff; |
expand_pattern = buff; |
|
|
|
|
if (*p == '!') /* forced commands */ |
if (*p == '!') /* forced commands */ |
{ |
{ |
forced = TRUE; |
forceit = TRUE; |
++p; |
++p; |
} |
} |
|
|
|
|
|
|
if (cmdidx == CMD_read) |
if (cmdidx == CMD_read) |
{ |
{ |
usefilter = forced; /* :r! filter if forced */ |
usefilter = forceit; /* :r! filter if forced */ |
if (*arg == '!') /* :r !filter */ |
if (*arg == '!') /* :r !filter */ |
{ |
{ |
++arg; |
++arg; |
|
|
case CMD_vmenu: case CMD_vnoremenu: case CMD_vunmenu: |
case CMD_vmenu: case CMD_vnoremenu: case CMD_vunmenu: |
case CMD_imenu: case CMD_inoremenu: case CMD_iunmenu: |
case CMD_imenu: case CMD_inoremenu: case CMD_iunmenu: |
case CMD_cmenu: case CMD_cnoremenu: case CMD_cunmenu: |
case CMD_cmenu: case CMD_cnoremenu: case CMD_cunmenu: |
return gui_set_context_in_menu_cmd(cmd, arg, forced); |
return gui_set_context_in_menu_cmd(cmd, arg, forceit); |
break; |
break; |
#endif |
#endif |
default: |
default: |
|
|
expand_context == EXPAND_BOOL_SETTINGS) |
expand_context == EXPAND_BOOL_SETTINGS) |
ret = ExpandSettings(prog, num_file, file); |
ret = ExpandSettings(prog, num_file, file); |
else if (expand_context == EXPAND_TAGS) |
else if (expand_context == EXPAND_TAGS) |
ret = find_tags(NULL, prog, num_file, file, FALSE); |
ret = find_tags(NULL, prog, num_file, file, FALSE, FALSE); |
#ifdef AUTOCMD |
#ifdef AUTOCMD |
else if (expand_context == EXPAND_EVENTS) |
else if (expand_context == EXPAND_EVENTS) |
ret = ExpandEvents(prog, num_file, file); |
ret = ExpandEvents(prog, num_file, file); |