home *** CD-ROM | disk | FTP | other *** search
/ High Voltage Shareware / high1.zip / high1 / DIR8 / TDE32.ZIP / DIFF.C < prev    next >
C/C++ Source or Header  |  1993-11-13  |  24KB  |  750 lines

  1. /*
  2.  * Being that the windows in TDE are numbered and lettered, we can easily
  3.  * prompt for windows to diff.  Might as well do a few standard diff
  4.  * options:  ignore leading space, ignore all space, ignore blank lines,
  5.  * ignore end-of-line, and Ignore/Match case.  Once the diff is defined,
  6.  * just press one key to find the next diff.  Any two visible windows may
  7.  * be diffed, which is really nice for comparing similar functions or
  8.  * data in seperate areas of a file.
  9.  *
  10.  *
  11.  * New editor name:  TDE, the Thomson-Davis Editor.
  12.  * Author:           Frank Davis
  13.  * Date:             June 5, 1991, version 1.0
  14.  * Date:             July 29, 1991, version 1.1
  15.  * Date:             October 5, 1991, version 1.2
  16.  * Date:             January 20, 1992, version 1.3
  17.  * Date:             February 17, 1992, version 1.4
  18.  * Date:             April 1, 1992, version 1.5
  19.  * Date:             June 5, 1992, version 2.0
  20.  * Date:             October 31, 1992, version 2.1
  21.  * Date:             April 1, 1993, version 2.2
  22.  * Date:             June 5, 1993, version 3.0
  23.  * Date:             August 29, 1993, version 3.1
  24.  * Date:             November 13, 1993, version 3.2
  25.  *
  26.  * This code is released into the public domain, Frank Davis.
  27.  * You may distribute it freely.
  28.  */
  29.  
  30. #include "tdestr.h"
  31. #include "common.h"
  32. #include "define.h"
  33. #include "tdefunc.h"
  34.  
  35.  
  36. /*
  37.  * Name:    define_diff
  38.  * Purpose: get info needed to initialize diff
  39.  * Date:    October 31, 1992
  40.  * Passed:  window:  pointer to current window
  41.  * Notes:   allow the user to start the diff at the beginning of the
  42.  *            file or at the current cursor location.  once the diff
  43.  *            has been defined, the user may press one key to diff again.
  44.  *          user may diff any two visible windows on the screen.
  45.  */
  46. int  define_diff( TDE_WIN *window )
  47. {
  48. int  rc;
  49. int  num1;
  50. int  let1;
  51. int  num2;
  52. int  let2;
  53. int  start;
  54. char temp[MAX_COLS+2];
  55. char answer[MAX_COLS+2];
  56. #if defined( __UNIX__ )
  57.  chtype display_buff[MAX_COLS+2];       /* chtype is defined in curses.h */
  58. #else
  59.  char display_buff[(MAX_COLS+2)*2];
  60. #endif
  61.  
  62.    rc = OK;
  63.  
  64.    /*
  65.     * get window number and letter of the first diff window.  then,
  66.     *   verify that window - does it exit? is it visible?
  67.     */
  68.    if (rc == OK) {
  69.       *temp = '\0';
  70.       rc = get_name( diff_prompt1, window->bottom_line, temp,
  71.                      g_display.message_color );
  72.    }
  73.  
  74.    if (rc == OK) {
  75.       rc = verify_number( temp, &num1 );
  76.       if (rc == OK)
  77.          rc = verify_letter( temp, &let1, &diff.w1 );
  78.    }
  79.  
  80.    if (rc == ERROR) {
  81.       combine_strings( answer, diff_prompt6a, temp, diff_prompt6b );
  82.       error( WARNING, window->bottom_line, answer );
  83.       return( ERROR );
  84.    }
  85.  
  86.    /*
  87.     * get and verify the next window number and letter to diff.
  88.     */
  89.    *temp = '\0';
  90.    rc = get_name( diff_prompt2, window->bottom_line, temp,
  91.                   g_display.message_color );
  92.    if (rc == OK) {
  93.       rc = verify_number( temp, &num2 );
  94.       if (rc == OK)
  95.          rc = verify_letter( temp, &let2, &diff.w2 );
  96.    }
  97.    if (rc == ERROR) {
  98.       combine_strings( answer, diff_prompt6a, temp, diff_prompt6b );
  99.       error( WARNING, window->bottom_line, answer );
  100.       return( ERROR );
  101.    }
  102.  
  103.    /*
  104.     * are leading spaces significant?
  105.     */
  106.    save_screen_line( 0, window->bottom_line, display_buff );
  107.    set_prompt( diff_prompt7a, window->bottom_line );
  108.    start = get_yn( );
  109.    restore_screen_line( 0, window->bottom_line, display_buff );
  110.    if (start != ERROR)
  111.       diff.leading =  start == A_YES ?  TRUE  :  FALSE;
  112.    else
  113.       return( ERROR );
  114.  
  115.    /*
  116.     * are all spaces significant?
  117.     */
  118.    save_screen_line( 0, window->bottom_line, display_buff );
  119.    set_prompt( diff_prompt7b, window->bottom_line );
  120.    start = get_yn( );
  121.    restore_screen_line( 0, window->bottom_line, display_buff );
  122.    if (start != ERROR) {
  123.       if (start == A_YES)
  124.          diff.leading = diff.all_space = TRUE;
  125.       else
  126.          diff.all_space = FALSE;
  127.    } else
  128.       return( ERROR );
  129.  
  130.    /*
  131.     * are blank lines significant?
  132.     */
  133.    save_screen_line( 0, window->bottom_line, display_buff );
  134.    set_prompt( diff_prompt7c, window->bottom_line );
  135.    start = get_yn( );
  136.    restore_screen_line( 0, window->bottom_line, display_buff );
  137.    if (start != ERROR)
  138.       diff.blank_lines =  start == A_YES  ?  TRUE : FALSE;
  139.    else
  140.       return( ERROR );
  141.  
  142.    /*
  143.     * is end of line significant?
  144.     */
  145.    save_screen_line( 0, window->bottom_line, display_buff );
  146.    set_prompt( diff_prompt7d, window->bottom_line );
  147.    start = get_yn( );
  148.    restore_screen_line( 0, window->bottom_line, display_buff );
  149.    if (start != ERROR)
  150.       diff.ignore_eol =  start == A_YES  ?  TRUE : FALSE;
  151.    else
  152.       return( ERROR );
  153.  
  154.    /*
  155.     * now, find out were to start the diff -- beginning of file or
  156.     *   current cursor location.
  157.     */
  158.    save_screen_line( 0, window->bottom_line, display_buff );
  159.    set_prompt( diff_prompt3, window->bottom_line );
  160.    start = get_bc( );
  161.    restore_screen_line( 0, window->bottom_line, display_buff );
  162.  
  163.    if (start != ERROR) {
  164.       entab_linebuff( );
  165.       if (un_copy_line( window->ll, window, TRUE ) == ERROR)
  166.          return( ERROR );
  167.  
  168.       /*
  169.        * if everything is everything, initialize the diff pointers.
  170.        */
  171.       diff.defined = TRUE;
  172.       if (start == BEGINNING) {
  173.          diff.d1 = diff.w1->file_info->line_list;
  174.          diff.d2 = diff.w2->file_info->line_list;
  175.          diff.rline1 = 1L;
  176.          diff.rline2 = 1L;
  177.          diff.bin_offset1 = 0;
  178.          diff.bin_offset2 = 0;
  179.          rc = differ( 0, 0, window->bottom_line );
  180.       } else {
  181.          diff.d1 = diff.w1->ll;
  182.          diff.d2 = diff.w2->ll;
  183.          diff.rline1 = diff.w1->rline;
  184.          diff.rline2 = diff.w2->rline;
  185.          diff.bin_offset1 = diff.w1->bin_offset;
  186.          diff.bin_offset2 = diff.w2->bin_offset;
  187.          rc = differ( diff.w1->rcol, diff.w2->rcol, window->bottom_line );
  188.       }
  189.    }
  190.    return( rc );
  191. }
  192.  
  193.  
  194. /*
  195.  * Name:    repeat_diff
  196.  * Purpose: compare two cursor positions
  197.  * Date:    October 31, 1992
  198.  * Passed:  window:  pointer to current window
  199.  * Notes:   user may press this key at any time once the diff has been
  200.  *            defined.
  201.  */
  202. int  repeat_diff( TDE_WIN *window )
  203. {
  204. register int rc = ERROR;
  205.  
  206.    if (diff.defined) {
  207.       entab_linebuff( );
  208.       if (un_copy_line( window->ll, window, TRUE ) == ERROR)
  209.          return( ERROR );
  210.  
  211.       /*
  212.        * initialize the diff pointers.
  213.        */
  214.       diff.d1 = diff.w1->ll;
  215.       diff.d2 = diff.w2->ll;
  216.       diff.rline1 = diff.w1->rline;
  217.       diff.rline2 = diff.w2->rline;
  218.       diff.bin_offset1 = diff.w1->bin_offset;
  219.       diff.bin_offset2 = diff.w2->bin_offset;
  220.       rc = differ( diff.w1->rcol, diff.w2->rcol, window->bottom_line );
  221.    } else
  222.       error( WARNING, window->bottom_line, diff_prompt5 );
  223.    return( rc );
  224. }
  225.  
  226.  
  227. /*
  228.  * Name:    differ
  229.  * Purpose: diff text pointers
  230.  * Date:    October 31, 1992
  231.  * Passed:  initial_rcol1:  beginning column to begin diff in window1
  232.  *          initial_rcol2:  beginning column to begin diff in window2
  233.  *          bottom:         line to display diagnostics
  234.  * Notes:   a straight diff on text pointers is simple; however, diffing
  235.  *            with leading spaces and tabs is kinda messy.  let's do the
  236.  *            messy diff.
  237.  */
  238. int  differ( int initial_rcol1, int initial_rcol2, int bottom )
  239. {
  240. int  rcol1;             /* virtual real column on diff window 1 */
  241. int  rcol2;             /* virtual real column on diff window 2 */
  242. int  r1;                /* real real column rcol1 - needed for tabs */
  243. int  r2;                /* real real column rcol2 - needed for tabs */
  244. char c1;                /* character under r1 */
  245. char c2;                /* character under r2 */
  246. int  leading1;          /* adjustment for leading space in window 1 */
  247. int  leading2;          /* adjustment for leading space in window 2 */
  248. int  len1;              /* length of diff1 line */
  249. int  len2;              /* length of diff2 line */
  250. line_list_ptr node1;    /* scratch node in window 1 */
  251. line_list_ptr node2;    /* scratch node in window 2 */
  252. text_ptr diff1;         /* scratch text ptr in window 1 */
  253. text_ptr diff2;         /* scratch text ptr in window 2 */
  254. long rline1;            /* real line number of diff pointer 1 */
  255. long rline2;            /* real line number of diff pointer 2 */
  256. long bin_offset1;       /* binary offset of diff pointer 1 */
  257. long bin_offset2;       /* binary offset of diff pointer 2 */
  258. int  len;               /* line length variable */
  259. register int tabs;      /* local variable for mode.inflate_tabs, T or F */
  260. #if defined( __UNIX__ )
  261.  chtype display_buff[MAX_COLS+2];       /* chtype is defined in curses.h */
  262. #else
  263.  char display_buff[(MAX_COLS+2)*2];
  264. #endif
  265.  
  266.    /*
  267.     * initialize the text pointers and the initial column.  skip any
  268.     *  initial blank lines.
  269.     */
  270.    rline1 = diff.rline1;
  271.    rline2 = diff.rline2;
  272.    node1 = diff.d1;
  273.    node2 = diff.d2;
  274.    bin_offset1 = diff.bin_offset1;
  275.    bin_offset2 = diff.bin_offset2;
  276.    tabs  = mode.inflate_tabs;
  277.    if (diff.blank_lines) {
  278.       while (node1->len != EOF  && is_line_blank( node1->line, node1->len )) {
  279.          bin_offset1 += node1->len;
  280.          node1 = node1->next;
  281.          ++rline1;
  282.          initial_rcol1 = 0;
  283.       }
  284.       while (node2->len != EOF  && is_line_blank( node2->line , node2->len)) {
  285.          bin_offset2 += node2->len;
  286.          node2 = node2->next;
  287.          ++rline2;
  288.          initial_rcol2 = 0;
  289.       }
  290.    }
  291.  
  292.    /*
  293.     * if everything is everything, initialize the diff variables and diff.
  294.     */
  295.    if (node1->len != EOF  &&  node2->len != EOF) {
  296.       diff1 = node1->line;
  297.       diff2 = node2->line;
  298.       rcol1 = initial_rcol1;
  299.       rcol2 = initial_rcol2;
  300.       len1  = node1->len;
  301.       len2  = node2->len;
  302.  
  303.       assert( rcol1 >= 0 );
  304.       assert( rcol1 < MAX_LINE_LENGTH );
  305.       assert( rcol2 >= 0 );
  306.       assert( rcol2 < MAX_LINE_LENGTH );
  307.       assert( len1 >= 0 );
  308.       assert( len1 < MAX_LINE_LENGTH );
  309.       assert( len2 >= 0 );
  310.       assert( len2 < MAX_LINE_LENGTH );
  311.  
  312.       /*
  313.        * if cursors are past EOL, move them back to EOL.
  314.        */
  315.       len = find_end( diff1, len1 );
  316.       if (rcol1 > len)
  317.          rcol1 = len;
  318.       len = find_end( diff2, len2 );
  319.       if (rcol2 > len)
  320.          rcol2 = len;
  321.  
  322.       /*
  323.        * if skip leading space, make sure our cursors start on first non-space.
  324.        */
  325.       if (diff.leading) {
  326.          leading1 = skip_leading_space( diff1, len1 );
  327.          leading2 = skip_leading_space( diff2, len2 );
  328.          if (tabs) {
  329.             leading1 = detab_adjust_rcol( diff1, leading1 );
  330.             leading2 = detab_adjust_rcol( diff2, leading2 );
  331.          }
  332.          if (rcol1 < leading1)
  333.             rcol1 = leading1;
  334.          if (rcol2 < leading2)
  335.             rcol2 = leading2;
  336.       }
  337.  
  338.       /*
  339.        * we now have a valid rcol for the diff start, we may need to adjust
  340.        *   for tabs, though.
  341.        */
  342.       assert( rcol1 >= 0 );
  343.       assert( rcol1 < MAX_LINE_LENGTH );
  344.       assert( rcol2 >= 0 );
  345.       assert( rcol2 < MAX_LINE_LENGTH );
  346.  
  347.       r1 =  tabs ? entab_adjust_rcol( diff1, len1, rcol1 ) : rcol1;
  348.       r2 =  tabs ? entab_adjust_rcol( diff2, len2, rcol2 ) : rcol2;
  349.  
  350.       assert( r1 >= 0 );
  351.       assert( r1 <= len1 );
  352.       assert( r2 >= 0 );
  353.       assert( r2 <= len2 );
  354.       assert( r1 <= rcol1 );
  355.       assert( r2 <= rcol2 );
  356.  
  357.       s_output( diff_message, g_display.mode_line, 67, g_display.diag_color );
  358.       while (node1->len != EOF  &&  node2->len != EOF  &&
  359.                          !g_status.control_break) {
  360.  
  361.          /*
  362.           * look at each character in each diff window
  363.           */
  364.          c1 = (char)(r1 < len1 ? *(diff1 + r1)  : 0);
  365.          c2 = (char)(r2 < len2 ? *(diff2 + r2)  : 0);
  366.  
  367.          /*
  368.           *  tabs == space
  369.           */
  370.          if (tabs) {
  371.             if (c1 == '\t')
  372.                c1 = ' ';
  373.             if (c2 == '\t')
  374.                c2 = ' ';
  375.          }
  376.  
  377.          /*
  378.           * skip spaces, if needed
  379.           */
  380.          if (diff.all_space) {
  381.             while (c1 == ' '  &&  r1 < len1) {
  382.                ++rcol1;
  383.                r1 = tabs ? entab_adjust_rcol( diff1, len1, rcol1 ) : rcol1;
  384.                c1 =  (char)(r1 < len1  ?  *(diff1 + r1) :  0);
  385.                if (c1 == '\t'  &&  tabs)
  386.                   c1 = ' ';
  387.             }
  388.             while (c2 == ' '  &&  r2 < len2) {
  389.                ++rcol2;
  390.                r2 = tabs ? entab_adjust_rcol( diff2, len2, rcol2 ) : rcol2;
  391.                c2 =  (char)(r2 < len2  ? *(diff2 + r2) : 0);
  392.                if (c2 == '\t'  &&  tabs)
  393.                   c2 = ' ';
  394.             }
  395.          }
  396.  
  397.          /*
  398.           * if one of the node pointers has come to EOL, move to next
  399.           *   diff line.
  400.           */
  401.          if (diff.ignore_eol) {
  402.             if (r1 >= len1) {
  403.                node1 = skip_eol( node1, &r1, &rcol1, &rline1, &bin_offset1 );
  404.                len1  = node1->len;
  405.                if (len1 != EOF) {
  406.                   diff1 = node1->line;
  407.                   c1 =  (char)(r1 < len1  ?  *(diff1 + r1) : 0);
  408.                   if (c1 == '\t'  &&  tabs)
  409.                      c1 = ' ';
  410.                }
  411.             }
  412.             if (r2 >= len2) {
  413.                node2 = skip_eol( node2, &r2, &rcol2, &rline2, &bin_offset2 );
  414.                len2  = node2->len;
  415.                if (len2 != EOF) {
  416.                   diff2 = node2->line;
  417.                   c2 =  (char)(r2 < len2  ? *(diff2 + r2)  :  0);
  418.                   if (c2 == '\t'  &&  tabs)
  419.                      c2 = ' ';
  420.                }
  421.             }
  422.          }
  423.  
  424.          /*
  425.           * convert the characters to lower case, if needed.
  426.           */
  427.          if (mode.search_case == IGNORE) {
  428.             c1 = (char)tolower( c1 );
  429.             c2 = (char)tolower( c2 );
  430.          }
  431.  
  432.          /*
  433.           * diff each character in the diff lines until we reach EOL
  434.           */
  435.          while (r1 < len1  && r2 < len2) {
  436.             if (c1 == c2) {
  437.                if (diff.all_space) {
  438.                   do {
  439.                      ++rcol1;
  440.                      r1 = tabs ? entab_adjust_rcol( diff1,len1,rcol1 ) : rcol1;
  441.                      c1 =  (char)(r1 < len1  ?  *(diff1 + r1)  :  0);
  442.                      if (c1 == '\t'  &&  tabs)
  443.                         c1 = ' ';
  444.                   } while (c1 == ' '  &&  r1 < len1);
  445.                   do {
  446.                      ++rcol2;
  447.                      r2 = tabs ? entab_adjust_rcol( diff2,len2,rcol2 ) : rcol2;
  448.                      c2 =  (char)(r2 < len2  ?  *(diff2 + r2)  :  0);
  449.                      if (c2 == '\t'  &&  tabs)
  450.                         c2 = ' ';
  451.                   } while (c2 == ' '  &&  r2 < len2);
  452.                } else {
  453.                   ++rcol1;
  454.                   ++rcol2;
  455.                   r1 = tabs ? entab_adjust_rcol( diff1, len1, rcol1 ) : rcol1;
  456.                   r2 = tabs ? entab_adjust_rcol( diff2, len2, rcol2 ) : rcol2;
  457.                   c1 =  (char)(r1 < len1  ?  *(diff1 + r1)  :  0);
  458.                   c2 =  (char)(r2 < len2  ?  *(diff2 + r2)  :  0);
  459.                   if (tabs) {
  460.                      if (c1 == '\t')
  461.                         c1 = ' ';
  462.                      if (c2 == '\t')
  463.                         c2 = ' ';
  464.                   }
  465.                }
  466.                if (diff.ignore_eol) {
  467.                   if (r1 >= len1) {
  468.                      node1 = skip_eol(node1, &r1, &rcol1, &rline1,&bin_offset1);
  469.                      len1  = node1->len;
  470.                      if (len1 != EOF) {
  471.                         diff1 = node1->line;
  472.                         c1 =  (char)(r1 < len1  ?  *(diff1 + r1)  : 0);
  473.                         if (c1 == '\t'  &&  tabs)
  474.                            c1 = ' ';
  475.                      }
  476.                   }
  477.                   if (r2 >= len2) {
  478.                      node2 = skip_eol(node2, &r2, &rcol2, &rline2,&bin_offset2);
  479.                      len2  = node2->len;
  480.                      if (len2 != EOF) {
  481.                         diff2 = node2->line;
  482.                         c2 = (char)(r2 < len2  ? *(diff2 + r2)  :  0);
  483.                         if (c2 == '\t'  &&  tabs)
  484.                            c2 = ' ';
  485.                      }
  486.                   }
  487.                }
  488.                if (mode.search_case == IGNORE) {
  489.                   c1 = (char)tolower( c1 );
  490.                   c2 = (char)tolower( c2 );
  491.                }
  492.             } else {
  493.  
  494.                /*
  495.                 * when we show the diff, use rcol1 and rcol2, as
  496.                 *   find_adjust does not adjust rcol for tabs.
  497.                 */
  498.                update_line( diff.w1 );
  499.                diff.w1->bin_offset = bin_offset1;
  500.                find_adjust( diff.w1, node1, rline1, rcol1 );
  501.                check_virtual_col( diff.w1, rcol1, rcol1 );
  502.                show_diff_window( diff.w1 );
  503.                update_line( diff.w2 );
  504.                diff.w2->bin_offset = bin_offset2;
  505.                bin_offset_adjust( diff.w2, rline2 );
  506.                find_adjust( diff.w2, node2, rline2, rcol2 );
  507.                check_virtual_col( diff.w2, rcol2, rcol2 );
  508.                show_diff_window( diff.w2 );
  509.                s_output( diff_blank, g_display.mode_line, 67,
  510.                          g_display.mode_color );
  511.                return( OK );
  512.             }
  513.          }
  514.  
  515.          /*
  516.           * if we haven't come to the end of a file buffer, check the last
  517.           *   characters.  see if pointers are at EOL.
  518.           */
  519.          if (node1->len != EOF && node2->len != EOF) {
  520.             if (rcol1 != len1  &&  rcol2 != len2) {
  521.                update_line( diff.w1 );
  522.                diff.w1->bin_offset = bin_offset1;
  523.                find_adjust( diff.w1, node1, rline1, rcol1 );
  524.                show_diff_window( diff.w1 );
  525.                update_line( diff.w2 );
  526.                diff.w2->bin_offset = bin_offset2;
  527.                find_adjust( diff.w2, node2, rline2, rcol2 );
  528.                show_diff_window( diff.w2 );
  529.                s_output( diff_blank, g_display.mode_line, 67,
  530.                          g_display.mode_color );
  531.                return( OK );
  532.             } else {
  533.                node1 = skip_eol( node1, &r1, &rcol1, &rline1, &bin_offset1 );
  534.                len1  = node1->len;
  535.                diff1 = node1->line;
  536.                node2 = skip_eol( node2, &r2, &rcol2, &rline2, &bin_offset2 );
  537.                len2  = node2->len;
  538.                diff2 = node2->line;
  539.             }
  540.          }
  541.  
  542.          assert( rcol1 >= 0 );
  543.          assert( rcol1 < MAX_LINE_LENGTH );
  544.          assert( rcol2 >= 0 );
  545.          assert( rcol2 < MAX_LINE_LENGTH );
  546.          assert( r1 >= 0 );
  547.          assert( r1 < MAX_LINE_LENGTH );
  548.          assert( r2 >= 0 );
  549.          assert( r2 < MAX_LINE_LENGTH );
  550.          assert( r1 <= rcol1 );
  551.          assert( r2 <= rcol2 );
  552.          if (node1->len == EOF)
  553.             assert( len1 == EOF );
  554.          else {
  555.             assert( len1 >= 0 );
  556.             assert( len1 < MAX_LINE_LENGTH );
  557.          }
  558.          if (node2->len == EOF)
  559.             assert( len2 == EOF );
  560.          else {
  561.             assert( len2 >= 0 );
  562.             assert( len2 < MAX_LINE_LENGTH );
  563.          }
  564.       }
  565.       save_screen_line( 0, bottom, display_buff );
  566.       set_prompt( diff_prompt4, bottom );
  567.       getkey( );
  568.       restore_screen_line( 0, bottom, display_buff );
  569.       s_output( diff_blank, g_display.mode_line, 67, g_display.mode_color );
  570.    }
  571.    return( ERROR );
  572. }
  573.  
  574.  
  575. /*
  576.  * Name:    skip_leading_space
  577.  * Purpose: put the diff on the first non-blank character
  578.  * Date:    October 31, 1992
  579.  * Passed:  s:  the string to search
  580.  *          len: length of string
  581.  * Returns: the first non-blank column
  582.  */
  583. int  skip_leading_space( text_ptr s, int len )
  584. {
  585. register int count = 0;
  586.  
  587.    assert( len >= 0 );
  588.    assert( len < MAX_LINE_LENGTH );
  589.  
  590.    if (s != NULL) {
  591.       if (mode.inflate_tabs) {
  592.          while (len > 0  &&  (*s == ' ' || *s == '\t')) {
  593.             ++count;
  594.             ++s;
  595.             --len;
  596.          }
  597.       } else {
  598.          while (len > 0  &&  *s == ' ') {
  599.            ++count;
  600.            ++s;
  601.            --len;
  602.          }
  603.       }
  604.    }
  605.    if (len == 0)
  606.       count = 0;
  607.    return( count );
  608. }
  609.  
  610.  
  611. /*
  612.  * Name:    skip_eol
  613.  * Purpose: move the diff to the next line
  614.  * Date:    October 31, 1992
  615.  * Passed:  d:           pointer to current node
  616.  *          r:           tab adjusted real col
  617.  *          rcol:        real real col
  618.  *          rline:       current line number
  619.  *          bin_offset:  offset from the beginning of the file
  620.  * Returns: next non-blank node
  621.  */
  622. line_list_ptr skip_eol( line_list_ptr d, int *r, int *rcol, long *rline,
  623.                         long *bin_offset )
  624. {
  625. int  leading;
  626. long rl;
  627. long bo;
  628.  
  629.    *r = *rcol = 0;
  630.    rl = *rline;
  631.    bo = *bin_offset;
  632.    if (d->len != EOF) {
  633.       bo += d->len;
  634.       d = d->next;
  635.       ++rl;
  636.       if (diff.blank_lines) {
  637.          while (d->len != EOF  &&  is_line_blank( d->line, d->len )) {
  638.             bo += d->len;
  639.             d = d->next;
  640.             ++rl;
  641.          }
  642.       }
  643.       if (d->len != EOF) {
  644.          if (diff.leading) {
  645.             leading = skip_leading_space( d->line, d->len );
  646.             if (mode.inflate_tabs)
  647.                leading = detab_adjust_rcol( d->line, leading );
  648.             *rcol = leading;
  649.          } else
  650.             *rcol = 0;
  651.          *r = *rcol;
  652.          if (mode.inflate_tabs)
  653.             *r = entab_adjust_rcol( d->line, d->len, *rcol );
  654.       }
  655.    }
  656.    *rline = rl;
  657.    *bin_offset = bo;
  658.    return( d );
  659. }
  660.  
  661.  
  662. /*
  663.  * Name:    show_diff_window
  664.  * Purpose: update the contents of a diff window
  665.  * Date:    October 31, 1992
  666.  * Passed:  win:  pointer to window
  667.  */
  668. void show_diff_window( TDE_WIN *win )
  669. {
  670.    if (win->file_info->dirty == LOCAL)
  671.       display_current_window( win );
  672.    else
  673.       show_curl_line( win );
  674.    show_line_col( win );
  675.    make_ruler( win );
  676.    show_ruler( win );
  677.    show_ruler_pointer( win );
  678.    win->file_info->dirty = FALSE;
  679. }
  680.  
  681.  
  682. /*
  683.  * Name:    verify_number
  684.  * Purpose: given a window number, verify the number
  685.  * Date:    October 31, 1992
  686.  * Passed:  temp:  string that contains number
  687.  *          num:   successfully converted number.
  688.  */
  689. int  verify_number( char *temp, int *num )
  690. {
  691. register file_infos *fp;
  692.  
  693.    /*
  694.     * see if string has a number.  if string does have a number, convert it.
  695.     */
  696.    if (*temp == '\0' || !bj_isdigit( *temp ))
  697.       return( ERROR );
  698.    *num = 0;
  699.    while (bj_isdigit( *temp ))
  700.       *num = *num * 10 + *temp++ - '0';
  701.  
  702.    /*
  703.     * now that we have a window number, see if any files have that number
  704.     */
  705.    for (fp=g_status.file_list; fp != NULL; fp=fp->next) {
  706.       if (fp->file_no == *num)
  707.          return( OK );
  708.    }
  709.    return( ERROR );
  710. }
  711.  
  712.  
  713.  
  714. /*
  715.  * Name:    verify_letter
  716.  * Purpose: given a window letter, verify the letter
  717.  * Date:    October 31, 1992
  718.  * Modified: November 13, 1993, Frank Davis per Byrial Jensen
  719.  * Passed:  temp:  string that contains letter
  720.  *          let:   window letter
  721.  *          win:   pointer to window that contains letter and number
  722.  *
  723.  * Change:  Control that the letter is in string windowletters
  724.  */
  725. int  verify_letter( char *temp, int *let, TDE_WIN **win )
  726. {
  727. register file_infos *fp;
  728. register TDE_WIN *wp;
  729. int  num;
  730.  
  731.    if (verify_number( temp, &num ) == OK) {
  732.       while (bj_isdigit( *temp ))
  733.          temp++;
  734.       if (*temp == '\0' || !strchr( windowletters, tolower( *temp )))
  735.          return( ERROR );
  736.       *let = (int)tolower( *temp );
  737.       for (fp=g_status.file_list; fp != NULL; fp=fp->next) {
  738.          if (fp->file_no == num)
  739.             break;
  740.       }
  741.       for (wp=g_status.window_list; wp != NULL; wp=wp->next) {
  742.          if (wp->file_info == fp  &&  wp->letter == *let  &&  wp->visible) {
  743.             *win = wp;
  744.             return( OK );
  745.          }
  746.       }
  747.    }
  748.    return( ERROR );
  749. }
  750.