aboutsummaryrefslogtreecommitdiff
path: root/editors/vi.c
diff options
context:
space:
mode:
Diffstat (limited to 'editors/vi.c')
-rw-r--r--editors/vi.c359
1 files changed, 166 insertions, 193 deletions
diff --git a/editors/vi.c b/editors/vi.c
index fcd139310..2abaf88b8 100644
--- a/editors/vi.c
+++ b/editors/vi.c
@@ -95,7 +95,7 @@ enum {
/* busybox build system provides that, but it's better */
/* to audit and fix the source */
-static int vi_setops;
+static smallint vi_setops;
#define VI_AUTOINDENT 1
#define VI_SHOWMATCH 2
#define VI_IGNORECASE 4
@@ -122,7 +122,7 @@ static char *status_buffer; // mesages to the user
static int have_status_msg; // is default edit status needed?
// [don't make smallint!]
static int last_status_cksum; // hash of current status line
-static char *cfn; // previous, current, and next file name
+static char *current_filename; // current file name
//static char *text, *end; // pointers to the user data in memory
static char *screen; // pointer to the virtual screen buffer
static int screensize; // and its size
@@ -134,8 +134,18 @@ static char last_input_char; // last char read from user
static char last_forward_char; // last char searched for with 'f'
#if ENABLE_FEATURE_VI_READONLY
-static smallint vi_readonly, readonly;
+//static smallint vi_readonly, readonly;
+static smallint readonly_mode = 0;
+#define SET_READONLY_FILE(flags) ((flags) |= 0x01)
+#define SET_READONLY_MODE(flags) ((flags) |= 0x02)
+#define UNSET_READONLY_FILE(flags) ((flags) &= 0xfe)
+#else
+#define readonly_mode 0
+#define SET_READONLY_FILE(flags)
+#define SET_READONLY_MODE(flags)
+#define UNSET_READONLY_FILE(flags)
#endif
+
#if ENABLE_FEATURE_VI_DOT_CMD
static smallint adding2q; // are we currently adding user input to q
static char *last_modifying_cmd; // last modifying cmd for "."
@@ -158,6 +168,7 @@ static char *last_search_pattern; // last pattern from a '/' or '?' search
struct globals {
/* many references - keep near the top of globals */
char *text, *end; // pointers to the user data in memory
+ int text_size; // size of the allocated buffer
char *dot; // where all the action takes place
#if ENABLE_FEATURE_VI_YANKMARK
char *reg[28]; // named register a-z, "D", and "U" 0-25,26,27
@@ -176,6 +187,7 @@ struct globals {
};
#define G (*ptr_to_globals)
#define text (G.text )
+#define text_size (G.text_size )
#define end (G.end )
#define dot (G.dot )
#define reg (G.reg )
@@ -189,8 +201,10 @@ struct globals {
#define term_vi (G.term_vi )
#define initial_cmds (G.initial_cmds )
+static int init_text_buffer(char *); // init from file or create new
static void edit_file(char *); // edit one file
static void do_cmd(char); // execute a command
+static int next_tabstop(int);
static void sync_cursor(char *, int *, int *); // synchronize the screen cursor to dot
static char *begin_line(char *); // return pointer to cur line B-o-l
static char *end_line(char *); // return pointer to cur line E-o-l
@@ -200,7 +214,6 @@ static char *end_screen(void); // get pointer to last char on screen
static int count_lines(char *, char *); // count line from start to stop
static char *find_line(int); // find begining of line #li
static char *move_to_col(char *, int); // move "p" to column l
-static int isblnk(char); // is the char a blank or tab
static void dot_left(void); // move dot left- dont leave line
static void dot_right(void); // move dot right- dont leave line
static void dot_begin(void); // move dot to B-o-l
@@ -212,7 +225,6 @@ static void dot_skip_over_ws(void); // move dot pat WS
static void dot_delete(void); // delete the char at 'dot'
static char *bound_dot(char *); // make sure text[0] <= P < "end"
static char *new_screen(int, int); // malloc virtual screen memory
-static char *new_text(int); // malloc memory for text[] buffer
static char *char_insert(char *, char); // insert the char c at 'p'
static char *stupid_insert(char *, char); // stupidly insert the char c at 'p'
static char find_range(char **, char **, char); // return pointers for an object
@@ -229,11 +241,10 @@ static int mysleep(int); // sleep for 'h' 1/100 seconds
static char readit(void); // read (maybe cursor) key from stdin
static char get_one_char(void); // read 1 char from stdin
static int file_size(const char *); // what is the byte size of "fn"
-static int file_insert(char *, char *);
#if ENABLE_FEATURE_VI_READONLY
-static void update_ro_status(const char *);
+static int file_insert(const char *, char *, int);
#else
-static ALWAYS_INLINE void update_ro_status(const char *name) {}
+static int file_insert(const char *, char *);
#endif
static int file_write(char *, char *, char *);
static void place_cursor(int, int, int);
@@ -305,9 +316,6 @@ int vi_main(int argc, char **argv)
int c;
RESERVE_CONFIG_BUFFER(STATUS_BUFFER, STATUS_BUFFER_LEN);
-#if ENABLE_FEATURE_VI_YANKMARK
- int i;
-#endif
#if ENABLE_FEATURE_VI_USE_SIGNALS || ENABLE_FEATURE_VI_CRASHME
my_pid = getpid();
#endif
@@ -320,19 +328,18 @@ int vi_main(int argc, char **argv)
status_buffer = STATUS_BUFFER;
last_status_cksum = 0;
+ text = NULL;
-#if ENABLE_FEATURE_VI_READONLY
- vi_readonly = readonly = FALSE;
- if (strncmp(argv[0], "view", 4) == 0) {
- readonly = TRUE;
- vi_readonly = TRUE;
+ if (ENABLE_FEATURE_VI_READONLY && strncmp(argv[0], "view", 4) == 0) {
+ SET_READONLY_MODE(readonly_mode);
}
-#endif
+
vi_setops = VI_AUTOINDENT | VI_SHOWMATCH | VI_IGNORECASE | VI_ERR_METHOD;
#if ENABLE_FEATURE_VI_YANKMARK
- for (i = 0; i < 28; i++) {
- reg[i] = 0;
- } // init the yank regs
+ //for (i = 0; i < 28; i++) {
+ // reg[i] = 0;
+ //} // init the yank regs
+ memset(reg, 0, sizeof(reg));
#endif
#if ENABLE_FEATURE_VI_DOT_CMD || ENABLE_FEATURE_VI_YANKMARK
modifying_cmds = (char *) "aAcCdDiIJoOpPrRsxX<>~"; // cmds modifying text[]
@@ -357,8 +364,7 @@ int vi_main(int argc, char **argv)
#endif
#if ENABLE_FEATURE_VI_READONLY
case 'R': // Read-only flag
- readonly = TRUE;
- vi_readonly = TRUE;
+ SET_READONLY_MODE(readonly_mode);
break;
#endif
//case 'r': // recover flag- ignore- we don't use tmp file
@@ -384,14 +390,10 @@ int vi_main(int argc, char **argv)
//----- This is the main file handling loop --------------
if (optind >= argc) {
- editing = 1; // 0= exit, 1= one file, 2 = multiple files
edit_file(0);
} else {
for (; optind < argc; optind++) {
- editing = 1; // 0=exit, 1=one file, 2+ = many files
- free(cfn);
- cfn = xstrdup(argv[optind]);
- edit_file(cfn);
+ edit_file(argv[optind]);
}
}
//-----------------------------------------------------------
@@ -399,10 +401,45 @@ int vi_main(int argc, char **argv)
return 0;
}
+/* read text from file or create an empty buf */
+/* will also update current_filename */
+static int init_text_buffer(char *fn)
+{
+ int rc;
+ int size = file_size(fn); // file size. -1 means does not exist.
+
+ /* allocate/reallocate text buffer */
+ free(text);
+ text_size = size * 2;
+ if (text_size < 10240)
+ text_size = 10240; // have a minimum size for new files
+ screenbegin = dot = end = text = xzalloc(text_size);
+
+ if (fn != current_filename) {
+ free(current_filename);
+ current_filename = xstrdup(fn);
+ }
+ if (size < 0) {
+ // file dont exist. Start empty buf with dummy line
+ char_insert(text, '\n');
+ rc = 0;
+ } else {
+ rc = file_insert(fn, text
+ USE_FEATURE_VI_READONLY(, 1));
+ }
+ file_modified = 0;
+ last_file_modified = -1;
+#if ENABLE_FEATURE_VI_YANKMARK
+ /* init the marks. */
+ memset(mark, 0, sizeof(mark));
+#endif
+ return rc;
+}
+
static void edit_file(char * fn)
{
char c;
- int cnt, size, ch;
+ int size;
#if ENABLE_FEATURE_VI_USE_SIGNALS
int sig;
@@ -411,33 +448,19 @@ static void edit_file(char * fn)
static char *cur_line;
#endif
+ editing = 1; // 0= exit, 1= one file, 2= multiple files
rawmode();
rows = 24;
columns = 80;
- ch = -1;
+ size = 0;
if (ENABLE_FEATURE_VI_WIN_RESIZE)
get_terminal_width_height(0, &columns, &rows);
new_screen(rows, columns); // get memory for virtual screen
+ init_text_buffer(fn);
- cnt = file_size(fn); // file size
- size = 2 * cnt; // 200% of file size
- new_text(size); // get a text[] buffer
- screenbegin = dot = end = text;
- if (fn != 0) {
- ch = file_insert(fn, text);
- update_ro_status(fn);
- }
- if (ch < 1) {
- char_insert(text, '\n'); // start empty buf with dummy line
- }
- file_modified = 0;
- last_file_modified = -1;
#if ENABLE_FEATURE_VI_YANKMARK
YDreg = 26; // default Yank/Delete reg
Ureg = 27; // hold orig line for "U" cmd
- for (cnt = 0; cnt < 28; cnt++) {
- mark[cnt] = 0;
- } // init the marks
mark[26] = mark[27] = text; // init "previous context"
#endif
@@ -455,7 +478,6 @@ static void edit_file(char * fn)
}
#endif
- editing = 1;
cmd_mode = 0; // 0=command 1=insert 2='R'eplace
cmdcnt = 0;
tabstop = 8;
@@ -468,7 +490,6 @@ static void edit_file(char * fn)
adding2q = 0;
#endif
redraw(FALSE); // dont force every col re-draw
- show_status_line();
#if ENABLE_FEATURE_VI_COLON
{
@@ -612,7 +633,7 @@ static char *get_address(char *p, int *b, int *e) // get two colon addrs, if pre
{
//----- get the address' i.e., 1,3 'a,'b -----
// get FIRST addr, if present
- while (isblnk(*p))
+ while (isblank(*p))
p++; // skip over leading spaces
if (*p == '%') { // alias for 1,$
p++;
@@ -621,17 +642,17 @@ static char *get_address(char *p, int *b, int *e) // get two colon addrs, if pre
goto ga0;
}
p = get_one_address(p, b);
- while (isblnk(*p))
+ while (isblank(*p))
p++;
if (*p == ',') { // is there a address separator
p++;
- while (isblnk(*p))
+ while (isblank(*p))
p++;
// get SECOND addr, if present
p = get_one_address(p, e);
}
ga0:
- while (isblnk(*p))
+ while (isblank(*p))
p++; // skip over trailing spaces
return p;
}
@@ -686,7 +707,7 @@ static void colon(char * buf)
q = text; // assume 1,$ for the range
r = end - 1;
li = count_lines(text, end - 1);
- fn = cfn; // default to current file
+ fn = current_filename; // default to current file
memset(cmd, '\0', MAX_LINELEN); // clear cmd[]
memset(args, '\0', MAX_LINELEN); // clear args[]
@@ -704,7 +725,7 @@ static void colon(char * buf)
*buf1++ = *buf++;
}
// get any ARGuments
- while (isblnk(*buf))
+ while (isblank(*buf))
buf++;
strcpy(args, buf);
buf1 = last_char_is(cmd, '!');
@@ -738,12 +759,15 @@ static void colon(char * buf)
}
#if ENABLE_FEATURE_ALLOW_EXEC
else if (strncmp(cmd, "!", 1) == 0) { // run a cmd
+ int retcode;
// :!ls run the <cmd>
alarm(0); // wait for input- no alarms
place_cursor(rows - 1, 0, FALSE); // go to Status line
clear_to_eol(); // clear the line
cookmode();
- system(orig_buf + 1); // run the cmd
+ retcode = system(orig_buf + 1); // run the cmd
+ if (retcode)
+ printf("\nshell returned %i\n\n", retcode);
rawmode();
Hit_Return(); // let user see results
alarm(3); // done waiting for input
@@ -762,9 +786,6 @@ static void colon(char * buf)
dot = yank_delete(q, r, 1, YANKDEL); // save, then delete lines
dot_skip_over_ws();
} else if (strncasecmp(cmd, "edit", i) == 0) { // Edit a file
- int sr;
- struct stat st_buf;
- sr= 0;
// don't edit, if the current file has been modified
if (file_modified && ! useforce) {
psbs("No write since last change (:edit! overrides)");
@@ -773,58 +794,18 @@ static void colon(char * buf)
if (args[0]) {
// the user supplied a file name
fn = args;
- } else if (cfn && cfn[0]) {
+ } else if (current_filename && current_filename[0]) {
// no user supplied name- use the current filename
- fn = cfn;
- goto vc5;
+ // fn = current_filename; was set by default
} else {
// no user file name, no current name- punt
psbs("No current filename");
goto vc1;
}
- // see if file exists- if not, its just a new file request
- sr = stat(fn, &st_buf);
- if (sr < 0) {
- // This is just a request for a new file creation.
- // The file_insert below will fail but we get
- // an empty buffer with a file name. Then the "write"
- // command can do the create.
- } else {
- if ((st_buf.st_mode & S_IFREG) == 0) {
- // This is not a regular file
- psbs("\"%s\" is not a regular file", fn);
- goto vc1;
- }
- if ((st_buf.st_mode & (S_IRUSR | S_IRGRP | S_IROTH)) == 0) {
- // dont have any read permissions
- psbs("\"%s\" is not readable", fn);
- goto vc1;
- }
- }
-
- // There is a read-able regular file
- // make this the current file
- q = xstrdup(fn); // save the cfn
- free(cfn); // free the old name
- cfn = q; // remember new cfn
-
- vc5:
- // delete all the contents of text[]
- new_text(2 * file_size(fn));
- screenbegin = dot = end = text;
-
- // insert new file
- ch = file_insert(fn, text);
- update_ro_status(fn);
+ if (init_text_buffer(fn) < 0)
+ goto vc1;
- if (ch < 1) {
- // start empty buf with dummy line
- char_insert(text, '\n');
- ch = 1;
- }
- file_modified = 0;
- last_file_modified = -1;
#if ENABLE_FEATURE_VI_YANKMARK
if (Ureg >= 0 && Ureg < 28 && reg[Ureg] != 0) {
free(reg[Ureg]); // free orig line reg- for 'U'
@@ -834,21 +815,16 @@ static void colon(char * buf)
free(reg[YDreg]); // free default yank/delete register
reg[YDreg]= 0;
}
- for (li = 0; li < 28; li++) {
- mark[li] = 0;
- } // init the marks
#endif
// how many lines in text[]?
li = count_lines(text, end - 1);
psb("\"%s\"%s"
-#if ENABLE_FEATURE_VI_READONLY
- "%s"
-#endif
- " %dL, %dC", cfn,
- (sr < 0 ? " [New file]" : ""),
-#if ENABLE_FEATURE_VI_READONLY
- ((vi_readonly || readonly) ? " [Read only]" : ""),
-#endif
+ USE_FEATURE_VI_READONLY("%s")
+ " %dL, %dC", current_filename,
+ (file_size(fn) < 0 ? " [New file]" : ""),
+ USE_FEATURE_VI_READONLY(
+ ((readonly_mode) ? " [Readonly]" : ""),
+ )
li, ch);
} else if (strncasecmp(cmd, "file", i) == 0) { // what File is this
if (b != -1 || e != -1) {
@@ -857,8 +833,8 @@ static void colon(char * buf)
}
if (args[0]) {
// user wants a new filename
- free(cfn);
- cfn = xstrdup(args);
+ free(current_filename);
+ current_filename = xstrdup(args);
} else {
// user wants file status info
last_status_cksum = 0; // force status update
@@ -944,7 +920,7 @@ static void colon(char * buf)
// read after current line- unless user said ":0r foo"
if (b != 0)
q = next_line(q);
- ch = file_insert(fn, q);
+ ch = file_insert(fn, q USE_FEATURE_VI_READONLY(, 0));
if (ch < 0)
goto vc1; // nothing was inserted
// how many lines in text[]?
@@ -952,7 +928,7 @@ static void colon(char * buf)
psb("\"%s\""
USE_FEATURE_VI_READONLY("%s")
" %dL, %dC", fn,
- USE_FEATURE_VI_READONLY(((vi_readonly || readonly) ? " [Read only]" : ""),)
+ USE_FEATURE_VI_READONLY((readonly_mode ? " [Readonly]" : ""),)
li, ch);
if (ch > 0) {
// if the insert is before "dot" then we need to update
@@ -1080,7 +1056,7 @@ static void colon(char * buf)
fn = args;
}
#if ENABLE_FEATURE_VI_READONLY
- if ((vi_readonly || readonly) && !useforce) {
+ if (readonly_mode && !useforce) {
psbs("\"%s\" File is read only", fn);
goto vc3;
}
@@ -1104,7 +1080,7 @@ static void colon(char * buf)
}
if (l < 0) {
if (l == -1)
- psbs("Write error: %s", strerror(errno));
+ psbs("\"%s\" %s", fn, strerror(errno));
} else {
psb("\"%s\" %dL, %dC", fn, li, l);
if (q == text && r == end - 1 && l == ch) {
@@ -1158,6 +1134,10 @@ static void Hit_Return(void)
redraw(TRUE); // force redraw all
}
+static int next_tabstop(int col) { //vda
+ return col + ((tabstop - 1) - (col % tabstop));
+}
+
//----- Synchronize the cursor to Dot --------------------------
static void sync_cursor(char * d, int *row, int *col)
{
@@ -1210,8 +1190,11 @@ static void sync_cursor(char * d, int *row, int *col)
if (*tp == '\n' || *tp == '\0')
break;
if (*tp == '\t') {
- // 7 - (co % 8 )
- co += ((tabstop - 1) - (co % tabstop));
+ if (d == tp && cmd_mode) { /* handle tabs like real vi */
+ break;
+ } else {
+ co = next_tabstop(co);
+ }
} else if (*tp < ' ' || *tp == 127) {
co++; // display as ^X, use 2 columns
}
@@ -1365,8 +1348,7 @@ static char *move_to_col(char * p, int l)
if (*p == '\n' || *p == '\0')
break;
if (*p == '\t') {
- // 7 - (co % 8 )
- co += ((tabstop - 1) - (co % tabstop));
+ co = next_tabstop(co);
} else if (*p < ' ' || *p == 127) {
co++; // display as ^X, use 2 columns
}
@@ -1462,28 +1444,15 @@ static char *new_screen(int ro, int co)
return screen;
}
-static char *new_text(int size)
-{
- if (size < 10240)
- size = 10240; // have a minimum size for new files
- free(text);
- text = xmalloc(size + 8);
- memset(text, '\0', size); // clear new text[]
- //text += 4; // leave some room for "oops"
- return text;
-}
-
#if ENABLE_FEATURE_VI_SEARCH
static int mycmp(const char * s1, const char * s2, int len)
{
int i;
i = strncmp(s1, s2, len);
-#if ENABLE_FEATURE_VI_SETOPTS
- if (ignorecase) {
+ if (ENABLE_FEATURE_VI_SETOPTS && ignorecase) {
i = strncasecmp(s1, s2, len);
}
-#endif
return i;
}
@@ -1621,7 +1590,7 @@ static char *char_insert(char * p, char c) // insert the char c at 'p'
char *q;
q = prev_line(p); // use prev line as templet
- for (; isblnk(*q); q++) {
+ for (; isblank(*q); q++) {
p = stupid_insert(p, *q); // insert the char
}
}
@@ -1828,11 +1797,14 @@ static char *text_hole_make(char * p, int size) // at "p", make a 'size' byte ho
src = p;
dest = p + size;
cnt = end - src; // the rest of buffer
- if (memmove(dest, src, cnt) != dest) {
+ if ( ((end + size) >= (text + text_size)) // TODO: realloc here
+ || memmove(dest, src, cnt) != dest) {
psbs("can't create room for new characters");
+ p = NULL;
+ goto thm0;
}
memset(p, ' ', size); // clear new hole
- end = end + size; // adjust the new END
+ end += size; // adjust the new END
file_modified++; // has the file been modified
thm0:
return p;
@@ -2010,15 +1982,16 @@ static char *string_insert(char * p, char * s) // insert the string at 'p'
int cnt, i;
i = strlen(s);
- p = text_hole_make(p, i);
- strncpy(p, s, i);
- for (cnt = 0; *s != '\0'; s++) {
- if (*s == '\n')
- cnt++;
- }
+ if (text_hole_make(p, i)) {
+ strncpy(p, s, i);
+ for (cnt = 0; *s != '\0'; s++) {
+ if (*s == '\n')
+ cnt++;
+ }
#if ENABLE_FEATURE_VI_YANKMARK
- psb("Put %d lines (%d chars) from [%c]", cnt, i, what_reg());
+ psb("Put %d lines (%d chars) from [%c]", cnt, i, what_reg());
#endif
+ }
return p;
}
#endif
@@ -2094,11 +2067,6 @@ static inline char *swap_context(char * p) // goto new context for '' command ma
}
#endif /* FEATURE_VI_YANKMARK */
-static int isblnk(char c) // is the char a blank or tab
-{
- return (c == ' ' || c == '\t');
-}
-
//----- Set terminal attributes --------------------------------
static void rawmode(void)
{
@@ -2240,13 +2208,8 @@ static char readit(void) // read (maybe cursor) key from stdin
if (n < 0) {
if (errno == EINTR)
goto ri0; // interrupted sys call
- if (errno == EBADF)
- editing = 0;
- if (errno == EFAULT)
- editing = 0;
- if (errno == EINVAL)
- editing = 0;
- if (errno == EIO)
+ if (errno == EBADF || errno == EFAULT || errno == EINVAL
+ || errno == EIO)
editing = 0;
errno = 0;
}
@@ -2393,7 +2356,7 @@ static char *get_input_line(const char * prompt) // get input line- use "status
return obufp;
}
-static int file_size(const char * fn) // what is the byte size of "fn"
+static int file_size(const char *fn) // what is the byte size of "fn"
{
struct stat st_buf;
int cnt;
@@ -2404,16 +2367,30 @@ static int file_size(const char * fn) // what is the byte size of "fn"
return cnt;
}
-static int file_insert(char *fn, char *p)
+static int file_insert(const char * fn, char *p
+ USE_FEATURE_VI_READONLY(, int update_ro_status))
{
int cnt = -1;
int fd, size;
-
- size = file_size(fn);
- if (size < 0) {
- psbs("File does not exist");
+ struct stat statbuf;
+
+ /* Validate file */
+ if (stat(fn, &statbuf) < 0) {
+ psbs("\"%s\" %s", fn, strerror(errno));
goto fi0;
}
+ if ((statbuf.st_mode & S_IFREG) == 0) {
+ // This is not a regular file
+ psbs("\"%s\" Not a regular file", fn);
+ goto fi0;
+ }
+ /* // this check is done by open()
+ if ((statbuf.st_mode & (S_IRUSR | S_IRGRP | S_IROTH)) == 0) {
+ // dont have any read permissions
+ psbs("\"%s\" Not readable", fn);
+ goto fi0;
+ }
+ */
if (p < text || p > end) {
psbs("Trying to insert file outside of memory");
goto fi0;
@@ -2422,16 +2399,17 @@ static int file_insert(char *fn, char *p)
// read file to buffer
fd = open(fn, O_RDONLY);
if (fd < 0) {
- psbs("\"%s\" %s", fn, "cannot open file");
+ psbs("\"%s\" %s", fn, strerror(errno));
goto fi0;
}
+ size = statbuf.st_size;
p = text_hole_make(p, size);
+ if (p == NULL)
+ goto fi0;
cnt = read(fd, p, size);
- close(fd);
if (cnt < 0) {
- cnt = -1;
+ psbs("\"%s\" %s", fn, strerror(errno));
p = text_hole_delete(p, p + size - 1); // un-do buffer insert
- psbs("cannot read file \"%s\"", fn);
} else if (cnt < size) {
// There was a partial read, shrink unused space text[]
p = text_hole_delete(p + cnt, p + (size - cnt) - 1); // un-do buffer insert
@@ -2439,22 +2417,19 @@ static int file_insert(char *fn, char *p)
}
if (cnt >= size)
file_modified++;
+ close(fd);
fi0:
- return cnt;
-}
-
-#if ENABLE_FEATURE_VI_READONLY
-static void update_ro_status(const char *fn)
-{
- struct stat sb;
- if (stat(fn, &sb) == 0) {
- readonly = vi_readonly || (access(fn, W_OK) < 0) ||
+ if (ENABLE_FEATURE_VI_READONLY && update_ro_status
+ && ((access(fn, W_OK) < 0) ||
/* root will always have access()
* so we check fileperms too */
- !(sb.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH));
+ !(statbuf.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH))))
+ {
+ SET_READONLY_FILE(readonly_mode);
}
+ return cnt;
}
-#endif
+
static int file_write(char * fn, char * first, char * last)
{
@@ -2687,7 +2662,7 @@ static void ni(const char * s) // display messages
static int format_edit_status(void) // show file status on status line
{
static int tot;
-
+ static const char cmd_mode_indicator[] = "-IR-";
int cur, percent, ret, trunc_at;
// file_modified is now a counter rather than a flag. this
@@ -2726,12 +2701,12 @@ static int format_edit_status(void) // show file status on status line
#else
"%c %s%s %d/%d %d%%",
#endif
- (cmd_mode ? (cmd_mode == 2 ? 'R':'I'):'-'),
- (cfn != 0 ? cfn : "No file"),
+ cmd_mode_indicator[cmd_mode & 3],
+ (current_filename != NULL ? current_filename : "No file"),
#if ENABLE_FEATURE_VI_READONLY
- ((vi_readonly || readonly) ? " [Read-only]" : ""),
+ (readonly_mode ? " [Readonly]" : ""),
#endif
- (file_modified ? " [modified]" : ""),
+ (file_modified ? " [Modified]" : ""),
cur, tot, percent);
if (ret >= 0 && ret < trunc_at)
@@ -3391,14 +3366,14 @@ static void do_cmd(char c)
|| strncasecmp(p, "wn", cnt) == 0
|| strncasecmp(p, "x", cnt) == 0
) {
- cnt = file_write(cfn, text, end - 1);
+ cnt = file_write(current_filename, text, end - 1);
if (cnt < 0) {
if (cnt == -1)
psbs("Write error: %s", strerror(errno));
} else {
file_modified = 0;
last_file_modified = -1;
- psb("\"%s\" %dL, %dC", cfn, count_lines(text, end - 1), cnt);
+ psb("\"%s\" %dL, %dC", current_filename, count_lines(text, end - 1), cnt);
if (p[0] == 'x' || p[1] == 'q' || p[1] == 'n'
|| p[0] == 'X' || p[1] == 'Q' || p[1] == 'N'
) {
@@ -3516,7 +3491,7 @@ static void do_cmd(char c)
if (dot < end - 1) { // make sure not last char in text[]
*dot++ = ' '; // replace NL with space
file_modified++;
- while (isblnk(*dot)) { // delete leading WS
+ while (isblank(*dot)) { // delete leading WS
dot_delete();
}
}
@@ -3583,13 +3558,11 @@ static void do_cmd(char c)
break;
}
if (file_modified) {
-#if ENABLE_FEATURE_VI_READONLY
- if (vi_readonly || readonly) {
- psbs("\"%s\" File is read only", cfn);
+ if (ENABLE_FEATURE_VI_READONLY && readonly_mode) {
+ psbs("\"%s\" File is read only", current_filename);
break;
}
-#endif
- cnt = file_write(cfn, text, end - 1);
+ cnt = file_write(current_filename, text, end - 1);
if (cnt < 0) {
if (cnt == -1)
psbs("Write error: %s", strerror(errno));
@@ -3644,7 +3617,7 @@ static void do_cmd(char c)
} else if (strchr("wW", c1)) {
if (c == 'c') {
// don't include trailing WS as part of word
- while (isblnk(*q)) {
+ while (isblank(*q)) {
if (q <= text || q[-1] == '\n')
break;
q--;