1 /*----------------------------------------------------------------------------*/
2 /* Program: hex.c */
3 /* Date: 27-nov-1988 */
4 /* Desc: Hex editor source */
5 /* Author: Dominic Alston */
6 /* Version: 2.4 */
7 /* Revision history: */
8 /* 25-jan-1989 dom: Added terminal independant code */
9 /* 30-jan-1989 dom: Redesigned screen, added features */
10 /* 03-feb-1989 dom: Modified code. */
11 /* 04-feb-1989 dom: Added own mmi routines */
12 /* 05-feb-1989 dom: Version 2 Increment 0 release finished. */
13 /* 06-feb-1989 dom: Fixed goto out of band chars being accepted */
14 /* 20-feb-1989 dom: Added version print and readonly feature */
15 /* 23-feb-1989 dom: Added screen refresh. */
16 /*----------------------------------------------------------------------------*/
17
18 #include <sys/types.h>
19 #include <curses.h>
20 #include <unistd.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <fcntl.h>
24 #include <ctype.h>
25 #include <errno.h>
26 #include <signal.h>
27 #include <sys/stat.h>
28
29 #define VERSION_STAMP "2.4"
30 #define PAGESIZE 1280
31 #define BUFSIZE 256
32 #define READING 0
33 #define WRITING 1
34 #define GOTO 2
35 #define DBUFF_SIZE 32
36 #define FBUFF_SIZE 16
37 #define X_PRODUCT 30
38 #define Y_PRODUCT 0
39 #define X_MENU1 0
40 #define Y_MENU1 2
41 #define X_MENU2 0
42 #define Y_MENU2 3
43 #define X_STATUS 0
44 #define Y_STATUS 5
45 #define X_FORMAT 76
46 #define X_POSITION 19
47 #define X_PROMPT 0
48 #define Y_PROMPT 6
49 #define X_INPUT 9
50 #define X_FIND 9
51 #define Y_FIND 6
52 #define X_HEX 0
53 #define Y_HEX 7
54 #define X_CHAR 52
55 #define Y_CHAR 7
56 #define X_EXIT 0
57 #define Y_EXIT 23
58 #define X_VERB 36
59 #define Y_VERB 5
60 #define CTRL(c) ((c) & 037)
61 #define _KEY_EXIT 'q'
62 #define ENTER '\n'
63 #define KEY_ESC '\033'
64 #define KEY_TAB '\t'
65
66 static int ch; /* buffer for single character read */
67 static char page[PAGESIZE]; /* buffer for screen display */
68 static char *hptr; /* pointer to page for hex display */
69 static char *cptr; /* pointer to page for character display */
70 static char buf[BUFSIZE]; /* buffer for input i/o */
71 static char *bptr; /* pointer to buf */
72 static char pos[9]; /* buffer for character format of position */
73 static char find_buff[FBUFF_SIZE]; /* buffer holding the string for searching */
74 static int find_length; /* size of string searched for */
75 static char disp_buff[DBUFF_SIZE]; /* buffer holding the search string during */
76 static int disp_length;
77 static char hexchars[] = "0123456789ABCDEF";
78 static char head1[] = " Hexpert [v2.4 (c)1988 Dominic Alston] ";
79 static char r_head2[] =
80 "Options: <Up-arrow> =Page-up <g>=Goto-position <c> =Char-find <q>=Exit ";
81 static char r_head3[] =
82 " <Down-arrow>=Page-down <h>=Hex-find <^l>=Refresh ";
83 static char head2[] =
84 "Options: <Up-arrow> =Page-up <g>=Goto-position <c>=Char-find <q> =Exit";
85 static char head3[] =
86 " <Down-arrow>=Page-down <e>=Edit-buffer <h>=Hex-find <^l>=Refresh";
87 static char head4[] =
88 "Status- Position: 00000000 Mode: View File: ";
89 static char head5[] =
90 "Options: <Enter>=Write-buffer <Tab>=Toggle hex/char edit ";
91 static char head6[] =
92 " <Esc> =Restore buffer & goto view mode ";
93 static char head7[] =
94 "Options: <Enter>=Do-search <Left-arrow>= Move-left ";
95 static char head8[] =
96 " <Esc> =Goto view mode <Right-arrow>=Move-right ";
97 static char edit1[] =
98 "Options: <Enter>=Goto-position <Left-arrow>=Move-left ";
99 static char edit2[] =
100 " <Esc> =Goto view mode <Right-mode>=Move-right ";
101 static char msg1[] = "pattern not found!";
102 static char usage_bnr[]=
103 "Usage: %s [-vr] 'file'\n";
104 static char version_bnr[]=
105 "HEXPERT V%s, Dominic Alston..\n";
106 static char error1[] = "internal error - hex unpaired!";
107 static int x,y; /* screen co-ordinates */
108 static int input; /* file descriptor for input file */
109 static int mode; /* current mode of use */
110 static int readonly; /* true if input file is read only */
111 static int bytes_written;
112 static int bytes_read;
113 static char hex_find; /* true if find mode is currently hex */
114 static off_t position; /* displacement of current buffer in input file */
115 static off_t lastbyte; /* displacement of end of file (Mod 256) */
116 static struct stat filedata; /* statistics of the input file,gives file size */
117 static int bool_hexfind=FALSE;
118
119
120 static void initialise(char *filename);
121 static void display(void);
122 static void closedown(void);
123 static void toplevel(void);
124 static int get_position(void);
125 static void pos_print(void);
126 static void editbuffer(void);
127 static void toplev_headings(void);
128 static void char_ed(void);
129 static void hex_ed(void);
130 static void hex_to_buf(void);
131 static int get_string(void);
132 static void set_string(void);
133 static void buftoh(char *out_string, char *in_string, int in_size);
134 static void htobuf(char *out_string, char *in_string, int in_size);
135 static void buftobuf(char *out_string, char *in_string, int in_size);
136 static void find_string(void);
137 static int search(char *sbuf, off_t *start, int size);
138 static void init_term(void);
139 static void reset_term(void);
140 static int get_str(WINDOW *wnd, int row, int col, char *str, char filler, int str_size);
141 static void ctrlc_ast(int sig);
142 static void put_prompt(void);
143 static void edit_headings(void);
144
145 int
main(int argc,char * argv[])146 main(int argc, char *argv[])
147 {
148 int c;
149 char *filenm = 0;
150
151 while ((c=getopt(argc,argv,"vr:"))!=EOF) {
152 switch(c)
153 {
154 case 'v':
155 fprintf(stderr,version_bnr,
156 VERSION_STAMP);
157 exit(-1);
158 case 'r':
159 readonly=TRUE;
160 filenm=optarg;
161 break;
162 default:
163 fprintf(stderr,usage_bnr,argv[0]);
164 exit(-1);
165 }
166 }
167 if (argc==1) {
168 fprintf(stderr,usage_bnr,argv[0]);
169 exit(-1);
170 } else
171 initialise(filenm==0?argv[1]:filenm);
172 toplevel();
173 closedown();
174 exit(0);
175 }
176
177 static void
initialise(char * filename)178 initialise(char *filename)
179 {
180 register int i,j;
181 char *ptr;
182
183 /* Open file for read & write, if this fails */
184 /* open file for reading, if fail exit. */
185 if ((input=open(filename,O_RDWR))==-1) {
186 if ((input=open(filename,O_RDONLY))==-1) {
187 perror(filename);
188 exit(-1);
189 } else
190 readonly=TRUE;
191 }
192 init_term(); /* init curses terminfo */
193 signal(SIGINT,ctrlc_ast); /* signal handler for contol c */
194 /* Read the file statistics to find the */
195 /* file size and put it in 'lastbyte', */
196 /* after adjusting to a multiple of 256 */
197 if ((fstat(input,&filedata))==0)
198 lastbyte=(filedata.st_size-1) & (off_t)0xffffff00;
199 else
200 lastbyte = 0;
201 /* Clear the display buffer. */
202 hptr=page;
203 for (i=0; i<PAGESIZE; i++)
204 *hptr++=' ';
205 attron(A_REVERSE);
206 addstr(head1);
207 attroff(A_REVERSE);
208 toplev_headings();
209 mvaddstr(Y_STATUS, X_STATUS,head4);
210 /* Display the input file name. */
211 i=strlen(filename);
212 ptr=(char *)filename;
213 if (i>33)
214 i=33;
215 for (j=0; j<i; j++)
216 addch(*ptr++);
217 /* Read and display the first 256 bytes */
218 if (readonly) {
219 attron(A_BOLD);
220 mvaddstr(Y_STATUS,72,"Readonly");
221 attroff(A_BOLD);
222 }
223 refresh();
224 position = 0;
225 lseek(input,position,0);
226 display();
227 mode = READING;
228 hex_find = FALSE;
229 find_length = 0;
230 put_prompt();
231 refresh();
232 }
233
234 static void
display(void)235 display(void)
236 {
237 int num;
238 register int i;
239 int j;
240 int jlimit;
241
242 hptr = page;
243 cptr = (hptr + 52);
244 bptr = buf;
245 pos_print();
246 move(Y_HEX, X_HEX);
247 if (((num=read(input,buf,BUFSIZE))!=EOF) && (num!=0)) {
248 if (num<BUFSIZE) {
249 for (i=0; i<PAGESIZE; i++)
250 *hptr++ = ' ';
251 hptr=page;
252 }
253 for (i=0; i<num; i+=16) {
254 jlimit=((num-i)>=16)?16:num-i;
255 for (j=0; j<jlimit; j++) {
256 *hptr++=hexchars[(*bptr>>4) & 0xf];
257 *hptr++=hexchars[*bptr & 0xf];
258 *hptr++=' ';
259 *cptr++=((*bptr)>0x1f &&
260 (*bptr)<0x7f?*bptr:'.');
261 bptr++;
262 }
263 *((cptr-jlimit)+80)='\n';
264 hptr+=32;
265 cptr=(hptr+52);
266 }
267 } else
268 for(i=0; i<PAGESIZE; i++)
269 *hptr++=' ';
270 bytes_read=num;
271 move(Y_HEX,X_HEX);
272 hptr=page;
273 for (i=0; i<PAGESIZE; i++)
274 mvaddch(Y_HEX+(i/80), X_HEX+(i%80),*hptr++);
275 bytes_written=i;
276 if (bytes_written!=PAGESIZE)
277 closedown();
278 put_prompt();
279 refresh();
280 }
281
282 static void
closedown(void)283 closedown(void)
284 {
285 reset_term();
286 exit(0);
287 }
288
289 static void
toplevel(void)290 toplevel(void)
291 {
292
293 while ((ch=getch())!=_KEY_EXIT) {
294 clrtoeol();
295 refresh();
296 switch(ch) {
297 case CTRL('l'):
298 clearok(curscr,TRUE);
299 doupdate();
300 break;
301 case KEY_HOME:
302 if (position!=0) {
303 position=0;
304 lseek(input,position,0);
305 display();
306 } else
307 beep();
308 break;
309 case KEY_DOWN:
310 if (position != lastbyte) {
311 if ((position += 256) > lastbyte)
312 position = lastbyte;
313 lseek(input,position,0);
314 display();
315 } else
316 beep();
317 break;
318 case KEY_UP:
319 if (position != 0) {
320 position -= 256;
321 if (position < 0)
322 position = 0;
323 lseek(input,position,0);
324 display();
325 } else
326 beep();
327 break;
328 case 'g':
329 case 'G':
330 mode=GOTO;
331 if (get_position()) {
332 lseek(input,position,0);
333 display();
334 } else
335 pos_print();
336 toplev_headings();
337 mode=READING;
338 break;
339 case 'e':
340 case 'E':
341 if (readonly) {
342 beep();
343 move(6,9);
344 refresh();
345 } else
346 editbuffer();
347 break;
348 case 'c':
349 case 'C':
350 case 'h':
351 case 'H':
352 if ((ch=='c') || (ch=='C'))
353 hex_find=FALSE;
354 else
355 hex_find=TRUE;
356 if (get_string()==1)
357 find_string();
358 toplev_headings();
359 break;
360 default:
361 beep();
362 break;
363 }
364 }
365 }
366
367 static int
get_position(void)368 get_position(void)
369 {
370 char num[9];
371 char *ptr1,*ptr2;
372 int status;
373 off_t posit;
374 register int i;
375
376 edit_headings();
377 posit=0;
378 ptr1=num;
379 ptr2=pos;
380 for (i=0; i<9; i++)
381 (*(ptr1++))=(*(ptr2++));
382 move(Y_STATUS,10);
383 disp_length=7;
384 if ((status=get_str(stdscr,Y_STATUS,X_POSITION,num,'0',8))==-1)
385 return(FALSE);
386 for (i=0; i<8; i++) {
387 posit=(posit<<4)+(num[i] & 0xf);
388 if (num[i]>'9')
389 posit+=9;
390 }
391 if (posit<0)
392 posit=0;
393 if (posit<=lastbyte)
394 position=posit;
395 else
396 position=lastbyte;
397 return(TRUE);
398 }
399
400 static void
pos_print(void)401 pos_print(void)
402 {
403 char *ptr;
404
405 ptr=pos+7;
406 *ptr--=hexchars[(position & 0xf)];
407 *ptr--=hexchars[((position>>4) & 0xf)];
408 *ptr--=hexchars[((position>>8) & 0xf)];
409 *ptr--=hexchars[((position>>12) & 0xf)];
410 *ptr--=hexchars[((position>>16) & 0xf)];
411 *ptr--=hexchars[((position>>20) & 0xf)];
412 *ptr--=hexchars[((position>>24) & 0xf)];
413 *ptr--=hexchars[((position>>28) & 0xf)];
414 *(pos+9)=0;
415 mvaddstr(Y_STATUS,X_POSITION,pos);
416 }
417
418 static void
editbuffer(void)419 editbuffer(void)
420 {
421 /* Display edit headings */
422 mvaddstr(Y_MENU1, X_MENU1,head5);
423 mvaddstr(Y_MENU2, X_MENU2,head6);
424 mvaddstr(Y_VERB, X_VERB,"Edit");
425 hex_ed();
426 mode = READING;
427 toplev_headings();
428 }
429
430 /* read_headings: Display read headings */
431 static void
toplev_headings(void)432 toplev_headings(void)
433 {
434 if (readonly) {
435 mvaddstr(Y_MENU1, X_MENU1,r_head2);
436 mvaddstr(Y_MENU2, X_MENU2,r_head3);
437 } else {
438 mvaddstr(Y_MENU1, X_MENU1,head2);
439 mvaddstr(Y_MENU2, X_MENU2,head3);
440 }
441 mvaddstr(Y_VERB, X_VERB,"View");
442 move(Y_PROMPT, X_INPUT);
443 refresh();
444 }
445
446 static void
char_ed(void)447 char_ed(void) /* Entered from hex_ed() when 'TAB' read. */
448 {
449 char *ptr;
450 char *eptr;
451 unsigned char c1,c2;
452 int xx;
453
454 /* get byte by mapping on to physical scale from screen scale */
455 ptr=page+(y-7)*80+x;
456 move(y,x);
457 refresh();
458 do {
459 ch=getch();
460 if ((ch)>=0x20 && (ch)<0x7f) {
461 addch(ch);
462 refresh();
463 *ptr = ch;
464 c1 = ch & 0xf;
465 c2 = (ch >> 4) & 0xf;
466 xx = (x - 52) * 3;
467 eptr = (ptr - x) + xx;
468 *eptr++ = hexchars[c2];
469 *eptr = hexchars[c1];
470 move(y,xx);
471 addch(*--eptr);
472 addch(*++eptr);
473 refresh();
474 if (x == 67) {
475 if (y < 22) {
476 ptr +=65;
477 x = 52;
478 y++;
479 } else {
480 ptr = page + 52;
481 x = 52;
482 y = 7;
483 }
484 } else {
485 ptr++;
486 x++;
487 }
488 }
489 else if (ch==KEY_RIGHT)
490 if (x==67) {
491 if (y<22) {
492 ptr+=65;
493 x=52;
494 y++;
495 } else {
496 ptr=page+52;
497 x=52;
498 y=7;
499 }
500 } else {
501 ptr++;
502 x++;
503 }
504 else if (ch == KEY_LEFT)
505 if (x == 52) {
506 if (y > 7) {
507 ptr -= 65;
508 x = 67;
509 y--;
510 } else {
511 ptr += 1215;
512 x = 67;
513 y = 22;
514 }
515 } else {
516 ptr--;
517 x--;
518 }
519 else if (ch == KEY_UP)
520 if (y > 7) {
521 ptr -=80;
522 y--;
523 } else {
524 ptr +=1200;
525 y = 22;
526 }
527 else if (ch == KEY_DOWN)
528 if (y < 22) {
529 ptr +=80;
530 y++;
531 } else {
532 ptr -=1200;
533 y = 7;
534 }
535 else if (ch == KEY_ESC) {
536 lseek(input,position,0);
537 display();
538 } else if ((ch == ENTER) || (ch == KEY_TAB))
539 /* do nothing */ ;
540 else
541 beep();
542 move(y,x);
543 refresh();
544 } while ((ch!=ENTER) && (ch!=KEY_TAB) && (ch!=KEY_ESC));
545 if (ch==ENTER) {
546 hex_to_buf();
547 lseek(input,position,0);
548 write(input,buf,bytes_read);
549 }
550 mode=READING;
551 }
552
553 static void
hex_ed(void)554 hex_ed(void)
555 {
556 char *ptr;
557
558 ptr=page;
559 x=X_HEX;
560 y=Y_HEX;
561 move(y,x);
562 refresh();
563 do {
564 ch=getch();
565 if (isxdigit(ch)) {
566 addch(toupper(ch));
567 refresh();
568 *ptr = ch;
569 {
570 char *eptr,c1,c2;
571 int xx;
572
573 if ((x%3) == 1)
574 eptr = ptr - 1;
575 else
576 eptr = ptr;
577 c1 = *eptr++;
578 c2 = *eptr;
579 if (c1 > '9')
580 c1 = (c1 + 9) & 0xf;
581 else
582 c1 = c1 & 0xf;
583 if (c2 > '9')
584 c2 = (c2 + 9) & 0xf;
585 else
586 c2 = c2 & 0xf;
587 c1 = (c1 << 4) + c2;
588 xx = (x/3) + 52;
589 move(y,xx);
590 refresh();
591 if ((c1>=0x20) && (c1<0x7f))
592 addch(c1);
593 else
594 addch('.');
595 refresh();
596 }
597 ptr++;
598 x++;
599 if (((x+1)%3)==0) {
600 if (x==47) {
601 if (y<22) {
602 ptr+=33;
603 x=0;
604 y++;
605 } else {
606 ptr=page;
607 x=0;
608 y=7;
609 }
610 } else {
611 ptr++;
612 x++;
613 }
614 }
615 } else if (ch==KEY_RIGHT) {
616 ptr++;
617 x++;
618 if (((x+1)%3)==0) {
619 if (x==47) {
620 if (y<22) {
621 ptr+=33;
622 x=0;
623 y++;
624 } else {
625 ptr=page;
626 x=0;
627 y=7;
628 }
629 } else {
630 ptr++;
631 x++;
632 }
633 }
634 }
635 else if (ch==KEY_LEFT)
636 if (x==0) {
637 if (y>7) {
638 ptr -= 34;
639 x = 46;
640 y--;
641 } else {
642 ptr += 1246;
643 x = 46;
644 y = 22;
645 }
646 } else {
647 ptr--;
648 x--;
649 if (((x+1)%3)==0)
650 {
651 ptr--;
652 x--;
653 }
654 }
655 else if (ch == KEY_UP)
656 if (y > 7) {
657 ptr -= 80;
658 y--;
659 } else {
660 ptr += 1200;
661 y = 22;
662 }
663 else if (ch == KEY_DOWN)
664 if (y < 22) {
665 ptr += 80;
666 y++;
667 } else {
668 ptr -= 1200;
669 y = 7;
670 }
671 else if (ch == KEY_ESC) {
672 lseek(input,position,0);
673 display();
674 }
675 else if (ch==ENTER)
676 ;
677 else if (ch==KEY_TAB) {
678 x = (x/3) + 52;
679 char_ed();
680 x = (x-52) * 3;
681 ptr = page + (y-7)*80 + x;
682 } else
683 beep();
684 move(y,x);
685 refresh();
686 } while (ch!=ENTER && ch!=KEY_ESC);
687 if (ch==ENTER) {
688 hex_to_buf();
689 lseek(input,position,0);
690 write(input,buf,bytes_read);
691 }
692 }
693
694 static void
hex_to_buf(void)695 hex_to_buf(void)
696 {
697 char c1,c2;
698 int i;
699 int j;
700
701 hptr = page;
702 bptr = buf;
703 for (i=0;i<16;i++) {
704 for (j=0;j<16;j++) {
705 c1 = *hptr++;
706 if (c1 > '9')
707 c1 = (c1 + 9) & 0xf;
708 else
709 c1 = c1 & 0xf;
710 c2 = *hptr++;
711 if (c2 > '9')
712 c2 = (c2 + 9) & 0xf;
713 else
714 c2 = c2 & 0xf;
715 *bptr++ = (c1 << 4) + c2;
716 hptr++;
717 }
718 hptr += 32;
719 }
720 }
721
722 static int
get_string(void)723 get_string(void)
724 {
725 mvaddstr(Y_MENU1, X_MENU1,head7);
726 mvaddstr(Y_MENU2, X_MENU2,head8);
727 mvaddstr(Y_VERB, X_VERB,"Find");
728 attron(A_BOLD);
729 mvaddstr(6,0,"search criteria: ");
730 attroff(A_BOLD);
731 if ((bool_hexfind && !hex_find) || (!bool_hexfind && hex_find)) {
732 if (hex_find)
733 bool_hexfind=TRUE;
734 else if (!hex_find)
735 bool_hexfind=FALSE;
736 find_length=0;
737 disp_buff[0]=0;
738 }
739 if (hex_find) {
740 buftoh(disp_buff,find_buff,find_length);
741 disp_length=find_length*2;
742 } else
743 buftobuf(disp_buff,find_buff,disp_length=find_length);
744 if ((disp_length=get_str(stdscr,6,17,disp_buff,'.',
745 hex_find?DBUFF_SIZE:FBUFF_SIZE))==-1) {
746 put_prompt();
747 return(FALSE);
748 } else if (disp_length==0 && hex_find)
749 disp_length=find_length*2;
750 else if (disp_length==0 && !hex_find)
751 disp_length=find_length;
752 set_string();
753 return(TRUE);
754 }
755
756 /* set_string: set up the string for return */
757 static void
set_string(void)758 set_string(void)
759 {
760 if (hex_find) {
761 htobuf(find_buff,disp_buff,disp_length);
762 find_length=disp_length/2;
763 } else
764 buftobuf(find_buff,disp_buff,find_length=disp_length);
765 }
766
767 /* buftoh: Converts input buffer to hexadecimal display in output string.
768 * String length is used since zero is legitimate.
769 */
770 static void
buftoh(char * out_string,char * in_string,int in_size)771 buftoh(char *out_string, char *in_string, int in_size)
772 {
773 register int i;
774
775 for (i=0; i < in_size; i++) {
776 char c = *in_string++;
777 *out_string++ = hexchars[(c >> 4) & 0xf]; /* [c/16]; */
778 *out_string++ = hexchars[ c & 0xf]; /* [c%16]; */
779 }
780 }
781
782 /* htobuf: converts hexadecimal display to binary. String length is used
783 * and only hexadecimal pairs are handled.
784 */
785 static void
htobuf(char * out_string,char * in_string,int in_size)786 htobuf(char *out_string, char *in_string, int in_size)
787 {
788 char i;
789 int h_value, c_value;
790 int byte_val = 0;
791
792 if (in_size%2 != 0) {
793 put_prompt();
794 addstr(error1);
795 beep();
796 refresh();
797 return;
798 }
799 for (i=0; i < in_size; i++) {
800 if ((h_value = *in_string++) >= '0' && h_value <= '9')
801 c_value = h_value -'0';
802 else
803 (c_value = 10 + (h_value & 0xf) - ('a' & 0xf));
804 if (!(i%2))
805 byte_val = c_value * 16;
806 else
807 *out_string++ = byte_val + c_value;
808 }
809 }
810
811 /* buftobuf: Copy buffer to buffer. Not quite strncopy since zero is valid
812 * and not a terminator.
813 */
814 static void
buftobuf(char * out_string,char * in_string,int in_size)815 buftobuf(char *out_string, char *in_string, int in_size)
816 {
817 register int i;
818
819 for (i=0; i<in_size; i++)
820 (*(out_string++))=(*(in_string++));
821 }
822
823 /* find_string: Locates the string which has been specified by the user.
824 * The search is carried out cyclically locating the string
825 * specified at the beginning of the buffer. If the string is
826 * not found we tell the user with a friendly message.
827 */
828 static void
find_string(void)829 find_string(void)
830 {
831 off_t start_pos=position; /* hold start position to stop cyclic search */
832 int inc_length;
833 /* the number of start points for search in one buffer full */
834 int num_read; /* number read in this read */
835 int found_it=0;
836
837 position ++; /* make sure we move ahead */
838 inc_length=BUFSIZE-find_length;
839 /* search to the end of the file */
840 while (filedata.st_size>=position+find_length && found_it!=1) {
841 lseek(input,position,0);
842 num_read=read(input,buf,BUFSIZE);
843 if (search(buf,&position,num_read-find_length))
844 found_it=1;
845 }
846 /* if still not found then search from beginning */
847 if (found_it!=1) {
848 position=0;
849 while (position<=start_pos && found_it!=1) {
850 lseek(input,position,0);
851 num_read=read(input,buf,BUFSIZE);
852 if (search(buf,&position,position+inc_length<start_pos?
853 (int)inc_length:(int)(start_pos-position)))
854 found_it=1;
855 }
856 }
857 if (found_it!=1) {
858 put_prompt();
859 addstr(msg1);
860 beep();
861 refresh();
862 position = start_pos;
863 lseek(input,position,0);
864 return;
865 }
866 lseek(input, position, 0);
867 display();
868 }
869
870 /* search: Search for the field described by find_buff and find_length in
871 * the parameter buf incrementing start as far as size.
872 * Returning true if the string is found.
873 */
874 static int
search(char * sbuf,off_t * start,int size)875 search(char *sbuf, off_t *start, int size)
876 {
877 int i, j;
878
879 i = 0;
880 j = -1;
881 while (i != find_length && j++ < size) { /* loop through buffer */
882 for (i=0; i<find_length && *(find_buff+i)==*(sbuf+i); i++)
883 /* loop through string (no body) */ ;
884 sbuf++;
885 }
886 *start+=j;
887 return (i==find_length);
888 }
889
890 /* initialise term.. */
891 static void
init_term(void)892 init_term(void)
893 {
894 initscr(); /* init curses terminfo */
895 keypad(stdscr,TRUE); /* allow keypad use */
896 noecho(); /* set terminal to noecho */
897 cbreak(); /* raw input */
898 }
899
900 /* reset term to the way it was */
901 static void
reset_term(void)902 reset_term(void)
903 {
904 nocbreak();
905 echo();
906 endwin();
907 }
908
909 /* get string routine */
910 static int
get_str(WINDOW * wnd,int row,int col,char * str,char filler,int str_size)911 get_str(WINDOW *wnd, int row, int col, char *str, char filler, int str_size)
912 {
913 int ccol=0,c,erase_flg=0;
914 register int i;
915 int leave=FALSE;
916 int status=0;
917
918 for (i=0; i<str_size; i++) /* paste filler to field */
919 mvwaddch(wnd,row,col+i,filler);
920 /* print contents of str */
921 for (i=0; i<disp_length; i++)
922 mvwaddch(wnd,row,col+i,str[i]);
923 wmove(wnd,row,col); /* move to field start */
924 wrefresh(wnd); /* refresh whats been done */
925 while (!leave) {
926 c=wgetch(wnd);
927 switch(c) {
928 case '\n':
929 case '\r':
930 leave=TRUE;
931 break;
932 case KEY_HOME:
933 ccol=0;
934 wmove(wnd,row,col+ccol);
935 refresh();
936 break;
937 case KEY_BACKSPACE:
938 case CTRL('h'):
939 if (ccol>0){
940 if (--ccol<0)
941 ccol=0;
942 mvwaddch(wnd,row,col+ccol,filler);
943 wmove(wnd,row,col+ccol);
944 *(str+ccol)=' ';
945 wrefresh(wnd);
946 } else
947 beep();
948 break;
949 case KEY_ESC: /* if escape pressed */
950 status=(char)-1;
951 leave=TRUE;
952 break;
953 case KEY_LEFT:
954 erase_flg=1;
955 if (ccol>0) {
956 if (--ccol<0)
957 ccol=0;
958 wmove(wnd,row,col+ccol);
959 wrefresh(wnd);
960 } else
961 beep();
962 break;
963 case KEY_RIGHT:
964 if (ccol<str_size-1) {
965 if (++ccol>str_size)
966 ccol=str_size;
967 wmove(wnd,row,col+ccol);
968 wrefresh(wnd);
969 } else
970 beep();
971 break;
972 default: /* other chars */
973 if ((((hex_find || mode==GOTO) && isxdigit(c)) ||
974 ((!hex_find && mode!=GOTO) &&
975 (c>=0x20 && c<0x7f))) &&
976 ccol<str_size) {
977 if (erase_flg==0){
978 for (i=0; i<str_size; i++) {
979 mvwaddch(wnd,row,col+i,
980 filler);
981 str[i]=' ';
982 }
983 }
984 mvwaddch(wnd,row,col+ccol,c);
985 wrefresh(wnd);
986 *(str+ccol)=c;
987 if (++ccol>str_size)
988 ccol=str_size;
989 } else
990 beep();
991 break;
992 }
993 erase_flg=1;
994 }
995 if (status==0)
996 status=ccol;
997 return(status);
998 }
999
1000 static void
ctrlc_ast(int sig)1001 ctrlc_ast(int sig)
1002 {
1003 if (sig==SIGINT)
1004 closedown();
1005 else
1006 signal(SIGINT,ctrlc_ast);
1007 }
1008
1009 static void
put_prompt(void)1010 put_prompt(void)
1011 {
1012 move(6,0);
1013 clrtoeol();
1014 attron(A_BOLD);
1015 mvaddstr(Y_PROMPT, X_PROMPT,"command> ");
1016 attroff(A_BOLD);
1017 }
1018
1019 static void
edit_headings(void)1020 edit_headings(void)
1021 {
1022 mvaddstr(Y_MENU1, X_MENU1,edit1);
1023 mvaddstr(Y_MENU2, X_MENU2,edit2);
1024 mvaddstr(Y_VERB, X_VERB,"Goto");
1025 }
1026