diff options
| author | Ian C <ianc@noddybox.co.uk> | 2005-05-04 01:12:19 +0000 | 
|---|---|---|
| committer | Ian C <ianc@noddybox.co.uk> | 2005-05-04 01:12:19 +0000 | 
| commit | 2d8a5ef444abc653e5976b73993a6e31948ae348 (patch) | |
| tree | 5f49c3382118d421d2c2605165e48daaddf5dd8b /xed.c | |
| parent | 8244355066c0dd5db3aa03a7fee341981881eee2 (diff) | |
This commit was generated by cvs2svn to compensate for changes in r2,
which included commits to RCS files with non-trunk default branches.
Diffstat (limited to 'xed.c')
| -rw-r--r-- | xed.c | 1619 | 
1 files changed, 1619 insertions, 0 deletions
| @@ -0,0 +1,1619 @@ +/* +    xed - Simple hex editor + +    Copyright (C) 2005  Ian Cowburn (ianc@noddybox.demon.co.uk) + +    This program is free software; you can redistribute it and/or modify +    it under the terms of the GNU General Public License as published by +    the Free Software Foundation; either version 2 of the License, or +    (at your option) any later version. + +    This program is distributed in the hope that it will be useful, +    but WITHOUT ANY WARRANTY; without even the implied warranty of +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +    GNU General Public License for more details. + +    You should have received a copy of the GNU General Public License +    along with this program; if not, write to the Free Software +    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + +    ------------------------------------------------------------------------- + +*/ +static const char id[]="$Id:"; + +#include <sys/types.h> +#include <curses.h> +#include <stdlib.h> +#include <stdio.h> +#include <fcntl.h> +#include <ctype.h> +#include <signal.h> +#include <stdarg.h> +#include <regex.h> +#include <string.h> + +#include "xedkeys.h" + +#define	VERSION		"V2.0" +#define USAGE		"[-x] [-i] [-r] [-c] [-R] file" + +#define NONE		0 +#define HEX		1 +#define ASCII		2 +#define REGEXP		3 + +#define FILENAME_LEN	25 + +#define GETSTR_LEN	80 +#define GETSTR_DISP_LEN	50 + +#define BUFSIZE(x)	((((x)/1024)+1)*1024) + +#define CTYPE(func,c)   (((c>=0)&&(c<=255)) ? func(c) : (c)) +#define CTEST(func,c)   (((c>=0)&&(c<=255)) ? func(c) : (FALSE)) + +#define IPBUFFSIZE	1024 + +typedef unsigned char	uchar; + +char	*name; +char	*filename; +char	print_name[FILENAME_LEN+1]; +uchar	*edit; +uchar	*mirror; +long	bufsize; +int	in_place=FALSE; +int	regexp=FALSE; +int	casesense=TRUE; +int	readonly=FALSE; +int	fd; +long	file_len; +long	page_ptr; +long	file_ptr; +long	end_page; +long	page_depth; +int	edit_hex=TRUE; +int	overtype=TRUE; +int	editted=FALSE; + +int	last_search=NONE; +char	sch_str[GETSTR_LEN]; +int	sch_hex[128]; +int	sch_no; + +regex_t	re; +int	re_alloc=FALSE; + +/* Function prototypes +*/ +void	Err(const char *s); +void	SysErr(const char *p); +void	MainCode(void); +int	HandleKey(int key); +int	HandleKeyHex(int key); +void	HandleKeyAscii(int key); +int	CompileRegExp(void); +void	SearchRegExp(void); +void	DoSearchRegExp(void); +void	SearchString(void); +void	DoSearchString(void); +void	SearchHex(void); +void	DoSearchHex(void); +int	Read(int fd, void *buff, int no); +int	Write(int fd, void *buff, int no); +void	OpenFile(void); +void	SaveFile(void); +int	CalcHex(int x[]); +int	GetByte(long cur); +char	*GetByteString(long *cur, int all_lower); +int	GetLastSaved(long cur); +void	Display(void); +void	PartialDisplay(long cur, int x, int y); +void	InsertValue(long p,long b); +void	DeleteValue(long p); +void	ReplaceValue(long p,long b); +void	UpdateValue(long p, int b); +void	ShowCursor(void); +void	ShowPos(void); +int	ScanKey(void); +int	GetKey(int allkeys); +void	GetString(char s[]); +char	*Get(char *p); +int	GetChar(char *p, char *v); +void	Message(const char *fmt, ...); +char	*Tail(char s[], int l); + + +int main(int argc, char *argv[]) +{ +    char *env,*arg,*list[256];	/* If you're that prepared to break it, you */ +    int listc;			/* DESERVE to get a segmentation fault */ +    int src,dest,f; + +    name=argv[0]; + +    /* Prepend XEDARG variable if present +    */ +    src=0; +    dest=0; +    if (env=getenv("XEDARG")) +    { +	arg=strtok(env," \t"); + +	while(arg) +	{ +	    list[dest++]=arg; +	    arg=strtok(NULL," \t"); +	} +    } + +    for(f=1;f<argc;f++) +    	list[dest++]=argv[f]; + +    listc=dest; + +    if (listc<1) +    { +        fprintf(stderr,"%s:usage %s %s\n",name,name,USAGE); +        exit(EXIT_FAILURE); +    } + +    f=0; +    while(*list[f]=='-') +    { +	switch (*(list[f]+1)) +	{ +	    case 'x': +		in_place=TRUE; +		break; +	    case 'i': +		overtype=FALSE; +		break; +	    case 'r': +		regexp=TRUE; +		break; +	    case 'c': +		casesense=FALSE; +		break; +	    case 'R': +		readonly=TRUE; +		break; +	    default: +		fprintf(stderr,"%s:usage %s %s\n",name,name,USAGE); +		exit(EXIT_FAILURE); +		break; +	} +	f++; + +	if (f==listc) +	{ +	    fprintf(stderr,"%s:usage %s %s\n",name,name,USAGE); +	    exit(EXIT_FAILURE); +	} +    } + +    filename=list[f]; + +    strcpy(print_name,Tail(filename,FILENAME_LEN)); + +    signal(SIGINT,SIG_IGN); + +    initscr(); +    cbreak(); +    noecho(); +    keypad(stdscr,TRUE); + +    MainCode(); + +    erase(); +    refresh(); + +    if (in_place) +        if (close(fd)==-1) +            SysErr(filename); + +    endwin(); + +    return EXIT_SUCCESS; +} + + +void Err(const char *s) +{ +    endwin(); + +    fprintf(stderr,"%s: %s\n",name,s); +    exit(EXIT_FAILURE); +} + + +void SysErr(const char *p) +{ +    endwin(); + +    if (p) +	perror(p); +    else +	perror(name); + +    exit(EXIT_FAILURE); +} + + +void MainCode(void) +{ +    char errstr[80]; +    int quit=FALSE; +    int ch; + +    if (COLS<80) +    { +	sprintf +	    (errstr, +		"Terminal width (%d) less than required minimum (80)",COLS); +        Err(errstr); +    } + +    if (LINES<10) +    { +	sprintf +	    (errstr, +		"Terminal depth (%d) less than required minimum (10)",LINES); +        Err(errstr); +    } + +    OpenFile(); + +    file_ptr=page_ptr=0L; + +    Display(); + +    Message(VERSION); +    ShowCursor(); + +    while(!quit) +    { +        switch (HandleKey(GetKey(TRUE))) +	{ +            case FALSE: +                if ((editted)&&(!in_place)) +		{ +                    ch=GetChar +                        ("File has been editted.  Quit (y/[n])?","yYnN\n"); + +                    if ((ch=='y')||(ch=='Y')) +                        quit=TRUE; +		} +                else +                    quit=TRUE; + +                break; +            case TRUE: +                break; +	} +    } +} + + +int HandleKey(int key) +{ +    int finished; + +    if (edit_hex) +    { +        HandleKeyHex(key); +        return ((key!='q')&&(key!='Q')&&(key!=3)); +    } +    else +    { +        HandleKeyAscii(key); +        return (key!=3); +    } +} + + +int HandleKeyHex(int key) +{ +    char *s; +    int hex[2],next_key,old_val; +    int ch; + +    switch(key) +    { +        case CURS_UP1: +        case CURS_UP2: +            if (file_ptr>15) +	    { +                file_ptr-=16; + +                if (file_ptr<page_ptr) +		{ +                    page_ptr-=16; + +                    if (page_ptr<0) +                        page_ptr=0; + +                    Display(); +		} +                else +                    ShowCursor(); +	    } +            break; + +        case CURS_LEFT1: +        case CURS_LEFT2: +            if (file_ptr) +	    { +                file_ptr--; + +                if (file_ptr<page_ptr) +		{ +                    page_ptr-=16; + +                    if (page_ptr<0) +                        page_ptr=0; + +                    Display(); +		} +                else +                    ShowCursor(); +	    } +            break; + +        case CURS_DOWN1: +        case CURS_DOWN2: +        case '\n': +            if (file_ptr<(file_len-1)) +	    { +                file_ptr+=16; + +		if (file_ptr>(file_len-1)) +		    file_ptr=file_len-1; + +                if (file_ptr>end_page) +		{ +                    page_ptr+=16; +                    Display(); +		} +                else +                    ShowCursor(); +	    } +            break; + +        case CURS_RIGHT1: +        case CURS_RIGHT2: +            if (file_ptr<(file_len-1)) +	    { +                file_ptr++; + +                if (file_ptr>end_page) +		{ +                    page_ptr+=16; +                    Display(); +		} +                else +                    ShowCursor(); +	    } +            break; + +        case PAGE_BACK1: +        case PAGE_BACK2: +        case PAGE_BACK3: +            if (file_ptr>=page_depth) +	    { +                page_ptr-=page_depth; + +                if (page_ptr<0) +                    page_ptr=0; + +                file_ptr-=page_depth; + +                Display(); +	    } +            break; + +        case PAGE_FWD1: +        case PAGE_FWD2: +        case PAGE_FWD3: +            if (page_ptr<=file_len-page_depth-1) +	    { +                page_ptr+=page_depth; + +                file_ptr+=page_depth; + +		if (file_ptr>(file_len-1)) +		    file_ptr=file_len-1; + +                Display(); +	    } +            break; + +        case SWITCH_TO_ASCII: +            edit_hex=FALSE; +            ShowCursor(); +            break; + +        case START_OF_FILE: +            page_ptr=file_ptr=0L; +            Display(); +            break; + +        case END_OF_FILE: +            page_ptr=file_len-page_depth; + +            if (page_ptr<0) +                page_ptr=0; + +            file_ptr=file_len-1; +            Display(); +            break; + +        case JUMP_TO: +            s=Get("Address to jump to (prefix with 0x for hex) : "); + +            page_ptr=strtol(s,(char **)NULL,0); + +            if (page_ptr<0) +                page_ptr=0; + +            if (page_ptr>=file_len) +                page_ptr=file_len-1; + +            file_ptr=page_ptr; + +            if ((page_ptr>file_len-page_depth)&&(page_depth<file_len)) +	    { +                page_ptr=file_len-page_depth; + +                if (page_ptr<0) +                    page_ptr=0; +	    } + +            Display(); + +            break; + +        case SAVE: +	    if (!readonly) +	    { +		if (!in_place) +		{ +		    SaveFile(); + +		    editted=FALSE; +		} +		else +		    Message("All changes already saved in -x mode!"); +	    } +	    else +		Message("File is read-only!"); + +            ShowCursor(); +            break; + +        case RESTORE_BYTE: +	    if (!readonly) +	    { +		if (!in_place) +		{ +		    if (file_len) +		    { +			ReplaceValue +				(file_ptr,(uchar)GetLastSaved(file_ptr)); + +			if (file_ptr<(file_len)-1) +			{ +			    file_ptr++; + +			    if (file_ptr>end_page) +			    { +				page_ptr+=16; +				Display(); +			    } +			    else +				ShowCursor(); +			} +		    } +		} +		else +		    Message("Can't recover in -x mode!"); +	    } +	    else +		Message("File is read-only!"); + +            ShowCursor(); +            break; + +        case REFRESH: +            Display(); +            break; + +        case INSERT_TOGGLE: +	    if (!readonly) +		if (in_place) +		{ +		    Message("no insert/delete in -x mode"); +		    ShowCursor(); +		} +		else +		{ +		    overtype=!overtype; +		    ShowPos(); +		    ShowCursor(); +		} +            break; + +        case DELETE_CHAR: +	    if (!readonly) +	    { +		if (in_place) +		    Message("no insert/delete in -x mode"); +		else +		    if (file_len) +		    { +			editted=TRUE; + +			DeleteValue(file_ptr); + +			if ((file_ptr>=file_len)&&(file_len)) +			    if (--file_ptr<page_ptr) +				page_ptr=file_ptr; + +			Display(); +		    } +	    } +	    else +		Message ("File is read-only!"); + +	    ShowCursor(); +            break; + +        case FIND_STRING: +	    if (!regexp) +	    { +		ch=GetChar("(S)tring or (N)umber search ? ","sSnN\n"); + +		if ((ch=='N')||(ch=='n')) +		{ +		    SearchHex(); +		    Display(); +		} +		else +		{ +		    if ((ch=='S')||(ch=='s')) +		    { +			SearchString(); +			Display(); +		    } +		    else +			ShowCursor(); +		} +	    } +	    else +	    { +		SearchRegExp(); + +		if (last_search==REGEXP) +		    Display(); +		else +		    ShowCursor(); +	    } + +            break; + +        case FIND_NEXT: +	    switch (last_search) +	    { +            	case NONE: +		    Message("No previous search!"); +		    ShowCursor(); +                    break; +                case HEX: +                    DoSearchHex(); +                    Display(); +                    break; +                case ASCII: +		    DoSearchString(); +		    Display(); +                    break; +		case REGEXP: +		    DoSearchRegExp(); +		    Display(); +                    break; +	    } +            break; + +	case FIND_TYPE: +	    regexp=!regexp; +            ShowCursor(); +	    break; + +	case FIND_CASE: +	    casesense=!casesense; + +	    if (last_search==REGEXP) +		CompileRegExp(); + +            ShowCursor(); +	    break; + +        default: +	    if (!readonly) +	    { +		if (CTEST(isxdigit,key)) +		{ +		    old_val=GetByte(file_ptr); + +		    hex[0]=CTYPE(toupper,key); + +		    addch(hex[0]); +		    refresh(); + +		    next_key=GetKey(FALSE); + +		    while ((!CTEST(isxdigit,next_key))&& +				    (next_key!=8)&&(next_key!=127)) +			next_key=GetKey(FALSE); + +		    hex[1]=CTYPE(toupper,next_key); + +		    if (CTEST(isxdigit,next_key)) +		    { +			editted=TRUE; + +			UpdateValue(file_ptr,CalcHex(hex)); + +			/* Special case for the first char in an empty file */ +			if (file_len==0) +			    file_len=1; + +			if (file_ptr<(file_len)-1) +			{ +			    file_ptr++; + +			    if (file_ptr>end_page) +			    { +				page_ptr=file_ptr; +				Display(); +			    } +			    else +				ShowCursor(); +			} +			else +			    ShowCursor(); +		    } +		    else +		    { +			if (!overtype) +			    ReplaceValue(file_ptr,old_val); +			else +			    UpdateValue(file_ptr,old_val); + +			ShowCursor(); +		    } +		} +	    } +            break; +    } +} + + +void HandleKeyAscii(int key) +{ +    switch(key) +    { +        case ASC_CURS_UP1: +        case ASC_CURS_UP2: +            if (file_ptr>15) +	    { +                file_ptr-=16; + +                if (file_ptr<page_ptr) +		{ +                    page_ptr-=16; + +                    if (page_ptr<0) +                        page_ptr=0; + +                    Display(); +		} +                else +                    ShowCursor(); +	    } +            break; + +        case ASC_CURS_LEFT1: +        case ASC_CURS_LEFT2: +            if (file_ptr) +	    { +                file_ptr--; + +                if (file_ptr<page_ptr) +		{ +                    page_ptr-=16; + +                    if (page_ptr<0) +                        page_ptr=0; + +                    Display(); +		} +                else +                    ShowCursor(); +	    } +            break; + +        case ASC_CURS_DOWN1: +        case ASC_CURS_DOWN2: +            if (file_ptr<(file_len-1)) +	    { +                file_ptr+=16; + +		if (file_ptr>(file_len-1)) +		    file_ptr=file_len-1; + +                if (file_ptr>end_page) +		{ +                    page_ptr+=16; +                    Display(); +		} +                else +                    ShowCursor(); +	    } +            break; + +        case ASC_CURS_RIGHT1: +        case ASC_CURS_RIGHT2: +            if (file_ptr<(file_len)-1) +	    { +                file_ptr++; + +                if (file_ptr>end_page) +		{ +                    page_ptr+=16; +                    Display(); +		} +                else +                    ShowCursor(); +	    } +            break; + +        case ASC_PAGE_BACK: +            if (file_ptr>=page_depth) +	    { +                page_ptr-=page_depth; + +                if (page_ptr<0) +                    page_ptr=0; + +                file_ptr-=page_depth; + +                Display(); +	    } +            break; + +        case ASC_PAGE_FWD: +            if (page_ptr<=file_len-page_depth-1) +	    { +                page_ptr+=page_depth; + +                file_ptr+=page_depth; + +		if (file_ptr>(file_len-1)) +		    file_ptr=file_len-1; + +                Display(); +	    } +            break; + +        case ASC_REFRESH: +            Display(); +            break; + +        case SWITCH_TO_HEX: +            edit_hex=TRUE; +            ShowCursor(); +            break; + +        case INSERT_TOGGLE: +	    if (!readonly) +		if (in_place) +		{ +		    Message("no insert/delete in -x mode"); +		    ShowCursor(); +		} +		else +		{ +		    overtype=!overtype; +		    ShowPos(); +		    ShowCursor(); +		} +            break; + +        case ASC_DELETE_CHAR: +	    if (!readonly) +	    { +		if (in_place) +		    Message("no insert/delete in -x mode"); +		else +		    if (file_len) +		    { +			DeleteValue(file_ptr); + +			if ((file_ptr>=file_len)&&(file_len)) +			    if (--file_ptr<page_ptr) +				page_ptr=file_ptr; + +			Display(); +		    } +	    } +	    else +		Message ("File is read-only!"); + +	    ShowCursor(); +            break; + +        default: +	    if (!readonly) +		if (CTEST(isprint,key)) +		{ +		    editted=TRUE; + +		    UpdateValue(file_ptr,key); + +		    /* Special case for the first char in an empty file */ +		    if (file_len==0) +			file_len=1; + +		    if (file_ptr<(file_len)-1) +		    { +			file_ptr++; + +			if (file_ptr>end_page) +			{ +			    page_ptr=file_ptr; +			    Display(); +			} +			else +			    ShowCursor(); +		    } +		    else +			ShowCursor(); +		} +            break; +    } +} + +int CompileRegExp(void) +{ +    char buff[80]; +    int ret; + +    if (re_alloc) +	regfree(&re); + +    re_alloc=FALSE; + +    if (casesense) +	ret=regcomp(&re,sch_str,REG_EXTENDED|REG_NEWLINE); +    else +	ret=regcomp(&re,sch_str,REG_EXTENDED|REG_ICASE|REG_NEWLINE); + +    if(ret!=0) +    { +	regerror(ret,&re,buff,80); +	Message ("RE error : %s",buff); +	return (FALSE); +    } + +    re_alloc=TRUE; + +    return TRUE; +} + +void SearchRegExp(void) +{ +    last_search=NONE; + +    strcpy(sch_str,Get("/")); + +    if (!strlen(sch_str)) +        return; + +    if (CompileRegExp()) +    { +	last_search=REGEXP; +	DoSearchRegExp(); +    } +} + +void DoSearchRegExp(void) +{ +    char *p; +    long f,of; +    regmatch_t re_match; + +    Message("Searching...."); + +    f=file_ptr+1; + +    of=f; +    p=GetByteString(&f,!casesense); +    while(p) +    { +	if (regexec(&re,p,1,&re_match,0)==0) +	{ +	    file_ptr=of+re_match.rm_so; + +	    if ((file_ptr<page_ptr)||(file_ptr>end_page)) +		page_ptr=file_ptr; + +	    free(p); +	    return; +	} + +	free(p); +	of=f; +	p=GetByteString(&f,!casesense); +    } + +    Message("Not found.  Press a key."); +    GetKey(TRUE); +    Message(""); +} + + +void SearchString(void) +{ +    last_search=NONE; + +    strcpy(sch_str,Get("Search string : ")); + +    if (!strlen(sch_str)) +        return; + +    last_search=ASCII; + +    DoSearchString(); +} + + +void DoSearchString(void) +{ +    long f; +    int l,r; + +    Message("Searching...."); + +    l=strlen(sch_str); + +    for(f=file_ptr+1;f<file_len-l+1;f++) +    { +        for(r=0;r<l;r++) +	    if (casesense) +	    { +		if (GetByte(f+r)!=sch_str[r]) +		    r=l+1; +	    } +	    else +	    { +		if (tolower(GetByte(f+r))!=tolower(sch_str[r])) +		    r=l+1; +	    } + +        if (r==l) +	{ +            file_ptr=f; + +            if ((file_ptr<page_ptr)||(file_ptr>end_page)) +                page_ptr=file_ptr; + +            return; +	} +    } + +    Message("Not found.  Press a key."); +    GetKey(TRUE); +    Message(""); +} + + +void SearchHex(void) +{ +    char *s; + +    last_search=NONE; +    sch_no=0; + +    s=Get("Enter First number (return to quit) : "); + +    while(*s) +    { +        sch_hex[sch_no++]=(int)strtol(s,(char **)NULL,0); +        s=Get("Enter next number (return to finish) : "); +    } + +    if (!sch_no) +        return; + +    last_search=HEX; + +    DoSearchHex(); +} + + +void DoSearchHex(void) +{ +    int f,r; + +    Message("Searching...."); + +    for(f=file_ptr+1;f<file_len-sch_no+1;f++) +    { +        for(r=0;r<sch_no;r++) +            if (GetByte(f+r)!=sch_hex[r]) +                r=sch_no+1; + +        if (r==sch_no) +	{ +            file_ptr=f; + +            if ((file_ptr<page_ptr)||(file_ptr>end_page)) +                page_ptr=file_ptr; + +            return; +	} +    } + +    Message("Not found.  Press a key"); +    GetKey(TRUE); +    Message(""); +} + + +/* Provide a skin to read(2) and write(2) +*/ +int Read(int fd, void *buff, int no) +{ +    int tot,rd; + +    tot=0; +    while(tot<no) +    { +	rd=read(fd,buff+tot,no-tot); + +	/* If we read zero bytes, it's probably the end of the file. +	*/ +	if (rd==0) +	    return tot; + +	/* Reading -1 leaves little room for argument! +	*/ +	if (rd==-1) +	    return -1; + +	tot+=rd; +    } + +    return tot; +} + + +int Write(int fd, void *buff, int no) +{ +    int tot,wr; + +    tot=0; +    while(tot<no) +    { +	wr=write(fd,buff+tot,no-tot); + +	if ((wr==-1)||(wr==0)) +	    return -1; + +	tot+=wr; +    } + +    return tot; +} + + +void OpenFile(void) +{ +    if (readonly) +    { +	if ((fd=open(filename,O_RDONLY))==-1) +	    SysErr(filename); +    } +    else +    { +	if ((fd=open(filename,O_RDWR))==-1) +	    SysErr(filename); +    } + +    if ((file_len=lseek(fd,0L,SEEK_END))==-1) +	SysErr(filename); + +    lseek(fd,0L,SEEK_SET); + +    if (!in_place) +    { +        if (!(edit=(uchar *)malloc(bufsize=BUFSIZE(file_len)))) +            SysErr(NULL); + +        if (!(mirror=(uchar *)malloc(bufsize))) +            SysErr(NULL); + +        if (Read(fd,edit,file_len)!=file_len) +            SysErr(filename); + +        memcpy(mirror,edit,file_len); + +        close(fd); +    } +} + + +void SaveFile(void) +{ +    Message("Writing..."); + +    if((fd=open(filename,O_WRONLY|O_TRUNC))==-1) +        SysErr(filename); + +    if (Write(fd,edit,file_len)!=file_len) +        SysErr(filename); + +    close(fd); + +    memcpy(mirror,edit,file_len); + +    Message("Done"); +} + + +int CalcHex(int x[]) +{ +    static char hex_digits[]="0123456789ABCDEF"; + +    int h,l; + +    for(h=0;(h<16)&&(x[0]!=hex_digits[h]);h++); +    for(l=0;(l<16)&&(x[1]!=hex_digits[l]);l++); + +    if ((h==16)||(l==16)) +        Err("CalcHex() broken!"); + +    return(h*16+l); +} + + +int GetByte(long cur) +{ +    static uchar ipbuff[IPBUFFSIZE]; +    static long buffpos; +    static int first_read=TRUE; +    uchar c; + +    if (cur>=file_len) +        return -1; + +    if(!in_place) +        return edit[cur]; + +    if (first_read) +	first_read=FALSE; +    else +	if ((cur>=buffpos)&&(cur<buffpos+IPBUFFSIZE)) +	    return ipbuff[cur-buffpos]; + +    if (lseek(fd,cur,SEEK_SET)==-1) +    	SysErr(filename); + +    if(Read(fd,ipbuff,IPBUFFSIZE)==-1) +        SysErr(filename); + +    buffpos=cur; + +    return ipbuff[cur-buffpos]; +} + + +char *GetByteString(long *cur, int all_lower) +{ +    char *p; +    long l,cp; +    int b; + +    cp=*cur; + +    if (cp>=file_len) +        return NULL; + +    l=0; + +    while(((b=GetByte(cp++))!=-1)&&(b!=0)&&(b!='\n')) +	l++; + +    if (!l) +    { +	if (!(p=(char *)malloc(0x1))) +	    SysErr(NULL); +	*p=0; +	*cur+=1; +	return p; +    } + +    if (!(p=(char *)malloc((int)l+1))) +	SysErr(NULL); + +    for(cp=0;cp<l;cp++) +	*(p+cp)=(all_lower) ? (tolower(GetByte((*cur)+cp))) : +					    (GetByte((*cur)+cp)); + +    *(p+cp)=0; + +    *cur+=l+1; + +    return p; +} + + +int GetLastSaved(long cur) +{ +    return (int)mirror[cur]; +} + + +void Display(void) +{ +    int r,f,b; +    long cur; + +    erase(); + +    mvprintw(0,0,"File : %s",print_name); + +    r=3; +    cur=page_ptr; + +    while(r<LINES-3) +    { +        mvprintw(r,0,"%8.8X :",cur); + +        for(f=0;f<16;f++) +            if ((b=GetByte(cur++))==-1) +                mvaddstr(r,11+f*3,"**"); +            else +	    { +                mvprintw(r,11+f*3,"%2.2X",(uchar)b); + +                if ((b<32)||(b>126)) +                    mvaddch(r,62+f,(chtype)'.'); +                else +                    mvaddch(r,62+f,(chtype)b); +	    } +        r++; +    } + +    end_page=cur-1; +    page_depth=end_page-page_ptr+1; + +    ShowCursor(); +} + + +void PartialDisplay(long cur, int x, int y) +{ +    int r,f,b; + +    r=y; + +    while(r<LINES-3) +    { +        if (!x) +            mvprintw(r,0,"%8.8X :",cur); + +        for(f=x;f<16;f++) +            if ((b=GetByte(cur++))==-1) +                mvaddstr(r,11+f*3,"**"); +            else +	    { +                mvprintw(r,11+f*3,"%2.2X",(uchar)b); + +                if ((b<32)||(b>126)) +                    mvaddch(r,62+f,(chtype)'.'); +                else +                    mvaddch(r,62+f,(chtype)b); +	    } + +        x=0; +        r++; +    } +} + + +void InsertValue(long p,long b) +{ +    if (++file_len>bufsize) +        { +        if (!(edit=(uchar *)realloc(edit,(bufsize=BUFSIZE(file_len))))) +            SysErr(NULL); + +        if (!(mirror=(uchar *)realloc(mirror,bufsize))) +            SysErr(NULL); +        } + +    memmove(edit+p+1,edit+p,file_len-p-1); +    memmove(mirror+p+1,mirror+p,file_len-p-1); + +    edit[p]=(uchar)b; +    mirror[p]=(uchar)b; +} + + +void DeleteValue(long p) +{ +    if (file_len>1) +    { +        memmove(edit+p,edit+p+1,file_len-p-1); +        memmove(mirror+p,mirror+p+1,file_len-p-1); + +        file_len--; +    } +    else +        file_len=0; +} + + +void ReplaceValue(long p,long b) +{ +    int x,y; +    uchar c=b; + +    edit[p]=(uchar)b; + +    y=3+(p-page_ptr)/16; +    x=(p-page_ptr)%16; + +    mvprintw(y,11+x*3,"%2.2X",(uchar)b); + +    if ((b<32)||(b>126)) +        mvaddch(y,62+x,(chtype)'.'); +    else +        mvaddch(y,62+x,(chtype)b); +} + + +void UpdateValue(long p, int b) +{ +    int x,y; +    uchar c=b; + +    if (!in_place) +    { +        if (overtype) +            edit[p]=(uchar)b; +        else +            InsertValue(p,b); +    } +    else +    { +        lseek(fd,p,SEEK_SET); +        if (Write(fd,&c,1)==-1) +            SysErr(filename); +    } + +    y=3+(p-page_ptr)/16; +    x=(p-page_ptr)%16; + +    if (overtype) +    { +        mvprintw(y,11+x*3,"%2.2X",(uchar)b); + +        if ((b<32)||(b>126)) +            mvaddch(y,62+x,(chtype)'.'); +        else +            mvaddch(y,62+x,(chtype)b); +    } +    else +        PartialDisplay(p,x,y); +} + + +void ShowCursor(void) +{ +    int x,y; + +    ShowPos(); + +    y=(file_ptr-page_ptr)/16; +    x=(file_ptr-page_ptr)%16; + +    if (edit_hex) +        move(3+y,11+x*3); +    else +        move(3+y,62+x); + +    refresh(); +} + + +void ShowPos(void) +{ +    mvprintw(1,0,"Pos : %8.8x",file_ptr); +    mvprintw(0,40,"File size : %8.8x",file_len); + +    /* Print Status line */ +    if (readonly) +	mvaddstr(1,20,"READ ONLY"); +    else +	if (overtype) +	    mvaddstr(1,20,"OVERTYPE"); +	else +	    mvaddstr(1,20," INSERT "); + +    if (regexp) +        mvaddstr(1,37,"REGEXP SEARCH"); +    else +        mvaddstr(1,37,"STRING SEARCH"); + +    if (casesense) +	mvaddstr(1,57," CASE SENSITIVE "); +    else +	mvaddstr(1,57,"CASE INSENSITIVE"); +} + + +int ScanKey(void) +{ +    int k; + +    k=getch(); + +    if (k==KEY_BACKSPACE) +	k=8; + +    if (k==ERR) +	k=3; + +    /* Message("Read key %9d",k); */ + +    return k; +} + + +int GetKey(int allkeys) +{ +    int k; + +    k=ScanKey(); + +    if (!allkeys) +	while(!CTEST(isascii,k)) +	    k=ScanKey(); + +    return k; +} + + +void GetString(char s[]) +{ +    int k,done,p,x,y; + +    done=FALSE; +    p=0; +    s[p]=0; +    getyx(stdscr,y,x); + +    while(!done) +    { +	mvprintw(y,x,"%-*.*s",GETSTR_DISP_LEN,GETSTR_DISP_LEN, +						Tail(s,GETSTR_DISP_LEN)); + +	move(y,x+((p>=GETSTR_DISP_LEN) ? (GETSTR_DISP_LEN) : (p))); + +	refresh(); + +	switch (k=GetKey(TRUE)) +	{ +	    case 8: +	    case 127: +		if (p) +		    s[--p]=0; +		break; + +	    case 3: +		strcpy(s,""); +		done=TRUE; +		break; + +	    case '\n': +		done=TRUE; +		break; + +	    default: +		if (p<GETSTR_LEN-1) +		{ +		    s[p++]=(char)k; +		    s[p]=0; +		} +		else +		    flash(); +	} +    } +} + + +char *Get(char *p) +{ +    static char s[GETSTR_LEN]; +    int f; + +    Message(p); + +    echo(); +    GetString(s); +    noecho(); + +    return s; +} + + +int GetChar(char *p, char *v) +{ +    int f,ch=0xff; + +    Message(p); + +    while(!strchr(v,ch)) +        ch=GetKey(TRUE); + +    ShowCursor(); + +    return ch; +} + + +void Message(const char *fmt, ...) +{ +    va_list arg; +    int f; + +    move(LINES-1,0); + +    for(f=0;f<COLS-2;f++) +        addch(' '); + +    va_start(arg,fmt); +    mvwprintw(stdscr,LINES-1,0,fmt,arg); +    va_end(arg); + +    refresh(); +} + + +char *Tail(char s[], int l) +{ +    static char ret[1024]; +    int sl,d; + +    if(strlen(s)<=l) +        strcpy(ret,s); +    else +        { +        sl=strlen(s); +        d=l; + +        while(d>-1) +            ret[d--]=s[sl--]; + +	ret[0]='.'; +	ret[1]='.'; +        } + +    return ret; +} + + +/* END OF FILE */ | 
