home *** CD-ROM | disk | FTP | other *** search
- /* fv is a binary file editor written by Chris Hooper (cdh@mtu.edu)
- * on 6-2-91 and has gone through many revisions since then.
- * Much inspiration was given by Bill Moore, the first real user!
- *
- * Author: CHRISTOPHER D HOOPER
- *
- * fv source Copyright (c) 1992 - 1998 Chris Hooper
- *
- * Modification and redistribution is strictly prohibited.
- * Sale of this software above media cost is prohibited.
- *
- * Except for above two restrictions, this software may be used for
- * any purpose, commercial or private.
- *
- * Disclaimer: This product is fit for no use, foreign or domestic.
- * Use implies knowledge you intend to destroy something.
- */
-
- #include <stdio.h>
- #include <curses.h>
- #include "main.h"
- #if !defined(Amiga) && !defined(OS9) && !defined(FreeBSD)
- # include <malloc.h>
- #endif
- #if defined(Win32) || defined(Solaris1)
- char *strdup();
- #else
- #include <strings.h>
- #endif
-
- #include "screen.h"
- #include "io.h"
-
- #ifdef LINT
- # include "lint.h"
- #endif
-
- #ifdef OS9
- char *strdup();
- #endif
-
- extern ulong cursor_address;
- extern ulong inbuf_size;
- extern int status_line;
- extern char *NONWORD;
-
- #define MARKS 64
-
- char markchar[MARKS];
- int markpos[MARKS];
- int marks = 0;
-
- char *ubar = "_____________________________________________________________________________________________________________________________________________________________________________________________________";
-
-
- void delchars();
- void delword();
- void help_me_prompt();
- static char *xbytes();
- #ifdef COLON_MODE
- static int know_file();
- #endif
-
- int save_changes(prompt_user)
- int prompt_user;
- {
- char ch;
- int saveprompt = 0;
- int yes = 1;
-
- if (!dirty)
- return(0);
-
- #if !defined(Dynix) && !defined(Linux) && !defined(FreeBSD) && !defined(HPUX)
- if (!noscreen)
- raw();
- #endif
-
- if ((ronly | force_ronly) && !force_write) {
- xmove(status_window, 0, COLS - 44);
- xaddstr(status_window,
- " File is read only, discard changes? (Y/n)");
- } else {
- saveprompt = 1;
- xmove(status_window, 0, COLS - 22);
- xaddstr(status_window, " Save changes? (Y/n)");
- }
- xclrtoeol(status_window);
- xrefresh(status_window);
-
- while (prompt_user) {
- ch = get_key();
- switch (ch) {
- case 27: /* ESC */
- case 3: /* ^C */
- case 24: /* ^X */
- goto no_save;
- case 'y': /* Yes */
- case 'Y':
- case 13: /* ^M */
- case 10: /* ^J */
- prompt_user = 0;
- break;
- case 'n': /* No */
- case 'N':
- yes = 0;
- prompt_user = 0;
- break;
- }
- }
-
- if (yes && saveprompt)
- buf_write(daddr, buffer, inbuf_size);
-
- if (yes || saveprompt)
- dirty = 0;
-
- no_save:
- xmove(status_window, 0, COLS - 44);
- xclrtoeol(status_window);
- xrefresh(status_window);
- status_mode();
-
- #if !defined(Dynix) && !defined(Linux) && !defined(FreeBSD) && !defined(HPUX)
- if (!noscreen) {
- noraw();
- # if defined(Solaris2)
- cbreak();
- # endif
- }
- #endif
- return(dirty);
- }
-
- int confirm(message)
- char *message;
- {
- char ch = ' ';
-
- xmove(status_window, 0, 20);
- xclrtoeol(status_window);
- xmove(status_window, 0, COLS - strlen(message) - 1);
- xaddstr(status_window, message);
- xrefresh(status_window);
- while ((ch != 'y') && (ch != 'n')) {
- ch = get_key();
- if ((ch == 'Y') || (ch == '\015') || (ch == '\012'))
- ch = 'y';
- if (ch == 'N')
- ch = 'n';
- }
- xmove(status_window, 0, COLS - 20);
- xclrtoeol(status_window);
- xrefresh(status_window);
- if (ch == 'y')
- return(1);
- else
- return(0);
- }
-
- int get_jump(start)
- int start;
- {
- char ch = ' ';
- char str[12];
- int index;
- static int hexdec = -1;
- ulong retval;
- WINDOW *jump_window;
-
- if (hexdec == -1)
- hexdec = wdismode;
-
- jump_window = xnewwin(1, 34, status_line, COLS - 34);
- xmove(jump_window, 0, 0);
- xclrtoeol(jump_window);
- xaddstr(jump_window, "Go to address:");
-
- xrefresh(jump_window);
-
- str[0] = '\0';
-
- index = 0;
- while (ch != 13) { /* ^M */
- xmove(jump_window, 0, 15);
- xclrtoeol(jump_window);
- xmove(jump_window, 0, 30);
- if (hexdec)
- xaddstr(jump_window, "Dec");
- else
- xaddstr(jump_window, "Hex");
- xmove(jump_window, 0, 15);
- xaddstr(jump_window, str);
- xrefresh(jump_window);
- ch = get_key();
- switch (ch) {
- case 8: /* ^H - delete */
- case 127: /* ^? */
- if (index > 0) {
- index--;
- str[index] = '\0';
- }
- break;
- case 21: /* ^U */
- index = 0;
- str[index] = '\0';
- break;
- case 'g':
- ch = 13;
- break;
- case 9: /* TAB */
- case 't':
- case 'T':
- hexdec = !hexdec;
-
- if (index != 0) {
- if (hexdec) {
- sscanf(str, "%x", (uint *) &retval);
- sprintf(str, "%d", (uint) retval);
- } else {
- sscanf(str, "%d", (uint *) &retval);
- sprintf(str, "%x", (uint) retval);
- }
- index = strlen(str);
- }
- break;
- case 'q': /* ^X */
- case 24: /* ^X */
- case 27: /* ESC */
- index = 0;
- ch = 13;
- break;
- default:
- if ((ch >= 'A') && (ch <= 'F'))
- ch += 'a' - 'A';
-
- if (hexdec) { /* DEC */
- if ((index < 10) && (ch >= '0') && (ch <= '9')) {
- str[index] = ch;
- index++;
- str[index] = '\0';
- }
- } else /* HEX */
- if ((index < 8) &&
- (((ch >= '0') && (ch <= '9')) ||
- ((ch >= 'a') && (ch <= 'f')))) {
- str[index] = ch;
- index++;
- str[index] = '\0';
- }
- }
-
- }
- retval = start;
-
- if (index == 0)
- return(-1);
-
- if (hexdec)
- sscanf(str, "%d", (uint *) &retval);
- else
- sscanf(str, "%x", (uint *) &retval);
-
- if (retval == fend)
- retval = fend - 1;
-
- xmove(jump_window, 0, 0);
- xclrtoeol(jump_window);
- xrefresh(jump_window);
-
- xdelwin(jump_window);
- return(retval);
- }
-
- int set_mark(addr)
- int addr;
- {
- char ch;
- int index;
-
- ch = get_key();
- for (index = 0; index < MARKS; index++)
- if (markchar[index] == ch) {
- markpos[index] = addr;
- return(0);
- }
- markchar[marks] = ch;
- markpos[marks] = addr;
- marks = (marks + 1) % MARKS;
- return(0);
- }
-
- int get_mark(start)
- int start;
- {
- int ch;
- int index;
-
- ch = get_key();
- if ((ch == '\'') || (ch == '`'))
- return(last_viewed);
- for (index = 0; index < MARKS; index++)
- if (markchar[index] == ch)
- return(markpos[index]);
- return(start);
- }
-
-
- int prompt_string(string, title)
- char *string;
- char *title;
- {
- char ch = ' ';
- char ch2;
- WINDOW *jump_window;
- char *prevstr;
- char *origstr;
- char *temp;
- int index = 0;
- int index2;
- int slen;
- int origlen;
- #ifdef STRICT_VI
- int emode = -1;
- #else
- int emode = 0;
- #endif
- int rc = 0;
- int titlelen = 0;
-
- /* must take into account that string length can be greater
- then the maximum displayable area on the line. */
-
- /* original copy of string */
- origstr = (char *) malloc(EDIT_STRLEN);
- if (origstr == NULL)
- error_exit("edit_prompt_string: malloc failed");
- strcpy(origstr, string);
-
- /* edit updated copy of string */
- prevstr = (char *) malloc(EDIT_STRLEN);
- if (prevstr == NULL)
- error_exit("edit_prompt_string: malloc failed");
- strcpy(prevstr, string);
-
- origlen = strlen(string);
- titlelen = strlen(title);
- index = origlen - 1;
-
- jump_window = xnewwin(1, COLS - 31, status_line, 20);
- xmove(jump_window, 0, 0);
- xaddstr(jump_window, title);
-
- while ((ch != 13) && (ch != 4)) { /* ^M or ^D */
- slen = strlen(string);
- xstandout(jump_window);
- xmove(jump_window, 0, titlelen);
- if (slen <= origlen) {
- sprintf(out_string, "%s", string);
- xaddstr(jump_window, out_string);
- sprintf(out_string, "%.*s", origlen -
- (int) strlen(out_string), ubar);
- xaddstr(jump_window, out_string);
- xstandend(jump_window);
- sprintf(out_string, "%.*s", EDIT_STRLEN - origlen, ubar);
- xaddstr(jump_window, out_string);
- } else {
- sprintf(out_string, "%.*s", origlen, string);
- xaddstr(jump_window, out_string);
- xstandend(jump_window);
- sprintf(out_string, "%s", string + origlen);
- xaddstr(jump_window, out_string);
- sprintf(out_string, "%.*s", EDIT_STRLEN - slen, ubar);
- xaddstr(jump_window, out_string);
- }
- xmove(jump_window, 0, index + titlelen);
- xrefresh(jump_window);
-
- ch = get_key();
-
- switch (ch) {
- case 2: /* ^B */
- index = 0;
- break;
- case 5: /* ^E */
- index = slen + emode;
- break;
- case 8: /* ^H - delete */
- case 127: /* ^? */
- #ifdef STRICT_VI
- if (emode) {
- if (index > 0)
- index--;
- break;
- }
- #endif
- strcpy(prevstr, string);
- if (index > 0) {
- index--;
- for (index2 = index; index2 < slen; index2++)
- string[index2] = string[index2 + 1];
- }
- break;
- case '':
- if (index > 0)
- index--;
- break;
- case 12: /* ^L */
- if (index < slen)
- index++;
- break;
- case 10: /* ^J */
- ch = 13;
- case 13: /* ^M */
- case 4: /* ^D */
- break;
- case 21: /* ^U */
- strcpy(prevstr, string);
- index = 0;
- string[index] = '\0';
- xmove(jump_window, 0, titlelen);
- xclrtoeol(jump_window);
- break;
- case 24: /* ^X */
- case 3: /* ^C */
- goto quit;
- break;
- case 27: /* ESC */
- emode = -1;
- if (index > slen - 1)
- index--;
- break;
- default:
- if (emode) {
- switch(ch) {
- case 'a':
- strcpy(prevstr, string);
- emode = 0;
- if (index < slen)
- index++;
- break;
- case 'A':
- strcpy(prevstr, string);
- emode = 0;
- index = slen;
- break;
- case 'c':
- emode = 0;
- case 'd':
- strcpy(prevstr, string);
- ch2 = get_key();
- if (ch2 == 'w')
- delword(string + index, slen);
- else if (ch2 == 't') {
- ch2 = get_key();
- for (index2 = index + 1; index2 < slen;
- index2++)
- if (string[index2] == ch2) {
- delchars(string + index, index2 -
- index, slen);
- break;
- }
- }
- if (index > ((int) strlen(string) - 1))
- index = strlen(string) - 1;
- break;
- case 'H':
- case '?':
- help_me(3);
- xtouchwin(jump_window);
- xtouchwin(main_window);
- xrefresh(jump_window);
- xrefresh(main_window);
- break;
- case 'h':
- case 'k':
- case 2: /* ^B */
- if (index > 0)
- index--;
- break;
- case 'I':
- index = 0;
- case 'i':
- strcpy(prevstr, string);
- emode = 0;
- break;
- case 'j':
- case 'l':
- case ' ':
- case 6: /* ^F */
- if (index < slen - 1)
- index++;
- break;
- case 'r':
- case 's':
- strcpy(prevstr, string);
- string[index] = get_key();
- break;
- case 't':
- case 'T':
- ch2 = get_key();
- for (index2 = index + 1; index2 < slen;index2++)
- if (string[index2] == ch2) {
- index = index2 - 1;
- break;
- }
- break;
- case 'u':
- temp = prevstr;
- prevstr = string;
- string = temp;
- break;
- case 'U':
- temp = prevstr;
- prevstr = string;
- string = temp;
- strcpy(string, origstr);
- break;
- case 'x':
- strcpy(prevstr, string);
- for (index2 = index; index2 < slen;index2++)
- string[index2] = string[index2 + 1];
- if (index == slen - 1)
- index--;
- break;
- case '0':
- case '^':
- index = 0;
- break;
- case '$':
- index = slen;
- break;
- }
- break;
- }
- if (ch == 22) /* ^V */
- ch = get_key();
- if (slen == EDIT_STRLEN)
- break;
- for (index2 = slen; index2 > index; index2--)
- string[index2] = string[index2 - 1];
- string[slen + 1] = '\0';
- string[index++] = ch;
- ch = ' ';
- break;
- }
- }
-
- if ((ch == '\015') || (ch == '\012'))
- rc = 2;
- else
- rc = 1;
-
- quit:
-
- xmove(jump_window, 0, 0);
- xclrtoeol(jump_window);
- xrefresh(jump_window);
-
- xdelwin(jump_window);
-
- return(rc);
- }
-
- void delword(string, slen)
- char *string;
- int slen;
- {
- int index;
-
- for (index = 1; index < slen; index++)
- if (strchr(NONWORD, string[index]))
- break;
- delchars(string, index, slen);
- }
-
- void delchars(string, index, slen)
- char *string;
- int index;
- int slen;
- {
- int index2;
-
- for (index2 = index; index2 <= slen; index2++)
- string[index2 - index] = string[index2];
- }
-
- int write_file(first, last, type)
- int first;
- int last;
- int type;
- {
- char name[128];
- char tmp[128];
- char *buf;
- ulong size;
- FILE *out_file;
-
- size = last - first;
- if (size > 65536) {
- if (wdismode)
- sprintf(tmp, "Write %d-%d, %s? (Y/n)",
- first, last, xbytes(size));
- else
- sprintf(tmp, "Write %08x-%08x, %s? (Y/n)",
- first, last, xbytes(size));
- if (!confirm(tmp))
- return(0);
- }
-
- top:
- strcpy(name, "output");
-
- buf = (char *) malloc(size);
- if (buf == NULL)
- error_exit("write_file: malloc failed");
- if (prompt_string(name, "Filename: ")) {
- if (type) {
- #ifdef Win32
- out_file = fopen(name, "ab+");
- if (out_file == NULL)
- out_file = fopen(name, "wb");
- } else
- out_file = fopen(name, "wb");
- #else
- out_file = fopen(name, "a+");
- if (out_file == NULL)
- out_file = fopen(name, "w");
- } else
- out_file = fopen(name, "w");
- #endif
- if (out_file == NULL) {
- sprintf(tmp, "Unable to open %s for writing. Another?", name);
- if (confirm(tmp))
- goto top;
- else {
- xmove(status_window, 0, 20);
- xclrtoeol(status_window);
- xrefresh(status_window);
- return(0);
- }
- }
- if (buf_read(first, buf, size) == 0)
- fwrite(buf, size, 1, out_file);
- fclose(out_file);
- }
- xmove(status_window, 0, 20);
- if (wdismode)
- sprintf(tmp, "Wrote %d-%d, %s.", first, last, xbytes(size));
- else
- sprintf(tmp, "Wrote %08x-%08x, %s.", first, last, xbytes(size));
- xaddstr(status_window, tmp);
-
- xclrtoeol(status_window);
- xrefresh(status_window);
- return(1);
- }
-
- int write_mark(start, type)
- int start;
- int type;
- {
- int ch;
- int temp;
- int end = 0;
-
- if (MARKS == 0) {
- xmove(status_window, 0, 20);
- xaddstr(status_window, "No marks set, press return.");
- goto mark_error;
- }
- leaveok(status_window, FALSE);
- xmove(status_window, 0, 20);
- xaddstr(status_window, "pick end mark ");
- xclrtoeol(status_window);
- xrefresh(status_window);
-
- if ((ch = get_key()) == '\'') {
- xmove(status_window, 0, 20);
- xaddstr(status_window, "pick end mark \'");
- xrefresh(status_window);
- ch = get_key();
- }
- leaveok(status_window, TRUE);
-
- switch (ch) {
- case 27: /* ESC */
- case 10: /* LF */
- case 13: /* CR */
- xmove(status_window, 0, 20);
- xclrtoeol(status_window);
- xrefresh(status_window);
- return(1);
- }
-
- for (temp = 0; temp < MARKS; temp++)
- if (markchar[temp] == ch) {
- end = markpos[temp];
- break;
- }
-
- if (temp == MARKS) {
- xmove(status_window, 0, 20);
- xaddstr(status_window, "Mark ");
- if (ch < ' ') {
- xaddch(status_window, '^');
- xaddch(status_window, ch + '@');
- } else
- xaddch(status_window, ch);
- xaddstr(status_window, " unknown, press return.");
- goto mark_error;
- }
-
- if (start > end) {
- write_file(end, start, type);
- return(0);
- } else if (start < end) {
- write_file(start, end, type);
- return(0);
- }
-
- xmove(status_window, 0, 20);
- xaddstr(status_window, "Can't write 0 bytes, press return.");
-
- mark_error:
- xclrtoeol(status_window);
- xrefresh(status_window);
- while ((ch = get_key()) != EOF)
- if ((ch == 13) || (ch == 10)) /* ^M or ^J */
- break;
- xmove(status_window, 0, 20);
- xclrtoeol(status_window);
- xrefresh(status_window);
- return(1);
- }
-
- static char *xbytes_val[] = {
- "", "K", "M", "G", "T"
- };
-
- static char *xbytes(value)
- ulong value;
- {
- static char buf[32];
- int mul = 0;
- while ((value > 65535) || ((mul > 1) && (value > 8192))) {
- value >>= 10;
- mul++;
- }
- sprintf(buf, "%d %sbytes", (uint) value, xbytes_val[mul]);
-
- return(buf);
- }
-
- #ifdef COLON_MODE
- int colon_mode()
- {
- char ch;
- char buf[128];
- int index = 0;
- int rc = 0;
- int temp;
- char *ptr;
- char *ptr2;
-
- leaveok(status_window, FALSE);
- xmove(status_window, 0, 0);
- xaddch(status_window, ':');
- xclrtoeol(status_window);
- xrefresh(status_window);
-
- buf[0] = '\0';
- do {
- xmove(status_window, 0, 1);
- xaddstr(status_window, buf);
- xrefresh(status_window);
- ch = get_key();
- switch (ch) {
- case 13: /* ^M */
- case 10: /* ^J */
- ch = 13;
- break;
- case 8: /* ^H */
- case 127: /* ^? */
- if (index > 0) {
- xmove(status_window, 0, index);
- xclrtoeol(status_window);
- buf[--index] = '\0';
- } else
- ch = 13;
- break;
- default:
- buf[index++] = ch;
- buf[index] = '\0';
- }
- } while (ch != 13); /* ^M */
-
- leaveok(status_window, TRUE);
- xmove(status_window, 0, 0);
- xclrtoeol(status_window);
- xrefresh(status_window);
-
- switch (buf[0]) {
- case '\0':
- break;
- case 'h':
- if ((buf[1] != '\0') &&
- ((buf[1] != 'e') || (buf[2] != 'l') || (buf[3] != 'p')))
- goto bad_command;
- case '?':
- help_me(5);
- xtouchwin(main_window);
- xrefresh(main_window);
- break;
- case 'e':
- if ((buf[1] != '\0') && (buf[1] != '!') && (buf[1] != ' ') &&
- ((buf[1] != 'd') || (buf[2] != 'i') || (buf[3] != 't')))
- goto bad_command;
-
- for (ptr = buf; *ptr != '\0'; ptr++)
- if (*ptr == ' ') {
- ptr++;
- break;
- }
-
- index = filenum;
- for (ptr2 = ptr; *ptr != '\0'; ptr++)
- if ((*ptr == ' ') || (*ptr == '\t')) {
- *ptr = '\0';
- if (index == filenum)
- index = know_file(ptr2);
- else
- know_file(ptr2);
- ptr2 = ptr + 1;
- }
-
- if (*ptr2 != '\0')
- if (index == filenum)
- index = know_file(ptr2);
- else
- know_file(ptr2);
-
- temp = index;
- if ((buf[1] == '!') || (buf[4] == '!'))
- dirty = 0;
-
- goto new_file;
-
- break;
- case 'n':
- if ((buf[1] != '\0') &&
- ((buf[1] != 'e') || (buf[2] != 'x') || (buf[3] != 't')))
- goto bad_command;
-
- temp = filenum + 1;
- if (temp == filenames) {
- xmove(status_window, 0, 20);
- xaddstr(status_window, "No more files to edit");
- xrefresh(status_window);
- break;
- }
-
- new_file:
- if (save_changes(1))
- break;
-
- close_file();
- view_address = 0;
- cursor_address = 0;
- daddr = -1;
- xmove(status_window, 0, 0);
- xclrtoeol(status_window);
- if (open_file(temp))
- filenum = temp;
- else if (open_file(filenum) == 0) {
- sprintf(out_string, "cannot reopen %s!\n",
- filename[filenum]);
- error_exit(out_string);
- }
- rc = 1;
- break;
- case 'p':
- if ((buf[1] != '\0') &&
- ((buf[1] != 'r') || (buf[2] != 'e')))
- goto bad_command;
-
- temp = filenum - 1;
- if (temp == -1) {
- xmove(status_window, 0, 20);
- xaddstr(status_window, "No previous file to edit");
- xrefresh(status_window);
- break;
- }
- goto new_file;
- case 'q':
- if ((buf[1] != '\0') && (buf[1] != '!') &&
- ((buf[1] != 'u') || (buf[2] != 'i') || (buf[3] != 't')))
- goto bad_command;
-
- /* if not q! then check if dirty, then if more files */
- if ((buf[1] != '!') && (buf[4] != '!')) {
- if (dirty) {
- xmove(status_window, 0, 20);
- xaddstr(status_window, "No write since last change");
- xrefresh(status_window);
- break;
- }
- if (filenum != filenames - 1) {
- char buf[32];
- if (filenum == filenames - 2)
- sprintf(buf, "There is one more file to edit.");
- else
- sprintf(buf, "There are %d more files to edit.",
- filenames - filenum - 1);
- xmove(status_window, 0, 20);
- xaddstr(status_window, buf);
- xrefresh(status_window);
- break;
- }
- }
- dirty = 0;
- rc = -1;
- break;
- case 'r':
- if ((buf[1] != '\0') &&
- ((buf[1] != 'e') || (buf[2] != 'w')))
- goto bad_command;
-
- temp = 0;
- goto new_file;
- case 'w':
- if ((buf[1] != '\0') &&
- ((buf[1] != 'r') || (buf[2] != 'i') ||
- (buf[3] != 't') || (buf[4] != 'e')) &&
- ((buf[1] != 'q') || (buf[2] != '\0')))
- goto bad_command;
-
- if (buf[1] == 'q') {
- save_changes(0);
- rc = -1;
- break;
- }
- dirty = 1;
- save_changes(0);
- xmove(status_window, 0, 20);
- xaddstr(status_window, "Updated ");
- xaddstr(status_window, filename[filenum]);
- xrefresh(status_window);
- break;
- case 'x':
- if ((buf[1] != '\0') &&
- ((buf[1] != 'i') || (buf[2] != 't')))
- goto bad_command;
-
- if (save_changes(0))
- rc = 0;
- else
- rc = -1;
- break;
- default:
- bad_command:
- xmove(status_window, 0, 20);
- xaddstr(status_window, "Unknown command ");
- xaddstr(status_window, buf);
- xrefresh(status_window);
- break;
- }
-
- return(rc);
- }
-
- static int know_file(name)
- char *name;
- {
- int index;
-
- for (index = 0; index < filenames; index++)
- if (!strcmp(filename[index], name))
- return(index);
-
- filename[filenames] = strdup(name);
-
- return(filenames++);
- }
- #endif /* COLON_MODE */
-