home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 211.lha / Spiff / output.c.orig < prev    next >
Text File  |  1996-02-14  |  11KB  |  559 lines

  1. /*                        Copyright (c) 1988 Bellcore
  2. **                            All Rights Reserved
  3. **       Permission is granted to copy or use this program, EXCEPT that it
  4. **       may not be sold for profit, the copyright notice must be reproduced
  5. **       on copies, and credit should be given to Bellcore where it is due.
  6. **       BELLCORE MAKES NO WARRANTY AND ACCEPTS NO LIABILITY FOR THIS PROGRAM.
  7. */
  8.  
  9.  
  10. #ifndef lint
  11. static char rcsid[]= "$Header: output.c,v 1.1 88/09/15 11:33:52 daniel Rel $";
  12. #endif
  13.  
  14. #include <stdio.h>
  15.  
  16. #ifdef M_TERMINFO
  17. #include <curses.h>
  18. #include <term.h>
  19. #endif
  20.  
  21. #ifdef M_TERMCAP
  22. #ifdef XENIX
  23. #include <tcap.h>
  24. #endif
  25. #endif
  26.  
  27. #include "misc.h"
  28. #include "flagdefs.h"
  29. #include "edit.h"
  30. #include "line.h"
  31. #include "token.h"
  32.  
  33. static int _O_need_init = 1;
  34. static int _O_st_ok = 0;
  35. static int _O_doing_ul = 0;
  36. static    char *_O_st_tmp;
  37. #ifdef M_TERMCAP
  38. static    char _O_startline[Z_WORDLEN];
  39. static    char _O_endline[Z_WORDLEN];
  40. #endif
  41.  
  42. static void
  43. _O_st_init()
  44. {
  45.     char termn[Z_WORDLEN];
  46. #ifdef M_TERMCAP
  47.     static    char entry[1024];
  48. #endif
  49.  
  50.     /*
  51.     **    see if standard out is a terminal
  52.     */
  53.     if (!isatty(1))
  54.     {
  55.         _O_need_init = 0;
  56.         _O_st_ok = 0;
  57.         return;
  58.     }
  59.  
  60.     if (NULL == (_O_st_tmp = (char*) getenv("TERM")))
  61.     {
  62.         Z_complain("can't find TERM entry in environment\n");
  63.         _O_need_init = 0;
  64.         _O_st_ok = 0;
  65.         return;
  66.     }
  67.     (void) strcpy(termn,_O_st_tmp);
  68.  
  69. #ifdef M_TERMCAP
  70.     if (1 != tgetent(entry,termn))
  71.     {
  72.         Z_complain("can't get TERMCAP info for terminal\n");
  73.         _O_need_init = 0;
  74.         _O_st_ok = 0;
  75.         return;
  76.     }
  77.  
  78.     _O_st_tmp = _O_startline;
  79.     _O_startline[0] = '\0';
  80.     tgetstr("so",&_O_st_tmp);
  81.  
  82.     _O_st_tmp = _O_endline;
  83.     _O_endline[0] = '\0';
  84.     tgetstr("se",&_O_st_tmp);
  85.  
  86.     _O_st_ok = (strlen(_O_startline) > 0) && (strlen(_O_endline) > 0);
  87. #endif
  88.  
  89. #ifdef M_TERMINFO
  90.     setupterm(termn,1,&_O_st_ok);
  91. #endif
  92.     _O_need_init = 0;
  93. }
  94.  
  95. void
  96. O_cleanup()
  97. {
  98.     /*
  99.     **    this probably isn't necessary, but in the
  100.     **    name of compeleteness.
  101.     */
  102. #ifdef M_TERMINFO
  103.     resetterm();
  104. #endif
  105. }
  106.  
  107. static void
  108. _O_start_standout()
  109. {
  110.     if (_O_need_init)
  111.     {
  112.         _O_st_init();
  113.     }
  114.     if (_O_st_ok)
  115.     {
  116. #ifdef M_TERMCAP
  117.         (void) printf("%s",_O_startline);
  118. #endif 
  119. #ifdef M_TERMINFO
  120.         vidattr(A_STANDOUT);
  121. #endif
  122.     }
  123.     else
  124.     {
  125.         _O_doing_ul = 1;
  126.     }
  127. }
  128.  
  129. static void
  130. _O_end_standout()
  131. {
  132.     if (_O_need_init)
  133.     {
  134.         _O_st_init();
  135.     }
  136.     if (_O_st_ok)
  137.     {
  138. #ifdef M_TERMCAP
  139.         (void) printf("%s",_O_endline);
  140. #endif 
  141. #ifdef M_TERMINFO
  142.         vidattr(0);
  143. #endif
  144.     }
  145.     else
  146.     {
  147.         _O_doing_ul = 0;
  148.     }
  149. }
  150.  
  151. static void
  152. _O_pchars(line,start,end)
  153. char *line;
  154. int start,end;
  155. {
  156.     int cnt;
  157.  
  158.     for(cnt=start;cnt < end; cnt++)
  159.     {
  160.         if (_O_doing_ul)
  161.         {
  162.             (void) putchar('_');
  163.             (void) putchar('\b');
  164.         }
  165.         (void) putchar(line[cnt]);
  166.     }
  167. }
  168.  
  169.  
  170. /*
  171. **    convert a 0 origin token number to a 1 orgin token
  172. **        number or 1 origin line number as appropriate
  173. */
  174. static
  175. _O_con_line(numb,flags,filenum)
  176. int numb, flags,filenum;
  177. {
  178.     if (flags & U_TOKENS)
  179.     {
  180.         return(numb+1);
  181.     }
  182.     else
  183.     {
  184.         /*
  185.         **     check to make sure that this is a real
  186.         **    line number. if not, then return 0
  187.         **    on rare occasions, (i.e. insertion/deletion
  188.         **    of the first token in a file) we'll get
  189.         **    line numbers of -1.  the usual look-up technique
  190.         **    won't work since we have no lines before than 0.
  191.         */
  192.         if (numb < 0)
  193.             return(0);
  194.         /*
  195.         **    look up the line number the token and then
  196.         **    add 1 to make line number 1 origin
  197.         */
  198.         return(L_tl2cl(filenum,numb)+1);
  199.     }
  200. }
  201.  
  202. static char *
  203. _O_convert(ptr)
  204. char *ptr;
  205. {
  206.     static char spacetext[Z_WORDLEN];
  207.  
  208.     if (1 == strlen(ptr))
  209.     {
  210.         switch (*ptr)
  211.         {
  212.             default:
  213.                 break;
  214.             case '\n' :
  215.                 (void) strcpy(spacetext,"<NEWLINE>");
  216.                 return(spacetext);
  217.             case '\t' :
  218.                 (void) strcpy(spacetext,"<TAB>");
  219.                 return(spacetext);
  220.             case ' ' :
  221.                 (void) strcpy(spacetext,"<SPACE>");
  222.                 return(spacetext);
  223.         }
  224.                 
  225.     }
  226.     return(ptr);
  227. }
  228.  
  229. static char*
  230. _O_get_text(file,index,flags)
  231. int file,index,flags;
  232. {
  233.     static char buf[Z_LINELEN*2];    /* leave lots of room for both
  234.                         the token text and the
  235.                         chatter that preceeds it */
  236.     char *text;
  237.     K_token tmp;
  238.  
  239.     if (flags & U_TOKENS)
  240.     {
  241.         tmp = K_gettoken(file,index);
  242.         text = _O_convert(K_gettext(tmp));
  243.         (void) sprintf(buf,"%s -- line %d, character %d\n",
  244.                 text,
  245.                 /*
  246.                 **    add 1 to make output start at line 1 
  247.                 **    and character numbers start at 1
  248.                 */
  249.                 L_tl2cl(file,K_getline(tmp))+1,
  250.                 K_getpos(tmp)+1);
  251.         return(buf);
  252.     }
  253.     else
  254.     {
  255.         return(L_gettline(file,index));
  256.     }
  257. }
  258. #define    _O_APP        1
  259. #define _O_DEL        2
  260. #define _O_CHA        3
  261. #define _O_TYPE_E    4
  262.  
  263. static void
  264. _O_do_lines(start,end,file)
  265. int start,end,file;
  266. {
  267.     int cnt;
  268.     int lastline = -1;
  269.     int nextline;
  270.     K_token nexttoken;
  271.     for (cnt=start;cnt <= end; cnt++)
  272.     {
  273.         nexttoken = K_get_token(file,cnt);
  274.         nextline = K_getline(nexttoken);
  275.         if (lastline != nextline)
  276.         {
  277.             int lastone,lastchar;
  278.             K_token lasttok;
  279.             char linetext[Z_LINELEN+1];    /* leave room for
  280.                                terminator */
  281.             if (0 == file)
  282.             {
  283.                 (void) printf("< ");
  284.             }
  285.             else
  286.             {
  287.                 (void) printf("> ");
  288.             }
  289.  
  290.             /*
  291.             **    put loop here if you want to print
  292.             **    out any intervening lines that don't
  293.             **    have any tokens on them
  294.             */
  295.  
  296.             /*
  297.             **    following line is necessary because
  298.             **    L_gettline is a macro, and can't be passed
  299.             */
  300.             (void) strcpy(linetext,L_gettline(file,nextline));
  301.             _O_pchars(linetext,0,K_getpos(nexttoken));
  302.             _O_start_standout();
  303.             /*
  304.             **     look for last token on this line to be
  305.             **    highlighted
  306.             */
  307.             for ( lastone=cnt,lasttok = K_get_token(file,lastone);
  308.                   (lastone<=end)&&(nextline == K_getline(lasttok));
  309.                 lastone++,lasttok = K_get_token(file,lastone))
  310.             {
  311.             }
  312.             lastone--;
  313.             lasttok = K_get_token(file,lastone);
  314.             lastchar = K_getpos(lasttok)
  315.                     + strlen(K_gettext(lasttok));
  316.             _O_pchars(linetext,K_getpos(nexttoken),lastchar);
  317.             _O_end_standout();
  318.             _O_pchars(linetext,lastchar,strlen(linetext));
  319.             
  320.             lastline = nextline;
  321.         }
  322.     }
  323. }
  324.  
  325. void
  326. O_output(start,flags)
  327. E_edit start;
  328. int flags;
  329. {
  330.     int type = _O_TYPE_E;    /* initialize to error state
  331.                 ** this is to make sure that type is set
  332.                 ** somewhere
  333.                 */
  334.     int t_beg1, t_beg2, t_end1, t_end2; /* token numbers */
  335.     int first1, last1, first2, last2;
  336.  
  337.     E_edit ep, behind, ahead, a, b;
  338.  
  339.     /*
  340.     **    reverse the list of edits
  341.     */
  342.     ahead = start;
  343.     ep = E_NULL;
  344.     while (ahead != E_NULL) {
  345.         /*
  346.         **    set token numbers intentionally out of range
  347.         **        as boilerplate
  348.         */
  349.         t_beg1 = t_beg2 = t_end1 = t_end2 = -1;
  350.         /*
  351.         **    edit script is 1 origin, all of
  352.         **     our routines are zero origin
  353.         */
  354.         E_setl1(ahead,(E_getl1(ahead))-1);
  355.         E_setl2(ahead,(E_getl2(ahead))-1);
  356.  
  357.         behind = ep;
  358.         ep = ahead;
  359.         ahead = E_getnext(ahead);
  360.         E_setnext(ep,behind);
  361.     }
  362.  
  363.     /*
  364.     **    now run down the list and collect the following information
  365.     **    type of change (_O_APP, _O_DEL or _O_CHA)
  366.     **    start and length for each file
  367.     */
  368.     while (ep != E_NULL)
  369.     {
  370.         b = ep;
  371.         /*
  372.         **    operation always start here
  373.         */
  374.         t_beg1 = E_getl1(ep);
  375.         /*
  376.         **    any deletions will appear before any insertions,
  377.         **    so, if the first edit is an E_INSERT, then this
  378.         **    this is an _O_APP
  379.         */
  380.         if (E_getop(ep) == E_INSERT)
  381.             type = _O_APP;
  382.         else {
  383.             /*
  384.             **    run down the list looking for the edit
  385.             **    that is not part of the current deletion
  386.             */    
  387.             do {
  388.                 a = b;
  389.                 b = E_getnext(b);
  390.             } while ((b != E_NULL) &&
  391.                  (E_getop(b) == E_DELETE) &&
  392.                  ((E_getl1(b)) == ((E_getl1(a))+1)));
  393.             /*
  394.             **    if we have an insertion at the same place
  395.             **    as the deletion we just scanned, then
  396.             **    this is a change
  397.             */
  398.             if ((b != E_NULL) &&
  399.                 ((E_getop(b)) == E_INSERT) &&
  400.                 ((E_getl1(b))==(E_getl1(a))))
  401.             {
  402.                 type = _O_CHA;
  403.             }
  404.             else
  405.             {
  406.                 type = _O_DEL;
  407.             }
  408.             /*
  409.             **    set up start and length information for
  410.             **    first file
  411.             */
  412.             t_end1 = E_getl1(a);
  413.             /*
  414.             **    move pointer to beginning of insertion
  415.             */
  416.             ep = b;
  417.             /*
  418.             **    if we are showing only a deletion,
  419.             **    then we're all done, so skip ahead
  420.             */ 
  421.             if (_O_DEL == type)
  422.             {
  423.                 t_beg2 = E_getl2(a);
  424.                 t_end2 = -1;    /* dummy number, won't
  425.                             ever be printed */
  426.                            
  427.                 goto skipit;
  428.             }
  429.         }
  430.         t_beg2 = E_getl2(ep);
  431.         t_end2 = t_beg2-1;
  432.         /*
  433.         **    now run down the list lookingfor the
  434.         **    end of this insertion and keep count
  435.         **    of the number of times we step along
  436.         */
  437.         do {
  438.             t_end2++;
  439.             ep = E_getnext(ep);
  440.         } while ((ep != E_NULL) && ((E_getop(ep)) == E_INSERT) &&
  441.                     ((E_getl1(ep)) == (E_getl1(b))));
  442.  
  443. skipit:;
  444.         if (flags & U_TOKENS)
  445.         {
  446.             /*
  447.             **    if we are dealing with tokens individually,
  448.             **    then just print then set printing so
  449.             */
  450.                 first1 = t_beg1;
  451.                 last1 = t_end1;
  452.                 first2 = t_beg2;
  453.                 last2 = t_end2;
  454.         }
  455.         else
  456.         {
  457.             /*
  458.             **    we are printing differences in terms of lines
  459.             **    so find the beginning and ending lines of the
  460.             **    changes and print header in those terms
  461.             */
  462.             if ( t_beg1 >= 0)
  463.                 first1 = K_getline(K_get_token(0,t_beg1));
  464.             else
  465.                 first1 = t_beg1;
  466.  
  467.             if ( t_end1 >= 0)
  468.                 last1 = K_getline(K_get_token(0,t_end1));
  469.             else
  470.                 last1 = t_end1;
  471.  
  472.             if ( t_beg2 >= 0)
  473.                 first2 = K_getline(K_get_token(1,t_beg2));
  474.             else
  475.                 first2 = t_beg2;
  476.  
  477.             if ( t_end2 >= 0)
  478.                 last2 = K_getline(K_get_token(1,t_end2));
  479.             else
  480.                 last2 = t_end2;
  481.  
  482.         }
  483.         /*
  484.         **    print the header for this difference
  485.         */
  486.         (void) printf("%d",_O_con_line(first1,flags,0));
  487.         switch (type)
  488.         {
  489.         case _O_APP :
  490.             (void) printf("a%d",_O_con_line(first2,flags,1));
  491.             if (last2 > first2)
  492.             {
  493.                 (void) printf(",%d",_O_con_line(last2,flags,1));
  494.             }
  495.             (void) printf("\n");
  496.             break;
  497.         case _O_DEL :
  498.             if (last1 > first1)
  499.             {
  500.                 (void) printf(",%d",_O_con_line(last1,flags,0));
  501.             }
  502.             (void) printf("d%d\n",_O_con_line(first2,flags,1));
  503.             break;
  504.         case _O_CHA :
  505.             if (last1 > first1)
  506.             {
  507.                 (void) printf(",%d",_O_con_line(last1,flags,0));
  508.             }
  509.             (void) printf("c%d",_O_con_line(first2,flags,1));
  510.             if (last2 > first2)
  511.             {
  512.                 (void) printf(",%d",_O_con_line(last2,flags,1));
  513.             }
  514.             (void) printf("\n");
  515.             break;
  516.         default:
  517.             Z_fatal("type in O_output wasn't set\n");
  518.         }
  519.         if (_O_DEL == type || _O_CHA == type)
  520.         {
  521.             if (flags & U_TOKENS)
  522.             {
  523.                 int cnt;
  524.                 for(cnt=first1;cnt <= last1; cnt++)
  525.                 {
  526.         (void) printf("< %s",
  527.                             _O_get_text(0,cnt,flags));
  528.                 }
  529.             }
  530.             else
  531.             {    
  532.                 _O_do_lines(t_beg1,t_end1,0);
  533.             }
  534.         }
  535.         if (_O_CHA == type)
  536.         {
  537.             (void) printf("---\n");
  538.         }
  539.         if (_O_APP == type || _O_CHA == type)
  540.         {
  541.             if (flags & U_TOKENS)
  542.             {
  543.                 int cnt;
  544.                 for(cnt=first2;cnt <= last2; cnt++)
  545.                 {
  546.                     (void) printf("> %s",
  547.                         _O_get_text(1,cnt,flags));
  548.                 }
  549.             }
  550.             else
  551.             {
  552.                 _O_do_lines(t_beg2,t_end2,1);
  553.             }
  554.         }
  555.     }
  556.     O_cleanup();
  557.     return;
  558. }
  559.