/* * Hexidecimal screen editor: * NOTE: Must be compiled in SMALL model! * * Special Keys: * PgDn = Page forward * PgUp = Page backward * CTRL-PgUp = Goto start of file * CTRL-PgDn = Goto end of file * Home = Goto start of line * End = Goto end of line * Ins = Insert a byte at cursor location * Del = Delete a byte at cursor location * F1 = Toggle between HEX/ASCII editing * CTRL-Home = Redraw screen * F10/Keypad '+' = Enter command * F9/Keypad '-' = Re-execute last command * Commands: * G = Goto address xxxx * Q = Quit editor * QQ = Quit even if unsaved changes * W[file] = Write file * X[file] = Exit and write file * ?xx ... = Search for HEX byte pattern * /text... = Search for ASCII text * * Copyright 1983-1995 Dave Dunfield * All rights reserved * * Permission granted for personal (non-commercial) use only. * * Compile command: cc hexed -fops */ #include #include #include #define ALLOCATION 60001 char cmdbuf[50], *cmdptr, searchbuf[50]; /* Declare data buffer in two chunks, to prevent a negative size, which confuses MASM */ unsigned char data[ALLOCATION/2], data1[ALLOCATION/2]; /* * Skip to the next non-blank character */ char skip() { while(*cmdptr == ' ') ++cmdptr; return *cmdptr; } main(argc, argv) unsigned argc; char *argv[]; { int cursor; unsigned i, j, k, pos, size; unsigned char c, chr, mode, modified; HANDLE fh; cursor = pos = mode = modified = 0; if(argc<2) abort("\nUse: hexed \n\nCopyright 1983-1995 Dave Dunfield\nAll rights reserved.\n"); if(!(fh=open(argv[1], F_READ))) abort("HEXED: Cannot open input file\n"); if((size = read(data, ALLOCATION, fh)) >= ALLOCATION) abort("HEXED: File to large\n"); close(fh); vopen(); draw: /* draw entire screen */ vgotoxy(0,0); for(i=0; i<30; ++i) vputc('-'); V_ATTR = REVERSE; putstr(" Hex-Ed Version 1.3 "); V_ATTR = NORMAL; for(i=0; i<30; ++i) vputc('-'); vgotoxy(0,2); vprintf("File: %s",argv[1]); vgotoxy(59,2); vprintf("Size: %u, ($%04x)",size, size); redraw: /* re-draw text area of screen */ for(i=0; i < 16; ++i) { /* for each line */ vgotoxy(0, i+4); if(size <= (k=pos+(i*16))) break; vprintf("%04x ",k=pos+(i*16)); for(j = k; j < (k+16) ; ++j) { if(j 255) { pos -= 256; goto redraw; } else if(pos) { pos = 0; goto redraw; } } break; case _KDA : /* advance a line (16 bytes) */ if((cursor + pos + 16) >= size) break; if(cursor <= (255-16)) { cursor += 16; break; } case _KPD : /* advance a page (256 bytes) */ if((pos+256) < size) pos += 256; if((pos + cursor) > size) cursor = size - pos - 1 ; goto redraw; case _KLA : /* backup one byte */ if(cursor) --cursor; else if(pos) { --pos; goto redraw; } break; case _KRA : /* advance one byte */ if(size <= (pos + ++cursor)) --cursor; else if(255 < cursor) { --cursor; if(pos < (size - 255)) ++pos; goto redraw; } break; case _CPD : /* goto end of file */ if(size > 255) { cursor = 255; pos = size - 256; } else { cursor = size-1; pos = 0; } goto redraw; case _CPU : /* goto start of file */ cursor = pos = 0; goto redraw; case _KEN : /* advance to end of field */ cursor = (cursor & 0xff0) + 15; if(size <= cursor+pos) cursor = size - pos - 1; break; case _KHO : /* backup to beginning of field */ cursor = cursor & 0xff0; break; case _K1 : /* swap editing field */ mode = ~mode; break; case _CHO : /* re-draw the screen */ vclscr(); goto draw; case _KDL: /* Delete a byte */ i = pos + cursor; while(i < size) data[i] = data[++i]; if((pos + cursor) >= --size) { if(cursor) --cursor; else if(pos) --pos; } modified = -1; goto redraw; case _KIN: /* Insert a byte */ i = pos + cursor; if(size < ALLOCATION) { chr = data[i]; while(i < size) { c = data[++i]; data[i] = chr; chr = c; } ++size; } modified = -1; goto redraw; case _K10 : /* execute line mode command */ case _KKP : vgotoxy(0,22); vcleos(); vputs("Command: "); i = 0; do { if((chr = vgetc()) == _KBS) { if (i) { putstr("\010 \010"); --i; } } else if(chr < 128) vputc(cmdbuf[i++] = chr); } while((chr != _KKP) && (chr != _K10)); cmdbuf[i] = 0; case _K9 : /* repeat last command */ case _KKM : vgotoxy(0, 22); V_ATTR = REVERSE; putstr(cmdbuf); V_ATTR = NORMAL; vcleos(); cmdptr = cmdbuf; switch(chr = toupper(skip())) { case 'G' : /* goto address */ ++cmdptr; skip(); i = 0; if((i = gethex()) == -1) break; cursor = 0; pos = (i= size) { error("Not found"); break; } } if(j < size) { if((cursor = j - pos) & 0xff00) { pos = j; cursor = 0; goto redraw; } } break; case 'X' : /* Exit and write file */ case 'W' : /* write file */ ++cmdptr; if(!skip()) cmdptr = argv[1]; if(fh=open(cmdptr, F_WRITE)) { write(data, size, fh); modified = 0; close(fh); } else { error("Can't open output file"); break; } if(chr != 'X') break; case 'Q' : /* quit (Exit) */ if(modified && (toupper(*(cmdptr+1)) != 'Q')) error("Unsaved changes, 'qq' to quit anyway"); else { vclscr(); exit(0); } break; case 0 : /* null command, do nothing */ break; default: error("Unknown command"); } vgotoxy(0,22); vcleol(); break; default: k = data[pos + cursor]; if(mode) { data[pos+cursor] = k = chr; chr = modified = -1; } else { if(ishex(chr = toupper(chr))) { vputc(chr); if(chr > '9') chr -= 7; i = (chr-'0')*16; vputc('-'); vputc('\b'); if(ishex(chr=toupper(vgetc()))) { if(chr > '9') chr -= 7; data[pos+cursor] = k =(chr-'0') + i; chr = modified = -1; } } } vgotoxy(7+3*(cursor%16), 4+cursor/16); vprintf("%02x ",k); vgotoxy(63 + cursor%16, 4 + cursor/16); putprint(k); if(chr == -1) { if(size <= (pos + ++cursor)) --cursor; else if(cursor > 255) { if(pos < (size-256)) { pos += 256; cursor = 0; } else pos = size-(pos + cursor); goto redraw; } } } goto prompt; } /* * Test for a valid hexidecimal digit */ ishex(chr) char chr; { return ((chr >= '0') && (chr <= '9')) || ((chr >= 'A') && (chr <= 'F')); } /* * Get a hex value from the input line */ gethex() { register unsigned i; register char chr, flag; flag = i = 0; while(ishex(chr = toupper(*cmdptr))) { ++cmdptr; flag = -1; if(chr > '9') chr -= 7; i = (i*16) + (chr - '0'); } if(!flag) { error("Invalid HEX digit"); return -1; } return i; } /* * Display a character in printable form. * Non-printable characters display as '.' */ putprint(chr) char chr; { vputc(((chr >= ' ') && (chr < 0x7f)) ? chr : '.'); } /* * Display an error message on the bottom line of the screen */ error(string) char *string; { vgotoxy(0,23); V_ATTR = REVERSE; putstr(string); V_ATTR = NORMAL; vcleos(); vputc(7); } /* * Compare two strings for the given length */ compare(str1, str2, len) char *str1, *str2; int len; { while(len--) { if(*str1++ != *str2++) return 0; } return 1; } /* * Write a string to the output device */ putstr(ptr) char *ptr; { register char c; while(c = *ptr++) vputc(c); }