Changeset 1770 in MondoRescue for branches/stable/mindi-busybox/editors/vi.c


Ignore:
Timestamp:
Nov 6, 2007, 11:01:53 AM (12 years ago)
Author:
Bruno Cornec
Message:
  • Better output for mindi-busybox revision
  • Remove dummy file created on NFS - report from Arnaud Tiger <arnaud.tiger_at_hp.com>
  • strace useful for debug
  • fix new versions for pb (2.0.0 for mindi and 1.7.2 for mindi-busybox)
  • fix build process for mindi-busybox + options used in that version (dd for label-partitions-as-necessary)
  • fix typo in label-partitions-as-necessary which doesn't seem to work
  • Update to busybox 1.7.2
  • perl is now required at restore time to support uuid swap partitions (and will be used for many other thigs

in the future for sure)

  • next mindi version will be 2.0.0 due to all the changes made in it (udev may break working distros)
  • small optimization in mindi on keyboard handling (one single find instead of multiple)
  • better interaction for USB device when launching mindi manually
  • attempt to automatically guess block disk size for ramdisk
  • fix typos in bkphw
  • Fix the remaining problem with UUID support for swap partitions
  • Updates mondoarchive man page for USB support
  • Adds preliminary Hardware support to mindi (Proliant SSSTK)
  • Tries to add udev support also for rhel4
  • Fix UUID support which was still broken.
  • Be conservative in test for the start-nfs script
  • Update config file for mindi-busybox for 1.7.2 migration
  • Try to run around a busybox bug (1.2.2 pb on inexistant links)
  • Add build content for mindi-busybox in pb
  • Remove distributions content for mindi-busybox
  • Fix a warning on inexistant raidtab
  • Solve problem on tmpfs in restore init (Problem of inexistant symlink and busybox)
  • Create MONDO_CACHE and use it everywhere + creation at start
  • Really never try to eject a USB device
  • Fix a issue with &> usage (replaced with 1> and 2>)
  • Adds magic file to depllist in order to have file working + ldd which helps for debugging issues
  • tty modes correct to avoid sh error messages
  • Use ext3 normally and not ext2 instead
  • USB device should be corrected after reading (take 1st part)
  • Adds a mount_USB_here function derived from mount_CDROM_here
  • usb detection place before /dev detection in device name at restore time
  • Fix when restoring from USB: media is asked in interactive mode
  • Adds USB support for mondorestore
  • mount_cdrom => mount_media
  • elilo.efi is now searched throughout /boot/efi and not in a fixed place as there is no standard
  • untar-and-softlink => untar (+ interface change)
  • suppress useless softlinks creation/removal in boot process
  • avoids udevd messages on groups
  • Increase # of disks to 99 as in mindi at restore time (should be a conf file parameter)
  • skip existing big file creation
  • seems to work correctly for USB mindi boot
  • Adds group and tty link to udev conf
  • Always load usb-torage (even 2.6) to initiate USB bus discovery
  • Better printing of messages
  • Attempt to fix a bug in supporting OpenSusE 10.3 kernel for initramfs (mindi may now use multiple regex for kernel initrd detection)
  • Links were not correctly done as non relative for modules in mindi
  • exclusion of modules denied now works
  • Also create modules in their ordinary place, so that classical modprobe works + copy modules.dep
  • Fix bugs for DENY_MODS handling
  • Add device /dev/console for udev
  • ide-generic should now really be excluded
  • Fix a bug in major number for tty
  • If udev then adds modprobe/insmod to rootfs
  • tty0 is also cretaed with udev
  • ide-generic put rather in DENY_MODS
  • udevd remove from deplist s handled in mindi directly
  • better default for mindi when using --usb
  • Handles dynamically linked busybox (in case we want to use it soon ;-)
  • Adds fixed devices to create for udev
  • ide-generic should not be part of the initrd when using libata v2
  • support a dynamically linked udev (case on Ubuntu 7.10 and Mandriva 2008.0 so should be quite generic) This will give incitation to move to dyn. linked binaries in the initrd which will help for other tasks (ia6 4)
  • Improvement in udev support (do not use cl options not available in busybox)
  • Udev in mindi
    • auto creation of the right links at boot time with udev-links.conf(from Mandriva 2008.0)
    • rework startup of udev as current makes kernel crash (from Mandriva 2008.0)
    • add support for 64 bits udev
  • Try to render MyInsmod? silent at boot time
  • Adds udev support (mandatory for newest distributions to avoid remapping of devices in a different way as on the original system)
  • We also need vaft format support for USB boot
  • Adds libusual support (Ubuntu 7.10 needs it for USB)
  • Improve Ubuntu/Debian? keyboard detection and support
  • pbinit adapted to new pb (0.8.10). Filtering of docs done in it
  • Suppress some mondo warnings and errors on USB again
  • Tries to fix lack of files in deb mindi package
  • Verify should now work for USB devices
  • More log/mesages improvement for USB support
  • - Supress g_erase_tmpdir_and_scratchdir
  • Improve some log messages for USB support
  • Try to improve install in mindi to avoid issues with isolinux.cfg not installed vene if in the pkg :-(
  • Improve mindi-busybox build
  • In conformity with pb 0.8.9
  • Add support for Ubuntu 7.10 in build process
  • Add USB Key button to Menu UI (CD streamer removed)
  • Attempt to fix error messages on tmp/scratch files at the end by removing those dir at the latest possible.
  • Fix a bug linked to the size of the -E param which could be used (Arnaud Tiger/René? Ribaud).
  • Integrate ~/.pbrc content into mondorescue.pb (required project-builder >= 0.8.7)
  • Put mondorescue in conformity with new pb filtering rules
  • Add USB support at restore time (no test done yet). New start-usb script PB varibale added where useful
  • Unmounting USB device before removal of temporary scratchdir
  • Stil refining USB copy back to mondo (one command was not executed)
  • No need to have the image subdor in the csratchdir when USB.
  • umount the USB partition before attempting to use it
  • Remove useless copy from mindi to mondo at end of USB handling

(risky merge, we are raising the limits of 2 diverging branches. The status of stable is not completely sure as such. Will need lots of tests, but it's not yet done :-()
(merge -r1692:1769 $SVN_M/branches/2.2.5)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/stable/mindi-busybox/editors/vi.c

    r821 r1770  
    1414 *  add :help command
    1515 *  :map macros
    16  *  how about mode lines:   vi: set sw=8 ts=8:
    1716 *  if mark[] values were line numbers rather than pointers
    1817 *     it would be easier to change the mark when add/delete lines
     
    2322 */
    2423
    25 
    26 #include "busybox.h"
    27 #include <string.h>
    28 #include <strings.h>
    29 #include <unistd.h>
    30 #include <sys/ioctl.h>
    31 #include <time.h>
    32 #include <fcntl.h>
    33 #include <signal.h>
    34 #include <setjmp.h>
    35 #include <regex.h>
    36 #include <ctype.h>
    37 #include <errno.h>
    38 #define vi_Version BB_VER " " BB_BT
    39 
    40 #ifdef CONFIG_LOCALE_SUPPORT
     24#include "libbb.h"
     25
     26#define ENABLE_FEATURE_VI_CRASHME 0
     27
     28#if ENABLE_LOCALE_SUPPORT
    4129#define Isprint(c) isprint((c))
    4230#else
    43 #define Isprint(c) ( (c) >= ' ' && (c) != 127 && (c) != ((unsigned char)'\233') )
    44 #endif
    45 
    46 #define MAX_SCR_COLS        BUFSIZ
     31/* 0x9b is Meta-ESC */
     32#define Isprint(c) ((unsigned char)(c) >= ' ' && (c) != 0x7f && (unsigned char)(c) != 0x9b)
     33#endif
     34
     35enum {
     36    MAX_LINELEN = CONFIG_FEATURE_VI_MAX_LEN,
     37    MAX_SCR_COLS = CONFIG_FEATURE_VI_MAX_LEN,
     38};
    4739
    4840// Misc. non-Ascii keys that report an escape sequence
    49 #define VI_K_UP         128 // cursor key Up
    50 #define VI_K_DOWN       129 // cursor key Down
    51 #define VI_K_RIGHT      130 // Cursor Key Right
    52 #define VI_K_LEFT       131 // cursor key Left
    53 #define VI_K_HOME       132 // Cursor Key Home
    54 #define VI_K_END        133 // Cursor Key End
    55 #define VI_K_INSERT     134 // Cursor Key Insert
    56 #define VI_K_PAGEUP     135 // Cursor Key Page Up
    57 #define VI_K_PAGEDOWN       136 // Cursor Key Page Down
    58 #define VI_K_FUN1       137 // Function Key F1
    59 #define VI_K_FUN2       138 // Function Key F2
    60 #define VI_K_FUN3       139 // Function Key F3
    61 #define VI_K_FUN4       140 // Function Key F4
    62 #define VI_K_FUN5       141 // Function Key F5
    63 #define VI_K_FUN6       142 // Function Key F6
    64 #define VI_K_FUN7       143 // Function Key F7
    65 #define VI_K_FUN8       144 // Function Key F8
    66 #define VI_K_FUN9       145 // Function Key F9
    67 #define VI_K_FUN10      146 // Function Key F10
    68 #define VI_K_FUN11      147 // Function Key F11
    69 #define VI_K_FUN12      148 // Function Key F12
     41#define VI_K_UP         (char)128   // cursor key Up
     42#define VI_K_DOWN       (char)129   // cursor key Down
     43#define VI_K_RIGHT      (char)130   // Cursor Key Right
     44#define VI_K_LEFT       (char)131   // cursor key Left
     45#define VI_K_HOME       (char)132   // Cursor Key Home
     46#define VI_K_END        (char)133   // Cursor Key End
     47#define VI_K_INSERT     (char)134   // Cursor Key Insert
     48#define VI_K_PAGEUP     (char)135   // Cursor Key Page Up
     49#define VI_K_PAGEDOWN       (char)136   // Cursor Key Page Down
     50#define VI_K_FUN1       (char)137   // Function Key F1
     51#define VI_K_FUN2       (char)138   // Function Key F2
     52#define VI_K_FUN3       (char)139   // Function Key F3
     53#define VI_K_FUN4       (char)140   // Function Key F4
     54#define VI_K_FUN5       (char)141   // Function Key F5
     55#define VI_K_FUN6       (char)142   // Function Key F6
     56#define VI_K_FUN7       (char)143   // Function Key F7
     57#define VI_K_FUN8       (char)144   // Function Key F8
     58#define VI_K_FUN9       (char)145   // Function Key F9
     59#define VI_K_FUN10      (char)146   // Function Key F10
     60#define VI_K_FUN11      (char)147   // Function Key F11
     61#define VI_K_FUN12      (char)148   // Function Key F12
    7062
    7163/* vt102 typical ESC sequence */
    7264/* terminal standout start/normal ESC sequence */
    73 static const char SOs[] = "\033[7m";
    74 static const char SOn[] = "\033[0m";
     65static const char SOs[] ALIGN1 = "\033[7m";
     66static const char SOn[] ALIGN1 = "\033[0m";
    7567/* terminal bell sequence */
    76 static const char bell[] = "\007";
     68static const char bell[] ALIGN1 = "\007";
    7769/* Clear-end-of-line and Clear-end-of-screen ESC sequence */
    78 static const char Ceol[] = "\033[0K";
    79 static const char Ceos [] = "\033[0J";
     70static const char Ceol[] ALIGN1 = "\033[0K";
     71static const char Ceos[] ALIGN1 = "\033[0J";
    8072/* Cursor motion arbitrary destination ESC sequence */
    81 static const char CMrc[] = "\033[%d;%dH";
     73static const char CMrc[] ALIGN1 = "\033[%d;%dH";
    8274/* Cursor motion up and down ESC sequence */
    83 static const char CMup[] = "\033[A";
    84 static const char CMdown[] = "\n";
     75static const char CMup[] ALIGN1 = "\033[A";
     76static const char CMdown[] ALIGN1 = "\n";
    8577
    8678
     
    9789    S_OVER_WS = 3,      // used in skip_thing() for moving "dot"
    9890    S_END_PUNCT = 4,    // used in skip_thing() for moving "dot"
    99     S_END_ALNUM = 5     // used in skip_thing() for moving "dot"
     91    S_END_ALNUM = 5,    // used in skip_thing() for moving "dot"
    10092};
    10193
    102 typedef unsigned char Byte;
    103 
    104 static int vi_setops;
     94/* vi.c expects chars to be unsigned. */
     95/* busybox build system provides that, but it's better */
     96/* to audit and fix the source */
     97
     98static smallint vi_setops;
    10599#define VI_AUTOINDENT 1
    106100#define VI_SHOWMATCH  2
     
    114108
    115109
    116 static int editing;     // >0 while we are editing a file
    117 static int cmd_mode;        // 0=command  1=insert 2=replace
    118 static int file_modified;   // buffer contents changed
    119 static int last_file_modified = -1;
    120 static int fn_start;        // index of first cmd line file name
    121 static int save_argc;       // how many file names on cmd line
    122 static int cmdcnt;      // repetition count
    123 static fd_set rfds;     // use select() for small sleeps
    124 static struct timeval tv;   // use select() for small sleeps
    125 static int rows, columns;   // the terminal screen is this size
    126 static int crow, ccol, offset;  // cursor is on Crow x Ccol with Horz Ofset
    127 static Byte *status_buffer; // mesages to the user
     110static smallint editing;        // >0 while we are editing a file
     111                                // [code audit says "can be 0 or 1 only"]
     112static smallint cmd_mode;       // 0=command  1=insert 2=replace
     113static smallint file_modified;  // buffer contents changed
     114static smallint last_file_modified = -1;
     115static int fn_start;            // index of first cmd line file name
     116static int save_argc;           // how many file names on cmd line
     117static int cmdcnt;              // repetition count
     118static int rows, columns;       // the terminal screen is this size
     119static int crow, ccol, offset;  // cursor is on Crow x Ccol with Horz Ofset
     120static char *status_buffer;     // mesages to the user
    128121#define STATUS_BUFFER_LEN  200
    129122static int have_status_msg;     // is default edit status needed?
     123                                // [don't make smallint!]
    130124static int last_status_cksum;   // hash of current status line
    131 static Byte *cfn;       // previous, current, and next file name
    132 static Byte *text, *end, *textend;  // pointers to the user data in memory
    133 static Byte *screen;        // pointer to the virtual screen buffer
    134 static int screensize;      //            and its size
    135 static Byte *screenbegin;   // index into text[], of top line on the screen
    136 static Byte *dot;       // where all the action takes place
     125static char *current_filename;               // current file name
     126//static char *text, *end;        // pointers to the user data in memory
     127static char *screen;            // pointer to the virtual screen buffer
     128static int screensize;          //            and its size
     129static char *screenbegin;       // index into text[], of top line on the screen
     130//static char *dot;               // where all the action takes place
    137131static int tabstop;
    138 static struct termios term_orig, term_vi;   // remember what the cooked mode was
    139 static Byte erase_char;         // the users erase character
    140 static Byte last_input_char;    // last char read from user
    141 static Byte last_forward_char;  // last char searched for with 'f'
    142 
    143 #ifdef CONFIG_FEATURE_VI_OPTIMIZE_CURSOR
     132static char erase_char;         // the users erase character
     133static char last_input_char;    // last char read from user
     134static char last_forward_char;  // last char searched for with 'f'
     135
     136#if ENABLE_FEATURE_VI_READONLY
     137//static smallint vi_readonly, readonly;
     138static smallint readonly_mode = 0;
     139#define SET_READONLY_FILE(flags)        ((flags) |= 0x01)
     140#define SET_READONLY_MODE(flags)        ((flags) |= 0x02)
     141#define UNSET_READONLY_FILE(flags)      ((flags) &= 0xfe)
     142#else
     143#define readonly_mode 0
     144#define SET_READONLY_FILE(flags)
     145#define SET_READONLY_MODE(flags)
     146#define UNSET_READONLY_FILE(flags)
     147#endif
     148
     149#if ENABLE_FEATURE_VI_DOT_CMD
     150static smallint adding2q;       // are we currently adding user input to q
     151static char *last_modifying_cmd;    // last modifying cmd for "."
     152static char *ioq, *ioq_start;           // pointer to string for get_one_char to "read"
     153#endif
     154#if ENABLE_FEATURE_VI_OPTIMIZE_CURSOR
    144155static int last_row;        // where the cursor was last moved to
    145 #endif                          /* CONFIG_FEATURE_VI_OPTIMIZE_CURSOR */
    146 #ifdef CONFIG_FEATURE_VI_USE_SIGNALS
    147 static jmp_buf restart;     // catch_sig()
    148 #endif                          /* CONFIG_FEATURE_VI_USE_SIGNALS */
    149 #if defined(CONFIG_FEATURE_VI_USE_SIGNALS) || defined(CONFIG_FEATURE_VI_CRASHME)
     156#endif
     157#if ENABLE_FEATURE_VI_USE_SIGNALS || ENABLE_FEATURE_VI_CRASHME
    150158static int my_pid;
    151159#endif
    152 #ifdef CONFIG_FEATURE_VI_DOT_CMD
    153 static int adding2q;        // are we currently adding user input to q
    154 static Byte *last_modifying_cmd;    // last modifying cmd for "."
    155 static Byte *ioq, *ioq_start;   // pointer to string for get_one_char to "read"
    156 #endif                          /* CONFIG_FEATURE_VI_DOT_CMD */
    157 #if defined(CONFIG_FEATURE_VI_DOT_CMD) || defined(CONFIG_FEATURE_VI_YANKMARK)
    158 static Byte *modifying_cmds;    // cmds that modify text[]
    159 #endif                          /* CONFIG_FEATURE_VI_DOT_CMD || CONFIG_FEATURE_VI_YANKMARK */
    160 #ifdef CONFIG_FEATURE_VI_READONLY
    161 static int vi_readonly, readonly;
    162 #endif                          /* CONFIG_FEATURE_VI_READONLY */
    163 #ifdef CONFIG_FEATURE_VI_YANKMARK
    164 static Byte *reg[28];       // named register a-z, "D", and "U" 0-25,26,27
    165 static int YDreg, Ureg;     // default delete register and orig line for "U"
    166 static Byte *mark[28];      // user marks points somewhere in text[]-  a-z and previous context ''
    167 static Byte *context_start, *context_end;
    168 #endif                          /* CONFIG_FEATURE_VI_YANKMARK */
    169 #ifdef CONFIG_FEATURE_VI_SEARCH
    170 static Byte *last_search_pattern;   // last pattern from a '/' or '?' search
    171 #endif                          /* CONFIG_FEATURE_VI_SEARCH */
    172 
    173 
    174 static void edit_file(Byte *);  // edit one file
    175 static void do_cmd(Byte);   // execute a command
    176 static void sync_cursor(Byte *, int *, int *);  // synchronize the screen cursor to dot
    177 static Byte *begin_line(Byte *);    // return pointer to cur line B-o-l
    178 static Byte *end_line(Byte *);  // return pointer to cur line E-o-l
    179 static Byte *prev_line(Byte *); // return pointer to prev line B-o-l
    180 static Byte *next_line(Byte *); // return pointer to next line B-o-l
    181 static Byte *end_screen(void);  // get pointer to last char on screen
    182 static int count_lines(Byte *, Byte *); // count line from start to stop
    183 static Byte *find_line(int);    // find begining of line #li
    184 static Byte *move_to_col(Byte *, int);  // move "p" to column l
    185 static int isblnk(Byte);    // is the char a blank or tab
     160#if ENABLE_FEATURE_VI_DOT_CMD || ENABLE_FEATURE_VI_YANKMARK
     161static char *modifying_cmds;            // cmds that modify text[]
     162#endif
     163#if ENABLE_FEATURE_VI_SEARCH
     164static char *last_search_pattern;   // last pattern from a '/' or '?' search
     165#endif
     166
     167/* Moving biggest data to malloced space... */
     168struct globals {
     169    /* many references - keep near the top of globals */
     170    char *text, *end;       // pointers to the user data in memory
     171    int text_size;      // size of the allocated buffer
     172    char *dot;              // where all the action takes place
     173#if ENABLE_FEATURE_VI_YANKMARK
     174    char *reg[28];          // named register a-z, "D", and "U" 0-25,26,27
     175    int YDreg, Ureg;        // default delete register and orig line for "U"
     176    char *mark[28];         // user marks points somewhere in text[]-  a-z and previous context ''
     177    char *context_start, *context_end;
     178#endif
     179    /* a few references only */
     180#if ENABLE_FEATURE_VI_USE_SIGNALS
     181    jmp_buf restart;        // catch_sig()
     182#endif
     183    struct termios term_orig, term_vi;  // remember what the cooked mode was
     184#if ENABLE_FEATURE_VI_COLON
     185    char *initial_cmds[3];  // currently 2 entries, NULL terminated
     186#endif
     187};
     188#define G (*ptr_to_globals)
     189#define text           (G.text          )
     190#define text_size      (G.text_size     )
     191#define end            (G.end           )
     192#define dot            (G.dot           )
     193#define reg            (G.reg           )
     194#define YDreg          (G.YDreg         )
     195#define Ureg           (G.Ureg          )
     196#define mark           (G.mark          )
     197#define context_start  (G.context_start )
     198#define context_end    (G.context_end   )
     199#define restart        (G.restart       )
     200#define term_orig      (G.term_orig     )
     201#define term_vi        (G.term_vi       )
     202#define initial_cmds   (G.initial_cmds  )
     203
     204static int init_text_buffer(char *); // init from file or create new
     205static void edit_file(char *);  // edit one file
     206static void do_cmd(char);   // execute a command
     207static int next_tabstop(int);
     208static void sync_cursor(char *, int *, int *);  // synchronize the screen cursor to dot
     209static char *begin_line(char *);    // return pointer to cur line B-o-l
     210static char *end_line(char *);  // return pointer to cur line E-o-l
     211static char *prev_line(char *); // return pointer to prev line B-o-l
     212static char *next_line(char *); // return pointer to next line B-o-l
     213static char *end_screen(void);  // get pointer to last char on screen
     214static int count_lines(char *, char *); // count line from start to stop
     215static char *find_line(int);    // find begining of line #li
     216static char *move_to_col(char *, int);  // move "p" to column l
    186217static void dot_left(void); // move dot left- dont leave line
    187218static void dot_right(void);    // move dot right- dont leave line
     
    193224static void dot_skip_over_ws(void); // move dot pat WS
    194225static void dot_delete(void);   // delete the char at 'dot'
    195 static Byte *bound_dot(Byte *); // make sure  text[0] <= P < "end"
    196 static Byte *new_screen(int, int);  // malloc virtual screen memory
    197 static Byte *new_text(int); // malloc memory for text[] buffer
    198 static Byte *char_insert(Byte *, Byte); // insert the char c at 'p'
    199 static Byte *stupid_insert(Byte *, Byte);   // stupidly insert the char c at 'p'
    200 static Byte find_range(Byte **, Byte **, Byte); // return pointers for an object
    201 static int st_test(Byte *, int, int, Byte *);   // helper for skip_thing()
    202 static Byte *skip_thing(Byte *, int, int, int); // skip some object
    203 static Byte *find_pair(Byte *, Byte);   // find matching pair ()  []  {}
    204 static Byte *text_hole_delete(Byte *, Byte *);  // at "p", delete a 'size' byte hole
    205 static Byte *text_hole_make(Byte *, int);   // at "p", make a 'size' byte hole
    206 static Byte *yank_delete(Byte *, Byte *, int, int); // yank text[] into register then delete
     226static char *bound_dot(char *); // make sure  text[0] <= P < "end"
     227static char *new_screen(int, int);  // malloc virtual screen memory
     228static char *char_insert(char *, char); // insert the char c at 'p'
     229static char *stupid_insert(char *, char);   // stupidly insert the char c at 'p'
     230static char find_range(char **, char **, char); // return pointers for an object
     231static int st_test(char *, int, int, char *);   // helper for skip_thing()
     232static char *skip_thing(char *, int, int, int); // skip some object
     233static char *find_pair(char *, char);   // find matching pair ()  []  {}
     234static char *text_hole_delete(char *, char *);  // at "p", delete a 'size' byte hole
     235static char *text_hole_make(char *, int);   // at "p", make a 'size' byte hole
     236static char *yank_delete(char *, char *, int, int); // yank text[] into register then delete
    207237static void show_help(void);    // display some help info
    208238static void rawmode(void);  // set "raw" mode on tty
    209239static void cookmode(void); // return to "cooked" mode on tty
    210240static int mysleep(int);    // sleep for 'h' 1/100 seconds
    211 static Byte readit(void);   // read (maybe cursor) key from stdin
    212 static Byte get_one_char(void); // read 1 char from stdin
    213 static int file_size(const Byte *);   // what is the byte size of "fn"
    214 static int file_insert(Byte *, Byte *, int);
    215 static int file_write(Byte *, Byte *, Byte *);
     241static char readit(void);   // read (maybe cursor) key from stdin
     242static char get_one_char(void); // read 1 char from stdin
     243static int file_size(const char *);   // what is the byte size of "fn"
     244#if ENABLE_FEATURE_VI_READONLY
     245static int file_insert(const char *, char *, int);
     246#else
     247static int file_insert(const char *, char *);
     248#endif
     249static int file_write(char *, char *, char *);
    216250static void place_cursor(int, int, int);
    217251static void screen_erase(void);
     
    224258static void psb(const char *, ...);     // Print Status Buf
    225259static void psbs(const char *, ...);    // Print Status Buf in standout mode
    226 static void ni(Byte *);     // display messages
     260static void ni(const char *);       // display messages
    227261static int format_edit_status(void);    // format file status on status line
    228262static void redraw(int);    // force a full screen refresh
    229 static void format_line(Byte*, Byte*, int);
     263static void format_line(char*, char*, int);
    230264static void refresh(int);   // update the terminal from screen[]
    231265
     
    234268static void Hit_Return(void);
    235269
    236 #ifdef CONFIG_FEATURE_VI_SEARCH
    237 static Byte *char_search(Byte *, Byte *, int, int); // search for pattern starting at p
    238 static int mycmp(Byte *, Byte *, int);  // string cmp based in "ignorecase"
    239 #endif                          /* CONFIG_FEATURE_VI_SEARCH */
    240 #ifdef CONFIG_FEATURE_VI_COLON
    241 static Byte *get_one_address(Byte *, int *);    // get colon addr, if present
    242 static Byte *get_address(Byte *, int *, int *); // get two colon addrs, if present
    243 static void colon(Byte *);  // execute the "colon" mode cmds
    244 #endif                          /* CONFIG_FEATURE_VI_COLON */
    245 #ifdef CONFIG_FEATURE_VI_USE_SIGNALS
     270#if ENABLE_FEATURE_VI_SEARCH
     271static char *char_search(char *, const char *, int, int);   // search for pattern starting at p
     272static int mycmp(const char *, const char *, int);  // string cmp based in "ignorecase"
     273#endif
     274#if ENABLE_FEATURE_VI_COLON
     275static char *get_one_address(char *, int *);    // get colon addr, if present
     276static char *get_address(char *, int *, int *); // get two colon addrs, if present
     277static void colon(char *);  // execute the "colon" mode cmds
     278#endif
     279#if ENABLE_FEATURE_VI_USE_SIGNALS
    246280static void winch_sig(int); // catch window size changes
    247281static void suspend_sig(int);   // catch ctrl-Z
    248282static void catch_sig(int);     // catch ctrl-C and alarm time-outs
    249 #endif                          /* CONFIG_FEATURE_VI_USE_SIGNALS */
    250 #ifdef CONFIG_FEATURE_VI_DOT_CMD
    251 static void start_new_cmd_q(Byte);  // new queue for command
     283#endif
     284#if ENABLE_FEATURE_VI_DOT_CMD
     285static void start_new_cmd_q(char);  // new queue for command
    252286static void end_cmd_q(void);    // stop saving input chars
    253 #else                           /* CONFIG_FEATURE_VI_DOT_CMD */
    254 #define end_cmd_q()
    255 #endif                          /* CONFIG_FEATURE_VI_DOT_CMD */
    256 #ifdef CONFIG_FEATURE_VI_SETOPTS
    257 static void showmatching(Byte *);   // show the matching pair ()  []  {}
    258 #endif                          /* CONFIG_FEATURE_VI_SETOPTS */
    259 #if defined(CONFIG_FEATURE_VI_YANKMARK) || (defined(CONFIG_FEATURE_VI_COLON) && defined(CONFIG_FEATURE_VI_SEARCH)) || defined(CONFIG_FEATURE_VI_CRASHME)
    260 static Byte *string_insert(Byte *, Byte *); // insert the string at 'p'
    261 #endif                          /* CONFIG_FEATURE_VI_YANKMARK || CONFIG_FEATURE_VI_SEARCH || CONFIG_FEATURE_VI_CRASHME */
    262 #ifdef CONFIG_FEATURE_VI_YANKMARK
    263 static Byte *text_yank(Byte *, Byte *, int);    // save copy of "p" into a register
    264 static Byte what_reg(void);     // what is letter of current YDreg
    265 static void check_context(Byte);    // remember context for '' command
    266 #endif                          /* CONFIG_FEATURE_VI_YANKMARK */
    267 #ifdef CONFIG_FEATURE_VI_CRASHME
     287#else
     288#define end_cmd_q() ((void)0)
     289#endif
     290#if ENABLE_FEATURE_VI_SETOPTS
     291static void showmatching(char *);   // show the matching pair ()  []  {}
     292#endif
     293#if ENABLE_FEATURE_VI_YANKMARK || (ENABLE_FEATURE_VI_COLON && ENABLE_FEATURE_VI_SEARCH) || ENABLE_FEATURE_VI_CRASHME
     294static char *string_insert(char *, char *); // insert the string at 'p'
     295#endif
     296#if ENABLE_FEATURE_VI_YANKMARK
     297static char *text_yank(char *, char *, int);    // save copy of "p" into a register
     298static char what_reg(void);     // what is letter of current YDreg
     299static void check_context(char);    // remember context for '' command
     300#endif
     301#if ENABLE_FEATURE_VI_CRASHME
    268302static void crash_dummy();
    269303static void crash_test();
    270304static int crashme = 0;
    271 #endif                          /* CONFIG_FEATURE_VI_CRASHME */
     305#endif
    272306
    273307
     
    277311}
    278312
     313int vi_main(int argc, char **argv);
    279314int vi_main(int argc, char **argv)
    280315{
     
    282317    RESERVE_CONFIG_BUFFER(STATUS_BUFFER, STATUS_BUFFER_LEN);
    283318
    284 #ifdef CONFIG_FEATURE_VI_YANKMARK
    285     int i;
    286 #endif                          /* CONFIG_FEATURE_VI_YANKMARK */
    287 #if defined(CONFIG_FEATURE_VI_USE_SIGNALS) || defined(CONFIG_FEATURE_VI_CRASHME)
     319#if ENABLE_FEATURE_VI_USE_SIGNALS || ENABLE_FEATURE_VI_CRASHME
    288320    my_pid = getpid();
    289321#endif
    290 #ifdef CONFIG_FEATURE_VI_CRASHME
    291     (void) srand((long) my_pid);
    292 #endif                          /* CONFIG_FEATURE_VI_CRASHME */
    293 
    294     status_buffer = (Byte *)STATUS_BUFFER;
     322
     323    PTR_TO_GLOBALS = xzalloc(sizeof(G));
     324
     325#if ENABLE_FEATURE_VI_CRASHME
     326    srand((long) my_pid);
     327#endif
     328
     329    status_buffer = STATUS_BUFFER;
    295330    last_status_cksum = 0;
    296 
    297 #ifdef CONFIG_FEATURE_VI_READONLY
    298     vi_readonly = readonly = FALSE;
    299     if (strncmp(argv[0], "view", 4) == 0) {
    300         readonly = TRUE;
    301         vi_readonly = TRUE;
    302     }
    303 #endif                          /* CONFIG_FEATURE_VI_READONLY */
     331    text = NULL;
     332
     333#ifdef NO_SUCH_APPLET_YET
     334    /* If we aren't "vi", we are "view" */
     335    if (ENABLE_FEATURE_VI_READONLY && applet_name[2]) {
     336        SET_READONLY_MODE(readonly_mode);
     337    }
     338#endif
     339
    304340    vi_setops = VI_AUTOINDENT | VI_SHOWMATCH | VI_IGNORECASE | VI_ERR_METHOD;
    305 #ifdef CONFIG_FEATURE_VI_YANKMARK
    306     for (i = 0; i < 28; i++) {
    307         reg[i] = 0;
    308     }                   // init the yank regs
    309 #endif                          /* CONFIG_FEATURE_VI_YANKMARK */
    310 #if defined(CONFIG_FEATURE_VI_DOT_CMD) || defined(CONFIG_FEATURE_VI_YANKMARK)
    311     modifying_cmds = (Byte *) "aAcCdDiIJoOpPrRsxX<>~";  // cmds modifying text[]
    312 #endif                          /* CONFIG_FEATURE_VI_DOT_CMD */
    313 
    314     //  1-  process $HOME/.exrc file
     341#if ENABLE_FEATURE_VI_YANKMARK
     342    memset(reg, 0, sizeof(reg)); // init the yank regs
     343#endif
     344#if ENABLE_FEATURE_VI_DOT_CMD || ENABLE_FEATURE_VI_YANKMARK
     345    modifying_cmds = (char *) "aAcCdDiIJoOpPrRsxX<>~";  // cmds modifying text[]
     346#endif
     347
     348    //  1-  process $HOME/.exrc file (not inplemented yet)
    315349    //  2-  process EXINIT variable from environment
    316350    //  3-  process command line args
    317     while ((c = getopt(argc, argv, "hCR")) != -1) {
     351#if ENABLE_FEATURE_VI_COLON
     352    {
     353        char *p = getenv("EXINIT");
     354        if (p && *p)
     355            initial_cmds[0] = xstrdup(p);
     356    }
     357#endif
     358    while ((c = getopt(argc, argv, "hCR" USE_FEATURE_VI_COLON("c:"))) != -1) {
    318359        switch (c) {
    319 #ifdef CONFIG_FEATURE_VI_CRASHME
     360#if ENABLE_FEATURE_VI_CRASHME
    320361        case 'C':
    321362            crashme = 1;
    322363            break;
    323 #endif                          /* CONFIG_FEATURE_VI_CRASHME */
    324 #ifdef CONFIG_FEATURE_VI_READONLY
     364#endif
     365#if ENABLE_FEATURE_VI_READONLY
    325366        case 'R':       // Read-only flag
    326             readonly = TRUE;
    327             vi_readonly = TRUE;
     367            SET_READONLY_MODE(readonly_mode);
    328368            break;
    329 #endif                          /* CONFIG_FEATURE_VI_READONLY */
     369#endif
    330370            //case 'r': // recover flag-  ignore- we don't use tmp file
    331371            //case 'x': // encryption flag- ignore
    332372            //case 'c': // execute command first
     373#if ENABLE_FEATURE_VI_COLON
     374        case 'c':       // cmd line vi command
     375            if (*optarg)
     376                initial_cmds[initial_cmds[0] != 0] = xstrdup(optarg);
     377            break;
    333378            //case 'h': // help -- just use default
     379#endif
    334380        default:
    335381            show_help();
     
    345391    //----- This is the main file handling loop --------------
    346392    if (optind >= argc) {
    347         editing = 1;    // 0= exit,  1= one file,  2= multiple files
    348393        edit_file(0);
    349394    } else {
    350395        for (; optind < argc; optind++) {
    351             editing = 1;    // 0=exit, 1=one file, 2+ =many files
    352             free(cfn);
    353             cfn = (Byte *) bb_xstrdup(argv[optind]);
    354             edit_file(cfn);
     396            edit_file(argv[optind]);
    355397        }
    356398    }
    357399    //-----------------------------------------------------------
    358400
    359     return (0);
    360 }
    361 
    362 static void edit_file(Byte * fn)
    363 {
    364     Byte c;
    365     int cnt, size, ch;
    366 
    367 #ifdef CONFIG_FEATURE_VI_USE_SIGNALS
     401    return 0;
     402}
     403
     404/* read text from file or create an empty buf */
     405/* will also update current_filename */
     406static int init_text_buffer(char *fn)
     407{
     408    int rc;
     409    int size = file_size(fn);   // file size. -1 means does not exist.
     410
     411    /* allocate/reallocate text buffer */
     412    free(text);
     413    text_size = size * 2;
     414    if (text_size < 10240)
     415        text_size = 10240;  // have a minimum size for new files
     416    screenbegin = dot = end = text = xzalloc(text_size);
     417
     418    if (fn != current_filename) {
     419        free(current_filename);
     420        current_filename = xstrdup(fn);
     421    }
     422    if (size < 0) {
     423        // file dont exist. Start empty buf with dummy line
     424        char_insert(text, '\n');
     425        rc = 0;
     426    } else {
     427        rc = file_insert(fn, text
     428            USE_FEATURE_VI_READONLY(, 1));
     429    }
     430    file_modified = 0;
     431    last_file_modified = -1;
     432#if ENABLE_FEATURE_VI_YANKMARK
     433    /* init the marks. */
     434    memset(mark, 0, sizeof(mark));
     435#endif
     436    return rc;
     437}
     438
     439static void edit_file(char * fn)
     440{
     441    char c;
     442    int size;
     443
     444#if ENABLE_FEATURE_VI_USE_SIGNALS
    368445    int sig;
    369 #endif                          /* CONFIG_FEATURE_VI_USE_SIGNALS */
    370 #ifdef CONFIG_FEATURE_VI_YANKMARK
    371     static Byte *cur_line;
    372 #endif                          /* CONFIG_FEATURE_VI_YANKMARK */
    373 
     446#endif
     447#if ENABLE_FEATURE_VI_YANKMARK
     448    static char *cur_line;
     449#endif
     450
     451    editing = 1;    // 0= exit,  1= one file, 2= multiple files
    374452    rawmode();
    375453    rows = 24;
    376454    columns = 80;
    377     ch= -1;
     455    size = 0;
    378456    if (ENABLE_FEATURE_VI_WIN_RESIZE)
    379457        get_terminal_width_height(0, &columns, &rows);
    380458    new_screen(rows, columns);  // get memory for virtual screen
    381 
    382     cnt = file_size(fn);    // file size
    383     size = 2 * cnt;     // 200% of file size
    384     new_text(size);     // get a text[] buffer
    385     screenbegin = dot = end = text;
    386     if (fn != 0) {
    387         ch= file_insert(fn, text, cnt);
    388     }
    389     if (ch < 1) {
    390         (void) char_insert(text, '\n'); // start empty buf with dummy line
    391     }
    392     file_modified = 0;
    393     last_file_modified = -1;
    394 #ifdef CONFIG_FEATURE_VI_YANKMARK
     459    init_text_buffer(fn);
     460
     461#if ENABLE_FEATURE_VI_YANKMARK
    395462    YDreg = 26;         // default Yank/Delete reg
    396463    Ureg = 27;          // hold orig line for "U" cmd
    397     for (cnt = 0; cnt < 28; cnt++) {
    398         mark[cnt] = 0;
    399     }                   // init the marks
    400464    mark[26] = mark[27] = text; // init "previous context"
    401 #endif                          /* CONFIG_FEATURE_VI_YANKMARK */
     465#endif
    402466
    403467    last_forward_char = last_input_char = '\0';
     
    405469    ccol = 0;
    406470
    407 #ifdef CONFIG_FEATURE_VI_USE_SIGNALS
     471#if ENABLE_FEATURE_VI_USE_SIGNALS
    408472    catch_sig(0);
    409473    signal(SIGWINCH, winch_sig);
     
    413477        screenbegin = dot = text;
    414478    }
    415 #endif                          /* CONFIG_FEATURE_VI_USE_SIGNALS */
    416 
    417     editing = 1;
     479#endif
     480
    418481    cmd_mode = 0;       // 0=command  1=insert  2='R'eplace
    419482    cmdcnt = 0;
     
    421484    offset = 0;         // no horizontal offset
    422485    c = '\0';
    423 #ifdef CONFIG_FEATURE_VI_DOT_CMD
     486#if ENABLE_FEATURE_VI_DOT_CMD
    424487    free(last_modifying_cmd);
    425488    free(ioq_start);
    426     ioq = ioq_start = last_modifying_cmd = 0;
     489    ioq = ioq_start = last_modifying_cmd = NULL;
    427490    adding2q = 0;
    428 #endif                          /* CONFIG_FEATURE_VI_DOT_CMD */
     491#endif
    429492    redraw(FALSE);          // dont force every col re-draw
    430     show_status_line();
    431 
     493
     494#if ENABLE_FEATURE_VI_COLON
     495    {
     496        char *p, *q;
     497        int n = 0;
     498
     499        while ((p = initial_cmds[n])) {
     500            do {
     501                q = p;
     502                p = strchr(q,'\n');
     503                if (p)
     504                    while (*p == '\n')
     505                        *p++ = '\0';
     506                if (*q)
     507                    colon(q);
     508            } while (p);
     509            free(initial_cmds[n]);
     510            initial_cmds[n] = NULL;
     511            n++;
     512        }
     513    }
     514#endif
    432515    //------This is the main Vi cmd handling loop -----------------------
    433516    while (editing > 0) {
    434 #ifdef CONFIG_FEATURE_VI_CRASHME
     517#if ENABLE_FEATURE_VI_CRASHME
    435518        if (crashme > 0) {
    436519            if ((end - text) > 1) {
     
    438521            } else {
    439522                crashme = 0;
    440                 dot =
    441                     string_insert(text, (Byte *) "\n\n#####  Ran out of text to work on.  #####\n\n");  // insert the string
     523                dot = string_insert(text, "\n\n#####  Ran out of text to work on.  #####\n\n"); // insert the string
    442524                refresh(FALSE);
    443525            }
    444526        }
    445 #endif                          /* CONFIG_FEATURE_VI_CRASHME */
     527#endif
    446528        last_input_char = c = get_one_char();   // get a cmd from user
    447 #ifdef CONFIG_FEATURE_VI_YANKMARK
     529#if ENABLE_FEATURE_VI_YANKMARK
    448530        // save a copy of the current line- for the 'U" command
    449531        if (begin_line(dot) != cur_line) {
     
    451533            text_yank(begin_line(dot), end_line(dot), Ureg);
    452534        }
    453 #endif                          /* CONFIG_FEATURE_VI_YANKMARK */
    454 #ifdef CONFIG_FEATURE_VI_DOT_CMD
     535#endif
     536#if ENABLE_FEATURE_VI_DOT_CMD
    455537        // These are commands that change text[].
    456538        // Remember the input for the "." command
    457539        if (!adding2q && ioq_start == 0
    458             && strchr((char *) modifying_cmds, c) != NULL) {
     540         && strchr(modifying_cmds, c)
     541        ) {
    459542            start_new_cmd_q(c);
    460543        }
    461 #endif                          /* CONFIG_FEATURE_VI_DOT_CMD */
     544#endif
    462545        do_cmd(c);      // execute the user command
    463546        //
     
    470553            show_status_line();
    471554        }
    472 #ifdef CONFIG_FEATURE_VI_CRASHME
     555#if ENABLE_FEATURE_VI_CRASHME
    473556        if (crashme > 0)
    474557            crash_test();   // test editor variables
    475 #endif                          /* CONFIG_FEATURE_VI_CRASHME */
     558#endif
    476559    }
    477560    //-------------------------------------------------------------------
     
    483566
    484567//----- The Colon commands -------------------------------------
    485 #ifdef CONFIG_FEATURE_VI_COLON
    486 static Byte *get_one_address(Byte * p, int *addr)   // get colon addr, if present
     568#if ENABLE_FEATURE_VI_COLON
     569static char *get_one_address(char * p, int *addr)   // get colon addr, if present
    487570{
    488571    int st;
    489     Byte *q;
    490 
    491 #ifdef CONFIG_FEATURE_VI_YANKMARK
    492     Byte c;
    493 #endif                          /* CONFIG_FEATURE_VI_YANKMARK */
    494 #ifdef CONFIG_FEATURE_VI_SEARCH
    495     Byte *pat, buf[BUFSIZ];
    496 #endif                          /* CONFIG_FEATURE_VI_SEARCH */
     572    char *q;
     573
     574#if ENABLE_FEATURE_VI_YANKMARK
     575    char c;
     576#endif
     577#if ENABLE_FEATURE_VI_SEARCH
     578    char *pat, buf[MAX_LINELEN];
     579#endif
    497580
    498581    *addr = -1;         // assume no addr
     
    501584        q = begin_line(dot);
    502585        *addr = count_lines(text, q);
    503 #ifdef CONFIG_FEATURE_VI_YANKMARK
     586#if ENABLE_FEATURE_VI_YANKMARK
    504587    } else if (*p == '\'') {    // is this a mark addr
    505588        p++;
     
    509592            // we have a mark
    510593            c = c - 'a';
    511             q = mark[(int) c];
     594            q = mark[(unsigned char) c];
    512595            if (q != NULL) {    // is mark valid
    513596                *addr = count_lines(text, q);   // count lines
    514597            }
    515598        }
    516 #endif                          /* CONFIG_FEATURE_VI_YANKMARK */
    517 #ifdef CONFIG_FEATURE_VI_SEARCH
     599#endif
     600#if ENABLE_FEATURE_VI_SEARCH
    518601    } else if (*p == '/') { // a search pattern
    519602        q = buf;
     
    524607            *q = '\0';
    525608        }
    526         pat = (Byte *) bb_xstrdup((char *) buf);    // save copy of pattern
     609        pat = xstrdup(buf); // save copy of pattern
    527610        if (*p == '/')
    528611            p++;
     
    532615        }
    533616        free(pat);
    534 #endif                          /* CONFIG_FEATURE_VI_SEARCH */
     617#endif
    535618    } else if (*p == '$') { // the last line in file
    536619        p++;
     
    538621        *addr = count_lines(text, q);
    539622    } else if (isdigit(*p)) {   // specific line number
    540         sscanf((char *) p, "%d%n", addr, &st);
     623        sscanf(p, "%d%n", addr, &st);
    541624        p += st;
    542625    } else {            // I don't reconise this
     
    544627        *addr = -1;
    545628    }
    546     return (p);
    547 }
    548 
    549 static Byte *get_address(Byte *p, int *b, int *e)   // get two colon addrs, if present
     629    return p;
     630}
     631
     632static char *get_address(char *p, int *b, int *e)   // get two colon addrs, if present
    550633{
    551634    //----- get the address' i.e., 1,3   'a,'b  -----
    552635    // get FIRST addr, if present
    553     while (isblnk(*p))
     636    while (isblank(*p))
    554637        p++;                // skip over leading spaces
    555638    if (*p == '%') {            // alias for 1,$
     
    560643    }
    561644    p = get_one_address(p, b);
    562     while (isblnk(*p))
     645    while (isblank(*p))
    563646        p++;
    564647    if (*p == ',') {            // is there a address separator
    565648        p++;
    566         while (isblnk(*p))
     649        while (isblank(*p))
    567650            p++;
    568651        // get SECOND addr, if present
    569652        p = get_one_address(p, e);
    570653    }
    571 ga0:
    572     while (isblnk(*p))
     654 ga0:
     655    while (isblank(*p))
    573656        p++;                // skip over trailing spaces
    574     return (p);
    575 }
    576 
    577 #ifdef CONFIG_FEATURE_VI_SETOPTS
    578 static void setops(const Byte *args, const char *opname, int flg_no,
     657    return p;
     658}
     659
     660#if ENABLE_FEATURE_VI_SET && ENABLE_FEATURE_VI_SETOPTS
     661static void setops(const char *args, const char *opname, int flg_no,
    579662            const char *short_opname, int opt)
    580663{
    581     const char *a = (char *) args + flg_no;
     664    const char *a = args + flg_no;
    582665    int l = strlen(opname) - 1; /* opname have + ' ' */
    583666
    584     if (strncasecmp(a, opname, l) == 0 ||
    585             strncasecmp(a, short_opname, 2) == 0) {
    586         if(flg_no)
     667    if (strncasecmp(a, opname, l) == 0
     668     || strncasecmp(a, short_opname, 2) == 0
     669    ) {
     670        if (flg_no)
    587671            vi_setops &= ~opt;
    588          else
     672        else
    589673            vi_setops |= opt;
    590674    }
     
    592676#endif
    593677
    594 static void colon(Byte * buf)
    595 {
    596     Byte c, *orig_buf, *buf1, *q, *r;
    597     Byte *fn, cmd[BUFSIZ], args[BUFSIZ];
    598     int i, l, li, ch, st, b, e;
     678static void colon(char * buf)
     679{
     680    char c, *orig_buf, *buf1, *q, *r;
     681    char *fn, cmd[MAX_LINELEN], args[MAX_LINELEN];
     682    int i, l, li, ch, b, e;
    599683    int useforce = FALSE, forced = FALSE;
    600     struct stat st_buf;
    601684
    602685    // :3154    // if (-e line 3154) goto it  else stay put
     
    615698    //
    616699
    617     if (strlen((char *) buf) <= 0)
     700    if (!buf[0])
    618701        goto vc1;
    619702    if (*buf == ':')
    620703        buf++;          // move past the ':'
    621704
    622     li = st = ch = i = 0;
     705    li = ch = i = 0;
    623706    b = e = -1;
    624707    q = text;           // assume 1,$ for the range
    625708    r = end - 1;
    626709    li = count_lines(text, end - 1);
    627     fn = cfn;           // default to current file
    628     memset(cmd, '\0', BUFSIZ);  // clear cmd[]
    629     memset(args, '\0', BUFSIZ); // clear args[]
     710    fn = current_filename;          // default to current file
     711    memset(cmd, '\0', MAX_LINELEN); // clear cmd[]
     712    memset(args, '\0', MAX_LINELEN);    // clear args[]
    630713
    631714    // look for optional address(es)  :.  :1  :1,9   :'q,'a   :%
     
    643726    }
    644727    // get any ARGuments
    645     while (isblnk(*buf))
     728    while (isblank(*buf))
    646729        buf++;
    647     strcpy((char *) args, (char *) buf);
    648     buf1 = (Byte*)last_char_is((char *)cmd, '!');
     730    strcpy(args, buf);
     731    buf1 = last_char_is(cmd, '!');
    649732    if (buf1) {
    650733        useforce = TRUE;
     
    668751    }
    669752    // ------------ now look for the command ------------
    670     i = strlen((char *) cmd);
     753    i = strlen(cmd);
    671754    if (i == 0) {       // :123CR goto line #123
    672755        if (b >= 0) {
     
    674757            dot_skip_over_ws();
    675758        }
    676     } else if (strncmp((char *) cmd, "!", 1) == 0) {    // run a cmd
     759    }
     760#if ENABLE_FEATURE_ALLOW_EXEC
     761    else if (strncmp(cmd, "!", 1) == 0) {   // run a cmd
     762        int retcode;
    677763        // :!ls   run the <cmd>
    678         (void) alarm(0);        // wait for input- no alarms
     764        alarm(0);       // wait for input- no alarms
    679765        place_cursor(rows - 1, 0, FALSE);   // go to Status line
    680766        clear_to_eol();         // clear the line
    681767        cookmode();
    682         system((char*)(orig_buf+1));        // run the cmd
     768        retcode = system(orig_buf + 1); // run the cmd
     769        if (retcode)
     770            printf("\nshell returned %i\n\n", retcode);
    683771        rawmode();
    684772        Hit_Return();           // let user see results
    685         (void) alarm(3);        // done waiting for input
    686     } else if (strncmp((char *) cmd, "=", i) == 0) {    // where is the address
     773        alarm(3);       // done waiting for input
     774    }
     775#endif
     776    else if (strncmp(cmd, "=", i) == 0) {   // where is the address
    687777        if (b < 0) {    // no addr given- use defaults
    688778            b = e = count_lines(text, dot);
    689779        }
    690780        psb("%d", b);
    691     } else if (strncasecmp((char *) cmd, "delete", i) == 0) {   // delete lines
     781    } else if (strncasecmp(cmd, "delete", i) == 0) {    // delete lines
    692782        if (b < 0) {    // no addr given- use defaults
    693783            q = begin_line(dot);    // assume .,. for the range
     
    696786        dot = yank_delete(q, r, 1, YANKDEL);    // save, then delete lines
    697787        dot_skip_over_ws();
    698     } else if (strncasecmp((char *) cmd, "edit", i) == 0) { // Edit a file
    699         int sr;
    700         sr= 0;
     788    } else if (strncasecmp(cmd, "edit", i) == 0) {  // Edit a file
    701789        // don't edit, if the current file has been modified
    702790        if (file_modified && ! useforce) {
     
    704792            goto vc1;
    705793        }
    706         if (strlen((char*)args) > 0) {
     794        if (args[0]) {
    707795            // the user supplied a file name
    708             fn= args;
    709         } else if (cfn != 0 && strlen((char*)cfn) > 0) {
     796            fn = args;
     797        } else if (current_filename && current_filename[0]) {
    710798            // no user supplied name- use the current filename
    711             fn= cfn;
    712             goto vc5;
     799            // fn = current_filename;  was set by default
    713800        } else {
    714801            // no user file name, no current name- punt
     
    717804        }
    718805
    719         // see if file exists- if not, its just a new file request
    720         if ((sr=stat((char*)fn, &st_buf)) < 0) {
    721             // This is just a request for a new file creation.
    722             // The file_insert below will fail but we get
    723             // an empty buffer with a file name.  Then the "write"
    724             // command can do the create.
    725         } else {
    726             if ((st_buf.st_mode & (S_IFREG)) == 0) {
    727                 // This is not a regular file
    728                 psbs("\"%s\" is not a regular file", fn);
    729                 goto vc1;
    730             }
    731             if ((st_buf.st_mode & (S_IRUSR | S_IRGRP | S_IROTH)) == 0) {
    732                 // dont have any read permissions
    733                 psbs("\"%s\" is not readable", fn);
    734                 goto vc1;
    735             }
    736         }
    737 
    738         // There is a read-able regular file
    739         // make this the current file
    740         q = (Byte *) bb_xstrdup((char *) fn);   // save the cfn
    741         free(cfn);      // free the old name
    742         cfn = q;            // remember new cfn
    743 
    744       vc5:
    745         // delete all the contents of text[]
    746         new_text(2 * file_size(fn));
    747         screenbegin = dot = end = text;
    748 
    749         // insert new file
    750         ch = file_insert(fn, text, file_size(fn));
    751 
    752         if (ch < 1) {
    753             // start empty buf with dummy line
    754             (void) char_insert(text, '\n');
    755             ch= 1;
    756         }
    757         file_modified = 0;
    758         last_file_modified = -1;
    759 #ifdef CONFIG_FEATURE_VI_YANKMARK
     806        if (init_text_buffer(fn) < 0)
     807            goto vc1;
     808
     809#if ENABLE_FEATURE_VI_YANKMARK
    760810        if (Ureg >= 0 && Ureg < 28 && reg[Ureg] != 0) {
    761811            free(reg[Ureg]);    //   free orig line reg- for 'U'
     
    766816            reg[YDreg]= 0;
    767817        }
    768         for (li = 0; li < 28; li++) {
    769             mark[li] = 0;
    770         }               // init the marks
    771 #endif                          /* CONFIG_FEATURE_VI_YANKMARK */
     818#endif
    772819        // how many lines in text[]?
    773820        li = count_lines(text, end - 1);
    774821        psb("\"%s\"%s"
    775 #ifdef CONFIG_FEATURE_VI_READONLY
    776             "%s"
    777 #endif                          /* CONFIG_FEATURE_VI_READONLY */
    778             " %dL, %dC", cfn,
    779             (sr < 0 ? " [New file]" : ""),
    780 #ifdef CONFIG_FEATURE_VI_READONLY
    781             ((vi_readonly || readonly) ? " [Read only]" : ""),
    782 #endif                          /* CONFIG_FEATURE_VI_READONLY */
     822            USE_FEATURE_VI_READONLY("%s")
     823            " %dL, %dC", current_filename,
     824            (file_size(fn) < 0 ? " [New file]" : ""),
     825            USE_FEATURE_VI_READONLY(
     826                ((readonly_mode) ? " [Readonly]" : ""),
     827            )
    783828            li, ch);
    784     } else if (strncasecmp((char *) cmd, "file", i) == 0) { // what File is this
     829    } else if (strncasecmp(cmd, "file", i) == 0) {  // what File is this
    785830        if (b != -1 || e != -1) {
    786             ni((Byte *) "No address allowed on this command");
     831            ni("No address allowed on this command");
    787832            goto vc1;
    788833        }
    789         if (strlen((char *) args) > 0) {
     834        if (args[0]) {
    790835            // user wants a new filename
    791             free(cfn);
    792             cfn = (Byte *) bb_xstrdup((char *) args);
     836            free(current_filename);
     837            current_filename = xstrdup(args);
    793838        } else {
    794839            // user wants file status info
    795840            last_status_cksum = 0;  // force status update
    796841        }
    797     } else if (strncasecmp((char *) cmd, "features", i) == 0) { // what features are available
     842    } else if (strncasecmp(cmd, "features", i) == 0) {  // what features are available
    798843        // print out values of all features
    799844        place_cursor(rows - 1, 0, FALSE);   // go to Status line, bottom of screen
     
    803848        rawmode();
    804849        Hit_Return();
    805     } else if (strncasecmp((char *) cmd, "list", i) == 0) { // literal print line
     850    } else if (strncasecmp(cmd, "list", i) == 0) {  // literal print line
    806851        if (b < 0) {    // no addr given- use defaults
    807852            q = begin_line(dot);    // assume .,. for the range
     
    815860
    816861            c = *q;
    817             c_is_no_print = c > 127 && !Isprint(c);
     862            c_is_no_print = (c & 0x80) && !Isprint(c);
    818863            if (c_is_no_print) {
    819864                c = '.';
     
    824869            } else if (c < ' ' || c == 127) {
    825870                putchar('^');
    826                 if(c == 127)
     871                if (c == 127)
    827872                    c = '?';
    828                  else
    829                 c += '@';
     873                else
     874                    c += '@';
    830875            }
    831876            putchar(c);
     
    833878                standout_end();
    834879        }
    835 #ifdef CONFIG_FEATURE_VI_SET
    836       vc2:
    837 #endif                          /* CONFIG_FEATURE_VI_SET */
     880#if ENABLE_FEATURE_VI_SET
     881 vc2:
     882#endif
    838883        Hit_Return();
    839     } else if ((strncasecmp((char *) cmd, "quit", i) == 0) ||   // Quit
    840                (strncasecmp((char *) cmd, "next", i) == 0)) {   // edit next file
     884    } else if (strncasecmp(cmd, "quit", i) == 0 // Quit
     885            || strncasecmp(cmd, "next", i) == 0 // edit next file
     886    ) {
    841887        if (useforce) {
    842888            // force end of argv list
     
    863909        }
    864910        editing = 0;
    865     } else if (strncasecmp((char *) cmd, "read", i) == 0) { // read file into text[]
     911    } else if (strncasecmp(cmd, "read", i) == 0) {  // read file into text[]
    866912        fn = args;
    867         if (strlen((char *) fn) <= 0) {
     913        if (!fn[0]) {
    868914            psbs("No filename given");
    869915            goto vc1;
     
    875921        if (b != 0)
    876922            q = next_line(q);
    877 #ifdef CONFIG_FEATURE_VI_READONLY
    878         l= readonly;            // remember current files' status
    879 #endif
    880         ch = file_insert(fn, q, file_size(fn));
    881 #ifdef CONFIG_FEATURE_VI_READONLY
    882         readonly= l;
    883 #endif
     923        ch = file_insert(fn, q  USE_FEATURE_VI_READONLY(, 0));
    884924        if (ch < 0)
    885925            goto vc1;   // nothing was inserted
     
    887927        li = count_lines(q, q + ch - 1);
    888928        psb("\"%s\""
    889 #ifdef CONFIG_FEATURE_VI_READONLY
    890             "%s"
    891 #endif                          /* CONFIG_FEATURE_VI_READONLY */
     929            USE_FEATURE_VI_READONLY("%s")
    892930            " %dL, %dC", fn,
    893 #ifdef CONFIG_FEATURE_VI_READONLY
    894             ((vi_readonly || readonly) ? " [Read only]" : ""),
    895 #endif                          /* CONFIG_FEATURE_VI_READONLY */
     931            USE_FEATURE_VI_READONLY((readonly_mode ? " [Readonly]" : ""),)
    896932            li, ch);
    897933        if (ch > 0) {
     
    901937            file_modified++;
    902938        }
    903     } else if (strncasecmp((char *) cmd, "rewind", i) == 0) {   // rewind cmd line args
     939    } else if (strncasecmp(cmd, "rewind", i) == 0) {    // rewind cmd line args
    904940        if (file_modified && ! useforce) {
    905941            psbs("No write since last change (:rewind! overrides)");
     
    909945            editing = 0;
    910946        }
    911 #ifdef CONFIG_FEATURE_VI_SET
    912     } else if (strncasecmp((char *) cmd, "set", i) == 0) {  // set or clear features
     947#if ENABLE_FEATURE_VI_SET
     948    } else if (strncasecmp(cmd, "set", i) == 0) {   // set or clear features
     949#if ENABLE_FEATURE_VI_SETOPTS
     950        char *argp;
     951#endif
    913952        i = 0;          // offset into args
    914         if (strlen((char *) args) == 0) {
     953        // only blank is regarded as args delmiter. What about tab '\t' ?
     954        if (!args[0] || strcasecmp(args, "all") == 0) {
    915955            // print out values of all options
    916956            place_cursor(rows - 1, 0, FALSE);   // go to Status line, bottom of screen
    917957            clear_to_eol(); // clear the line
    918958            printf("----------------------------------------\r\n");
    919 #ifdef CONFIG_FEATURE_VI_SETOPTS
     959#if ENABLE_FEATURE_VI_SETOPTS
    920960            if (!autoindent)
    921961                printf("no");
     
    931971            printf("showmatch ");
    932972            printf("tabstop=%d ", tabstop);
    933 #endif                          /* CONFIG_FEATURE_VI_SETOPTS */
     973#endif
    934974            printf("\r\n");
    935975            goto vc2;
    936976        }
    937         if (strncasecmp((char *) args, "no", 2) == 0)
    938             i = 2;      // ":set noautoindent"
    939 #ifdef CONFIG_FEATURE_VI_SETOPTS
    940         setops(args, "autoindent ", i, "ai", VI_AUTOINDENT);
    941         setops(args, "flash ", i, "fl", VI_ERR_METHOD);
    942         setops(args, "ignorecase ", i, "ic", VI_IGNORECASE);
    943         setops(args, "showmatch ", i, "ic", VI_SHOWMATCH);
    944         if (strncasecmp((char *) args + i, "tabstop=%d ", 7) == 0) {
    945             sscanf(strchr((char *) args + i, '='), "=%d", &ch);
    946             if (ch > 0 && ch < columns - 1)
    947                 tabstop = ch;
    948         }
    949 #endif                          /* CONFIG_FEATURE_VI_SETOPTS */
    950 #endif                          /* CONFIG_FEATURE_VI_SET */
    951 #ifdef CONFIG_FEATURE_VI_SEARCH
    952     } else if (strncasecmp((char *) cmd, "s", 1) == 0) {    // substitute a pattern with a replacement pattern
    953         Byte *ls, *F, *R;
     977#if ENABLE_FEATURE_VI_SETOPTS
     978        argp = args;
     979        while (*argp) {
     980            if (strncasecmp(argp, "no", 2) == 0)
     981                i = 2;      // ":set noautoindent"
     982            setops(argp, "autoindent ", i, "ai", VI_AUTOINDENT);
     983            setops(argp, "flash ", i, "fl", VI_ERR_METHOD);
     984            setops(argp, "ignorecase ", i, "ic", VI_IGNORECASE);
     985            setops(argp, "showmatch ", i, "ic", VI_SHOWMATCH);
     986            /* tabstopXXXX */
     987            if (strncasecmp(argp + i, "tabstop=%d ", 7) == 0) {
     988                sscanf(strchr(argp + i, '='), "tabstop=%d" + 7, &ch);
     989                if (ch > 0 && ch < columns - 1)
     990                    tabstop = ch;
     991            }
     992            while (*argp && *argp != ' ')
     993                argp++; // skip to arg delimiter (i.e. blank)
     994            while (*argp && *argp == ' ')
     995                argp++; // skip all delimiting blanks
     996        }
     997#endif /* FEATURE_VI_SETOPTS */
     998#endif /* FEATURE_VI_SET */
     999#if ENABLE_FEATURE_VI_SEARCH
     1000    } else if (strncasecmp(cmd, "s", 1) == 0) { // substitute a pattern with a replacement pattern
     1001        char *ls, *F, *R;
    9541002        int gflag;
    9551003
     
    9601008        c = orig_buf[1];    // what is the delimiter
    9611009        F = orig_buf + 2;   // start of "find"
    962         R = (Byte *) strchr((char *) F, c); // middle delimiter
     1010        R = strchr(F, c);   // middle delimiter
    9631011        if (!R) goto colon_s_fail;
    9641012        *R++ = '\0';    // terminate "find"
    965         buf1 = (Byte *) strchr((char *) R, c);
     1013        buf1 = strchr(R, c);
    9661014        if (!buf1) goto colon_s_fail;
    9671015        *buf1++ = '\0'; // terminate "replace"
     
    9791027        for (i = b; i <= e; i++) {  // so, :20,23 s \0 find \0 replace \0
    9801028            ls = q;     // orig line start
    981           vc4:
     1029 vc4:
    9821030            buf1 = char_search(q, F, FORWARD, LIMITED); // search cur line only for "find"
    983             if (buf1 != NULL) {
    984                 // we found the "find" pattern- delete it
    985                 (void) text_hole_delete(buf1, buf1 + strlen((char *) F) - 1);
     1031            if (buf1) {
     1032                // we found the "find" pattern - delete it
     1033                text_hole_delete(buf1, buf1 + strlen(F) - 1);
    9861034                // inset the "replace" patern
    987                 (void) string_insert(buf1, R);  // insert the string
     1035                string_insert(buf1, R); // insert the string
    9881036                // check for "global"  :s/foo/bar/g
    9891037                if (gflag == 1) {
    990                     if ((buf1 + strlen((char *) R)) < end_line(ls)) {
    991                         q = buf1 + strlen((char *) R);
     1038                    if ((buf1 + strlen(R)) < end_line(ls)) {
     1039                        q = buf1 + strlen(R);
    9921040                        goto vc4;   // don't let q move past cur line
    9931041                    }
     
    9961044            q = next_line(ls);
    9971045        }
    998 #endif                          /* CONFIG_FEATURE_VI_SEARCH */
    999     } else if (strncasecmp((char *) cmd, "version", i) == 0) {  // show software version
    1000         psb("%s", vi_Version);
    1001     } else if (strncasecmp((char *) cmd, "write", i) == 0       // write text to file
    1002             || strncasecmp((char *) cmd, "wq", i) == 0
    1003             || strncasecmp((char *) cmd, "wn", i) == 0
    1004             || strncasecmp((char *) cmd, "x", i) == 0) {
     1046#endif /* FEATURE_VI_SEARCH */
     1047    } else if (strncasecmp(cmd, "version", i) == 0) {  // show software version
     1048        psb("%s", BB_VER " " BB_BT);
     1049    } else if (strncasecmp(cmd, "write", i) == 0  // write text to file
     1050            || strncasecmp(cmd, "wq", i) == 0
     1051            || strncasecmp(cmd, "wn", i) == 0
     1052            || strncasecmp(cmd, "x", i) == 0
     1053    ) {
    10051054        // is there a file name to write to?
    1006         if (strlen((char *) args) > 0) {
     1055        if (args[0]) {
    10071056            fn = args;
    10081057        }
    1009 #ifdef CONFIG_FEATURE_VI_READONLY
    1010         if ((vi_readonly || readonly) && ! useforce) {
     1058#if ENABLE_FEATURE_VI_READONLY
     1059        if (readonly_mode && !useforce) {
    10111060            psbs("\"%s\" File is read only", fn);
    10121061            goto vc3;
    10131062        }
    1014 #endif                          /* CONFIG_FEATURE_VI_READONLY */
     1063#endif
    10151064        // how many lines in text[]?
    10161065        li = count_lines(q, r);
     
    10321081        if (l < 0) {
    10331082            if (l == -1)
    1034                 psbs("Write error: %s", strerror(errno));
     1083                psbs("\"%s\" %s", fn, strerror(errno));
    10351084        } else {
    10361085            psb("\"%s\" %dL, %dC", fn, li, l);
     
    10451094            }
    10461095        }
    1047 #ifdef CONFIG_FEATURE_VI_READONLY
    1048       vc3:;
    1049 #endif                          /* CONFIG_FEATURE_VI_READONLY */
    1050 #ifdef CONFIG_FEATURE_VI_YANKMARK
    1051     } else if (strncasecmp((char *) cmd, "yank", i) == 0) { // yank lines
     1096#if ENABLE_FEATURE_VI_READONLY
     1097 vc3:;
     1098#endif
     1099#if ENABLE_FEATURE_VI_YANKMARK
     1100    } else if (strncasecmp(cmd, "yank", i) == 0) {  // yank lines
    10521101        if (b < 0) {    // no addr given- use defaults
    10531102            q = begin_line(dot);    // assume .,. for the range
     
    10571106        li = count_lines(q, r);
    10581107        psb("Yank %d lines (%d chars) into [%c]",
    1059             li, strlen((char *) reg[YDreg]), what_reg());
    1060 #endif                          /* CONFIG_FEATURE_VI_YANKMARK */
     1108                li, strlen(reg[YDreg]), what_reg());
     1109#endif
    10611110    } else {
    10621111        // cmd unknown
    1063         ni((Byte *) cmd);
    1064     }
    1065   vc1:
     1112        ni(cmd);
     1113    }
     1114 vc1:
    10661115    dot = bound_dot(dot);   // make sure "dot" is valid
    10671116    return;
    1068 #ifdef CONFIG_FEATURE_VI_SEARCH
    1069 colon_s_fail:
     1117#if ENABLE_FEATURE_VI_SEARCH
     1118 colon_s_fail:
    10701119    psb(":s expression missing delimiters");
    10711120#endif
    10721121}
    10731122
    1074 #endif                          /* CONFIG_FEATURE_VI_COLON */
     1123#endif /* FEATURE_VI_COLON */
    10751124
    10761125static void Hit_Return(void)
     
    10861135}
    10871136
     1137static int next_tabstop(int col)
     1138{
     1139    return col + ((tabstop - 1) - (col % tabstop));
     1140}
     1141
    10881142//----- Synchronize the cursor to Dot --------------------------
    1089 static void sync_cursor(Byte * d, int *row, int *col)
    1090 {
    1091     Byte *beg_cur;              // begin and end of "d" line
    1092     Byte *beg_scr, *end_scr;    // begin and end of screen
    1093     Byte *tp;
     1143static void sync_cursor(char * d, int *row, int *col)
     1144{
     1145    char *beg_cur;  // begin and end of "d" line
     1146    char *end_scr;  // begin and end of screen
     1147    char *tp;
    10941148    int cnt, ro, co;
    10951149
    10961150    beg_cur = begin_line(d);    // first char of cur line
    10971151
    1098     beg_scr = end_scr = screenbegin;    // first char of screen
    10991152    end_scr = end_screen(); // last char of screen
    11001153
     
    11031156        // how many lines do we have to move
    11041157        cnt = count_lines(beg_cur, screenbegin);
    1105       sc1:
     1158 sc1:
    11061159        screenbegin = beg_cur;
    11071160        if (cnt > (rows - 1) / 2) {
     
    11391192            break;
    11401193        if (*tp == '\t') {
    1141             //         7       - (co %    8  )
    1142             co += ((tabstop - 1) - (co % tabstop));
     1194            if (d == tp && cmd_mode) { /* handle tabs like real vi */
     1195                break;
     1196            } else {
     1197                co = next_tabstop(co);
     1198            }
    11431199        } else if (*tp < ' ' || *tp == 127) {
    11441200            co++;       // display as ^X, use 2 columns
     
    11771233
    11781234//----- Text Movement Routines ---------------------------------
    1179 static Byte *begin_line(Byte * p) // return pointer to first char cur line
     1235static char *begin_line(char * p) // return pointer to first char cur line
    11801236{
    11811237    while (p > text && p[-1] != '\n')
    11821238        p--;            // go to cur line B-o-l
    1183     return (p);
    1184 }
    1185 
    1186 static Byte *end_line(Byte * p) // return pointer to NL of cur line line
     1239    return p;
     1240}
     1241
     1242static char *end_line(char * p) // return pointer to NL of cur line line
    11871243{
    11881244    while (p < end - 1 && *p != '\n')
    11891245        p++;            // go to cur line E-o-l
    1190     return (p);
    1191 }
    1192 
    1193 static inline Byte *dollar_line(Byte * p) // return pointer to just before NL line
     1246    return p;
     1247}
     1248
     1249static inline char *dollar_line(char * p) // return pointer to just before NL line
    11941250{
    11951251    while (p < end - 1 && *p != '\n')
     
    11981254    if (*p == '\n' && (p - begin_line(p)) > 0)
    11991255        p--;
    1200     return (p);
    1201 }
    1202 
    1203 static Byte *prev_line(Byte * p) // return pointer first char prev line
     1256    return p;
     1257}
     1258
     1259static char *prev_line(char * p) // return pointer first char prev line
    12041260{
    12051261    p = begin_line(p);  // goto begining of cur line
     
    12071263        p--;            // step to prev line
    12081264    p = begin_line(p);  // goto begining of prev line
    1209     return (p);
    1210 }
    1211 
    1212 static Byte *next_line(Byte * p) // return pointer first char next line
     1265    return p;
     1266}
     1267
     1268static char *next_line(char * p) // return pointer first char next line
    12131269{
    12141270    p = end_line(p);
    12151271    if (*p == '\n' && p < end - 1)
    12161272        p++;            // step to next line
    1217     return (p);
     1273    return p;
    12181274}
    12191275
    12201276//----- Text Information Routines ------------------------------
    1221 static Byte *end_screen(void)
    1222 {
    1223     Byte *q;
     1277static char *end_screen(void)
     1278{
     1279    char *q;
    12241280    int cnt;
    12251281
     
    12291285        q = next_line(q);
    12301286    q = end_line(q);
    1231     return (q);
    1232 }
    1233 
    1234 static int count_lines(Byte * start, Byte * stop) // count line from start to stop
    1235 {
    1236     Byte *q;
     1287    return q;
     1288}
     1289
     1290static int count_lines(char * start, char * stop) // count line from start to stop
     1291{
     1292    char *q;
    12371293    int cnt;
    12381294
     
    12481304            cnt++;
    12491305    }
    1250     return (cnt);
    1251 }
    1252 
    1253 static Byte *find_line(int li)  // find begining of line #li
    1254 {
    1255     Byte *q;
     1306    return cnt;
     1307}
     1308
     1309static char *find_line(int li)  // find begining of line #li
     1310{
     1311    char *q;
    12561312
    12571313    for (q = text; li > 1; li--) {
    12581314        q = next_line(q);
    12591315    }
    1260     return (q);
     1316    return q;
    12611317}
    12621318
     
    12841340}
    12851341
    1286 static Byte *move_to_col(Byte * p, int l)
     1342static char *move_to_col(char * p, int l)
    12871343{
    12881344    int co;
     
    12941350            break;
    12951351        if (*p == '\t') {
    1296             //         7       - (co %    8  )
    1297             co += ((tabstop - 1) - (co % tabstop));
     1352            co = next_tabstop(co);
    12981353        } else if (*p < ' ' || *p == 127) {
    12991354            co++;       // display as ^X, use 2 columns
    13001355        }
    13011356    } while (++co <= l && p++ < end);
    1302     return (p);
     1357    return p;
    13031358}
    13041359
     
    13151370static void dot_scroll(int cnt, int dir)
    13161371{
    1317     Byte *q;
     1372    char *q;
    13181373
    13191374    for (; cnt > 0; cnt--) {
     
    13461401static void dot_delete(void)    // delete the char at 'dot'
    13471402{
    1348     (void) text_hole_delete(dot, dot);
    1349 }
    1350 
    1351 static Byte *bound_dot(Byte * p) // make sure  text[0] <= P < "end"
     1403    text_hole_delete(dot, dot);
     1404}
     1405
     1406static char *bound_dot(char * p) // make sure  text[0] <= P < "end"
    13521407{
    13531408    if (p >= end && end > text) {
     
    13591414        indicate_error('2');
    13601415    }
    1361     return (p);
     1416    return p;
    13621417}
    13631418
     
    13751430 */
    13761431
    1377 static Byte *new_screen(int ro, int co)
     1432static char *new_screen(int ro, int co)
    13781433{
    13791434    int li;
     
    13811436    free(screen);
    13821437    screensize = ro * co + 8;
    1383     screen = (Byte *) xmalloc(screensize);
     1438    screen = xmalloc(screensize);
    13841439    // initialize the new screen. assume this will be a empty file.
    13851440    screen_erase();
     
    13881443        screen[(li * co) + 0] = '~';
    13891444    }
    1390     return (screen);
    1391 }
    1392 
    1393 static Byte *new_text(int size)
    1394 {
    1395     if (size < 10240)
    1396         size = 10240;   // have a minimum size for new files
    1397     free(text);
    1398     text = (Byte *) xmalloc(size + 8);
    1399     memset(text, '\0', size);   // clear new text[]
    1400     //text += 4;        // leave some room for "oops"
    1401     textend = text + size - 1;
    1402     //textend -= 4;     // leave some root for "oops"
    1403     return (text);
    1404 }
    1405 
    1406 #ifdef CONFIG_FEATURE_VI_SEARCH
    1407 static int mycmp(Byte * s1, Byte * s2, int len)
     1445    return screen;
     1446}
     1447
     1448#if ENABLE_FEATURE_VI_SEARCH
     1449static int mycmp(const char * s1, const char * s2, int len)
    14081450{
    14091451    int i;
    14101452
    1411     i = strncmp((char *) s1, (char *) s2, len);
    1412 #ifdef CONFIG_FEATURE_VI_SETOPTS
    1413     if (ignorecase) {
    1414         i = strncasecmp((char *) s1, (char *) s2, len);
    1415     }
    1416 #endif                          /* CONFIG_FEATURE_VI_SETOPTS */
    1417     return (i);
    1418 }
    1419 
    1420 static Byte *char_search(Byte * p, Byte * pat, int dir, int range)  // search for pattern starting at p
     1453    i = strncmp(s1, s2, len);
     1454    if (ENABLE_FEATURE_VI_SETOPTS && ignorecase) {
     1455        i = strncasecmp(s1, s2, len);
     1456    }
     1457    return i;
     1458}
     1459
     1460// search for pattern starting at p
     1461static char *char_search(char * p, const char * pat, int dir, int range)
    14211462{
    14221463#ifndef REGEX_SEARCH
    1423     Byte *start, *stop;
     1464    char *start, *stop;
    14241465    int len;
    14251466
    1426     len = strlen((char *) pat);
     1467    len = strlen(pat);
    14271468    if (dir == FORWARD) {
    14281469        stop = end - 1; // assume range is p - end-1
     
    14311472        for (start = p; start < stop; start++) {
    14321473            if (mycmp(start, pat, len) == 0) {
    1433                 return (start);
     1474                return start;
    14341475            }
    14351476        }
     
    14401481        for (start = p - len; start >= stop; start--) {
    14411482            if (mycmp(start, pat, len) == 0) {
    1442                 return (start);
     1483                return start;
    14431484            }
    14441485        }
    14451486    }
    14461487    // pattern not found
    1447     return (NULL);
    1448 #else                           /*REGEX_SEARCH */
     1488    return NULL;
     1489#else /* REGEX_SEARCH */
    14491490    char *q;
    14501491    struct re_pattern_buffer preg;
     
    14731514    range = q - p;
    14741515
    1475     q = (char *) re_compile_pattern(pat, strlen((char *) pat), &preg);
     1516    q = re_compile_pattern(pat, strlen(pat), &preg);
    14761517    if (q != 0) {
    14771518        // The pattern was not compiled
     
    15001541        i = 0;          // return NULL if pattern not found
    15011542    }
    1502   cs1:
     1543 cs1:
    15031544    if (dir == FORWARD) {
    15041545        p = p + i;
     
    15061547        p = p - i;
    15071548    }
    1508     return (p);
    1509 #endif                          /*REGEX_SEARCH */
    1510 }
    1511 #endif                          /* CONFIG_FEATURE_VI_SEARCH */
    1512 
    1513 static Byte *char_insert(Byte * p, Byte c) // insert the char c at 'p'
     1549    return p;
     1550#endif /* REGEX_SEARCH */
     1551}
     1552#endif /* FEATURE_VI_SEARCH */
     1553
     1554static char *char_insert(char * p, char c) // insert the char c at 'p'
    15141555{
    15151556    if (c == 22) {      // Is this an ctrl-V?
     
    15261567        end_cmd_q();    // stop adding to q
    15271568        last_status_cksum = 0;  // force status update
    1528         if ((p[-1] != '\n') && (dot>text)) {
     1569        if ((p[-1] != '\n') && (dot > text)) {
    15291570            p--;
    15301571        }
     
    15371578    } else {
    15381579        // insert a char into text[]
    1539         Byte *sp;       // "save p"
     1580        char *sp;       // "save p"
    15401581
    15411582        if (c == 13)
     
    15431584        sp = p;         // remember addr of insert
    15441585        p = stupid_insert(p, c);    // insert the char
    1545 #ifdef CONFIG_FEATURE_VI_SETOPTS
     1586#if ENABLE_FEATURE_VI_SETOPTS
    15461587        if (showmatch && strchr(")]}", *sp) != NULL) {
    15471588            showmatching(sp);
    15481589        }
    15491590        if (autoindent && c == '\n') {  // auto indent the new line
    1550             Byte *q;
     1591            char *q;
    15511592
    15521593            q = prev_line(p);   // use prev line as templet
    1553             for (; isblnk(*q); q++) {
     1594            for (; isblank(*q); q++) {
    15541595                p = stupid_insert(p, *q);   // insert the char
    15551596            }
    15561597        }
    1557 #endif                          /* CONFIG_FEATURE_VI_SETOPTS */
    1558     }
    1559     return (p);
    1560 }
    1561 
    1562 static Byte *stupid_insert(Byte * p, Byte c) // stupidly insert the char c at 'p'
     1598#endif
     1599    }
     1600    return p;
     1601}
     1602
     1603static char *stupid_insert(char * p, char c) // stupidly insert the char c at 'p'
    15631604{
    15641605    p = text_hole_make(p, 1);
     
    15681609        p++;
    15691610    }
    1570     return (p);
    1571 }
    1572 
    1573 static Byte find_range(Byte ** start, Byte ** stop, Byte c)
    1574 {
    1575     Byte *save_dot, *p, *q;
     1611    return p;
     1612}
     1613
     1614static char find_range(char ** start, char ** stop, char c)
     1615{
     1616    char *save_dot, *p, *q;
    15761617    int cnt;
    15771618
     
    16251666    }
    16261667    dot = save_dot;
    1627     return (c);
    1628 }
    1629 
    1630 static int st_test(Byte * p, int type, int dir, Byte * tested)
    1631 {
    1632     Byte c, c0, ci;
     1668    return c;
     1669}
     1670
     1671static int st_test(char * p, int type, int dir, char * tested)
     1672{
     1673    char c, c0, ci;
    16331674    int test, inc;
    16341675
     
    16591700    }
    16601701    *tested = c;
    1661     return (test);
    1662 }
    1663 
    1664 static Byte *skip_thing(Byte * p, int linecnt, int dir, int type)
    1665 {
    1666     Byte c;
     1702    return test;
     1703}
     1704
     1705static char *skip_thing(char * p, int linecnt, int dir, int type)
     1706{
     1707    char c;
    16671708
    16681709    while (st_test(p, type, dir, &c)) {
     
    16761717        p += dir;       // move to next char
    16771718    }
    1678     return (p);
     1719    return p;
    16791720}
    16801721
    16811722// find matching char of pair  ()  []  {}
    1682 static Byte *find_pair(Byte * p, Byte c)
    1683 {
    1684     Byte match, *q;
     1723static char *find_pair(char * p, char c)
     1724{
     1725    char match, *q;
    16851726    int dir, level;
    16861727
     
    17221763    if (level != 0)
    17231764        q = NULL;       // indicate no match
    1724     return (q);
    1725 }
    1726 
    1727 #ifdef CONFIG_FEATURE_VI_SETOPTS
     1765    return q;
     1766}
     1767
     1768#if ENABLE_FEATURE_VI_SETOPTS
    17281769// show the matching char of a pair,  ()  []  {}
    1729 static void showmatching(Byte * p)
    1730 {
    1731     Byte *q, *save_dot;
     1770static void showmatching(char * p)
     1771{
     1772    char *q, *save_dot;
    17321773
    17331774    // we found half of a pair
     
    17401781        dot = q;        // go to new loc
    17411782        refresh(FALSE); // let the user see it
    1742         (void) mysleep(40); // give user some time
     1783        mysleep(40);    // give user some time
    17431784        dot = save_dot; // go back to old loc
    17441785        refresh(FALSE);
    17451786    }
    17461787}
    1747 #endif                          /* CONFIG_FEATURE_VI_SETOPTS */
     1788#endif /* FEATURE_VI_SETOPTS */
    17481789
    17491790//  open a hole in text[]
    1750 static Byte *text_hole_make(Byte * p, int size) // at "p", make a 'size' byte hole
    1751 {
    1752     Byte *src, *dest;
     1791static char *text_hole_make(char * p, int size) // at "p", make a 'size' byte hole
     1792{
     1793    char *src, *dest;
    17531794    int cnt;
    17541795
     
    17581799    dest = p + size;
    17591800    cnt = end - src;    // the rest of buffer
    1760     if (memmove(dest, src, cnt) != dest) {
     1801    if ( ((end + size) >= (text + text_size)) // TODO: realloc here
     1802            || memmove(dest, src, cnt) != dest) {
    17611803        psbs("can't create room for new characters");
     1804        p = NULL;
     1805        goto thm0;
    17621806    }
    17631807    memset(p, ' ', size);   // clear new hole
    1764     end = end + size;   // adjust the new END
     1808    end += size;        // adjust the new END
    17651809    file_modified++;    // has the file been modified
    1766   thm0:
    1767     return (p);
     1810 thm0:
     1811    return p;
    17681812}
    17691813
    17701814//  close a hole in text[]
    1771 static Byte *text_hole_delete(Byte * p, Byte * q) // delete "p" thru "q", inclusive
    1772 {
    1773     Byte *src, *dest;
     1815static char *text_hole_delete(char * p, char * q) // delete "p" thru "q", inclusive
     1816{
     1817    char *src, *dest;
    17741818    int cnt, hole_size;
    17751819
     
    17931837        psbs("can't delete the character");
    17941838    }
    1795   thd_atend:
     1839 thd_atend:
    17961840    end = end - hole_size;  // adjust the new END
    17971841    if (dest >= end)
     
    18001844        dest = end = text;  // keep pointers valid
    18011845    file_modified++;    // has the file been modified
    1802   thd0:
    1803     return (dest);
     1846 thd0:
     1847    return dest;
    18041848}
    18051849
     
    18071851// if dist <= 0, do not include, or go past, a NewLine
    18081852//
    1809 static Byte *yank_delete(Byte * start, Byte * stop, int dist, int yf)
    1810 {
    1811     Byte *p;
     1853static char *yank_delete(char * start, char * stop, int dist, int yf)
     1854{
     1855    char *p;
    18121856
    18131857    // make sure start <= stop
     
    18191863    }
    18201864    if (dist <= 0) {
    1821         // we can not cross NL boundaries
     1865        // we cannot cross NL boundaries
    18221866        p = start;
    18231867        if (*p == '\n')
    1824             return (p);
     1868            return p;
    18251869        // dont go past a NewLine
    18261870        for (; p + 1 <= stop; p++) {
     
    18321876    }
    18331877    p = start;
    1834 #ifdef CONFIG_FEATURE_VI_YANKMARK
     1878#if ENABLE_FEATURE_VI_YANKMARK
    18351879    text_yank(start, stop, YDreg);
    1836 #endif                          /* CONFIG_FEATURE_VI_YANKMARK */
     1880#endif
    18371881    if (yf == YANKDEL) {
    18381882        p = text_hole_delete(start, stop);
    18391883    }                   // delete lines
    1840     return (p);
     1884    return p;
    18411885}
    18421886
     
    18441888{
    18451889    puts("These features are available:"
    1846 #ifdef CONFIG_FEATURE_VI_SEARCH
     1890#if ENABLE_FEATURE_VI_SEARCH
    18471891    "\n\tPattern searches with / and ?"
    1848 #endif                          /* CONFIG_FEATURE_VI_SEARCH */
    1849 #ifdef CONFIG_FEATURE_VI_DOT_CMD
     1892#endif
     1893#if ENABLE_FEATURE_VI_DOT_CMD
    18501894    "\n\tLast command repeat with \'.\'"
    1851 #endif                          /* CONFIG_FEATURE_VI_DOT_CMD */
    1852 #ifdef CONFIG_FEATURE_VI_YANKMARK
     1895#endif
     1896#if ENABLE_FEATURE_VI_YANKMARK
    18531897    "\n\tLine marking with  'x"
    18541898    "\n\tNamed buffers with  \"x"
    1855 #endif                          /* CONFIG_FEATURE_VI_YANKMARK */
    1856 #ifdef CONFIG_FEATURE_VI_READONLY
     1899#endif
     1900#if ENABLE_FEATURE_VI_READONLY
    18571901    "\n\tReadonly if vi is called as \"view\""
    18581902    "\n\tReadonly with -R command line arg"
    1859 #endif                          /* CONFIG_FEATURE_VI_READONLY */
    1860 #ifdef CONFIG_FEATURE_VI_SET
     1903#endif
     1904#if ENABLE_FEATURE_VI_SET
    18611905    "\n\tSome colon mode commands with \':\'"
    1862 #endif                          /* CONFIG_FEATURE_VI_SET */
    1863 #ifdef CONFIG_FEATURE_VI_SETOPTS
     1906#endif
     1907#if ENABLE_FEATURE_VI_SETOPTS
    18641908    "\n\tSettable options with \":set\""
    1865 #endif                          /* CONFIG_FEATURE_VI_SETOPTS */
    1866 #ifdef CONFIG_FEATURE_VI_USE_SIGNALS
     1909#endif
     1910#if ENABLE_FEATURE_VI_USE_SIGNALS
    18671911    "\n\tSignal catching- ^C"
    18681912    "\n\tJob suspend and resume with ^Z"
    1869 #endif                          /* CONFIG_FEATURE_VI_USE_SIGNALS */
    1870 #ifdef CONFIG_FEATURE_VI_WIN_RESIZE
     1913#endif
     1914#if ENABLE_FEATURE_VI_WIN_RESIZE
    18711915    "\n\tAdapt to window re-sizes"
    1872 #endif                          /* CONFIG_FEATURE_VI_WIN_RESIZE */
     1916#endif
    18731917    );
    18741918}
    18751919
    1876 static inline void print_literal(Byte * buf, Byte * s) // copy s to buf, convert unprintable
    1877 {
    1878     Byte c, b[2];
     1920static inline void print_literal(char * buf, const char * s) // copy s to buf, convert unprintable
     1921{
     1922    unsigned char c;
     1923    char b[2];
    18791924
    18801925    b[1] = '\0';
    1881     strcpy((char *) buf, "");   // init buf
    1882     if (strlen((char *) s) <= 0)
    1883         s = (Byte *) "(NULL)";
    1884     for (; *s > '\0'; s++) {
     1926    buf[0] = '\0';
     1927    if (!s[0])
     1928        s = "(NULL)";
     1929    for (; *s; s++) {
    18851930        int c_is_no_print;
    18861931
    18871932        c = *s;
    1888         c_is_no_print = c > 127 && !Isprint(c);
     1933        c_is_no_print = (c & 0x80) && !Isprint(c);
    18891934        if (c_is_no_print) {
    1890             strcat((char *) buf, SOn);
     1935            strcat(buf, SOn);
    18911936            c = '.';
    18921937        }
    18931938        if (c < ' ' || c == 127) {
    1894             strcat((char *) buf, "^");
    1895             if(c == 127)
     1939            strcat(buf, "^");
     1940            if (c == 127)
    18961941                c = '?';
    1897              else
    1898             c += '@';
     1942            else
     1943                c += '@';
    18991944        }
    19001945        b[0] = c;
    1901         strcat((char *) buf, (char *) b);
     1946        strcat(buf, b);
    19021947        if (c_is_no_print)
    1903             strcat((char *) buf, SOs);
    1904         if (*s == '\n') {
    1905             strcat((char *) buf, "$");
    1906         }
    1907     }
    1908 }
    1909 
    1910 #ifdef CONFIG_FEATURE_VI_DOT_CMD
    1911 static void start_new_cmd_q(Byte c)
     1948            strcat(buf, SOs);
     1949        if (*s == '\n')
     1950            strcat(buf, "$");
     1951    }
     1952}
     1953
     1954#if ENABLE_FEATURE_VI_DOT_CMD
     1955static void start_new_cmd_q(char c)
    19121956{
    19131957    // release old cmd
    19141958    free(last_modifying_cmd);
    19151959    // get buffer for new cmd
    1916     last_modifying_cmd = (Byte *) xmalloc(BUFSIZ);
    1917     memset(last_modifying_cmd, '\0', BUFSIZ);   // clear new cmd queue
     1960    last_modifying_cmd = xzalloc(MAX_LINELEN);
    19181961    // if there is a current cmd count put it in the buffer first
    19191962    if (cmdcnt > 0)
    1920         sprintf((char *) last_modifying_cmd, "%d%c", cmdcnt, c);
     1963        sprintf(last_modifying_cmd, "%d%c", cmdcnt, c);
    19211964    else // just save char c onto queue
    19221965        last_modifying_cmd[0] = c;
     
    19261969static void end_cmd_q(void)
    19271970{
    1928 #ifdef CONFIG_FEATURE_VI_YANKMARK
     1971#if ENABLE_FEATURE_VI_YANKMARK
    19291972    YDreg = 26;         // go back to default Yank/Delete reg
    1930 #endif                          /* CONFIG_FEATURE_VI_YANKMARK */
     1973#endif
    19311974    adding2q = 0;
    1932     return;
    1933 }
    1934 #endif                          /* CONFIG_FEATURE_VI_DOT_CMD */
    1935 
    1936 #if defined(CONFIG_FEATURE_VI_YANKMARK) || (defined(CONFIG_FEATURE_VI_COLON) && defined(CONFIG_FEATURE_VI_SEARCH)) || defined(CONFIG_FEATURE_VI_CRASHME)
    1937 static Byte *string_insert(Byte * p, Byte * s) // insert the string at 'p'
     1975}
     1976#endif /* FEATURE_VI_DOT_CMD */
     1977
     1978#if ENABLE_FEATURE_VI_YANKMARK \
     1979 || (ENABLE_FEATURE_VI_COLON && ENABLE_FEATURE_VI_SEARCH) \
     1980 || ENABLE_FEATURE_VI_CRASHME
     1981static char *string_insert(char * p, char * s) // insert the string at 'p'
    19381982{
    19391983    int cnt, i;
    19401984
    1941     i = strlen((char *) s);
    1942     p = text_hole_make(p, i);
    1943     strncpy((char *) p, (char *) s, i);
    1944     for (cnt = 0; *s != '\0'; s++) {
    1945         if (*s == '\n')
    1946             cnt++;
    1947     }
    1948 #ifdef CONFIG_FEATURE_VI_YANKMARK
    1949     psb("Put %d lines (%d chars) from [%c]", cnt, i, what_reg());
    1950 #endif                          /* CONFIG_FEATURE_VI_YANKMARK */
    1951     return (p);
    1952 }
    1953 #endif                          /* CONFIG_FEATURE_VI_YANKMARK || CONFIG_FEATURE_VI_COLON || CONFIG_FEATURE_VI_CRASHME */
    1954 
    1955 #ifdef CONFIG_FEATURE_VI_YANKMARK
    1956 static Byte *text_yank(Byte * p, Byte * q, int dest)    // copy text into a register
    1957 {
    1958     Byte *t;
     1985    i = strlen(s);
     1986    if (text_hole_make(p, i)) {
     1987        strncpy(p, s, i);
     1988        for (cnt = 0; *s != '\0'; s++) {
     1989            if (*s == '\n')
     1990                cnt++;
     1991        }
     1992#if ENABLE_FEATURE_VI_YANKMARK
     1993        psb("Put %d lines (%d chars) from [%c]", cnt, i, what_reg());
     1994#endif
     1995    }
     1996    return p;
     1997}
     1998#endif
     1999
     2000#if ENABLE_FEATURE_VI_YANKMARK
     2001static char *text_yank(char * p, char * q, int dest)    // copy text into a register
     2002{
     2003    char *t;
    19592004    int cnt;
    19602005
     
    19672012    t = reg[dest];
    19682013    free(t);        //  if already a yank register, free it
    1969     t = (Byte *) xmalloc(cnt + 1);  // get a new register
     2014    t = xmalloc(cnt + 1);   // get a new register
    19702015    memset(t, '\0', cnt + 1);   // clear new text[]
    1971     strncpy((char *) t, (char *) p, cnt);   // copy text[] into bufer
     2016    strncpy(t, p, cnt); // copy text[] into bufer
    19722017    reg[dest] = t;
    1973     return (p);
    1974 }
    1975 
    1976 static Byte what_reg(void)
    1977 {
    1978     Byte c;
    1979     int i;
    1980 
    1981     i = 0;
     2018    return p;
     2019}
     2020
     2021static char what_reg(void)
     2022{
     2023    char c;
     2024
    19822025    c = 'D';            // default to D-reg
    19832026    if (0 <= YDreg && YDreg <= 25)
    1984         c = 'a' + (Byte) YDreg;
     2027        c = 'a' + (char) YDreg;
    19852028    if (YDreg == 26)
    19862029        c = 'D';
    19872030    if (YDreg == 27)
    19882031        c = 'U';
    1989     return (c);
    1990 }
    1991 
    1992 static void check_context(Byte cmd)
     2032    return c;
     2033}
     2034
     2035static void check_context(char cmd)
    19932036{
    19942037    // A context is defined to be "modifying text"
     
    19962039
    19972040    if (dot < context_start || dot > context_end) {
    1998         if (strchr((char *) modifying_cmds, cmd) != NULL) {
     2041        if (strchr(modifying_cmds, cmd) != NULL) {
    19992042            // we are trying to modify text[]- make this the current context
    20002043            mark[27] = mark[26];    // move cur to prev
     
    20052048        }
    20062049    }
    2007     return;
    2008 }
    2009 
    2010 static inline Byte *swap_context(Byte * p) // goto new context for '' command make this the current context
    2011 {
    2012     Byte *tmp;
     2050}
     2051
     2052static inline char *swap_context(char * p) // goto new context for '' command make this the current context
     2053{
     2054    char *tmp;
    20132055
    20142056    // the current context is in mark[26]
     
    20232065        context_end = next_line(next_line(next_line(p)));
    20242066    }
    2025     return (p);
    2026 }
    2027 #endif                          /* CONFIG_FEATURE_VI_YANKMARK */
    2028 
    2029 static int isblnk(Byte c) // is the char a blank or tab
    2030 {
    2031     return (c == ' ' || c == '\t');
    2032 }
     2067    return p;
     2068}
     2069#endif /* FEATURE_VI_YANKMARK */
    20332070
    20342071//----- Set terminal attributes --------------------------------
     
    20532090
    20542091//----- Come here when we get a window resize signal ---------
    2055 #ifdef CONFIG_FEATURE_VI_USE_SIGNALS
     2092#if ENABLE_FEATURE_VI_USE_SIGNALS
    20562093static void winch_sig(int sig ATTRIBUTE_UNUSED)
    20572094{
    20582095    signal(SIGWINCH, winch_sig);
    20592096    if (ENABLE_FEATURE_VI_WIN_RESIZE)
    2060        get_terminal_width_height(0, &columns, &rows);
     2097        get_terminal_width_height(0, &columns, &rows);
    20612098    new_screen(rows, columns);  // get memory for virtual screen
    20622099    redraw(TRUE);       // re-draw the screen
     
    20912128{
    20922129    signal(SIGINT, catch_sig);
    2093     if(sig)
     2130    if (sig)
    20942131        longjmp(restart, sig);
    20952132}
    2096 #endif                          /* CONFIG_FEATURE_VI_USE_SIGNALS */
     2133#endif /* FEATURE_VI_USE_SIGNALS */
    20972134
    20982135static int mysleep(int hund)    // sleep for 'h' 1/100 seconds
    20992136{
     2137    fd_set rfds;
     2138    struct timeval tv;
     2139
    21002140    // Don't hang- Wait 5/100 seconds-  1 Sec= 1000000
    21012141    fflush(stdout);
     
    21052145    tv.tv_usec = hund * 10000;
    21062146    select(1, &rfds, NULL, NULL, &tv);
    2107     return (FD_ISSET(0, &rfds));
     2147    return FD_ISSET(0, &rfds);
    21082148}
    21092149
     
    21132153
    21142154//----- IO Routines --------------------------------------------
    2115 static Byte readit(void)    // read (maybe cursor) key from stdin
    2116 {
    2117     Byte c;
     2155static char readit(void)    // read (maybe cursor) key from stdin
     2156{
     2157    char c;
    21182158    int n;
    21192159    struct esc_cmds {
    21202160        const char *seq;
    2121         Byte val;
     2161        char val;
    21222162    };
    21232163
    21242164    static const struct esc_cmds esccmds[] = {
    2125         {"OA", (Byte) VI_K_UP},       // cursor key Up
    2126         {"OB", (Byte) VI_K_DOWN},     // cursor key Down
    2127         {"OC", (Byte) VI_K_RIGHT},    // Cursor Key Right
    2128         {"OD", (Byte) VI_K_LEFT},     // cursor key Left
    2129         {"OH", (Byte) VI_K_HOME},     // Cursor Key Home
    2130         {"OF", (Byte) VI_K_END},      // Cursor Key End
    2131         {"[A", (Byte) VI_K_UP},       // cursor key Up
    2132         {"[B", (Byte) VI_K_DOWN},     // cursor key Down
    2133         {"[C", (Byte) VI_K_RIGHT},    // Cursor Key Right
    2134         {"[D", (Byte) VI_K_LEFT},     // cursor key Left
    2135         {"[H", (Byte) VI_K_HOME},     // Cursor Key Home
    2136         {"[F", (Byte) VI_K_END},      // Cursor Key End
    2137         {"[1~", (Byte) VI_K_HOME},     // Cursor Key Home
    2138         {"[2~", (Byte) VI_K_INSERT},  // Cursor Key Insert
    2139         {"[4~", (Byte) VI_K_END},      // Cursor Key End
    2140         {"[5~", (Byte) VI_K_PAGEUP},  // Cursor Key Page Up
    2141         {"[6~", (Byte) VI_K_PAGEDOWN},        // Cursor Key Page Down
    2142         {"OP", (Byte) VI_K_FUN1},     // Function Key F1
    2143         {"OQ", (Byte) VI_K_FUN2},     // Function Key F2
    2144         {"OR", (Byte) VI_K_FUN3},     // Function Key F3
    2145         {"OS", (Byte) VI_K_FUN4},     // Function Key F4
    2146         {"[15~", (Byte) VI_K_FUN5},   // Function Key F5
    2147         {"[17~", (Byte) VI_K_FUN6},   // Function Key F6
    2148         {"[18~", (Byte) VI_K_FUN7},   // Function Key F7
    2149         {"[19~", (Byte) VI_K_FUN8},   // Function Key F8
    2150         {"[20~", (Byte) VI_K_FUN9},   // Function Key F9
    2151         {"[21~", (Byte) VI_K_FUN10},  // Function Key F10
    2152         {"[23~", (Byte) VI_K_FUN11},  // Function Key F11
    2153         {"[24~", (Byte) VI_K_FUN12},  // Function Key F12
    2154         {"[11~", (Byte) VI_K_FUN1},   // Function Key F1
    2155         {"[12~", (Byte) VI_K_FUN2},   // Function Key F2
    2156         {"[13~", (Byte) VI_K_FUN3},   // Function Key F3
    2157         {"[14~", (Byte) VI_K_FUN4},   // Function Key F4
     2165        {"OA", VI_K_UP},       // cursor key Up
     2166        {"OB", VI_K_DOWN},     // cursor key Down
     2167        {"OC", VI_K_RIGHT},    // Cursor Key Right
     2168        {"OD", VI_K_LEFT},     // cursor key Left
     2169        {"OH", VI_K_HOME},     // Cursor Key Home
     2170        {"OF", VI_K_END},      // Cursor Key End
     2171        {"[A", VI_K_UP},       // cursor key Up
     2172        {"[B", VI_K_DOWN},     // cursor key Down
     2173        {"[C", VI_K_RIGHT},    // Cursor Key Right
     2174        {"[D", VI_K_LEFT},     // cursor key Left
     2175        {"[H", VI_K_HOME},     // Cursor Key Home
     2176        {"[F", VI_K_END},      // Cursor Key End
     2177        {"[1~", VI_K_HOME},    // Cursor Key Home
     2178        {"[2~", VI_K_INSERT},  // Cursor Key Insert
     2179        {"[4~", VI_K_END},     // Cursor Key End
     2180        {"[5~", VI_K_PAGEUP},  // Cursor Key Page Up
     2181        {"[6~", VI_K_PAGEDOWN},// Cursor Key Page Down
     2182        {"OP", VI_K_FUN1},     // Function Key F1
     2183        {"OQ", VI_K_FUN2},     // Function Key F2
     2184        {"OR", VI_K_FUN3},     // Function Key F3
     2185        {"OS", VI_K_FUN4},     // Function Key F4
     2186        {"[15~", VI_K_FUN5},   // Function Key F5
     2187        {"[17~", VI_K_FUN6},   // Function Key F6
     2188        {"[18~", VI_K_FUN7},   // Function Key F7
     2189        {"[19~", VI_K_FUN8},   // Function Key F8
     2190        {"[20~", VI_K_FUN9},   // Function Key F9
     2191        {"[21~", VI_K_FUN10},  // Function Key F10
     2192        {"[23~", VI_K_FUN11},  // Function Key F11
     2193        {"[24~", VI_K_FUN12},  // Function Key F12
     2194        {"[11~", VI_K_FUN1},   // Function Key F1
     2195        {"[12~", VI_K_FUN2},   // Function Key F2
     2196        {"[13~", VI_K_FUN3},   // Function Key F3
     2197        {"[14~", VI_K_FUN4},   // Function Key F4
    21582198    };
    2159 
    2160 #define ESCCMDS_COUNT (sizeof(esccmds)/sizeof(struct esc_cmds))
    2161 
    2162     (void) alarm(0);    // turn alarm OFF while we wait for input
     2199    enum { ESCCMDS_COUNT = ARRAY_SIZE(esccmds) };
     2200
     2201    alarm(0);   // turn alarm OFF while we wait for input
    21632202    fflush(stdout);
    21642203    n = readed_for_parse;
    21652204    // get input from User- are there already input chars in Q?
    21662205    if (n <= 0) {
    2167       ri0:
     2206 ri0:
    21682207        // the Q is empty, wait for a typed char
    2169         n = read(0, readbuffer, BUFSIZ - 1);
     2208        n = read(0, readbuffer, MAX_LINELEN - 1);
    21702209        if (n < 0) {
    21712210            if (errno == EINTR)
    21722211                goto ri0;   // interrupted sys call
    2173             if (errno == EBADF)
    2174                 editing = 0;
    2175             if (errno == EFAULT)
    2176                 editing = 0;
    2177             if (errno == EINVAL)
    2178                 editing = 0;
    2179             if (errno == EIO)
     2212            if (errno == EBADF || errno == EFAULT || errno == EINVAL
     2213                    || errno == EIO)
    21802214                editing = 0;
    21812215            errno = 0;
    21822216        }
    2183         if(n <= 0)
     2217        if (n <= 0)
    21842218            return 0;       // error
    21852219        if (readbuffer[0] == 27) {
    2186     // This is an ESC char. Is this Esc sequence?
    2187     // Could be bare Esc key. See if there are any
    2188     // more chars to read after the ESC. This would
    2189     // be a Function or Cursor Key sequence.
    2190     FD_ZERO(&rfds);
    2191     FD_SET(0, &rfds);
    2192     tv.tv_sec = 0;
    2193     tv.tv_usec = 50000; // Wait 5/100 seconds- 1 Sec=1000000
    2194 
    2195     // keep reading while there are input chars and room in buffer
    2196             while (select(1, &rfds, NULL, NULL, &tv) > 0 && n <= (BUFSIZ - 5)) {
    2197         // read the rest of the ESC string
    2198                 int r = read(0, (void *) (readbuffer + n), BUFSIZ - n);
     2220            fd_set rfds;
     2221            struct timeval tv;
     2222
     2223            // This is an ESC char. Is this Esc sequence?
     2224            // Could be bare Esc key. See if there are any
     2225            // more chars to read after the ESC. This would
     2226            // be a Function or Cursor Key sequence.
     2227            FD_ZERO(&rfds);
     2228            FD_SET(0, &rfds);
     2229            tv.tv_sec = 0;
     2230            tv.tv_usec = 50000; // Wait 5/100 seconds- 1 Sec=1000000
     2231
     2232            // keep reading while there are input chars and room in buffer
     2233            while (select(1, &rfds, NULL, NULL, &tv) > 0 && n <= (MAX_LINELEN - 5)) {
     2234                // read the rest of the ESC string
     2235                int r = read(0, (void *) (readbuffer + n), MAX_LINELEN - n);
    21992236                if (r > 0) {
    22002237                    n += r;
     
    22052242    }
    22062243    c = readbuffer[0];
    2207     if(c == 27 && n > 1) {
    2208     // Maybe cursor or function key?
     2244    if (c == 27 && n > 1) {
     2245        // Maybe cursor or function key?
    22092246        const struct esc_cmds *eindex;
    22102247
     
    22122249            int cnt = strlen(eindex->seq);
    22132250
    2214             if(n <= cnt)
     2251            if (n <= cnt)
    22152252                continue;
    2216             if(strncmp(eindex->seq, (char *) readbuffer + 1, cnt))
     2253            if (strncmp(eindex->seq, readbuffer + 1, cnt))
    22172254                continue;
    22182255            // is a Cursor key- put derived value back into Q
     
    22222259            break;
    22232260        }
    2224         if(eindex == &esccmds[ESCCMDS_COUNT]) {
     2261        if (eindex == &esccmds[ESCCMDS_COUNT]) {
    22252262            /* defined ESC sequence not found, set only one ESC */
    22262263            n = 1;
     
    22312268    // remove key sequence from Q
    22322269    readed_for_parse -= n;
    2233     memmove(readbuffer, readbuffer + n, BUFSIZ - n);
    2234     (void) alarm(3);    // we are done waiting for input, turn alarm ON
    2235     return (c);
     2270    memmove(readbuffer, readbuffer + n, MAX_LINELEN - n);
     2271    alarm(3);   // we are done waiting for input, turn alarm ON
     2272    return c;
    22362273}
    22372274
    22382275//----- IO Routines --------------------------------------------
    2239 static Byte get_one_char(void)
    2240 {
    2241     static Byte c;
    2242 
    2243 #ifdef CONFIG_FEATURE_VI_DOT_CMD
     2276static char get_one_char(void)
     2277{
     2278    static char c;
     2279
     2280#if ENABLE_FEATURE_VI_DOT_CMD
    22442281    // ! adding2q  && ioq == 0  read()
    22452282    // ! adding2q  && ioq != 0  *ioq
     
    22652302        c = readit();   // get the users input
    22662303        if (last_modifying_cmd != 0) {
    2267             int len = strlen((char *) last_modifying_cmd);
    2268             if (len + 1 >= BUFSIZ) {
     2304            int len = strlen(last_modifying_cmd);
     2305            if (len >= MAX_LINELEN - 1) {
    22692306                psbs("last_modifying_cmd overrun");
    22702307            } else {
     
    22742311        }
    22752312    }
    2276 #else                           /* CONFIG_FEATURE_VI_DOT_CMD */
     2313#else
    22772314    c = readit();       // get the users input
    2278 #endif                          /* CONFIG_FEATURE_VI_DOT_CMD */
    2279     return (c);         // return the char, where ever it came from
    2280 }
    2281 
    2282 static Byte *get_input_line(Byte * prompt) // get input line- use "status line"
    2283 {
    2284     Byte buf[BUFSIZ];
    2285     Byte c;
     2315#endif /* FEATURE_VI_DOT_CMD */
     2316    return c;           // return the char, where ever it came from
     2317}
     2318
     2319static char *get_input_line(const char * prompt) // get input line- use "status line"
     2320{
     2321    static char *obufp;
     2322
     2323    char buf[MAX_LINELEN];
     2324    char c;
    22862325    int i;
    2287     static Byte *obufp = NULL;
    2288 
    2289     strcpy((char *) buf, (char *) prompt);
     2326
     2327    strcpy(buf, prompt);
    22902328    last_status_cksum = 0;  // force status update
    22912329    place_cursor(rows - 1, 0, FALSE);   // go to Status line, bottom of screen
    22922330    clear_to_eol();     // clear the line
    2293     write1((char *) prompt);      // write out the :, /, or ? prompt
    2294 
    2295     for (i = strlen((char *) buf); i < BUFSIZ;) {
     2331    write1(prompt);      // write out the :, /, or ? prompt
     2332
     2333    i = strlen(buf);
     2334    while (i < MAX_LINELEN) {
    22962335        c = get_one_char(); // read user input
    22972336        if (c == '\n' || c == '\r' || c == 27)
     
    23152354    refresh(FALSE);
    23162355    free(obufp);
    2317     obufp = (Byte *) bb_xstrdup((char *) buf);
    2318     return (obufp);
    2319 }
    2320 
    2321 static int file_size(const Byte * fn) // what is the byte size of "fn"
     2356    obufp = xstrdup(buf);
     2357    return obufp;
     2358}
     2359
     2360static int file_size(const char *fn) // what is the byte size of "fn"
    23222361{
    23232362    struct stat st_buf;
    2324     int cnt, sr;
    2325 
    2326     if (fn == 0 || strlen((char *)fn) <= 0)
    2327         return (-1);
     2363    int cnt;
     2364
    23282365    cnt = -1;
    2329     sr = stat((char *) fn, &st_buf);    // see if file exists
    2330     if (sr >= 0) {
     2366    if (fn && fn[0] && stat(fn, &st_buf) == 0)  // see if file exists
    23312367        cnt = (int) st_buf.st_size;
    2332     }
    2333     return (cnt);
    2334 }
    2335 
    2336 static int file_insert(Byte * fn, Byte * p, int size)
    2337 {
    2338     int fd, cnt;
    2339 
    2340     cnt = -1;
    2341 #ifdef CONFIG_FEATURE_VI_READONLY
    2342     readonly = FALSE;
    2343 #endif                          /* CONFIG_FEATURE_VI_READONLY */
    2344     if (fn == 0 || strlen((char*) fn) <= 0) {
    2345         psbs("No filename given");
     2368    return cnt;
     2369}
     2370
     2371static int file_insert(const char * fn, char *p
     2372        USE_FEATURE_VI_READONLY(, int update_ro_status))
     2373{
     2374    int cnt = -1;
     2375    int fd, size;
     2376    struct stat statbuf;
     2377
     2378    /* Validate file */
     2379    if (stat(fn, &statbuf) < 0) {
     2380        psbs("\"%s\" %s", fn, strerror(errno));
    23462381        goto fi0;
    23472382    }
    2348     if (size == 0) {
    2349         // OK- this is just a no-op
    2350         cnt = 0;
     2383    if ((statbuf.st_mode & S_IFREG) == 0) {
     2384        // This is not a regular file
     2385        psbs("\"%s\" Not a regular file", fn);
    23512386        goto fi0;
    23522387    }
    2353     if (size < 0) {
    2354         psbs("Trying to insert a negative number (%d) of characters", size);
     2388    /* // this check is done by open()
     2389    if ((statbuf.st_mode & (S_IRUSR | S_IRGRP | S_IROTH)) == 0) {
     2390        // dont have any read permissions
     2391        psbs("\"%s\" Not readable", fn);
    23552392        goto fi0;
    23562393    }
     2394    */
    23572395    if (p < text || p > end) {
    23582396        psbs("Trying to insert file outside of memory");
     
    23602398    }
    23612399
    2362     // see if we can open the file
    2363 #ifdef CONFIG_FEATURE_VI_READONLY
    2364     if (vi_readonly) goto fi1;      // do not try write-mode
    2365 #endif
    2366     fd = open((char *) fn, O_RDWR);         // assume read & write
     2400    // read file to buffer
     2401    fd = open(fn, O_RDONLY);
    23672402    if (fd < 0) {
    2368         // could not open for writing- maybe file is read only
    2369 #ifdef CONFIG_FEATURE_VI_READONLY
    2370   fi1:
    2371 #endif
    2372         fd = open((char *) fn, O_RDONLY);   // try read-only
    2373         if (fd < 0) {
    2374             psbs("\"%s\" %s", fn, "could not open file");
    2375             goto fi0;
    2376         }
    2377 #ifdef CONFIG_FEATURE_VI_READONLY
    2378         // got the file- read-only
    2379         readonly = TRUE;
    2380 #endif                          /* CONFIG_FEATURE_VI_READONLY */
    2381     }
     2403        psbs("\"%s\" %s", fn, strerror(errno));
     2404        goto fi0;
     2405    }
     2406    size = statbuf.st_size;
    23822407    p = text_hole_make(p, size);
     2408    if (p == NULL)
     2409        goto fi0;
    23832410    cnt = read(fd, p, size);
    2384     close(fd);
    23852411    if (cnt < 0) {
    2386         cnt = -1;
     2412        psbs("\"%s\" %s", fn, strerror(errno));
    23872413        p = text_hole_delete(p, p + size - 1);  // un-do buffer insert
    2388         psbs("could not read file \"%s\"", fn);
    23892414    } else if (cnt < size) {
    23902415        // There was a partial read, shrink unused space text[]
    23912416        p = text_hole_delete(p + cnt, p + (size - cnt) - 1);    // un-do buffer insert
    2392         psbs("could not read all of file \"%s\"", fn);
     2417        psbs("cannot read all of file \"%s\"", fn);
    23932418    }
    23942419    if (cnt >= size)
    23952420        file_modified++;
    2396   fi0:
    2397     return (cnt);
    2398 }
    2399 
    2400 static int file_write(Byte * fn, Byte * first, Byte * last)
     2421    close(fd);
     2422 fi0:
     2423#if ENABLE_FEATURE_VI_READONLY
     2424    if (update_ro_status
     2425     && ((access(fn, W_OK) < 0) ||
     2426        /* root will always have access()
     2427         * so we check fileperms too */
     2428        !(statbuf.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH))
     2429        )
     2430    ) {
     2431        SET_READONLY_FILE(readonly_mode);
     2432    }
     2433#endif
     2434    return cnt;
     2435}
     2436
     2437
     2438static int file_write(char * fn, char * first, char * last)
    24012439{
    24022440    int fd, cnt, charcnt;
     
    24042442    if (fn == 0) {
    24052443        psbs("No current filename");
    2406         return (-2);
     2444        return -2;
    24072445    }
    24082446    charcnt = 0;
    24092447    // FIXIT- use the correct umask()
    2410     fd = open((char *) fn, (O_WRONLY | O_CREAT | O_TRUNC), 0664);
     2448    fd = open(fn, (O_WRONLY | O_CREAT | O_TRUNC), 0664);
    24112449    if (fd < 0)
    2412         return (-1);
     2450        return -1;
    24132451    cnt = last - first + 1;
    24142452    charcnt = write(fd, first, cnt);
    24152453    if (charcnt == cnt) {
    24162454        // good write
    2417         //file_modified= FALSE; // the file has not been modified
     2455        //file_modified = FALSE; // the file has not been modified
    24182456    } else {
    24192457        charcnt = 0;
    24202458    }
    24212459    close(fd);
    2422     return (charcnt);
     2460    return charcnt;
    24232461}
    24242462
     
    24382476static void place_cursor(int row, int col, int opti)
    24392477{
    2440     char cm1[BUFSIZ];
     2478    char cm1[MAX_LINELEN];
    24412479    char *cm;
    2442 #ifdef CONFIG_FEATURE_VI_OPTIMIZE_CURSOR
    2443     char cm2[BUFSIZ];
    2444     Byte *screenp;
    2445     // char cm3[BUFSIZ];
    2446     int Rrow= last_row;
    2447 #endif                          /* CONFIG_FEATURE_VI_OPTIMIZE_CURSOR */
    2448 
    2449     memset(cm1, '\0', BUFSIZ - 1);  // clear the buffer
     2480#if ENABLE_FEATURE_VI_OPTIMIZE_CURSOR
     2481    char cm2[MAX_LINELEN];
     2482    char *screenp;
     2483    // char cm3[MAX_LINELEN];
     2484    int Rrow = last_row;
     2485#endif
     2486
     2487    memset(cm1, '\0', MAX_LINELEN);  // clear the buffer
    24502488
    24512489    if (row < 0) row = 0;
     
    24552493
    24562494    //----- 1.  Try the standard terminal ESC sequence
    2457     sprintf((char *) cm1, CMrc, row + 1, col + 1);
    2458     cm= cm1;
    2459     if (! opti) goto pc0;
    2460 
    2461 #ifdef CONFIG_FEATURE_VI_OPTIMIZE_CURSOR
     2495    sprintf(cm1, CMrc, row + 1, col + 1);
     2496    cm = cm1;
     2497    if (!opti)
     2498        goto pc0;
     2499
     2500#if ENABLE_FEATURE_VI_OPTIMIZE_CURSOR
    24622501    //----- find the minimum # of chars to move cursor -------------
    24632502    //----- 2.  Try moving with discreet chars (Newline, [back]space, ...)
    2464     memset(cm2, '\0', BUFSIZ - 1);  // clear the buffer
     2503    memset(cm2, '\0', MAX_LINELEN);  // clear the buffer
    24652504
    24662505    // move to the correct row
     
    24802519    // just send out orignal source char to get to correct place
    24812520    screenp = &screen[row * columns];   // start of screen line
    2482     strncat(cm2, (char* )screenp, col);
     2521    strncat(cm2, screenp, col);
    24832522
    24842523    //----- 3.  Try some other way of moving cursor
     
    24862525
    24872526    // pick the shortest cursor motion to send out
    2488     cm= cm1;
     2527    cm = cm1;
    24892528    if (strlen(cm2) < strlen(cm)) {
    2490         cm= cm2;
     2529        cm = cm2;
    24912530    }  /* else if (strlen(cm3) < strlen(cm)) {
    24922531        cm= cm3;
    24932532    } */
    2494 #endif                          /* CONFIG_FEATURE_VI_OPTIMIZE_CURSOR */
    2495   pc0:
     2533#endif /* FEATURE_VI_OPTIMIZE_CURSOR */
     2534 pc0:
    24962535    write1(cm);                 // move the cursor
    24972536}
     
    25262565    standout_start();   // send "start reverse video" sequence
    25272566    redraw(TRUE);
    2528     (void) mysleep(h);
     2567    mysleep(h);
    25292568    standout_end();     // send "end reverse video" sequence
    25302569    redraw(TRUE);
     
    25332572static void Indicate_Error(void)
    25342573{
    2535 #ifdef CONFIG_FEATURE_VI_CRASHME
     2574#if ENABLE_FEATURE_VI_CRASHME
    25362575    if (crashme > 0)
    25372576        return;         // generate a random command
    2538 #endif                          /* CONFIG_FEATURE_VI_CRASHME */
     2577#endif
    25392578    if (!err_method) {
    25402579        write1(bell);   // send out a bell character
     
    25512590}
    25522591
    2553 static int bufsum(unsigned char *buf, int count)
     2592static int bufsum(char *buf, int count)
    25542593{
    25552594    int sum = 0;
    2556     unsigned char *e = buf + count;
     2595    char *e = buf + count;
     2596
    25572597    while (buf < e)
    2558         sum += *buf++;
     2598        sum += (unsigned char) *buf++;
    25592599    return sum;
    25602600}
     
    25742614        last_status_cksum= cksum;       // remember if we have seen this line
    25752615        place_cursor(rows - 1, 0, FALSE);   // put cursor on status line
    2576         write1((char*)status_buffer);
     2616        write1(status_buffer);
    25772617        clear_to_eol();
    25782618        if (have_status_msg) {
    2579             if (((int)strlen((char*)status_buffer) - (have_status_msg - 1)) >
     2619            if (((int)strlen(status_buffer) - (have_status_msg - 1)) >
    25802620                    (columns - 1) ) {
    25812621                have_status_msg = 0;
     
    25962636
    25972637    va_start(args, format);
    2598     strcpy((char *) status_buffer, SOs);    // Terminal standout mode on
    2599     vsprintf((char *) status_buffer + strlen((char *) status_buffer), format, args);
    2600     strcat((char *) status_buffer, SOn);    // Terminal standout mode off
     2638    strcpy(status_buffer, SOs); // Terminal standout mode on
     2639    vsprintf(status_buffer + strlen(status_buffer), format, args);
     2640    strcat(status_buffer, SOn); // Terminal standout mode off
    26012641    va_end(args);
    26022642
    26032643    have_status_msg = 1 + sizeof(SOs) + sizeof(SOn) - 2;
    2604 
    2605     return;
    26062644}
    26072645
     
    26122650
    26132651    va_start(args, format);
    2614     vsprintf((char *) status_buffer, format, args);
     2652    vsprintf(status_buffer, format, args);
    26152653    va_end(args);
    26162654
    26172655    have_status_msg = 1;
    2618 
    2619     return;
    2620 }
    2621 
    2622 static void ni(Byte * s) // display messages
    2623 {
    2624     Byte buf[BUFSIZ];
     2656}
     2657
     2658static void ni(const char * s) // display messages
     2659{
     2660    char buf[MAX_LINELEN];
    26252661
    26262662    print_literal(buf, s);
     
    26302666static int format_edit_status(void) // show file status on status line
    26312667{
     2668    static int tot;
     2669    static const char cmd_mode_indicator[] ALIGN1 = "-IR-";
    26322670    int cur, percent, ret, trunc_at;
    2633     static int tot;
    26342671
    26352672    // file_modified is now a counter rather than a flag.  this
     
    26632700        columns : STATUS_BUFFER_LEN-1;
    26642701
    2665     ret = snprintf((char *) status_buffer, trunc_at+1,
    2666 #ifdef CONFIG_FEATURE_VI_READONLY
     2702    ret = snprintf(status_buffer, trunc_at+1,
     2703#if ENABLE_FEATURE_VI_READONLY
    26672704        "%c %s%s%s %d/%d %d%%",
    26682705#else
    26692706        "%c %s%s %d/%d %d%%",
    26702707#endif
    2671         (cmd_mode ? (cmd_mode == 2 ? 'R':'I'):'-'),
    2672         (cfn != 0 ? (char *) cfn : "No file"),
    2673 #ifdef CONFIG_FEATURE_VI_READONLY
    2674         ((vi_readonly || readonly) ? " [Read-only]" : ""),
    2675 #endif
    2676         (file_modified ? " [modified]" : ""),
     2708        cmd_mode_indicator[cmd_mode & 3],
     2709        (current_filename != NULL ? current_filename : "No file"),
     2710#if ENABLE_FEATURE_VI_READONLY
     2711        (readonly_mode ? " [Readonly]" : ""),
     2712#endif
     2713        (file_modified ? " [Modified]" : ""),
    26772714        cur, tot, percent);
    26782715
     
    26952732
    26962733//----- Format a text[] line into a buffer ---------------------
    2697 static void format_line(Byte *dest, Byte *src, int li)
     2734static void format_line(char *dest, char *src, int li)
    26982735{
    26992736    int co;
    2700     Byte c;
    2701 
    2702     for (co= 0; co < MAX_SCR_COLS; co++) {
    2703         c= ' ';     // assume blank
     2737    char c;
     2738
     2739    for (co = 0; co < MAX_SCR_COLS; co++) {
     2740        c = ' ';        // assume blank
    27042741        if (li > 0 && co == 0) {
    27052742            c = '~';        // not first line, assume Tilde
     
    27112748        if (c == '\n')
    27122749            break;
    2713         if (c > 127 && !Isprint(c)) {
     2750        if ((c & 0x80) && !Isprint(c)) {
    27142751            c = '.';
    27152752        }
    2716         if (c < ' ' || c == 127) {
     2753        if ((unsigned char)(c) < ' ' || c == 0x7f) {
    27172754            if (c == '\t') {
    27182755                c = ' ';
     
    27232760            } else {
    27242761                dest[co++] = '^';
    2725                 if(c == 127)
     2762                if (c == 0x7f)
    27262763                    c = '?';
    2727                  else
     2764                else
    27282765                    c += '@';       // make it visible
    27292766            }
     
    27452782{
    27462783    static int old_offset;
     2784
    27472785    int li, changed;
    2748     Byte buf[MAX_SCR_COLS];
    2749     Byte *tp, *sp;      // pointer into text[] and screen[]
    2750 #ifdef CONFIG_FEATURE_VI_OPTIMIZE_CURSOR
    2751     int last_li= -2;                // last line that changed- for optimizing cursor movement
    2752 #endif                          /* CONFIG_FEATURE_VI_OPTIMIZE_CURSOR */
     2786    char buf[MAX_SCR_COLS];
     2787    char *tp, *sp;      // pointer into text[] and screen[]
     2788#if ENABLE_FEATURE_VI_OPTIMIZE_CURSOR
     2789    int last_li = -2; // last line that changed- for optimizing cursor movement
     2790#endif
    27532791
    27542792    if (ENABLE_FEATURE_VI_WIN_RESIZE)
     
    27662804
    27672805        // skip to the end of the current text[] line
    2768         while (tp < end && *tp++ != '\n') /*no-op*/ ;
     2806        while (tp < end && *tp++ != '\n') /*no-op*/;
    27692807
    27702808        // see if there are any changes between vitual screen and buf
     
    27792817        // compare newly formatted buffer with virtual screen
    27802818        // look forward for first difference between buf and screen
    2781         for ( ; cs <= ce; cs++) {
     2819        for (; cs <= ce; cs++) {
    27822820            if (buf[cs + offset] != sp[cs]) {
    27832821                changed = TRUE; // mark for redraw
     
    27972835        // if horz offset has changed, force a redraw
    27982836        if (offset != old_offset) {
    2799   re0:
     2837 re0:
    28002838            changed = TRUE;
    28012839        }
     
    28162854                place_cursor(li, cs, FALSE);
    28172855            } else {
    2818 #ifdef CONFIG_FEATURE_VI_OPTIMIZE_CURSOR
     2856#if ENABLE_FEATURE_VI_OPTIMIZE_CURSOR
    28192857                // if this just the next line
    28202858                //  try to optimize cursor movement
     
    28222860                place_cursor(li, cs, li == (last_li+1) ? TRUE : FALSE);
    28232861                last_li= li;
    2824 #else                           /* CONFIG_FEATURE_VI_OPTIMIZE_CURSOR */
     2862#else
    28252863                place_cursor(li, cs, FALSE);    // use standard ESC sequence
    2826 #endif                          /* CONFIG_FEATURE_VI_OPTIMIZE_CURSOR */
     2864#endif /* FEATURE_VI_OPTIMIZE_CURSOR */
    28272865            }
    28282866
    28292867            // write line out to terminal
    28302868            {
    2831                 int nic = ce-cs+1;
    2832                 char *out = (char*)sp+cs;
    2833 
    2834                 while(nic-- > 0) {
     2869                int nic = ce - cs + 1;
     2870                char *out = sp + cs;
     2871
     2872                while (nic-- > 0) {
    28352873                    putchar(*out);
    28362874                    out++;
    28372875                }
    28382876            }
    2839 #ifdef CONFIG_FEATURE_VI_OPTIMIZE_CURSOR
     2877#if ENABLE_FEATURE_VI_OPTIMIZE_CURSOR
    28402878            last_row = li;
    2841 #endif                          /* CONFIG_FEATURE_VI_OPTIMIZE_CURSOR */
    2842         }
    2843     }
    2844 
    2845 #ifdef CONFIG_FEATURE_VI_OPTIMIZE_CURSOR
     2879#endif
     2880        }
     2881    }
     2882
     2883#if ENABLE_FEATURE_VI_OPTIMIZE_CURSOR
    28462884    place_cursor(crow, ccol, (crow == last_row) ? TRUE : FALSE);
    28472885    last_row = crow;
    28482886#else
    28492887    place_cursor(crow, ccol, FALSE);
    2850 #endif                          /* CONFIG_FEATURE_VI_OPTIMIZE_CURSOR */
     2888#endif
    28512889
    28522890    if (offset != old_offset)
     
    28762914
    28772915//----- Execute a Vi Command -----------------------------------
    2878 static void do_cmd(Byte c)
    2879 {
    2880     Byte c1, *p, *q, *msg, buf[9], *save_dot;
     2916static void do_cmd(char c)
     2917{
     2918    const char *msg;
     2919    char c1, *p, *q, buf[9], *save_dot;
    28812920    int cnt, i, j, dir, yf;
    28822921
    28832922    c1 = c;             // quiet the compiler
    28842923    cnt = yf = dir = 0; // quiet the compiler
    2885     p = q = save_dot = msg = buf;   // quiet the compiler
     2924    msg = p = q = save_dot = buf;   // quiet the compiler
    28862925    memset(buf, '\0', 9);   // clear buf
    28872926
     
    29032942    if (cmd_mode == 2) {
    29042943        //  flip-flop Insert/Replace mode
    2905         if (c == VI_K_INSERT) goto dc_i;
     2944        if (c == VI_K_INSERT)
     2945            goto dc_i;
    29062946        // we are 'R'eplacing the current *dot with new char
    29072947        if (*dot == '\n') {
     
    29272967    }
    29282968
    2929 key_cmd_mode:
     2969 key_cmd_mode:
    29302970    switch (c) {
    29312971        //case 0x01:    // soh
     
    29372977        //case 0x11:    // dc1
    29382978        //case 0x13:    // dc3
    2939 #ifdef CONFIG_FEATURE_VI_CRASHME
     2979#if ENABLE_FEATURE_VI_CRASHME
    29402980    case 0x14:          // dc4  ctrl-T
    29412981        crashme = (crashme == 0) ? 1 : 0;
    29422982        break;
    2943 #endif                          /* CONFIG_FEATURE_VI_CRASHME */
     2983#endif
    29442984        //case 0x16:    // syn
    29452985        //case 0x17:    // etb
     
    29803020            buf[2] = '\0';
    29813021        }
    2982         ni((Byte *) buf);
     3022        ni(buf);
    29833023        end_cmd_q();    // stop adding to q
    29843024    case 0x00:          // nul- ignore
     
    29883028        dot_scroll(rows - 2, -1);
    29893029        break;
    2990 #ifdef CONFIG_FEATURE_VI_USE_SIGNALS
     3030#if ENABLE_FEATURE_VI_USE_SIGNALS
    29913031    case 0x03:          // ctrl-C   interrupt
    29923032        longjmp(restart, 1);
     
    29953035        suspend_sig(SIGTSTP);
    29963036        break;
    2997 #endif                          /* CONFIG_FEATURE_VI_USE_SIGNALS */
     3037#endif
    29983038    case 4:         // ctrl-D  scroll down half screen
    29993039        dot_scroll((rows - 2) / 2, 1);
     
    30123052    case VI_K_LEFT: // cursor key Left
    30133053    case 8:     // ctrl-H- move left    (This may be ERASE char)
    3014     case 127:   // DEL- move left   (This may be ERASE char)
     3054    case 0x7f:  // DEL- move left   (This may be ERASE char)
    30153055        if (cmdcnt-- > 1) {
    30163056            do_cmd(c);
     
    30313071        place_cursor(0, 0, FALSE);  // put cursor in correct place
    30323072        clear_to_eos(); // tel terminal to erase display
    3033         (void) mysleep(10);
     3073        mysleep(10);
    30343074        screen_erase(); // erase the internal screen buffer
    30353075        last_status_cksum = 0;  // force status update
     
    30653105        dot_right();
    30663106        break;
    3067 #ifdef CONFIG_FEATURE_VI_YANKMARK
     3107#if ENABLE_FEATURE_VI_YANKMARK
    30683108    case '"':           // "- name a register to use for Delete/Yank
    30693109        c1 = get_one_char();
     
    30813121            c1 = c1 - 'a';
    30823122            // get the b-o-l
    3083             q = mark[(int) c1];
     3123            q = mark[(unsigned char) c1];
    30843124            if (text <= q && q < end) {
    30853125                dot = q;
     
    31183158        }
    31193159        // are we putting whole lines or strings
    3120         if (strchr((char *) p, '\n') != NULL) {
     3160        if (strchr(p, '\n') != NULL) {
    31213161            if (c == 'P') {
    31223162                dot_begin();    // putting lines- Put above
     
    31473187        }
    31483188        break;
    3149 #endif                          /* CONFIG_FEATURE_VI_YANKMARK */
     3189#endif /* FEATURE_VI_YANKMARK */
    31503190    case '$':           // $- goto end of line
    31513191    case VI_K_END:      // Cursor Key End
     
    31813221            do_cmd(';');
    31823222        }               // repeat cnt
    3183         if (last_forward_char == 0) break;
     3223        if (last_forward_char == 0)
     3224            break;
    31843225        q = dot + 1;
    31853226        while (q < end - 1 && *q != '\n' && *q != last_forward_char) {
     
    31963237        dot_skip_over_ws();
    31973238        break;
    3198 #ifdef CONFIG_FEATURE_VI_DOT_CMD
     3239#if ENABLE_FEATURE_VI_DOT_CMD
    31993240    case '.':           // .- repeat the last modifying command
    32003241        // Stuff the last_modifying_cmd back into stdin
    32013242        // and let it be re-executed.
    32023243        if (last_modifying_cmd != 0) {
    3203             ioq = ioq_start = (Byte *) bb_xstrdup((char *) last_modifying_cmd);
    3204         }
    3205         break;
    3206 #endif                          /* CONFIG_FEATURE_VI_DOT_CMD */
    3207 #ifdef CONFIG_FEATURE_VI_SEARCH
     3244            ioq = ioq_start = xstrdup(last_modifying_cmd);
     3245        }
     3246        break;
     3247#endif
     3248#if ENABLE_FEATURE_VI_SEARCH
    32083249    case '?':           // /- search for a pattern
    32093250    case '/':           // /- search for a pattern
     
    32113252        buf[1] = '\0';
    32123253        q = get_input_line(buf);    // get input line- use "status line"
    3213         if (strlen((char *) q) == 1)
    3214             goto dc3;   // if no pat re-use old pat
    3215         if (strlen((char *) q) > 1) {   // new pat- save it and find
     3254        if (q[0] && !q[1])
     3255            goto dc3; // if no pat re-use old pat
     3256        if (q[0]) {       // strlen(q) > 1: new pat- save it and find
    32163257            // there is a new pat
    32173258            free(last_search_pattern);
    3218             last_search_pattern = (Byte *) bb_xstrdup((char *) q);
     3259            last_search_pattern = xstrdup(q);
    32193260            goto dc3;   // now find the pattern
    32203261        }
     
    32393280            do_cmd(c);
    32403281        }               // repeat cnt
    3241       dc3:
     3282 dc3:
    32423283        if (last_search_pattern == 0) {
    3243             msg = (Byte *) "No previous regular expression";
     3284            msg = "No previous regular expression";
    32443285            goto dc2;
    32453286        }
     
    32523293            p = dot - 1;
    32533294        }
    3254       dc4:
     3295 dc4:
    32553296        q = char_search(p, last_search_pattern + 1, dir, FULL);
    32563297        if (q != NULL) {
    32573298            dot = q;    // good search, update "dot"
    3258             msg = (Byte *) "";
     3299            msg = "";
    32593300            goto dc2;
    32603301        }
     
    32673308        if (q != NULL) {    // found something
    32683309            dot = q;    // found new pattern- goto it
    3269             msg = (Byte *) "search hit BOTTOM, continuing at TOP";
     3310            msg = "search hit BOTTOM, continuing at TOP";
    32703311            if (dir == BACK) {
    3271                 msg = (Byte *) "search hit TOP, continuing at BOTTOM";
     3312                msg = "search hit TOP, continuing at BOTTOM";
    32723313            }
    32733314        } else {
    3274             msg = (Byte *) "Pattern not found";
    3275         }
    3276       dc2:
    3277         if (*msg) psbs("%s", msg);
     3315            msg = "Pattern not found";
     3316        }
     3317 dc2:
     3318        if (*msg)
     3319            psbs("%s", msg);
    32783320        break;
    32793321    case '{':           // {- move backward paragraph
    3280         q = char_search(dot, (Byte *) "\n\n", BACK, FULL);
     3322        q = char_search(dot, "\n\n", BACK, FULL);
    32813323        if (q != NULL) {    // found blank line
    32823324            dot = next_line(q); // move to next blank line
     
    32843326        break;
    32853327    case '}':           // }- move forward paragraph
    3286         q = char_search(dot, (Byte *) "\n\n", FORWARD, FULL);
     3328        q = char_search(dot, "\n\n", FORWARD, FULL);
    32873329        if (q != NULL) {    // found blank line
    32883330            dot = next_line(q); // move to next blank line
    32893331        }
    32903332        break;
    3291 #endif                          /* CONFIG_FEATURE_VI_SEARCH */
     3333#endif /* FEATURE_VI_SEARCH */
    32923334    case '0':           // 0- goto begining of line
    32933335    case '1':           // 1-
     
    33073349        break;
    33083350    case ':':           // :- the colon mode commands
    3309         p = get_input_line((Byte *) ":");   // get input line- use "status line"
    3310 #ifdef CONFIG_FEATURE_VI_COLON
     3351        p = get_input_line(":");    // get input line- use "status line"
     3352#if ENABLE_FEATURE_VI_COLON
    33113353        colon(p);       // execute the command
    3312 #else                           /* CONFIG_FEATURE_VI_COLON */
     3354#else
    33133355        if (*p == ':')
    33143356            p++;                // move past the ':'
    3315         cnt = strlen((char *) p);
     3357        cnt = strlen(p);
    33163358        if (cnt <= 0)
    33173359            break;
    3318         if (strncasecmp((char *) p, "quit", cnt) == 0 ||
    3319             strncasecmp((char *) p, "q!", cnt) == 0) {  // delete lines
     3360        if (strncasecmp(p, "quit", cnt) == 0
     3361         || strncasecmp(p, "q!", cnt) == 0   // delete lines
     3362        ) {
    33203363            if (file_modified && p[1] != '!') {
    33213364                psbs("No write since last change (:quit! overrides)");
     
    33233366                editing = 0;
    33243367            }
    3325         } else if (strncasecmp((char *) p, "write", cnt) == 0
    3326                 || strncasecmp((char *) p, "wq", cnt) == 0
    3327                 || strncasecmp((char *) p, "wn", cnt) == 0
    3328                 || strncasecmp((char *) p, "x", cnt) == 0) {
    3329             cnt = file_write(cfn, text, end - 1);
     3368        } else if (strncasecmp(p, "write", cnt) == 0
     3369                || strncasecmp(p, "wq", cnt) == 0
     3370                || strncasecmp(p, "wn", cnt) == 0
     3371                || strncasecmp(p, "x", cnt) == 0
     3372        ) {
     3373            cnt = file_write(current_filename, text, end - 1);
    33303374            if (cnt < 0) {
    33313375                if (cnt == -1)
     
    33343378                file_modified = 0;
    33353379                last_file_modified = -1;
    3336                 psb("\"%s\" %dL, %dC", cfn, count_lines(text, end - 1), cnt);
    3337                 if (p[0] == 'x' || p[1] == 'q' || p[1] == 'n' ||
    3338                     p[0] == 'X' || p[1] == 'Q' || p[1] == 'N') {
     3380                psb("\"%s\" %dL, %dC", current_filename, count_lines(text, end - 1), cnt);
     3381                if (p[0] == 'x' || p[1] == 'q' || p[1] == 'n'
     3382                 || p[0] == 'X' || p[1] == 'Q' || p[1] == 'N'
     3383                ) {
    33393384                    editing = 0;
    33403385                }
    33413386            }
    3342         } else if (strncasecmp((char *) p, "file", cnt) == 0 ) {
     3387        } else if (strncasecmp(p, "file", cnt) == 0) {
    33433388            last_status_cksum = 0;  // force status update
    3344         } else if (sscanf((char *) p, "%d", &j) > 0) {
     3389        } else if (sscanf(p, "%d", &j) > 0) {
    33453390            dot = find_line(j);     // go to line # j
    33463391            dot_skip_over_ws();
    33473392        } else {        // unrecognised cmd
    3348             ni((Byte *) p);
    3349         }
    3350 #endif                          /* CONFIG_FEATURE_VI_COLON */
     3393            ni(p);
     3394        }
     3395#endif /* !FEATURE_VI_COLON */
    33513396        break;
    33523397    case '<':           // <- Left  shift something
     
    33553400        c1 = get_one_char();    // get the type of thing to delete
    33563401        find_range(&p, &q, c1);
    3357         (void) yank_delete(p, q, 1, YANKONLY);  // save copy before change
     3402        yank_delete(p, q, 1, YANKONLY); // save copy before change
    33583403        p = begin_line(p);
    33593404        q = end_line(q);
     
    33643409                if (*p == '\t') {
    33653410                    // shrink buffer 1 char
    3366                     (void) text_hole_delete(p, p);
     3411                    text_hole_delete(p, p);
    33673412                } else if (*p == ' ') {
    33683413                    // we should be calculating columns, not just SPACE
    33693414                    for (j = 0; *p == ' ' && j < tabstop; j++) {
    3370                         (void) text_hole_delete(p, p);
     3415                        text_hole_delete(p, p);
    33713416                    }
    33723417                }
    33733418            } else if (c == '>') {
    33743419                // shift right -- add tab or 8 spaces
    3375                 (void) char_insert(p, '\t');
     3420                char_insert(p, '\t');
    33763421            }
    33773422        }
     
    34123457        if (c == 'C')
    34133458            goto dc_i;  // start inserting
    3414 #ifdef CONFIG_FEATURE_VI_DOT_CMD
     3459#if ENABLE_FEATURE_VI_DOT_CMD
    34153460        if (c == 'D')
    34163461            end_cmd_q();    // stop adding to q
    3417 #endif                          /* CONFIG_FEATURE_VI_DOT_CMD */
     3462#endif
    34183463        break;
    34193464    case 'G':       // G- goto to a line number (default= E-O-F)
     
    34403485    case 'i':           // i- insert before current char
    34413486    case VI_K_INSERT:   // Cursor Key Insert
    3442       dc_i:
     3487 dc_i:
    34433488        cmd_mode = 1;   // start insrting
    34443489        break;
     
    34513496            *dot++ = ' ';   // replace NL with space
    34523497            file_modified++;
    3453             while (isblnk(*dot)) {  // delete leading WS
     3498            while (isblank(*dot)) { // delete leading WS
    34543499                dot_delete();
    34553500            }
     
    34893534        break;
    34903535    case 'R':           // R- continuous Replace char
    3491       dc5:
     3536 dc5:
    34923537        cmd_mode = 2;
    34933538        break;
     
    35183563        }
    35193564        if (file_modified) {
    3520 #ifdef CONFIG_FEATURE_VI_READONLY
    3521             if (vi_readonly || readonly) {
    3522                 psbs("\"%s\" File is read only", cfn);
    3523                 break;
    3524             }
    3525 #endif      /* CONFIG_FEATURE_VI_READONLY */
    3526             cnt = file_write(cfn, text, end - 1);
     3565            if (ENABLE_FEATURE_VI_READONLY && readonly_mode) {
     3566                psbs("\"%s\" File is read only", current_filename);
     3567                break;
     3568            }
     3569            cnt = file_write(current_filename, text, end - 1);
    35273570            if (cnt < 0) {
    35283571                if (cnt == -1)
     
    35613604    case 'c':           // c- change something
    35623605    case 'd':           // d- delete something
    3563 #ifdef CONFIG_FEATURE_VI_YANKMARK
     3606#if ENABLE_FEATURE_VI_YANKMARK
    35643607    case 'y':           // y- yank   something
    35653608    case 'Y':           // Y- Yank a line
    3566 #endif                          /* CONFIG_FEATURE_VI_YANKMARK */
     3609#endif
    35673610        yf = YANKDEL;   // assume either "c" or "d"
    3568 #ifdef CONFIG_FEATURE_VI_YANKMARK
     3611#if ENABLE_FEATURE_VI_YANKMARK
    35693612        if (c == 'y' || c == 'Y')
    35703613            yf = YANKONLY;
    3571 #endif                          /* CONFIG_FEATURE_VI_YANKMARK */
     3614#endif
    35723615        c1 = 'y';
    35733616        if (c != 'Y')
     
    35793622            if (c == 'c') {
    35803623                // don't include trailing WS as part of word
    3581                 while (isblnk(*q)) {
     3624                while (isblank(*q)) {
    35823625                    if (q <= text || q[-1] == '\n')
    35833626                        break;
     
    36103653            // if CHANGING, not deleting, start inserting after the delete
    36113654            if (c == 'c') {
    3612                 strcpy((char *) buf, "Change");
     3655                strcpy(buf, "Change");
    36133656                goto dc_i;  // start inserting
    36143657            }
    36153658            if (c == 'd') {
    3616                 strcpy((char *) buf, "Delete");
    3617             }
    3618 #ifdef CONFIG_FEATURE_VI_YANKMARK
     3659                strcpy(buf, "Delete");
     3660            }
     3661#if ENABLE_FEATURE_VI_YANKMARK
    36193662            if (c == 'y' || c == 'Y') {
    3620                 strcpy((char *) buf, "Yank");
     3663                strcpy(buf, "Yank");
    36213664            }
    36223665            p = reg[YDreg];
    3623             q = p + strlen((char *) p);
     3666            q = p + strlen(p);
    36243667            for (cnt = 0; p <= q; p++) {
    36253668                if (*p == '\n')
     
    36273670            }
    36283671            psb("%s %d lines (%d chars) using [%c]",
    3629                 buf, cnt, strlen((char *) reg[YDreg]), what_reg());
    3630 #endif                          /* CONFIG_FEATURE_VI_YANKMARK */
     3672                buf, cnt, strlen(reg[YDreg]), what_reg());
     3673#endif
    36313674            end_cmd_q();    // stop adding to q
    36323675        }
     
    37173760    }
    37183761
    3719   dc1:
     3762 dc1:
    37203763    // if text[] just became empty, add back an empty line
    37213764    if (end == text) {
    3722         (void) char_insert(text, '\n'); // start empty buf with dummy line
     3765        char_insert(text, '\n');    // start empty buf with dummy line
    37233766        dot = text;
    37243767    }
     
    37273770        dot = bound_dot(dot);   // make sure "dot" is valid
    37283771    }
    3729 #ifdef CONFIG_FEATURE_VI_YANKMARK
     3772#if ENABLE_FEATURE_VI_YANKMARK
    37303773    check_context(c);   // update the current context
    3731 #endif                          /* CONFIG_FEATURE_VI_YANKMARK */
     3774#endif
    37323775
    37333776    if (!isdigit(c))
     
    37393782}
    37403783
    3741 #ifdef CONFIG_FEATURE_VI_CRASHME
     3784#if ENABLE_FEATURE_VI_CRASHME
    37423785static int totalcmds = 0;
    37433786static int Mp = 85;             // Movement command Probability
     
    37483791static int Pp = 99;             // Put command Probability
    37493792static int M = 0, N = 0, I = 0, D = 0, Y = 0, P = 0, U = 0;
    3750 char chars[20] = "\t012345 abcdABCD-=.$";
    3751 char *words[20] = { "this", "is", "a", "test",
     3793const char chars[20] = "\t012345 abcdABCD-=.$";
     3794const char *const words[20] = {
     3795    "this", "is", "a", "test",
    37523796    "broadcast", "the", "emergency", "of",
    37533797    "system", "quick", "brown", "fox",
     
    37553799    "back", "January", "Febuary", "March"
    37563800};
    3757 char *lines[20] = {
     3801const char *const lines[20] = {
    37583802    "You should have received a copy of the GNU General Public License\n",
    37593803    "char c, cm, *cmd, *cmd1;\n",
     
    38133857    if (readed_for_parse > 0)
    38143858        goto cd1;
    3815   cd0:
     3859 cd0:
    38163860    startrbi = rbi = 0;
    38173861    sleeptime = 0;          // how long to pause between commands
    3818     memset(readbuffer, '\0', BUFSIZ);   // clear the read buffer
     3862    memset(readbuffer, '\0', MAX_LINELEN);   // clear the read buffer
    38193863    // generate a command by percentages
    38203864    percent = (int) lrand48() % 100;        // get a number from 0-99
     
    38753919                readbuffer[rbi++] = chars[((int) lrand48() % strlen(chars))];
    38763920            } else if (thing == 1) {        // insert words
    3877                 strcat((char *) readbuffer, words[(int) lrand48() % 20]);
    3878                 strcat((char *) readbuffer, " ");
     3921                strcat(readbuffer, words[(int) lrand48() % 20]);
     3922                strcat(readbuffer, " ");
    38793923                sleeptime = 0;  // how fast to type
    38803924            } else if (thing == 2) {        // insert lines
    3881                 strcat((char *) readbuffer, lines[(int) lrand48() % 20]);
     3925                strcat(readbuffer, lines[(int) lrand48() % 20]);
    38823926                sleeptime = 0;  // how fast to type
    38833927            } else {        // insert multi-lines
    3884                 strcat((char *) readbuffer, multilines[(int) lrand48() % 20]);
     3928                strcat(readbuffer, multilines[(int) lrand48() % 20]);
    38853929                sleeptime = 0;  // how fast to type
    38863930            }
    38873931        }
    3888         strcat((char *) readbuffer, "\033");
     3932        strcat(readbuffer, "\033");
    38893933    }
    38903934    readed_for_parse = strlen(readbuffer);
    3891   cd1:
     3935 cd1:
    38923936    totalcmds++;
    38933937    if (sleeptime > 0)
    3894         (void) mysleep(sleeptime);      // sleep 1/100 sec
     3938        mysleep(sleeptime);      // sleep 1/100 sec
    38953939}
    38963940
     
    38993943{
    39003944    static time_t oldtim;
     3945
    39013946    time_t tim;
    3902     char d[2], msg[BUFSIZ];
     3947    char d[2], msg[MAX_LINELEN];
    39033948
    39043949    msg[0] = '\0';
    39053950    if (end < text) {
    3906         strcat((char *) msg, "end<text ");
     3951        strcat(msg, "end<text ");
    39073952    }
    39083953    if (end > textend) {
    3909         strcat((char *) msg, "end>textend ");
     3954        strcat(msg, "end>textend ");
    39103955    }
    39113956    if (dot < text) {
    3912         strcat((char *) msg, "dot<text ");
     3957        strcat(msg, "dot<text ");
    39133958    }
    39143959    if (dot > end) {
    3915         strcat((char *) msg, "dot>end ");
     3960        strcat(msg, "dot>end ");
    39163961    }
    39173962    if (screenbegin < text) {
    3918         strcat((char *) msg, "screenbegin<text ");
     3963        strcat(msg, "screenbegin<text ");
    39193964    }
    39203965    if (screenbegin > end - 1) {
    3921         strcat((char *) msg, "screenbegin>end-1 ");
    3922     }
    3923 
    3924     if (strlen(msg) > 0) {
     3966        strcat(msg, "screenbegin>end-1 ");
     3967    }
     3968
     3969    if (msg[0]) {
    39253970        alarm(0);
    39263971        printf("\n\n%d: \'%c\' %s\n\n\n%s[Hit return to continue]%s",
     
    39353980    tim = (time_t) time((time_t *) 0);
    39363981    if (tim >= (oldtim + 3)) {
    3937         sprintf((char *) status_buffer,
     3982        sprintf(status_buffer,
    39383983                "Tot=%d: M=%d N=%d I=%d D=%d Y=%d P=%d U=%d size=%d",
    39393984                totalcmds, M, N, I, D, Y, P, U, end - text + 1);
    39403985        oldtim = tim;
    39413986    }
    3942     return;
    3943 }
    3944 #endif                            /* CONFIG_FEATURE_VI_CRASHME */
     3987}
     3988#endif
Note: See TracChangeset for help on using the changeset viewer.