HexEditor written in C, using curses written in Xcode 6


Open Xcode

File -> New Project

OSX -> Application -> Command Line Tool

Next

Product Name: Hexedit

Organization: com.skills421

Language: C

compile on the command line using: gcc -o hexedit hexedit.c -lcurses

#include <curses.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define OFF 0
#define ASC 1
#define HEX 2

void keyoffset();
void keysearch();
void showcurr();
void delcurr();
void hexent();
void currdown(int delcur);
void currup(int delcur);
void ascent();
int redrawfl();
int getinpstr(char *str,int mx);
int checkrest(char *str);

FILE *f1, *fopen();
int linebuf[18],  cyp=0, cxp=0, llp, lastline=FALSE, maxl, modeon=OFF, holdchar; WINDOW *win;
long fp=0, lfp; char modetp[15], wron[10];

int main(int argc, const char * argv[])
{
    int c;

    if(argc!=2)
    {
        printf("Incorrect number of arguments\nUse hexedit filename");
        exit(1);
    }

    if((f1=fopen(argv[1],"r+"))==(FILE *) NULL)
    {
        printf("could not open file %s for input\n",argv[1]);
        exit(1);
    }

    initscr();
    curs_set(0);
    win=newwin(23,80,1,0);
    noecho();
    cbreak();
    nonl();
    intrflush(win,FALSE);
    keypad(win,TRUE);
    idlok(win,TRUE);    // allow hardware scrolling
    scrollok(win,TRUE);
    lfp = fseek(f1,0L,2);
    lfp = ftell(f1);
    llp=(lfp-1) %16;
    rewind(f1);
    maxl=redrawfl();

    strcpy(wron,"");
    strcpy(modetp,"");
    showcurr();

    while((c=wgetch(win)) != KEY_F0 && c!=26 && c!='x' && c!='X')
    {
        switch(c)
        {
            case KEY_RIGHT:
            case 12:
                delcurr();
                if(++cxp==16)
                {
                    cxp=0;
                    currdown(0);
                }
                else
                    showcurr();

                break;

            case KEY_LEFT:
            case 8:
                delcurr();
                if(--cxp==-1)
                {
                    cxp=15;
                    currup(0);
                }
                else
                    showcurr();

                break;

            case KEY_UP:
            case 11:
                currup(1);
                break;

            case KEY_DOWN:
            case 10:
                currdown(1);
                break;
                
            case 'H':
            case 'h':
                modeon=HEX;
                wmove(win,22,60);
                strcpy(modetp,"MODE HEX");
                wprintw(win,"%s   ",modetp);
                wrefresh(win);
                break;

            case 'A':
            case 'a':
                modeon=ASC;
                wmove(win,22,60);
                strcpy(modetp,"MODE ASCII");
                wprintw(win,"%s",modetp);
                wrefresh(win);
                break;

            case 'W':
            case 'w':
                if(!modeon)
                {
                    beep();
                    break;
                }
                if(modeon==ASC) ascent();
                if(modeon==HEX) hexent();
                break;

            case 'O':
            case 'o':
                modeon=OFF;
                wmove(win,22,60);
                wclrtoeol(win);
                wrefresh(win);
                break;
        
            case ':':
                keyoffset();
                break;

            case '/':
                keysearch();
                break;

            case 4:
                if(fp+672<lfp)
                {
                    delcurr();
                    fp+=336;
                    fseek(f1,fp,0);
                    redrawfl();
                    showcurr();
                }
                else
                    beep();

                break;

            case 21:
                if(fp>335)
                {
                    delcurr();
                    fp-=336;
                    redrawfl();
                    showcurr();
                }
                else
                    beep();

                break;
        }
    }

    endwin();
    fclose(f1);
    
}


int read16(int pos)
{
    int cnt;
    long tfp;

    tfp=fp+16*pos;
    fseek(f1,tfp,0);

    for(cnt=0;cnt<16;cnt++)
    {
        linebuf[cnt]=getc(f1);
        if(linebuf[cnt]==EOF)
            return(cnt);
    }

    return(16);
}

void displayline(int pos,int num)
{
    int cnt,c;
    long tfp;

    tfp=fp+16*pos;
    wmove(win,pos,0);
    wprintw(win,"%06x:  ",(int) tfp);

    for(cnt=0;cnt<num;cnt++)
    {
        wprintw(win,"%02x ",linebuf[cnt]);
    }
    wmove(win,pos,62);

    for(cnt=0;cnt<num;cnt++)
    {
        c=(linebuf[cnt]>31 && linebuf[cnt]<126) ? linebuf[cnt] : '.';
        waddch(win,c);
    }

    wrefresh(win);
}

void showcurr()
{
    int c;
    
    if(cyp==maxl && lastline && cxp>llp) cxp=llp;
    wmove(win,cyp,3*cxp+8);
    waddch(win,'>');
    wmove(win,cyp,3*cxp+11);
    waddch(win,'<');
    c=mvwinch(win,cyp,cxp+62);
    wattrset(win,A_STANDOUT);
    waddch(win,c);
    wattrset(win,0);
    holdchar=c;
    wrefresh(win);
}

void delcurr()
{
    wmove(win,cyp,3*cxp+8);
    waddch(win,' ');
    wmove(win,cyp,3*cxp+11);
    waddch(win,' ');
    wmove(win,cyp,cxp+62);
    waddch(win,holdchar);
}

void currdown(int delcur)
{
    int num;
long tfp;

if(delcur) delcurr();

if(++cyp<=maxl) 
    showcurr();
    else
    {
        cyp=maxl;

        if(fp+336<lfp)
        {
            tfp=ftell(f1);
            fp+=16;
            if(fp+336>=lfp) lastline=TRUE;
            num=read16(20);
            fseek(f1,tfp,0);
            if(modeon)
            {
                wmove(win,22,45);
                wclrtoeol(win);
                scroll(win);
                wmove(win,22,45);
                wprintw(win,"%s",wron);
                wmove(win,22,60);
                wprintw(win,"%s",modetp);
            }
            else
                scroll(win);

            displayline(20,num);
        }
        else
            beep();

        showcurr();
    }
}

void currup(int delcur)
{
    if(delcur) delcurr();

    if(--cyp!=-1) 
        showcurr();
    else
    {
        cyp=0;
        if(fp>15)
        {
            lastline=FALSE;
            fp-=16;
            read16(0);

            wmove(win,0,0);
            winsertln(win);
            wmove(win,21,0);
            wclrtoeol(win);

            if(modeon)
            {
                wmove(win,22,45);
                wprintw(win,"%s",wron);
                wmove(win,22,60);
                wprintw(win,"%s",modetp);
            }

            displayline(0,16);
        }
        else
            beep();

        showcurr();
    }
}

void ascent()
{
    int c;

    wmove(win,22,45);
    strcpy(wron,"WRITE ON");
    wprintw(win,"%s",wron);
    fseek(f1,fp+cxp+cyp*16,0);
    while((c=wgetch(win))!=KEY_F0 && c!=26)
    {
        switch(c)
        {
            case KEY_RIGHT:
            case 12:
                delcurr();
                if(++cxp==16)
                {
                    cxp=0;
                    currdown(0);
                }
                else
                    showcurr();

                fseek(f1,fp+cxp+cyp+16,0);
                break;

            case KEY_LEFT:
            case 8:
                delcurr();
                if(--cxp == -1)
                {
                    cxp=15;
                    currup(0);
                }
                else
                    showcurr();

                fseek(f1,fp+cxp+cyp*16,0);
                break;

            case KEY_UP:
            case 11:
                currup(1);
                fseek(f1,fp+cxp+cyp*16,0);
                break;

            case KEY_DOWN:
            case 10:
                currdown(1);
                fseek(f1,fp+cxp+cyp*16,0);
                break;

            default:
                putc(c,f1);
                wmove(win,cyp,3*cxp+9);
                wprintw(win,"%02x",c);
                wmove(win,cyp,cxp+62);
                if(c<32||c>125) c='.';
                holdchar=c;
                wprintw(win,"%c",c);
                wrefresh(win);
                delcurr();
                
                if(++cxp==16)
                {
                    cxp=0;
                    currdown(0);
                }
                else
                    showcurr();

                break;
        }
    }

    wmove(win,22,45);
    strcpy(wron,"");
    wprintw(win,"            ");
    wrefresh(win);
}

void hexent()
{
    int c, currval=0;

    wmove(win,22,45);
    strcpy(wron,"WRITE ON");
    wprintw(win,"%s",wron);
    fseek(f1,fp+cxp+cyp*16,0);
    while((c=wgetch(win))!=KEY_F0 && c!=26)
    {
        switch(c)
        {
            case KEY_RIGHT:
            case 12:
                delcurr();
                if(++cxp==16)
                {
                    cxp=0;
                    currdown(0);
                }
                else
                    showcurr();

                fseek(f1,fp+cxp+cyp*16,0);
                currval=0;
                break;

            case KEY_LEFT:
            case 8:
                delcurr();
                if(--cxp==-1)
                {
                    cxp=15;
                    currup(0);
                }
                else
                    showcurr();

                fseek(f1,fp+cxp+cyp*16,0);
                currval=0;
                break;

            case KEY_UP:
            case 11:
                currup(1);
                fseek(f1,fp+cxp+cyp*16,0);
                currval=0;
                break;

            case KEY_DOWN:
            case 10:
                currdown(1);
                fseek(f1,fp+cxp+cyp*16,0);
                currval=0;
                break;

            default:
                c = c |  32;
                if((c>='0' && c<='9') || (c>='a' && c<='f'))
                {
                    currval%=16;
                    currval*=16;
                    c=(c>'9') ? c-87 : c-48;
                    currval=currval+c;
putc(currval,f1);
fseek(f1,-1L,1);
wmove(win,cyp,3*cxp+9);
wprintw(win,"%02x",currval);
wmove(win,cyp,cxp+62);
c=(currval<32||currval>125)?'.':currval;
holdchar=c;
wprintw(win,"%c",c);
wrefresh(win);
break;
                }
                else
                    beep();
        }
    }

    wmove(win,22,45);
    strcpy(wron,"");
    wprintw(win,"         ");
    wrefresh(win);
}

void keyoffset()
{
    int tmpvar;
    char instr[8];
    long dval;

    wmove(win,22,0);
    wechochar(win,':');
    if(getinpstr(instr,6)) return;
    if(instr[0]=='$')
    {
        if(lfp<337)
        {
            beep();
            return;
        }

        fp=lfp-336;
        tmpvar=lfp%16;
        fp-=tmpvar;
        if(tmpvar) fp+=16;
        fseek(f1,fp,0);
        cyp=redrawfl();
        cxp=((lfp-1)%16);
        lastline=TRUE;
        showcurr();
        return;
    }

    dval=strtol(instr,(char **)NULL,16);

    if(dval>lfp-336)
    {
        beep();
        return;
    }

    cxp=tmpvar=dval%16;
    cyp=0;
    fp=dval-cxp;
    fseek(f1,fp,0);
    redrawfl();
    showcurr();
    return;
}

int getinp(char *str,int mx)
{
    int cnt=0, c;

    while((c=wgetch(win))!=KEY_F0 && c!=26 && c!=13 && cnt<mx)
    {
        if((c>='0' && c<='9') || (c>='a' && c<='f'))
        {
            str[cnt++]=c;
            wechochar(win,c);
        }

        if(cnt==0 && c=='$')
        {
            str[cnt++]='$';
            break;
        }
    }

    str[cnt]='\0';
    wmove(win,22,0);
    wclrtoeol(win);
    wrefresh(win);
    if(c==KEY_F0 || c==26) return(1);
    return(0);
}

int redrawfl()
{
    int cnt,tmaxl,num;

    werase(win);

    for(cnt=0;cnt<=20;cnt++)
    {
        num=read16(cnt);

        if(num)
            displayline(cnt,num);
        else
            cnt--;

        if(num<16)
        {
            lastline=TRUE;
            break;
        }
    }

    tmaxl=(cnt==21) ? 20 : cnt;
    return(tmaxl);
}

void keysearch()
{
    int c;
    char instr[22];
    long rel,tfp;

    tfp=(long) fp+cxp+cyp*16;
    fseek(f1,++tfp,0);
    wmove(win,22,0);
    wechochar(win,'/');

    if(getinpstr(instr,20)) return;

    while((c=getc(f1))!=EOF)
    {
        if(c==instr[0])
        {
            if(checkrest(instr))
            {
                delcurr();
                tfp=ftell(f1)-1;
                rel=tfp-(fp+cxp+cyp*16);

                if(rel+cxp+cyp*16<336)
                {
                    cyp=cyp+(int)((rel+cxp)/16);
                    cxp=(rel+cxp)%16;
                    showcurr();
                }
                else
                {
                    fp=fp+rel+cxp+cyp*16-320;
                    cxp=(rel+cxp)%16;
                    cyp=20;
                    fp-=cxp;
                    fseek(f1,fp,1);
                    redrawfl();
                    showcurr();
                }

                return;
            }
        }
    }
        
    beep();
}

int checkrest(char *str)
{
    int cnt,c=1;
    char findstr[22];
    long tfp;

    for(cnt=1;cnt<strlen(str)&&c!=EOF;cnt++)
    {
        c=getc(f1);
        findstr[cnt]=c;
    }

    if(c==EOF) return(0);
    tfp=1-cnt;
    fseek(f1,tfp,1);
    findstr[cnt]='\0';
    if(strcmp(&str[1],&findstr[1])==0) return(1);
    return(0);
}

int getinpstr(char *str,int mx)
{
    int cnt=0,c;

    while((c=wgetch(win)) !=KEY_F0 && c!=26 && c!=13 && cnt<mx)
    {
        str[cnt++]=c;
        wechochar(win,c);
    }

    str[cnt]='\0';
    wmove(win,22,0);
    wclrtoeol(win);
    wrefresh(win);

    if(c==KEY_F0 || c==26) return(1);
    return(0);
}
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s