/*
- * TODO before releasable quality:
- *
- * - Thorough testing.
- *
- * - Half decent build system.
- *
* TODO possibly after that:
*
- * - Need to handle >2Gb files! Up the `filesize' type to long
- * long and use it everywhere.
- *
* - Multiple buffers, multiple on-screen windows.
* + ^X^F to open new file
* + ^X^R to open new file RO
* rather than the current rather crap one; in particular
* this enables pasting into the search string.
* + er, how exactly do we deal with the problem of saving over
- * a file which we're maintaining references to?
+ * a file which we're maintaining references to in another
+ * buffer? The _current_ buffer can at least be sorted out by
+ * replacing it with a fresh tree containing a single
+ * file-data block, but other buffers are in trouble.
+ * * if we can rely on Unix fd semantics, this isn't too
+ * bad; we can just keep the fd open on the original file,
+ * and then the data stays around even after we rename(2)
+ * our new version over the top. Disk space usage gets
+ * silly after a few iterations, but it's better than
+ * nothing.
*
* - Undo!
* + this actually doesn't seem _too_ horrid. For a start, one
* buf_delete_data (both must be cloned for an overwrite),
* but I'm not convinced that simply cloning the entire thing
* isn't a superior option.
- *
- * - Reverse search.
- * + need to construct a reverse DFA.
- * + probably should construct both every time, so that you can
- * search forward for a thing and then immediately change
- * your mind and search backward for the same thing.
+ * + this really starts to show up the distinction between a
+ * `buffer' and a bare tree. A buffer is something which has
+ * an undo chain attached; so, in particular, the cut buffer
+ * shouldn't be one. Sort that out.
*
* - In-place editing.
* + this is an extra option when running in Fix mode. It
* one, we simply seek within the original file and write out
* all the pieces that have changed.
* + Primarily useful for editing disk devices directly
- * (yikes!).
+ * (yikes!), or other situations where you actually cannot
+ * create a fresh copy of the file and rename(2) it into
+ * place.
* + I had intended to suggest that in Fix mode this would be
* nice and easy, since every element of the buffer tree is
* either a literal block (needs writing) or a from-file
* _and_ when pasting a cut buffer _into_ one.
*/
+#include "tweak.h"
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <process.h>
#endif
-#include "tweak.h"
-
static void init(void);
static void done(void);
static void load_file (char *);
char message[80];
-char decstatus[] = "%s TWEAK "VER": %-18.18s %s posn=%-10d size=%-10d";
-char hexstatus[] = "%s TWEAK "VER": %-18.18s %s posn=0x%-8X size=0x%-8X";
+char decstatus[] = "%s TWEAK "VER": %-18.18s %s posn=%-10"OFF"d size=%-10"OFF"d";
+char hexstatus[] = "%s TWEAK "VER": %-18.18s %s posn=0x%-8"OFF"X size=0x%-8"OFF"X";
char *statfmt = hexstatus;
char last_char;
int modified = FALSE;
int new_file = FALSE; /* shouldn't need initialisation -
* but let's not take chances :-) */
-int width = 16;
-int realoffset = 0, offset = 16;
+fileoffset_t width = 16;
+fileoffset_t realoffset = 0, offset = 16;
int ascii_enabled = TRUE;
-long file_size = 0, top_pos = 0, cur_pos = 0, mark_point = 0;
+fileoffset_t file_size = 0, top_pos = 0, cur_pos = 0, mark_point = 0;
int scrlines;
* Main program
*/
int main(int argc, char **argv) {
- int newoffset = -1, newwidth = -1;
+ fileoffset_t newoffset = -1, newwidth = -1;
/*
* Parse command line arguments
}
switch (c) {
case 'o': case 'O':
- newoffset = strtol(value, NULL, 0); /* allow `0xXX' */
+ newoffset = parse_num(value, NULL);
break;
case 'w': case 'W':
- newwidth = strtol(value, NULL, 0);
+ newwidth = parse_num(value, NULL);
break;
}
break;
void fix_offset(void) {
if (3*width+11 > display_cols) {
width = (display_cols-11) / 3;
- sprintf (message, "Width reduced to %d to fit on the screen", width);
+ sprintf (message, "Width reduced to %"OFF"d to fit on the screen", width);
}
if (4*width+14 > display_cols) {
ascii_enabled = FALSE;
display_setup();
- display_define_colour(COL_BUFFER, 7, 0);
- display_define_colour(COL_SELECT, 0, 7);
- display_define_colour(COL_STATUS, 11, 4);
- display_define_colour(COL_ESCAPE, 9, 0);
- display_define_colour(COL_INVALID, 11, 0);
+ display_define_colour(COL_BUFFER, -1, -1, FALSE);
+ display_define_colour(COL_SELECT, 0, 7, TRUE);
+ display_define_colour(COL_STATUS, 11, 4, TRUE);
+ display_define_colour(COL_ESCAPE, 9, 0, FALSE);
+ display_define_colour(COL_INVALID, 11, 0, FALSE);
for (i=0; i<256; i++) {
sprintf(hex[i], "%02X", i);
file_size = 0;
if ( (fp = fopen (fname, "rb")) ) {
if (eager_mode) {
- long len;
+ size_t len;
static char buffer[4096];
filedata = buf_new_empty();
}
fclose (fp);
assert(file_size == buf_length(filedata));
- sprintf(message, "loaded %s (size %ld == 0x%lX).",
+ sprintf(message, "loaded %s (size %"OFF"d == 0x%"OFF"X).",
fname, file_size, file_size);
} else {
filedata = buf_new_from_file(fp);
file_size = buf_length(filedata);
- sprintf(message, "opened %s (size %ld == 0x%lX).",
+ sprintf(message, "opened %s (size %"OFF"d == 0x%"OFF"X).",
fname, file_size, file_size);
}
new_file = FALSE;
*/
int save_file (void) {
FILE *fp;
- long pos = 0;
+ fileoffset_t pos = 0;
if (look_mode)
return FALSE; /* do nothing! */
static char buffer[SAVE_BLKSIZ];
while (pos < file_size) {
- long size = file_size - pos;
+ fileoffset_t size = file_size - pos;
if (size > SAVE_BLKSIZ)
size = SAVE_BLKSIZ;
*/
void draw_scr (void) {
int scrsize, scroff, llen, i, j;
- long currpos;
- int marktop, markbot, mark;
+ fileoffset_t currpos;
+ fileoffset_t marktop, markbot;
+ int mark;
char *p;
unsigned char c, *q;
char *linebuf;
* requiring highlighting: a hex bit and an ascii
* bit.
*/
- int localstart= (currpos<marktop?marktop:currpos) - currpos;
- int localstop = (currpos+llen>markbot ? markbot :
- currpos+llen) - currpos;
+ fileoffset_t localstart= (currpos<marktop ? marktop :
+ currpos) - currpos;
+ fileoffset_t localstop = (currpos+llen>markbot ? markbot :
+ currpos+llen) - currpos;
localstart += width-llen;
localstop += width-llen;
display_write_chars(linebuf, 11+3*localstart);
display_write_chars(linebuf+10+3*localstop,
2+3*width-3*localstop);
}
- } else
+ } else {
+ display_set_colour(COL_BUFFER);
display_write_chars(linebuf,
ascii_enabled ? 13+4*width : 10+3*width);
+ }
}
currpos += (currpos ? width : offset);
display_clear_to_eol();
display_refresh ();
}
+volatile int safe_update, update_required;
+void update (void);
+
/*
* Get a string, in the "minibuffer". Return TRUE on success, FALSE
* on break. Possibly syntax-highlight the entered string for
p++;
if (p<r && *p == '\\')
p++, display_set_colour(COL_ESCAPE);
- else if (p>=r || !isxdigit (*p))
+ else if (p>=r || !isxdigit ((unsigned char)*p))
display_set_colour(COL_INVALID);
- else if (p+1>=r || !isxdigit (p[1]))
+ else if (p+1>=r || !isxdigit ((unsigned char)p[1]))
p++, display_set_colour(COL_INVALID);
else
p+=2, display_set_colour(COL_ESCAPE);
p++;
if (*p == '\\')
*q++ = *p++;
- else if (p[1] && isxdigit(*p) && isxdigit(p[1])) {
+ else if (p[1] && isxdigit((unsigned char)*p) &&
+ isxdigit((unsigned char)p[1])) {
char buf[3];
buf[0] = *p++;
buf[1] = *p++;
#endif
}
-volatile int safe_update, update_required;
-
void update (void) {
display_recheck_size();
fix_offset ();
update_required = TRUE;
}
-long parse_num (char *buffer, int *error) {
+fileoffset_t parse_num (char *buffer, int *error) {
if (error)
*error = FALSE;
if (!buffer[strspn(buffer, "0123456789")]) {
/* interpret as decimal */
- return atoi(buffer);
+ return ATOOFF(buffer);
} else if (buffer[0]=='0' && (buffer[1]=='X' || buffer[1]=='x') &&
!buffer[2+strspn(buffer+2,"0123456789ABCDEFabcdef")]) {
- return strtol(buffer+2, NULL, 16);
+ return STRTOOFF(buffer+2, NULL, 16);
} else if (buffer[0]=='$' &&
!buffer[1+strspn(buffer+1,"0123456789ABCDEFabcdef")]) {
- return strtol(buffer+1, NULL, 16);
+ return STRTOOFF(buffer+1, NULL, 16);
} else {
return 0;
if (error)