home *** CD-ROM | disk | FTP | other *** search
- /* twin.c */
- /* Twin Aspect Display: compare 2 files */
- /* (c) Istvan Mohos, 1988 */
-
- #define MAIN
- #include "ilib.h"
- #include <curses.h>
- #include <signal.h>
-
- #define NSTRIP 4
- #define DIVI 1
- #define SO standout()
- #define SE standend()
- #define HIT 1
- #define YET 0
- #define OVR -1
- #define A 0
- #define B 1
- #define T 2
-
- char *Mesg = "Insufficient terminal capabilities. Sorry...";
- int charsA;
- int charsB;
- int Lcount = 1;
- int chindxA = 1;
- int chindxB = 1;
- int Alines;
- int Blines;
- int oldLcount = 1;
- unsigned char *bigbufA;
- unsigned char *bigbufB;
- unsigned char *Alist;
- unsigned char *Blist;
- unsigned char **Ap;
- unsigned char **Bp;
- unsigned char **Aend;
- unsigned char **Bend;
- unsigned char **oldAp;
- unsigned char **oldBp;
- unsigned char *tpA;
- unsigned char *tpB;
-
- main (argc, argv)
- int argc;
- char *argv[];
- {
- register int ri, rj;
- register unsigned char *pr1, *pr2;
- int startline = 1;
- int endline = 0;
- int x1, x2, ver, llen, redg_x;
- int bugs, realc, is_hope;
- int totchars;
- int ucount = 0;
- int newline = 1;
- unsigned char c, *lstart, *rstart, *bufend;
- unsigned char buf0[512], prcount[60];
- char *cop = "(c)mohos1988";
- int goaway();
-
- if (argc != 3)
- fprintf(stderr, "Usage: %s file1 file2\n", argv[0]), exit(1);
-
- if (imode(argv[1], "40000") == 1)
- fprintf(stderr, "%s is a directory\n", argv[1]), exit(1);
- strcpy(buf0, argv[2]);
- if (imode(buf0, "40000") == 1) {
- pr1 = buf0 + strlen(buf0);
- *pr1++ = '/';
- iego(argv[1], pr1, '/', '/');
- }
-
- if ((charsA = iread(argv[1], &bigbufA)) < 1)
- fprintf(stderr, "%s %s \n",ierbuf, argv[1]), exit(1);
- if ((charsB = iread(buf0, &bigbufB)) < 1)
- fprintf(stderr, "%s %s \n",ierbuf, buf0), exit(1);
-
- if ((Alines = illistn(bigbufA, bigbufA+charsA, &Alist)) < 1)
- fprintf(stderr, "%s %s \n",ierbuf, argv[1]), exit(1);
- if ((Blines = illistn(bigbufB, bigbufB+charsB, &Blist)) < 1)
- fprintf(stderr, "%s %s \n",ierbuf, buf0), exit(1);
-
- initscr();
- crmode();
- noecho();
-
- /* God knows why I had this here originally, maybe SysV needs it:
- nonl();
- */
- signal(SIGINT, goaway);
- if ((COLS < 60) || (LINES < 20))
- goaway();
-
- bufend = buf0 + COLS;
- llen = (COLS - NSTRIP - DIVI -1) / 2;
- redg_x = NSTRIP + llen + DIVI; /* x coordinate for curses */
- lstart = buf0 + NSTRIP;
- rstart = buf0 + NSTRIP + llen + DIVI;
- Mesg = "user interrupt...exiting";
-
- ri = 2;
- mvaddstr(ri++, 1, argv[1]);
- sprintf(prcount, "%4d lines, %5d characters ", Alines, charsA);
- SO, mvaddstr(ri++, 5, prcount), SE;
- ri++;
-
- mvaddstr(ri++, 1, buf0);
- sprintf(prcount, "%4d lines, %5d characters ", Blines, charsB);
- SO, mvaddstr(ri++, 5, prcount), SE;
- ri++;
-
- mvaddstr(1, COLS-15, cop);
-
- mvaddstr(ri++, 1, "[N]f left text up N lines");
- mvaddstr(ri++, 1, "[N]d left text down N lines");
- mvaddstr(ri++, 1, "[N]k right text up N lines");
- mvaddstr(ri++, 1, "[N]j right text down N lines");
- mvaddstr(ri++, 1, "[N]u both texts up N lines");
- mvaddstr(ri++, 1, "[N]v both texts down N lines");
- mvaddstr(ri++, 1, " t back to top of files");
- mvaddstr(ri++, 1, " n show next difference");
- mvaddstr(ri++, 1, "<TAB> page backward");
- mvaddstr(ri++, 1, "<any> page forward");
- mvaddstr(ri++, 1, " q quit");
- refresh();
-
- Ap = oldAp = (unsigned char **)Alist;
- Bp = oldBp = (unsigned char **)Blist;
- Aend = (unsigned char **)Alist + Alines -1; /* last line */
- Bend = (unsigned char **)Blist + Blines -1;
- tpA = *Ap;
- tpB = *Bp;
-
- totchars = charsA + charsB;
- c = getchar();
-
- for (;; ucount = 0) {
- number:
- switch(c) {
-
- default:
- break;
-
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- ucount *= 10;
- ucount += (c - 48);
- c = getchar();
- goto number;
- break;
-
- case 'k': /* bring text up on the right */
- reset();
- if (!ucount)
- ucount = 1;
- mov(B, ucount);
- break;
-
- case 'j': /* bring text down on the right */
- reset();
- if (!ucount)
- ucount = 1;
- mov(B, -ucount);
- break;
-
- case 'f': /* bring text up on the left */
- reset();
- if (!ucount)
- ucount = 1;
- mov(A, ucount);
- break;
-
- case 'd': /* bring text down on the left */
- reset();
- if (!ucount)
- ucount = 1;
- mov(A, -ucount);
- break;
-
- case 'u': /* both up N lines */
- reset();
- if (!ucount)
- ucount = 1;
- mov(T, -ucount);
- break;
-
- case 'v': /* both down N lines */
- reset();
- if (!ucount)
- ucount = 1;
- mov(T, ucount);
- break;
-
- case '\t': /* both up one window */
- reset();
- ucount = endline - startline +1;
- mov(T, -ucount);
- break;
-
- case 't': /* back to top */
- Ap = (unsigned char **)Alist;
- Lcount = 1;
- Bp = (unsigned char **)Blist;
- tpA = *Ap;
- chindxA = 1;
- tpB = *Bp;
- chindxB = 1;
- break;
-
- case 'q': /* quit */
- Mesg = "";
- goaway();
-
- case 'n': /* proceed to next difference */
- while (Bp <= Bend && Ap <= Aend) {
- tpA = *Ap;
- tpB = *Bp;
-
- /* quick test for size of next line */
- if (Ap[1] - tpA != Bp[1] - tpB)
- goto breakout;
- pr1 = tpA;
- pr2 = tpB;
- for (;*pr1; pr1++, pr2++)
- if (*pr1 != *pr2)
- goto breakout;
- if (++Ap <= Aend)
- ++Lcount;
- ++Bp;
- }
- reset(); /* no change found */
- putchar(7);
- breakout:
- chindxA = tpA - bigbufA +1;
- chindxB = tpB - bigbufB +1;
- break;
- }
-
- if (chindxA + chindxB >= totchars) {
- Mesg = "";
- goaway();
- }
-
- oldAp = Ap;
- oldBp = Bp;
- oldLcount = Lcount;
- ver = 0; /* new page starts at line 0 */
-
- /* process one line in each iteration of the loop */
- startline = Lcount;
- while (ver < LINES) {
- iblank(buf0, bufend);
- if (newline && chindxA < charsA) {
-
- sprintf(buf0, "%3d ", Lcount);
- /* last 3 digits of linenum only, plus space */
- pr1 = buf0 + strlen(buf0) - NSTRIP;
- pr2 = buf0;
- for (ri = NSTRIP; --ri >= 0; *pr2++ = *pr1++);
- newline = 0;
- }
- else
- sprintf(buf0, " ");
-
- pr1 = lstart;
- pr2 = rstart;
-
- for (ri = 0; ri < llen; ri++) {
- *pr1 = *tpA;
- *pr2 = *tpB;
-
- /* end of both text lines */
- if((*tpA == '\0') && (*tpB == '\0')) {
- newline = 1;
- if ((rj = inc(A)) == YET)
- ++Lcount, ++Ap, ++tpA;
- else if (rj == OVR)
- *pr1 = '~';
- if ((rj = inc(B)) == YET)
- ++Bp, ++tpB;
- else if (rj == OVR)
- *pr2 = '~';
- break;
- }
-
- /* string ends on left side */
- else if (*tpA == '\0') {
- /* right side done already */
- if (chindxB == charsB) {
- newline = 1;
- if ((rj = inc(A)) == YET)
- ++Lcount, ++Ap, ++tpA;
- else if (rj == OVR)
- *pr1 = '~';
- break;
- }
- /* leave tpA on null while incrementing tpB */
- else {
- if ((rj = inc(B)) == YET || rj == HIT)
- ++pr2, ++tpB;
- if (rj == HIT)
- --chindxB;
- }
- }
-
- /* string ends on right side */
- else if (*tpB == '\0') {
- /* left side is done already */
- if (chindxA == charsA) {
- if ((rj = inc(B)) == YET)
- ++Bp, ++tpB;
- else if (rj == OVR)
- *pr2 = '~';
- break;
- }
- /* leave tpB on null while incrementing tpA */
- else {
- if ((rj = inc(A)) == YET || rj == HIT)
- ++pr1, ++tpA;
- if (rj == HIT)
- --chindxA;
- }
- }
-
- /* add character from both texts */
- else {
- if ((rj = inc(A)) == YET || rj == HIT)
- ++pr1, ++tpA;
- if (rj == HIT)
- --chindxA;
- if ((rj = inc(B)) == YET || rj == HIT)
- ++pr2, ++tpB;
- if (rj == HIT)
- --chindxB;
- }
- }
- *(buf0 + COLS) = 0;
- mvaddstr(ver, 0, buf0);
-
- /* leave text alone: analyze display line */
- pr1 = lstart;
- pr2 = rstart;
- for (bugs = 0, realc = llen, ri = 0; ri < llen; ++ri) {
- if (WHITE(*pr1) && WHITE(*pr2))
- --realc;
- if (*pr1++ != *pr2++)
- ++bugs;
- }
-
- /* at least half of the printing characters match */
- is_hope = bugs <= (realc >> 1);
- pr1 = lstart;
- pr2 = rstart;
- x1 = NSTRIP;
- x2 = redg_x;
- for (ri = 0; ri < llen; ++ri) {
- if ((*pr1 == *pr2) && is_hope) {
- if (WHITE(*pr1))
- *pr1 = ' ', *pr2 = ' ';
- mvaddch(ver, x1++, *pr1);
- mvaddch(ver, x2++, *pr2);
- }
- else {
- if (WHITE(*pr1))
- *pr1 = ' ';
- if (WHITE(*pr2))
- *pr2 = ' ';
-
- standout();
- mvaddch(ver, x1++, *pr1);
- mvaddch(ver, x2++, *pr2);
- standend();
- }
- ++pr1;
- ++pr2;
- }
- if (chindxA <= charsA)
- mvaddstr(ver, x1, "|");
- else
- mvaddstr(ver, x1, " ");
- ++ver;
- }
- endline = Lcount;
- move(LINES -1, COLS -2);
- refresh();
- c = getchar();
- }
- }
-
- goaway() /* restore terminal in case of interrupt */
- {
- signal(SIGINT, SIG_IGN); /* ignore 2nd interrupt */
- mvcur(0, COLS-1, LINES-1, 0);
- endwin();
- printf("%s\n", Mesg);
- exit(0);
- }
-
- reset()
- {
- Ap = oldAp;
- Bp = oldBp;
- tpA = *Ap;
- tpB = *Bp;
- chindxA = tpA - bigbufA +1;
- chindxB = tpB - bigbufB +1;
- Lcount = oldLcount;
- }
-
- mov(side, ucount)
- int side;
- register int ucount;
- {
- switch (side) {
- case A:
- if (ucount > 0) {
- if ((Ap += ucount) <= Aend)
- Lcount += ucount;
- else {
- Ap = Aend;
- Lcount = Alines;
- putchar(7);
- }
- }
- else {
- if ((Ap += ucount) >= (unsigned char **)Alist)
- Lcount += ucount;
- else {
- Ap = (unsigned char **)Alist;
- Lcount = 1;
- putchar(7);
- }
- }
- tpA = *Ap;
- chindxA = tpA - bigbufA +1;
- break;
-
- case B:
- if (ucount > 0) {
- if ((Bp += ucount) > Bend) {
- Bp = Bend;
- putchar(7);
- }
- }
- else {
- if ((Bp += ucount) < (unsigned char **)Blist) {
- Bp = (unsigned char **)Blist;
- putchar(7);
- }
- }
- tpB = *Bp;
- chindxB = tpB - bigbufB +1;
- break;
-
- case T:
- default:
- if (ucount > 0) {
- if (Ap + ucount > Aend || Bp + ucount > Bend) {
- Ap = Aend;
- Lcount = Alines;
- Bp = Bend;
- putchar(7);
- }
- else {
- Ap += ucount;
- Bp += ucount;
- Lcount += ucount;
- }
- }
- else {
- if (Ap + ucount < (unsigned char **)Alist ||
- Bp + ucount < (unsigned char **)Blist) {
- Ap = (unsigned char **)Alist;
- Lcount = 1;
- Bp = (unsigned char **)Blist;
- putchar(7);
- }
- else {
- Ap += ucount;
- Bp += ucount;
- Lcount += ucount;
- }
- }
- tpA = *Ap;
- chindxA = tpA - bigbufA +1;
- tpB = *Bp;
- chindxB = tpB - bigbufB +1;
- break;
- }
- }
-
- inc(side)
- int side;
- {
- if (side) {
- if (chindxB < charsB) {
- if (++chindxB == charsB) {
- return(HIT);
- }
- return(YET);
- }
- return(OVR);
- }
- else {
- if (chindxA < charsA) {
- if (++chindxA == charsA) {
- return(HIT);
- }
- return(YET);
- }
- return(OVR);
- }
- }
-
-