[alt.sources] Binary editor

wmark@wb3ffv.ampr.org (Mark Winsor) (10/13/90)

Here is a binary editor that i've found useful. It has only been tested in
SYSV & SCO XENIX environments, but should be relatively easy to port. Do to
the non-standard alternate character set mapping prior to SYSV3, the line 
drawing characters are replaced with, |, -, and + for those environments 
(or if your terminal doesn't support line drawing charaters).

Mark S. Winsor
Systems Analyst
ProVAR, Inc.


-------------------------------CUT HERE---------------------------------
#!/bin/sh
# to extract, remove the header and type "sh filename"
if `test ! -s ./Makefile`
then
echo "writing ./Makefile"
cat > ./Makefile << '\Rogue\Monster\'
# The XENIX define is used for any system that uses xenix style echoing

OBJS = filepatch.o bxline.o getword.o getattrs.o

SOURCE = filepatch.c bxline.c getword.c getattrs.c

make:
	@echo "You must specify system type (i.e. sys5.3 or sco, etc)"

sys5.3:
	make filepatch "FLAGS = -O -g -c -D SYSV3"\
				   "LDFLAGS = -g -lcurses"

ncr:
	make filepatch "FLAGS = -O -c -D XENIX"\
				   "LDFLAGS = -s -lcurses"

sco:
	make filepatch "FLAGS = -O -c -D SCO286"\
				   "LDFLAGS = -s -Ml -F 4000 -lx -lcurses"

clean:
	rm -f *\.o filepatch core

filepatch: $(OBJS)
		cc $(OBJS) -o filepatch $(LDFLAGS)

.c.o:
		cc $(FLAGS) $*.c

\Rogue\Monster\
else
  echo "will not over write ./Makefile"
fi
if `test ! -s ./bxline.c`
then
echo "writing ./bxline.c"
cat > ./bxline.c << '\Rogue\Monster\'
/* 
 *  This is a routine to place a solid line border 
 *  around a window.    Mark S. Winsor
 *                      ProVAR 
 */ 

static char rcsid[] = "$Id: bxline.c,v 1.2 90/10/10 21:03:48 wmark Exp $";
static char rcsrev[] = "$Revision: 1.2 $";

/*
$Author: wmark $
$Date: 90/10/10 21:03:48 $
$Locker:  $
$RCSfile: bxline.c,v $
$Source: /usr9/people/mark/C/filepatch/bxline.c,v $
$State: Exp $

$Log:	bxline.c,v $
 * Revision 1.2  90/10/10  21:03:48  wmark
 * Took out color
 * 
 * Revision 1.1  90/07/29  18:00:24  wmark
 * Initial revision
 * 
*/

#include <curses.h>

#ifdef SCO286
#define XENIX
#endif

bxline(towindow, vert_len, horz_len )

char *towindow;
int vert_len;
int horz_len;

{
        int a;
        int b;
        int line;
        extern int altchar;
        char *acsc_ptr;
        char acsc_arr[80];
        char upperright;
        char upperleft;
        char lowerright;
        char lowerleft;
        char horizontal;
        char vertical;

#ifdef SYSV3
        upperright = ACS_URCORNER;
        upperleft  = ACS_ULCORNER;
        lowerright = ACS_LRCORNER;
        lowerleft  = ACS_LLCORNER;
        horizontal = ACS_HLINE;
        vertical   = ACS_VLINE;
#else
        upperright = '+';
        upperleft  = '+';
        lowerright = '+';
        lowerleft  = '+';
        horizontal = '-';
        vertical   = '|';
#endif
        
#ifdef SYSV3
        (void) wattrset(towindow,A_ALTCHARSET);
#endif
        (void) mvwprintw(towindow,0,0,"%c",upperleft);
        (void) mvwprintw(towindow,0,(horz_len - 1),"%c",upperright);
        (void) mvwprintw(towindow,(vert_len - 1),0,"%c",lowerleft);
        (void) mvwprintw(towindow,(vert_len - 1),(horz_len - 1),"%c",
                lowerright);
        a = 0;
        b = horz_len - 1;
        line = 1;
        while ( line < (vert_len - 1)) {
             (void) mvwprintw (towindow,line,a,"%c",vertical);
             (void) mvwprintw (towindow,line,b,"%c",vertical);
             ++line;
        }
        a = 0;
        for ( b = 1; b < (horz_len - 1); ++b) {
             (void) mvwprintw (towindow,a,b,"%c",horizontal);
        }
        a = vert_len - 1;
        for ( b = 1; b < (horz_len - 1); ++b) {
             (void) mvwprintw (towindow,a,b,"%c",horizontal);
        }
        (void) wrefresh(towindow);
        (void) wattrset(towindow,0);
}
\Rogue\Monster\
else
  echo "will not over write ./bxline.c"
fi
if `test ! -s ./filepatch.c`
then
echo "writing ./filepatch.c"
cat > ./filepatch.c << '\Rogue\Monster\'
/*
 *      Norton-esque file patch utility program
 *
 *      Copyright ProVAR, Inc. &
 *                Emtronix Data Services
 *
 *      Mark S. Winsor
 *      Marc A. Siegel
 *
 *      This program may be freely distributed provided this notice remains
 *
 *      Send any bug reports, questions, or suggestions to 
 *      {uunet}!cp1!briar!mas!bohica!wmark
 */

static char rcsid[] = "$Id: filepatch.c,v 1.12 90/10/10 21:03:24 wmark Exp $";
static char rcsrev[] = "$Revision: 1.12 $";

/*
$Author: wmark $
$Date: 90/10/10 21:03:24 $
$Locker:  $
$RCSfile: filepatch.c,v $
$Source: /usr9/people/mark/C/filepatch/filepatch.c,v $
$State: Exp $

$Log:	filepatch.c,v $
 * Revision 1.12  90/10/10  21:03:24  wmark
 * fixed display
 * 
 * Revision 1.11  90/08/13  12:53:42  wmark
 * Repeat last search if no argument given
 * 
 * Revision 1.9  90/08/13  10:15:28  wmark
 * Added relative offsets (using "+" or "-" in first character of offset)
 * 
 * Revision 1.3  90/07/30  09:26:07  wmark
 * Centered title line
 * 
 * Revision 1.2  90/07/29  18:19:44  wmark
 * Use RCS revision number in title line
 * 
 * Revision 1.1  90/07/29  18:17:58  wmark
 * Initial revision
 * 
*/


#include <curses.h>
#include <ctype.h>
#include <fcntl.h>
#include <signal.h>
#include <errno.h>

#define ESC    '\033'
#define TAB    '\011'
#define NUMBUF 25
#define MAX    256
#define MAXPAT 40
#define MAXHEX 20

#ifdef SCO286
#define XENIX
#endif

int colors;
int blink;
int reverse;
int altchar;
int underline;
int edit_type;    /* 0 = edit hex, 1 = edit chars */
char lastsearch[MAXPAT];

struct scr_pos {
    int h_scr_row;
    int h_scr_col;
    int c_scr_row;
    int c_scr_col;
};

/*  
 * This table below is used instead of printw("%X") for two reasons.
 * 1 - speed, and 2 - there appears to be a problem with printf type
 * commands printing hex FF on Xenix and ncr systems.
 */

char *hexconv[] = { "00", "01", "02", "03", "04", "05", "06", "07", "08",
                    "09", "0A", "0B", "0C", "0D", "0E", "0F",
                    "10", "11", "12", "13", "14", "15", "16", "17", "18",
                    "19", "1A", "1B", "1C", "1D", "1E", "1F",
                    "20", "21", "22", "23", "24", "25", "26", "27", "28",
                    "29", "2A", "2B", "2C", "2D", "2E", "2F",
                    "30", "31", "32", "33", "34", "35", "36", "37", "38",
                    "39", "3A", "3B", "3C", "3D", "3E", "3F",
                    "40", "41", "42", "43", "44", "45", "46", "47", "48",
                    "49", "4A", "4B", "4C", "4D", "4E", "4F",
                    "50", "51", "52", "53", "54", "55", "56", "57", "58",
                    "59", "5A", "5B", "5C", "5D", "5E", "5F",
                    "60", "61", "62", "63", "64", "65", "66", "67", "68",
                    "69", "6A", "6B", "6C", "6D", "6E", "6F",
                    "70", "71", "72", "73", "74", "75", "76", "77", "78",
                    "79", "7A", "7B", "7C", "7D", "7E", "7F",
                    "80", "81", "82", "83", "84", "85", "86", "87", "88",
                    "89", "8A", "8B", "8C", "8D", "8E", "8F",
                    "90", "91", "92", "93", "94", "95", "96", "97", "98",
                    "99", "9A", "9B", "9C", "9D", "9E", "9F",
                    "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8",
                    "A9", "AA", "AB", "AC", "AD", "AE", "AF",
                    "B0", "B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8",
                    "B9", "BA", "BB", "BC", "BD", "BE", "BF",
                    "C0", "C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8",
                    "C9", "CA", "CB", "CC", "CD", "CE", "CF",
                    "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7", "D8",
                    "D9", "DA", "DB", "DC", "DD", "DE", "DF",
                    "E0", "E1", "E2", "E3", "E4", "E5", "E6", "E7", "E8",
                    "E9", "EA", "EB", "EC", "ED", "EE", "EF",
                    "F0", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8",
                    "F9", "FA", "FB", "FC", "FD", "FE", "FF" 
                 };

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

    if (argc != 2) {
        (void) usage(argv[0]);
    }
    if ((input = open(argv[1],O_RDWR)) == -1) {
        (void) fprintf(stderr,"%s: Cannot open %s, error %d\n",
                 argv[0],argv[1],errno);
        (void) exit(1);
    }
    edit_type = 0;
    lastsearch[0] = '\0';
    (void) process_file (input,argv[1]);
    (void) close(input);
    (void) exit(0);
}

process_file(input,filename)
int input;
char *filename;
{
    static char buffer[MAX];
    long seek_no;
    int max;
    int proc_ret;
    int byebye();
    long end_of_file;
    long lseek();

    (void) initscr();
    (void) raw();
#ifndef XENIX
    (void) noecho();
#endif
    (void) keypad(stdscr,TRUE);
    (void) signal(SIGINT,byebye);
    (void) signal(SIGQUIT,byebye);
    (void) get_attrs();
    (void) bxline(stdscr,23,80);
    if (reverse == TRUE) {
        (void) attrset(A_REVERSE);
    }
    (void) mvprintw(0,20," ProVAR File Patch Utility   ");
    (void) printw("Rev: %c%c%c%c ",rcsrev[11],rcsrev[12],rcsrev[13],rcsrev[14]);
    (void) attrset(0);
    (void) mvprintw(2,3,"File Name: %-40.40s",filename);
    (void) mvprintw(21,28,"Enter '?' for help");

    seek_no = 0;
    end_of_file = lseek(input,0L,2);
    for (;;) {
        (void) mvprintw(2,55,"Offset: %7ld bytes",seek_no);
        (void) move(23,0);
        (void) clrtoeol();
        if (lseek(input,seek_no,0) == -1)
            break;
        max = read(input,buffer,MAX);
        if (max < 1) 
            break;
        proc_ret = process_buf(buffer,max,&seek_no,end_of_file,input);
        if (proc_ret == -1)
            break;
        if (proc_ret == 1) {
            if (lseek(input,seek_no,0) == -1)
                break;
            (void) write(input,buffer,max);
        }
    }
    (void) erase();
    (void) mvprintw(12,25,"-- Finished Processing --");
    (void) refresh();
    (void) endwin();
}

process_buf(buffer,max,seek_ptr,end_of_file,input)
char *buffer;
int max;
long *seek_ptr;
long end_of_file;
int input;
{
    int index;

    for (index = 0; index < max; index++) {
        (void) disp_char(*(buffer + index),index);
    }
    for ( ; index < MAX; index++) {
        (void) erase_char(index);
    }
    return(update_buf(buffer,max,seek_ptr,end_of_file,input));
}

update_buf(buffer,max,seek_ptr,end_of_file,input)
char *buffer;
int max;
long *seek_ptr;
long end_of_file;
int input;
{
    struct scr_pos pos;
    unsigned int i;
    int index;
    int oldindex;
    long new_offset;
    long get_new_offset();
    long get_pattern();
    long lseek();
    int c;
    char chgs_made;
    char answer;
    char mode;
    char hex_string[3];

    mode = 'C';                    /* C = Command, E = Edit */
    index = 0;
    chgs_made = 'N';

    for (;;) {
        if (mode == 'C') {
            (void) mvprintw(23,0,"Command Mode");
            (void) refresh();
        }
        else {
            (void) mvprintw(23,0,"Edit mode   ");
            (void) refresh();
        }
        (void) pos_char(index,&pos);
        if (edit_type == 0) {
            (void) move (pos.h_scr_row,pos.h_scr_col);
        }
        else {
            (void) move (pos.c_scr_row,pos.c_scr_col);
        }
        (void) refresh();
        c = getch();

        if (mode == 'E') {
            switch(c) {

                case ESC:
                case TAB:
                         mode = 'C';
                         break;

                default:
                         if (edit_type == 0) {
                             c = toupper(c);
                             hex_string[0] = c;
                             (void) move (pos.h_scr_row,(pos.h_scr_col + 1));
                             (void) refresh();
                             c = getch();
                             c = toupper(c);
                             hex_string[1] = c;
                             hex_string[2] = '\0';
                             if (hex_string[0] < '0' || hex_string[0] > '9') {
                                 if (hex_string[0] < 'A' 
                                 || hex_string[0] > 'F') {
                                     (void) beep();
                                     break;
                                 }
                             }
                             if (hex_string[1] < '0' || hex_string[1] > '9') {
                                 if (hex_string[1] < 'A' 
                                 || hex_string[1] > 'F') {
                                     (void) beep();
                                     break;
                                 }
                             }
                             (void) sscanf(hex_string,"%x",&i);
                         }
                         else {
                             i = c;
                         }
                         *(buffer + index) = i;
                         (void) disp_char(*(buffer + index),index);
                         chgs_made = 'Y';
                         ++index;
                         if (index >= max)
                             index = 0;
                         break;
            }
        }
        else {
            switch(c) {

                case ESC:
                case TAB:
                         mode = 'E';
                         break;

                case 'W':
                case 'w':
                         (void) mvprintw(23,0,"... Writing     ");
                         (void) refresh();
                         return(1);

                case 'E':
                case 'e':
                         *seek_ptr = end_of_file - 256;
                         if (*seek_ptr < 0) {
                             *seek_ptr = 0;
                         }
                         return(0);

                case 'Q':
                case 'q':
                         if (chgs_made == 'Y') {
                             answer = ask_ignore();
                         }
                         if (chgs_made == 'Y' && answer == 'N') {
                             break;
                         }
                         else {
                             return(-1);
                         }

                case '?':
                         (void) help();
                         break;

                case 'T':
                case 't':
                         edit_type ^= 1;
                         break;

                case 'O':
                case 'o':
                         new_offset = get_new_offset(*seek_ptr);
                         if (new_offset < 0 || new_offset > end_of_file) {
                             (void) error("Offset out of range");
                             break;
                         }
                         else {
                             *seek_ptr = new_offset;
                             return(0);
                         }

                case '/':
                         if (chgs_made == 'Y') {
                             answer = ask_ignore();
                         }
                         if (chgs_made == 'Y' && answer == 'N') {
                             break;
                         }
                         else {
                             new_offset = get_pattern((*seek_ptr + index),
                                                     buffer,max,input);
                             (void) move(23,0);
                             (void) clrtoeol();
                             (void) refresh();
                             if (new_offset == -1) {             /* Not found */
                                 (void) error("Pattern not found");
                                 break;
                             }
                             if (new_offset == -2) {                /*Not fnd */
                                 (void) error("Pattern not found"); /*re-read */
                                 lseek(input,*seek_ptr,0);          /*required*/
                                 max = read(input,buffer,MAX);
                                 break;
                             }
                             if (new_offset == -3) {
                                 break;
                             }
                             else {
                                 *seek_ptr = new_offset;
                                 return(0);
                             }
                         }

                case KEY_RIGHT:
                case 'R':
                case 'r':
                         ++index;
                         if (index > max) {
                             --index;
                             (void) beep();
                         }
                         break;

                case KEY_LEFT:
                case 'L':
                case 'l':
                         --index;
                         if (index < 0) {
                             index = 0;
                             (void) beep();
                         }
                         break;

                case KEY_DOWN:
                case 'D':
                case 'd':
                         index += 16;
                         if (index >= max) {
                             index -= 16;
                             (void) beep();
                         }
                         break;

                case KEY_UP:
                case 'U':
                case 'u':
                         index -= 16;
                         if (index < 0) {
                             index += 16;
                             (void) beep();
                         }
                         break;

                case '\n':
                         oldindex = index;
                         index += 16;
                         index = index - (index % 16);
                         if (index >= max) {
                             index = oldindex;
                             (void) beep();
                         }
                         break;

                case 'F':
                case 'f':
                         if (chgs_made == 'Y') {
                             answer = ask_ignore();
                         }
                         if (chgs_made == 'Y' && answer == 'N') {
                             break;
                         }
                         else {
                             *seek_ptr += MAX;
                             if (*seek_ptr >= end_of_file) {
                                 (void) error("No pages after this one");
                                 *seek_ptr -= MAX;
                                 break;
                             }
                             else {
                                 return(0);
                             }
                         }

                case 'B':
                case 'b':
                         if (chgs_made == 'Y') {
                             answer = ask_ignore();
                         }
                         if (chgs_made == 'Y' && answer == 'N') {
                             break;
                         }
                         else {
                             if (*seek_ptr == 0) {
                                 (void) error("No pages before this one");
                                 break;
                             }
                             else {
                                 *seek_ptr -= MAX;
                                 if (*seek_ptr < 0) 
                                     *seek_ptr = 0;
                                 return(0);
                             }
                         }

                default:
                         (void) beep();
                         break;
            }         
        }         
    }
}

ask_ignore()
{
    int answer;
    
    (void) mvprintw(23,0, "This will ignore changes in this block, ");
    (void) printw("Is this ok ? ");
    do {
        (void) move(23,53);
        (void) refresh();
        answer = getch();
        answer = toupper(answer);
        (void) move(23,53);
        (void) addch(answer);
        (void) refresh();
    } while(answer != 'N' && answer != 'Y');
    (void) move(23,0);
    (void) clrtoeol();
    return(answer);
}

long
get_new_offset(oldoffset)
long oldoffset;
{
    long offset;
    char offsetbuf[15];

#ifndef XENIX
    (void) echo();
#endif
    (void) mvprintw(23,0,"Enter Offset: ");
    offsetbuf[0] = '\0';
    (void) get_word(14,offsetbuf,stdscr,23,14);
    if (offsetbuf[0] == '\0') {
        offset = -1;
    }
    else if (offsetbuf[0] == '+' || offsetbuf[0] == '-') {
        if ((sscanf(offsetbuf,"%ld",&offset)) != 1) {
            offset = -1;
        }
        else {
            offset += oldoffset;
        }
    }
    else {
        if ((sscanf(offsetbuf,"%ld",&offset)) != 1) {
            offset = -1;
        }
    }
    (void) move(23,0);
    (void) clrtoeol();
#ifndef XENIX
    (void) noecho();
#endif
    return(offset);
}

long
get_pattern(offset,buffer,max,input)
long offset;
char *buffer;
int max;
int input;
{
    static char pat[MAXPAT];
    int         wordresult;
    long        search();

#ifndef XENIX
    (void) echo();
#endif
    (void) mvprintw(23,0,"Enter pattern (ESC to enter in hex): ");
    pat[0] = '\0';
    wordresult = get_word(MAXPAT,pat,stdscr,23,37);
    if (wordresult == 6) {          /* The get_word() func is overkill     */
        (void) hex_pattern(pat);    /* but I use it often in other         */
    }                               /* things, so why re-invent the wheel! */

    if (pat[0] == '\0') {
#ifndef XENIX
        (void) noecho();
#endif
        if (lastsearch[0] == '\0') {
            return(-3);
        }
        else {
            (void) strcpy(pat,lastsearch);
        }
    }
    (void) move(23,0);
    (void) clrtoeol();
    (void) mvprintw(23,0,"... Searching");
    (void) refresh();
#ifndef XENIX
    (void) noecho();
#endif
    (void) strcpy(lastsearch,pat);
    return(search(pat,buffer,offset,max,input));
}

hex_pattern(pat)
char *pat;
{
    int i;
    int j;
    int c;
    char hex_string[3];

#ifndef XENIX
    (void) noecho();
#endif
    (void) move(23,0);
    (void) clrtoeol();
    (void) mvprintw(23,0,"Enter hex characters:");
    (void) refresh();
    i = 0;
    do {
        (void) move(23,(22 + (i * 3)));
        (void) refresh();
        c = getch();
        if (c != '\n') {
            hex_string[0] = c;
            hex_string[1] = getch();
            hex_string[2] = '\0';
             if (sscanf(hex_string,"%x",&c) != 1) {
                 (void) beep();
             }
             else {
                 *(pat + i) = c;
                 (void) mvaddstr(23,(22 + (i * 3)),
                     hexconv[(unsigned int)*(pat + i)]);
                 (void) refresh();
                 c = '\0';
                 ++i;
             }
         }
     } while (c != '\n' && i < MAXHEX);
     ++i;
     *(pat + i) = '\0';
#ifndef XENIX
    (void) echo();
#endif
}

long
search(pat,buffer,offset,max,input)
char *pat;
char *buffer;
long offset;
int max;
int input;
{
    register int index;
    int pat_length;
    char re_read;
    static char srch_buf[MAX * NUMBUF];
    char *search_buf;
    long lseek();

    re_read = 'N';
    pat_length = strlen(pat);
    (void) memcpy(srch_buf,buffer,max);
    search_buf = srch_buf;
    for (;;) {
        for (index = 1; index < (max - pat_length + 1); index++) {
            if (*(search_buf + index) == *pat) {
                if (!memcmp((search_buf + index),pat,pat_length)) {
                    return(index + offset);
                }
            }
        }
        if (max < MAX) {
            if (re_read == 'N') {
                return(-1);
            }
            else {
                return(-2);
            }
        }
        offset += max;
        if (lseek(input,offset,0) == -1) {
            if (re_read == 'N') {
                return(-1);
            }
            else {
                return(-2);
            }
        }
        max = read(input,srch_buf,(MAX * NUMBUF));
        re_read = 'Y';
    }
}

disp_char(c,index)
unsigned char c;
int index;
{
    struct scr_pos pos;

    (void) pos_char(index,&pos);
    (void) mvaddstr(pos.h_scr_row,pos.h_scr_col,hexconv[(unsigned int)c]);
    if (c < ' ' || c > '~') {
        c = '.';
    }
    (void) mvaddch(pos.c_scr_row,pos.c_scr_col,c);
}

erase_char(index)
int index;
{
    struct scr_pos pos;

    (void) pos_char(index,&pos);
    (void) mvprintw(pos.h_scr_row,pos.h_scr_col,"  ");
    (void) mvprintw(pos.c_scr_row,pos.c_scr_col," ");
}

pos_char(index,posptr)
int index;
struct scr_pos *posptr;
{
    int st_row;
    int st_col;
    int calc_row;
    int calc_rem;
    int even_odd;

    st_row = 4;
    st_col = 2;

    calc_row = index / 16;
    calc_rem = index % 16;
    even_odd = calc_rem % 2;
    even_odd ^= 1;             /* If 0 make it one, and vice versa */

    posptr->h_scr_row = posptr->c_scr_row = st_row + calc_row;
    posptr->h_scr_col = (st_col + (calc_rem * 3) + (even_odd * 1));
    posptr->c_scr_col = st_col + 52 + calc_rem;
    return(0);
}

help()
{
    WINDOW *helpwin;

    helpwin = newwin(20,48,1,15);
    bxline(helpwin,20,48);

    (void) mvwprintw(helpwin,1,15,"Action Key List");
    (void) mvwprintw(helpwin,3,3,"ESC or TAB toggles edit/command mode");
    (void) mvwprintw(helpwin,4,3,"R or Right arrow = Move to right");
    (void) mvwprintw(helpwin,5,3,"L or Left arrow  = Move to left");
    (void) mvwprintw(helpwin,6,3,"D or Down arrow  = Down one line");
    (void) mvwprintw(helpwin,7,3,"U or Up arrow    = Up one line");
    (void) mvwprintw(helpwin,8,3,"<RETURN>         = Beginning of next line");
    (void) mvwprintw(helpwin,9,3,"W                = Write current buffer");
    (void) mvwprintw(helpwin,10,3,"Q                = Quit processing");
    (void) mvwprintw(helpwin,11,3,"F                = Forward page");
    (void) mvwprintw(helpwin,12,3,"B                = Backward page");
    (void) mvwprintw(helpwin,13,3,"O                = Change offset");
    (void) mvwprintw(helpwin,14,3,"E                = Go to last page");
    (void) mvwprintw(helpwin,15,3,"T                = Toggle hex/char edit");
    (void) mvwprintw(helpwin,16,3,"/                = Pattern match");
    (void) mvwprintw(helpwin,18,3,"Press Any key to continue ");
    (void) wrefresh(helpwin);
    (void) wgetch(helpwin);

    (void) delwin(helpwin);
    (void) touchwin(stdscr);
}

error(str)
char *str;
{
    (void) mvprintw(23,0,"%s ",str);
    (void) refresh();
    (void) beep();
    (void) getch();
    (void) move(23,0);
    (void) clrtoeol();
}

usage(progname)
char *progname;
{
    (void) fprintf(stderr,"Usage: %s filename\n",progname);
    (void) exit(1);
}

byebye()
{
    (void) endwin();
    (void) exit(2);
}
\Rogue\Monster\
else
  echo "will not over write ./filepatch.c"
fi
if `test ! -s ./getattrs.c`
then
echo "writing ./getattrs.c"
cat > ./getattrs.c << '\Rogue\Monster\'

static char rcsid[] = "$Id: getattrs.c,v 1.1 90/07/29 18:00:32 wmark Exp $";
static char rcsrev[] = "$Revision: 1.1 $";

/*
$Author: wmark $
$Date: 90/07/29 18:00:32 $
$Locker:  $
$RCSfile: getattrs.c,v $
$Source: /usr9/people/mark/C/filepatch/getattrs.c,v $
$State: Exp $

$Log:	getattrs.c,v $
 * Revision 1.1  90/07/29  18:00:32  wmark
 * Initial revision
 * 
*/

#include <curses.h>

#ifdef SCO286
#define XENIX
#endif

get_attrs()
{
    extern int blink;
    extern int colors;
    extern int reverse;
    extern int altchar;
    extern int underline;
    char sm[30];

    blink = FALSE;
    colors = FALSE;
    reverse = FALSE;
    altchar = FALSE;
    underline = FALSE;

#ifdef XENIX
    if (((char *) tgetstr("bm",sm)) != NULL) { 
        blink = TRUE;
    }
    if (((char *) tgetstr("so",sm)) != NULL) { 
        reverse = TRUE;
    }
    if (((char *) tgetstr("as",sm)) != NULL) { 
        altchar = TRUE;
    }
    if (((char *) tgetstr("us",sm)) != NULL) { 
        underline = TRUE;
    }
#else
    if (((char *) tigetstr("blink")) != NULL) {
        blink = TRUE;
    }
    if (((char *) tigetstr("smso")) != NULL) {
        reverse = TRUE;
    }
    altchar = TRUE;
    if (((char *) tigetstr("smul")) != NULL) {
        underline = TRUE;
    }
#endif

#ifdef USECOLORS
    colors = start_color();
    if (colors != ERR) {
        colors = TRUE;
    }
#endif
}
\Rogue\Monster\
else
  echo "will not over write ./getattrs.c"
fi
if `test ! -s ./getword.c`
then
echo "writing ./getword.c"
cat > ./getword.c << '\Rogue\Monster\'
/* This is a common accept routine for all character and character
   string input.    Mark S. Winsor
                    ProVAR                                         */

static char rcsid[] = "$Id: getword.c,v 1.1 90/07/29 18:00:37 wmark Exp $";
static char rcsrev[] = "$Revision: 1.1 $";

/*
$Author: wmark $
$Date: 90/07/29 18:00:37 $
$Locker:  $
$RCSfile: getword.c,v $
$Source: /usr9/people/mark/C/filepatch/getword.c,v $
$State: Exp $

$Log:	getword.c,v $
 * Revision 1.1  90/07/29  18:00:37  wmark
 * Initial revision
 * 
*/

#include <curses.h>

#define CTRLA '\001'
#define CTRLB '\002'
#define CTRLC '\003'
#define CTRLD '\004'
#define CTRLT '\024'
#define BELL '\007'
#define REPAINT '\014'

#ifndef ESC
#define ESC '\033'
#endif

#ifdef SCO286
#define XENIX
#endif
   
get_word(size,fld_ptr,fromwindow,beg_row,beg_col)

int size;
char *fld_ptr;
char *fromwindow;
int beg_row;
int beg_col;

{
    int offset;
    int ch;
    char fill_flag = 'y';

                        /* 
                         * Keypad must be enabled to use this function, 
                         * the arrow keys will return : 
                         *          1 for KEY_UP, KEY_F2,
                         *          2 for KEY_LEFT, KEY_F3,
                         *          3 for KEY_DOWN, KEY_F1,
                         *          4 for KEY_RIGHT, KEY_F4, 
                         *          and 0 for no arrow 
                         */

#ifndef XENIX
    (void) noecho();
#endif
    (void) wmove(fromwindow,beg_row,beg_col);
    (void) wrefresh(fromwindow);
    for (;;) {
        for (offset = 0; offset < size; offset++) {
            ch = wgetch(fromwindow);
            if (ch == REPAINT && offset == 0) {               /* If CTRL-L is */
                (void) wmove (fromwindow,beg_row,beg_col);    /* is pressed   */
                (void) wprintw(fromwindow,"  ");              /* in the 1'st  */
                (void) wmove (fromwindow,beg_row,beg_col);    /* postition,   */
                (void) clearok(fromwindow);                   /* then repaint */
                (void) wrefresh(fromwindow);                  /* screen and   */
                --offset;                                     /* continue     */
                continue;
            }
            if (offset == 0) {
                if (ch == ESC) {
                    return(6);
                }
                if (ch == KEY_UP || ch == CTRLB) {
                    return(1);
                }
                if (ch == KEY_RIGHT || ch == CTRLD) {
                    return(4);
                }
                if (ch == KEY_DOWN || ch == CTRLA) {
                    return(3);
                }
                if (ch == KEY_LEFT || ch == CTRLC) {
                    return(2);
                }
                if (ch == CTRLT) {
                    return(6);
                }
            }
            if (ch == '\n' && offset == 0) {
                return(0);
            }
            if (ch == '\n') {
                *(fld_ptr + offset) = '\0';
                fill_flag = 'n';
                return(0);
            }
            if (ch == '\b') {
                offset = offset - 2;
                if (offset < -1) {
                    (void) putchar(BELL);
                    (void) mvwprintw(fromwindow,beg_row,beg_col," ");
                    (void) wrefresh(fromwindow);
                    (void) wmove(fromwindow,beg_row,beg_col);
                    (void) wrefresh(fromwindow);
                    *fld_ptr = '\0';
                    offset = -1;
                }
                else {
/* Mimic a Unix */  (void) wmove (fromwindow,beg_row,(beg_col + offset + 1));
/* stty echoe   */  (void) wprintw(fromwindow, " ");
                    (void) wprintw(fromwindow, " ");
                    (void) wrefresh(fromwindow);
                    (void) wmove (fromwindow,beg_row,(beg_col + offset + 1));
                    (void) wrefresh(fromwindow);
                    *(fld_ptr + (offset + 1)) = '\0';
                }
            }
            if (offset == 0) {
                (void) clr_fld(size,fromwindow,beg_row,beg_col);
                (void) wmove (fromwindow, beg_row, (beg_col + 1));
                (void) wrefresh (fromwindow);
            }
            if (ch != '\b') {
                *(fld_ptr + offset) = ch;
                (void) wmove (fromwindow,beg_row,(beg_col + offset));
                (void) waddch(fromwindow,ch);
                (void) wrefresh (fromwindow);
            }
        }
        if (fill_flag == 'y') {
            if (size > 1) {
                *(fld_ptr + offset) = '\0';
            }
        }
#ifndef XENIX
        (void) echo();
#endif
        break;
    }
}

clr_fld (size, fromwindow, beg_row, beg_col)

int size;
int beg_row; 
int beg_col;
char *fromwindow;

{
    int i;

    for (i = (beg_col+1); i < (beg_col+size); ++i) {
        (void) mvwprintw(fromwindow,beg_row,i," ");
    }
    (void) wrefresh(fromwindow);
}

\Rogue\Monster\
else
  echo "will not over write ./getword.c"
fi
echo "Finished archive 1 of 1"
exit