+# Useful options you might want to put on the make command line:
+#
+# - `SLANG=yes' to build against libslang instead of libncurses
+# (libncurses is better and more reliable, but libslang might be
+# all you have on a particular platform if you're unlucky).
+#
+# - `XFLAGS=-DNO_LARGE_FILES' to leave out the 64-bit file access
+# support (restricts Tweak to editing files under 2Gb, but
+# should cause it to compile successfully on platforms without
+# fseeko and ftello and/or long long support).
+#
+# - `VERSION=X.XX' (for whatever X.XX you like) to cause the `make
+# release' target to build a release tarball called
+# `tweak-X.XX.tar.gz' which unpacks into a directory
+# `tweak-X.XX'. Note that you also need to modify the version
+# number in tweak.h, or else the resulting binary won't match
+# the version number on the archive.
+
CC := gcc
CFLAGS := -g -c -Wall $(XFLAGS)
LINK := gcc
+#include "tweak.h"
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
-#include "tweak.h"
-
static void act_exit (void);
static void act_save (void);
static void act_exitsave (void);
return NULL;
}
-static int begline(int x) {
- int y = x + width-offset;
+static fileoffset_t begline(fileoffset_t x) {
+ fileoffset_t y = x + width-offset;
y -= (y % width);
y -= width-offset;
if (y < 0)
return y;
}
-static int endline(int x) {
- int y = x + width-offset;
+static fileoffset_t endline(fileoffset_t x) {
+ fileoffset_t y = x + width-offset;
y -= (y % width);
y += width-1;
y -= width-offset;
}
static void act_right(void) {
- int new_top;
+ fileoffset_t new_top;
if (edit_type == 1) {
if (cur_pos < file_size)
}
static void act_end(void) {
- int new_top;
+ fileoffset_t new_top;
cur_pos = endline(cur_pos);
edit_type = !!edit_type;
}
static void act_down(void) {
- int new_top;
+ fileoffset_t new_top;
cur_pos += width;
if (cur_pos >= file_size) {
}
static void act_pgdn(void) {
- int new_top;
+ fileoffset_t new_top;
cur_pos += (scrlines-1) * width;
if (cur_pos >= file_size) {
}
static void act_bottom (void) {
- int new_top;
+ fileoffset_t new_top;
cur_pos = file_size;
edit_type = !!edit_type;
}
static void act_cut (void) {
- long marktop, marksize;
+ fileoffset_t marktop, marksize;
if (!marking || mark_point==cur_pos) {
display_beep();
}
static void act_copy (void) {
- int marktop, marksize;
+ fileoffset_t marktop, marksize;
if (!marking) {
display_beep();
}
static void act_paste (void) {
- int cutsize, new_top;
+ fileoffset_t cutsize, new_top;
cutsize = buf_length (cutbuffer);
if (!insert_mode) {
static void act_goto (void) {
char buffer[80];
- long position, new_top;
+ fileoffset_t position, new_top;
int error;
if (!get_str("Enter position to go to: ", buffer, FALSE))
}
static void act_search (void) {
- int len, posn, dfapos;
+ int len;
+ fileoffset_t posn, dfapos;
DFA dfa;
static unsigned char sblk[SEARCH_BLK];
static char withdef[] = "Search forward (default=last): ";
posn++;
dfapos = dfa[dfapos][*q++];
if (dfapos == len) {
- int new_top;
+ fileoffset_t new_top;
cur_pos = posn - len;
edit_type = !!edit_type;
}
static void act_search_backwards (void) {
- int len, posn, dfapos;
+ int len;
+ fileoffset_t posn, dfapos;
DFA dfa;
static unsigned char sblk[SEARCH_BLK];
static char withdef[] = "Search backward (default=last): ";
posn--;
dfapos = dfa[dfapos][*--q];
if (dfapos == len) {
- int new_top;
+ fileoffset_t new_top;
cur_pos = posn;
edit_type = !!edit_type;
static void act_width (void) {
char buffer[80];
char prompt[80];
- long w;
- long new_top;
+ fileoffset_t w;
+ fileoffset_t new_top;
int error;
- sprintf (prompt, "Enter screen width in bytes (now %d): ", width);
+ sprintf (prompt, "Enter screen width in bytes (now %"OFF"d): ", width);
if (!get_str (prompt, buffer, FALSE))
return;
w = parse_num (buffer, &error);
static void act_offset (void) {
char buffer[80];
char prompt[80];
- long o;
- long new_top;
+ fileoffset_t o;
+ fileoffset_t new_top;
int error;
- sprintf (prompt, "Enter start-of-file offset in bytes (now %d): ",
+ sprintf (prompt, "Enter start-of-file offset in bytes (now %"OFF"d): ",
realoffset);
if (!get_str (prompt, buffer, FALSE))
return;
+#include "tweak.h"
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
-#include "tweak.h"
#include "btree.h"
#ifdef TEST_BUFFER
};
struct bufblk {
- int len; /* number of bytes in block, always */
+ fileoffset_t len; /* number of bytes in block, always */
struct file *file; /* non-NULL indicates a file block */
- int filepos; /* only meaningful if fp!=NULL */
+ fileoffset_t filepos; /* only meaningful if fp!=NULL */
unsigned char *data; /* only used if fp==NULL */
};
-typedef int filesize; /* FIXME: should be larger */
-
static bt_element_t bufblkcopy(void *state, void *av)
{
struct bufblk *a = (struct bufblk *)av;
void bufblkpropmake(void *state, bt_element_t av, void *destv)
{
struct bufblk *a = (struct bufblk *)av;
- filesize *dest = (filesize *)destv;
+ fileoffset_t *dest = (fileoffset_t *)destv;
*dest = a->len;
}
/* s1 may be NULL (indicating copy s2 into dest). s2 is never NULL. */
void bufblkpropmerge(void *state, void *s1v, void *s2v, void *destv)
{
- filesize *s1 = (filesize *)s1v;
- filesize *s2 = (filesize *)s2v;
- filesize *dest = (filesize *)destv;
+ fileoffset_t *s1 = (fileoffset_t *)s1v;
+ fileoffset_t *s2 = (fileoffset_t *)s2v;
+ fileoffset_t *dest = (fileoffset_t *)destv;
if (!s1 && !s2) return; /* don't need to free anything */
*dest = *s2 + (s1 ? *s1 : 0);
}
static btree *buf_bt_new(void)
{
- return bt_new(NULL, bufblkcopy, bufblkfree, sizeof(filesize),
- alignof(filesize), bufblkpropmake, bufblkpropmerge,
+ return bt_new(NULL, bufblkcopy, bufblkfree, sizeof(fileoffset_t),
+ alignof(fileoffset_t), bufblkpropmake, bufblkpropmerge,
NULL, 2);
}
void **props, int *counts,
bt_element_t *elts, int *is_elt)
{
- int *disttogo = (int *)sstate;
- int distsofar = 0;
+ fileoffset_t *disttogo = (fileoffset_t *)sstate;
+ fileoffset_t distsofar = 0;
int i;
for (i = 0; i < ntrees; i++) {
struct bufblk *blk;
- int sublen = props[i] ? *(filesize *)props[i] : 0;
+ fileoffset_t sublen = props[i] ? *(fileoffset_t *)props[i] : 0;
if ((props[i] && *disttogo < distsofar + sublen) ||
(*disttogo == distsofar + sublen && i == ntrees-1)) {
return 0; /* placate gcc */
}
-static int buf_bt_find_pos(btree *bt, int pos, int *poswithin)
+static int buf_bt_find_pos(btree *bt, fileoffset_t pos, fileoffset_t *poswithin)
{
int index;
ret->file = NULL;
ret->filepos = 0;
ret->len = blk->len;
- fseek(blk->file->fp, blk->filepos, SEEK_SET);
+ fseeko(blk->file->fp, blk->filepos, SEEK_SET);
fread(ret->data, blk->len, 1, blk->file->fp);
return ret;
static int buf_bt_cleanup(btree *bt, int index)
{
struct bufblk *a, *b, *cvt;
- int totallen;
+ fileoffset_t totallen;
unsigned char tmpdata[BLKMAX*2];
if (index < 0) return 0;
}
}
-static int buf_bt_splitpoint(btree *bt, int pos)
+static int buf_bt_splitpoint(btree *bt, fileoffset_t pos)
{
- int poswithin, index;
+ fileoffset_t poswithin;
+ int index;
struct bufblk *blk, *newblk;
index = buf_bt_find_pos(bt, pos, &poswithin);
return index + 1;
}
-static btree *buf_bt_split(btree *bt, int pos, int before)
+static btree *buf_bt_split(btree *bt, fileoffset_t pos, int before)
{
int index = buf_bt_splitpoint(bt, pos);
return bt_splitpos(bt, index, before);
return ret;
}
-static void buf_insert_bt(buffer *buf, btree *bt, int pos)
+static void buf_insert_bt(buffer *buf, btree *bt, fileoffset_t pos)
{
btree *right = buf_bt_split(buf->bt, pos, FALSE);
buf->bt = buf_bt_join(buf->bt, bt);
void **props, int *counts,
bt_element_t *elts, int *is_elt)
{
- int *output = (int *)sstate;
- int i, size = 0;
+ fileoffset_t *output = (fileoffset_t *)sstate;
+ fileoffset_t size = 0;
+ int i;
for (i = 0; i < ntrees; i++) {
struct bufblk *blk;
if (props[i])
- size += *(filesize *)props[i];
+ size += *(fileoffset_t *)props[i];
if (i < ntrees-1) {
blk = (struct bufblk *)elts[i];
return 1;
}
-static int buf_bt_length(btree *bt)
+static fileoffset_t buf_bt_length(btree *bt)
{
- int length;
+ fileoffset_t length;
bt_propfind(bt, bufblklensearch, &length, NULL);
return length;
}
-extern int buf_length(buffer *buf)
+extern fileoffset_t buf_length(buffer *buf)
{
return buf_bt_length(buf->bt);
}
blk->file = file;
blk->filepos = 0;
- fseek(fp, 0, SEEK_END);
- blk->len = ftell(fp);
+ fseeko(fp, 0, SEEK_END);
+ blk->len = ftello(fp);
bt_addpos(buf->bt, blk, 0);
return buf;
}
-extern void buf_fetch_data(buffer *buf, void *vdata, int len, int pos)
+extern void buf_fetch_data(buffer *buf, void *vdata, int len, fileoffset_t pos)
{
- int index, poswithin, thislen;
+ int index;
+ fileoffset_t poswithin;
+ fileoffset_t thislen;
unsigned char *data = (unsigned char *)vdata;
index = buf_bt_find_pos(buf->bt, pos, &poswithin);
thislen = len;
if (blk->file) {
- fseek(blk->file->fp, blk->filepos + poswithin, SEEK_SET);
+ fseeko(blk->file->fp, blk->filepos + poswithin, SEEK_SET);
fread(data, thislen, 1, blk->file->fp);
} else {
memcpy(data, blk->data + poswithin, thislen);
}
}
-extern void buf_insert_data(buffer *buf, void *vdata, int len, int pos)
+extern void buf_insert_data(buffer *buf, void *vdata, int len,
+ fileoffset_t pos)
{
btree *bt = buf_bt_new();
int nblocks, blklen1, extra;
buf_insert_bt(buf, bt, pos);
}
-extern void buf_delete(buffer *buf, int len, int pos)
+extern void buf_delete(buffer *buf, fileoffset_t len, fileoffset_t pos)
{
btree *left = buf_bt_split(buf->bt, pos, TRUE);
btree *right = buf_bt_split(buf->bt, len, FALSE);
buf->bt = buf_bt_join(left, right);
}
-extern void buf_overwrite_data(buffer *buf, void *data, int len, int pos)
+extern void buf_overwrite_data(buffer *buf, void *data, int len,
+ fileoffset_t pos)
{
buf_delete(buf, len, pos);
buf_insert_data(buf, data, len, pos);
}
-extern buffer *buf_cut(buffer *buf, int len, int pos)
+extern buffer *buf_cut(buffer *buf, fileoffset_t len, fileoffset_t pos)
{
btree *left = buf_bt_split(buf->bt, pos, TRUE);
btree *right = buf_bt_split(buf->bt, len, FALSE);
return buf_new_from_bt(ret);
}
-extern buffer *buf_copy(buffer *buf, int len, int pos)
+extern buffer *buf_copy(buffer *buf, fileoffset_t len, fileoffset_t pos)
{
btree *left = buf_bt_split(buf->bt, pos, TRUE);
btree *right = buf_bt_split(buf->bt, len, FALSE);
return buf_new_from_bt(ret);
}
-extern void buf_paste(buffer *buf, buffer *cutbuffer, int pos)
+extern void buf_paste(buffer *buf, buffer *cutbuffer, fileoffset_t pos)
{
btree *bt = bt_clone(cutbuffer->bt);
buf_insert_bt(buf, bt, pos);
static FILE *debugfp = NULL;
extern void buffer_diagnostic(buffer *buf, char *title)
{
- int i, offset;
+ int i;
+ fileoffset_t offset;
struct bufblk *blk;
if (!debugfp) {
fprintf(debugfp, "Listing of buffer [%s]:\n", title);
offset = 0;
for (i = 0; (blk = (struct bufblk *)bt_index(buf->bt, i)) != NULL; i++) {
- fprintf(debugfp, "%08x: %p, len =%8d,", offset, blk, blk->len);
+ fprintf(debugfp, "%016"OFF"x: %p, len =%8"OFF"d,", offset, blk, blk->len);
if (blk->file) {
- fprintf(debugfp, " file %p pos %8d\n", blk->file, blk->filepos);
+ fprintf(debugfp, " file %p pos %8"OFF"d\n", blk->file, blk->filepos);
} else {
int j;
+#include "tweak.h"
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
-
#include <curses.h>
-#include "tweak.h"
-
int display_rows, display_cols;
void display_beep(void)
+#include "tweak.h"
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
-#include "tweak.h"
-
typedef union keytab keytab;
union keytab {
/*
* TODO possibly after that:
*
- * - Need to handle >2Gb files! Up the `filesize' type to long
- * long, and use it everywhere (not just in buffer.c).
- *
* - Multiple buffers, multiple on-screen windows.
* + ^X^F to open new file
* + ^X^R to open new file RO
* _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;
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);
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)
+#include "tweak.h"
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
-#include "tweak.h"
-
#if defined(unix) && !defined(GO32)
#define RCNAME ".tweakrc"
#elif defined(MSDOS)
+#include "tweak.h"
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include "tweak.h"
-
static DFA build_dfa (char *pattern, int len)
{
int i, j, k, b;
+#include "tweak.h"
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <slang.h>
-#include "tweak.h"
-
#if defined(unix) && !defined(GO32)
static int sigwinch (int sigtype)
{
#ifndef TWEAK_TWEAK_H
#define TWEAK_TWEAK_H
+#ifndef NO_LARGE_FILES
+
+#ifndef _LARGEFILE_SOURCE
+#define _LARGEFILE_SOURCE
+#endif
+#ifndef _FILE_OFFSET_BITS
+#define _FILE_OFFSET_BITS 64
+#endif
+
+#endif
+
#ifndef FALSE
#define FALSE 0
#endif
#define NULL64 NULL16,NULL16,NULL16,NULL16
#define NULL256 NULL64,NULL64,NULL64,NULL64
+#include <stdio.h>
+
+#ifdef NO_LARGE_FILES
+typedef int fileoffset_t; /* used for all file offsets */
+#define OFF
+#define ATOOFF atoi
+#define STRTOOFF strtol
+#define fseeko fseek
+#define ftello ftell
+#else
+typedef long long fileoffset_t; /* used for all file offsets */
+#define OFF "ll"
+#define ATOOFF atoll
+#define STRTOOFF strtoll
+#endif
+
typedef int (*DFA)[256];
typedef struct {
int len;
extern char last_char, *pname, *filename;
extern buffer *filedata, *cutbuffer;
extern int fix_mode, look_mode, insert_mode, edit_type, finished, marking;
-extern long file_size, top_pos, cur_pos, mark_point;
+extern fileoffset_t file_size, top_pos, cur_pos, mark_point;
extern int scrlines, modified, new_file;
-extern int width, offset, realoffset, ascii_enabled;
+extern fileoffset_t width, offset, realoffset;
+extern int ascii_enabled;
#ifdef unix
extern volatile int safe_update, update_required;
#endif
extern void fix_offset(void);
-extern long parse_num (char *buffer, int *error);
+extern fileoffset_t parse_num (char *buffer, int *error);
extern void draw_scr (void);
extern int backup_file (void);
extern buffer *buf_new_from_file(FILE *fp);
extern void buf_free(buffer *buf);
-extern void buf_insert_data(buffer *buf, void *data, int len, int pos);
-extern void buf_fetch_data(buffer *buf, void *data, int len, int pos);
-extern void buf_overwrite_data(buffer *buf, void *data, int len, int pos);
-extern void buf_delete(buffer *buf, int len, int pos);
-extern buffer *buf_cut(buffer *buf, int len, int pos);
-extern buffer *buf_copy(buffer *buf, int len, int pos);
-extern void buf_paste(buffer *buf, buffer *cutbuffer, int pos);
-extern int buf_length(buffer *buf);
+extern void buf_insert_data(buffer *buf, void *data, int len,
+ fileoffset_t pos);
+extern void buf_fetch_data(buffer *buf, void *data, int len, fileoffset_t pos);
+extern void buf_overwrite_data(buffer *buf, void *data, int len,
+ fileoffset_t pos);
+extern void buf_delete(buffer *buf, fileoffset_t len, fileoffset_t pos);
+extern buffer *buf_cut(buffer *buf, fileoffset_t len, fileoffset_t pos);
+extern buffer *buf_copy(buffer *buf, fileoffset_t len, fileoffset_t pos);
+extern void buf_paste(buffer *buf, buffer *cutbuffer, fileoffset_t pos);
+extern fileoffset_t buf_length(buffer *buf);
extern void display_setup(void);
extern void display_cleanup(void);