home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (c) 1988 Bellcore
- ** All Rights Reserved
- ** Permission is granted to copy or use this program, EXCEPT that it
- ** may not be sold for profit, the copyright notice must be reproduced
- ** on copies, and credit should be given to Bellcore where it is due.
- ** BELLCORE MAKES NO WARRANTY AND ACCEPTS NO LIABILITY FOR THIS PROGRAM.
- */
-
-
- #ifndef lint
- static char rcsid[]= "$Header: output.c,v 1.1 88/09/15 11:33:52 daniel Rel $";
- #endif
-
- #include <stdio.h>
-
- #ifdef M_TERMINFO
- #include <curses.h>
- #include <term.h>
- #endif
-
- #ifdef M_TERMCAP
- #ifdef XENIX
- #include <tcap.h>
- #endif
- #endif
-
- #include "misc.h"
- #include "flagdefs.h"
- #include "edit.h"
- #include "line.h"
- #include "token.h"
-
- static int _O_need_init = 1;
- static int _O_st_ok = 0;
- static int _O_doing_ul = 0;
- static char *_O_st_tmp;
- #ifdef M_TERMCAP
- static char _O_startline[Z_WORDLEN];
- static char _O_endline[Z_WORDLEN];
- #endif
-
- static void
- _O_st_init()
- {
- char termn[Z_WORDLEN];
- #ifdef M_TERMCAP
- static char entry[1024];
- #endif
-
- /*
- ** see if standard out is a terminal
- */
- if (!isatty(1))
- {
- _O_need_init = 0;
- _O_st_ok = 0;
- return;
- }
-
- if (NULL == (_O_st_tmp = (char*) getenv("TERM")))
- {
- Z_complain("can't find TERM entry in environment\n");
- _O_need_init = 0;
- _O_st_ok = 0;
- return;
- }
- (void) strcpy(termn,_O_st_tmp);
-
- #ifdef M_TERMCAP
- if (1 != tgetent(entry,termn))
- {
- Z_complain("can't get TERMCAP info for terminal\n");
- _O_need_init = 0;
- _O_st_ok = 0;
- return;
- }
-
- _O_st_tmp = _O_startline;
- _O_startline[0] = '\0';
- tgetstr("so",&_O_st_tmp);
-
- _O_st_tmp = _O_endline;
- _O_endline[0] = '\0';
- tgetstr("se",&_O_st_tmp);
-
- _O_st_ok = (strlen(_O_startline) > 0) && (strlen(_O_endline) > 0);
- #endif
-
- #ifdef M_TERMINFO
- setupterm(termn,1,&_O_st_ok);
- #endif
- _O_need_init = 0;
- }
-
- void
- O_cleanup()
- {
- /*
- ** this probably isn't necessary, but in the
- ** name of compeleteness.
- */
- #ifdef M_TERMINFO
- resetterm();
- #endif
- }
-
- static void
- _O_start_standout()
- {
- if (_O_need_init)
- {
- _O_st_init();
- }
- if (_O_st_ok)
- {
- #ifdef M_TERMCAP
- (void) printf("%s",_O_startline);
- #endif
- #ifdef M_TERMINFO
- vidattr(A_STANDOUT);
- #endif
- }
- else
- {
- _O_doing_ul = 1;
- }
- }
-
- static void
- _O_end_standout()
- {
- if (_O_need_init)
- {
- _O_st_init();
- }
- if (_O_st_ok)
- {
- #ifdef M_TERMCAP
- (void) printf("%s",_O_endline);
- #endif
- #ifdef M_TERMINFO
- vidattr(0);
- #endif
- }
- else
- {
- _O_doing_ul = 0;
- }
- }
-
- static void
- _O_pchars(line,start,end)
- char *line;
- int start,end;
- {
- int cnt;
-
- for(cnt=start;cnt < end; cnt++)
- {
- if (_O_doing_ul)
- {
- (void) putchar('_');
- (void) putchar('\b');
- }
- (void) putchar(line[cnt]);
- }
- }
-
-
- /*
- ** convert a 0 origin token number to a 1 orgin token
- ** number or 1 origin line number as appropriate
- */
- static
- _O_con_line(numb,flags,filenum)
- int numb, flags,filenum;
- {
- if (flags & U_TOKENS)
- {
- return(numb+1);
- }
- else
- {
- /*
- ** check to make sure that this is a real
- ** line number. if not, then return 0
- ** on rare occasions, (i.e. insertion/deletion
- ** of the first token in a file) we'll get
- ** line numbers of -1. the usual look-up technique
- ** won't work since we have no lines before than 0.
- */
- if (numb < 0)
- return(0);
- /*
- ** look up the line number the token and then
- ** add 1 to make line number 1 origin
- */
- return(L_tl2cl(filenum,numb)+1);
- }
- }
-
- static char *
- _O_convert(ptr)
- char *ptr;
- {
- static char spacetext[Z_WORDLEN];
-
- if (1 == strlen(ptr))
- {
- switch (*ptr)
- {
- default:
- break;
- case '\n' :
- (void) strcpy(spacetext,"<NEWLINE>");
- return(spacetext);
- case '\t' :
- (void) strcpy(spacetext,"<TAB>");
- return(spacetext);
- case ' ' :
- (void) strcpy(spacetext,"<SPACE>");
- return(spacetext);
- }
-
- }
- return(ptr);
- }
-
- static char*
- _O_get_text(file,index,flags)
- int file,index,flags;
- {
- static char buf[Z_LINELEN*2]; /* leave lots of room for both
- the token text and the
- chatter that preceeds it */
- char *text;
- K_token tmp;
-
- if (flags & U_TOKENS)
- {
- tmp = K_gettoken(file,index);
- text = _O_convert(K_gettext(tmp));
- (void) sprintf(buf,"%s -- line %d, character %d\n",
- text,
- /*
- ** add 1 to make output start at line 1
- ** and character numbers start at 1
- */
- L_tl2cl(file,K_getline(tmp))+1,
- K_getpos(tmp)+1);
- return(buf);
- }
- else
- {
- return(L_gettline(file,index));
- }
- }
- #define _O_APP 1
- #define _O_DEL 2
- #define _O_CHA 3
- #define _O_TYPE_E 4
-
- static void
- _O_do_lines(start,end,file)
- int start,end,file;
- {
- int cnt;
- int lastline = -1;
- int nextline;
- K_token nexttoken;
- for (cnt=start;cnt <= end; cnt++)
- {
- nexttoken = K_get_token(file,cnt);
- nextline = K_getline(nexttoken);
- if (lastline != nextline)
- {
- int lastone,lastchar;
- K_token lasttok;
- char linetext[Z_LINELEN+1]; /* leave room for
- terminator */
- if (0 == file)
- {
- (void) printf("< ");
- }
- else
- {
- (void) printf("> ");
- }
-
- /*
- ** put loop here if you want to print
- ** out any intervening lines that don't
- ** have any tokens on them
- */
-
- /*
- ** following line is necessary because
- ** L_gettline is a macro, and can't be passed
- */
- (void) strcpy(linetext,L_gettline(file,nextline));
- _O_pchars(linetext,0,K_getpos(nexttoken));
- _O_start_standout();
- /*
- ** look for last token on this line to be
- ** highlighted
- */
- for ( lastone=cnt,lasttok = K_get_token(file,lastone);
- (lastone<=end)&&(nextline == K_getline(lasttok));
- lastone++,lasttok = K_get_token(file,lastone))
- {
- }
- lastone--;
- lasttok = K_get_token(file,lastone);
- lastchar = K_getpos(lasttok)
- + strlen(K_gettext(lasttok));
- _O_pchars(linetext,K_getpos(nexttoken),lastchar);
- _O_end_standout();
- _O_pchars(linetext,lastchar,strlen(linetext));
-
- lastline = nextline;
- }
- }
- }
-
- void
- O_output(start,flags)
- E_edit start;
- int flags;
- {
- int type = _O_TYPE_E; /* initialize to error state
- ** this is to make sure that type is set
- ** somewhere
- */
- int t_beg1, t_beg2, t_end1, t_end2; /* token numbers */
- int first1, last1, first2, last2;
-
- E_edit ep, behind, ahead, a, b;
-
- /*
- ** reverse the list of edits
- */
- ahead = start;
- ep = E_NULL;
- while (ahead != E_NULL) {
- /*
- ** set token numbers intentionally out of range
- ** as boilerplate
- */
- t_beg1 = t_beg2 = t_end1 = t_end2 = -1;
- /*
- ** edit script is 1 origin, all of
- ** our routines are zero origin
- */
- E_setl1(ahead,(E_getl1(ahead))-1);
- E_setl2(ahead,(E_getl2(ahead))-1);
-
- behind = ep;
- ep = ahead;
- ahead = E_getnext(ahead);
- E_setnext(ep,behind);
- }
-
- /*
- ** now run down the list and collect the following information
- ** type of change (_O_APP, _O_DEL or _O_CHA)
- ** start and length for each file
- */
- while (ep != E_NULL)
- {
- b = ep;
- /*
- ** operation always start here
- */
- t_beg1 = E_getl1(ep);
- /*
- ** any deletions will appear before any insertions,
- ** so, if the first edit is an E_INSERT, then this
- ** this is an _O_APP
- */
- if (E_getop(ep) == E_INSERT)
- type = _O_APP;
- else {
- /*
- ** run down the list looking for the edit
- ** that is not part of the current deletion
- */
- do {
- a = b;
- b = E_getnext(b);
- } while ((b != E_NULL) &&
- (E_getop(b) == E_DELETE) &&
- ((E_getl1(b)) == ((E_getl1(a))+1)));
- /*
- ** if we have an insertion at the same place
- ** as the deletion we just scanned, then
- ** this is a change
- */
- if ((b != E_NULL) &&
- ((E_getop(b)) == E_INSERT) &&
- ((E_getl1(b))==(E_getl1(a))))
- {
- type = _O_CHA;
- }
- else
- {
- type = _O_DEL;
- }
- /*
- ** set up start and length information for
- ** first file
- */
- t_end1 = E_getl1(a);
- /*
- ** move pointer to beginning of insertion
- */
- ep = b;
- /*
- ** if we are showing only a deletion,
- ** then we're all done, so skip ahead
- */
- if (_O_DEL == type)
- {
- t_beg2 = E_getl2(a);
- t_end2 = -1; /* dummy number, won't
- ever be printed */
-
- goto skipit;
- }
- }
- t_beg2 = E_getl2(ep);
- t_end2 = t_beg2-1;
- /*
- ** now run down the list lookingfor the
- ** end of this insertion and keep count
- ** of the number of times we step along
- */
- do {
- t_end2++;
- ep = E_getnext(ep);
- } while ((ep != E_NULL) && ((E_getop(ep)) == E_INSERT) &&
- ((E_getl1(ep)) == (E_getl1(b))));
-
- skipit:;
- if (flags & U_TOKENS)
- {
- /*
- ** if we are dealing with tokens individually,
- ** then just print then set printing so
- */
- first1 = t_beg1;
- last1 = t_end1;
- first2 = t_beg2;
- last2 = t_end2;
- }
- else
- {
- /*
- ** we are printing differences in terms of lines
- ** so find the beginning and ending lines of the
- ** changes and print header in those terms
- */
- if ( t_beg1 >= 0)
- first1 = K_getline(K_get_token(0,t_beg1));
- else
- first1 = t_beg1;
-
- if ( t_end1 >= 0)
- last1 = K_getline(K_get_token(0,t_end1));
- else
- last1 = t_end1;
-
- if ( t_beg2 >= 0)
- first2 = K_getline(K_get_token(1,t_beg2));
- else
- first2 = t_beg2;
-
- if ( t_end2 >= 0)
- last2 = K_getline(K_get_token(1,t_end2));
- else
- last2 = t_end2;
-
- }
- /*
- ** print the header for this difference
- */
- (void) printf("%d",_O_con_line(first1,flags,0));
- switch (type)
- {
- case _O_APP :
- (void) printf("a%d",_O_con_line(first2,flags,1));
- if (last2 > first2)
- {
- (void) printf(",%d",_O_con_line(last2,flags,1));
- }
- (void) printf("\n");
- break;
- case _O_DEL :
- if (last1 > first1)
- {
- (void) printf(",%d",_O_con_line(last1,flags,0));
- }
- (void) printf("d%d\n",_O_con_line(first2,flags,1));
- break;
- case _O_CHA :
- if (last1 > first1)
- {
- (void) printf(",%d",_O_con_line(last1,flags,0));
- }
- (void) printf("c%d",_O_con_line(first2,flags,1));
- if (last2 > first2)
- {
- (void) printf(",%d",_O_con_line(last2,flags,1));
- }
- (void) printf("\n");
- break;
- default:
- Z_fatal("type in O_output wasn't set\n");
- }
- if (_O_DEL == type || _O_CHA == type)
- {
- if (flags & U_TOKENS)
- {
- int cnt;
- for(cnt=first1;cnt <= last1; cnt++)
- {
- (void) printf("< %s",
- _O_get_text(0,cnt,flags));
- }
- }
- else
- {
- _O_do_lines(t_beg1,t_end1,0);
- }
- }
- if (_O_CHA == type)
- {
- (void) printf("---\n");
- }
- if (_O_APP == type || _O_CHA == type)
- {
- if (flags & U_TOKENS)
- {
- int cnt;
- for(cnt=first2;cnt <= last2; cnt++)
- {
- (void) printf("> %s",
- _O_get_text(1,cnt,flags));
- }
- }
- else
- {
- _O_do_lines(t_beg2,t_end2,1);
- }
- }
- }
- O_cleanup();
- return;
- }
-