ex_docmd.c
资源名称:vim53src.zip [点击查看]
上传用户:gddssl
上传日期:2007-01-06
资源大小:1003k
文件大小:169k
源码类别:
编辑器/阅读器
开发平台:
DOS
- /*
- * start editing a new file
- *
- * fnum: file number; if zero use ffname/sfname
- * ffname: the file name
- * - full path if sfname used,
- * - any file name if sfname is NULL
- * - empty string to re-edit with the same file name (but may be
- * in a different directory)
- * - NULL to start an empty buffer
- * sfname: the short file name (or NULL)
- * command: the command to be executed after loading the file
- * newlnum: put cursor on this line number (if possible)
- * 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
- * ECMD_ADDBUF : don't edit, just add to buffer list
- *
- * return FAIL for failure, OK otherwise
- */
- int
- do_ecmd(fnum, ffname, sfname, command, newlnum, flags)
- int fnum;
- char_u *ffname;
- char_u *sfname;
- char_u *command;
- linenr_t newlnum;
- int flags;
- {
- int other_file; /* TRUE if editing another file */
- 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;
- char_u *free_fname = NULL;
- #ifdef USE_BROWSE
- char_u *browse_file = NULL;
- #endif
- int retval = FAIL;
- long n;
- if (fnum != 0)
- {
- if (fnum == curbuf->b_fnum) /* file is already being edited */
- return OK; /* nothing to do */
- other_file = TRUE;
- }
- else
- {
- #ifdef USE_BROWSE
- if (browse)
- {
- browse_file = do_browse(FALSE, (char_u *)"Edit File", NULL,
- NULL, ffname, NULL, curbuf);
- if (browse_file == NULL)
- goto theend;
- ffname = browse_file;
- }
- #endif
- /* if no short name given, use ffname for short name */
- if (sfname == NULL)
- sfname = ffname;
- #ifdef USE_FNAME_CASE
- # ifdef USE_LONG_FNAME
- if (USE_LONG_FNAME)
- # endif
- fname_case(sfname); /* set correct case for short file name */
- #endif
- if ((flags & ECMD_ADDBUF) && (ffname == NULL || *ffname == NUL))
- goto theend;
- if (ffname == NULL)
- other_file = TRUE;
- /* there is no file name */
- else if (*ffname == NUL && curbuf->b_ffname == NULL)
- other_file = FALSE;
- else
- {
- if (*ffname == NUL) /* re-edit with same file name */
- {
- ffname = curbuf->b_ffname;
- sfname = curbuf->b_fname;
- }
- free_fname = fix_fname(ffname); /* may expand to full path name */
- if (free_fname != NULL)
- ffname = free_fname;
- other_file = otherfile(ffname);
- }
- }
- /*
- * if the file was changed we may not be allowed to abandon it
- * - if we are going to re-edit the same file
- * - or if we are the only window on this file and if ECMD_HIDE is FALSE
- */
- if ( ((!other_file && !(flags & ECMD_OLDBUF))
- || (curbuf->b_nwindows == 1
- && !(flags & (ECMD_HIDE | ECMD_ADDBUF))))
- && check_changed(curbuf, FALSE, !other_file,
- (flags & ECMD_FORCEIT), FALSE))
- {
- if (fnum == 0 && other_file && ffname != NULL)
- setaltfname(ffname, sfname, newlnum);
- goto theend;
- }
- /*
- * End Visual mode before switching to another buffer, so the text can be
- * copied into the GUI selection buffer.
- */
- if (VIsual_active)
- {
- end_visual_mode();
- VIsual_reselect = FALSE;
- }
- /*
- * If we are starting to edit another file, open a (new) buffer.
- * Otherwise we re-use the current buffer.
- */
- if (other_file)
- {
- if (!(flags & ECMD_ADDBUF))
- {
- curwin->w_alt_fnum = curbuf->b_fnum;
- buflist_altfpos();
- }
- if (fnum)
- buf = buflist_findnr(fnum);
- else
- {
- if (flags & ECMD_ADDBUF)
- {
- linenr_t tlnum = 1L;
- if (command != NULL)
- {
- tlnum = atol((char *)command);
- if (tlnum <= 0)
- tlnum = 1L;
- }
- (void)buflist_new(ffname, sfname, tlnum, FALSE);
- goto theend;
- }
- else
- buf = buflist_new(ffname, sfname, 1L, TRUE);
- }
- if (buf == NULL)
- goto theend;
- if (buf->b_ml.ml_mfp == NULL) /* no memfile yet */
- {
- oldbuf = FALSE;
- buf->b_nwindows = 0;
- }
- else /* existing memfile */
- {
- oldbuf = TRUE;
- buf_check_timestamp(buf);
- }
- /*
- * Make the (new) buffer the one used by the current window.
- * 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
- * is returned by buflist_new().
- */
- if (buf != curbuf)
- {
- #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_fname != NULL)
- new_name = vim_strsave(buf->b_fname);
- apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, FALSE, curbuf);
- 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);
- goto theend;
- }
- vim_free(new_name);
- if (buf == curbuf) /* already in new buffer */
- auto_buf = TRUE;
- else
- {
- if (curbuf == old_curbuf)
- #endif
- buf_copy_options(curbuf, buf, BCO_ENTER);
- close_buffer(curwin, curbuf, !(flags & ECMD_HIDE), FALSE);
- curwin->w_buffer = buf;
- curbuf = buf;
- ++curbuf->b_nwindows;
- /* set 'fileformat' */
- if (*p_ffs && !oldbuf)
- set_fileformat(default_fileformat());
- #ifdef AUTOCMD
- }
- #endif
- }
- else
- ++curbuf->b_nwindows;
- curwin->w_pcmark.lnum = 1;
- curwin->w_pcmark.col = 0;
- }
- else
- {
- if ((flags & ECMD_ADDBUF) || check_fname() == FAIL)
- goto theend;
- oldbuf = (flags & ECMD_OLDBUF);
- }
- /*
- * If we get here we are sure to start editing
- */
- /* don't redraw until the cursor is in the right line */
- ++RedrawingDisabled;
- if (flags & ECMD_SET_HELP)
- {
- curbuf->b_help = TRUE;
- curbuf->b_p_bin = FALSE; /* reset 'bin' before reading file */
- }
- /*
- * other_file oldbuf
- * FALSE FALSE re-edit same file, buffer is re-used
- * FALSE TRUE re-edit same file, nothing changes
- * TRUE FALSE start editing new file, new buffer
- * TRUE TRUE start editing in existing buffer (nothing to do)
- */
- if (!other_file && !oldbuf) /* re-use the buffer */
- {
- if (newlnum == 0)
- newlnum = curwin->w_cursor.lnum;
- buf_freeall(curbuf, FALSE); /* free all things for buffer */
- buf_clear(curbuf);
- curbuf->b_op_start.lnum = 0; /* clear '[ and '] marks */
- curbuf->b_op_end.lnum = 0;
- }
- /*
- * 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_arg_idx();
- #ifdef AUTOCMD
- if (!auto_buf)
- #endif
- {
- /*
- * Set cursor and init window before reading the file and executing
- * autocommands. This allows for the autocommands to position the
- * cursor.
- */
- win_init(curwin);
- /*
- * Careful: open_buffer() and apply_autocmds() may change the current
- * buffer and window.
- */
- if (!oldbuf) /* need to read the file */
- {
- curbuf->b_flags |= BF_CHECK_RO; /* set/reset 'ro' flag */
- (void)open_buffer(FALSE);
- }
- #ifdef AUTOCMD
- else
- apply_autocmds(EVENT_BUFENTER, NULL, NULL, FALSE, curbuf);
- check_arg_idx();
- #endif
- maketitle();
- }
- if (command == NULL)
- {
- if (newlnum)
- {
- curwin->w_cursor.lnum = newlnum;
- check_cursor_lnum();
- beginline(BL_SOL | BL_FIX);
- }
- else
- {
- if (exmode_active)
- {
- curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
- check_cursor_lnum();
- }
- beginline(BL_WHITE | BL_FIX);
- }
- }
- /* Check if cursors in other windows on the same buffer are still valid */
- check_lnums(FALSE);
- /*
- * Did not read the file, need to show some info about the file.
- * Do this after setting the cursor.
- */
- if (oldbuf
- #ifdef AUTOCMD
- && !auto_buf
- #endif
- )
- fileinfo(FALSE, TRUE, FALSE);
- if (command != NULL)
- do_cmdline(command, NULL, NULL, DOCMD_VERBOSE);
- --RedrawingDisabled;
- if (!skip_redraw)
- {
- n = p_so;
- if (command == NULL)
- p_so = 999; /* force cursor halfway the window */
- update_topline();
- p_so = n;
- update_curbuf(NOT_VALID); /* redraw now */
- }
- if (p_im)
- need_start_insertmode = TRUE;
- retval = OK;
- theend:
- #ifdef USE_BROWSE
- vim_free(browse_file);
- #endif
- vim_free(free_fname);
- return retval;
- }
- #ifdef QUICKFIX
- static void
- do_make(arg, errorformat)
- char_u *arg;
- char_u *errorformat;
- {
- char_u *name;
- autowrite_all();
- name = get_mef_name(TRUE);
- if (name == NULL)
- return;
- mch_remove(name); /* in case it's not unique */
- /*
- * If 'shellpipe' empty: don't redirect to 'errorfile'.
- */
- if (*p_sp == NUL)
- sprintf((char *)IObuff, "%s%s%s", p_shq, arg, p_shq);
- else
- sprintf((char *)IObuff, "%s%s%s %s %s", p_shq, arg, p_shq, p_sp, name);
- /*
- * Output a newline if there's something else than the :make command that
- * was typed (in which case the cursor is in column 0).
- */
- if (msg_col != 0)
- msg_putchar('n');
- MSG_PUTS(":!");
- msg_outtrans(IObuff); /* show what we are doing */
- /* let the shell know if we are redirecting output or not */
- do_shell(IObuff, *p_sp ? SHELL_DOOUT : 0);
- #ifdef AMIGA
- out_flush();
- /* read window status report and redraw before message */
- (void)char_avail();
- #endif
- if (qf_init(name, errorformat) > 0)
- qf_jump(0, 0, FALSE); /* display first error */
- mch_remove(name);
- vim_free(name);
- }
- /*
- * Return the name for the errorfile, in allocated memory.
- * When "newname" is TRUE, find a new unique name when 'makeef' contains
- * "##". Returns NULL for error.
- */
- static char_u *
- get_mef_name(newname)
- int newname;
- {
- char_u *p;
- char_u *name;
- static int start = -1;
- static int off = 0;
- if (*p_mef == NUL)
- {
- EMSG("makeef option not set");
- return NULL;
- }
- for (p = p_mef; *p; ++p)
- if (p[0] == '#' && p[1] == '#')
- break;
- if (*p == NUL)
- return vim_strsave(p_mef);
- /* When "newname" set: keep trying until the name doesn't exist yet. */
- for (;;)
- {
- if (newname)
- {
- if (start == -1)
- start = mch_get_pid();
- ++off;
- }
- name = alloc((unsigned)STRLEN(p_mef) + 30);
- if (name == NULL)
- break;
- STRCPY(name, p_mef);
- sprintf((char *)name + (p - p_mef), "%d%d", start, off);
- STRCAT(name, p + 2);
- if (!newname || mch_getperm(name) < 0)
- break;
- vim_free(name);
- }
- return name;
- }
- /*
- * ":cfile" command.
- */
- static void
- do_cfile(eap)
- EXARG *eap;
- {
- if (*eap->arg != NUL)
- set_string_option_direct((char_u *)"ef", -1, eap->arg, TRUE);
- if (qf_init(p_ef, p_efm) > 0)
- qf_jump(0, 0, eap->forceit); /* display first error */
- }
- #endif /* QUICKFIX */
- /*
- * Redefine the argument list to 'str'.
- *
- * Return FAIL for failure, OK otherwise.
- */
- static int
- do_arglist(str)
- char_u *str;
- {
- int new_count = 0;
- char_u **new_files = NULL;
- int exp_count;
- char_u **exp_files;
- char_u **t;
- char_u *p;
- int inquote;
- int i;
- while (*str)
- {
- /*
- * create a new entry in new_files[]
- */
- t = (char_u **)lalloc((long_u)(sizeof(char_u *) * (new_count + 1)),
- TRUE);
- if (t != NULL)
- for (i = new_count; --i >= 0; )
- t[i] = new_files[i];
- vim_free(new_files);
- if (t == NULL)
- return FAIL;
- new_files = t;
- new_files[new_count++] = str;
- /*
- * isolate one argument, taking quotes
- */
- inquote = FALSE;
- for (p = str; *str; ++str)
- {
- /*
- * for MSDOS et.al. a backslash is part of a file name.
- * Only skip ", space and tab.
- */
- if (rem_backslash(str))
- *p++ = *++str;
- else
- {
- if (!inquote && vim_isspace(*str))
- break;
- if (*str == '"')
- inquote ^= TRUE;
- else
- *p++ = *str;
- }
- }
- str = skipwhite(str);
- *p = NUL;
- }
- i = expand_wildcards(new_count, new_files, &exp_count, &exp_files,
- EW_DIR|EW_FILE|EW_NOTFOUND);
- vim_free(new_files);
- if (i == FAIL)
- return FAIL;
- if (exp_count == 0)
- {
- emsg(e_nomatch);
- return FAIL;
- }
- FreeWild(arg_file_count, arg_files);
- arg_files = exp_files;
- arg_file_count = exp_count;
- arg_had_last = FALSE;
- /*
- * put all file names in the buffer list
- */
- for (i = 0; i < arg_file_count; ++i)
- (void)buflist_add(arg_files[i]);
- return OK;
- }
- /*
- * Check if we are editing the w_arg_idx file in the argument list.
- */
- void
- check_arg_idx()
- {
- if (arg_file_count > 1
- && (curbuf->b_ffname == NULL
- || curwin->w_arg_idx >= arg_file_count
- || !(fullpathcmp(arg_files[curwin->w_arg_idx],
- curbuf->b_ffname, TRUE) & FPC_SAME)))
- curwin->w_arg_idx_invalid = TRUE;
- else
- curwin->w_arg_idx_invalid = FALSE;
- }
- int
- ends_excmd(c)
- int c;
- {
- return (c == NUL || c == '|' || c == '"' || c == 'n');
- }
- /*
- * Return the next command, after the first '|' or 'n'.
- * Return NULL if not found.
- */
- char_u *
- find_nextcmd(p)
- char_u *p;
- {
- while (*p != '|' && *p != 'n')
- {
- if (*p == NUL)
- return NULL;
- ++p;
- }
- return (p + 1);
- }
- /*
- * Check if *p is a separator between Ex commands.
- * Return NULL if it isn't, (p + 1) if it is.
- */
- char_u *
- check_nextcmd(p)
- char_u *p;
- {
- p = skipwhite(p);
- if (*p == '|' || *p == 'n')
- return (p + 1);
- else
- return NULL;
- }
- /*
- * - if there are more files to edit
- * - and this is the last window
- * - and forceit not used
- * - and not repeated twice on a row
- * return FAIL and give error message if 'message' TRUE
- * return OK otherwise
- */
- static int
- check_more(message, forceit)
- int message; /* when FALSE check only, no messages */
- int forceit;
- {
- int n = arg_file_count - curwin->w_arg_idx - 1;
- if (!forceit && only_one_window() && arg_file_count > 1 && !arg_had_last
- && n >= 0 && quitmore == 0)
- {
- if (message)
- {
- #if defined(GUI_DIALOG) || defined(CON_DIALOG)
- if ((p_confirm || confirm) && curbuf->b_fname != NULL)
- {
- char_u buff[IOSIZE];
- sprintf((char *)buff, "%d more files to edit. Quit anyway?",
- n);
- if (vim_dialog_yesno(VIM_QUESTION, NULL, buff, 1) == VIM_YES)
- return OK;
- return FAIL;
- }
- #endif
- EMSGN("%ld more files to edit", n);
- quitmore = 2; /* next try to quit is allowed */
- }
- return FAIL;
- }
- return OK;
- }
- /*
- * Structure used to store info for each sourced file.
- * It is shared between do_source() and getsourceline().
- * This is required, because it needs to be handed to do_cmdline() and
- * sourcing can be done recursively.
- */
- struct source_cookie
- {
- FILE *fp; /* opened file for sourcing */
- #ifdef USE_CRNL
- int fileformat; /* EOL_UNKNOWN, EOL_UNIX or EOL_DOS */
- int error; /* TRUE if LF found after CR-LF */
- #endif
- };
- /*
- * do_source: Read the file "fname" and execute its lines as EX commands.
- *
- * This function may be called recursively!
- *
- * return FAIL if file could not be opened, OK otherwise
- */
- int
- do_source(fname, check_other, is_vimrc)
- char_u *fname;
- int check_other; /* check for .vimrc and _vimrc */
- int is_vimrc; /* call vimrc_found() when file exists */
- {
- struct source_cookie cookie;
- char_u *save_sourcing_name;
- linenr_t save_sourcing_lnum;
- char_u *p;
- char_u *fname_exp;
- int retval = FAIL;
- #ifdef WANT_EVAL
- void *save_funccalp;
- #endif
- #ifdef RISCOS
- fname_exp = mch_munge_fname(fname);
- #else
- fname_exp = expand_env_save(fname);
- #endif
- if (fname_exp == NULL)
- goto theend;
- #ifdef macintosh
- slash_n_colon_adjust(fname_exp);
- #endif
- cookie.fp = fopen((char *)fname_exp, READBIN);
- if (cookie.fp == NULL && check_other)
- {
- /*
- * Try again, replacing file name ".vimrc" by "_vimrc" or vice versa,
- * and ".exrc" by "_exrc" or vice versa.
- */
- p = gettail(fname_exp);
- if ((*p == '.' || *p == '_') &&
- (STRICMP(p + 1, "vimrc") == 0 ||
- STRICMP(p + 1, "gvimrc") == 0 ||
- STRICMP(p + 1, "exrc") == 0))
- {
- if (*p == '_')
- *p = '.';
- else
- *p = '_';
- cookie.fp = fopen((char *)fname_exp, READBIN);
- }
- }
- if (cookie.fp == NULL)
- {
- if (p_verbose > 0)
- smsg((char_u *)"could not source "%s"", fname);
- goto theend;
- }
- /*
- * The file exists.
- * - In verbose mode, give a message.
- * - For a vimrc file, may want to set 'compatible', call vimrc_found().
- */
- if (p_verbose > 0)
- smsg((char_u *)"sourcing "%s"", fname);
- if (is_vimrc)
- vimrc_found();
- #ifdef USE_CRNL
- /* If no automatic file format: Set default to CR-NL. */
- if (*p_ffs == NUL)
- cookie.fileformat = EOL_DOS;
- else
- cookie.fileformat = EOL_UNKNOWN;
- cookie.error = FALSE;
- #endif
- /*
- * Keep the sourcing name, for recursive calls.
- */
- save_sourcing_name = sourcing_name;
- save_sourcing_lnum = sourcing_lnum;
- sourcing_name = fname_exp;
- sourcing_lnum = 0;
- #ifdef WANT_EVAL
- /* Don't use local function variables, if called from a function */
- save_funccalp = save_funccal();
- #endif
- /*
- * Call do_cmdline, which will call getsourceline() to get the lines.
- */
- do_cmdline(NULL, getsourceline, (void *)&cookie,
- DOCMD_VERBOSE|DOCMD_NOWAIT|DOCMD_REPEAT);
- retval = OK;
- fclose(cookie.fp);
- if (got_int)
- emsg(e_interr);
- sourcing_name = save_sourcing_name;
- sourcing_lnum = save_sourcing_lnum;
- #ifdef WANT_EVAL
- restore_funccal(save_funccalp);
- #endif
- theend:
- vim_free(fname_exp);
- return retval;
- }
- /*
- * Get one full line from a sourced file.
- * Called by do_source() and do_cmdline().
- *
- * Return a pointer to the line in allocated memory.
- * Return NULL for end-of-file or some error.
- */
- /* ARGSUSED */
- char_u *
- getsourceline(c, cookie, indent)
- int c; /* not used */
- void *cookie;
- int indent; /* not used */
- {
- struct source_cookie *sp = (struct source_cookie *)cookie;
- struct growarray ga;
- int len;
- char_u *buf;
- #ifdef USE_CRNL
- int has_cr; /* CR-LF found */
- #endif
- int have_read = FALSE;
- /* use a growarray to store the sourced line */
- ga_init2(&ga, 1, 200);
- /*
- * Loop until there is a finished line (or end-of-file).
- */
- sourcing_lnum++;
- for (;;)
- {
- /* make room to read at least 80 (more) characters */
- if (ga_grow(&ga, 80) == FAIL)
- break;
- buf = (char_u *)ga.ga_data;
- if (fgets((char *)buf + ga.ga_len, ga.ga_room, sp->fp) == NULL
- || got_int)
- break;
- len = STRLEN(buf);
- #ifdef USE_CRNL
- /* Ignore a trailing CTRL-Z, when in Dos mode. Only recognize the
- * CTRL-Z by its own, or after a NL. */
- if ( (len == 1 || (len >= 2 && buf[len - 2] == 'n'))
- && sp->fileformat == EOL_DOS
- && buf[len - 1] == Ctrl('Z'))
- {
- buf[len - 1] = NUL;
- break;
- }
- #endif
- have_read = TRUE;
- ga.ga_room -= len - ga.ga_len;
- ga.ga_len = len;
- /* If the line was longer than the buffer, read more. */
- if (ga.ga_room == 1 && buf[len - 1] != 'n')
- continue;
- if (len >= 1 && buf[len - 1] == 'n') /* remove trailing NL */
- {
- #ifdef USE_CRNL
- has_cr = (len >= 2 && buf[len - 2] == 'r');
- if (sp->fileformat == EOL_UNKNOWN)
- {
- if (has_cr)
- sp->fileformat = EOL_DOS;
- else
- sp->fileformat = EOL_UNIX;
- }
- if (sp->fileformat == EOL_DOS)
- {
- if (has_cr) /* replace trailing CR */
- {
- buf[len - 2] = 'n';
- --len;
- --ga.ga_len;
- ++ga.ga_room;
- }
- else /* lines like ":map xx yy^M" will have failed */
- {
- if (!sp->error)
- EMSG("Warning: Wrong line separator, ^M may be missing");
- sp->error = TRUE;
- sp->fileformat = EOL_UNIX;
- }
- }
- #endif
- /* The 'n' is escaped if there is an odd number of ^V's just
- * before it, first set "c" just before the 'V's and then check
- * len&c parities (is faster than ((len-c)%2 == 0)) -- Acevedo */
- for (c = len - 2; c >= 0 && buf[c] == Ctrl('V'); c--)
- ;
- if ((len & 1) != (c & 1)) /* escaped NL, read more */
- {
- sourcing_lnum++;
- continue;
- }
- buf[len - 1] = NUL; /* remove the NL */
- }
- /*
- * Check for ^C here now and then, so recursive :so can be broken.
- */
- line_breakcheck();
- break;
- }
- if (have_read)
- return (char_u *)ga.ga_data;
- vim_free(ga.ga_data);
- return NULL;
- }
- /*
- * Function given to ExpandGeneric() to obtain the list of command names.
- */
- char_u *
- get_command_name(idx)
- int idx;
- {
- #ifdef USER_COMMANDS
- if (idx >= (int)CMD_SIZE)
- {
- int i = idx - (int)CMD_SIZE;
- if (i >= ucmds.ga_len)
- return NULL;
- return USER_CMD(i)->uc_name;
- }
- #else
- if (idx >= (int)CMD_SIZE)
- return NULL;
- #endif
- return cmdnames[idx].cmd_name;
- }
- /*
- * Call this function if we thought we were going to exit, but we won't
- * (because of an error). May need to restore the terminal mode.
- */
- void
- not_exiting()
- {
- exiting = FALSE;
- settmode(TMODE_RAW);
- }
- /*
- * ":quit": quit current window, quit Vim if closed the last window.
- */
- static void
- do_quit(eap)
- EXARG *eap;
- {
- /*
- * If there are more files or windows we won't exit.
- */
- if (check_more(FALSE, eap->forceit) == OK && only_one_window())
- exiting = TRUE;
- if ((!p_hid && check_changed(curbuf, FALSE, FALSE, eap->forceit, FALSE))
- || check_more(TRUE, eap->forceit) == FAIL
- || (only_one_window() && check_changed_any(eap->forceit)))
- {
- not_exiting();
- }
- else
- {
- if (only_one_window()) /* quit last window */
- getout(0);
- #ifdef USE_GUI
- need_mouse_correct = TRUE;
- #endif
- close_window(curwin, !p_hid || eap->forceit); /* may free buffer */
- }
- }
- /*
- * ":qall": try to quit all windows
- */
- static void
- do_quit_all(forceit)
- int forceit;
- {
- exiting = TRUE;
- if (forceit || !check_changed_any(FALSE))
- getout(0);
- not_exiting();
- }
- /*
- * ":close": close current window, unless it is the last one
- */
- static void
- do_close(eap)
- EXARG *eap;
- {
- int need_hide;
- need_hide = (buf_changed(curbuf) && curbuf->b_nwindows <= 1);
- if (need_hide && !p_hid && !eap->forceit)
- {
- #if defined(GUI_DIALOG) || defined(CON_DIALOG)
- if (p_confirm || confirm)
- {
- dialog_changed(curbuf, FALSE);
- if (buf_changed(curbuf))
- return;
- }
- else
- #endif
- {
- emsg(e_nowrtmsg);
- return;
- }
- }
- #ifdef USE_GUI
- need_mouse_correct = TRUE;
- #endif
- close_window(curwin, !need_hide); /* may free buffer */
- }
- /*
- * ":stop" and ":suspend": Suspend Vim.
- */
- static void
- do_suspend(forceit)
- int forceit;
- {
- /*
- * Disallow suspending for "rvim".
- */
- if (!check_restricted()
- #ifdef WIN32
- /*
- * Check if external commands are allowed now.
- */
- && can_end_termcap_mode(TRUE)
- #endif
- )
- {
- if (!forceit)
- autowrite_all();
- windgoto((int)Rows - 1, 0);
- out_char('n');
- out_flush();
- stoptermcap();
- mch_restore_title(3); /* restore window titles */
- ui_suspend(); /* call machine specific function */
- maketitle();
- starttermcap();
- scroll_start(); /* scroll screen before redrawing */
- must_redraw = CLEAR;
- set_winsize(0, 0, FALSE); /* May have resized window */
- }
- }
- /*
- * ":exit", ":xit" and ":wq": Write file and exit Vim.
- */
- static void
- do_exit(eap)
- EXARG *eap;
- {
- /*
- * if more files or windows we won't exit
- */
- if (check_more(FALSE, eap->forceit) == OK && only_one_window())
- exiting = TRUE;
- if ( ((eap->cmdidx == CMD_wq
- || curbuf_changed())
- && do_write(eap) == FAIL)
- || check_more(TRUE, eap->forceit) == FAIL
- || (only_one_window() && check_changed_any(eap->forceit)))
- {
- not_exiting();
- }
- else
- {
- if (only_one_window()) /* quit last window, exit Vim */
- getout(0);
- #ifdef USE_GUI
- need_mouse_correct = TRUE;
- #endif
- close_window(curwin, !p_hid); /* quit current window, may free buffer */
- }
- }
- /*
- * ":wall", ":wqall" and ":xall": Write all changed files (and exit).
- */
- static void
- do_wqall(eap)
- EXARG *eap;
- {
- BUF *buf;
- int error = 0;
- for (buf = firstbuf; buf != NULL; buf = buf->b_next)
- {
- if (buf_changed(buf))
- {
- if (buf->b_ffname == NULL)
- {
- emsg(e_noname);
- ++error;
- }
- else if (!eap->forceit && buf->b_p_ro)
- {
- EMSG2(""%s" is readonly, use ! to write anyway",
- buf->b_fname);
- ++error;
- }
- else
- {
- 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 (!error)
- getout(0); /* exit Vim */
- not_exiting();
- }
- }
- static void
- do_print(eap)
- EXARG *eap;
- {
- for ( ;!got_int; ui_breakcheck())
- {
- print_line(eap->line1,
- (eap->cmdidx == CMD_number || eap->cmdidx == CMD_pound));
- if (++eap->line1 > eap->line2)
- break;
- out_flush(); /* show one line at a time */
- }
- setpcmark();
- /* put cursor at last line */
- curwin->w_cursor.lnum = eap->line2;
- beginline(BL_SOL | BL_FIX);
- ex_no_reprint = TRUE;
- }
- /*
- * Edit file "argn" from the arguments.
- */
- static void
- do_argfile(eap, argn)
- EXARG *eap;
- int argn;
- {
- int other;
- char_u *p;
- char_u *ffname;
- BUF *buf;
- if (argn < 0 || argn >= arg_file_count)
- {
- if (arg_file_count <= 1)
- EMSG("There is only one file to edit");
- else if (argn < 0)
- EMSG("Cannot go before first file");
- else
- EMSG("Cannot go beyond last file");
- }
- else
- {
- setpcmark();
- #ifdef USE_GUI
- need_mouse_correct = TRUE;
- #endif
- if (*eap->cmd == 's') /* split window first */
- {
- if (win_split(0, FALSE, FALSE) == FAIL)
- return;
- }
- else
- {
- /*
- * if 'hidden' set, only check for changed file when re-editing
- * the same buffer
- */
- other = TRUE;
- if (p_hid)
- {
- p = fix_fname(arg_files[argn]);
- other = otherfile(p);
- vim_free(p);
- }
- if ((!p_hid || !other)
- && check_changed(curbuf, TRUE, !other, eap->forceit, FALSE))
- return;
- }
- curwin->w_arg_idx = argn;
- if (argn == arg_file_count - 1)
- arg_had_last = TRUE;
- /*
- * If no line number given, use the last known line number.
- */
- if (eap->do_ecmd_lnum == 0)
- {
- ffname = fix_fname(arg_files[curwin->w_arg_idx]);
- if (ffname != NULL)
- {
- buf = buflist_findname(ffname);
- if (buf != NULL)
- eap->do_ecmd_lnum = buflist_findlnum(buf);
- vim_free(ffname);
- }
- }
- (void)do_ecmd(0, arg_files[curwin->w_arg_idx],
- NULL, eap->do_ecmd_cmd, eap->do_ecmd_lnum,
- (p_hid ? ECMD_HIDE : 0) +
- (eap->forceit ? ECMD_FORCEIT : 0));
- }
- }
- /*
- * Do ":next" command, and commands that behave like it.
- */
- static void
- do_next(eap)
- EXARG *eap;
- {
- int i;
- /*
- * check for changed buffer now, if this fails the argument list is not
- * redefined.
- */
- if ( p_hid
- || eap->cmdidx == CMD_snext
- || !check_changed(curbuf, TRUE, FALSE, eap->forceit, FALSE))
- {
- if (*eap->arg != NUL) /* redefine file list */
- {
- if (do_arglist(eap->arg) == FAIL)
- return;
- i = 0;
- }
- else
- i = curwin->w_arg_idx + (int)eap->line2;
- do_argfile(eap, i);
- }
- }
- #if defined(USE_GUI_WIN32) || defined(USE_GUI_BEOS) || defined(PROTO) || defined(macintosh)
- /*
- * Handle a file drop. The code is here because a drop is *nearly* like an
- * :args command, but not quite (we have a list of exact filenames, so we
- * don't want to (a) parse a command line, or (b) expand wildcards. So the
- * code is very similar to :args and hence needs access to a lot of the static
- * functions in this file.
- *
- * Arguments:
- * FILEC => the number of files dropped
- * FILEV => the list of files dropped
- *
- * The list should be allocated using vim_alloc(), as should each item in the
- * list. This function takes over responsibility for freeing the list.
- *
- * XXX The list is made into the arg_files list. This is freed using
- * FreeWild(), which does a series of vim_free() calls, unless the two defines
- * __EMX__ and __ALWAYS_HAS_TRAILING_NUL_POINTER are set. In this case, a
- * routine _fnexplodefree() is used. This may cause problems, but as the drop
- * file functionality is (currently) Win32-specific (where these defines are
- * not set), this is not presently a problem.
- */
- void
- handle_drop(filec, filev)
- int filec;
- char_u **filev;
- {
- EXARG ea;
- int i;
- int split = FALSE;
- /* Check whether the current buffer is changed. If so, we will need
- * to split the current window or data could be lost.
- * We don't need to check if the 'hidden' option is set, as in this
- * case the buffer won't be lost.
- */
- if (!p_hid)
- {
- int old_emsg = emsg_off;
- emsg_off = TRUE;
- split = check_changed(curbuf, TRUE, FALSE, FALSE, FALSE);
- emsg_off = old_emsg;
- }
- /*
- * Set up the new argument list.
- * This code is copied from the tail end of do_arglist()
- */
- FreeWild(arg_file_count, arg_files);
- arg_file_count = filec;
- arg_files = filev;
- arg_had_last = FALSE;
- for (i = 0; i < arg_file_count; ++i)
- if (arg_files[i] != NULL)
- (void)buflist_add(arg_files[i]);
- /*
- * Move to the first file.
- */
- /* Fake up a minimal "[s]next" command for do_argfile() */
- ea.cmd = (char_u *)(split ? "snext" : "next");
- ea.forceit = FALSE;
- ea.do_ecmd_cmd = NULL;
- ea.do_ecmd_lnum = 0;
- do_argfile(&ea, 0);
- }
- #endif
- /*
- * Handle ":recover" command.
- */
- static void
- do_recover(eap)
- EXARG *eap;
- {
- recoverymode = TRUE;
- if (!check_changed(curbuf, FALSE, TRUE, eap->forceit, FALSE)
- && (*eap->arg == NUL || setfname(eap->arg, NULL, TRUE) == OK))
- ml_recover();
- recoverymode = FALSE;
- }
- /*
- * Handle ":args" command.
- */
- static void
- do_args(eap)
- EXARG *eap;
- {
- int i;
- /* ":args file": handle like :next */
- if (!ends_excmd(*eap->arg))
- do_next(eap);
- else
- {
- if (arg_file_count == 0) /* no file name list */
- {
- if (check_fname() == OK) /* check for no file name */
- smsg((char_u *)"[%s]", curbuf->b_ffname);
- }
- else
- {
- /*
- * Overwrite the command, in most cases there is no scrolling
- * required and no wait_return().
- */
- gotocmdline(TRUE);
- for (i = 0; i < arg_file_count; ++i)
- {
- if (i == curwin->w_arg_idx)
- msg_putchar('[');
- msg_outtrans(arg_files[i]);
- if (i == curwin->w_arg_idx)
- msg_putchar(']');
- msg_putchar(' ');
- }
- }
- }
- }
- /*
- * Handle ":wnext", ":wNext" and ":wprevious" commands.
- */
- static void
- do_wnext(eap)
- EXARG *eap;
- {
- int i;
- if (eap->cmd[1] == 'n')
- i = curwin->w_arg_idx + (int)eap->line2;
- else
- i = curwin->w_arg_idx - (int)eap->line2;
- eap->line1 = 1;
- eap->line2 = curbuf->b_ml.ml_line_count;
- if (do_write(eap) != FAIL)
- do_argfile(eap, i);
- }
- /*
- * :sview [+command] file split window with new file, read-only
- * :split [[+command] file] split window with current or new file
- * :new [[+command] file] split window with no or new file
- */
- static void
- do_splitview(eap)
- EXARG *eap;
- {
- WIN *old_curwin;
- #ifdef USE_BROWSE
- char_u *browseFile = NULL;
- #endif
- old_curwin = curwin;
- #ifdef USE_GUI
- need_mouse_correct = TRUE;
- #endif
- #ifdef USE_BROWSE
- if (browse && eap->cmdidx != CMD_new)
- {
- browseFile = do_browse(FALSE, (char_u *)"Edit File in new window",
- NULL, NULL, eap->arg, NULL, curbuf);
- if (browseFile == NULL)
- goto theend;
- eap->arg = browseFile;
- }
- #endif
- if (win_split(eap->addr_count ? (int)eap->line2 : 0, FALSE, FALSE) != FAIL)
- do_exedit(eap, old_curwin);
- #ifdef USE_BROWSE
- theend:
- vim_free(browseFile);
- #endif
- }
- /*
- * Handle ":resize" command.
- * set, increment or decrement current window height
- */
- static void
- do_resize(eap)
- EXARG *eap;
- {
- int n;
- #ifdef USE_GUI
- need_mouse_correct = TRUE;
- #endif
- n = atol((char *)eap->arg);
- if (*eap->arg == '-' || *eap->arg == '+')
- n += curwin->w_height;
- else if (n == 0) /* default is very high */
- n = 9999;
- win_setheight((int)n);
- }
- static void
- do_exedit(eap, old_curwin)
- EXARG *eap;
- WIN *old_curwin;
- {
- int n;
- /*
- * ":vi" command ends Ex mode.
- */
- if (exmode_active && (eap->cmdidx == CMD_visual || eap->cmdidx == CMD_view))
- {
- exmode_active = FALSE;
- if (*eap->arg == NUL)
- return;
- }
- if ((eap->cmdidx == CMD_new) && *eap->arg == NUL)
- {
- setpcmark();
- (void)do_ecmd(0, NULL, NULL, eap->do_ecmd_cmd, (linenr_t)1,
- ECMD_HIDE + (eap->forceit ? ECMD_FORCEIT : 0));
- }
- else if (eap->cmdidx != CMD_split || *eap->arg != NUL
- #ifdef USE_BROWSE
- || browse
- #endif
- )
- {
- n = readonlymode;
- if (eap->cmdidx == CMD_view || eap->cmdidx == CMD_sview)
- readonlymode = TRUE;
- setpcmark();
- (void)do_ecmd(0, eap->arg, NULL, eap->do_ecmd_cmd, eap->do_ecmd_lnum,
- (p_hid ? ECMD_HIDE : 0) +
- (eap->forceit ? ECMD_FORCEIT : 0) +
- (eap->cmdidx == CMD_badd ? ECMD_ADDBUF : 0 ));
- readonlymode = n;
- }
- else
- {
- if (eap->do_ecmd_cmd != NULL)
- do_cmdline(eap->do_ecmd_cmd, NULL, NULL, DOCMD_VERBOSE);
- update_screen(NOT_VALID);
- }
- /*
- * if ":split file" worked, set alternate file name in old window to new
- * file
- */
- if ( (eap->cmdidx == CMD_new
- || eap->cmdidx == CMD_split)
- && *eap->arg != NUL
- && curwin != old_curwin
- && win_valid(old_curwin)
- && old_curwin->w_buffer != curbuf)
- old_curwin->w_alt_fnum = curbuf->b_fnum;
- ex_no_reprint = TRUE;
- }
- #ifdef USE_GUI
- /*
- * Handle ":gui" or ":gvim" command.
- */
- static void
- do_gui(eap)
- EXARG *eap;
- {
- /*
- * Check for "-f" argument: foreground, don't fork.
- */
- if (eap->arg[0] == '-' && eap->arg[1] == 'f' &&
- (eap->arg[2] == NUL || vim_iswhite(eap->arg[2])))
- {
- gui.dofork = FALSE;
- eap->arg = skipwhite(eap->arg + 2);
- }
- else
- gui.dofork = TRUE;
- if (!gui.in_use)
- {
- /* Clear the command. Needed for when forking+exiting, to avoid part
- * of the argument ending up after the shell prompt. */
- msg_clr_eos();
- gui_start();
- }
- if (!ends_excmd(*eap->arg))
- do_next(eap);
- }
- #endif
- static void
- do_swapname()
- {
- if (curbuf->b_ml.ml_mfp == NULL || curbuf->b_ml.ml_mfp->mf_fname == NULL)
- MSG("No swap file");
- else
- msg(curbuf->b_ml.ml_mfp->mf_fname);
- }
- static void
- do_read(eap)
- EXARG *eap;
- {
- int i;
- if (eap->usefilter) /* :r!cmd */
- do_bang(1, eap->line1, eap->line2, FALSE, eap->arg, FALSE, TRUE);
- else
- {
- if (u_save(eap->line2, (linenr_t)(eap->line2 + 1)) == FAIL)
- return;
- #ifdef USE_BROWSE
- if (browse)
- {
- char_u *browseFile;
- browseFile = do_browse(FALSE, (char_u *)"Append File", NULL,
- NULL, eap->arg, NULL, curbuf);
- if (browseFile != NULL)
- {
- i = readfile(browseFile, NULL,
- eap->line2, (linenr_t)0, (linenr_t)MAXLNUM, 0);
- vim_free(browseFile);
- }
- else
- i = OK;
- }
- else
- #endif
- if (*eap->arg == NUL)
- {
- if (check_fname() == FAIL) /* check for no file name */
- return;
- i = readfile(curbuf->b_ffname, curbuf->b_fname,
- eap->line2, (linenr_t)0, (linenr_t)MAXLNUM, 0);
- }
- else
- {
- if (vim_strchr(p_cpo, CPO_ALTREAD) != NULL)
- setaltfname(eap->arg, eap->arg, (linenr_t)1);
- i = readfile(eap->arg, NULL,
- eap->line2, (linenr_t)0, (linenr_t)MAXLNUM, 0);
- }
- if (i == FAIL)
- emsg2(e_notopen, eap->arg);
- else
- update_screen(NOT_VALID);
- }
- }
- static void
- do_cd(eap)
- EXARG *eap;
- {
- #ifdef UNIX
- /*
- * for UNIX ":cd" means: go to home directory
- */
- if (*eap->arg == NUL) /* use NameBuff for home directory name */
- {
- expand_env((char_u *)"$HOME", NameBuff, MAXPATHL);
- eap->arg = NameBuff;
- }
- #endif
- if (*eap->arg == NUL)
- do_pwd();
- else
- {
- if (mch_chdir((char *)eap->arg))
- emsg(e_failed);
- else
- shorten_fnames();
- }
- }
- static void
- do_pwd()
- {
- if (mch_dirname(NameBuff, MAXPATHL) == OK)
- msg(NameBuff);
- else
- emsg(e_unknown);
- }
- static void
- do_sleep(eap)
- EXARG *eap;
- {
- int n;
- if (cursor_valid())
- {
- n = curwin->w_winpos + curwin->w_wrow - msg_scrolled;
- if (n >= 0)
- windgoto((int)n, curwin->w_wcol);
- }
- cursor_on();
- out_flush();
- ui_delay(eap->line2 * (*eap->arg == 'm' ? 1L : 1000L), TRUE);
- }
- static void
- do_exmap(eap, isabbrev)
- EXARG *eap;
- int isabbrev;
- {
- int mode;
- char_u *cmdp;
- cmdp = eap->cmd;
- mode = get_map_mode(&cmdp, eap->forceit || isabbrev);
- switch (do_map((*cmdp == 'n') ? 2 : (*cmdp == 'u'),
- eap->arg, mode, isabbrev))
- {
- case 1: emsg(e_invarg);
- break;
- case 2: emsg(e_nomap);
- break;
- case 3: emsg(e_ambmap);
- break;
- }
- }
- /*
- * ":winsize" command (obsolete).
- */
- static void
- do_winsize(arg)
- char_u *arg;
- {
- int w, h;
- w = getdigits(&arg);
- arg = skipwhite(arg);
- h = getdigits(&arg);
- set_winsize(w, h, TRUE);
- }
- /*
- * Handle command that work like operators: ":delete", ":yank", ":>" and ":<".
- */
- static void
- do_exops(eap)
- EXARG *eap;
- {
- OPARG oa;
- clear_oparg(&oa);
- oa.regname = eap->regname;
- oa.start.lnum = eap->line1;
- oa.end.lnum = eap->line2;
- oa.line_count = eap->line2 - eap->line1 + 1;
- oa.motion_type = MLINE;
- if (eap->cmdidx != CMD_yank) /* position cursor for undo */
- {
- setpcmark();
- curwin->w_cursor.lnum = eap->line1;
- beginline(BL_SOL | BL_FIX);
- }
- switch (eap->cmdidx)
- {
- case CMD_delete:
- oa.op_type = OP_DELETE;
- op_delete(&oa);
- break;
- case CMD_yank:
- oa.op_type = OP_YANK;
- (void)op_yank(&oa, FALSE, TRUE);
- break;
- default: /* CMD_rshift or CMD_lshift */
- if ((eap->cmdidx == CMD_rshift)
- #ifdef RIGHTLEFT
- ^ curwin->w_p_rl
- #endif
- )
- oa.op_type = OP_RSHIFT;
- else
- oa.op_type = OP_LSHIFT;
- op_shift(&oa, FALSE, eap->amount);
- break;
- }
- }
- /*
- * Handle ":copy" and ":move".
- */
- static void
- do_copymove(eap)
- EXARG *eap;
- {
- long n;
- n = get_address(&eap->arg, FALSE);
- if (eap->arg == NULL) /* error detected */
- {
- eap->nextcmd = NULL;
- return;
- }
- /*
- * move or copy lines from 'eap->line1'-'eap->line2' to below line 'n'
- */
- if (n == MAXLNUM || n < 0 || n > curbuf->b_ml.ml_line_count)
- {
- emsg(e_invaddr);
- return;
- }
- if (eap->cmdidx == CMD_move)
- {
- if (do_move(eap->line1, eap->line2, n) == FAIL)
- return;
- }
- else
- do_copy(eap->line1, eap->line2, n);
- u_clearline();
- beginline(BL_SOL | BL_FIX);
- update_screen(NOT_VALID);
- }
- /*
- * Handle ":join" command.
- */
- static void
- do_exjoin(eap)
- EXARG *eap;
- {
- curwin->w_cursor.lnum = eap->line1;
- if (eap->line1 == eap->line2)
- {
- if (eap->addr_count >= 2) /* :2,2join does nothing */
- return;
- if (eap->line2 == curbuf->b_ml.ml_line_count)
- {
- beep_flush();
- return;
- }
- ++eap->line2;
- }
- do_do_join(eap->line2 - eap->line1 + 1, !eap->forceit, FALSE);
- beginline(BL_WHITE | BL_FIX);
- }
- /*
- * Handle ":@" or ":*" command, execute from register.
- */
- static void
- do_exat(eap)
- EXARG *eap;
- {
- int c;
- curwin->w_cursor.lnum = eap->line2;
- #ifdef USE_GUI_WIN32
- dont_scroll = TRUE; /* disallow scrolling here */
- #endif
- /* get the register name. No name means to use the previous one */
- c = *eap->arg;
- if (c == NUL || c == '*')
- c = '@';
- /* put the register in mapbuf */
- if (do_execreg(c, TRUE, vim_strchr(p_cpo, CPO_EXECBUF) != NULL) == FAIL)
- beep_flush();
- else
- {
- /* execute from the mapbuf */
- while (vpeekc() == ':')
- {
- (void)vgetc();
- (void)do_cmdline(NULL, getexline, NULL, DOCMD_NOWAIT|DOCMD_VERBOSE);
- }
- }
- }
- /*
- * Handle ":redir" command, start/stop redirection.
- */
- static void
- do_redir(eap)
- EXARG *eap;
- {
- char *mode;
- #ifdef USE_BROWSE
- char_u *browseFile = NULL;
- #endif
- if (STRICMP(eap->arg, "END") == 0)
- close_redir();
- else
- {
- if (*eap->arg == '>')
- {
- ++eap->arg;
- if (*eap->arg == '>')
- {
- ++eap->arg;
- mode = "a";
- }
- else
- mode = "w";
- eap->arg = skipwhite(eap->arg);
- close_redir();
- #ifdef USE_BROWSE
- if (browse)
- {
- browseFile = do_browse(TRUE, (char_u *)"Save Redirection",
- NULL, NULL, eap->arg, BROWSE_FILTER_ALL_FILES, curbuf);
- if (browseFile == NULL)
- return; /* operation cancelled */
- eap->arg = browseFile;
- eap->forceit = TRUE; /* since dialog already asked */
- }
- #endif /* USE_BROWSE */
- redir_fd = open_exfile(eap, mode);
- #ifdef USE_BROWSE
- vim_free(browseFile);
- #endif
- }
- /* TODO: redirect to a buffer */
- /* TODO: redirect to an internal variable */
- else
- EMSG(e_invarg);
- }
- }
- static void
- close_redir()
- {
- if (redir_fd != NULL)
- {
- fclose(redir_fd);
- redir_fd = NULL;
- }
- }
- /*
- * Handle ":mkexrc", ":mkvimrc" and ":mksession" commands.
- */
- static void
- do_mkrc(eap, defname)
- EXARG *eap;
- char_u *defname; /* default file name */
- {
- FILE *fd;
- int failed;
- #ifdef USE_BROWSE
- char_u *browseFile = NULL;
- #endif
- if (*eap->arg == NUL)
- eap->arg = defname;
- #ifdef USE_BROWSE
- if (browse)
- {
- browseFile = do_browse(TRUE,
- STRCMP(defname, SESSION_FILE) == 0 ? (char_u *)"Save Session"
- : (char_u *)"Save Setup",
- NULL, (char_u *)"vim", eap->arg, BROWSE_FILTER_MACROS, curbuf);
- if (browseFile == NULL)
- return; /* operation cancelled */
- eap->arg = browseFile;
- eap->forceit = TRUE; /* since dialog already asked */
- }
- #endif /* USE_BROWSE */
- fd = open_exfile(eap, WRITEBIN);
- if (fd != NULL)
- {
- /* Write the version command for :mkvimrc and :mksession */
- if (eap->cmdidx == CMD_mkvimrc || eap->cmdidx == CMD_mksession)
- {
- fprintf(fd, "version 5.0");
- (void)put_eol(fd);
- }
- /* Write setting 'compatible' first, because it has side effects */
- if (p_cp)
- fprintf(fd, "set compatible");
- else
- fprintf(fd, "set nocompatible");
- (void)put_eol(fd);
- if ((eap->cmdidx != CMD_mksession)
- || (vim_strchr(p_sessopt, 'o') != NULL)) /* "options" */
- failed = (makemap(fd) == FAIL || makeset(fd) == FAIL);
- else
- failed = FALSE;
- if (eap->cmdidx == CMD_mksession && !failed)
- {
- /* save current dir*/
- char_u dirnow[MAXPATHL];
- if (mch_dirname(dirnow, MAXPATHL) == FAIL)
- *dirnow = NUL;
- /*
- * Change to session file's dir.
- */
- (void)vim_chdirfile(eap->arg);
- shorten_fnames();
- failed |= (makeopens(fd) == FAIL);
- /* restore original dir */
- if (*dirnow)
- {
- (void)mch_chdir((char *)dirnow);
- shorten_fnames();
- }
- }
- failed |= fclose(fd);
- if (failed)
- emsg(e_write);
- #ifdef WANT_EVAL
- else if (eap->cmdidx == CMD_mksession)
- {
- /* successful session write - set this_session var */
- char_u tbuf[MAXPATHL];
- if (mch_FullName(eap->arg, tbuf, MAXPATHL, FALSE) == OK)
- set_internal_string_var((char_u *)"this_session", tbuf);
- }
- #endif
- }
- #ifdef USE_BROWSE
- vim_free(browseFile);
- #endif
- }
- /*
- * Open a file for writing for an Ex command, with some checks.
- * Return file descriptor, or NULL on failure.
- */
- static FILE *
- open_exfile(eap, mode)
- EXARG *eap;
- char *mode; /* "w" for create new file or "a" for append */
- {
- FILE *fd;
- #ifdef UNIX
- /* with Unix it is possible to open a directory */
- if (mch_isdir(eap->arg))
- {
- EMSG2(""%s" is a directory", eap->arg);
- return NULL;
- }
- #endif
- if (!eap->forceit && *mode != 'a' && vim_fexists(eap->arg))
- {
- EMSG2(""%s" exists (use ! to override)", eap->arg);
- return NULL;
- }
- if ((fd = fopen((char *)eap->arg, mode)) == NULL)
- EMSG2("Cannot open "%s" for writing", eap->arg);
- return fd;
- }
- /*
- * Handle ":mark" or ":k" command.
- */
- static void
- do_setmark(eap)
- EXARG *eap;
- {
- FPOS pos;
- pos = curwin->w_cursor; /* save curwin->w_cursor */
- curwin->w_cursor.lnum = eap->line2;
- beginline(BL_WHITE | BL_FIX);
- (void)setmark(*eap->arg); /* set mark */
- curwin->w_cursor = pos; /* restore curwin->w_cursor */
- }
- #ifdef EX_EXTRA
- /*
- * Handle ":normal[!] {commands}" - execute normal mode commands
- * Often used for ":autocmd".
- */
- static void
- do_normal(eap)
- EXARG *eap;
- {
- OPARG oa;
- int len;
- int save_msg_scroll = msg_scroll;
- int save_restart_edit = restart_edit;
- int save_msg_didout = msg_didout;
- static int depth = 0;
- if (depth >= p_mmd)
- {
- EMSG("Recursive use of :normal too deep");
- return;
- }
- ++depth;
- msg_scroll = FALSE; /* no msg scrolling in Normal mode */
- restart_edit = 0; /* don't go to Insert mode */
- /*
- * Repeat the :normal command for each line in the range. When no range
- * given, execute it just once, without positioning the cursor first.
- */
- do
- {
- clear_oparg(&oa);
- if (eap->addr_count != 0)
- {
- curwin->w_cursor.lnum = eap->line1++;
- curwin->w_cursor.col = 0;
- }
- /*
- * Stuff the argument into the typeahead buffer.
- * Execute normal_cmd() until there is no more
- * typeahead than there was before this command.
- */
- len = typelen;
- ins_typebuf(eap->arg, eap->forceit ? -1 : 0, 0, TRUE);
- while ( (!stuff_empty()
- || (!typebuf_typed()
- && typelen > len))
- && !got_int)
- {
- adjust_cursor(); /* put cursor on valid line */
- /* Make sure w_topline and w_leftcol are correct. */
- update_topline();
- if (!curwin->w_p_wrap)
- validate_cursor();
- update_curswant();
- normal_cmd(&oa, FALSE); /* execute a Normal mode cmd */
- }
- }
- while (eap->addr_count > 0 && eap->line1 <= eap->line2 && !got_int);
- --depth;
- msg_scroll = save_msg_scroll;
- restart_edit = save_restart_edit;
- msg_didout |= save_msg_didout; /* don't reset msg_didout now */
- }
- #endif
- #ifdef FIND_IN_PATH
- static char_u *
- do_findpat(eap, action)
- EXARG *eap;
- int action;
- {
- int whole = TRUE;
- long n;
- char_u *p;
- char_u *errormsg = NULL;
- n = 1;
- if (isdigit(*eap->arg)) /* get count */
- {
- n = getdigits(&eap->arg);
- eap->arg = skipwhite(eap->arg);
- }
- if (*eap->arg == '/') /* Match regexp, not just whole words */
- {
- whole = FALSE;
- ++eap->arg;
- p = skip_regexp(eap->arg, '/', p_magic);
- if (*p)
- {
- *p++ = NUL;
- p = skipwhite(p);
- /* Check for trailing illegal characters */
- if (!ends_excmd(*p))
- errormsg = e_trailing;
- else
- eap->nextcmd = check_nextcmd(p);
- }
- }
- if (!eap->skip)
- find_pattern_in_path(eap->arg, 0, (int)STRLEN(eap->arg),
- whole, !eap->forceit,
- *eap->cmd == 'd' ? FIND_DEFINE : FIND_ANY,
- n, action, eap->line1, eap->line2);
- return errormsg;
- }
- #endif
- static void
- do_ex_tag(eap, dt)
- EXARG *eap;
- int dt;
- {
- do_tag((char_u *)"", dt, eap->addr_count ? (int)eap->line2
- : 1, eap->forceit, TRUE);
- }
- #ifdef WANT_EVAL
- static char_u *
- do_if(eap, cstack)
- EXARG *eap;
- struct condstack *cstack;
- {
- char_u *errormsg = NULL;
- int error;
- int skip;
- int result;
- if (cstack->cs_idx == CSTACK_LEN - 1)
- errormsg = (char_u *)":if nesting too deep";
- else
- {
- ++cstack->cs_idx;
- cstack->cs_flags[cstack->cs_idx] = 0;
- /*
- * Don't do something when there is a surrounding conditional and it
- * was not active.
- */
- skip = (cstack->cs_idx > 0
- && !(cstack->cs_flags[cstack->cs_idx - 1] & CSF_ACTIVE));
- if (skip)
- ++emsg_off;
- result = eval_to_bool(eap->arg, &error, &eap->nextcmd);
- if (skip)
- --emsg_off;
- if (!skip)
- {
- if (result)
- cstack->cs_flags[cstack->cs_idx] = CSF_ACTIVE | CSF_TRUE;
- if (error)
- --cstack->cs_idx;
- }
- }
- return errormsg;
- }
- /*
- * Handle ":else" and ":elseif" commands.
- */
- static char_u *
- do_else(eap, cstack)
- EXARG *eap;
- struct condstack *cstack;
- {
- char_u *errormsg = NULL;
- int error;
- int skip;
- int result;
- if (cstack->cs_idx < 0 || (cstack->cs_flags[cstack->cs_idx] & CSF_WHILE))
- {
- if (eap->cmdidx == CMD_else)
- errormsg = (char_u *)":else without :if";
- else
- errormsg = (char_u *)":elseif without :if";
- }
- else
- {
- /*
- * Don't do something when there is a surrounding conditional and it
- * was not active.
- */
- skip = (cstack->cs_idx > 0
- && !(cstack->cs_flags[cstack->cs_idx - 1] & CSF_ACTIVE));
- if (!skip)
- {
- /* if the ":if" was TRUE, reset active, otherwise set it */
- if (cstack->cs_flags[cstack->cs_idx] & CSF_TRUE)
- cstack->cs_flags[cstack->cs_idx] = CSF_TRUE;
- else
- cstack->cs_flags[cstack->cs_idx] = CSF_ACTIVE;
- }
- if (eap->cmdidx == CMD_elseif)
- {
- if (skip)
- ++emsg_off;
- result = eval_to_bool(eap->arg, &error, &eap->nextcmd);
- if (skip)
- --emsg_off;
- if (!skip && (cstack->cs_flags[cstack->cs_idx] & CSF_ACTIVE))
- {
- if (result)
- cstack->cs_flags[cstack->cs_idx] = CSF_ACTIVE | CSF_TRUE;
- else
- cstack->cs_flags[cstack->cs_idx] = 0;
- if (error)
- --cstack->cs_idx;
- }
- }
- }
- return errormsg;
- }
- /*
- * Handle ":while".
- */
- static char_u *
- do_while(eap, cstack)
- EXARG *eap;
- struct condstack *cstack;
- {
- char_u *errormsg = NULL;
- int error;
- int skip;
- int result;
- if (cstack->cs_idx == CSTACK_LEN - 1)
- errormsg = (char_u *)":while nesting too deep";
- else
- {
- /*
- * cs_had_while is set when we have jumped back from the matching
- * ":endwhile". When not set, need to init this cstack entry.
- */
- if (!cstack->cs_had_while)
- {
- ++cstack->cs_idx;
- ++cstack->cs_whilelevel;
- }
- cstack->cs_flags[cstack->cs_idx] = CSF_WHILE;
- /*
- * Don't do something when there is a surrounding conditional and it
- * was not active.
- */
- skip = (cstack->cs_idx > 0
- && !(cstack->cs_flags[cstack->cs_idx - 1] & CSF_ACTIVE));
- if (skip)
- ++emsg_off;
- result = eval_to_bool(eap->arg, &error, &eap->nextcmd);
- if (skip)
- --emsg_off;
- if (!skip)
- {
- if (result)
- cstack->cs_flags[cstack->cs_idx] |= CSF_ACTIVE | CSF_TRUE;
- if (error)
- --cstack->cs_idx;
- else
- /*
- * Set cs_had_while flag, so do_cmdline() will set the line
- * number in cs_line[].
- */
- cstack->cs_had_while = TRUE;
- }
- }
- return errormsg;
- }
- /*
- * Handle ":continue".
- */
- static char_u *
- do_continue(cstack)
- struct condstack *cstack;
- {
- char_u *errormsg = NULL;
- if (cstack->cs_whilelevel <= 0 || cstack->cs_idx < 0)
- errormsg = (char_u *)":continue without :while";
- else
- {
- /* Find the matching ":while". */
- while (cstack->cs_idx > 0
- && !(cstack->cs_flags[cstack->cs_idx] & CSF_WHILE))
- --cstack->cs_idx;
- /*
- * Set cs_had_continue, so do_cmdline() will jump back to the matching
- * ":while".
- */
- cstack->cs_had_continue = TRUE; /* let do_cmdline() handle it */
- }
- return errormsg;
- }
- /*
- * Handle ":break".
- */
- static char_u *
- do_break(cstack)
- struct condstack *cstack;
- {
- char_u *errormsg = NULL;
- int idx;
- if (cstack->cs_whilelevel <= 0 || cstack->cs_idx < 0)
- errormsg = (char_u *)":break without :while";
- else
- {
- /* Find the matching ":while". */
- for (idx = cstack->cs_idx; idx >= 0; --idx)
- {
- cstack->cs_flags[idx] &= ~CSF_ACTIVE;
- if (cstack->cs_flags[idx] & CSF_WHILE)
- break;
- }
- }
- return errormsg;
- }
- /*
- * Handle ":endwhile".
- */
- static char_u *
- do_endwhile(cstack)
- struct condstack *cstack;
- {
- char_u *errormsg = NULL;
- if (cstack->cs_whilelevel <= 0 || cstack->cs_idx < 0)
- errormsg = (char_u *)":endwhile without :while";
- else
- {
- if (!(cstack->cs_flags[cstack->cs_idx] & CSF_WHILE))
- {
- errormsg = (char_u *)":endwhile without :while";
- while (cstack->cs_idx > 0
- && !(cstack->cs_flags[cstack->cs_idx] & CSF_WHILE))
- --cstack->cs_idx;
- }
- /*
- * Set cs_had_endwhile, so do_cmdline() will jump back to the matching
- * ":while".
- */
- cstack->cs_had_endwhile = TRUE;
- }
- return errormsg;
- }
- /*
- * Return TRUE if the string "p" looks like a ":while" command.
- */
- static int
- has_while_cmd(p)
- char_u *p;
- {
- p = skipwhite(p);
- while (*p == ':')
- ++p;
- p = skipwhite(p);
- if (p[0] == 'w' && p[1] == 'h')
- return TRUE;
- return FALSE;
- }
- #endif /* WANT_EVAL */
- /*
- * Evaluate cmdline variables.
- *
- * change '%' to curbuf->b_ffname
- * '#' to curwin->w_altfile
- * '<cword>' to word under the cursor
- * '<cWORD>' to WORD under the cursor
- * '<cfile>' to path name under the cursor
- * '<sfile>" to sourced file name"
- * '<afile>' to file name for autocommand
- * '<abuf>' to buffer number for autocommand
- *
- * When an error is detected, "errormsg" is set to a non-NULL pointer (may be
- * "" for error without a message) and NULL is returned.
- * Returns an allocated string if a valid match was found.
- * Returns NULL if no match was found. "usedlen" then still contains the
- * number of characters to skip.
- */
- char_u *
- eval_vars(src, usedlen, lnump, errormsg, srcstart)
- char_u *src; /* pointer into commandline */
- int *usedlen; /* characters after src that are used */
- linenr_t *lnump; /* line number for :e command, or NULL */
- char_u **errormsg; /* error message, or NULL */
- char_u *srcstart; /* beginning of valid memory for src */
- {
- int i;
- char_u *s;
- char_u *result;
- char_u *resultbuf = NULL;
- int resultlen;
- BUF *buf;
- int valid = VALID_HEAD + VALID_PATH; /* assume valid result */
- int spec_idx;
- static char *(spec_str[]) =
- {
- "%",
- #define SPEC_PERC 0
- "#",
- #define SPEC_HASH 1
- "<cword>", /* cursor word */
- #define SPEC_CWORD 2
- "<cWORD>", /* cursor WORD */
- #define SPEC_CCWORD 3
- "<cfile>", /* cursor path name */
- #define SPEC_CFILE 4
- "<sfile>", /* ":so" file name */
- #define SPEC_SFILE 5
- #ifdef AUTOCMD
- "<afile>", /* autocommand file name */
- # define SPEC_AFILE 6
- "<abuf>" /* autocommand buffer number */
- # define SPEC_ABUF 7
- #endif
- };
- #define SPEC_COUNT (sizeof(spec_str) / sizeof(char *))
- #ifdef AUTOCMD
- char_u abuf_nr[30];
- #endif
- *errormsg = NULL;
- /*
- * Check if there is something to do.
- */
- for (spec_idx = 0; spec_idx < SPEC_COUNT; ++spec_idx)
- {
- *usedlen = strlen(spec_str[spec_idx]);
- if (STRNCMP(src, spec_str[spec_idx], *usedlen) == 0)
- break;
- }
- if (spec_idx == SPEC_COUNT) /* no match */
- {
- *usedlen = 1;
- return NULL;
- }
- /*
- * Skip when preceded with a backslash "%" and "#".
- * Note: In "\%" the % is also not recognized!
- */
- if ((src > srcstart) && (*(src - 1) == '\'))
- {
- *usedlen = 0;
- STRCPY(src - 1, src); /* remove backslash */
- return NULL;
- }
- /*
- * word or WORD under cursor
- */
- if (spec_idx == SPEC_CWORD || spec_idx == SPEC_CCWORD)
- {
- resultlen = find_ident_under_cursor(&result, spec_idx == SPEC_CWORD ?
- (FIND_IDENT|FIND_STRING) : FIND_STRING);
- if (resultlen == 0)
- {
- *errormsg = (char_u *)"";
- return NULL;
- }
- }
- /*
- * '#': Alternate file name
- * '%': Current file name
- * File name under the cursor
- * File name for autocommand
- * and following modifiers
- */
- else
- {
- switch (spec_idx)
- {
- case SPEC_PERC: /* '%': current file */
- if (curbuf->b_fname == NULL)
- {
- result = (char_u *)"";
- valid = 0; /* Must have ":p:h" to be valid */
- }
- else
- #ifdef RISCOS
- /* Always use the full path for RISC OS if possible. */
- result = curbuf->b_ffname;
- if (result == NULL)
- result = curbuf->b_fname;
- #else
- result = curbuf->b_fname;
- #endif
- break;
- case SPEC_HASH: /* '#' or "#99": alternate file */
- s = src + 1;
- i = (int)getdigits(&s);
- *usedlen = s - src; /* length of what we expand */
- buf = buflist_findnr(i);
- if (buf == NULL)
- {
- *errormsg = (char_u *)"No alternate file name to substitute for '#'";
- return NULL;
- }
- if (lnump != NULL)
- *lnump = buflist_findlnum(buf);
- if (buf->b_fname == NULL)
- {
- result = (char_u *)"";
- valid = 0; /* Must have ":p:h" to be valid */
- }
- else
- result = buf->b_fname;
- break;
- #ifdef FILE_IN_PATH
- case SPEC_CFILE: /* file name under cursor */
- result = file_name_at_cursor(FNAME_MESS|FNAME_HYP, 1L);
- if (result == NULL)
- {
- *errormsg = (char_u *)"";
- return NULL;
- }
- resultbuf = result; /* remember allocated string */
- break;
- #endif
- #ifdef AUTOCMD
- case SPEC_AFILE: /* file name for autocommand */
- result = autocmd_fname;
- if (result == NULL)
- {
- *errormsg = (char_u *)"no autocommand file name to substitute for "<afile>"";
- return NULL;
- }
- break;
- case SPEC_ABUF: /* buffer number for autocommand */
- if (autocmd_bufnr <= 0)
- {
- *errormsg = (char_u *)"no autocommand buffer number to substitute for "<abuf>"";
- return NULL;
- }
- sprintf((char *)abuf_nr, "%d", autocmd_bufnr);
- result = abuf_nr;
- break;
- #endif
- case SPEC_SFILE: /* file name for ":so" command */
- result = sourcing_name;
- if (result == NULL)
- {
- *errormsg = (char_u *)"no :source file name to substitute for "<sfile>"";
- return NULL;
- }
- break;
- }
- resultlen = STRLEN(result); /* length of new string */
- if (src[*usedlen] == '<') /* remove the file name extension */
- {
- ++*usedlen;
- #ifdef RISCOS
- if ((s = vim_strrchr(result, '/')) != NULL && s >= gettail(result))
- #else
- if ((s = vim_strrchr(result, '.')) != NULL && s >= gettail(result))
- #endif
- resultlen = s - result;
- }
- #ifdef WANT_MODIFY_FNAME
- else
- {
- valid |= modify_fname(src, usedlen, &result, &resultbuf,
- &resultlen);
- if (result == NULL)
- {
- *errormsg = (char_u *)"";
- return NULL;
- }
- }
- #endif
- }
- if (resultlen == 0 || valid != VALID_HEAD + VALID_PATH)
- {
- if (valid != VALID_HEAD + VALID_PATH)
- *errormsg = (char_u *)"Empty file name for '%' or '#', only works with ":p:h"";
- else
- *errormsg = (char_u *)"Evaluates to an empty string";
- result = NULL;
- }
- else
- result = vim_strnsave(result, resultlen);
- vim_free(resultbuf);
- return result;
- }
- /*
- * Expand the <sfile> string in "arg".
- *
- * Returns an allocated string, or NULL for any error.
- */
- char_u *
- expand_sfile(arg)
- char_u *arg;
- {
- char_u *errormsg;
- int len;
- char_u *result;
- char_u *newres;
- char_u *repl;
- int srclen;
- char_u *p;
- linenr_t dummy;
- result = vim_strsave(arg);
- if (result == NULL)
- return NULL;
- for (p = result; *p; )
- {
- if (STRNCMP(p, "<sfile>", 7))
- ++p;
- else
- {
- /* replace "<sfile>" with the sourced file name, and do ":" stuff */
- repl = eval_vars(p, &srclen, &dummy, &errormsg, result);
- if (errormsg != NULL)
- {
- if (*errormsg)
- emsg(errormsg);
- vim_free(result);
- return NULL;
- }
- if (repl == NULL) /* no match (cannot happen) */
- {
- p += srclen;
- continue;
- }
- len = STRLEN(result) - srclen + STRLEN(repl) + 1;
- newres = alloc(len);
- if (newres == NULL)
- {
- vim_free(repl);
- vim_free(result);
- return NULL;
- }
- mch_memmove(newres, result, (size_t)(p - result));
- STRCPY(newres + (p - result), repl);
- len = STRLEN(newres);
- STRCAT(newres, p + srclen);
- vim_free(result);
- result = newres;
- p = newres + len; /* continue after the match */
- }
- }
- return result;
- }
- /*
- * Write openfile commands for the current buffers to an .exrc file.
- * Return FAIL on error, OK otherwise.
- */
- static int
- makeopens(fd)
- FILE *fd;
- {
- BUF *buf;
- /*
- * Begin by setting the this_session variable.
- */
- #ifdef WANT_EVAL
- if (fprintf(fd, "let this_session=expand("<sfile>:p")") < 0
- || put_eol(fd) == FAIL)
- return FAIL;
- #endif
- /*
- * Next a command to unload current buffers.
- */
- if (fprintf(fd, "1,999bd") < 0 || put_eol(fd) == FAIL)
- return FAIL;
- /*
- * Now a :cd command to the current directory
- */
- if (fprintf(fd, "execute "cd " . expand("<sfile>:p:h")") < 0
- || put_eol(fd) == FAIL)
- return FAIL;
- /*
- * Now save the current files, current buffer first.
- */
- if (fprintf(fd, "let shmsave = &shortmess | set shortmess=aoO") < 0
- || put_eol(fd) == FAIL)
- return FAIL;
- if (curbuf->b_fname != NULL)
- {
- /* current buffer - must load */
- if (fprintf(fd, "e +%ld ", curwin->w_cursor.lnum ) < 0)
- return FAIL;
- if (fprintf(fd, (curbuf->b_sfname != NULL)
- ? (char *)curbuf->b_sfname
- : (char *)curbuf->b_ffname) < 0
- || put_eol(fd) == FAIL)
- return FAIL;
- }
- /* Now put the other buffers into the buffer list */
- for (buf = firstbuf; buf != NULL; buf = buf->b_next)
- if (buf->b_fname != NULL && buf != curbuf)
- {
- if (fprintf(fd, "badd +%ld ", buf->b_winfpos->wl_fpos.lnum) < 0)
- return FAIL;
- if (fprintf(fd, (buf->b_sfname != NULL)
- ? (char *)buf->b_sfname
- : (char *)buf->b_ffname) < 0
- || put_eol(fd) == FAIL)
- return FAIL;
- }
- if (vim_strchr(p_sessopt, 'r') != NULL) /* "resize" */
- {
- /* Note: after the restore we still check it worked!*/
- if (fprintf(fd, "set lines=%ld" , Rows) < 0 || put_eol(fd) == FAIL)
- return FAIL;
- if (fprintf(fd, "set columns=%ld" , Columns) < 0 || put_eol(fd) == FAIL)
- return FAIL;
- }
- /*
- * Save current windows and cursor pos
- */
- if (vim_strchr(p_sessopt, 'w') != NULL) /* "winsize" */
- {
- int nr = 0;
- int cnr = 0;
- WIN *wp;
- if (fprintf(fd, "let sbsave = &splitbelow | set splitbelow") < 0
- || put_eol(fd) == FAIL)
- return FAIL;
- for (wp = firstwin; wp != NULL; wp = wp->w_next)
- {
- ++nr;
- if (wp->w_buffer->b_fname == NULL)
- {
- /* create new, empty window, except for first window */
- if (nr != 1 && fprintf(fd, "new") < 0)
- return FAIL;
- }
- else
- {
- if (nr == 1)
- {
- /* First window, i.e. already exists*/
- if (fprintf(fd, "b ") < 0)
- return FAIL;
- }
- else
- {
- /* create a new window */
- if (fprintf(fd, "sb ") < 0)
- return FAIL;
- }
- if (wp->w_buffer->b_sfname)
- {
- if (fprintf(fd, (char *)wp->w_buffer->b_sfname) < 0)
- return FAIL;
- }
- else if (wp->w_buffer->b_ffname)
- {
- if (fprintf(fd, (char *)wp->w_buffer->b_ffname) < 0)
- return FAIL;
- }
- }
- if (put_eol(fd) == FAIL)
- return FAIL;
- if (wp->w_buffer->b_fname != NULL
- && (fprintf(fd, "normal %ldG%d|zz", (long)wp->w_cursor.lnum,
- wp->w_cursor.col + 1) < 0
- || put_eol(fd) == FAIL))
- return FAIL;
- if (curwin == wp)
- cnr = nr;
- }
- if (fprintf(fd, "let &splitbelow = sbsave") <0 || put_eol(fd) == FAIL)
- return FAIL;
- /*
- * if more than one window, see if sizes can be restored
- */
- if (nr > 1)
- {
- if (fprintf(fd,
- "if (&lines == %ld)" , Rows) < 0 || put_eol(fd) == FAIL)
- return FAIL;
- if (fprintf(fd, " normal